http: fix client parse error handling
[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 vrrp_main.msg_id_base
24 #include <vlibapi/api_helper_macros.h>
25
26 /* API message handlers */
27 static void
28 vl_api_vrrp_vr_update_t_handler (vl_api_vrrp_vr_update_t *mp)
29 {
30   vl_api_vrrp_vr_update_reply_t *rmp;
31   vrrp_vr_config_t vr_conf;
32   u32 api_flags;
33   u32 vrrp_index = INDEX_INVALID;
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   int i;
61   for (i = 0; i < mp->n_addrs; i++)
62     {
63       ip46_address_t *addr;
64       void *src, *dst;
65       int len;
66
67       vec_add2 (addrs, addr, 1);
68
69       if (ntohl (mp->addrs[i].af) == ADDRESS_IP4)
70         {
71           src = &mp->addrs[i].un.ip4;
72           dst = &addr->ip4;
73           len = sizeof (addr->ip4);
74         }
75       else
76         {
77           src = &mp->addrs[i].un.ip6;
78           dst = &addr->ip6;
79           len = sizeof (addr->ip6);
80         }
81
82       clib_memcpy (dst, src, len);
83     }
84
85   vr_conf.vr_addrs = addrs;
86
87   if (vr_conf.priority == 0)
88     {
89       clib_warning ("VR priority must be > 0");
90       rv = VNET_API_ERROR_INVALID_VALUE;
91     }
92   else if (vr_conf.adv_interval == 0)
93     {
94       clib_warning ("VR advertisement interval must be > 0");
95       rv = VNET_API_ERROR_INVALID_VALUE;
96     }
97   else if (vr_conf.vr_id == 0)
98     {
99       clib_warning ("VR ID must be > 0");
100       rv = VNET_API_ERROR_INVALID_VALUE;
101     }
102   else
103     {
104       vrrp_index = ntohl (mp->vrrp_index);
105       rv = vrrp_vr_update (&vrrp_index, &vr_conf);
106     }
107
108   vec_free (addrs);
109
110   BAD_SW_IF_INDEX_LABEL;
111   // clang-format off
112   REPLY_MACRO2 (VL_API_VRRP_VR_UPDATE_REPLY,
113   ({
114     rmp->vrrp_index = htonl (vrrp_index);
115   }));
116   // clang-format on
117 }
118
119 static void
120 vl_api_vrrp_vr_del_t_handler (vl_api_vrrp_vr_del_t *mp)
121 {
122   vl_api_vrrp_vr_del_reply_t *rmp;
123   int rv;
124
125   rv = vrrp_vr_del (ntohl (mp->vrrp_index));
126
127   REPLY_MACRO (VL_API_VRRP_VR_DEL_REPLY);
128 }
129
130 static void
131 vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp)
132 {
133   vl_api_vrrp_vr_add_del_reply_t *rmp;
134   vrrp_vr_config_t vr_conf;
135   u32 api_flags;
136   ip46_address_t *addrs = 0;
137   int rv;
138
139   VALIDATE_SW_IF_INDEX (mp);
140
141   api_flags = htonl (mp->flags);
142
143   clib_memset (&vr_conf, 0, sizeof (vr_conf));
144
145   vr_conf.sw_if_index = ntohl (mp->sw_if_index);
146   vr_conf.vr_id = mp->vr_id;
147   vr_conf.priority = mp->priority;
148   vr_conf.adv_interval = ntohs (mp->interval);
149
150   if (api_flags & VRRP_API_VR_PREEMPT)
151     vr_conf.flags |= VRRP_VR_PREEMPT;
152
153   if (api_flags & VRRP_API_VR_ACCEPT)
154     vr_conf.flags |= VRRP_VR_ACCEPT;
155
156   if (api_flags & VRRP_API_VR_UNICAST)
157     vr_conf.flags |= VRRP_VR_UNICAST;
158
159   if (api_flags & VRRP_API_VR_IPV6)
160     vr_conf.flags |= VRRP_VR_IPV6;
161
162   if (mp->is_add)
163     {
164       int i;
165
166       for (i = 0; i < mp->n_addrs; i++)
167         {
168           ip46_address_t *addr;
169           void *src, *dst;
170           int len;
171
172           vec_add2 (addrs, addr, 1);
173
174           if (ntohl (mp->addrs[i].af) == ADDRESS_IP4)
175             {
176               src = &mp->addrs[i].un.ip4;
177               dst = &addr->ip4;
178               len = sizeof (addr->ip4);
179             }
180           else
181             {
182               src = &mp->addrs[i].un.ip6;
183               dst = &addr->ip6;
184               len = sizeof (addr->ip6);
185             }
186
187           clib_memcpy (dst, src, len);
188         }
189
190       vr_conf.vr_addrs = addrs;
191     }
192
193   if (vr_conf.priority == 0)
194     {
195       clib_warning ("VR priority must be > 0");
196       rv = VNET_API_ERROR_INVALID_VALUE;
197     }
198   else if (vr_conf.adv_interval == 0)
199     {
200       clib_warning ("VR advertisement interval must be > 0");
201       rv = VNET_API_ERROR_INVALID_VALUE;
202     }
203   else if (vr_conf.vr_id == 0)
204     {
205       clib_warning ("VR ID must be > 0");
206       rv = VNET_API_ERROR_INVALID_VALUE;
207     }
208   else
209     rv = vrrp_vr_add_del (mp->is_add, &vr_conf, NULL);
210
211   vec_free (addrs);
212
213   BAD_SW_IF_INDEX_LABEL;
214   REPLY_MACRO (VL_API_VRRP_VR_ADD_DEL_REPLY);
215 }
216
217 static vl_api_vrrp_vr_state_t
218 vrrp_vr_state_encode (vrrp_vr_state_t vr_state)
219 {
220   if (vr_state == VRRP_VR_STATE_BACKUP)
221     return VRRP_API_VR_STATE_BACKUP;
222   if (vr_state == VRRP_VR_STATE_MASTER)
223     return VRRP_API_VR_STATE_MASTER;
224   if (vr_state == VRRP_VR_STATE_INTF_DOWN)
225     return VRRP_API_VR_STATE_INTF_DOWN;
226
227   return VRRP_API_VR_STATE_INIT;
228 }
229
230 static void
231 send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
232                       u32 context)
233 {
234   vrrp_main_t *vmp = &vrrp_main;
235   vl_api_vrrp_vr_details_t *mp;
236   int n_addrs, msg_size;
237   ip46_address_t *addr;
238   vl_api_address_t *api_addr;
239   u32 api_flags = 0;
240
241   n_addrs = vec_len (vr->config.vr_addrs);
242   msg_size = sizeof (*mp) + n_addrs * sizeof (*api_addr);
243   mp = vl_msg_api_alloc (msg_size);
244   if (!mp)
245     return;
246   clib_memset (mp, 0, msg_size);
247   mp->_vl_msg_id = htons (VL_API_VRRP_VR_DETAILS + vmp->msg_id_base);
248   mp->context = context;
249
250   /* config */
251   mp->config.sw_if_index = htonl (vr->config.sw_if_index);
252   mp->config.vr_id = vr->config.vr_id;
253   mp->config.priority = vr->config.priority;
254   mp->config.interval = htons (vr->config.adv_interval);
255
256   if (vr->config.flags & VRRP_VR_PREEMPT)
257     api_flags |= VRRP_API_VR_PREEMPT;
258   if (vr->config.flags & VRRP_VR_ACCEPT)
259     api_flags |= VRRP_API_VR_ACCEPT;
260   if (vrrp_vr_is_unicast (vr))
261     api_flags |= VRRP_API_VR_UNICAST;
262   if (vrrp_vr_is_ipv6 (vr))
263     api_flags |= VRRP_API_VR_IPV6;
264
265   mp->config.flags = htonl (api_flags);
266
267   /* runtime */
268   mp->runtime.state = htonl (vrrp_vr_state_encode (vr->runtime.state));
269
270   mp->runtime.master_adv_int = htons (vr->runtime.master_adv_int);
271   mp->runtime.skew = htons (vr->runtime.skew);
272   mp->runtime.master_down_int = htons (vr->runtime.master_down_int);
273   clib_memcpy (&mp->runtime.mac, &vr->runtime.mac, sizeof (vr->runtime.mac));
274
275   mp->runtime.tracking.interfaces_dec = htonl (vr->tracking.interfaces_dec);
276   mp->runtime.tracking.priority = vrrp_vr_priority (vr);
277
278   /* addrs */
279   mp->n_addrs = vec_len (vr->config.vr_addrs);
280   api_addr = mp->addrs;
281   vec_foreach (addr, vr->config.vr_addrs)
282   {
283     void *src, *dst;
284     size_t len;
285
286     if (vrrp_vr_is_ipv6 (vr))
287       {
288         api_addr->af = ADDRESS_IP6;
289         dst = &api_addr->un.ip6;
290         src = &addr->ip6;
291         len = sizeof (addr->ip6);
292       }
293     else
294       {
295         api_addr->af = ADDRESS_IP4;
296         dst = &api_addr->un.ip4;
297         src = &addr->ip4;
298         len = sizeof (addr->ip4);
299       }
300     clib_memcpy (dst, src, len);
301     api_addr++;
302   }
303
304   vl_api_send_msg (reg, (u8 *) mp);
305 }
306
307 static void
308 vl_api_vrrp_vr_dump_t_handler (vl_api_vrrp_vr_dump_t * mp)
309 {
310   vrrp_main_t *vmp = &vrrp_main;
311   vl_api_registration_t *reg;
312   vrrp_vr_t *vr;
313   u32 sw_if_index;
314
315   reg = vl_api_client_index_to_registration (mp->client_index);
316   if (!reg)
317     return;
318
319   sw_if_index = htonl (mp->sw_if_index);
320
321   pool_foreach (vr, vmp->vrs)  {
322
323     if (sw_if_index && (sw_if_index != ~0) &&
324         (sw_if_index != vr->config.sw_if_index))
325       continue;
326
327     send_vrrp_vr_details (vr, reg, mp->context);
328   }
329 }
330
331 static void
332 vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp)
333 {
334   vl_api_vrrp_vr_start_stop_reply_t *rmp;
335   vrrp_vr_key_t vr_key;
336   int rv;
337
338   clib_memset (&vr_key, 0, sizeof (vr_key));
339
340   vr_key.sw_if_index = ntohl (mp->sw_if_index);
341   vr_key.vr_id = mp->vr_id;
342   vr_key.is_ipv6 = (mp->is_ipv6 != 0);
343
344   rv = vrrp_vr_start_stop ((mp->is_start != 0), &vr_key);
345
346   REPLY_MACRO (VL_API_VRRP_VR_START_STOP_REPLY);
347 }
348
349 static void
350 vl_api_vrrp_vr_set_peers_t_handler (vl_api_vrrp_vr_set_peers_t * mp)
351 {
352   vl_api_vrrp_vr_set_peers_reply_t *rmp;
353   vrrp_vr_key_t vr_key;
354   ip46_address_t *peer_addrs = 0;
355   int i;
356   int rv;
357
358   clib_memset (&vr_key, 0, sizeof (vr_key));
359
360   vr_key.sw_if_index = ntohl (mp->sw_if_index);
361   vr_key.vr_id = mp->vr_id;
362   vr_key.is_ipv6 = (mp->is_ipv6 != 0);
363
364   for (i = 0; i < mp->n_addrs; i++)
365     {
366       ip46_address_t *peer;
367
368       vec_add2 (peer_addrs, peer, 1);
369
370       if (mp->is_ipv6)
371         clib_memcpy (&peer->ip6, mp->addrs[i].un.ip6, 16);
372       else
373         clib_memcpy (&peer->ip4, mp->addrs[i].un.ip4, 4);
374     }
375
376   rv = vrrp_vr_set_peers (&vr_key, peer_addrs);
377
378   vec_free (peer_addrs);
379   REPLY_MACRO (VL_API_VRRP_VR_SET_PEERS_REPLY);
380 }
381
382 static void
383 send_vrrp_vr_peer_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
384                            u32 context)
385 {
386   vrrp_main_t *vmp = &vrrp_main;
387   vl_api_vrrp_vr_peer_details_t *mp;
388   int n_addrs, msg_size;
389   ip46_address_t *addr;
390   vl_api_address_t *api_addr;
391
392   n_addrs = vec_len (vr->config.peer_addrs);
393   msg_size = sizeof (*mp) + n_addrs * sizeof (*api_addr);
394   mp = vl_msg_api_alloc (msg_size);
395   if (!mp)
396     return;
397   clib_memset (mp, 0, msg_size);
398   mp->_vl_msg_id = htons (VL_API_VRRP_VR_PEER_DETAILS + vmp->msg_id_base);
399   mp->context = context;
400
401   mp->sw_if_index = htonl (vr->config.sw_if_index);
402   mp->vr_id = vr->config.vr_id;
403   mp->is_ipv6 = vrrp_vr_is_ipv6 (vr);
404
405   /* addrs */
406   mp->n_peer_addrs = n_addrs;
407   api_addr = mp->peer_addrs;
408   vec_foreach (addr, vr->config.peer_addrs)
409   {
410     void *src, *dst;
411     size_t len;
412
413     if (vrrp_vr_is_ipv6 (vr))
414       {
415         api_addr->af = ADDRESS_IP6;
416         dst = &api_addr->un.ip6;
417         src = &addr->ip6;
418         len = sizeof (addr->ip6);
419       }
420     else
421       {
422         api_addr->af = ADDRESS_IP4;
423         dst = &api_addr->un.ip4;
424         src = &addr->ip4;
425         len = sizeof (addr->ip4);
426       }
427     clib_memcpy (dst, src, len);
428     api_addr++;
429   }
430
431   vl_api_send_msg (reg, (u8 *) mp);
432 }
433
434 static void
435 vl_api_vrrp_vr_peer_dump_t_handler (vl_api_vrrp_vr_peer_dump_t * mp)
436 {
437   vrrp_main_t *vmp = &vrrp_main;
438   vl_api_registration_t *reg;
439   vrrp_vr_t *vr;
440   vrrp_vr_key_t vr_key;
441
442   reg = vl_api_client_index_to_registration (mp->client_index);
443   if (!reg)
444     return;
445
446   vr_key.sw_if_index = ntohl (mp->sw_if_index);
447
448   if (vr_key.sw_if_index && (vr_key.sw_if_index != ~0))
449     {
450       uword *p;
451       u32 vr_index = ~0;
452
453       vr_key.vr_id = mp->vr_id;
454       vr_key.is_ipv6 = mp->is_ipv6;
455
456       p = mhash_get (&vmp->vr_index_by_key, &vr_key);
457       if (!p)
458         return;
459
460       vr_index = p[0];
461       vr = pool_elt_at_index (vmp->vrs, vr_index);
462       send_vrrp_vr_peer_details (vr, reg, mp->context);
463
464       return;
465     }
466
467   pool_foreach (vr, vmp->vrs)  {
468
469     if (!vec_len (vr->config.peer_addrs))
470       continue;
471
472     send_vrrp_vr_details (vr, reg, mp->context);
473
474   }
475 }
476
477 static void
478   vl_api_vrrp_vr_track_if_add_del_t_handler
479   (vl_api_vrrp_vr_track_if_add_del_t * mp)
480 {
481   vl_api_vrrp_vr_track_if_add_del_reply_t *rmp;
482   vrrp_vr_t *vr;
483   vrrp_vr_tracking_if_t *track_if, *track_ifs = 0;
484   int rv = 0, i;
485
486   /* lookup VR and return error if it does not exist */
487   vr =
488     vrrp_vr_lookup (ntohl (mp->sw_if_index), mp->vr_id, (mp->is_ipv6 != 0));
489   if (!vr)
490     {
491       rv = VNET_API_ERROR_INVALID_VALUE;
492       goto done;
493     }
494
495   for (i = 0; i < mp->n_ifs; i++)
496     {
497       vl_api_vrrp_vr_track_if_t *api_track_if = &mp->ifs[i];
498
499       vec_add2 (track_ifs, track_if, 1);
500       track_if->sw_if_index = ntohl (api_track_if->sw_if_index);
501       track_if->priority = api_track_if->priority;
502     }
503
504   rv = vrrp_vr_tracking_ifs_add_del (vr, track_ifs, mp->is_add != 0);
505
506 done:
507   vec_free (track_ifs);
508   REPLY_MACRO (VL_API_VRRP_VR_TRACK_IF_ADD_DEL_REPLY);
509 }
510
511 static void
512 send_vrrp_vr_track_if_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
513                                u32 context)
514 {
515   vrrp_main_t *vmp = &vrrp_main;
516   vl_api_vrrp_vr_track_if_details_t *mp;
517   int n_ifs, msg_size;
518   vl_api_vrrp_vr_track_if_t *api_track_if;
519   vrrp_vr_tracking_if_t *track_if;
520
521   if (!vr)
522     return;
523
524   n_ifs = vec_len (vr->tracking.interfaces);
525   msg_size = sizeof (*mp) + n_ifs * sizeof (*api_track_if);
526   mp = vl_msg_api_alloc (msg_size);
527   if (!mp)
528     return;
529   clib_memset (mp, 0, msg_size);
530   mp->_vl_msg_id = htons (VL_API_VRRP_VR_TRACK_IF_DETAILS + vmp->msg_id_base);
531   mp->context = context;
532
533   mp->sw_if_index = htonl (vr->config.sw_if_index);
534   mp->vr_id = vr->config.vr_id;
535   mp->is_ipv6 = vrrp_vr_is_ipv6 (vr);
536
537   /* tracked interfaces */
538   mp->n_ifs = n_ifs;
539   api_track_if = mp->ifs;
540   vec_foreach (track_if, vr->tracking.interfaces)
541   {
542     api_track_if->sw_if_index = htonl (track_if->sw_if_index);
543     api_track_if->priority = track_if->priority;
544     api_track_if += 1;
545   }
546
547   vl_api_send_msg (reg, (u8 *) mp);
548 }
549
550 static void
551 vl_api_vrrp_vr_track_if_dump_t_handler (vl_api_vrrp_vr_track_if_dump_t * mp)
552 {
553   vrrp_main_t *vmp = &vrrp_main;
554   vl_api_registration_t *reg;
555   vrrp_vr_t *vr;
556
557   reg = vl_api_client_index_to_registration (mp->client_index);
558   if (!reg)
559     return;
560
561   if (!mp->dump_all)
562     {
563       vr = vrrp_vr_lookup (ntohl (mp->sw_if_index), mp->vr_id, mp->is_ipv6);
564       send_vrrp_vr_track_if_details (vr, reg, mp->context);
565
566       return;
567     }
568
569   pool_foreach (vr, vmp->vrs)  {
570
571     if (!vec_len (vr->tracking.interfaces))
572       continue;
573
574     send_vrrp_vr_track_if_details (vr, reg, mp->context);
575
576   }
577 }
578
579 static void
580 send_vrrp_vr_event (vpe_client_registration_t * reg,
581                     vl_api_registration_t * vl_reg,
582                     vrrp_vr_t * vr, vrrp_vr_state_t new_state)
583 {
584   vrrp_main_t *vmp = &vrrp_main;
585   vl_api_vrrp_vr_event_t *mp;
586
587   mp = vl_msg_api_alloc (sizeof (*mp));
588
589   clib_memset (mp, 0, sizeof (*mp));
590   mp->_vl_msg_id = ntohs (VL_API_VRRP_VR_EVENT + vmp->msg_id_base);
591   mp->client_index = reg->client_index;
592   mp->pid = reg->client_pid;
593   mp->vr.sw_if_index = ntohl (vr->config.sw_if_index);
594   mp->vr.vr_id = vr->config.vr_id;
595   mp->vr.is_ipv6 = ((vr->config.flags & VRRP_VR_IPV6) != 0);
596
597   mp->old_state = htonl (vrrp_vr_state_encode (vr->runtime.state));
598   mp->new_state = htonl (vrrp_vr_state_encode (new_state));
599
600   vl_api_send_msg (vl_reg, (u8 *) mp);
601 }
602
603 void
604 vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state)
605 {
606   vpe_api_main_t *vam = &vpe_api_main;
607   vpe_client_registration_t *reg;
608   vl_api_registration_t *vl_reg;
609
610   pool_foreach (reg, vam->vrrp_vr_events_registrations)
611    {
612     vl_reg = vl_api_client_index_to_registration (reg->client_index);
613     if (vl_reg)
614       send_vrrp_vr_event (reg, vl_reg, vr, new_state);
615   }
616 }
617
618 pub_sub_handler (vrrp_vr_events, VRRP_VR_EVENTS);
619
620 /* Set up the API message handling tables */
621 #include <vrrp/vrrp.api.c>
622 clib_error_t *
623 vrrp_plugin_api_hookup (vlib_main_t * vm)
624 {
625   vrrp_main_t *vmp = &vrrp_main;
626
627   /* Ask for a correctly-sized block of API message decode slots */
628   vmp->msg_id_base = setup_message_id_table ();
629
630   return 0;
631 }
632
633
634 /*
635  * fd.io coding-style-patch-verification: ON
636  *
637  * Local Variables:
638  * eval: (c-set-style "gnu")
639  * End:
640  */