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