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