1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2002 Michael Shalayeff.
5 * Copyright (c) 2003 Ryan McBride.
6 * Copyright (c) 2011 Gleb Smirnoff <glebius@FreeBSD.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 #include "opt_bpf.h"
33 #include "opt_inet.h"
34 #include "opt_inet6.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/devctl.h>
39 #include <sys/jail.h>
40 #include <sys/kassert.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/module.h>
46 #include <sys/priv.h>
47 #include <sys/proc.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
51 #include <sys/syslog.h>
52 #include <sys/taskqueue.h>
53 #include <sys/counter.h>
54
55 #include <net/ethernet.h>
56 #include <net/if.h>
57 #include <net/if_var.h>
58 #include <net/if_dl.h>
59 #include <net/if_llatbl.h>
60 #include <net/if_private.h>
61 #include <net/if_types.h>
62 #include <net/route.h>
63 #include <net/vnet.h>
64
65 #if defined(INET) || defined(INET6)
66 #include <netinet/in.h>
67 #include <netinet/in_var.h>
68 #include <netinet/ip_carp.h>
69 #include <netinet/ip_carp_nl.h>
70 #include <netinet/ip.h>
71 #include <machine/in_cksum.h>
72 #endif
73 #ifdef INET
74 #include <netinet/ip_var.h>
75 #include <netinet/if_ether.h>
76 #endif
77
78 #ifdef INET6
79 #include <netinet/icmp6.h>
80 #include <netinet/ip6.h>
81 #include <netinet6/in6_var.h>
82 #include <netinet6/ip6_var.h>
83 #include <netinet6/scope6_var.h>
84 #include <netinet6/nd6.h>
85 #endif
86
87 #include <netlink/netlink.h>
88 #include <netlink/netlink_ctl.h>
89 #include <netlink/netlink_generic.h>
90 #include <netlink/netlink_message_parser.h>
91
92 #include <crypto/sha1.h>
93
94 static MALLOC_DEFINE(M_CARP, "CARP", "CARP addresses");
95
96 struct carp_softc {
97 struct ifnet *sc_carpdev; /* Pointer to parent ifnet. */
98 struct ifaddr **sc_ifas; /* Our ifaddrs. */
99 carp_version_t sc_version; /* carp or VRRPv3 */
100 uint8_t sc_addr[ETHER_ADDR_LEN]; /* Our link level address. */
101 struct callout sc_ad_tmo; /* Advertising timeout. */
102 #ifdef INET
103 struct callout sc_md_tmo; /* Master down timeout. */
104 #endif
105 #ifdef INET6
106 struct callout sc_md6_tmo; /* XXX: Master down timeout. */
107 #endif
108 struct mtx sc_mtx;
109
110 int sc_vhid;
111 union {
112 struct { /* sc_version == CARP_VERSION_CARP */
113 int sc_advskew;
114 int sc_advbase;
115 struct in_addr sc_carpaddr;
116 struct in6_addr sc_carpaddr6;
117 uint64_t sc_counter;
118 bool sc_init_counter;
119 #define CARP_HMAC_PAD 64
120 unsigned char sc_key[CARP_KEY_LEN];
121 unsigned char sc_pad[CARP_HMAC_PAD];
122 SHA1_CTX sc_sha1;
123 };
124 struct { /* sc_version == CARP_VERSION_VRRPv3 */
125 uint8_t sc_vrrp_prio;
126 uint16_t sc_vrrp_adv_inter;
127 uint16_t sc_vrrp_master_inter;
128 };
129 };
130 int sc_naddrs;
131 int sc_naddrs6;
132 int sc_ifasiz;
133 enum { INIT = 0, BACKUP, MASTER } sc_state;
134 int sc_suppress;
135 int sc_sendad_errors;
136 #define CARP_SENDAD_MAX_ERRORS 3
137 int sc_sendad_success;
138 #define CARP_SENDAD_MIN_SUCCESS 3
139
140 TAILQ_ENTRY(carp_softc) sc_list; /* On the carp_if list. */
141 LIST_ENTRY(carp_softc) sc_next; /* On the global list. */
142 };
143
144 struct carp_if {
145 #ifdef INET
146 int cif_naddrs;
147 #endif
148 #ifdef INET6
149 int cif_naddrs6;
150 #endif
151 TAILQ_HEAD(, carp_softc) cif_vrs;
152 #ifdef INET
153 struct ip_moptions cif_imo;
154 #endif
155 #ifdef INET6
156 struct ip6_moptions cif_im6o;
157 #endif
158 struct ifnet *cif_ifp;
159 struct mtx cif_mtx;
160 uint32_t cif_flags;
161 #define CIF_PROMISC 0x00000001
162 };
163
164 /* Kernel equivalent of struct carpreq, but with more fields for new features.
165 * */
166 struct carpkreq {
167 int carpr_count;
168 int carpr_vhid;
169 int carpr_state;
170 int carpr_advskew;
171 int carpr_advbase;
172 unsigned char carpr_key[CARP_KEY_LEN];
173 /* Everything above this is identical to carpreq */
174 struct in_addr carpr_addr;
175 struct in6_addr carpr_addr6;
176 carp_version_t carpr_version;
177 uint8_t carpr_vrrp_priority;
178 uint16_t carpr_vrrp_adv_inter;
179 };
180
181 /*
182 * Brief design of carp(4).
183 *
184 * Any carp-capable ifnet may have a list of carp softcs hanging off
185 * its ifp->if_carp pointer. Each softc represents one unique virtual
186 * host id, or vhid. The softc has a back pointer to the ifnet. All
187 * softcs are joined in a global list, which has quite limited use.
188 *
189 * Any interface address that takes part in CARP negotiation has a
190 * pointer to the softc of its vhid, ifa->ifa_carp. That could be either
191 * AF_INET or AF_INET6 address.
192 *
193 * Although, one can get the softc's backpointer to ifnet and traverse
194 * through its ifp->if_addrhead queue to find all interface addresses
195 * involved in CARP, we keep a growable array of ifaddr pointers. This
196 * allows us to avoid grabbing the IF_ADDR_LOCK() in many traversals that
197 * do calls into the network stack, thus avoiding LORs.
198 *
199 * Locking:
200 *
201 * Each softc has a lock sc_mtx. It is used to synchronise carp_input_c(),
202 * callout-driven events and ioctl()s.
203 *
204 * To traverse the list of softcs on an ifnet we use CIF_LOCK() or carp_sx.
205 * To traverse the global list we use the mutex carp_mtx.
206 *
207 * Known issues with locking:
208 *
209 * - Sending ad, we put the pointer to the softc in an mtag, and no reference
210 * counting is done on the softc.
211 * - On module unload we may race (?) with packet processing thread
212 * dereferencing our function pointers.
213 */
214
215 /* Accept incoming CARP packets. */
216 VNET_DEFINE_STATIC(int, carp_allow) = 1;
217 #define V_carp_allow VNET(carp_allow)
218
219 /* Set DSCP in outgoing CARP packets. */
220 VNET_DEFINE_STATIC(int, carp_dscp) = 56;
221 #define V_carp_dscp VNET(carp_dscp)
222
223 /* Preempt slower nodes. */
224 VNET_DEFINE_STATIC(int, carp_preempt) = 0;
225 #define V_carp_preempt VNET(carp_preempt)
226
227 /* Log level. */
228 VNET_DEFINE_STATIC(int, carp_log) = 1;
229 #define V_carp_log VNET(carp_log)
230
231 /* Global advskew demotion. */
232 VNET_DEFINE_STATIC(int, carp_demotion) = 0;
233 #define V_carp_demotion VNET(carp_demotion)
234
235 /* Send error demotion factor. */
236 VNET_DEFINE_STATIC(int, carp_senderr_adj) = CARP_MAXSKEW;
237 #define V_carp_senderr_adj VNET(carp_senderr_adj)
238
239 /* Iface down demotion factor. */
240 VNET_DEFINE_STATIC(int, carp_ifdown_adj) = CARP_MAXSKEW;
241 #define V_carp_ifdown_adj VNET(carp_ifdown_adj)
242
243 static int carp_allow_sysctl(SYSCTL_HANDLER_ARGS);
244 static int carp_dscp_sysctl(SYSCTL_HANDLER_ARGS);
245 static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS);
246
247 SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
248 "CARP");
249 SYSCTL_PROC(_net_inet_carp, OID_AUTO, allow,
250 CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NOFETCH | CTLFLAG_MPSAFE,
251 &VNET_NAME(carp_allow), 0, carp_allow_sysctl, "I",
252 "Accept incoming CARP packets");
253 SYSCTL_PROC(_net_inet_carp, OID_AUTO, dscp,
254 CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
255 0, 0, carp_dscp_sysctl, "I",
256 "DSCP value for carp packets");
257 SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET | CTLFLAG_RW,
258 &VNET_NAME(carp_preempt), 0, "High-priority backup preemption mode");
259 SYSCTL_INT(_net_inet_carp, OID_AUTO, log, CTLFLAG_VNET | CTLFLAG_RW,
260 &VNET_NAME(carp_log), 0, "CARP log level");
261 SYSCTL_PROC(_net_inet_carp, OID_AUTO, demotion,
262 CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
263 0, 0, carp_demote_adj_sysctl, "I",
264 "Adjust demotion factor (skew of advskew)");
265 SYSCTL_INT(_net_inet_carp, OID_AUTO, senderr_demotion_factor,
266 CTLFLAG_VNET | CTLFLAG_RW,
267 &VNET_NAME(carp_senderr_adj), 0, "Send error demotion factor adjustment");
268 SYSCTL_INT(_net_inet_carp, OID_AUTO, ifdown_demotion_factor,
269 CTLFLAG_VNET | CTLFLAG_RW,
270 &VNET_NAME(carp_ifdown_adj), 0,
271 "Interface down demotion factor adjustment");
272
273 VNET_PCPUSTAT_DEFINE(struct carpstats, carpstats);
274 VNET_PCPUSTAT_SYSINIT(carpstats);
275 VNET_PCPUSTAT_SYSUNINIT(carpstats);
276
277 #define CARPSTATS_ADD(name, val) \
278 counter_u64_add(VNET(carpstats)[offsetof(struct carpstats, name) / \
279 sizeof(uint64_t)], (val))
280 #define CARPSTATS_INC(name) CARPSTATS_ADD(name, 1)
281
282 SYSCTL_VNET_PCPUSTAT(_net_inet_carp, OID_AUTO, stats, struct carpstats,
283 carpstats, "CARP statistics (struct carpstats, netinet/ip_carp.h)");
284
285 #define CARP_LOCK_INIT(sc) mtx_init(&(sc)->sc_mtx, "carp_softc", \
286 NULL, MTX_DEF)
287 #define CARP_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
288 #define CARP_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
289 #define CARP_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
290 #define CARP_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
291 #define CIF_LOCK_INIT(cif) mtx_init(&(cif)->cif_mtx, "carp_if", \
292 NULL, MTX_DEF)
293 #define CIF_LOCK_DESTROY(cif) mtx_destroy(&(cif)->cif_mtx)
294 #define CIF_LOCK_ASSERT(cif) mtx_assert(&(cif)->cif_mtx, MA_OWNED)
295 #define CIF_LOCK(cif) mtx_lock(&(cif)->cif_mtx)
296 #define CIF_UNLOCK(cif) mtx_unlock(&(cif)->cif_mtx)
297 #define CIF_FREE(cif) do { \
298 CIF_LOCK(cif); \
299 if (TAILQ_EMPTY(&(cif)->cif_vrs)) \
300 carp_free_if(cif); \
301 else \
302 CIF_UNLOCK(cif); \
303 } while (0)
304
305 #define CARP_LOG(...) do { \
306 if (V_carp_log > 0) \
307 log(LOG_INFO, "carp: " __VA_ARGS__); \
308 } while (0)
309
310 #define CARP_DEBUG(...) do { \
311 if (V_carp_log > 1) \
312 log(LOG_DEBUG, __VA_ARGS__); \
313 } while (0)
314
315 #define IFNET_FOREACH_IFA(ifp, ifa) \
316 CK_STAILQ_FOREACH((ifa), &(ifp)->if_addrhead, ifa_link) \
317 if ((ifa)->ifa_carp != NULL)
318
319 #define CARP_FOREACH_IFA(sc, ifa) \
320 CARP_LOCK_ASSERT(sc); \
321 for (int _i = 0; \
322 _i < (sc)->sc_naddrs + (sc)->sc_naddrs6 && \
323 ((ifa) = sc->sc_ifas[_i]) != NULL; \
324 ++_i)
325
326 #define IFNET_FOREACH_CARP(ifp, sc) \
327 KASSERT(mtx_owned(&ifp->if_carp->cif_mtx) || \
328 sx_xlocked(&carp_sx), ("cif_vrs not locked")); \
329 TAILQ_FOREACH((sc), &(ifp)->if_carp->cif_vrs, sc_list)
330
331 #define DEMOTE_ADVSKEW(sc) \
332 (((sc)->sc_advskew + V_carp_demotion > CARP_MAXSKEW) ? \
333 CARP_MAXSKEW : \
334 (((sc)->sc_advskew + V_carp_demotion < 0) ? \
335 0 : ((sc)->sc_advskew + V_carp_demotion)))
336
337 static void carp_input_c(struct mbuf *, struct carp_header *, sa_family_t, int);
338 static void vrrp_input_c(struct mbuf *, int, sa_family_t, int, int, uint16_t);
339 static struct carp_softc
340 *carp_alloc(struct ifnet *, carp_version_t, int);
341 static void carp_destroy(struct carp_softc *);
342 static struct carp_if
343 *carp_alloc_if(struct ifnet *);
344 static void carp_free_if(struct carp_if *);
345 static void carp_set_state(struct carp_softc *, int, const char* reason);
346 static void carp_sc_state(struct carp_softc *);
347 static void carp_setrun(struct carp_softc *, sa_family_t);
348 static void carp_master_down(void *);
349 static void carp_master_down_locked(struct carp_softc *,
350 const char* reason);
351 static void carp_send_ad_locked(struct carp_softc *);
352 static void vrrp_send_ad_locked(struct carp_softc *);
353 static void carp_addroute(struct carp_softc *);
354 static void carp_ifa_addroute(struct ifaddr *);
355 static void carp_delroute(struct carp_softc *);
356 static void carp_ifa_delroute(struct ifaddr *);
357 static void carp_send_ad_all(void *, int);
358 static void carp_demote_adj(int, char *);
359
360 static LIST_HEAD(, carp_softc) carp_list;
361 static struct mtx carp_mtx;
362 static struct sx carp_sx;
363 static struct task carp_sendall_task =
364 TASK_INITIALIZER(0, carp_send_ad_all, NULL);
365
366 static int
carp_is_supported_if(if_t ifp)367 carp_is_supported_if(if_t ifp)
368 {
369 if (ifp == NULL)
370 return (ENXIO);
371
372 switch (ifp->if_type) {
373 case IFT_ETHER:
374 case IFT_L2VLAN:
375 case IFT_BRIDGE:
376 break;
377 default:
378 return (EOPNOTSUPP);
379 }
380
381 return (0);
382 }
383
384 static void
carp_hmac_prepare(struct carp_softc * sc)385 carp_hmac_prepare(struct carp_softc *sc)
386 {
387 uint8_t version = CARP_VERSION_CARP, type = CARP_ADVERTISEMENT;
388 uint8_t vhid = sc->sc_vhid & 0xff;
389 struct ifaddr *ifa;
390 int i, found;
391 #ifdef INET
392 struct in_addr last, cur, in;
393 #endif
394 #ifdef INET6
395 struct in6_addr last6, cur6, in6;
396 #endif
397
398 CARP_LOCK_ASSERT(sc);
399 MPASS(sc->sc_version == CARP_VERSION_CARP);
400
401 /* Compute ipad from key. */
402 bzero(sc->sc_pad, sizeof(sc->sc_pad));
403 bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key));
404 for (i = 0; i < sizeof(sc->sc_pad); i++)
405 sc->sc_pad[i] ^= 0x36;
406
407 /* Precompute first part of inner hash. */
408 SHA1Init(&sc->sc_sha1);
409 SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad));
410 SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version));
411 SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type));
412 SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid));
413 #ifdef INET
414 cur.s_addr = 0;
415 do {
416 found = 0;
417 last = cur;
418 cur.s_addr = 0xffffffff;
419 CARP_FOREACH_IFA(sc, ifa) {
420 in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
421 if (ifa->ifa_addr->sa_family == AF_INET &&
422 ntohl(in.s_addr) > ntohl(last.s_addr) &&
423 ntohl(in.s_addr) < ntohl(cur.s_addr)) {
424 cur.s_addr = in.s_addr;
425 found++;
426 }
427 }
428 if (found)
429 SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur));
430 } while (found);
431 #endif /* INET */
432 #ifdef INET6
433 memset(&cur6, 0, sizeof(cur6));
434 do {
435 found = 0;
436 last6 = cur6;
437 memset(&cur6, 0xff, sizeof(cur6));
438 CARP_FOREACH_IFA(sc, ifa) {
439 in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
440 if (IN6_IS_SCOPE_EMBED(&in6))
441 in6.s6_addr16[1] = 0;
442 if (ifa->ifa_addr->sa_family == AF_INET6 &&
443 memcmp(&in6, &last6, sizeof(in6)) > 0 &&
444 memcmp(&in6, &cur6, sizeof(in6)) < 0) {
445 cur6 = in6;
446 found++;
447 }
448 }
449 if (found)
450 SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6));
451 } while (found);
452 #endif /* INET6 */
453
454 /* convert ipad to opad */
455 for (i = 0; i < sizeof(sc->sc_pad); i++)
456 sc->sc_pad[i] ^= 0x36 ^ 0x5c;
457 }
458
459 static void
carp_hmac_generate(struct carp_softc * sc,uint32_t counter[2],unsigned char md[20])460 carp_hmac_generate(struct carp_softc *sc, uint32_t counter[2],
461 unsigned char md[20])
462 {
463 SHA1_CTX sha1ctx;
464
465 CARP_LOCK_ASSERT(sc);
466
467 /* fetch first half of inner hash */
468 bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx));
469
470 SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter));
471 SHA1Final(md, &sha1ctx);
472
473 /* outer hash */
474 SHA1Init(&sha1ctx);
475 SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad));
476 SHA1Update(&sha1ctx, md, 20);
477 SHA1Final(md, &sha1ctx);
478 }
479
480 static int
carp_hmac_verify(struct carp_softc * sc,uint32_t counter[2],unsigned char md[20])481 carp_hmac_verify(struct carp_softc *sc, uint32_t counter[2],
482 unsigned char md[20])
483 {
484 unsigned char md2[20];
485
486 CARP_LOCK_ASSERT(sc);
487
488 carp_hmac_generate(sc, counter, md2);
489
490 return (bcmp(md, md2, sizeof(md2)));
491 }
492
493 static int
vrrp_checksum_verify(struct mbuf * m,int off,int len,uint16_t phdrcksum)494 vrrp_checksum_verify(struct mbuf *m, int off, int len, uint16_t phdrcksum)
495 {
496 uint16_t cksum;
497
498 /*
499 * Note that VRRPv3 checksums are different from CARP checksums.
500 * Carp just calculates the checksum over the packet.
501 * VRRPv3 includes the pseudo-header checksum as well.
502 */
503 cksum = in_cksum_skip(m, off + len, off);
504 cksum -= phdrcksum;
505
506 return (cksum);
507 }
508
509 /*
510 * process input packet.
511 * we have rearranged checks order compared to the rfc,
512 * but it seems more efficient this way or not possible otherwise.
513 */
514 #ifdef INET
515 static int
carp_input(struct mbuf ** mp,int * offp,int proto)516 carp_input(struct mbuf **mp, int *offp, int proto)
517 {
518 struct mbuf *m = *mp;
519 struct ip *ip = mtod(m, struct ip *);
520 struct vrrpv3_header *vh;
521 int iplen;
522 int minlen;
523 int totlen;
524
525 iplen = *offp;
526 *mp = NULL;
527
528 CARPSTATS_INC(carps_ipackets);
529
530 if (!V_carp_allow) {
531 m_freem(m);
532 return (IPPROTO_DONE);
533 }
534
535 iplen = ip->ip_hl << 2;
536 totlen = ntohs(ip->ip_len);
537
538 /* Ensure we have enough header to figure out the version. */
539 if (m->m_pkthdr.len < iplen + sizeof(*vh)) {
540 CARPSTATS_INC(carps_badlen);
541 CARP_DEBUG("%s: received len %zd < sizeof(struct vrrpv3_header) "
542 "on %s\n", __func__, m->m_len - sizeof(struct ip),
543 if_name(m->m_pkthdr.rcvif));
544 m_freem(m);
545 return (IPPROTO_DONE);
546 }
547
548 if (iplen + sizeof(*vh) < m->m_len) {
549 if ((m = m_pullup(m, iplen + sizeof(*vh))) == NULL) {
550 CARPSTATS_INC(carps_hdrops);
551 CARP_DEBUG("%s():%d: pullup failed\n", __func__, __LINE__);
552 return (IPPROTO_DONE);
553 }
554 ip = mtod(m, struct ip *);
555 }
556 vh = (struct vrrpv3_header *)((char *)ip + iplen);
557
558 switch (vh->vrrp_version) {
559 case CARP_VERSION_CARP:
560 minlen = sizeof(struct carp_header);
561 break;
562 case CARP_VERSION_VRRPv3:
563 minlen = sizeof(struct vrrpv3_header);
564 break;
565 default:
566 CARPSTATS_INC(carps_badver);
567 CARP_DEBUG("%s: unsupported version %d on %s\n", __func__,
568 vh->vrrp_version, if_name(m->m_pkthdr.rcvif));
569 m_freem(m);
570 return (IPPROTO_DONE);
571 }
572
573 /* And now check the length again but with the real minimal length. */
574 if (m->m_pkthdr.len < iplen + minlen) {
575 CARPSTATS_INC(carps_badlen);
576 CARP_DEBUG("%s: received len %zd < %d "
577 "on %s\n", __func__, m->m_len - sizeof(struct ip),
578 iplen + minlen,
579 if_name(m->m_pkthdr.rcvif));
580 m_freem(m);
581 return (IPPROTO_DONE);
582 }
583
584 if (iplen + minlen < m->m_len) {
585 if ((m = m_pullup(m, iplen + minlen)) == NULL) {
586 CARPSTATS_INC(carps_hdrops);
587 CARP_DEBUG("%s():%d: pullup failed\n", __func__, __LINE__);
588 return (IPPROTO_DONE);
589 }
590 ip = mtod(m, struct ip *);
591 vh = (struct vrrpv3_header *)((char *)ip + iplen);
592 }
593
594 switch (vh->vrrp_version) {
595 case CARP_VERSION_CARP: {
596 struct carp_header *ch;
597
598 /* verify the CARP checksum */
599 m->m_data += iplen;
600 if (in_cksum(m, totlen - iplen)) {
601 CARPSTATS_INC(carps_badsum);
602 CARP_DEBUG("%s: checksum failed on %s\n", __func__,
603 if_name(m->m_pkthdr.rcvif));
604 m_freem(m);
605 break;
606 }
607 m->m_data -= iplen;
608 ch = (struct carp_header *)((char *)ip + iplen);
609 carp_input_c(m, ch, AF_INET, ip->ip_ttl);
610 break;
611 }
612 case CARP_VERSION_VRRPv3: {
613 uint16_t phdrcksum;
614
615 phdrcksum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
616 htonl((u_short)(totlen - iplen) + ip->ip_p));
617 vrrp_input_c(m, iplen, AF_INET, ip->ip_ttl, totlen - iplen,
618 phdrcksum);
619 break;
620 }
621 default:
622 KASSERT(false, ("Unsupported version %d", vh->vrrp_version));
623 }
624
625 return (IPPROTO_DONE);
626 }
627 #endif
628
629 #ifdef INET6
630 static int
carp6_input(struct mbuf ** mp,int * offp,int proto)631 carp6_input(struct mbuf **mp, int *offp, int proto)
632 {
633 struct mbuf *m = *mp;
634 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
635 struct vrrpv3_header *vh;
636 u_int len, minlen;
637
638 CARPSTATS_INC(carps_ipackets6);
639
640 if (!V_carp_allow) {
641 m_freem(m);
642 return (IPPROTO_DONE);
643 }
644
645 /* check if received on a valid carp interface */
646 if (m->m_pkthdr.rcvif->if_carp == NULL) {
647 CARPSTATS_INC(carps_badif);
648 CARP_DEBUG("%s: packet received on non-carp interface: %s\n",
649 __func__, if_name(m->m_pkthdr.rcvif));
650 m_freem(m);
651 return (IPPROTO_DONE);
652 }
653
654 if (m->m_len < *offp + sizeof(*vh)) {
655 len = m->m_len;
656 m = m_pullup(m, *offp + sizeof(*vh));
657 if (m == NULL) {
658 CARPSTATS_INC(carps_badlen);
659 CARP_DEBUG("%s: packet size %u too small\n", __func__, len);
660 return (IPPROTO_DONE);
661 }
662 ip6 = mtod(m, struct ip6_hdr *);
663 }
664 vh = (struct vrrpv3_header *)(mtod(m, char *) + *offp);
665
666 switch (vh->vrrp_version) {
667 case CARP_VERSION_CARP:
668 minlen = sizeof(struct carp_header);
669 break;
670 case CARP_VERSION_VRRPv3:
671 minlen = sizeof(struct vrrpv3_header);
672 break;
673 default:
674 CARPSTATS_INC(carps_badver);
675 CARP_DEBUG("%s: unsupported version %d on %s\n", __func__,
676 vh->vrrp_version, if_name(m->m_pkthdr.rcvif));
677 m_freem(m);
678 return (IPPROTO_DONE);
679 }
680
681 /* And now check the length again but with the real minimal length. */
682 if (m->m_pkthdr.len < sizeof(*ip6) + minlen) {
683 CARPSTATS_INC(carps_badlen);
684 CARP_DEBUG("%s: received len %zd < %zd "
685 "on %s\n", __func__, m->m_len - sizeof(struct ip),
686 sizeof(*ip6) + minlen,
687 if_name(m->m_pkthdr.rcvif));
688 m_freem(m);
689 return (IPPROTO_DONE);
690 }
691
692 if (sizeof (*ip6) + minlen < m->m_len) {
693 if ((m = m_pullup(m, sizeof(*ip6) + minlen)) == NULL) {
694 CARPSTATS_INC(carps_hdrops);
695 CARP_DEBUG("%s():%d: pullup failed\n", __func__, __LINE__);
696 return (IPPROTO_DONE);
697 }
698 ip6 = mtod(m, struct ip6_hdr *);
699 vh = (struct vrrpv3_header *)mtodo(m, sizeof(*ip6));
700 }
701
702 switch (vh->vrrp_version) {
703 case CARP_VERSION_CARP: {
704 struct carp_header *ch;
705
706 /* verify the CARP checksum */
707 m->m_data += *offp;
708 if (in_cksum(m, sizeof(struct carp_header))) {
709 CARPSTATS_INC(carps_badsum);
710 CARP_DEBUG("%s: checksum failed, on %s\n", __func__,
711 if_name(m->m_pkthdr.rcvif));
712 m_freem(m);
713 break;
714 }
715 m->m_data -= *offp;
716 ch = (struct carp_header *)((char *)ip6 + sizeof(*ip6));
717 carp_input_c(m, ch, AF_INET6, ip6->ip6_hlim);
718 break;
719 }
720 case CARP_VERSION_VRRPv3: {
721 uint16_t phdrcksum;
722
723 phdrcksum = in6_cksum_pseudo(ip6, ntohs(ip6->ip6_plen),
724 ip6->ip6_nxt, 0);
725 vrrp_input_c(m, sizeof(*ip6), AF_INET6, ip6->ip6_hlim,
726 ntohs(ip6->ip6_plen), phdrcksum);
727 break;
728 }
729 default:
730 KASSERT(false, ("Unsupported version %d", vh->vrrp_version));
731 }
732 return (IPPROTO_DONE);
733 }
734 #endif /* INET6 */
735
736 /*
737 * This routine should not be necessary at all, but some switches
738 * (VMWare ESX vswitches) can echo our own packets back at us,
739 * and we must ignore them or they will cause us to drop out of
740 * MASTER mode.
741 *
742 * We cannot catch all cases of network loops. Instead, what we
743 * do here is catch any packet that arrives with a carp header
744 * with a VHID of 0, that comes from an address that is our own.
745 * These packets are by definition "from us" (even if they are from
746 * a misconfigured host that is pretending to be us).
747 *
748 * The VHID test is outside this mini-function.
749 */
750 static int
carp_source_is_self(const struct mbuf * m,struct ifaddr * ifa,sa_family_t af)751 carp_source_is_self(const struct mbuf *m, struct ifaddr *ifa, sa_family_t af)
752 {
753 #ifdef INET
754 struct ip *ip4;
755 struct in_addr in4;
756 #endif
757 #ifdef INET6
758 struct ip6_hdr *ip6;
759 struct in6_addr in6;
760 #endif
761
762 switch (af) {
763 #ifdef INET
764 case AF_INET:
765 ip4 = mtod(m, struct ip *);
766 in4 = ifatoia(ifa)->ia_addr.sin_addr;
767 return (in4.s_addr == ip4->ip_src.s_addr);
768 #endif
769 #ifdef INET6
770 case AF_INET6:
771 ip6 = mtod(m, struct ip6_hdr *);
772 in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
773 return (memcmp(&in6, &ip6->ip6_src, sizeof(in6)) == 0);
774 #endif
775 default:
776 break;
777 }
778 return (0);
779 }
780
781 static struct ifaddr *
carp_find_ifa(const struct mbuf * m,sa_family_t af,uint8_t vhid)782 carp_find_ifa(const struct mbuf *m, sa_family_t af, uint8_t vhid)
783 {
784 struct ifnet *ifp = m->m_pkthdr.rcvif;
785 struct ifaddr *ifa, *match;
786 int error;
787
788 NET_EPOCH_ASSERT();
789
790 /*
791 * Verify that the VHID is valid on the receiving interface.
792 *
793 * There should be just one match. If there are none
794 * the VHID is not valid and we drop the packet. If
795 * there are multiple VHID matches, take just the first
796 * one, for compatibility with previous code. While we're
797 * scanning, check for obvious loops in the network topology
798 * (these should never happen, and as noted above, we may
799 * miss real loops; this is just a double-check).
800 */
801 error = 0;
802 match = NULL;
803 IFNET_FOREACH_IFA(ifp, ifa) {
804 if (match == NULL && ifa->ifa_carp != NULL &&
805 ifa->ifa_addr->sa_family == af &&
806 ifa->ifa_carp->sc_vhid == vhid)
807 match = ifa;
808 if (vhid == 0 && carp_source_is_self(m, ifa, af))
809 error = ELOOP;
810 }
811 ifa = error ? NULL : match;
812 if (ifa != NULL)
813 ifa_ref(ifa);
814
815 if (ifa == NULL) {
816 if (error == ELOOP) {
817 CARP_DEBUG("dropping looped packet on interface %s\n",
818 if_name(ifp));
819 CARPSTATS_INC(carps_badif); /* ??? */
820 } else {
821 CARPSTATS_INC(carps_badvhid);
822 }
823 }
824
825 return (ifa);
826 }
827
828 static void
carp_input_c(struct mbuf * m,struct carp_header * ch,sa_family_t af,int ttl)829 carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af, int ttl)
830 {
831 struct ifnet *ifp = m->m_pkthdr.rcvif;
832 struct ifaddr *ifa;
833 struct carp_softc *sc;
834 uint64_t tmp_counter;
835 struct timeval sc_tv, ch_tv;
836 bool multicast = false;
837
838 NET_EPOCH_ASSERT();
839 MPASS(ch->carp_version == CARP_VERSION_CARP);
840
841 ifa = carp_find_ifa(m, af, ch->carp_vhid);
842 if (ifa == NULL) {
843 m_freem(m);
844 return;
845 }
846
847 sc = ifa->ifa_carp;
848 CARP_LOCK(sc);
849
850 /* verify the CARP version. */
851 if (sc->sc_version != CARP_VERSION_CARP) {
852 CARP_UNLOCK(sc);
853
854 CARPSTATS_INC(carps_badver);
855 CARP_DEBUG("%s: invalid version %d\n", if_name(ifp),
856 ch->carp_version);
857 ifa_free(ifa);
858 m_freem(m);
859 return;
860 }
861
862 if (ifa->ifa_addr->sa_family == AF_INET) {
863 multicast = IN_MULTICAST(sc->sc_carpaddr.s_addr);
864 } else {
865 multicast = IN6_IS_ADDR_MULTICAST(&sc->sc_carpaddr6);
866 }
867 ifa_free(ifa);
868
869 /* verify that the IP TTL is 255, but only if we're not in unicast mode. */
870 if (multicast && ttl != CARP_DFLTTL) {
871 CARPSTATS_INC(carps_badttl);
872 CARP_DEBUG("%s: received ttl %d != 255 on %s\n", __func__,
873 ttl, if_name(m->m_pkthdr.rcvif));
874 goto out;
875 }
876
877 if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) {
878 CARPSTATS_INC(carps_badauth);
879 CARP_DEBUG("%s: incorrect hash for VHID %u@%s\n", __func__,
880 sc->sc_vhid, if_name(ifp));
881 goto out;
882 }
883
884 tmp_counter = ntohl(ch->carp_counter[0]);
885 tmp_counter = tmp_counter<<32;
886 tmp_counter += ntohl(ch->carp_counter[1]);
887
888 /* XXX Replay protection goes here */
889
890 sc->sc_init_counter = false;
891 sc->sc_counter = tmp_counter;
892
893 sc_tv.tv_sec = sc->sc_advbase;
894 sc_tv.tv_usec = DEMOTE_ADVSKEW(sc) * 1000000 / 256;
895 ch_tv.tv_sec = ch->carp_advbase;
896 ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256;
897
898 switch (sc->sc_state) {
899 case INIT:
900 break;
901 case MASTER:
902 /*
903 * If we receive an advertisement from a master who's going to
904 * be more frequent than us, go into BACKUP state.
905 */
906 if (timevalcmp(&sc_tv, &ch_tv, >) ||
907 timevalcmp(&sc_tv, &ch_tv, ==)) {
908 callout_stop(&sc->sc_ad_tmo);
909 carp_set_state(sc, BACKUP,
910 "more frequent advertisement received");
911 carp_setrun(sc, 0);
912 carp_delroute(sc);
913 }
914 break;
915 case BACKUP:
916 /*
917 * If we're pre-empting masters who advertise slower than us,
918 * and this one claims to be slower, treat him as down.
919 */
920 if (V_carp_preempt && timevalcmp(&sc_tv, &ch_tv, <)) {
921 carp_master_down_locked(sc,
922 "preempting a slower master");
923 break;
924 }
925
926 /*
927 * If the master is going to advertise at such a low frequency
928 * that he's guaranteed to time out, we'd might as well just
929 * treat him as timed out now.
930 */
931 sc_tv.tv_sec = sc->sc_advbase * 3;
932 if (timevalcmp(&sc_tv, &ch_tv, <)) {
933 carp_master_down_locked(sc, "master will time out");
934 break;
935 }
936
937 /*
938 * Otherwise, we reset the counter and wait for the next
939 * advertisement.
940 */
941 carp_setrun(sc, af);
942 break;
943 }
944
945 out:
946 CARP_UNLOCK(sc);
947 m_freem(m);
948 }
949
950 static void
vrrp_input_c(struct mbuf * m,int off,sa_family_t af,int ttl,int len,uint16_t phdrcksum)951 vrrp_input_c(struct mbuf *m, int off, sa_family_t af, int ttl,
952 int len, uint16_t phdrcksum)
953 {
954 struct vrrpv3_header *vh = mtodo(m, off);
955 struct ifnet *ifp = m->m_pkthdr.rcvif;
956 struct ifaddr *ifa;
957 struct carp_softc *sc;
958
959 NET_EPOCH_ASSERT();
960 MPASS(vh->vrrp_version == CARP_VERSION_VRRPv3);
961
962 ifa = carp_find_ifa(m, af, vh->vrrp_vrtid);
963 if (ifa == NULL) {
964 m_freem(m);
965 return;
966 }
967
968 sc = ifa->ifa_carp;
969 CARP_LOCK(sc);
970
971 ifa_free(ifa);
972
973 /* verify the CARP version. */
974 if (sc->sc_version != CARP_VERSION_VRRPv3) {
975 CARP_UNLOCK(sc);
976
977 CARPSTATS_INC(carps_badver);
978 CARP_DEBUG("%s: invalid version %d\n", if_name(ifp),
979 vh->vrrp_version);
980 m_freem(m);
981 return;
982 }
983
984 /* verify that the IP TTL is 255. */
985 if (ttl != CARP_DFLTTL) {
986 CARPSTATS_INC(carps_badttl);
987 CARP_DEBUG("%s: received ttl %d != 255 on %s\n", __func__,
988 ttl, if_name(m->m_pkthdr.rcvif));
989 goto out;
990 }
991
992 if (vrrp_checksum_verify(m, off, len, phdrcksum)) {
993 CARPSTATS_INC(carps_badsum);
994 CARP_DEBUG("%s: incorrect checksum for VRID %u@%s\n", __func__,
995 sc->sc_vhid, if_name(ifp));
996 goto out;
997 }
998
999 /* RFC9568, 7.1 Receiving VRRP packets. */
1000 if (sc->sc_vrrp_prio == 255) {
1001 CARP_DEBUG("%s: our priority is 255. Ignore peer announcement.\n",
1002 __func__);
1003 goto out;
1004 }
1005
1006 /* XXX TODO Check IP address payload. */
1007
1008 sc->sc_vrrp_master_inter = ntohs(vh->vrrp_max_adver_int);
1009
1010 switch (sc->sc_state) {
1011 case INIT:
1012 break;
1013 case MASTER:
1014 /*
1015 * If we receive an advertisement from a master who's going to
1016 * be more frequent than us, go into BACKUP state.
1017 * Same if the peer has a higher priority than us.
1018 */
1019 if (ntohs(vh->vrrp_max_adver_int) < sc->sc_vrrp_adv_inter ||
1020 vh->vrrp_priority > sc->sc_vrrp_prio) {
1021 callout_stop(&sc->sc_ad_tmo);
1022 carp_set_state(sc, BACKUP,
1023 "more frequent advertisement received");
1024 carp_setrun(sc, 0);
1025 carp_delroute(sc);
1026 }
1027 break;
1028 case BACKUP:
1029 /*
1030 * If we're pre-empting masters who advertise slower than us,
1031 * and this one claims to be slower, treat him as down.
1032 */
1033 if (V_carp_preempt && (ntohs(vh->vrrp_max_adver_int) > sc->sc_vrrp_adv_inter
1034 || vh->vrrp_priority < sc->sc_vrrp_prio)) {
1035 carp_master_down_locked(sc,
1036 "preempting a slower master");
1037 break;
1038 }
1039
1040 /*
1041 * Otherwise, we reset the counter and wait for the next
1042 * advertisement.
1043 */
1044 carp_setrun(sc, af);
1045 break;
1046 }
1047
1048 out:
1049 CARP_UNLOCK(sc);
1050 m_freem(m);
1051 }
1052
1053 static int
carp_tag(struct carp_softc * sc,struct mbuf * m)1054 carp_tag(struct carp_softc *sc, struct mbuf *m)
1055 {
1056 struct m_tag *mtag;
1057
1058 /* Tag packet for carp_output */
1059 if ((mtag = m_tag_get(PACKET_TAG_CARP, sizeof(sc->sc_vhid),
1060 M_NOWAIT)) == NULL) {
1061 m_freem(m);
1062 CARPSTATS_INC(carps_onomem);
1063 return (ENOMEM);
1064 }
1065 bcopy(&sc->sc_vhid, mtag + 1, sizeof(sc->sc_vhid));
1066 m_tag_prepend(m, mtag);
1067
1068 return (0);
1069 }
1070
1071 static void
carp_prepare_ad(struct mbuf * m,struct carp_softc * sc,struct carp_header * ch)1072 carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch)
1073 {
1074
1075 MPASS(sc->sc_version == CARP_VERSION_CARP);
1076
1077 if (sc->sc_init_counter) {
1078 /* this could also be seconds since unix epoch */
1079 sc->sc_counter = arc4random();
1080 sc->sc_counter = sc->sc_counter << 32;
1081 sc->sc_counter += arc4random();
1082 } else
1083 sc->sc_counter++;
1084
1085 ch->carp_counter[0] = htonl((sc->sc_counter>>32)&0xffffffff);
1086 ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff);
1087
1088 carp_hmac_generate(sc, ch->carp_counter, ch->carp_md);
1089 }
1090
1091 static inline void
send_ad_locked(struct carp_softc * sc)1092 send_ad_locked(struct carp_softc *sc)
1093 {
1094 switch (sc->sc_version) {
1095 case CARP_VERSION_CARP:
1096 carp_send_ad_locked(sc);
1097 break;
1098 case CARP_VERSION_VRRPv3:
1099 vrrp_send_ad_locked(sc);
1100 break;
1101 }
1102 }
1103
1104 /*
1105 * To avoid LORs and possible recursions this function shouldn't
1106 * be called directly, but scheduled via taskqueue.
1107 */
1108 static void
carp_send_ad_all(void * ctx __unused,int pending __unused)1109 carp_send_ad_all(void *ctx __unused, int pending __unused)
1110 {
1111 struct carp_softc *sc;
1112 struct epoch_tracker et;
1113
1114 NET_EPOCH_ENTER(et);
1115 mtx_lock(&carp_mtx);
1116 LIST_FOREACH(sc, &carp_list, sc_next)
1117 if (sc->sc_state == MASTER) {
1118 CARP_LOCK(sc);
1119 CURVNET_SET(sc->sc_carpdev->if_vnet);
1120 send_ad_locked(sc);
1121 CURVNET_RESTORE();
1122 CARP_UNLOCK(sc);
1123 }
1124 mtx_unlock(&carp_mtx);
1125 NET_EPOCH_EXIT(et);
1126 }
1127
1128 /* Send a periodic advertisement, executed in callout context. */
1129 static void
carp_callout(void * v)1130 carp_callout(void *v)
1131 {
1132 struct carp_softc *sc = v;
1133 struct epoch_tracker et;
1134
1135 NET_EPOCH_ENTER(et);
1136 CARP_LOCK_ASSERT(sc);
1137 CURVNET_SET(sc->sc_carpdev->if_vnet);
1138 send_ad_locked(sc);
1139 CURVNET_RESTORE();
1140 CARP_UNLOCK(sc);
1141 NET_EPOCH_EXIT(et);
1142 }
1143
1144 static void
carp_send_ad_error(struct carp_softc * sc,int error)1145 carp_send_ad_error(struct carp_softc *sc, int error)
1146 {
1147
1148 /*
1149 * We track errors and successful sends with this logic:
1150 * - Any error resets success counter to 0.
1151 * - MAX_ERRORS triggers demotion.
1152 * - MIN_SUCCESS successes resets error counter to 0.
1153 * - MIN_SUCCESS reverts demotion, if it was triggered before.
1154 */
1155 if (error) {
1156 if (sc->sc_sendad_errors < INT_MAX)
1157 sc->sc_sendad_errors++;
1158 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) {
1159 static const char fmt[] = "send error %d on %s";
1160 char msg[sizeof(fmt) + IFNAMSIZ];
1161
1162 sprintf(msg, fmt, error, if_name(sc->sc_carpdev));
1163 carp_demote_adj(V_carp_senderr_adj, msg);
1164 }
1165 sc->sc_sendad_success = 0;
1166 } else if (sc->sc_sendad_errors > 0) {
1167 if (++sc->sc_sendad_success >= CARP_SENDAD_MIN_SUCCESS) {
1168 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) {
1169 static const char fmt[] = "send ok on %s";
1170 char msg[sizeof(fmt) + IFNAMSIZ];
1171
1172 sprintf(msg, fmt, if_name(sc->sc_carpdev));
1173 carp_demote_adj(-V_carp_senderr_adj, msg);
1174 }
1175 sc->sc_sendad_errors = 0;
1176 }
1177 }
1178 }
1179
1180 /*
1181 * Pick the best ifaddr on the given ifp for sending CARP
1182 * advertisements.
1183 *
1184 * "Best" here is defined by ifa_preferred(). This function is much
1185 * much like ifaof_ifpforaddr() except that we just use ifa_preferred().
1186 *
1187 * (This could be simplified to return the actual address, except that
1188 * it has a different format in AF_INET and AF_INET6.)
1189 */
1190 static struct ifaddr *
carp_best_ifa(int af,struct ifnet * ifp)1191 carp_best_ifa(int af, struct ifnet *ifp)
1192 {
1193 struct ifaddr *ifa, *best;
1194
1195 NET_EPOCH_ASSERT();
1196
1197 if (af >= AF_MAX)
1198 return (NULL);
1199 best = NULL;
1200 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1201 if (ifa->ifa_addr->sa_family == af &&
1202 (best == NULL || ifa_preferred(best, ifa)))
1203 best = ifa;
1204 }
1205 if (best != NULL)
1206 ifa_ref(best);
1207 return (best);
1208 }
1209
1210 static void
carp_send_ad_locked(struct carp_softc * sc)1211 carp_send_ad_locked(struct carp_softc *sc)
1212 {
1213 struct carp_header ch;
1214 struct timeval tv;
1215 struct ifaddr *ifa;
1216 struct carp_header *ch_ptr;
1217 struct mbuf *m;
1218 int len, advskew;
1219
1220 NET_EPOCH_ASSERT();
1221 CARP_LOCK_ASSERT(sc);
1222 MPASS(sc->sc_version == CARP_VERSION_CARP);
1223
1224 advskew = DEMOTE_ADVSKEW(sc);
1225 tv.tv_sec = sc->sc_advbase;
1226 tv.tv_usec = advskew * 1000000 / 256;
1227
1228 ch.carp_version = CARP_VERSION_CARP;
1229 ch.carp_type = CARP_ADVERTISEMENT;
1230 ch.carp_vhid = sc->sc_vhid;
1231 ch.carp_advbase = sc->sc_advbase;
1232 ch.carp_advskew = advskew;
1233 ch.carp_authlen = 7; /* XXX DEFINE */
1234 ch.carp_pad1 = 0; /* must be zero */
1235 ch.carp_cksum = 0;
1236
1237 /* XXXGL: OpenBSD picks first ifaddr with needed family. */
1238
1239 #ifdef INET
1240 if (sc->sc_naddrs) {
1241 struct ip *ip;
1242
1243 m = m_gethdr(M_NOWAIT, MT_DATA);
1244 if (m == NULL) {
1245 CARPSTATS_INC(carps_onomem);
1246 goto resched;
1247 }
1248 len = sizeof(*ip) + sizeof(ch);
1249 m->m_pkthdr.len = len;
1250 m->m_pkthdr.rcvif = NULL;
1251 m->m_len = len;
1252 M_ALIGN(m, m->m_len);
1253 if (IN_MULTICAST(sc->sc_carpaddr.s_addr))
1254 m->m_flags |= M_MCAST;
1255 ip = mtod(m, struct ip *);
1256 ip->ip_v = IPVERSION;
1257 ip->ip_hl = sizeof(*ip) >> 2;
1258 ip->ip_tos = V_carp_dscp << IPTOS_DSCP_OFFSET;
1259 ip->ip_len = htons(len);
1260 ip->ip_off = htons(IP_DF);
1261 ip->ip_ttl = CARP_DFLTTL;
1262 ip->ip_p = IPPROTO_CARP;
1263 ip->ip_sum = 0;
1264 ip_fillid(ip);
1265
1266 ifa = carp_best_ifa(AF_INET, sc->sc_carpdev);
1267 if (ifa != NULL) {
1268 ip->ip_src.s_addr =
1269 ifatoia(ifa)->ia_addr.sin_addr.s_addr;
1270 ifa_free(ifa);
1271 } else
1272 ip->ip_src.s_addr = 0;
1273 ip->ip_dst = sc->sc_carpaddr;
1274
1275 ch_ptr = (struct carp_header *)(&ip[1]);
1276 bcopy(&ch, ch_ptr, sizeof(ch));
1277 carp_prepare_ad(m, sc, ch_ptr);
1278 if (IN_MULTICAST(ntohl(sc->sc_carpaddr.s_addr)) &&
1279 carp_tag(sc, m) != 0)
1280 goto resched;
1281
1282 m->m_data += sizeof(*ip);
1283 ch_ptr->carp_cksum = in_cksum(m, len - sizeof(*ip));
1284 m->m_data -= sizeof(*ip);
1285
1286 CARPSTATS_INC(carps_opackets);
1287
1288 carp_send_ad_error(sc, ip_output(m, NULL, NULL, IP_RAWOUTPUT,
1289 &sc->sc_carpdev->if_carp->cif_imo, NULL));
1290 }
1291 #endif /* INET */
1292 #ifdef INET6
1293 if (sc->sc_naddrs6) {
1294 struct ip6_hdr *ip6;
1295
1296 m = m_gethdr(M_NOWAIT, MT_DATA);
1297 if (m == NULL) {
1298 CARPSTATS_INC(carps_onomem);
1299 goto resched;
1300 }
1301 len = sizeof(*ip6) + sizeof(ch);
1302 m->m_pkthdr.len = len;
1303 m->m_pkthdr.rcvif = NULL;
1304 m->m_len = len;
1305 M_ALIGN(m, m->m_len);
1306 ip6 = mtod(m, struct ip6_hdr *);
1307 bzero(ip6, sizeof(*ip6));
1308 ip6->ip6_vfc |= IPV6_VERSION;
1309 /* Traffic class isn't defined in ip6 struct instead
1310 * it gets offset into flowid field */
1311 ip6->ip6_flow |= htonl(V_carp_dscp << (IPV6_FLOWLABEL_LEN +
1312 IPTOS_DSCP_OFFSET));
1313 ip6->ip6_hlim = CARP_DFLTTL;
1314 ip6->ip6_nxt = IPPROTO_CARP;
1315
1316 /* set the source address */
1317 ifa = carp_best_ifa(AF_INET6, sc->sc_carpdev);
1318 if (ifa != NULL) {
1319 bcopy(IFA_IN6(ifa), &ip6->ip6_src,
1320 sizeof(struct in6_addr));
1321 ifa_free(ifa);
1322 } else
1323 /* This should never happen with IPv6. */
1324 bzero(&ip6->ip6_src, sizeof(struct in6_addr));
1325
1326 /* Set the multicast destination. */
1327 memcpy(&ip6->ip6_dst, &sc->sc_carpaddr6, sizeof(ip6->ip6_dst));
1328 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1329 IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
1330 if (in6_setscope(&ip6->ip6_dst, sc->sc_carpdev, NULL) != 0) {
1331 m_freem(m);
1332 CARP_DEBUG("%s: in6_setscope failed\n", __func__);
1333 goto resched;
1334 }
1335 }
1336
1337 ch_ptr = (struct carp_header *)(&ip6[1]);
1338 bcopy(&ch, ch_ptr, sizeof(ch));
1339 carp_prepare_ad(m, sc, ch_ptr);
1340 if (IN6_IS_ADDR_MULTICAST(&sc->sc_carpaddr6) &&
1341 carp_tag(sc, m) != 0)
1342 goto resched;
1343
1344 m->m_data += sizeof(*ip6);
1345 ch_ptr->carp_cksum = in_cksum(m, len - sizeof(*ip6));
1346 m->m_data -= sizeof(*ip6);
1347
1348 CARPSTATS_INC(carps_opackets6);
1349
1350 carp_send_ad_error(sc, ip6_output(m, NULL, NULL, 0,
1351 &sc->sc_carpdev->if_carp->cif_im6o, NULL, NULL));
1352 }
1353 #endif /* INET6 */
1354
1355 resched:
1356 callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), carp_callout, sc);
1357 }
1358
1359 static void
vrrp_send_ad_locked(struct carp_softc * sc)1360 vrrp_send_ad_locked(struct carp_softc *sc)
1361 {
1362 struct vrrpv3_header *vh_ptr;
1363 struct ifaddr *ifa;
1364 struct mbuf *m;
1365 int len;
1366 struct vrrpv3_header vh = {
1367 .vrrp_version = CARP_VERSION_VRRPv3,
1368 .vrrp_type = VRRP_TYPE_ADVERTISEMENT,
1369 .vrrp_vrtid = sc->sc_vhid,
1370 .vrrp_priority = sc->sc_vrrp_prio,
1371 .vrrp_count_addr = 0,
1372 .vrrp_max_adver_int = htons(sc->sc_vrrp_adv_inter),
1373 .vrrp_checksum = 0,
1374 };
1375
1376 NET_EPOCH_ASSERT();
1377 CARP_LOCK_ASSERT(sc);
1378 MPASS(sc->sc_version == CARP_VERSION_VRRPv3);
1379
1380 #ifdef INET
1381 if (sc->sc_naddrs) {
1382 struct ip *ip;
1383
1384 m = m_gethdr(M_NOWAIT, MT_DATA);
1385 if (m == NULL) {
1386 CARPSTATS_INC(carps_onomem);
1387 goto resched;
1388 }
1389 len = sizeof(*ip) + sizeof(vh);
1390 m->m_pkthdr.len = len;
1391 m->m_pkthdr.rcvif = NULL;
1392 m->m_len = len;
1393 M_ALIGN(m, m->m_len);
1394 m->m_flags |= M_MCAST;
1395 ip = mtod(m, struct ip *);
1396 ip->ip_v = IPVERSION;
1397 ip->ip_hl = sizeof(*ip) >> 2;
1398 ip->ip_tos = V_carp_dscp << IPTOS_DSCP_OFFSET;
1399 ip->ip_off = htons(IP_DF);
1400 ip->ip_ttl = CARP_DFLTTL;
1401 ip->ip_p = IPPROTO_CARP;
1402 ip->ip_sum = 0;
1403 ip_fillid(ip);
1404
1405 ifa = carp_best_ifa(AF_INET, sc->sc_carpdev);
1406 if (ifa != NULL) {
1407 ip->ip_src.s_addr =
1408 ifatoia(ifa)->ia_addr.sin_addr.s_addr;
1409 ifa_free(ifa);
1410 } else
1411 ip->ip_src.s_addr = 0;
1412 ip->ip_dst.s_addr = htonl(INADDR_CARP_GROUP);
1413
1414 /* Include the IP addresses in the announcement. */
1415 for (int i = 0; i < (sc->sc_naddrs + sc->sc_naddrs6); i++) {
1416 struct sockaddr_in *in;
1417
1418 MPASS(sc->sc_ifas[i] != NULL);
1419 if (sc->sc_ifas[i]->ifa_addr->sa_family != AF_INET)
1420 continue;
1421
1422 in = (struct sockaddr_in *)sc->sc_ifas[i]->ifa_addr;
1423
1424 if (m_append(m, sizeof(in->sin_addr),
1425 (caddr_t)&in->sin_addr) != 1) {
1426 m_freem(m);
1427 goto resched;
1428 }
1429
1430 vh.vrrp_count_addr++;
1431 len += sizeof(in->sin_addr);
1432 }
1433 ip->ip_len = htons(len);
1434
1435 vh_ptr = (struct vrrpv3_header *)mtodo(m, sizeof(*ip));
1436 bcopy(&vh, vh_ptr, sizeof(vh));
1437
1438 vh_ptr->vrrp_checksum = in_pseudo(ip->ip_src.s_addr,
1439 ip->ip_dst.s_addr,
1440 htonl((uint16_t)(len - sizeof(*ip)) + ip->ip_p));
1441 vh_ptr->vrrp_checksum = in_cksum_skip(m, len, sizeof(*ip));
1442
1443 if (carp_tag(sc, m))
1444 goto resched;
1445
1446 CARPSTATS_INC(carps_opackets);
1447
1448 carp_send_ad_error(sc, ip_output(m, NULL, NULL, IP_RAWOUTPUT,
1449 &sc->sc_carpdev->if_carp->cif_imo, NULL));
1450 }
1451 #endif
1452 #ifdef INET6
1453 if (sc->sc_naddrs6) {
1454 struct ip6_hdr *ip6;
1455
1456 m = m_gethdr(M_NOWAIT, MT_DATA);
1457 if (m == NULL) {
1458 CARPSTATS_INC(carps_onomem);
1459 goto resched;
1460 }
1461 len = sizeof(*ip6) + sizeof(vh);
1462 m->m_pkthdr.len = len;
1463 m->m_pkthdr.rcvif = NULL;
1464 m->m_len = len;
1465 M_ALIGN(m, m->m_len);
1466 m->m_flags |= M_MCAST;
1467 ip6 = mtod(m, struct ip6_hdr *);
1468 bzero(ip6, sizeof(*ip6));
1469 ip6->ip6_vfc |= IPV6_VERSION;
1470 /* Traffic class isn't defined in ip6 struct instead
1471 * it gets offset into flowid field */
1472 ip6->ip6_flow |= htonl(V_carp_dscp << (IPV6_FLOWLABEL_LEN +
1473 IPTOS_DSCP_OFFSET));
1474 ip6->ip6_hlim = CARP_DFLTTL;
1475 ip6->ip6_nxt = IPPROTO_CARP;
1476
1477 /* set the source address */
1478 ifa = carp_best_ifa(AF_INET6, sc->sc_carpdev);
1479 if (ifa != NULL) {
1480 bcopy(IFA_IN6(ifa), &ip6->ip6_src,
1481 sizeof(struct in6_addr));
1482 ifa_free(ifa);
1483 } else
1484 /* This should never happen with IPv6. */
1485 bzero(&ip6->ip6_src, sizeof(struct in6_addr));
1486
1487 /* Set the multicast destination. */
1488 bzero(&ip6->ip6_dst, sizeof(ip6->ip6_dst));
1489 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
1490 ip6->ip6_dst.s6_addr8[15] = 0x12;
1491
1492 /* Include the IP addresses in the announcement. */
1493 len = sizeof(vh);
1494 for (int i = 0; i < (sc->sc_naddrs + sc->sc_naddrs6); i++) {
1495 struct sockaddr_in6 *in6;
1496
1497 MPASS(sc->sc_ifas[i] != NULL);
1498 if (sc->sc_ifas[i]->ifa_addr->sa_family != AF_INET6)
1499 continue;
1500
1501 in6 = (struct sockaddr_in6 *)sc->sc_ifas[i]->ifa_addr;
1502
1503 if (m_append(m, sizeof(in6->sin6_addr),
1504 (char *)&in6->sin6_addr) != 1) {
1505 m_freem(m);
1506 goto resched;
1507 }
1508
1509 vh.vrrp_count_addr++;
1510 len += sizeof(in6->sin6_addr);
1511 }
1512 ip6->ip6_plen = htonl(len);
1513
1514 vh_ptr = (struct vrrpv3_header *)mtodo(m, sizeof(*ip6));
1515 bcopy(&vh, vh_ptr, sizeof(vh));
1516
1517 vh_ptr->vrrp_checksum = in6_cksum_pseudo(ip6, len, ip6->ip6_nxt, 0);
1518 vh_ptr->vrrp_checksum = in_cksum_skip(m, len + sizeof(*ip6), sizeof(*ip6));
1519
1520 if (in6_setscope(&ip6->ip6_dst, sc->sc_carpdev, NULL) != 0) {
1521 m_freem(m);
1522 CARP_DEBUG("%s: in6_setscope failed\n", __func__);
1523 goto resched;
1524 }
1525
1526 if (carp_tag(sc, m))
1527 goto resched;
1528 CARPSTATS_INC(carps_opackets6);
1529
1530 carp_send_ad_error(sc, ip6_output(m, NULL, NULL, 0,
1531 &sc->sc_carpdev->if_carp->cif_im6o, NULL, NULL));
1532 }
1533 #endif
1534
1535 resched:
1536 callout_reset(&sc->sc_ad_tmo, sc->sc_vrrp_adv_inter * hz / 100,
1537 carp_callout, sc);
1538 }
1539
1540 static void
carp_addroute(struct carp_softc * sc)1541 carp_addroute(struct carp_softc *sc)
1542 {
1543 struct ifaddr *ifa;
1544
1545 CARP_FOREACH_IFA(sc, ifa)
1546 carp_ifa_addroute(ifa);
1547 }
1548
1549 static void
carp_ifa_addroute(struct ifaddr * ifa)1550 carp_ifa_addroute(struct ifaddr *ifa)
1551 {
1552
1553 switch (ifa->ifa_addr->sa_family) {
1554 #ifdef INET
1555 case AF_INET:
1556 in_addprefix(ifatoia(ifa));
1557 ifa_add_loopback_route(ifa,
1558 (struct sockaddr *)&ifatoia(ifa)->ia_addr);
1559 break;
1560 #endif
1561 #ifdef INET6
1562 case AF_INET6:
1563 ifa_add_loopback_route(ifa,
1564 (struct sockaddr *)&ifatoia6(ifa)->ia_addr);
1565 nd6_add_ifa_lle(ifatoia6(ifa));
1566 break;
1567 #endif
1568 }
1569 }
1570
1571 static void
carp_delroute(struct carp_softc * sc)1572 carp_delroute(struct carp_softc *sc)
1573 {
1574 struct ifaddr *ifa;
1575
1576 CARP_FOREACH_IFA(sc, ifa)
1577 carp_ifa_delroute(ifa);
1578 }
1579
1580 static void
carp_ifa_delroute(struct ifaddr * ifa)1581 carp_ifa_delroute(struct ifaddr *ifa)
1582 {
1583
1584 switch (ifa->ifa_addr->sa_family) {
1585 #ifdef INET
1586 case AF_INET:
1587 ifa_del_loopback_route(ifa,
1588 (struct sockaddr *)&ifatoia(ifa)->ia_addr);
1589 in_scrubprefix(ifatoia(ifa), LLE_STATIC);
1590 break;
1591 #endif
1592 #ifdef INET6
1593 case AF_INET6:
1594 ifa_del_loopback_route(ifa,
1595 (struct sockaddr *)&ifatoia6(ifa)->ia_addr);
1596 nd6_rem_ifa_lle(ifatoia6(ifa), 1);
1597 break;
1598 #endif
1599 }
1600 }
1601
1602 int
carp_master(struct ifaddr * ifa)1603 carp_master(struct ifaddr *ifa)
1604 {
1605 struct carp_softc *sc = ifa->ifa_carp;
1606
1607 return (sc->sc_state == MASTER);
1608 }
1609
1610 #ifdef INET
1611 /*
1612 * Broadcast a gratuitous ARP request containing
1613 * the virtual router MAC address for each IP address
1614 * associated with the virtual router.
1615 */
1616 static void
carp_send_arp(struct carp_softc * sc)1617 carp_send_arp(struct carp_softc *sc)
1618 {
1619 struct ifaddr *ifa;
1620 struct in_addr addr;
1621
1622 NET_EPOCH_ASSERT();
1623
1624 CARP_FOREACH_IFA(sc, ifa) {
1625 if (ifa->ifa_addr->sa_family != AF_INET)
1626 continue;
1627 addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
1628 arp_announce_ifaddr(sc->sc_carpdev, addr, sc->sc_addr);
1629 }
1630 }
1631
1632 int
carp_iamatch(struct ifaddr * ifa,uint8_t ** enaddr)1633 carp_iamatch(struct ifaddr *ifa, uint8_t **enaddr)
1634 {
1635 struct carp_softc *sc = ifa->ifa_carp;
1636
1637 if (sc->sc_state == MASTER) {
1638 *enaddr = sc->sc_addr;
1639 return (1);
1640 }
1641
1642 return (0);
1643 }
1644 #endif
1645
1646 #ifdef INET6
1647 static void
carp_send_na(struct carp_softc * sc)1648 carp_send_na(struct carp_softc *sc)
1649 {
1650 static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
1651 struct ifaddr *ifa;
1652 struct in6_addr *in6;
1653
1654 CARP_FOREACH_IFA(sc, ifa) {
1655 if (ifa->ifa_addr->sa_family != AF_INET6)
1656 continue;
1657
1658 in6 = IFA_IN6(ifa);
1659 nd6_na_output(sc->sc_carpdev, &mcast, in6,
1660 ND_NA_FLAG_OVERRIDE, 1, NULL);
1661 DELAY(1000); /* XXX */
1662 }
1663 }
1664
1665 /*
1666 * Returns ifa in case it's a carp address and it is MASTER, or if the address
1667 * matches and is not a carp address. Returns NULL otherwise.
1668 */
1669 struct ifaddr *
carp_iamatch6(struct ifnet * ifp,struct in6_addr * taddr)1670 carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr)
1671 {
1672 struct ifaddr *ifa;
1673
1674 NET_EPOCH_ASSERT();
1675
1676 ifa = NULL;
1677 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1678 if (ifa->ifa_addr->sa_family != AF_INET6)
1679 continue;
1680 if (!IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa)))
1681 continue;
1682 if (ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER)
1683 ifa = NULL;
1684 else
1685 ifa_ref(ifa);
1686 break;
1687 }
1688
1689 return (ifa);
1690 }
1691
1692 char *
carp_macmatch6(struct ifnet * ifp,struct mbuf * m,const struct in6_addr * taddr)1693 carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
1694 {
1695 struct ifaddr *ifa;
1696
1697 NET_EPOCH_ASSERT();
1698
1699 IFNET_FOREACH_IFA(ifp, ifa)
1700 if (ifa->ifa_addr->sa_family == AF_INET6 &&
1701 IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa))) {
1702 struct carp_softc *sc = ifa->ifa_carp;
1703 struct m_tag *mtag;
1704
1705 mtag = m_tag_get(PACKET_TAG_CARP,
1706 sizeof(struct carp_softc *), M_NOWAIT);
1707 if (mtag == NULL)
1708 /* Better a bit than nothing. */
1709 return (sc->sc_addr);
1710
1711 bcopy(&sc, mtag + 1, sizeof(sc));
1712 m_tag_prepend(m, mtag);
1713
1714 return (sc->sc_addr);
1715 }
1716
1717 return (NULL);
1718 }
1719 #endif /* INET6 */
1720
1721 int
carp_forus(struct ifnet * ifp,u_char * dhost)1722 carp_forus(struct ifnet *ifp, u_char *dhost)
1723 {
1724 struct carp_softc *sc;
1725 uint8_t *ena = dhost;
1726
1727 if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1)
1728 return (0);
1729
1730 CIF_LOCK(ifp->if_carp);
1731 IFNET_FOREACH_CARP(ifp, sc) {
1732 /*
1733 * CARP_LOCK() is not here, since would protect nothing, but
1734 * cause deadlock with if_bridge, calling this under its lock.
1735 */
1736 if (sc->sc_state == MASTER && !bcmp(dhost, sc->sc_addr,
1737 ETHER_ADDR_LEN)) {
1738 CIF_UNLOCK(ifp->if_carp);
1739 return (1);
1740 }
1741 }
1742 CIF_UNLOCK(ifp->if_carp);
1743
1744 return (0);
1745 }
1746
1747 /* Master down timeout event, executed in callout context. */
1748 static void
carp_master_down(void * v)1749 carp_master_down(void *v)
1750 {
1751 struct carp_softc *sc = v;
1752 struct epoch_tracker et;
1753
1754 NET_EPOCH_ENTER(et);
1755 CARP_LOCK_ASSERT(sc);
1756
1757 CURVNET_SET(sc->sc_carpdev->if_vnet);
1758 if (sc->sc_state == BACKUP) {
1759 carp_master_down_locked(sc, "master timed out");
1760 }
1761 CURVNET_RESTORE();
1762
1763 CARP_UNLOCK(sc);
1764 NET_EPOCH_EXIT(et);
1765 }
1766
1767 static void
carp_master_down_locked(struct carp_softc * sc,const char * reason)1768 carp_master_down_locked(struct carp_softc *sc, const char *reason)
1769 {
1770
1771 NET_EPOCH_ASSERT();
1772 CARP_LOCK_ASSERT(sc);
1773
1774 switch (sc->sc_state) {
1775 case BACKUP:
1776 carp_set_state(sc, MASTER, reason);
1777 send_ad_locked(sc);
1778 #ifdef INET
1779 carp_send_arp(sc);
1780 #endif
1781 #ifdef INET6
1782 carp_send_na(sc);
1783 #endif
1784 carp_setrun(sc, 0);
1785 carp_addroute(sc);
1786 break;
1787 case INIT:
1788 case MASTER:
1789 #ifdef INVARIANTS
1790 panic("carp: VHID %u@%s: master_down event in %s state\n",
1791 sc->sc_vhid,
1792 if_name(sc->sc_carpdev),
1793 sc->sc_state ? "MASTER" : "INIT");
1794 #endif
1795 break;
1796 }
1797 }
1798
1799 /*
1800 * When in backup state, af indicates whether to reset the master down timer
1801 * for v4 or v6. If it's set to zero, reset the ones which are already pending.
1802 */
1803 static void
carp_setrun(struct carp_softc * sc,sa_family_t af)1804 carp_setrun(struct carp_softc *sc, sa_family_t af)
1805 {
1806 struct timeval tv;
1807 int timeout;
1808
1809 CARP_LOCK_ASSERT(sc);
1810
1811 if ((sc->sc_carpdev->if_flags & IFF_UP) == 0 ||
1812 sc->sc_carpdev->if_link_state != LINK_STATE_UP ||
1813 (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) ||
1814 !V_carp_allow)
1815 return;
1816
1817 switch (sc->sc_state) {
1818 case INIT:
1819 carp_set_state(sc, BACKUP, "initialization complete");
1820 carp_setrun(sc, 0);
1821 break;
1822 case BACKUP:
1823 callout_stop(&sc->sc_ad_tmo);
1824
1825 switch (sc->sc_version) {
1826 case CARP_VERSION_CARP:
1827 tv.tv_sec = 3 * sc->sc_advbase;
1828 tv.tv_usec = sc->sc_advskew * 1000000 / 256;
1829 timeout = tvtohz(&tv);
1830 break;
1831 case CARP_VERSION_VRRPv3:
1832 /* skew time */
1833 timeout = (256 - sc->sc_vrrp_prio) *
1834 sc->sc_vrrp_master_inter / 256;
1835 timeout += (3 * sc->sc_vrrp_master_inter);
1836 timeout *= hz;
1837 timeout /= 100; /* master interval is in centiseconds */
1838 break;
1839 }
1840 switch (af) {
1841 #ifdef INET
1842 case AF_INET:
1843 callout_reset(&sc->sc_md_tmo, timeout,
1844 carp_master_down, sc);
1845 break;
1846 #endif
1847 #ifdef INET6
1848 case AF_INET6:
1849 callout_reset(&sc->sc_md6_tmo, timeout,
1850 carp_master_down, sc);
1851 break;
1852 #endif
1853 default:
1854 #ifdef INET
1855 if (sc->sc_naddrs)
1856 callout_reset(&sc->sc_md_tmo, timeout,
1857 carp_master_down, sc);
1858 #endif
1859 #ifdef INET6
1860 if (sc->sc_naddrs6)
1861 callout_reset(&sc->sc_md6_tmo, timeout,
1862 carp_master_down, sc);
1863 #endif
1864 break;
1865 }
1866 break;
1867 case MASTER:
1868 switch (sc->sc_version) {
1869 case CARP_VERSION_CARP:
1870 tv.tv_sec = sc->sc_advbase;
1871 tv.tv_usec = sc->sc_advskew * 1000000 / 256;
1872 callout_reset(&sc->sc_ad_tmo, tvtohz(&tv),
1873 carp_callout, sc);
1874 break;
1875 case CARP_VERSION_VRRPv3:
1876 callout_reset(&sc->sc_ad_tmo,
1877 sc->sc_vrrp_adv_inter * hz / 100,
1878 carp_callout, sc);
1879 break;
1880 }
1881 break;
1882 }
1883 }
1884
1885 /*
1886 * Setup multicast structures.
1887 */
1888 static int
carp_multicast_setup(struct carp_if * cif,sa_family_t sa)1889 carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
1890 {
1891 struct ifnet *ifp = cif->cif_ifp;
1892 int error = 0;
1893
1894 switch (sa) {
1895 #ifdef INET
1896 case AF_INET:
1897 {
1898 struct ip_moptions *imo = &cif->cif_imo;
1899 struct in_mfilter *imf;
1900 struct in_addr addr;
1901
1902 if (ip_mfilter_first(&imo->imo_head) != NULL)
1903 return (0);
1904
1905 imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
1906 ip_mfilter_init(&imo->imo_head);
1907 imo->imo_multicast_vif = -1;
1908
1909 addr.s_addr = htonl(INADDR_CARP_GROUP);
1910 if ((error = in_joingroup(ifp, &addr, NULL,
1911 &imf->imf_inm)) != 0) {
1912 ip_mfilter_free(imf);
1913 break;
1914 }
1915
1916 ip_mfilter_insert(&imo->imo_head, imf);
1917 imo->imo_multicast_ifp = ifp;
1918 imo->imo_multicast_ttl = CARP_DFLTTL;
1919 imo->imo_multicast_loop = 0;
1920 break;
1921 }
1922 #endif
1923 #ifdef INET6
1924 case AF_INET6:
1925 {
1926 struct ip6_moptions *im6o = &cif->cif_im6o;
1927 struct in6_mfilter *im6f[2];
1928 struct in6_addr in6;
1929
1930 if (ip6_mfilter_first(&im6o->im6o_head))
1931 return (0);
1932
1933 im6f[0] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
1934 im6f[1] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
1935
1936 ip6_mfilter_init(&im6o->im6o_head);
1937 im6o->im6o_multicast_hlim = CARP_DFLTTL;
1938 im6o->im6o_multicast_ifp = ifp;
1939
1940 /* Join IPv6 CARP multicast group. */
1941 bzero(&in6, sizeof(in6));
1942 in6.s6_addr16[0] = htons(0xff02);
1943 in6.s6_addr8[15] = 0x12;
1944 if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
1945 ip6_mfilter_free(im6f[0]);
1946 ip6_mfilter_free(im6f[1]);
1947 break;
1948 }
1949 if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[0]->im6f_in6m, 0)) != 0) {
1950 ip6_mfilter_free(im6f[0]);
1951 ip6_mfilter_free(im6f[1]);
1952 break;
1953 }
1954
1955 /* Join solicited multicast address. */
1956 bzero(&in6, sizeof(in6));
1957 in6.s6_addr16[0] = htons(0xff02);
1958 in6.s6_addr32[1] = 0;
1959 in6.s6_addr32[2] = htonl(1);
1960 in6.s6_addr32[3] = 0;
1961 in6.s6_addr8[12] = 0xff;
1962
1963 if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
1964 ip6_mfilter_free(im6f[0]);
1965 ip6_mfilter_free(im6f[1]);
1966 break;
1967 }
1968
1969 if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[1]->im6f_in6m, 0)) != 0) {
1970 in6_leavegroup(im6f[0]->im6f_in6m, NULL);
1971 ip6_mfilter_free(im6f[0]);
1972 ip6_mfilter_free(im6f[1]);
1973 break;
1974 }
1975 ip6_mfilter_insert(&im6o->im6o_head, im6f[0]);
1976 ip6_mfilter_insert(&im6o->im6o_head, im6f[1]);
1977 break;
1978 }
1979 #endif
1980 }
1981
1982 return (error);
1983 }
1984
1985 /*
1986 * Free multicast structures.
1987 */
1988 static void
carp_multicast_cleanup(struct carp_if * cif,sa_family_t sa)1989 carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa)
1990 {
1991 #ifdef INET
1992 struct ip_moptions *imo = &cif->cif_imo;
1993 struct in_mfilter *imf;
1994 #endif
1995 #ifdef INET6
1996 struct ip6_moptions *im6o = &cif->cif_im6o;
1997 struct in6_mfilter *im6f;
1998 #endif
1999 sx_assert(&carp_sx, SA_XLOCKED);
2000
2001 switch (sa) {
2002 #ifdef INET
2003 case AF_INET:
2004 if (cif->cif_naddrs != 0)
2005 break;
2006
2007 while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
2008 ip_mfilter_remove(&imo->imo_head, imf);
2009 in_leavegroup(imf->imf_inm, NULL);
2010 ip_mfilter_free(imf);
2011 }
2012 break;
2013 #endif
2014 #ifdef INET6
2015 case AF_INET6:
2016 if (cif->cif_naddrs6 != 0)
2017 break;
2018
2019 while ((im6f = ip6_mfilter_first(&im6o->im6o_head)) != NULL) {
2020 ip6_mfilter_remove(&im6o->im6o_head, im6f);
2021 in6_leavegroup(im6f->im6f_in6m, NULL);
2022 ip6_mfilter_free(im6f);
2023 }
2024 break;
2025 #endif
2026 }
2027 }
2028
2029 int
carp_output(struct ifnet * ifp,struct mbuf * m,const struct sockaddr * sa)2030 carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
2031 {
2032 struct m_tag *mtag;
2033 int vhid;
2034
2035 if (!sa)
2036 return (0);
2037
2038 switch (sa->sa_family) {
2039 #ifdef INET
2040 case AF_INET:
2041 break;
2042 #endif
2043 #ifdef INET6
2044 case AF_INET6:
2045 break;
2046 #endif
2047 default:
2048 return (0);
2049 }
2050
2051 mtag = m_tag_find(m, PACKET_TAG_CARP, NULL);
2052 if (mtag == NULL)
2053 return (0);
2054
2055 bcopy(mtag + 1, &vhid, sizeof(vhid));
2056
2057 /* Set the source MAC address to the Virtual Router MAC Address. */
2058 switch (ifp->if_type) {
2059 case IFT_ETHER:
2060 case IFT_BRIDGE:
2061 case IFT_L2VLAN: {
2062 struct ether_header *eh;
2063
2064 eh = mtod(m, struct ether_header *);
2065 eh->ether_shost[0] = 0;
2066 eh->ether_shost[1] = 0;
2067 eh->ether_shost[2] = 0x5e;
2068 eh->ether_shost[3] = 0;
2069 eh->ether_shost[4] = 1;
2070 eh->ether_shost[5] = vhid;
2071 }
2072 break;
2073 default:
2074 printf("%s: carp is not supported for the %d interface type\n",
2075 if_name(ifp), ifp->if_type);
2076 return (EOPNOTSUPP);
2077 }
2078
2079 return (0);
2080 }
2081
2082 static struct carp_softc*
carp_alloc(struct ifnet * ifp,carp_version_t version,int vhid)2083 carp_alloc(struct ifnet *ifp, carp_version_t version, int vhid)
2084 {
2085 struct carp_softc *sc;
2086 struct carp_if *cif;
2087
2088 sx_assert(&carp_sx, SA_XLOCKED);
2089
2090 if ((cif = ifp->if_carp) == NULL)
2091 cif = carp_alloc_if(ifp);
2092
2093 sc = malloc(sizeof(*sc), M_CARP, M_WAITOK);
2094 *sc = (struct carp_softc ){
2095 .sc_vhid = vhid,
2096 .sc_version = version,
2097 .sc_state = INIT,
2098 .sc_carpdev = ifp,
2099 .sc_ifasiz = sizeof(struct ifaddr *),
2100 .sc_addr = { 0, 0, 0x5e, 0, 1, vhid },
2101 };
2102 sc->sc_ifas = malloc(sc->sc_ifasiz, M_CARP, M_WAITOK|M_ZERO);
2103
2104 switch (version) {
2105 case CARP_VERSION_CARP:
2106 sc->sc_advbase = CARP_DFLTINTV;
2107 sc->sc_init_counter = true;
2108 sc->sc_carpaddr.s_addr = htonl(INADDR_CARP_GROUP);
2109 sc->sc_carpaddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
2110 sc->sc_carpaddr6.s6_addr8[15] = 0x12;
2111 break;
2112 case CARP_VERSION_VRRPv3:
2113 sc->sc_vrrp_adv_inter = 100;
2114 sc->sc_vrrp_master_inter = sc->sc_vrrp_adv_inter;
2115 sc->sc_vrrp_prio = 100;
2116 break;
2117 }
2118
2119 CARP_LOCK_INIT(sc);
2120 #ifdef INET
2121 callout_init_mtx(&sc->sc_md_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED);
2122 #endif
2123 #ifdef INET6
2124 callout_init_mtx(&sc->sc_md6_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED);
2125 #endif
2126 callout_init_mtx(&sc->sc_ad_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED);
2127
2128 CIF_LOCK(cif);
2129 TAILQ_INSERT_TAIL(&cif->cif_vrs, sc, sc_list);
2130 CIF_UNLOCK(cif);
2131
2132 mtx_lock(&carp_mtx);
2133 LIST_INSERT_HEAD(&carp_list, sc, sc_next);
2134 mtx_unlock(&carp_mtx);
2135
2136 return (sc);
2137 }
2138
2139 static void
carp_grow_ifas(struct carp_softc * sc)2140 carp_grow_ifas(struct carp_softc *sc)
2141 {
2142 struct ifaddr **new;
2143
2144 new = malloc(sc->sc_ifasiz * 2, M_CARP, M_WAITOK | M_ZERO);
2145 CARP_LOCK(sc);
2146 bcopy(sc->sc_ifas, new, sc->sc_ifasiz);
2147 free(sc->sc_ifas, M_CARP);
2148 sc->sc_ifas = new;
2149 sc->sc_ifasiz *= 2;
2150 CARP_UNLOCK(sc);
2151 }
2152
2153 static void
carp_destroy(struct carp_softc * sc)2154 carp_destroy(struct carp_softc *sc)
2155 {
2156 struct ifnet *ifp = sc->sc_carpdev;
2157 struct carp_if *cif = ifp->if_carp;
2158
2159 sx_assert(&carp_sx, SA_XLOCKED);
2160
2161 if (sc->sc_suppress)
2162 carp_demote_adj(-V_carp_ifdown_adj, "vhid removed");
2163 CARP_UNLOCK(sc);
2164
2165 CIF_LOCK(cif);
2166 TAILQ_REMOVE(&cif->cif_vrs, sc, sc_list);
2167 CIF_UNLOCK(cif);
2168
2169 mtx_lock(&carp_mtx);
2170 LIST_REMOVE(sc, sc_next);
2171 mtx_unlock(&carp_mtx);
2172
2173 callout_drain(&sc->sc_ad_tmo);
2174 #ifdef INET
2175 callout_drain(&sc->sc_md_tmo);
2176 #endif
2177 #ifdef INET6
2178 callout_drain(&sc->sc_md6_tmo);
2179 #endif
2180 CARP_LOCK_DESTROY(sc);
2181
2182 free(sc->sc_ifas, M_CARP);
2183 free(sc, M_CARP);
2184 }
2185
2186 static struct carp_if*
carp_alloc_if(struct ifnet * ifp)2187 carp_alloc_if(struct ifnet *ifp)
2188 {
2189 struct carp_if *cif;
2190 int error;
2191
2192 cif = malloc(sizeof(*cif), M_CARP, M_WAITOK|M_ZERO);
2193
2194 if ((error = ifpromisc(ifp, 1)) != 0)
2195 printf("%s: ifpromisc(%s) failed: %d\n",
2196 __func__, if_name(ifp), error);
2197 else
2198 cif->cif_flags |= CIF_PROMISC;
2199
2200 CIF_LOCK_INIT(cif);
2201 cif->cif_ifp = ifp;
2202 TAILQ_INIT(&cif->cif_vrs);
2203
2204 IF_ADDR_WLOCK(ifp);
2205 ifp->if_carp = cif;
2206 if_ref(ifp);
2207 IF_ADDR_WUNLOCK(ifp);
2208
2209 return (cif);
2210 }
2211
2212 static void
carp_free_if(struct carp_if * cif)2213 carp_free_if(struct carp_if *cif)
2214 {
2215 struct ifnet *ifp = cif->cif_ifp;
2216
2217 CIF_LOCK_ASSERT(cif);
2218 KASSERT(TAILQ_EMPTY(&cif->cif_vrs), ("%s: softc list not empty",
2219 __func__));
2220
2221 IF_ADDR_WLOCK(ifp);
2222 ifp->if_carp = NULL;
2223 IF_ADDR_WUNLOCK(ifp);
2224
2225 CIF_LOCK_DESTROY(cif);
2226
2227 if (cif->cif_flags & CIF_PROMISC)
2228 ifpromisc(ifp, 0);
2229 if_rele(ifp);
2230
2231 free(cif, M_CARP);
2232 }
2233
2234 static bool
carp_carprcp(void * arg,struct carp_softc * sc,int priv)2235 carp_carprcp(void *arg, struct carp_softc *sc, int priv)
2236 {
2237 struct carpreq *carpr = arg;
2238
2239 CARP_LOCK(sc);
2240 carpr->carpr_state = sc->sc_state;
2241 carpr->carpr_vhid = sc->sc_vhid;
2242 switch (sc->sc_version) {
2243 case CARP_VERSION_CARP:
2244 carpr->carpr_advbase = sc->sc_advbase;
2245 carpr->carpr_advskew = sc->sc_advskew;
2246 if (priv)
2247 bcopy(sc->sc_key, carpr->carpr_key,
2248 sizeof(carpr->carpr_key));
2249 else
2250 bzero(carpr->carpr_key, sizeof(carpr->carpr_key));
2251 break;
2252 case CARP_VERSION_VRRPv3:
2253 break;
2254 }
2255 CARP_UNLOCK(sc);
2256
2257 return (true);
2258 }
2259
2260 static int
carp_ioctl_set(if_t ifp,struct carpkreq * carpr)2261 carp_ioctl_set(if_t ifp, struct carpkreq *carpr)
2262 {
2263 struct epoch_tracker et;
2264 struct carp_softc *sc = NULL;
2265 int error = 0;
2266
2267 if (carpr->carpr_vhid <= 0 || carpr->carpr_vhid > CARP_MAXVHID)
2268 return (EINVAL);
2269
2270 switch (carpr->carpr_version) {
2271 case CARP_VERSION_CARP:
2272 if (carpr->carpr_advbase != 0 && (carpr->carpr_advbase > 255 ||
2273 carpr->carpr_advbase < CARP_DFLTINTV))
2274 return (EINVAL);
2275 if (carpr->carpr_advskew < 0 || carpr->carpr_advskew >= 255)
2276 return (EINVAL);
2277 break;
2278 case CARP_VERSION_VRRPv3:
2279 /* XXXGL: shouldn't we check anything? */
2280 break;
2281 default:
2282 return (EINVAL);
2283 }
2284
2285 if (ifp->if_carp) {
2286 IFNET_FOREACH_CARP(ifp, sc)
2287 if (sc->sc_vhid == carpr->carpr_vhid)
2288 break;
2289 }
2290
2291 if (sc == NULL)
2292 sc = carp_alloc(ifp, carpr->carpr_version, carpr->carpr_vhid);
2293 else if (sc->sc_version != carpr->carpr_version)
2294 return (EINVAL);
2295
2296 CARP_LOCK(sc);
2297 switch (sc->sc_version) {
2298 case CARP_VERSION_CARP:
2299 if (carpr->carpr_advbase != 0)
2300 sc->sc_advbase = carpr->carpr_advbase;
2301 sc->sc_advskew = carpr->carpr_advskew;
2302 if (carpr->carpr_addr.s_addr != INADDR_ANY)
2303 sc->sc_carpaddr = carpr->carpr_addr;
2304 if (!IN6_IS_ADDR_UNSPECIFIED(&carpr->carpr_addr6)) {
2305 memcpy(&sc->sc_carpaddr6, &carpr->carpr_addr6,
2306 sizeof(sc->sc_carpaddr6));
2307 }
2308 if (carpr->carpr_key[0] != '\0') {
2309 bcopy(carpr->carpr_key, sc->sc_key, sizeof(sc->sc_key));
2310 carp_hmac_prepare(sc);
2311 }
2312 break;
2313 case CARP_VERSION_VRRPv3:
2314 if (carpr->carpr_vrrp_priority != 0)
2315 sc->sc_vrrp_prio = carpr->carpr_vrrp_priority;
2316 if (carpr->carpr_vrrp_adv_inter)
2317 sc->sc_vrrp_adv_inter = carpr->carpr_vrrp_adv_inter;
2318 break;
2319 }
2320
2321 if (sc->sc_state != INIT &&
2322 carpr->carpr_state != sc->sc_state) {
2323 switch (carpr->carpr_state) {
2324 case BACKUP:
2325 callout_stop(&sc->sc_ad_tmo);
2326 carp_set_state(sc, BACKUP,
2327 "user requested via ifconfig");
2328 carp_setrun(sc, 0);
2329 carp_delroute(sc);
2330 break;
2331 case MASTER:
2332 NET_EPOCH_ENTER(et);
2333 carp_master_down_locked(sc,
2334 "user requested via ifconfig");
2335 NET_EPOCH_EXIT(et);
2336 break;
2337 default:
2338 break;
2339 }
2340 }
2341 CARP_UNLOCK(sc);
2342
2343 return (error);
2344 }
2345
2346 static int
carp_ioctl_get(if_t ifp,struct ucred * cred,struct carpreq * carpr,bool (* outfn)(void *,struct carp_softc *,int),void * arg)2347 carp_ioctl_get(if_t ifp, struct ucred *cred, struct carpreq *carpr,
2348 bool (*outfn)(void *, struct carp_softc *, int), void *arg)
2349 {
2350 int priveleged;
2351 struct carp_softc *sc;
2352
2353 if (carpr->carpr_vhid < 0 || carpr->carpr_vhid > CARP_MAXVHID)
2354 return (EINVAL);
2355 if (carpr->carpr_count < 1)
2356 return (EMSGSIZE);
2357 if (ifp->if_carp == NULL)
2358 return (ENOENT);
2359
2360 priveleged = (priv_check_cred(cred, PRIV_NETINET_CARP) == 0);
2361 if (carpr->carpr_vhid != 0) {
2362 IFNET_FOREACH_CARP(ifp, sc)
2363 if (sc->sc_vhid == carpr->carpr_vhid)
2364 break;
2365 if (sc == NULL)
2366 return (ENOENT);
2367
2368 if (! outfn(arg, sc, priveleged))
2369 return (ENOMEM);
2370 carpr->carpr_count = 1;
2371 } else {
2372 int count;
2373
2374 count = 0;
2375 IFNET_FOREACH_CARP(ifp, sc)
2376 count++;
2377
2378 if (count > carpr->carpr_count)
2379 return (EMSGSIZE);
2380
2381 IFNET_FOREACH_CARP(ifp, sc) {
2382 if (! outfn(arg, sc, priveleged))
2383 return (ENOMEM);
2384 carpr->carpr_count = count;
2385 }
2386 }
2387
2388 return (0);
2389 }
2390
2391 int
carp_ioctl(struct ifreq * ifr,u_long cmd,struct thread * td)2392 carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td)
2393 {
2394 struct carpreq carpr;
2395 struct carpkreq carprk = {
2396 .carpr_version = CARP_VERSION_CARP,
2397 };
2398 struct ifnet *ifp;
2399 int error = 0;
2400
2401 if ((error = copyin(ifr_data_get_ptr(ifr), &carpr, sizeof carpr)))
2402 return (error);
2403
2404 ifp = ifunit_ref(ifr->ifr_name);
2405 if ((error = carp_is_supported_if(ifp)) != 0)
2406 goto out;
2407
2408 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
2409 error = EADDRNOTAVAIL;
2410 goto out;
2411 }
2412
2413 sx_xlock(&carp_sx);
2414 switch (cmd) {
2415 case SIOCSVH:
2416 if ((error = priv_check(td, PRIV_NETINET_CARP)))
2417 break;
2418
2419 memcpy(&carprk, &carpr, sizeof(carpr));
2420 error = carp_ioctl_set(ifp, &carprk);
2421 break;
2422
2423 case SIOCGVH:
2424 error = carp_ioctl_get(ifp, td->td_ucred, &carpr,
2425 carp_carprcp, &carpr);
2426 if (error == 0) {
2427 error = copyout(&carpr,
2428 (char *)ifr_data_get_ptr(ifr),
2429 carpr.carpr_count * sizeof(carpr));
2430 }
2431 break;
2432 default:
2433 error = EINVAL;
2434 }
2435 sx_xunlock(&carp_sx);
2436
2437 out:
2438 if (ifp != NULL)
2439 if_rele(ifp);
2440
2441 return (error);
2442 }
2443
2444 static int
carp_get_vhid(struct ifaddr * ifa)2445 carp_get_vhid(struct ifaddr *ifa)
2446 {
2447
2448 if (ifa == NULL || ifa->ifa_carp == NULL)
2449 return (0);
2450
2451 return (ifa->ifa_carp->sc_vhid);
2452 }
2453
2454 int
carp_attach(struct ifaddr * ifa,int vhid)2455 carp_attach(struct ifaddr *ifa, int vhid)
2456 {
2457 struct ifnet *ifp = ifa->ifa_ifp;
2458 struct carp_if *cif = ifp->if_carp;
2459 struct carp_softc *sc;
2460 int index, error;
2461
2462 KASSERT(ifa->ifa_carp == NULL, ("%s: ifa %p attached", __func__, ifa));
2463
2464 switch (ifa->ifa_addr->sa_family) {
2465 #ifdef INET
2466 case AF_INET:
2467 #endif
2468 #ifdef INET6
2469 case AF_INET6:
2470 #endif
2471 break;
2472 default:
2473 return (EPROTOTYPE);
2474 }
2475
2476 sx_xlock(&carp_sx);
2477 if (ifp->if_carp == NULL) {
2478 sx_xunlock(&carp_sx);
2479 return (ENOPROTOOPT);
2480 }
2481
2482 IFNET_FOREACH_CARP(ifp, sc)
2483 if (sc->sc_vhid == vhid)
2484 break;
2485 if (sc == NULL) {
2486 sx_xunlock(&carp_sx);
2487 return (ENOENT);
2488 }
2489
2490 error = carp_multicast_setup(cif, ifa->ifa_addr->sa_family);
2491 if (error) {
2492 CIF_FREE(cif);
2493 sx_xunlock(&carp_sx);
2494 return (error);
2495 }
2496
2497 index = sc->sc_naddrs + sc->sc_naddrs6 + 1;
2498 if (index > sc->sc_ifasiz / sizeof(struct ifaddr *))
2499 carp_grow_ifas(sc);
2500
2501 switch (ifa->ifa_addr->sa_family) {
2502 #ifdef INET
2503 case AF_INET:
2504 cif->cif_naddrs++;
2505 sc->sc_naddrs++;
2506 break;
2507 #endif
2508 #ifdef INET6
2509 case AF_INET6:
2510 cif->cif_naddrs6++;
2511 sc->sc_naddrs6++;
2512 break;
2513 #endif
2514 }
2515
2516 ifa_ref(ifa);
2517
2518 CARP_LOCK(sc);
2519 sc->sc_ifas[index - 1] = ifa;
2520 ifa->ifa_carp = sc;
2521 if (sc->sc_version == CARP_VERSION_CARP)
2522 carp_hmac_prepare(sc);
2523 carp_sc_state(sc);
2524 CARP_UNLOCK(sc);
2525
2526 sx_xunlock(&carp_sx);
2527
2528 return (0);
2529 }
2530
2531 void
carp_detach(struct ifaddr * ifa,bool keep_cif)2532 carp_detach(struct ifaddr *ifa, bool keep_cif)
2533 {
2534 struct ifnet *ifp = ifa->ifa_ifp;
2535 struct carp_if *cif = ifp->if_carp;
2536 struct carp_softc *sc = ifa->ifa_carp;
2537 int i, index;
2538
2539 KASSERT(sc != NULL, ("%s: %p not attached", __func__, ifa));
2540
2541 sx_xlock(&carp_sx);
2542
2543 CARP_LOCK(sc);
2544 /* Shift array. */
2545 index = sc->sc_naddrs + sc->sc_naddrs6;
2546 for (i = 0; i < index; i++)
2547 if (sc->sc_ifas[i] == ifa)
2548 break;
2549 KASSERT(i < index, ("%s: %p no backref", __func__, ifa));
2550 for (; i < index - 1; i++)
2551 sc->sc_ifas[i] = sc->sc_ifas[i+1];
2552 sc->sc_ifas[index - 1] = NULL;
2553
2554 switch (ifa->ifa_addr->sa_family) {
2555 #ifdef INET
2556 case AF_INET:
2557 cif->cif_naddrs--;
2558 sc->sc_naddrs--;
2559 break;
2560 #endif
2561 #ifdef INET6
2562 case AF_INET6:
2563 cif->cif_naddrs6--;
2564 sc->sc_naddrs6--;
2565 break;
2566 #endif
2567 }
2568
2569 carp_ifa_delroute(ifa);
2570 carp_multicast_cleanup(cif, ifa->ifa_addr->sa_family);
2571
2572 ifa->ifa_carp = NULL;
2573 ifa_free(ifa);
2574
2575 if (sc->sc_version == CARP_VERSION_CARP)
2576 carp_hmac_prepare(sc);
2577 carp_sc_state(sc);
2578
2579 if (!keep_cif && sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0)
2580 carp_destroy(sc);
2581 else
2582 CARP_UNLOCK(sc);
2583
2584 if (!keep_cif)
2585 CIF_FREE(cif);
2586
2587 sx_xunlock(&carp_sx);
2588 }
2589
2590 static void
carp_set_state(struct carp_softc * sc,int state,const char * reason)2591 carp_set_state(struct carp_softc *sc, int state, const char *reason)
2592 {
2593
2594 CARP_LOCK_ASSERT(sc);
2595
2596 if (sc->sc_state != state) {
2597 const char *carp_states[] = { CARP_STATES };
2598 char subsys[IFNAMSIZ+5];
2599
2600 snprintf(subsys, IFNAMSIZ+5, "%u@%s", sc->sc_vhid,
2601 if_name(sc->sc_carpdev));
2602
2603 CARP_LOG("%s: %s -> %s (%s)\n", subsys,
2604 carp_states[sc->sc_state], carp_states[state], reason);
2605
2606 sc->sc_state = state;
2607
2608 devctl_notify("CARP", subsys, carp_states[state], NULL);
2609 }
2610 }
2611
2612 static void
carp_linkstate(struct ifnet * ifp)2613 carp_linkstate(struct ifnet *ifp)
2614 {
2615 struct carp_softc *sc;
2616
2617 CIF_LOCK(ifp->if_carp);
2618 IFNET_FOREACH_CARP(ifp, sc) {
2619 CARP_LOCK(sc);
2620 carp_sc_state(sc);
2621 CARP_UNLOCK(sc);
2622 }
2623 CIF_UNLOCK(ifp->if_carp);
2624 }
2625
2626 static void
carp_sc_state(struct carp_softc * sc)2627 carp_sc_state(struct carp_softc *sc)
2628 {
2629
2630 CARP_LOCK_ASSERT(sc);
2631
2632 if (sc->sc_carpdev->if_link_state != LINK_STATE_UP ||
2633 !(sc->sc_carpdev->if_flags & IFF_UP) ||
2634 !V_carp_allow) {
2635 callout_stop(&sc->sc_ad_tmo);
2636 #ifdef INET
2637 callout_stop(&sc->sc_md_tmo);
2638 #endif
2639 #ifdef INET6
2640 callout_stop(&sc->sc_md6_tmo);
2641 #endif
2642 carp_set_state(sc, INIT, "hardware interface down");
2643 carp_setrun(sc, 0);
2644 carp_delroute(sc);
2645 if (!sc->sc_suppress)
2646 carp_demote_adj(V_carp_ifdown_adj, "interface down");
2647 sc->sc_suppress = 1;
2648 } else {
2649 carp_set_state(sc, INIT, "hardware interface up");
2650 carp_setrun(sc, 0);
2651 if (sc->sc_suppress)
2652 carp_demote_adj(-V_carp_ifdown_adj, "interface up");
2653 sc->sc_suppress = 0;
2654 }
2655 }
2656
2657 static void
carp_demote_adj(int adj,char * reason)2658 carp_demote_adj(int adj, char *reason)
2659 {
2660 atomic_add_int(&V_carp_demotion, adj);
2661 CARP_LOG("demoted by %d to %d (%s)\n", adj, V_carp_demotion, reason);
2662 taskqueue_enqueue(taskqueue_swi, &carp_sendall_task);
2663 }
2664
2665 static int
carp_allow_sysctl(SYSCTL_HANDLER_ARGS)2666 carp_allow_sysctl(SYSCTL_HANDLER_ARGS)
2667 {
2668 int new, error;
2669 struct carp_softc *sc;
2670
2671 new = V_carp_allow;
2672 error = sysctl_handle_int(oidp, &new, 0, req);
2673 if (error || !req->newptr)
2674 return (error);
2675
2676 if (V_carp_allow != new) {
2677 V_carp_allow = new;
2678
2679 mtx_lock(&carp_mtx);
2680 LIST_FOREACH(sc, &carp_list, sc_next) {
2681 CARP_LOCK(sc);
2682 if (curvnet == sc->sc_carpdev->if_vnet)
2683 carp_sc_state(sc);
2684 CARP_UNLOCK(sc);
2685 }
2686 mtx_unlock(&carp_mtx);
2687 }
2688
2689 return (0);
2690 }
2691
2692 static int
carp_dscp_sysctl(SYSCTL_HANDLER_ARGS)2693 carp_dscp_sysctl(SYSCTL_HANDLER_ARGS)
2694 {
2695 int new, error;
2696
2697 new = V_carp_dscp;
2698 error = sysctl_handle_int(oidp, &new, 0, req);
2699 if (error || !req->newptr)
2700 return (error);
2701
2702 if (new < 0 || new > 63)
2703 return (EINVAL);
2704
2705 V_carp_dscp = new;
2706
2707 return (0);
2708 }
2709
2710 static int
carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS)2711 carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS)
2712 {
2713 int new, error;
2714
2715 new = V_carp_demotion;
2716 error = sysctl_handle_int(oidp, &new, 0, req);
2717 if (error || !req->newptr)
2718 return (error);
2719
2720 carp_demote_adj(new, "sysctl");
2721
2722 return (0);
2723 }
2724
2725 static int
nlattr_get_carp_key(struct nlattr * nla,struct nl_pstate * npt,const void * arg,void * target)2726 nlattr_get_carp_key(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target)
2727 {
2728 if (__predict_false(NLA_DATA_LEN(nla) > CARP_KEY_LEN))
2729 return (EINVAL);
2730
2731 memcpy(target, NLA_DATA_CONST(nla), NLA_DATA_LEN(nla));
2732 return (0);
2733 }
2734
2735 struct carp_nl_send_args {
2736 struct nlmsghdr *hdr;
2737 struct nl_pstate *npt;
2738 };
2739
2740 static bool
carp_nl_send(void * arg,struct carp_softc * sc,int priv)2741 carp_nl_send(void *arg, struct carp_softc *sc, int priv)
2742 {
2743 struct carp_nl_send_args *nlsa = arg;
2744 struct nlmsghdr *hdr = nlsa->hdr;
2745 struct nl_pstate *npt = nlsa->npt;
2746 struct nl_writer *nw = npt->nw;
2747 struct genlmsghdr *ghdr_new;
2748
2749 if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) {
2750 nlmsg_abort(nw);
2751 return (false);
2752 }
2753
2754 ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr);
2755 if (ghdr_new == NULL) {
2756 nlmsg_abort(nw);
2757 return (false);
2758 }
2759
2760 ghdr_new->cmd = CARP_NL_CMD_GET;
2761 ghdr_new->version = 0;
2762 ghdr_new->reserved = 0;
2763
2764 CARP_LOCK(sc);
2765
2766 nlattr_add_u32(nw, CARP_NL_VHID, sc->sc_vhid);
2767 nlattr_add_u32(nw, CARP_NL_STATE, sc->sc_state);
2768 nlattr_add_u8(nw, CARP_NL_VERSION, sc->sc_version);
2769 switch (sc->sc_version) {
2770 case CARP_VERSION_CARP:
2771 nlattr_add_s32(nw, CARP_NL_ADVBASE, sc->sc_advbase);
2772 nlattr_add_s32(nw, CARP_NL_ADVSKEW, sc->sc_advskew);
2773 nlattr_add_in_addr(nw, CARP_NL_ADDR, &sc->sc_carpaddr);
2774 nlattr_add_in6_addr(nw, CARP_NL_ADDR6, &sc->sc_carpaddr6);
2775 if (priv)
2776 nlattr_add(nw, CARP_NL_KEY, sizeof(sc->sc_key),
2777 sc->sc_key);
2778 break;
2779 case CARP_VERSION_VRRPv3:
2780 nlattr_add_u8(nw, CARP_NL_VRRP_PRIORITY, sc->sc_vrrp_prio);
2781 nlattr_add_u16(nw, CARP_NL_VRRP_ADV_INTER,
2782 sc->sc_vrrp_adv_inter);
2783 break;
2784 }
2785
2786 CARP_UNLOCK(sc);
2787
2788 if (! nlmsg_end(nw)) {
2789 nlmsg_abort(nw);
2790 return (false);
2791 }
2792
2793 return (true);
2794 }
2795
2796 struct nl_carp_parsed {
2797 unsigned int ifindex;
2798 char *ifname;
2799 uint32_t state;
2800 uint32_t vhid;
2801 int32_t advbase;
2802 int32_t advskew;
2803 char key[CARP_KEY_LEN];
2804 struct in_addr addr;
2805 struct in6_addr addr6;
2806 carp_version_t version;
2807 uint8_t vrrp_prio;
2808 uint16_t vrrp_adv_inter;
2809 };
2810
2811 #define _IN(_field) offsetof(struct genlmsghdr, _field)
2812 #define _OUT(_field) offsetof(struct nl_carp_parsed, _field)
2813
2814 static const struct nlattr_parser nla_p_set[] = {
2815 { .type = CARP_NL_VHID, .off = _OUT(vhid), .cb = nlattr_get_uint32 },
2816 { .type = CARP_NL_STATE, .off = _OUT(state), .cb = nlattr_get_uint32 },
2817 { .type = CARP_NL_ADVBASE, .off = _OUT(advbase), .cb = nlattr_get_uint32 },
2818 { .type = CARP_NL_ADVSKEW, .off = _OUT(advskew), .cb = nlattr_get_uint32 },
2819 { .type = CARP_NL_KEY, .off = _OUT(key), .cb = nlattr_get_carp_key },
2820 { .type = CARP_NL_IFINDEX, .off = _OUT(ifindex), .cb = nlattr_get_uint32 },
2821 { .type = CARP_NL_ADDR, .off = _OUT(addr), .cb = nlattr_get_in_addr },
2822 { .type = CARP_NL_ADDR6, .off = _OUT(addr6), .cb = nlattr_get_in6_addr },
2823 { .type = CARP_NL_IFNAME, .off = _OUT(ifname), .cb = nlattr_get_string },
2824 { .type = CARP_NL_VERSION, .off = _OUT(version), .cb = nlattr_get_uint8 },
2825 { .type = CARP_NL_VRRP_PRIORITY, .off = _OUT(vrrp_prio), .cb = nlattr_get_uint8 },
2826 { .type = CARP_NL_VRRP_ADV_INTER, .off = _OUT(vrrp_adv_inter), .cb = nlattr_get_uint16 },
2827 };
2828 static const struct nlfield_parser nlf_p_set[] = {
2829 };
2830 NL_DECLARE_PARSER(carp_parser, struct genlmsghdr, nlf_p_set, nla_p_set);
2831 #undef _IN
2832 #undef _OUT
2833
2834
2835 static int
carp_nl_get(struct nlmsghdr * hdr,struct nl_pstate * npt)2836 carp_nl_get(struct nlmsghdr *hdr, struct nl_pstate *npt)
2837 {
2838 struct nl_carp_parsed attrs = { };
2839 struct carp_nl_send_args args;
2840 struct carpreq carpr = { };
2841 struct epoch_tracker et;
2842 if_t ifp = NULL;
2843 int error;
2844
2845 error = nl_parse_nlmsg(hdr, &carp_parser, npt, &attrs);
2846 if (error != 0)
2847 return (error);
2848
2849 NET_EPOCH_ENTER(et);
2850 if (attrs.ifname != NULL)
2851 ifp = ifunit_ref(attrs.ifname);
2852 else if (attrs.ifindex != 0)
2853 ifp = ifnet_byindex_ref(attrs.ifindex);
2854 NET_EPOCH_EXIT(et);
2855
2856 if ((error = carp_is_supported_if(ifp)) != 0)
2857 goto out;
2858
2859 hdr->nlmsg_flags |= NLM_F_MULTI;
2860 args.hdr = hdr;
2861 args.npt = npt;
2862
2863 carpr.carpr_vhid = attrs.vhid;
2864 carpr.carpr_count = CARP_MAXVHID;
2865
2866 sx_xlock(&carp_sx);
2867 error = carp_ioctl_get(ifp, nlp_get_cred(npt->nlp), &carpr,
2868 carp_nl_send, &args);
2869 sx_xunlock(&carp_sx);
2870
2871 if (! nlmsg_end_dump(npt->nw, error, hdr))
2872 error = ENOMEM;
2873
2874 out:
2875 if (ifp != NULL)
2876 if_rele(ifp);
2877
2878 return (error);
2879 }
2880
2881 static int
carp_nl_set(struct nlmsghdr * hdr,struct nl_pstate * npt)2882 carp_nl_set(struct nlmsghdr *hdr, struct nl_pstate *npt)
2883 {
2884 struct nl_carp_parsed attrs = { };
2885 struct carpkreq carpr;
2886 struct epoch_tracker et;
2887 if_t ifp = NULL;
2888 int error;
2889
2890 error = nl_parse_nlmsg(hdr, &carp_parser, npt, &attrs);
2891 if (error != 0)
2892 return (error);
2893
2894 if (attrs.vhid <= 0 || attrs.vhid > CARP_MAXVHID)
2895 return (EINVAL);
2896 if (attrs.state > CARP_MAXSTATE)
2897 return (EINVAL);
2898 if (attrs.version == 0) /* compat with pre-VRRPv3 */
2899 attrs.version = CARP_VERSION_CARP;
2900 switch (attrs.version) {
2901 case CARP_VERSION_CARP:
2902 if (attrs.advbase < 0 || attrs.advskew < 0)
2903 return (EINVAL);
2904 if (attrs.advbase > 255)
2905 return (EINVAL);
2906 if (attrs.advskew >= 255)
2907 return (EINVAL);
2908 break;
2909 case CARP_VERSION_VRRPv3:
2910 if (attrs.vrrp_adv_inter > VRRP_MAX_INTERVAL)
2911 return (EINVAL);
2912 break;
2913 default:
2914 return (EINVAL);
2915 }
2916
2917 NET_EPOCH_ENTER(et);
2918 if (attrs.ifname != NULL)
2919 ifp = ifunit_ref(attrs.ifname);
2920 else if (attrs.ifindex != 0)
2921 ifp = ifnet_byindex_ref(attrs.ifindex);
2922 NET_EPOCH_EXIT(et);
2923
2924 if ((error = carp_is_supported_if(ifp)) != 0)
2925 goto out;
2926
2927 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
2928 error = EADDRNOTAVAIL;
2929 goto out;
2930 }
2931
2932 carpr.carpr_count = 1;
2933 carpr.carpr_vhid = attrs.vhid;
2934 carpr.carpr_state = attrs.state;
2935 carpr.carpr_version = attrs.version;
2936 switch (attrs.version) {
2937 case CARP_VERSION_CARP:
2938 carpr.carpr_advbase = attrs.advbase;
2939 carpr.carpr_advskew = attrs.advskew;
2940 carpr.carpr_addr = attrs.addr;
2941 carpr.carpr_addr6 = attrs.addr6;
2942 memcpy(&carpr.carpr_key, &attrs.key, sizeof(attrs.key));
2943 break;
2944 case CARP_VERSION_VRRPv3:
2945 carpr.carpr_vrrp_priority = attrs.vrrp_prio;
2946 carpr.carpr_vrrp_adv_inter = attrs.vrrp_adv_inter;
2947 break;
2948 }
2949
2950 sx_xlock(&carp_sx);
2951 error = carp_ioctl_set(ifp, &carpr);
2952 sx_xunlock(&carp_sx);
2953
2954 out:
2955 if (ifp != NULL)
2956 if_rele(ifp);
2957
2958 return (error);
2959 }
2960
2961 static const struct nlhdr_parser *all_parsers[] = {
2962 &carp_parser
2963 };
2964
2965 static const struct genl_cmd carp_cmds[] = {
2966 {
2967 .cmd_num = CARP_NL_CMD_GET,
2968 .cmd_name = "SIOCGVH",
2969 .cmd_cb = carp_nl_get,
2970 .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP |
2971 GENL_CMD_CAP_HASPOL,
2972 },
2973 {
2974 .cmd_num = CARP_NL_CMD_SET,
2975 .cmd_name = "SIOCSVH",
2976 .cmd_cb = carp_nl_set,
2977 .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL,
2978 .cmd_priv = PRIV_NETINET_CARP,
2979 },
2980 };
2981
2982 static void
carp_nl_register(void)2983 carp_nl_register(void)
2984 {
2985 bool ret __diagused;
2986 int family_id __diagused;
2987
2988 NL_VERIFY_PARSERS(all_parsers);
2989 family_id = genl_register_family(CARP_NL_FAMILY_NAME, 0, 2,
2990 CARP_NL_CMD_MAX);
2991 MPASS(family_id != 0);
2992
2993 ret = genl_register_cmds(CARP_NL_FAMILY_NAME, carp_cmds,
2994 NL_ARRAY_LEN(carp_cmds));
2995 MPASS(ret);
2996 }
2997
2998 static void
carp_nl_unregister(void)2999 carp_nl_unregister(void)
3000 {
3001 genl_unregister_family(CARP_NL_FAMILY_NAME);
3002 }
3003
3004 static void
carp_mod_cleanup(void)3005 carp_mod_cleanup(void)
3006 {
3007
3008 carp_nl_unregister();
3009
3010 #ifdef INET
3011 (void)ipproto_unregister(IPPROTO_CARP);
3012 carp_iamatch_p = NULL;
3013 #endif
3014 #ifdef INET6
3015 (void)ip6proto_unregister(IPPROTO_CARP);
3016 carp_iamatch6_p = NULL;
3017 carp_macmatch6_p = NULL;
3018 #endif
3019 carp_ioctl_p = NULL;
3020 carp_attach_p = NULL;
3021 carp_detach_p = NULL;
3022 carp_get_vhid_p = NULL;
3023 carp_linkstate_p = NULL;
3024 carp_forus_p = NULL;
3025 carp_output_p = NULL;
3026 carp_demote_adj_p = NULL;
3027 carp_master_p = NULL;
3028 mtx_unlock(&carp_mtx);
3029 taskqueue_drain(taskqueue_swi, &carp_sendall_task);
3030 mtx_destroy(&carp_mtx);
3031 sx_destroy(&carp_sx);
3032 }
3033
3034 static void
ipcarp_sysinit(void)3035 ipcarp_sysinit(void)
3036 {
3037
3038 /* Load allow as tunable so to postpone carp start after module load */
3039 TUNABLE_INT_FETCH("net.inet.carp.allow", &V_carp_allow);
3040 }
3041 VNET_SYSINIT(ip_carp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, ipcarp_sysinit, NULL);
3042
3043 static int
carp_mod_load(void)3044 carp_mod_load(void)
3045 {
3046 int err;
3047
3048 mtx_init(&carp_mtx, "carp_mtx", NULL, MTX_DEF);
3049 sx_init(&carp_sx, "carp_sx");
3050 LIST_INIT(&carp_list);
3051 carp_get_vhid_p = carp_get_vhid;
3052 carp_forus_p = carp_forus;
3053 carp_output_p = carp_output;
3054 carp_linkstate_p = carp_linkstate;
3055 carp_ioctl_p = carp_ioctl;
3056 carp_attach_p = carp_attach;
3057 carp_detach_p = carp_detach;
3058 carp_demote_adj_p = carp_demote_adj;
3059 carp_master_p = carp_master;
3060 #ifdef INET6
3061 carp_iamatch6_p = carp_iamatch6;
3062 carp_macmatch6_p = carp_macmatch6;
3063 err = ip6proto_register(IPPROTO_CARP, carp6_input, NULL);
3064 if (err) {
3065 printf("carp: error %d registering with INET6\n", err);
3066 carp_mod_cleanup();
3067 return (err);
3068 }
3069 #endif
3070 #ifdef INET
3071 carp_iamatch_p = carp_iamatch;
3072 err = ipproto_register(IPPROTO_CARP, carp_input, NULL);
3073 if (err) {
3074 printf("carp: error %d registering with INET\n", err);
3075 carp_mod_cleanup();
3076 return (err);
3077 }
3078 #endif
3079
3080 carp_nl_register();
3081
3082 return (0);
3083 }
3084
3085 static int
carp_modevent(module_t mod,int type,void * data)3086 carp_modevent(module_t mod, int type, void *data)
3087 {
3088 switch (type) {
3089 case MOD_LOAD:
3090 return carp_mod_load();
3091 /* NOTREACHED */
3092 case MOD_UNLOAD:
3093 mtx_lock(&carp_mtx);
3094 if (LIST_EMPTY(&carp_list))
3095 carp_mod_cleanup();
3096 else {
3097 mtx_unlock(&carp_mtx);
3098 return (EBUSY);
3099 }
3100 break;
3101
3102 default:
3103 return (EINVAL);
3104 }
3105
3106 return (0);
3107 }
3108
3109 static moduledata_t carp_mod = {
3110 "carp",
3111 carp_modevent,
3112 0
3113 };
3114
3115 DECLARE_MODULE(carp, carp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
3116