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