vrrp dns: fix coverity warnings
[vpp.git] / src / plugins / vrrp / vrrp_api.c
1 /*
2  * vrrp.c - vpp vrrp plug-in
3  *
4  * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  */
9
10 #include <vnet/vnet.h>
11 #include <vnet/plugin/plugin.h>
12 #include <vrrp/vrrp.h>
13
14 #include <vlibapi/api.h>
15 #include <vlibmemory/api.h>
16 #include <vpp/app/version.h>
17
18 /* define message IDs */
19 #include <vnet/format_fns.h>
20 #include <vrrp/vrrp.api_enum.h>
21 #include <vrrp/vrrp.api_types.h>
22
23 #define REPLY_MSG_ID_BASE vmp->msg_id_base
24 #include <vlibapi/api_helper_macros.h>
25
26 /* API message handlers */
27 static void
28 vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp)
29 {
30   vrrp_main_t *vmp = &vrrp_main;
31   vl_api_vrrp_vr_add_del_reply_t *rmp;
32   vrrp_vr_config_t vr_conf;
33   u32 api_flags;
34   ip46_address_t *addrs = 0;
35   int rv;
36
37   api_flags = htonl (mp->flags);
38
39   clib_memset (&vr_conf, 0, sizeof (vr_conf));
40
41   vr_conf.sw_if_index = ntohl (mp->sw_if_index);
42   vr_conf.vr_id = mp->vr_id;
43   vr_conf.priority = mp->priority;
44   vr_conf.adv_interval = ntohs (mp->interval);
45
46   if (api_flags & VRRP_API_VR_PREEMPT)
47     vr_conf.flags |= VRRP_VR_PREEMPT;
48
49   if (api_flags & VRRP_API_VR_ACCEPT)
50     vr_conf.flags |= VRRP_VR_ACCEPT;
51
52   if (api_flags & VRRP_API_VR_UNICAST)
53     vr_conf.flags |= VRRP_VR_UNICAST;
54
55   if (api_flags & VRRP_API_VR_IPV6)
56     vr_conf.flags |= VRRP_VR_IPV6;
57
58   if (mp->is_add)
59     {
60       int i;
61
62       for (i = 0; i < mp->n_addrs; i++)
63         {
64           ip46_address_t *addr;
65           void *src, *dst;
66           int len;
67
68           vec_add2 (addrs, addr, 1);
69
70           if (ntohl (mp->addrs[i].af) == ADDRESS_IP4)
71             {
72               src = &mp->addrs[i].un.ip4;
73               dst = &addr->ip4;
74               len = sizeof (addr->ip4);
75             }
76           else
77             {
78               src = &mp->addrs[i].un.ip6;
79               dst = &addr->ip6;
80               len = sizeof (addr->ip6);
81             }
82
83           clib_memcpy (dst, src, len);
84         }
85
86       vr_conf.vr_addrs = addrs;
87     }
88
89   if (vr_conf.priority == 0)
90     {
91       clib_warning ("VR priority must be > 0");
92       rv = VNET_API_ERROR_INVALID_VALUE;
93     }
94   else if (vr_conf.adv_interval == 0)
95     {
96       clib_warning ("VR advertisement interval must be > 0");
97       rv = VNET_API_ERROR_INVALID_VALUE;
98     }
99   else if (vr_conf.vr_id == 0)
100     {
101       clib_warning ("VR ID must be > 0");
102       rv = VNET_API_ERROR_INVALID_VALUE;
103     }
104   else
105     rv = vrrp_vr_add_del (mp->is_add, &vr_conf);
106
107   vec_free (addrs);
108
109   REPLY_MACRO (VL_API_VRRP_VR_ADD_DEL_REPLY);
110 }
111
112 static void
113 send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
114                       u32 context)
115 {
116   vrrp_main_t *vmp = &vrrp_main;
117   vl_api_vrrp_vr_details_t *mp;
118   int n_addrs, msg_size;
119   ip46_address_t *addr;
120   vl_api_address_t *api_addr;
121   u32 api_flags = 0;
122
123   n_addrs = vec_len (vr->config.vr_addrs);
124   msg_size = sizeof (*mp) + n_addrs * sizeof (*api_addr);
125   mp = vl_msg_api_alloc (msg_size);
126   if (!mp)
127     return;
128   clib_memset (mp, 0, msg_size);
129   mp->_vl_msg_id = htons (VL_API_VRRP_VR_DETAILS + vmp->msg_id_base);
130   mp->context = context;
131
132   /* config */
133   mp->config.sw_if_index = htonl (vr->config.sw_if_index);
134   mp->config.vr_id = vr->config.vr_id;
135   mp->config.priority = vr->config.priority;
136   mp->config.interval = htons (vr->config.adv_interval);
137
138   if (vr->config.flags & VRRP_VR_PREEMPT)
139     api_flags |= VRRP_API_VR_PREEMPT;
140   if (vr->config.flags & VRRP_VR_ACCEPT)
141     api_flags |= VRRP_API_VR_ACCEPT;
142   if (vrrp_vr_is_unicast (vr))
143     api_flags |= VRRP_API_VR_UNICAST;
144   if (vrrp_vr_is_ipv6 (vr))
145     api_flags |= VRRP_API_VR_IPV6;
146
147   mp->config.flags = htonl (api_flags);
148
149   /* runtime */
150   switch (vr->runtime.state)
151     {
152     case VRRP_VR_STATE_INIT:
153       mp->runtime.state = htonl (VRRP_API_VR_STATE_INIT);
154       break;
155     case VRRP_VR_STATE_BACKUP:
156       mp->runtime.state = htonl (VRRP_API_VR_STATE_BACKUP);
157       break;
158     case VRRP_VR_STATE_MASTER:
159       mp->runtime.state = htonl (VRRP_API_VR_STATE_MASTER);
160       break;
161     case VRRP_VR_STATE_INTF_DOWN:
162       mp->runtime.state = htonl (VRRP_API_VR_STATE_INTF_DOWN);
163       break;
164     default:
165       break;
166     }
167
168   mp->runtime.master_adv_int = htons (vr->runtime.master_adv_int);
169   mp->runtime.skew = htons (vr->runtime.skew);
170   mp->runtime.master_down_int = htons (vr->runtime.master_down_int);
171   clib_memcpy (&mp->runtime.mac, &vr->runtime.mac, sizeof (vr->runtime.mac));
172
173   mp->runtime.tracking.interfaces_dec = htonl (vr->tracking.interfaces_dec);
174   mp->runtime.tracking.priority = vrrp_vr_priority (vr);
175
176   /* addrs */
177   mp->n_addrs = vec_len (vr->config.vr_addrs);
178   api_addr = mp->addrs;
179   vec_foreach (addr, vr->config.vr_addrs)
180   {
181     void *src, *dst;
182     size_t len;
183
184     if (vrrp_vr_is_ipv6 (vr))
185       {
186         api_addr->af = htonl (ADDRESS_IP6);
187         dst = &api_addr->un.ip6;
188         src = &addr->ip6;
189         len = sizeof (addr->ip6);
190       }
191     else
192       {
193         api_addr->af = htonl (ADDRESS_IP4);
194         dst = &api_addr->un.ip4;
195         src = &addr->ip4;
196         len = sizeof (addr->ip4);
197       }
198     clib_memcpy (dst, src, len);
199     api_addr++;
200   }
201
202   vl_api_send_msg (reg, (u8 *) mp);
203 }
204
205 static void
206 vl_api_vrrp_vr_dump_t_handler (vl_api_vrrp_vr_dump_t * mp)
207 {
208   vrrp_main_t *vmp = &vrrp_main;
209   vl_api_registration_t *reg;
210   vrrp_vr_t *vr;
211   u32 sw_if_index;
212
213   reg = vl_api_client_index_to_registration (mp->client_index);
214   if (!reg)
215     return;
216
217   sw_if_index = htonl (mp->sw_if_index);
218
219   /* *INDENT-OFF* */
220   pool_foreach (vr, vmp->vrs, ({
221
222     if (sw_if_index && (sw_if_index != ~0) &&
223         (sw_if_index != vr->config.sw_if_index))
224       continue;
225
226     send_vrrp_vr_details (vr, reg, mp->context);
227   }));
228   /* *INDENT-ON* */
229 }
230
231 static void
232 vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp)
233 {
234   vrrp_main_t *vmp = &vrrp_main;
235   vl_api_vrrp_vr_start_stop_reply_t *rmp;
236   vrrp_vr_key_t vr_key;
237   int rv;
238
239   clib_memset (&vr_key, 0, sizeof (vr_key));
240
241   vr_key.sw_if_index = ntohl (mp->sw_if_index);
242   vr_key.vr_id = mp->vr_id;
243   vr_key.is_ipv6 = (mp->is_ipv6 != 0);
244
245   rv = vrrp_vr_start_stop ((mp->is_start != 0), &vr_key);
246
247   REPLY_MACRO (VL_API_VRRP_VR_START_STOP_REPLY);
248 }
249
250 static void
251 vl_api_vrrp_vr_set_peers_t_handler (vl_api_vrrp_vr_set_peers_t * mp)
252 {
253   vrrp_main_t *vmp = &vrrp_main;
254   vl_api_vrrp_vr_set_peers_reply_t *rmp;
255   vrrp_vr_key_t vr_key;
256   ip46_address_t *peer_addrs = 0;
257   int i;
258   int rv;
259
260   clib_memset (&vr_key, 0, sizeof (vr_key));
261
262   vr_key.sw_if_index = ntohl (mp->sw_if_index);
263   vr_key.vr_id = mp->vr_id;
264   vr_key.is_ipv6 = (mp->is_ipv6 != 0);
265
266   for (i = 0; i < mp->n_addrs; i++)
267     {
268       ip46_address_t *peer;
269
270       vec_add2 (peer_addrs, peer, 1);
271
272       if (mp->is_ipv6)
273         clib_memcpy (&peer->ip6, mp->addrs[i].un.ip6, 16);
274       else
275         clib_memcpy (&peer->ip4, mp->addrs[i].un.ip4, 4);
276     }
277
278   rv = vrrp_vr_set_peers (&vr_key, peer_addrs);
279
280   vec_free (peer_addrs);
281   REPLY_MACRO (VL_API_VRRP_VR_SET_PEERS_REPLY);
282 }
283
284 static void
285 send_vrrp_vr_peer_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
286                            u32 context)
287 {
288   vrrp_main_t *vmp = &vrrp_main;
289   vl_api_vrrp_vr_peer_details_t *mp;
290   int n_addrs, msg_size;
291   ip46_address_t *addr;
292   vl_api_address_t *api_addr;
293
294   n_addrs = vec_len (vr->config.peer_addrs);
295   msg_size = sizeof (*mp) + n_addrs * sizeof (*api_addr);
296   mp = vl_msg_api_alloc (msg_size);
297   if (!mp)
298     return;
299   clib_memset (mp, 0, msg_size);
300   mp->_vl_msg_id = htons (VL_API_VRRP_VR_PEER_DETAILS + vmp->msg_id_base);
301   mp->context = context;
302
303   mp->sw_if_index = htonl (vr->config.sw_if_index);
304   mp->vr_id = vr->config.vr_id;
305   mp->is_ipv6 = vrrp_vr_is_ipv6 (vr);
306
307   /* addrs */
308   mp->n_peer_addrs = n_addrs;
309   api_addr = mp->peer_addrs;
310   vec_foreach (addr, vr->config.peer_addrs)
311   {
312     void *src, *dst;
313     size_t len;
314
315     if (vrrp_vr_is_ipv6 (vr))
316       {
317         api_addr->af = htonl (ADDRESS_IP6);
318         dst = &api_addr->un.ip6;
319         src = &addr->ip6;
320         len = sizeof (addr->ip6);
321       }
322     else
323       {
324         api_addr->af = htonl (ADDRESS_IP4);
325         dst = &api_addr->un.ip4;
326         src = &addr->ip4;
327         len = sizeof (addr->ip4);
328       }
329     clib_memcpy (dst, src, len);
330     api_addr++;
331   }
332
333   vl_api_send_msg (reg, (u8 *) mp);
334 }
335
336 static void
337 vl_api_vrrp_vr_peer_dump_t_handler (vl_api_vrrp_vr_peer_dump_t * mp)
338 {
339   vrrp_main_t *vmp = &vrrp_main;
340   vl_api_registration_t *reg;
341   vrrp_vr_t *vr;
342   vrrp_vr_key_t vr_key;
343
344   reg = vl_api_client_index_to_registration (mp->client_index);
345   if (!reg)
346     return;
347
348   vr_key.sw_if_index = ntohl (mp->sw_if_index);
349
350   if (vr_key.sw_if_index && (vr_key.sw_if_index != ~0))
351     {
352       uword *p;
353       u32 vr_index = ~0;
354
355       vr_key.vr_id = mp->vr_id;
356       vr_key.is_ipv6 = mp->is_ipv6;
357
358       p = mhash_get (&vmp->vr_index_by_key, &vr_key);
359       if (!p)
360         return;
361
362       vr_index = p[0];
363       vr = pool_elt_at_index (vmp->vrs, vr_index);
364       send_vrrp_vr_peer_details (vr, reg, mp->context);
365
366       return;
367     }
368
369   /* *INDENT-OFF* */
370   pool_foreach (vr, vmp->vrs, ({
371
372     if (!vec_len (vr->config.peer_addrs))
373       continue;
374
375     send_vrrp_vr_details (vr, reg, mp->context);
376
377   }));
378   /* *INDENT-ON* */
379 }
380
381 static void
382   vl_api_vrrp_vr_track_if_add_del_t_handler
383   (vl_api_vrrp_vr_track_if_add_del_t * mp)
384 {
385   vrrp_main_t *vmp = &vrrp_main;
386   vl_api_vrrp_vr_track_if_add_del_reply_t *rmp;
387   vrrp_vr_t *vr;
388   vrrp_vr_tracking_if_t *track_if, *track_ifs = 0;
389   int rv = 0, i;
390
391   /* lookup VR and return error if it does not exist */
392   vr =
393     vrrp_vr_lookup (ntohl (mp->sw_if_index), mp->vr_id, (mp->is_ipv6 != 0));
394   if (!vr)
395     {
396       rv = VNET_API_ERROR_INVALID_VALUE;
397       goto done;
398     }
399
400   for (i = 0; i < mp->n_ifs; i++)
401     {
402       vl_api_vrrp_vr_track_if_t *api_track_if = &mp->ifs[i];
403
404       vec_add2 (track_ifs, track_if, 1);
405       track_if->sw_if_index = ntohl (api_track_if->sw_if_index);
406       track_if->priority = api_track_if->priority;
407     }
408
409   rv = vrrp_vr_tracking_ifs_add_del (vr, track_ifs, mp->is_add != 0);
410
411 done:
412   vec_free (track_ifs);
413   REPLY_MACRO (VL_API_VRRP_VR_TRACK_IF_ADD_DEL_REPLY);
414 }
415
416 static void
417 send_vrrp_vr_track_if_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
418                                u32 context)
419 {
420   vrrp_main_t *vmp = &vrrp_main;
421   vl_api_vrrp_vr_track_if_details_t *mp;
422   int n_ifs, msg_size;
423   vl_api_vrrp_vr_track_if_t *api_track_if;
424   vrrp_vr_tracking_if_t *track_if;
425
426   if (!vr)
427     return;
428
429   n_ifs = vec_len (vr->tracking.interfaces);
430   msg_size = sizeof (*mp) + n_ifs * sizeof (*api_track_if);
431   mp = vl_msg_api_alloc (msg_size);
432   if (!mp)
433     return;
434   clib_memset (mp, 0, msg_size);
435   mp->_vl_msg_id = htons (VL_API_VRRP_VR_TRACK_IF_DETAILS + vmp->msg_id_base);
436   mp->context = context;
437
438   mp->sw_if_index = htonl (vr->config.sw_if_index);
439   mp->vr_id = vr->config.vr_id;
440   mp->is_ipv6 = vrrp_vr_is_ipv6 (vr);
441
442   /* tracked interfaces */
443   mp->n_ifs = n_ifs;
444   api_track_if = mp->ifs;
445   vec_foreach (track_if, vr->tracking.interfaces)
446   {
447     api_track_if->sw_if_index = htonl (track_if->sw_if_index);
448     api_track_if->priority = track_if->priority;
449     api_track_if += 1;
450   }
451
452   vl_api_send_msg (reg, (u8 *) mp);
453 }
454
455 static void
456 vl_api_vrrp_vr_track_if_dump_t_handler (vl_api_vrrp_vr_track_if_dump_t * mp)
457 {
458   vrrp_main_t *vmp = &vrrp_main;
459   vl_api_registration_t *reg;
460   vrrp_vr_t *vr;
461
462   reg = vl_api_client_index_to_registration (mp->client_index);
463   if (!reg)
464     return;
465
466   if (!mp->dump_all)
467     {
468       vr = vrrp_vr_lookup (ntohl (mp->sw_if_index), mp->vr_id, mp->is_ipv6);
469       send_vrrp_vr_track_if_details (vr, reg, mp->context);
470
471       return;
472     }
473
474   /* *INDENT-OFF* */
475   pool_foreach (vr, vmp->vrs, ({
476
477     if (!vec_len (vr->tracking.interfaces))
478       continue;
479
480     send_vrrp_vr_track_if_details (vr, reg, mp->context);
481
482   }));
483   /* *INDENT-ON* */
484 }
485
486 /* Set up the API message handling tables */
487 #include <vrrp/vrrp.api.c>
488 clib_error_t *
489 vrrp_plugin_api_hookup (vlib_main_t * vm)
490 {
491   vrrp_main_t *vmp = &vrrp_main;
492
493   /* Ask for a correctly-sized block of API message decode slots */
494   vmp->msg_id_base = setup_message_id_table ();
495
496   return 0;
497 }
498
499 /* *INDENT-ON* */
500
501 /*
502  * fd.io coding-style-patch-verification: ON
503  *
504  * Local Variables:
505  * eval: (c-set-style "gnu")
506  * End:
507  */