]> git.proxmox.com Git - mirror_frr.git/blob - vrrpd/vrrp.c
Merge pull request #5246 from sworleys/README-Frr-Chicken
[mirror_frr.git] / vrrpd / vrrp.c
1 /*
2 * VRRP global definitions and state machine.
3 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
4 * Quentin Young
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <zebra.h>
21
22 #include "lib/hash.h"
23 #include "lib/hook.h"
24 #include "lib/if.h"
25 #include "lib/linklist.h"
26 #include "lib/memory.h"
27 #include "lib/network.h"
28 #include "lib/prefix.h"
29 #include "lib/sockopt.h"
30 #include "lib/sockunion.h"
31 #include "lib/vrf.h"
32 #include "lib/vty.h"
33
34 #include "vrrp.h"
35 #include "vrrp_arp.h"
36 #include "vrrp_debug.h"
37 #include "vrrp_ndisc.h"
38 #include "vrrp_packet.h"
39 #include "vrrp_zebra.h"
40
41 #define VRRP_LOGPFX "[CORE] "
42
43 DEFINE_MTYPE_STATIC(VRRPD, VRRP_IP, "VRRP IP address")
44 DEFINE_MTYPE_STATIC(VRRPD, VRRP_RTR, "VRRP Router")
45
46 /* statics */
47 struct hash *vrrp_vrouters_hash;
48 bool vrrp_autoconfig_is_on;
49 int vrrp_autoconfig_version;
50
51 struct vrrp_defaults vd;
52
53 const char *vrrp_state_names[3] = {
54 [VRRP_STATE_INITIALIZE] = "Initialize",
55 [VRRP_STATE_MASTER] = "Master",
56 [VRRP_STATE_BACKUP] = "Backup",
57 };
58
59 const char *vrrp_event_names[2] = {
60 [VRRP_EVENT_STARTUP] = "Startup",
61 [VRRP_EVENT_SHUTDOWN] = "Shutdown",
62 };
63
64
65 /* Utility functions ------------------------------------------------------- */
66
67 /*
68 * Sets an ethaddr to RFC-defined Virtual Router MAC address.
69 *
70 * mac
71 * ethaddr to set
72 *
73 * v6
74 * Whether this is a V6 or V4 Virtual Router MAC
75 *
76 * vrid
77 * Virtual Router Identifier
78 */
79 static void vrrp_mac_set(struct ethaddr *mac, bool v6, uint8_t vrid)
80 {
81 /*
82 * V4: 00-00-5E-00-01-{VRID}
83 * V6: 00-00-5E-00-02-{VRID}
84 */
85 mac->octet[0] = 0x00;
86 mac->octet[1] = 0x00;
87 mac->octet[2] = 0x5E;
88 mac->octet[3] = 0x00;
89 mac->octet[4] = v6 ? 0x02 : 0x01;
90 mac->octet[5] = vrid;
91 }
92
93 /*
94 * Recalculates and sets skew_time and master_down_interval based
95 * values.
96 *
97 * r
98 * VRRP Router to operate on
99 */
100 static void vrrp_recalculate_timers(struct vrrp_router *r)
101 {
102 uint16_t mdiadv = r->vr->version == 3 ? r->master_adver_interval
103 : r->vr->advertisement_interval;
104 uint16_t skm = (r->vr->version == 3) ? r->master_adver_interval : 100;
105
106 r->skew_time = ((256 - r->vr->priority) * skm) / 256;
107 r->master_down_interval = 3 * mdiadv;
108 r->master_down_interval += r->skew_time;
109 }
110
111 /*
112 * Determines if a VRRP router is the owner of the specified address.
113 *
114 * The determining factor for whether an interface is the address owner is
115 * simply whether the address is assigned to the VRRP base interface by someone
116 * other than vrrpd.
117 *
118 * This function should always return the correct answer regardless of
119 * master/backup status.
120 *
121 * ifp
122 * The interface to check owernship of. This should be the base interface of
123 * a VRRP router.
124 *
125 * vr
126 * Virtual Router
127 *
128 * Returns:
129 * whether or not vr owns the specified address
130 */
131 static bool vrrp_is_owner(struct interface *ifp, struct ipaddr *addr)
132 {
133 /*
134 * This code sanity checks implicit ownership configuration. Ideally,
135 * the way we determine address ownership status for this VRRP router
136 * is by looking at whether our VIPs are also assigned to the base
137 * interface, and therefore count as "real" addresses. This frees the
138 * user from having to manually configure priority 255 to indicate
139 * address ownership. However, this means one of the VIPs will be used
140 * as the source address for VRRP advertisements, which in turn means
141 * that other VRRP routers will be receiving packets with a source
142 * address they themselves have. This causes lots of different issues
143 * so for now we're disabling this and forcing the user to configure
144 * priority 255 to indicate ownership.
145 */
146
147 return false;
148
149 #if 0
150 struct prefix p;
151
152 p.family = IS_IPADDR_V4(addr) ? AF_INET : AF_INET6;
153 p.prefixlen = IS_IPADDR_V4(addr) ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN;
154 memcpy(&p.u, &addr->ip, sizeof(addr->ip));
155
156 return !!connected_lookup_prefix_exact(ifp, &p);
157 #endif
158 }
159
160 /*
161 * Whether an interface has a MAC address that matches the VRRP RFC.
162 *
163 * ifp
164 * Interface to check
165 *
166 * Returns:
167 * Whether the interface has a VRRP mac or not
168 */
169 static bool vrrp_ifp_has_vrrp_mac(struct interface *ifp)
170 {
171 struct ethaddr vmac4;
172 struct ethaddr vmac6;
173
174 vrrp_mac_set(&vmac4, 0, 0x00);
175 vrrp_mac_set(&vmac6, 1, 0x00);
176
177 return !memcmp(ifp->hw_addr, vmac4.octet, sizeof(vmac4.octet) - 1)
178 || !memcmp(ifp->hw_addr, vmac6.octet, sizeof(vmac6.octet) - 1);
179 }
180
181 /*
182 * Lookup a Virtual Router instance given a macvlan subinterface.
183 *
184 * The VRID is extracted from the interface MAC and the 2-tuple (iface, vrid)
185 * is used to look up any existing instances that match the interface. It does
186 * not matter whether the instance is already bound to the interface or not.
187 *
188 * mvl_ifp
189 * Interface pointer to use to lookup. Should be a macvlan device.
190 *
191 * Returns:
192 * Virtual Router, if found
193 * NULL otherwise
194 */
195 static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp)
196 {
197 struct interface *p;
198
199 if (!mvl_ifp || mvl_ifp->link_ifindex == 0
200 || !vrrp_ifp_has_vrrp_mac(mvl_ifp)) {
201 if (mvl_ifp && mvl_ifp->link_ifindex == 0)
202 DEBUGD(&vrrp_dbg_zebra,
203 VRRP_LOGPFX
204 "Interface %s has no parent ifindex; disregarding",
205 mvl_ifp->name);
206 if (mvl_ifp && !vrrp_ifp_has_vrrp_mac(mvl_ifp))
207 DEBUGD(&vrrp_dbg_zebra,
208 VRRP_LOGPFX
209 "Interface %s has a non-VRRP MAC; disregarding",
210 mvl_ifp->name);
211 return NULL;
212 }
213
214 p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
215 uint8_t vrid = mvl_ifp->hw_addr[5];
216
217 return vrrp_lookup(p, vrid);
218 }
219
220 /*
221 * Lookup the Virtual Router instances configured on a particular interface.
222 *
223 * ifp
224 * Interface pointer to use to lookup. Should not be a macvlan device.
225 *
226 * Returns:
227 * List of virtual routers found
228 */
229 static struct list *vrrp_lookup_by_if(struct interface *ifp)
230 {
231 struct list *l = hash_to_list(vrrp_vrouters_hash);
232 struct listnode *ln, *nn;
233 struct vrrp_vrouter *vr;
234
235 for (ALL_LIST_ELEMENTS(l, ln, nn, vr))
236 if (vr->ifp != ifp)
237 list_delete_node(l, ln);
238
239 return l;
240 }
241
242 /*
243 * Lookup any Virtual Router instances associated with a particular interface.
244 * This is a combination of the results from vrrp_lookup_by_if_mvl and
245 * vrrp_lookup_by_if.
246 *
247 * Suppose the system interface list looks like the following:
248 *
249 * eth0
250 * \- eth0-v0 00:00:5e:00:01:01
251 * \- eth0-v1 00:00:5e:00:02:01
252 * \- eth0-v2 00:00:5e:00:01:0a
253 *
254 * Passing eth0-v2 to this function will give you the VRRP instance configured
255 * on eth0 with VRID 10. Passing eth0-v0 or eth0-v1 will give you the VRRP
256 * instance configured on eth0 with VRID 1. Passing eth0 will give you both.
257 *
258 * ifp
259 * Interface pointer to use to lookup. Can be any interface.
260 *
261 * Returns:
262 * List of virtual routers found
263 */
264 static struct list *vrrp_lookup_by_if_any(struct interface *ifp)
265 {
266 struct vrrp_vrouter *vr;
267 struct list *vrs;
268
269 vr = vrrp_lookup_by_if_mvl(ifp);
270 vrs = vr ? list_new() : vrrp_lookup_by_if(ifp);
271
272 if (vr)
273 listnode_add(vrs, vr);
274
275 return vrs;
276 }
277
278 /* Configuration controllers ----------------------------------------------- */
279
280 void vrrp_check_start(struct vrrp_vrouter *vr)
281 {
282 struct vrrp_router *r;
283 bool start;
284 const char *whynot;
285
286 if (vr->shutdown || vr->ifp == NULL)
287 return;
288
289 r = vr->v4;
290 /* Must not already be started */
291 start = r->fsm.state == VRRP_STATE_INITIALIZE;
292 whynot = NULL;
293 /* Must have a parent interface */
294 start = start && (vr->ifp != NULL);
295 whynot = (!start && !whynot) ? "No base interface" : whynot;
296 #if 0
297 /* Parent interface must be up */
298 start = start && if_is_operative(vr->ifp);
299 #endif
300 /* Parent interface must have at least one v4 */
301 start = start && connected_count_by_family(vr->ifp, AF_INET) > 0;
302 whynot = (!start && !whynot) ? "No primary IPv4 address" : whynot;
303 /* Must have a macvlan interface */
304 start = start && (r->mvl_ifp != NULL);
305 whynot = (!start && !whynot) ? "No VRRP interface" : whynot;
306 #if 0
307 /* Macvlan interface must be admin up */
308 start = start && CHECK_FLAG(r->mvl_ifp->flags, IFF_UP);
309 #endif
310 /* Must have at least one VIP configured */
311 start = start && r->addrs->count > 0;
312 whynot = (!start && !whynot) ? "No Virtual IP address configured"
313 : whynot;
314 if (start)
315 vrrp_event(r, VRRP_EVENT_STARTUP);
316 else if (whynot)
317 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
318 "Refusing to start Virtual Router: %s",
319 vr->vrid, family2str(r->family), whynot);
320
321 r = vr->v6;
322 /* Must not already be started */
323 start = r->fsm.state == VRRP_STATE_INITIALIZE;
324 whynot = NULL;
325 /* Must not be v2 */
326 start = start && vr->version != 2;
327 whynot = (!start && !whynot) ? "VRRPv2 does not support v6" : whynot;
328 /* Must have a parent interface */
329 start = start && (vr->ifp != NULL);
330 whynot = (!start && !whynot) ? "No base interface" : whynot;
331 #if 0
332 /* Parent interface must be up */
333 start = start && if_is_operative(vr->ifp);
334 #endif
335 /* Must have a macvlan interface */
336 start = start && (r->mvl_ifp != NULL);
337 whynot = (!start && !whynot) ? "No VRRP interface" : whynot;
338 #if 0
339 /* Macvlan interface must be admin up */
340 start = start && CHECK_FLAG(r->mvl_ifp->flags, IFF_UP);
341 /* Macvlan interface must have a link local */
342 start = start && connected_get_linklocal(r->mvl_ifp);
343 whynot =
344 (!start && !whynot) ? "No link local address configured" : whynot;
345 /* Macvlan interface must have a v6 IP besides the link local */
346 start = start && (connected_count_by_family(r->mvl_ifp, AF_INET6) > 1);
347 whynot = (!start && !whynot)
348 ? "No Virtual IPv6 address configured on macvlan device"
349 : whynot;
350 #endif
351 /* Must have at least one VIP configured */
352 start = start && r->addrs->count > 0;
353 whynot =
354 (!start && !whynot) ? "No Virtual IP address configured" : whynot;
355 if (start)
356 vrrp_event(r, VRRP_EVENT_STARTUP);
357 else if (whynot)
358 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
359 "Refusing to start Virtual Router: %s",
360 vr->vrid, family2str(r->family), whynot);
361 }
362
363 void vrrp_set_priority(struct vrrp_vrouter *vr, uint8_t priority)
364 {
365 vr->priority = priority;
366 vr->v4->priority = priority;
367 vr->v6->priority = priority;
368 }
369
370 void vrrp_set_advertisement_interval(struct vrrp_vrouter *vr,
371 uint16_t advertisement_interval)
372 {
373 if (vr->advertisement_interval == advertisement_interval)
374 return;
375
376 vr->advertisement_interval = advertisement_interval;
377 vrrp_recalculate_timers(vr->v4);
378 vrrp_recalculate_timers(vr->v6);
379 }
380
381 static bool vrrp_has_ip(struct vrrp_vrouter *vr, struct ipaddr *ip)
382 {
383 struct vrrp_router *r = ip->ipa_type == IPADDR_V4 ? vr->v4 : vr->v6;
384 struct listnode *ln;
385 struct ipaddr *iter;
386
387 for (ALL_LIST_ELEMENTS_RO(r->addrs, ln, iter))
388 if (!memcmp(&iter->ip, &ip->ip, IPADDRSZ(ip)))
389 return true;
390
391 return false;
392 }
393
394 int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip)
395 {
396 int af = (ip->ipa_type == IPADDR_V6) ? AF_INET6 : AF_INET;
397
398 assert(r->family == af);
399 assert(!(r->vr->version == 2 && ip->ipa_type == IPADDR_V6));
400
401 if (vrrp_has_ip(r->vr, ip))
402 return 0;
403
404 if (!vrrp_is_owner(r->vr->ifp, ip) && r->is_owner) {
405 char ipbuf[INET6_ADDRSTRLEN];
406
407 inet_ntop(r->family, &ip->ip, ipbuf, sizeof(ipbuf));
408 zlog_err(
409 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
410 "This VRRP router is not the address owner of %s, but is the address owner of other addresses; this config is unsupported.",
411 r->vr->vrid, family2str(r->family), ipbuf);
412 return -1;
413 }
414
415 struct ipaddr *new = XCALLOC(MTYPE_VRRP_IP, sizeof(struct ipaddr));
416
417 *new = *ip;
418 listnode_add(r->addrs, new);
419
420 if (r->fsm.state == VRRP_STATE_MASTER) {
421 switch (r->family) {
422 case AF_INET:
423 vrrp_garp_send(r, &new->ipaddr_v4);
424 break;
425 case AF_INET6:
426 vrrp_ndisc_una_send(r, new);
427 break;
428 }
429 }
430
431 return 0;
432 }
433
434 int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
435 {
436 struct ipaddr ip;
437
438 ip.ipa_type = IPADDR_V4;
439 ip.ipaddr_v4 = v4;
440 return vrrp_add_ip(vr->v4, &ip);
441 }
442
443 int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
444 {
445 assert(vr->version != 2);
446
447 struct ipaddr ip;
448
449 ip.ipa_type = IPADDR_V6;
450 ip.ipaddr_v6 = v6;
451 return vrrp_add_ip(vr->v6, &ip);
452 }
453
454 int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip)
455 {
456 struct listnode *ln, *nn;
457 struct ipaddr *iter;
458 int ret = 0;
459
460 if (!vrrp_has_ip(r->vr, ip))
461 return 0;
462
463 for (ALL_LIST_ELEMENTS(r->addrs, ln, nn, iter))
464 if (!memcmp(&iter->ip, &ip->ip, IPADDRSZ(ip)))
465 list_delete_node(r->addrs, ln);
466
467 /*
468 * NB: Deleting the last address and then issuing a shutdown will cause
469 * transmission of a priority 0 VRRP Advertisement - as per the RFC -
470 * but it will have no addresses. This is not forbidden in the RFC but
471 * might confuse other implementations.
472 */
473 if (r->addrs->count == 0 && r->fsm.state != VRRP_STATE_INITIALIZE)
474 ret = vrrp_event(r, VRRP_EVENT_SHUTDOWN);
475
476 return ret;
477 }
478
479 int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
480 {
481 struct ipaddr ip;
482
483 ip.ipa_type = IPADDR_V6;
484 ip.ipaddr_v6 = v6;
485 return vrrp_del_ip(vr->v6, &ip);
486 }
487
488 int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
489 {
490 struct ipaddr ip;
491
492 ip.ipa_type = IPADDR_V4;
493 ip.ipaddr_v4 = v4;
494 return vrrp_del_ip(vr->v4, &ip);
495 }
496
497
498 /* Creation and destruction ------------------------------------------------ */
499
500 static void vrrp_router_addr_list_del_cb(void *val)
501 {
502 struct ipaddr *ip = val;
503
504 XFREE(MTYPE_VRRP_IP, ip);
505 }
506
507 /*
508 * Search for a suitable macvlan subinterface we can attach to, and if found,
509 * attach to it.
510 *
511 * r
512 * Router to attach to interface
513 *
514 * Returns:
515 * Whether an interface was successfully attached
516 */
517 static bool vrrp_attach_interface(struct vrrp_router *r)
518 {
519 /* Search for existing interface with computed MAC address */
520 struct interface **ifps;
521
522 size_t ifps_cnt = if_lookup_by_hwaddr(
523 r->vmac.octet, sizeof(r->vmac.octet), &ifps, VRF_DEFAULT);
524
525 /*
526 * Filter to only those macvlan interfaces whose parent is the base
527 * interface this VRRP router is configured on.
528 *
529 * If there are still multiple interfaces we just select the first one,
530 * as it should be functionally identical to the others.
531 */
532 unsigned int candidates = 0;
533 struct interface *selection = NULL;
534
535 for (unsigned int i = 0; i < ifps_cnt; i++) {
536 if (ifps[i]->link_ifindex != r->vr->ifp->ifindex)
537 ifps[i] = NULL;
538 else {
539 selection = selection ? selection : ifps[i];
540 candidates++;
541 }
542 }
543
544 if (ifps_cnt)
545 XFREE(MTYPE_TMP, ifps);
546
547 char ethstr[ETHER_ADDR_STRLEN];
548
549 prefix_mac2str(&r->vmac, ethstr, sizeof(ethstr));
550
551 assert(!!selection == !!candidates);
552
553 if (candidates == 0)
554 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
555 "Interface: None (no interface found w/ MAC %s)",
556 r->vr->vrid, family2str(r->family), ethstr);
557 else if (candidates > 1)
558 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
559 "Interface: Multiple interfaces found; using %s",
560 r->vr->vrid, family2str(r->family), selection->name);
561 else
562 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
563 "Interface: %s",
564 r->vr->vrid, family2str(r->family), selection->name);
565
566 r->mvl_ifp = selection;
567
568 return !!r->mvl_ifp;
569 }
570
571 static struct vrrp_router *vrrp_router_create(struct vrrp_vrouter *vr,
572 int family)
573 {
574 struct vrrp_router *r =
575 XCALLOC(MTYPE_VRRP_RTR, sizeof(struct vrrp_router));
576
577 r->family = family;
578 r->sock_rx = -1;
579 r->sock_tx = -1;
580 r->vr = vr;
581 r->addrs = list_new();
582 r->addrs->del = vrrp_router_addr_list_del_cb;
583 r->priority = vr->priority;
584 r->fsm.state = VRRP_STATE_INITIALIZE;
585 vrrp_mac_set(&r->vmac, family == AF_INET6, vr->vrid);
586
587 vrrp_attach_interface(r);
588
589 return r;
590 }
591
592 static void vrrp_router_destroy(struct vrrp_router *r)
593 {
594 if (r->is_active)
595 vrrp_event(r, VRRP_EVENT_SHUTDOWN);
596
597 if (r->sock_rx >= 0)
598 close(r->sock_rx);
599 if (r->sock_tx >= 0)
600 close(r->sock_tx);
601
602 /* FIXME: also delete list elements */
603 list_delete(&r->addrs);
604 XFREE(MTYPE_VRRP_RTR, r);
605 }
606
607 struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid,
608 uint8_t version)
609 {
610 struct vrrp_vrouter *vr = vrrp_lookup(ifp, vrid);
611
612 if (vr)
613 return vr;
614
615 if (version != 2 && version != 3)
616 return NULL;
617
618 vr = XCALLOC(MTYPE_VRRP_RTR, sizeof(struct vrrp_vrouter));
619
620 vr->ifp = ifp;
621 vr->version = version;
622 vr->vrid = vrid;
623 vr->priority = vd.priority;
624 vr->preempt_mode = vd.preempt_mode;
625 vr->accept_mode = vd.accept_mode;
626 vr->shutdown = vd.shutdown;
627
628 vr->v4 = vrrp_router_create(vr, AF_INET);
629 vr->v6 = vrrp_router_create(vr, AF_INET6);
630
631 vrrp_set_advertisement_interval(vr, vd.advertisement_interval);
632
633 hash_get(vrrp_vrouters_hash, vr, hash_alloc_intern);
634
635 return vr;
636 }
637
638 void vrrp_vrouter_destroy(struct vrrp_vrouter *vr)
639 {
640 vrrp_router_destroy(vr->v4);
641 vrrp_router_destroy(vr->v6);
642 hash_release(vrrp_vrouters_hash, vr);
643 XFREE(MTYPE_VRRP_RTR, vr);
644 }
645
646 struct vrrp_vrouter *vrrp_lookup(struct interface *ifp, uint8_t vrid)
647 {
648 struct vrrp_vrouter vr;
649
650 vr.vrid = vrid;
651 vr.ifp = ifp;
652
653 return hash_lookup(vrrp_vrouters_hash, &vr);
654 }
655
656 /* Network ----------------------------------------------------------------- */
657
658 /* Forward decls */
659 static void vrrp_change_state(struct vrrp_router *r, int to);
660 static int vrrp_adver_timer_expire(struct thread *thread);
661 static int vrrp_master_down_timer_expire(struct thread *thread);
662
663 /*
664 * Finds the first connected address of the appropriate family on a VRRP
665 * router's interface and binds the Tx socket of the VRRP router to that
666 * address.
667 *
668 * Also sets src field of vrrp_router.
669 *
670 * r
671 * VRRP router to operate on
672 *
673 * Returns:
674 * 0 on success
675 * -1 on failure
676 */
677 static int vrrp_bind_to_primary_connected(struct vrrp_router *r)
678 {
679 char ipstr[INET6_ADDRSTRLEN];
680 struct interface *ifp;
681
682 /*
683 * A slight quirk: the RFC specifies that advertisements under IPv6 must
684 * be transmitted using the link local address of the source interface
685 */
686 ifp = r->family == AF_INET ? r->vr->ifp : r->mvl_ifp;
687
688 struct listnode *ln;
689 struct connected *c = NULL;
690
691 for (ALL_LIST_ELEMENTS_RO(ifp->connected, ln, c))
692 if (c->address->family == r->family) {
693 if (r->family == AF_INET6
694 && IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
695 break;
696 else if (r->family == AF_INET)
697 break;
698 }
699
700 if (c == NULL) {
701 zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
702 "Failed to find address to bind on %s",
703 r->vr->vrid, family2str(r->family), ifp->name);
704 return -1;
705 }
706
707 union sockunion su;
708
709 memset(&su, 0x00, sizeof(su));
710
711 switch (r->family) {
712 case AF_INET:
713 r->src.ipa_type = IPADDR_V4;
714 r->src.ipaddr_v4 = c->address->u.prefix4;
715 su.sin.sin_family = AF_INET;
716 su.sin.sin_addr = c->address->u.prefix4;
717 break;
718 case AF_INET6:
719 r->src.ipa_type = IPADDR_V6;
720 r->src.ipaddr_v6 = c->address->u.prefix6;
721 su.sin6.sin6_family = AF_INET6;
722 su.sin6.sin6_scope_id = ifp->ifindex;
723 su.sin6.sin6_addr = c->address->u.prefix6;
724 break;
725 }
726
727 int ret = 0;
728
729 sockopt_reuseaddr(r->sock_tx);
730 if (bind(r->sock_tx, (const struct sockaddr *)&su, sizeof(su)) < 0) {
731 zlog_err(
732 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
733 "Failed to bind Tx socket to primary IP address %s: %s",
734 r->vr->vrid, family2str(r->family),
735 inet_ntop(r->family,
736 (const void *)&c->address->u.prefix, ipstr,
737 sizeof(ipstr)),
738 safe_strerror(errno));
739 ret = -1;
740 } else {
741 DEBUGD(&vrrp_dbg_sock,
742 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
743 "Bound Tx socket to primary IP address %s",
744 r->vr->vrid, family2str(r->family),
745 inet_ntop(r->family, (const void *)&c->address->u.prefix,
746 ipstr, sizeof(ipstr)));
747 }
748
749 return ret;
750 }
751
752
753 /*
754 * Create and multicast a VRRP ADVERTISEMENT message.
755 *
756 * r
757 * VRRP Router for which to send ADVERTISEMENT
758 */
759 static void vrrp_send_advertisement(struct vrrp_router *r)
760 {
761 struct vrrp_pkt *pkt;
762 ssize_t pktsz;
763 struct ipaddr *addrs[r->addrs->count];
764 union sockunion dest;
765
766 if (r->src.ipa_type == IPADDR_NONE
767 && vrrp_bind_to_primary_connected(r) < 0)
768 return;
769
770 list_to_array(r->addrs, (void **)addrs, r->addrs->count);
771
772 pktsz = vrrp_pkt_adver_build(&pkt, &r->src, r->vr->version, r->vr->vrid,
773 r->priority, r->vr->advertisement_interval,
774 r->addrs->count, (struct ipaddr **)&addrs);
775
776 if (DEBUG_MODE_CHECK(&vrrp_dbg_pkt, DEBUG_MODE_ALL))
777 zlog_hexdump(pkt, (size_t)pktsz);
778
779 const char *group = r->family == AF_INET ? VRRP_MCASTV4_GROUP_STR
780 : VRRP_MCASTV6_GROUP_STR;
781 (void)str2sockunion(group, &dest);
782
783 ssize_t sent = sendto(r->sock_tx, pkt, (size_t)pktsz, 0, &dest.sa,
784 sockunion_sizeof(&dest));
785
786 vrrp_pkt_free(pkt);
787
788 if (sent < 0) {
789 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
790 "Failed to send VRRP Advertisement: %s",
791 r->vr->vrid, family2str(r->family),
792 safe_strerror(errno));
793 } else {
794 ++r->stats.adver_tx_cnt;
795 }
796 }
797
798 /*
799 * Receive and parse VRRP advertisement.
800 *
801 * By the time we get here all fields have been validated for basic correctness
802 * and the packet is a valid VRRP packet.
803 *
804 * However, we have not validated whether the VRID is correct for this virtual
805 * router, nor whether the priority is correct (i.e. is not 255 when we are the
806 * address owner), nor whether the advertisement interval equals our own
807 * configured value (this check is only performed in VRRPv2).
808 *
809 * r
810 * VRRP Router associated with the socket this advertisement was received on
811 *
812 * src
813 * Source address of sender
814 *
815 * pkt
816 * The advertisement they sent
817 *
818 * pktsize
819 * Size of advertisement
820 *
821 * Returns:
822 * -1 if advertisement is invalid
823 * 0 otherwise
824 */
825 static int vrrp_recv_advertisement(struct vrrp_router *r, struct ipaddr *src,
826 struct vrrp_pkt *pkt, size_t pktsize)
827 {
828 char sipstr[INET6_ADDRSTRLEN];
829 char dipstr[INET6_ADDRSTRLEN];
830
831 ipaddr2str(src, sipstr, sizeof(sipstr));
832 ipaddr2str(&r->src, dipstr, sizeof(dipstr));
833
834 char dumpbuf[BUFSIZ];
835
836 vrrp_pkt_adver_dump(dumpbuf, sizeof(dumpbuf), pkt);
837 DEBUGD(&vrrp_dbg_proto,
838 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
839 "Received VRRP Advertisement from %s:\n%s",
840 r->vr->vrid, family2str(r->family), sipstr, dumpbuf);
841
842 /* Check that VRID matches our configured VRID */
843 if (pkt->hdr.vrid != r->vr->vrid) {
844 DEBUGD(&vrrp_dbg_proto,
845 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
846 "Datagram invalid: Advertisement contains VRID %" PRIu8
847 " which does not match our instance",
848 r->vr->vrid, family2str(r->family), pkt->hdr.vrid);
849 return -1;
850 }
851
852 /* Verify that we are not the IPvX address owner */
853 if (r->is_owner) {
854 DEBUGD(&vrrp_dbg_proto,
855 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
856 "Datagram invalid: Received advertisement but we are the address owner",
857 r->vr->vrid, family2str(r->family));
858 return -1;
859 }
860
861 /* If v2, verify that adver time matches ours */
862 bool adveq = (pkt->hdr.v2.adver_int
863 == MAX(r->vr->advertisement_interval / 100, 1));
864 if (r->vr->version == 2 && !adveq) {
865 DEBUGD(&vrrp_dbg_proto,
866 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
867 "Datagram invalid: Received advertisement with advertisement interval %" PRIu8
868 " unequal to our configured value %u",
869 r->vr->vrid, family2str(r->family),
870 pkt->hdr.v2.adver_int,
871 MAX(r->vr->advertisement_interval / 100, 1));
872 return -1;
873 }
874
875
876 /* Check that # IPs received matches our # configured IPs */
877 if (pkt->hdr.naddr != r->addrs->count)
878 DEBUGD(&vrrp_dbg_proto,
879 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
880 "Datagram has %" PRIu8
881 " addresses, but this VRRP instance has %u",
882 r->vr->vrid, family2str(r->family), pkt->hdr.naddr,
883 r->addrs->count);
884
885 ++r->stats.adver_rx_cnt;
886
887 int addrcmp;
888
889 switch (r->fsm.state) {
890 case VRRP_STATE_MASTER:
891 addrcmp = memcmp(&src->ip, &r->src.ip, IPADDRSZ(src));
892
893 if (pkt->hdr.priority == 0) {
894 vrrp_send_advertisement(r);
895 THREAD_OFF(r->t_adver_timer);
896 thread_add_timer_msec(
897 master, vrrp_adver_timer_expire, r,
898 r->vr->advertisement_interval * CS2MS,
899 &r->t_adver_timer);
900 } else if (pkt->hdr.priority > r->priority
901 || ((pkt->hdr.priority == r->priority)
902 && addrcmp > 0)) {
903 zlog_info(
904 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
905 "Received advertisement from %s w/ priority %" PRIu8
906 "; switching to Backup",
907 r->vr->vrid, family2str(r->family), sipstr,
908 pkt->hdr.priority);
909 THREAD_OFF(r->t_adver_timer);
910 if (r->vr->version == 3) {
911 r->master_adver_interval =
912 htons(pkt->hdr.v3.adver_int);
913 }
914 vrrp_recalculate_timers(r);
915 THREAD_OFF(r->t_master_down_timer);
916 thread_add_timer_msec(master,
917 vrrp_master_down_timer_expire, r,
918 r->master_down_interval * CS2MS,
919 &r->t_master_down_timer);
920 vrrp_change_state(r, VRRP_STATE_BACKUP);
921 } else {
922 /* Discard advertisement */
923 DEBUGD(&vrrp_dbg_proto,
924 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
925 "Discarding advertisement from %s (%" PRIu8
926 " <= %" PRIu8 " & %s <= %s)",
927 r->vr->vrid, family2str(r->family), sipstr,
928 pkt->hdr.priority, r->priority, sipstr, dipstr);
929 }
930 break;
931 case VRRP_STATE_BACKUP:
932 if (pkt->hdr.priority == 0) {
933 THREAD_OFF(r->t_master_down_timer);
934 thread_add_timer_msec(
935 master, vrrp_master_down_timer_expire, r,
936 r->skew_time * CS2MS, &r->t_master_down_timer);
937 } else if (r->vr->preempt_mode == false
938 || pkt->hdr.priority >= r->priority) {
939 if (r->vr->version == 3) {
940 r->master_adver_interval =
941 ntohs(pkt->hdr.v3.adver_int);
942 }
943 vrrp_recalculate_timers(r);
944 THREAD_OFF(r->t_master_down_timer);
945 thread_add_timer_msec(master,
946 vrrp_master_down_timer_expire, r,
947 r->master_down_interval * CS2MS,
948 &r->t_master_down_timer);
949 } else if (r->vr->preempt_mode == true
950 && pkt->hdr.priority < r->priority) {
951 /* Discard advertisement */
952 DEBUGD(&vrrp_dbg_proto,
953 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
954 "Discarding advertisement from %s (%" PRIu8
955 " < %" PRIu8 " & preempt = true)",
956 r->vr->vrid, family2str(r->family), sipstr,
957 pkt->hdr.priority, r->priority);
958 }
959 break;
960 case VRRP_STATE_INITIALIZE:
961 zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
962 "Received ADVERTISEMENT in state %s; this is a bug",
963 r->vr->vrid, family2str(r->family),
964 vrrp_state_names[r->fsm.state]);
965 break;
966 }
967
968 return 0;
969 }
970
971 /*
972 * Read and process next IPvX datagram.
973 */
974 static int vrrp_read(struct thread *thread)
975 {
976 struct vrrp_router *r = thread->arg;
977
978 struct vrrp_pkt *pkt;
979 ssize_t pktsize;
980 ssize_t nbytes;
981 bool resched;
982 char errbuf[BUFSIZ];
983 struct sockaddr_storage sa;
984 uint8_t control[64];
985 struct ipaddr src = {};
986
987 struct msghdr m = {};
988 struct iovec iov;
989
990 iov.iov_base = r->ibuf;
991 iov.iov_len = sizeof(r->ibuf);
992 m.msg_name = &sa;
993 m.msg_namelen = sizeof(sa);
994 m.msg_iov = &iov;
995 m.msg_iovlen = 1;
996 m.msg_control = control;
997 m.msg_controllen = sizeof(control);
998
999 nbytes = recvmsg(r->sock_rx, &m, MSG_DONTWAIT);
1000
1001 if ((nbytes < 0 && ERRNO_IO_RETRY(errno))) {
1002 resched = true;
1003 goto done;
1004 } else if (nbytes <= 0) {
1005 vrrp_event(r, VRRP_EVENT_SHUTDOWN);
1006 resched = false;
1007 goto done;
1008 }
1009
1010 if (DEBUG_MODE_CHECK(&vrrp_dbg_pkt, DEBUG_MODE_ALL)) {
1011 DEBUGD(&vrrp_dbg_pkt,
1012 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1013 "Datagram rx: ",
1014 r->vr->vrid, family2str(r->family));
1015 zlog_hexdump(r->ibuf, nbytes);
1016 }
1017
1018 pktsize = vrrp_pkt_parse_datagram(r->family, r->vr->version, &m, nbytes,
1019 &src, &pkt, errbuf, sizeof(errbuf));
1020
1021 if (pktsize < 0)
1022 DEBUGD(&vrrp_dbg_pkt,
1023 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1024 "Datagram invalid: %s",
1025 r->vr->vrid, family2str(r->family), errbuf);
1026 else
1027 vrrp_recv_advertisement(r, &src, pkt, pktsize);
1028
1029 resched = true;
1030
1031 done:
1032 memset(r->ibuf, 0x00, sizeof(r->ibuf));
1033
1034 if (resched)
1035 thread_add_read(master, vrrp_read, r, r->sock_rx, &r->t_read);
1036
1037 return 0;
1038 }
1039
1040 /*
1041 * Creates and configures VRRP router sockets.
1042 *
1043 * This function:
1044 * - Creates two sockets, one for Tx, one for Rx
1045 * - Joins the Rx socket to the appropriate VRRP multicast group
1046 * - Sets the Tx socket to set the TTL (v4) or Hop Limit (v6) field to 255 for
1047 * all transmitted IPvX packets
1048 * - Requests the kernel to deliver IPv6 header values needed to validate VRRP
1049 * packets
1050 *
1051 * If any of the above fail, the sockets are closed. The only exception is if
1052 * the TTL / Hop Limit settings fail; these are logged, but configuration
1053 * proceeds.
1054 *
1055 * The first connected address on the Virtual Router's interface is used as the
1056 * interface address.
1057 *
1058 * r
1059 * VRRP Router for which to create listen socket
1060 *
1061 * Returns:
1062 * 0 on success
1063 * -1 on failure
1064 */
1065 static int vrrp_socket(struct vrrp_router *r)
1066 {
1067 int ret;
1068 bool failed = false;
1069
1070 frr_with_privs(&vrrp_privs) {
1071 r->sock_rx = socket(r->family, SOCK_RAW, IPPROTO_VRRP);
1072 r->sock_tx = socket(r->family, SOCK_RAW, IPPROTO_VRRP);
1073 }
1074
1075 if (r->sock_rx < 0 || r->sock_tx < 0) {
1076 const char *rxtx = r->sock_rx < 0 ? "Rx" : "Tx";
1077
1078 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1079 "Can't create VRRP %s socket",
1080 r->vr->vrid, family2str(r->family), rxtx);
1081 failed = true;
1082 goto done;
1083 }
1084
1085 /* Configure sockets */
1086 if (r->family == AF_INET) {
1087 /* Set Tx socket to always Tx with TTL set to 255 */
1088 int ttl = 255;
1089
1090 ret = setsockopt(r->sock_tx, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
1091 sizeof(ttl));
1092 if (ret < 0) {
1093 zlog_warn(
1094 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1095 "Failed to set outgoing multicast TTL count to 255; RFC 5798 compliant implementations will drop our packets",
1096 r->vr->vrid, family2str(r->family));
1097 }
1098
1099 /* Set Tx socket DSCP byte */
1100 setsockopt_ipv4_tos(r->sock_tx, IPTOS_PREC_INTERNETCONTROL);
1101
1102 /* Turn off multicast loop on Tx */
1103 setsockopt_ipv4_multicast_loop(r->sock_tx, 0);
1104
1105 /* Bind Rx socket to exact interface */
1106 frr_with_privs(&vrrp_privs) {
1107 ret = setsockopt(r->sock_rx, SOL_SOCKET,
1108 SO_BINDTODEVICE, r->vr->ifp->name,
1109 strlen(r->vr->ifp->name));
1110 }
1111 if (ret) {
1112 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1113 "Failed to bind Rx socket to %s: %s",
1114 r->vr->vrid, family2str(r->family),
1115 r->vr->ifp->name, safe_strerror(errno));
1116 failed = true;
1117 goto done;
1118 }
1119 DEBUGD(&vrrp_dbg_sock,
1120 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1121 "Bound Rx socket to %s",
1122 r->vr->vrid, family2str(r->family), r->vr->ifp->name);
1123
1124 /* Bind Rx socket to v4 multicast address */
1125 struct sockaddr_in sa = {0};
1126
1127 sa.sin_family = AF_INET;
1128 sa.sin_addr.s_addr = htonl(VRRP_MCASTV4_GROUP);
1129 if (bind(r->sock_rx, (struct sockaddr *)&sa, sizeof(sa))) {
1130 zlog_err(
1131 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1132 "Failed to bind Rx socket to VRRP multicast group: %s",
1133 r->vr->vrid, family2str(r->family),
1134 safe_strerror(errno));
1135 failed = true;
1136 goto done;
1137 }
1138 DEBUGD(&vrrp_dbg_sock,
1139 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1140 "Bound Rx socket to VRRP multicast group",
1141 r->vr->vrid, family2str(r->family));
1142
1143 /* Join Rx socket to VRRP IPv4 multicast group */
1144 assert(listhead(r->vr->ifp->connected));
1145 struct connected *c = listhead(r->vr->ifp->connected)->data;
1146 struct in_addr v4 = c->address->u.prefix4;
1147
1148 ret = setsockopt_ipv4_multicast(r->sock_rx, IP_ADD_MEMBERSHIP,
1149 v4, htonl(VRRP_MCASTV4_GROUP),
1150 r->vr->ifp->ifindex);
1151 if (ret < 0) {
1152 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID
1153 "Failed to join VRRP %s multicast group",
1154 r->vr->vrid, family2str(r->family));
1155 failed = true;
1156 goto done;
1157 }
1158 DEBUGD(&vrrp_dbg_sock,
1159 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1160 "Joined VRRP multicast group",
1161 r->vr->vrid, family2str(r->family));
1162
1163 /* Set outgoing interface for advertisements */
1164 struct ip_mreqn mreqn = {};
1165
1166 mreqn.imr_ifindex = r->mvl_ifp->ifindex;
1167 ret = setsockopt(r->sock_tx, IPPROTO_IP, IP_MULTICAST_IF,
1168 (void *)&mreqn, sizeof(mreqn));
1169 if (ret < 0) {
1170 zlog_warn(
1171 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1172 "Could not set %s as outgoing multicast interface",
1173 r->vr->vrid, family2str(r->family),
1174 r->mvl_ifp->name);
1175 failed = true;
1176 goto done;
1177 }
1178 DEBUGD(&vrrp_dbg_sock,
1179 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1180 "Set %s as outgoing multicast interface",
1181 r->vr->vrid, family2str(r->family), r->mvl_ifp->name);
1182
1183 /* Select and bind source address */
1184 if (vrrp_bind_to_primary_connected(r) < 0) {
1185 failed = true;
1186 goto done;
1187 }
1188
1189 } else if (r->family == AF_INET6) {
1190 /* Always transmit IPv6 packets with hop limit set to 255 */
1191 ret = setsockopt_ipv6_multicast_hops(r->sock_tx, 255);
1192 if (ret < 0) {
1193 zlog_warn(
1194 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1195 "Failed to set outgoing multicast hop count to 255; RFC 5798 compliant implementations will drop our packets",
1196 r->vr->vrid, family2str(r->family));
1197 }
1198
1199 /* Set Tx socket DSCP byte */
1200 setsockopt_ipv6_tclass(r->sock_tx, IPTOS_PREC_INTERNETCONTROL);
1201
1202 /* Request hop limit delivery */
1203 setsockopt_ipv6_hoplimit(r->sock_rx, 1);
1204 if (ret < 0) {
1205 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1206 "Failed to request IPv6 Hop Limit delivery",
1207 r->vr->vrid, family2str(r->family));
1208 failed = true;
1209 goto done;
1210 }
1211
1212 /* Turn off multicast loop on Tx */
1213 setsockopt_ipv6_multicast_loop(r->sock_tx, 0);
1214
1215 /* Bind Rx socket to exact interface */
1216 frr_with_privs(&vrrp_privs) {
1217 ret = setsockopt(r->sock_rx, SOL_SOCKET,
1218 SO_BINDTODEVICE, r->vr->ifp->name,
1219 strlen(r->vr->ifp->name));
1220 }
1221 if (ret) {
1222 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1223 "Failed to bind Rx socket to %s: %s",
1224 r->vr->vrid, family2str(r->family),
1225 r->vr->ifp->name, safe_strerror(errno));
1226 failed = true;
1227 goto done;
1228 }
1229 DEBUGD(&vrrp_dbg_sock,
1230 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1231 "Bound Rx socket to %s",
1232 r->vr->vrid, family2str(r->family), r->vr->ifp->name);
1233
1234 /* Bind Rx socket to v6 multicast address */
1235 struct sockaddr_in6 sa = {0};
1236
1237 sa.sin6_family = AF_INET6;
1238 inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR, &sa.sin6_addr);
1239 if (bind(r->sock_rx, (struct sockaddr *)&sa, sizeof(sa))) {
1240 zlog_err(
1241 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1242 "Failed to bind Rx socket to VRRP multicast group: %s",
1243 r->vr->vrid, family2str(r->family),
1244 safe_strerror(errno));
1245 failed = true;
1246 goto done;
1247 }
1248 DEBUGD(&vrrp_dbg_sock,
1249 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1250 "Bound Rx socket to VRRP multicast group",
1251 r->vr->vrid, family2str(r->family));
1252
1253 /* Join VRRP IPv6 multicast group */
1254 struct ipv6_mreq mreq;
1255
1256 inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR,
1257 &mreq.ipv6mr_multiaddr);
1258 mreq.ipv6mr_interface = r->vr->ifp->ifindex;
1259 ret = setsockopt(r->sock_rx, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1260 &mreq, sizeof(mreq));
1261 if (ret < 0) {
1262 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1263 "Failed to join VRRP multicast group",
1264 r->vr->vrid, family2str(r->family));
1265 failed = true;
1266 goto done;
1267 }
1268 DEBUGD(&vrrp_dbg_sock,
1269 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1270 "Joined VRRP multicast group",
1271 r->vr->vrid, family2str(r->family));
1272
1273 /* Set outgoing interface for advertisements */
1274 ret = setsockopt(r->sock_tx, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1275 &r->mvl_ifp->ifindex, sizeof(ifindex_t));
1276 if (ret < 0) {
1277 zlog_warn(
1278 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1279 "Could not set %s as outgoing multicast interface",
1280 r->vr->vrid, family2str(r->family),
1281 r->mvl_ifp->name);
1282 failed = true;
1283 goto done;
1284 }
1285 DEBUGD(&vrrp_dbg_sock,
1286 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1287 "Set %s as outgoing multicast interface",
1288 r->vr->vrid, family2str(r->family), r->mvl_ifp->name);
1289 }
1290
1291 done:
1292 ret = 0;
1293 if (failed) {
1294 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1295 "Failed to initialize VRRP router",
1296 r->vr->vrid, family2str(r->family));
1297 if (r->sock_rx >= 0) {
1298 close(r->sock_rx);
1299 r->sock_rx = -1;
1300 }
1301 if (r->sock_tx >= 0) {
1302 close(r->sock_tx);
1303 r->sock_tx = -1;
1304 }
1305 ret = -1;
1306 }
1307
1308 return ret;
1309 }
1310
1311
1312 /* State machine ----------------------------------------------------------- */
1313
1314 DEFINE_HOOK(vrrp_change_state_hook, (struct vrrp_router *r, int to), (r, to));
1315
1316 /*
1317 * Handle any necessary actions during state change to MASTER state.
1318 *
1319 * r
1320 * VRRP Router to operate on
1321 */
1322 static void vrrp_change_state_master(struct vrrp_router *r)
1323 {
1324 /* Enable ND Router Advertisements */
1325 if (r->family == AF_INET6)
1326 vrrp_zebra_radv_set(r, true);
1327
1328 /* Set protodown off */
1329 vrrp_zclient_send_interface_protodown(r->mvl_ifp, false);
1330
1331 /*
1332 * If protodown is already off, we can send our stuff, otherwise we
1333 * have to delay until the interface is all the way up
1334 */
1335 if (if_is_operative(r->mvl_ifp)) {
1336 vrrp_send_advertisement(r);
1337
1338 if (r->family == AF_INET)
1339 vrrp_garp_send_all(r);
1340 else if (r->family == AF_INET6)
1341 vrrp_ndisc_una_send_all(r);
1342 } else {
1343 DEBUGD(&vrrp_dbg_proto,
1344 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1345 "Delaying VRRP advertisement until interface is up",
1346 r->vr->vrid, family2str(r->family));
1347 r->advert_pending = true;
1348
1349 if (r->family == AF_INET) {
1350 DEBUGD(&vrrp_dbg_proto,
1351 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1352 "Delaying VRRP gratuitous ARPs until interface is up",
1353 r->vr->vrid, family2str(r->family));
1354 r->garp_pending = true;
1355 } else if (r->family == AF_INET6) {
1356 DEBUGD(&vrrp_dbg_proto,
1357 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1358 "Delaying VRRP unsolicited neighbor advertisement until interface is up",
1359 r->vr->vrid, family2str(r->family));
1360 r->ndisc_pending = true;
1361 }
1362 }
1363 }
1364
1365 /*
1366 * Handle any necessary actions during state change to BACKUP state.
1367 *
1368 * r
1369 * Virtual Router to operate on
1370 */
1371 static void vrrp_change_state_backup(struct vrrp_router *r)
1372 {
1373 /* Disable ND Router Advertisements */
1374 if (r->family == AF_INET6)
1375 vrrp_zebra_radv_set(r, false);
1376
1377 /* Disable Adver_Timer */
1378 THREAD_OFF(r->t_adver_timer);
1379
1380 r->advert_pending = false;
1381 r->garp_pending = false;
1382 r->ndisc_pending = false;
1383 memset(&r->src, 0x00, sizeof(r->src));
1384
1385 vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
1386 }
1387
1388 /*
1389 * Handle any necessary actions during state change to INITIALIZE state.
1390 *
1391 * This is not called for initial startup, only when transitioning from MASTER
1392 * or BACKUP.
1393 *
1394 * r
1395 * VRRP Router to operate on
1396 */
1397 static void vrrp_change_state_initialize(struct vrrp_router *r)
1398 {
1399 r->master_adver_interval = 0;
1400 vrrp_recalculate_timers(r);
1401
1402 r->advert_pending = false;
1403 r->garp_pending = false;
1404 r->ndisc_pending = false;
1405
1406 /* Disable ND Router Advertisements */
1407 if (r->family == AF_INET6)
1408 vrrp_zebra_radv_set(r, false);
1409 }
1410
1411 void (*vrrp_change_state_handlers[])(struct vrrp_router *vr) = {
1412 [VRRP_STATE_MASTER] = vrrp_change_state_master,
1413 [VRRP_STATE_BACKUP] = vrrp_change_state_backup,
1414 [VRRP_STATE_INITIALIZE] = vrrp_change_state_initialize,
1415 };
1416
1417 /*
1418 * Change Virtual Router FSM position. Handles transitional actions and calls
1419 * any subscribers to the state change hook.
1420 *
1421 * r
1422 * Virtual Router for which to change state
1423 *
1424 * to
1425 * State to change to
1426 */
1427 static void vrrp_change_state(struct vrrp_router *r, int to)
1428 {
1429 if (r->fsm.state == to)
1430 return;
1431
1432 /* Call our handlers, then any subscribers */
1433 vrrp_change_state_handlers[to](r);
1434 hook_call(vrrp_change_state_hook, r, to);
1435 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM "%s -> %s",
1436 r->vr->vrid, family2str(r->family),
1437 vrrp_state_names[r->fsm.state], vrrp_state_names[to]);
1438 r->fsm.state = to;
1439
1440 ++r->stats.trans_cnt;
1441 }
1442
1443 /*
1444 * Called when Adver_Timer expires.
1445 */
1446 static int vrrp_adver_timer_expire(struct thread *thread)
1447 {
1448 struct vrrp_router *r = thread->arg;
1449
1450 DEBUGD(&vrrp_dbg_proto,
1451 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1452 "Adver_Timer expired",
1453 r->vr->vrid, family2str(r->family));
1454
1455 if (r->fsm.state == VRRP_STATE_MASTER) {
1456 /* Send an ADVERTISEMENT */
1457 vrrp_send_advertisement(r);
1458
1459 /* Reset the Adver_Timer to Advertisement_Interval */
1460 thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
1461 r->vr->advertisement_interval * CS2MS,
1462 &r->t_adver_timer);
1463 } else {
1464 zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1465 "Adver_Timer expired in state '%s'; this is a bug",
1466 r->vr->vrid, family2str(r->family),
1467 vrrp_state_names[r->fsm.state]);
1468 }
1469
1470 return 0;
1471 }
1472
1473 /*
1474 * Called when Master_Down_Timer expires.
1475 */
1476 static int vrrp_master_down_timer_expire(struct thread *thread)
1477 {
1478 struct vrrp_router *r = thread->arg;
1479
1480 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1481 "Master_Down_Timer expired",
1482 r->vr->vrid, family2str(r->family));
1483
1484 thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
1485 r->vr->advertisement_interval * CS2MS,
1486 &r->t_adver_timer);
1487 vrrp_change_state(r, VRRP_STATE_MASTER);
1488
1489 return 0;
1490 }
1491
1492 /*
1493 * Event handler for Startup event.
1494 *
1495 * Creates sockets, sends advertisements and ARP requests, starts timers,
1496 * and transitions the Virtual Router to either Master or Backup states.
1497 *
1498 * This function will also initialize the program's global ARP subsystem if it
1499 * has not yet been initialized.
1500 *
1501 * r
1502 * VRRP Router on which to apply Startup event
1503 *
1504 * Returns:
1505 * < 0 if the session socket could not be created, or the state is not
1506 * Initialize
1507 * 0 on success
1508 */
1509 static int vrrp_startup(struct vrrp_router *r)
1510 {
1511 /* May only be called when the state is Initialize */
1512 if (r->fsm.state != VRRP_STATE_INITIALIZE)
1513 return -1;
1514
1515 /* Must have a valid macvlan interface available */
1516 if (r->mvl_ifp == NULL && !vrrp_attach_interface(r)) {
1517 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1518 "No appropriate interface found",
1519 r->vr->vrid, family2str(r->family));
1520 return -1;
1521 }
1522
1523 /* Initialize global gratuitous ARP socket if necessary */
1524 if (r->family == AF_INET && !vrrp_garp_is_init())
1525 vrrp_garp_init();
1526 if (r->family == AF_INET6 && !vrrp_ndisc_is_init())
1527 vrrp_ndisc_init();
1528
1529 /* Create socket */
1530 if (r->sock_rx < 0 || r->sock_tx < 0) {
1531 int ret = vrrp_socket(r);
1532
1533 if (ret < 0 || r->sock_tx < 0 || r->sock_rx < 0)
1534 return ret;
1535 }
1536
1537 /* Schedule listener */
1538 thread_add_read(master, vrrp_read, r, r->sock_rx, &r->t_read);
1539
1540 /* Configure effective priority */
1541 assert(listhead(r->addrs));
1542 struct ipaddr *primary = (struct ipaddr *)listhead(r->addrs)->data;
1543 char ipbuf[INET6_ADDRSTRLEN];
1544
1545 inet_ntop(r->family, &primary->ip.addr, ipbuf, sizeof(ipbuf));
1546
1547 if (r->vr->priority == VRRP_PRIO_MASTER
1548 || vrrp_is_owner(r->vr->ifp, primary)) {
1549 r->priority = VRRP_PRIO_MASTER;
1550 vrrp_recalculate_timers(r);
1551
1552 zlog_info(
1553 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1554 "%s has priority set to 255 or owns primary Virtual Router IP %s; electing self as Master",
1555 r->vr->vrid, family2str(r->family), r->vr->ifp->name,
1556 ipbuf);
1557 }
1558
1559 if (r->priority == VRRP_PRIO_MASTER) {
1560 thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
1561 r->vr->advertisement_interval * CS2MS,
1562 &r->t_adver_timer);
1563 vrrp_change_state(r, VRRP_STATE_MASTER);
1564 } else {
1565 r->master_adver_interval = r->vr->advertisement_interval;
1566 vrrp_recalculate_timers(r);
1567 thread_add_timer_msec(master, vrrp_master_down_timer_expire, r,
1568 r->master_down_interval * CS2MS,
1569 &r->t_master_down_timer);
1570 vrrp_change_state(r, VRRP_STATE_BACKUP);
1571 }
1572
1573 r->is_active = true;
1574
1575 return 0;
1576 }
1577
1578 /*
1579 * Shuts down a Virtual Router and transitions it to Initialize.
1580 *
1581 * This call must be idempotent; it is safe to call multiple times on the same
1582 * VRRP Router.
1583 */
1584 static int vrrp_shutdown(struct vrrp_router *r)
1585 {
1586 uint8_t saved_prio;
1587
1588 switch (r->fsm.state) {
1589 case VRRP_STATE_MASTER:
1590 /* Send an ADVERTISEMENT with Priority = 0 */
1591 saved_prio = r->priority;
1592 r->priority = 0;
1593 vrrp_send_advertisement(r);
1594 r->priority = saved_prio;
1595 break;
1596 case VRRP_STATE_BACKUP:
1597 break;
1598 case VRRP_STATE_INITIALIZE:
1599 DEBUGD(&vrrp_dbg_proto,
1600 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1601 "Received '%s' event in '%s' state; ignoring",
1602 r->vr->vrid, family2str(r->family),
1603 vrrp_event_names[VRRP_EVENT_SHUTDOWN],
1604 vrrp_state_names[VRRP_STATE_INITIALIZE]);
1605 break;
1606 }
1607
1608 /* Cancel all timers */
1609 THREAD_OFF(r->t_adver_timer);
1610 THREAD_OFF(r->t_master_down_timer);
1611 THREAD_OFF(r->t_read);
1612 THREAD_OFF(r->t_write);
1613
1614 /* Protodown macvlan */
1615 vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
1616
1617 /* Throw away our source address */
1618 memset(&r->src, 0x00, sizeof(r->src));
1619
1620 if (r->sock_rx > 0) {
1621 close(r->sock_rx);
1622 r->sock_rx = -1;
1623 }
1624 if (r->sock_tx > 0) {
1625 close(r->sock_tx);
1626 r->sock_tx = -1;
1627 }
1628
1629 vrrp_change_state(r, VRRP_STATE_INITIALIZE);
1630
1631 r->is_active = false;
1632
1633 return 0;
1634 }
1635
1636 static int (*vrrp_event_handlers[])(struct vrrp_router *r) = {
1637 [VRRP_EVENT_STARTUP] = vrrp_startup,
1638 [VRRP_EVENT_SHUTDOWN] = vrrp_shutdown,
1639 };
1640
1641 /*
1642 * Spawn a VRRP FSM event on a VRRP Router.
1643 *
1644 * vr
1645 * VRRP Router on which to spawn event
1646 *
1647 * event
1648 * The event to spawn
1649 *
1650 * Returns:
1651 * -1 on failure
1652 * 0 otherwise
1653 */
1654 int vrrp_event(struct vrrp_router *r, int event)
1655 {
1656 zlog_info(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM "'%s' event",
1657 r->vr->vrid, family2str(r->family), vrrp_event_names[event]);
1658 return vrrp_event_handlers[event](r);
1659 }
1660
1661
1662 /* Autoconfig -------------------------------------------------------------- */
1663
1664 /*
1665 * Set the configured addresses for this VRRP instance to exactly the addresses
1666 * present on its macvlan subinterface(s).
1667 *
1668 * vr
1669 * VRRP router to act on
1670 */
1671 static void vrrp_autoconfig_autoaddrupdate(struct vrrp_router *r)
1672 {
1673 struct listnode *ln;
1674 struct connected *c = NULL;
1675 bool is_v6_ll;
1676 char ipbuf[INET6_ADDRSTRLEN];
1677
1678 if (!r->mvl_ifp)
1679 return;
1680
1681 DEBUGD(&vrrp_dbg_auto,
1682 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1683 "Setting Virtual IP list to match IPv4 addresses on %s",
1684 r->vr->vrid, family2str(r->family), r->mvl_ifp->name);
1685 for (ALL_LIST_ELEMENTS_RO(r->mvl_ifp->connected, ln, c)) {
1686 is_v6_ll = (c->address->family == AF_INET6
1687 && IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6));
1688 if (c->address->family == r->family && !is_v6_ll) {
1689 inet_ntop(r->family, &c->address->u.prefix, ipbuf,
1690 sizeof(ipbuf));
1691 DEBUGD(&vrrp_dbg_auto,
1692 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1693 "Adding %s",
1694 r->vr->vrid, family2str(r->family), ipbuf);
1695 if (r->family == AF_INET)
1696 vrrp_add_ipv4(r->vr, c->address->u.prefix4);
1697 else if (r->vr->version == 3)
1698 vrrp_add_ipv6(r->vr, c->address->u.prefix6);
1699 }
1700 }
1701
1702 vrrp_check_start(r->vr);
1703
1704 if (r->addrs->count == 0 && r->fsm.state != VRRP_STATE_INITIALIZE) {
1705 DEBUGD(&vrrp_dbg_auto,
1706 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1707 "Virtual IP list is empty; shutting down",
1708 r->vr->vrid, family2str(r->family));
1709 vrrp_event(r, VRRP_EVENT_SHUTDOWN);
1710 }
1711 }
1712
1713 static struct vrrp_vrouter *
1714 vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
1715 {
1716 struct interface *p;
1717 struct vrrp_vrouter *vr;
1718
1719 p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
1720
1721 if (!p)
1722 return NULL;
1723
1724 uint8_t vrid = mvl_ifp->hw_addr[5];
1725 uint8_t fam = mvl_ifp->hw_addr[4];
1726
1727 DEBUGD(&vrrp_dbg_auto,
1728 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1729 "Autoconfiguring VRRP on %s",
1730 vrid, family2str(fam), p->name);
1731
1732 vr = vrrp_vrouter_create(p, vrid, vrrp_autoconfig_version);
1733
1734 if (!vr) {
1735 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1736 "Failed to autoconfigure VRRP on %s",
1737 vrid, family2str(fam), p->name);
1738 return NULL;
1739 }
1740
1741 vr->autoconf = true;
1742
1743 /*
1744 * If these interfaces are protodown on, we need to un-protodown them
1745 * in order to get Zebra to send us their addresses so we can
1746 * autoconfigure them.
1747 */
1748 if (vr->v4->mvl_ifp)
1749 vrrp_zclient_send_interface_protodown(vr->v4->mvl_ifp, false);
1750 if (vr->v6->mvl_ifp)
1751 vrrp_zclient_send_interface_protodown(vr->v6->mvl_ifp, false);
1752
1753 /* If they're not, we can go ahead and add the addresses we have */
1754 vrrp_autoconfig_autoaddrupdate(vr->v4);
1755 vrrp_autoconfig_autoaddrupdate(vr->v6);
1756
1757 return vr;
1758 }
1759
1760 /*
1761 * Callback to notify autoconfig of interface add.
1762 *
1763 * If the interface is a VRRP-compatible device, and there is no existing VRRP
1764 * router running on it, one is created. All addresses on the interface are
1765 * added to the router.
1766 *
1767 * ifp
1768 * Interface to operate on
1769 *
1770 * Returns:
1771 * -1 on failure
1772 * 0 otherwise
1773 */
1774 static int vrrp_autoconfig_if_add(struct interface *ifp)
1775 {
1776 bool created = false;
1777 struct vrrp_vrouter *vr;
1778
1779 if (!vrrp_autoconfig_is_on)
1780 return 0;
1781
1782 if (!ifp || !ifp->link_ifindex || !vrrp_ifp_has_vrrp_mac(ifp))
1783 return -1;
1784
1785 vr = vrrp_lookup_by_if_mvl(ifp);
1786
1787 if (!vr) {
1788 vr = vrrp_autoconfig_autocreate(ifp);
1789 created = true;
1790 }
1791
1792 if (!vr || vr->autoconf == false)
1793 return 0;
1794
1795 if (!created) {
1796 /*
1797 * We didn't create it, but it has already been autoconfigured.
1798 * Try to attach this interface to the existing instance.
1799 */
1800 if (!vr->v4->mvl_ifp) {
1801 vrrp_attach_interface(vr->v4);
1802 /* If we just attached it, make sure it's turned on */
1803 if (vr->v4->mvl_ifp) {
1804 vrrp_zclient_send_interface_protodown(
1805 vr->v4->mvl_ifp, false);
1806 /*
1807 * If it's already up, we can go ahead and add
1808 * the addresses we have
1809 */
1810 vrrp_autoconfig_autoaddrupdate(vr->v4);
1811 }
1812 }
1813 if (!vr->v6->mvl_ifp) {
1814 vrrp_attach_interface(vr->v6);
1815 /* If we just attached it, make sure it's turned on */
1816 if (vr->v6->mvl_ifp) {
1817 vrrp_zclient_send_interface_protodown(
1818 vr->v6->mvl_ifp, false);
1819 /*
1820 * If it's already up, we can go ahead and add
1821 * the addresses we have
1822 */
1823 vrrp_autoconfig_autoaddrupdate(vr->v6);
1824 }
1825 }
1826 }
1827
1828 return 0;
1829 }
1830
1831 /*
1832 * Callback to notify autoconfig of interface delete.
1833 *
1834 * If the interface is a VRRP-compatible device, and a VRRP router is running
1835 * on it, and that VRRP router was automatically configured, it will be
1836 * deleted. If that was the last router for the corresponding VRID (i.e., if
1837 * this interface was a v4 VRRP interface and no v6 router is configured for
1838 * the same VRID) then the entire virtual router is deleted.
1839 *
1840 * ifp
1841 * Interface to operate on
1842 *
1843 * Returns:
1844 * -1 on failure
1845 * 0 otherwise
1846 */
1847 static int vrrp_autoconfig_if_del(struct interface *ifp)
1848 {
1849 if (!vrrp_autoconfig_is_on)
1850 return 0;
1851
1852 struct vrrp_vrouter *vr;
1853 struct listnode *ln;
1854 struct list *vrs;
1855
1856 vrs = vrrp_lookup_by_if_any(ifp);
1857
1858 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr))
1859 if (vr->autoconf
1860 && (!vr->ifp || (!vr->v4->mvl_ifp && !vr->v6->mvl_ifp))) {
1861 DEBUGD(&vrrp_dbg_auto,
1862 VRRP_LOGPFX VRRP_LOGPFX_VRID
1863 "All VRRP interfaces for instance deleted; destroying autoconfigured VRRP router",
1864 vr->vrid);
1865 vrrp_vrouter_destroy(vr);
1866 }
1867
1868 list_delete(&vrs);
1869
1870 return 0;
1871 }
1872
1873 /*
1874 * Callback to notify autoconfig of interface up.
1875 *
1876 * Creates VRRP instance on interface if it does not exist. Otherwise does
1877 * nothing.
1878 *
1879 * ifp
1880 * Interface to operate on
1881 *
1882 * Returns:
1883 * -1 on failure
1884 * 0 otherwise
1885 */
1886 static int vrrp_autoconfig_if_up(struct interface *ifp)
1887 {
1888 if (!vrrp_autoconfig_is_on)
1889 return 0;
1890
1891 struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp);
1892
1893 if (vr && !vr->autoconf)
1894 return 0;
1895
1896 if (!vr) {
1897 vrrp_autoconfig_if_add(ifp);
1898 return 0;
1899 }
1900
1901 return 0;
1902 }
1903
1904 /*
1905 * Callback to notify autoconfig of interface down.
1906 *
1907 * Does nothing. An interface down event is accompanied by address deletion
1908 * events for all the addresses on the interface; if an autoconfigured VRRP
1909 * router exists on this interface, then it will have all its addresses deleted
1910 * and end up in Initialize.
1911 *
1912 * ifp
1913 * Interface to operate on
1914 *
1915 * Returns:
1916 * -1 on failure
1917 * 0 otherwise
1918 */
1919 static int vrrp_autoconfig_if_down(struct interface *ifp)
1920 {
1921 if (!vrrp_autoconfig_is_on)
1922 return 0;
1923
1924 return 0;
1925 }
1926
1927 /*
1928 * Callback to notify autoconfig of a new interface address.
1929 *
1930 * If a VRRP router exists on this interface, its address list is updated to
1931 * match the new address list. If no addresses remain, a Shutdown event is
1932 * issued to the VRRP router.
1933 *
1934 * ifp
1935 * Interface to operate on
1936 *
1937 * Returns:
1938 * -1 on failure
1939 * 0 otherwise
1940 *
1941 */
1942 static int vrrp_autoconfig_if_address_add(struct interface *ifp)
1943 {
1944 if (!vrrp_autoconfig_is_on)
1945 return 0;
1946
1947 struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp);
1948
1949 if (vr && vr->autoconf) {
1950 if (vr->v4->mvl_ifp == ifp)
1951 vrrp_autoconfig_autoaddrupdate(vr->v4);
1952 else if (vr->v6->mvl_ifp == ifp)
1953 vrrp_autoconfig_autoaddrupdate(vr->v6);
1954 }
1955
1956 return 0;
1957 }
1958
1959 /*
1960 * Callback to notify autoconfig of a removed interface address.
1961 *
1962 * If a VRRP router exists on this interface, its address list is updated to
1963 * match the new address list. If no addresses remain, a Shutdown event is
1964 * issued to the VRRP router.
1965 *
1966 * ifp
1967 * Interface to operate on
1968 *
1969 * Returns:
1970 * -1 on failure
1971 * 0 otherwise
1972 *
1973 */
1974 static int vrrp_autoconfig_if_address_del(struct interface *ifp)
1975 {
1976 if (!vrrp_autoconfig_is_on)
1977 return 0;
1978
1979 struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp);
1980
1981 if (vr && vr->autoconf) {
1982 if (vr->v4->mvl_ifp == ifp)
1983 vrrp_autoconfig_autoaddrupdate(vr->v4);
1984 else if (vr->v6->mvl_ifp == ifp)
1985 vrrp_autoconfig_autoaddrupdate(vr->v6);
1986 }
1987
1988 return 0;
1989 }
1990
1991 int vrrp_autoconfig(void)
1992 {
1993 if (!vrrp_autoconfig_is_on)
1994 return 0;
1995
1996 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
1997 struct interface *ifp;
1998
1999 FOR_ALL_INTERFACES (vrf, ifp)
2000 vrrp_autoconfig_if_add(ifp);
2001
2002 return 0;
2003 }
2004
2005 void vrrp_autoconfig_on(int version)
2006 {
2007 vrrp_autoconfig_is_on = true;
2008 vrrp_autoconfig_version = version;
2009
2010 vrrp_autoconfig();
2011 }
2012
2013 void vrrp_autoconfig_off(void)
2014 {
2015 vrrp_autoconfig_is_on = false;
2016
2017 struct list *ll = hash_to_list(vrrp_vrouters_hash);
2018
2019 struct listnode *ln;
2020 struct vrrp_vrouter *vr;
2021
2022 for (ALL_LIST_ELEMENTS_RO(ll, ln, vr))
2023 if (vr->autoconf)
2024 vrrp_vrouter_destroy(vr);
2025
2026 list_delete(&ll);
2027 }
2028
2029 /* Interface tracking ------------------------------------------------------ */
2030
2031 /*
2032 * Bind any pending interfaces.
2033 *
2034 * mvl_ifp
2035 * macvlan interface that some VRRP instances might want to bind to
2036 */
2037 static void vrrp_bind_pending(struct interface *mvl_ifp)
2038 {
2039 struct vrrp_vrouter *vr;
2040
2041 DEBUGD(&vrrp_dbg_zebra,
2042 VRRP_LOGPFX
2043 "Searching for instances that could use interface %s",
2044 mvl_ifp->name);
2045
2046 vr = vrrp_lookup_by_if_mvl(mvl_ifp);
2047
2048 if (vr) {
2049 DEBUGD(&vrrp_dbg_zebra,
2050 VRRP_LOGPFX VRRP_LOGPFX_VRID
2051 "<-- This instance can probably use interface %s",
2052 vr->vrid, mvl_ifp->name);
2053
2054 if (mvl_ifp->hw_addr[4] == 0x01 && !vr->v4->mvl_ifp)
2055 vrrp_attach_interface(vr->v4);
2056 else if (mvl_ifp->hw_addr[4] == 0x02 && !vr->v6->mvl_ifp)
2057 vrrp_attach_interface(vr->v6);
2058 }
2059 }
2060
2061 void vrrp_if_up(struct interface *ifp)
2062 {
2063 struct vrrp_vrouter *vr;
2064 struct listnode *ln;
2065 struct list *vrs;
2066
2067 vrrp_bind_pending(ifp);
2068
2069 vrs = vrrp_lookup_by_if_any(ifp);
2070
2071 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
2072 vrrp_check_start(vr);
2073
2074 if (!if_is_operative(ifp))
2075 continue;
2076
2077 /*
2078 * Handle the situation in which we performed a state
2079 * transition on this VRRP router but needed to wait for the
2080 * macvlan interface to come up to perform some actions
2081 */
2082 if (ifp == vr->v4->mvl_ifp) {
2083 if (vr->v4->advert_pending) {
2084 DEBUGD(&vrrp_dbg_proto,
2085 VRRP_LOGPFX VRRP_LOGPFX_VRID
2086 VRRP_LOGPFX_FAM
2087 "Interface up; sending pending advertisement",
2088 vr->vrid, family2str(vr->v4->family));
2089 vrrp_send_advertisement(vr->v4);
2090 vr->v4->advert_pending = false;
2091 }
2092 if (vr->v4->garp_pending) {
2093 DEBUGD(&vrrp_dbg_proto,
2094 VRRP_LOGPFX VRRP_LOGPFX_VRID
2095 VRRP_LOGPFX_FAM
2096 "Interface up; sending pending gratuitous ARP",
2097 vr->vrid, family2str(vr->v4->family));
2098 vrrp_garp_send_all(vr->v4);
2099 vr->v4->garp_pending = false;
2100 }
2101 }
2102 if (ifp == vr->v6->mvl_ifp) {
2103 if (vr->v6->advert_pending) {
2104 DEBUGD(&vrrp_dbg_proto,
2105 VRRP_LOGPFX VRRP_LOGPFX_VRID
2106 VRRP_LOGPFX_FAM
2107 "Interface up; sending pending advertisement",
2108 vr->vrid, family2str(vr->v6->family));
2109 vrrp_send_advertisement(vr->v6);
2110 vr->v6->advert_pending = false;
2111 }
2112 if (vr->v6->ndisc_pending) {
2113 DEBUGD(&vrrp_dbg_proto,
2114 VRRP_LOGPFX VRRP_LOGPFX_VRID
2115 VRRP_LOGPFX_FAM
2116 "Interface up; sending pending Unsolicited Neighbor Advertisement",
2117 vr->vrid, family2str(vr->v6->family));
2118 vrrp_ndisc_una_send_all(vr->v6);
2119 vr->v6->ndisc_pending = false;
2120 }
2121 }
2122 }
2123
2124 list_delete(&vrs);
2125
2126 vrrp_autoconfig_if_up(ifp);
2127 }
2128
2129 void vrrp_if_down(struct interface *ifp)
2130 {
2131 struct vrrp_vrouter *vr;
2132 struct listnode *ln;
2133 struct list *vrs;
2134
2135 vrrp_bind_pending(ifp);
2136
2137 vrs = vrrp_lookup_by_if_any(ifp);
2138
2139 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
2140 vrrp_check_start(vr);
2141
2142 if (vr->ifp == ifp || vr->v4->mvl_ifp == ifp
2143 || vr->v6->mvl_ifp == ifp) {
2144 DEBUGD(&vrrp_dbg_auto,
2145 VRRP_LOGPFX VRRP_LOGPFX_VRID "Interface %s down",
2146 vr->vrid, ifp->name);
2147 }
2148 }
2149
2150 list_delete(&vrs);
2151
2152 vrrp_autoconfig_if_down(ifp);
2153 }
2154
2155 void vrrp_if_add(struct interface *ifp)
2156 {
2157 vrrp_bind_pending(ifp);
2158
2159 /* thanks, zebra */
2160 if (CHECK_FLAG(ifp->flags, IFF_UP))
2161 vrrp_if_up(ifp);
2162
2163 vrrp_autoconfig_if_add(ifp);
2164 }
2165
2166 void vrrp_if_del(struct interface *ifp)
2167 {
2168 struct listnode *ln;
2169 struct vrrp_vrouter *vr;
2170 struct list *vrs = vrrp_lookup_by_if_any(ifp);
2171
2172 vrrp_if_down(ifp);
2173
2174 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
2175 if ((vr->v4->mvl_ifp == ifp || vr->ifp == ifp)
2176 && vr->v4->fsm.state != VRRP_STATE_INITIALIZE) {
2177 vrrp_event(vr->v4, VRRP_EVENT_SHUTDOWN);
2178 vr->v4->mvl_ifp = NULL;
2179 } else if ((vr->v6->mvl_ifp == ifp || vr->ifp == ifp)
2180 && vr->v6->fsm.state != VRRP_STATE_INITIALIZE) {
2181 vrrp_event(vr->v6, VRRP_EVENT_SHUTDOWN);
2182 vr->v6->mvl_ifp = NULL;
2183 }
2184 }
2185
2186 list_delete(&vrs);
2187
2188 vrrp_autoconfig_if_del(ifp);
2189 }
2190
2191 void vrrp_if_address_add(struct interface *ifp)
2192 {
2193 struct vrrp_vrouter *vr;
2194 struct listnode *ln;
2195 struct list *vrs;
2196
2197 /*
2198 * We have to do a wide search here, because we need to know when a v6
2199 * macvlan device gets a new address. This is because the macvlan link
2200 * local is used as the source address for v6 advertisements, and hence
2201 * "do I have a link local" constitutes an activation condition for v6
2202 * virtual routers.
2203 */
2204 vrs = vrrp_lookup_by_if_any(ifp);
2205
2206 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr))
2207 vrrp_check_start(vr);
2208
2209 list_delete(&vrs);
2210
2211 vrrp_autoconfig_if_address_add(ifp);
2212 }
2213
2214 void vrrp_if_address_del(struct interface *ifp)
2215 {
2216 /*
2217 * Zebra is stupid and sends us address deletion notifications
2218 * when any of the following condition sets are met:
2219 *
2220 * - if_is_operative && address deleted
2221 * - if_is_operative -> !if_is_operative
2222 *
2223 * Note that the second one is nonsense, because Zebra behaves as
2224 * though an interface going down means all the addresses on that
2225 * interface got deleted. Which is a problem for autoconfig because all
2226 * the addresses on an interface going away means the VRRP session goes
2227 * to Initialize. However interfaces go down whenever we transition to
2228 * Backup, so this effectively means that for autoconfigured instances
2229 * we actually end up in Initialize whenever we try to go into Backup.
2230 *
2231 * Also, Zebra does NOT send us notifications when:
2232 * - !if_is_operative && address deleted
2233 *
2234 * Which means if we're in backup and an address is deleted out from
2235 * under us, we won't even know.
2236 *
2237 * The only solution here is to only resynchronize our address list
2238 * when:
2239 *
2240 * - An interfaces comes up
2241 * - An interface address is added
2242 * - An interface address is deleted AND the interface is up
2243 *
2244 * Even though this is only a problem with autoconfig at the moment I'm
2245 * papering over Zebra's braindead semantics here. Every piece of code
2246 * in this function should be protected by a check that the interface
2247 * is up.
2248 */
2249 if (if_is_operative(ifp))
2250 vrrp_autoconfig_if_address_del(ifp);
2251 }
2252
2253 /* Other ------------------------------------------------------------------- */
2254
2255 int vrrp_config_write_interface(struct vty *vty)
2256 {
2257 struct list *vrs = hash_to_list(vrrp_vrouters_hash);
2258 struct listnode *ln, *ipln;
2259 struct vrrp_vrouter *vr;
2260 int writes = 0;
2261
2262 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
2263 vty_frame(vty, "interface %s\n", vr->ifp->name);
2264 ++writes;
2265
2266 vty_out(vty, " vrrp %" PRIu8 "%s\n", vr->vrid,
2267 vr->version == 2 ? " version 2" : "");
2268 ++writes;
2269
2270 if (vr->shutdown != vd.shutdown && ++writes)
2271 vty_out(vty, " %svrrp %" PRIu8 " shutdown\n",
2272 vr->shutdown ? "" : "no ", vr->vrid);
2273
2274 if (vr->preempt_mode != vd.preempt_mode && ++writes)
2275 vty_out(vty, " %svrrp %" PRIu8 " preempt\n",
2276 vr->preempt_mode ? "" : "no ", vr->vrid);
2277
2278 if (vr->accept_mode != vd.accept_mode && ++writes)
2279 vty_out(vty, " %svrrp %" PRIu8 " accept\n",
2280 vr->accept_mode ? "" : "no ", vr->vrid);
2281
2282 if (vr->advertisement_interval != vd.advertisement_interval
2283 && ++writes)
2284 vty_out(vty,
2285 " vrrp %" PRIu8
2286 " advertisement-interval %d\n",
2287 vr->vrid, vr->advertisement_interval * CS2MS);
2288
2289 if (vr->priority != vd.priority && ++writes)
2290 vty_out(vty, " vrrp %" PRIu8 " priority %" PRIu8 "\n",
2291 vr->vrid, vr->priority);
2292
2293 struct ipaddr *ip;
2294
2295 for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ipln, ip)) {
2296 char ipbuf[INET6_ADDRSTRLEN];
2297
2298 ipaddr2str(ip, ipbuf, sizeof(ipbuf));
2299 vty_out(vty, " vrrp %" PRIu8 " ip %s\n", vr->vrid,
2300 ipbuf);
2301 ++writes;
2302 }
2303
2304 for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ipln, ip)) {
2305 char ipbuf[INET6_ADDRSTRLEN];
2306
2307 ipaddr2str(ip, ipbuf, sizeof(ipbuf));
2308 vty_out(vty, " vrrp %" PRIu8 " ipv6 %s\n", vr->vrid,
2309 ipbuf);
2310 ++writes;
2311 }
2312 vty_endframe(vty, "!\n");
2313 }
2314
2315 list_delete(&vrs);
2316
2317 return writes;
2318 }
2319
2320 int vrrp_config_write_global(struct vty *vty)
2321 {
2322 unsigned int writes = 0;
2323
2324 if (vrrp_autoconfig_is_on && ++writes)
2325 vty_out(vty, "vrrp autoconfigure%s\n",
2326 vrrp_autoconfig_version == 2 ? " version 2" : "");
2327
2328 if (vd.priority != VRRP_DEFAULT_PRIORITY && ++writes)
2329 vty_out(vty, "vrrp default priority %" PRIu8 "\n", vd.priority);
2330
2331 if (vd.advertisement_interval != VRRP_DEFAULT_ADVINT && ++writes)
2332 vty_out(vty,
2333 "vrrp default advertisement-interval %" PRIu16 "\n",
2334 vd.advertisement_interval * CS2MS);
2335
2336 if (vd.preempt_mode != VRRP_DEFAULT_PREEMPT && ++writes)
2337 vty_out(vty, "%svrrp default preempt\n",
2338 !vd.preempt_mode ? "no " : "");
2339
2340 if (vd.accept_mode != VRRP_DEFAULT_ACCEPT && ++writes)
2341 vty_out(vty, "%svrrp default accept\n",
2342 !vd.accept_mode ? "no " : "");
2343
2344 if (vd.shutdown != VRRP_DEFAULT_SHUTDOWN && ++writes)
2345 vty_out(vty, "%svrrp default shutdown\n",
2346 !vd.shutdown ? "no " : "");
2347
2348 return writes;
2349 }
2350
2351 static unsigned int vrrp_hash_key(const void *arg)
2352 {
2353 const struct vrrp_vrouter *vr = arg;
2354 char key[IFNAMSIZ + 64];
2355
2356 snprintf(key, sizeof(key), "%s@%" PRIu8, vr->ifp->name, vr->vrid);
2357
2358 return string_hash_make(key);
2359 }
2360
2361 static bool vrrp_hash_cmp(const void *arg1, const void *arg2)
2362 {
2363 const struct vrrp_vrouter *vr1 = arg1;
2364 const struct vrrp_vrouter *vr2 = arg2;
2365
2366 if (vr1->ifp != vr2->ifp)
2367 return 0;
2368 if (vr1->vrid != vr2->vrid)
2369 return 0;
2370
2371 return 1;
2372 }
2373
2374 void vrrp_init(void)
2375 {
2376 /* Set default defaults */
2377 vd.priority = VRRP_DEFAULT_PRIORITY;
2378 vd.advertisement_interval = VRRP_DEFAULT_ADVINT;
2379 vd.preempt_mode = VRRP_DEFAULT_PREEMPT;
2380 vd.accept_mode = VRRP_DEFAULT_ACCEPT;
2381 vd.shutdown = VRRP_DEFAULT_SHUTDOWN;
2382
2383 vrrp_autoconfig_version = 3;
2384 vrrp_vrouters_hash = hash_create(&vrrp_hash_key, vrrp_hash_cmp,
2385 "VRRP virtual router hash");
2386 vrf_init(NULL, NULL, NULL, NULL, NULL);
2387 }
2388
2389 void vrrp_fini(void)
2390 {
2391 /* Destroy all instances */
2392 struct list *vrs = hash_to_list(vrrp_vrouters_hash);
2393
2394 struct listnode *ln;
2395 struct vrrp_vrouter *vr;
2396
2397 for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr))
2398 vrrp_vrouter_destroy(vr);
2399
2400 list_delete(&vrs);
2401
2402 hash_clean(vrrp_vrouters_hash, NULL);
2403 hash_free(vrrp_vrouters_hash);
2404 }