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