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