1 /* 2 * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 3 * Copyright (c) 2003 Ryan McBride. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 /* 27 * $FreeBSD: src/sys/netinet/ip_carp.c,v 1.48 2007/02/02 09:39:09 glebius Exp $ 28 */ 29 30 #include "opt_carp.h" 31 #include "opt_inet.h" 32 #include "opt_inet6.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/in_cksum.h> 38 #include <sys/limits.h> 39 #include <sys/malloc.h> 40 #include <sys/mbuf.h> 41 #include <sys/msgport2.h> 42 #include <sys/time.h> 43 #include <sys/proc.h> 44 #include <sys/priv.h> 45 #include <sys/sockio.h> 46 #include <sys/socket.h> 47 #include <sys/sysctl.h> 48 #include <sys/syslog.h> 49 #include <sys/thread.h> 50 51 #include <machine/stdarg.h> 52 #include <crypto/sha1.h> 53 54 #include <net/bpf.h> 55 #include <net/ethernet.h> 56 #include <net/if.h> 57 #include <net/if_dl.h> 58 #include <net/if_types.h> 59 #include <net/route.h> 60 #include <net/if_clone.h> 61 #include <net/if_var.h> 62 #include <net/ifq_var.h> 63 64 #ifdef INET 65 #include <netinet/in.h> 66 #include <netinet/in_var.h> 67 #include <netinet/in_systm.h> 68 #include <netinet/ip.h> 69 #include <netinet/ip_var.h> 70 #include <netinet/if_ether.h> 71 #endif 72 73 #ifdef INET6 74 #include <netinet/icmp6.h> 75 #include <netinet/ip6.h> 76 #include <netinet6/ip6_var.h> 77 #include <netinet6/scope6_var.h> 78 #include <netinet6/nd6.h> 79 #endif 80 81 #include <netinet/ip_carp.h> 82 83 #define CARP_IFNAME "carp" 84 #define CARP_IS_RUNNING(ifp) \ 85 (((ifp)->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) 86 87 struct carp_vhaddr { 88 uint32_t vha_flags; /* CARP_VHAF_ */ 89 struct in_ifaddr *vha_ia; /* carp address */ 90 struct in_ifaddr *vha_iaback; /* backing address */ 91 TAILQ_ENTRY(carp_vhaddr) vha_link; 92 }; 93 TAILQ_HEAD(carp_vhaddr_list, carp_vhaddr); 94 95 struct carp_softc { 96 struct arpcom arpcom; 97 struct ifnet *sc_carpdev; /* parent interface */ 98 struct carp_vhaddr_list sc_vha_list; /* virtual addr list */ 99 100 const struct in_ifaddr *sc_ia; /* primary iface address v4 */ 101 struct ip_moptions sc_imo; 102 103 #ifdef INET6 104 struct in6_ifaddr *sc_ia6; /* primary iface address v6 */ 105 struct ip6_moptions sc_im6o; 106 #endif /* INET6 */ 107 TAILQ_ENTRY(carp_softc) sc_list; 108 109 enum { INIT = 0, BACKUP, MASTER } 110 sc_state; 111 int sc_dead; 112 113 int sc_suppress; 114 115 int sc_sendad_errors; 116 #define CARP_SENDAD_MAX_ERRORS 3 117 int sc_sendad_success; 118 #define CARP_SENDAD_MIN_SUCCESS 3 119 120 int sc_vhid; 121 int sc_advskew; 122 int sc_naddrs; /* actually used IPv4 vha */ 123 int sc_naddrs6; 124 int sc_advbase; /* seconds */ 125 int sc_init_counter; 126 uint64_t sc_counter; 127 128 /* authentication */ 129 #define CARP_HMAC_PAD 64 130 unsigned char sc_key[CARP_KEY_LEN]; 131 unsigned char sc_pad[CARP_HMAC_PAD]; 132 SHA1_CTX sc_sha1; 133 134 struct callout sc_ad_tmo; /* advertisement timeout */ 135 struct callout sc_md_tmo; /* master down timeout */ 136 struct callout sc_md6_tmo; /* master down timeout */ 137 138 LIST_ENTRY(carp_softc) sc_next; /* Interface clue */ 139 }; 140 141 #define sc_if arpcom.ac_if 142 143 struct carp_if { 144 TAILQ_HEAD(, carp_softc) vhif_vrs; 145 }; 146 147 enum { CARP_COUNT_MASTER, CARP_COUNT_RUNNING }; 148 149 SYSCTL_DECL(_net_inet_carp); 150 151 static int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0 }; /* XXX for now */ 152 SYSCTL_INT(_net_inet_carp, CARPCTL_ALLOW, allow, CTLFLAG_RW, 153 &carp_opts[CARPCTL_ALLOW], 0, "Accept incoming CARP packets"); 154 SYSCTL_INT(_net_inet_carp, CARPCTL_PREEMPT, preempt, CTLFLAG_RW, 155 &carp_opts[CARPCTL_PREEMPT], 0, "high-priority backup preemption mode"); 156 SYSCTL_INT(_net_inet_carp, CARPCTL_LOG, log, CTLFLAG_RW, 157 &carp_opts[CARPCTL_LOG], 0, "log bad carp packets"); 158 SYSCTL_INT(_net_inet_carp, CARPCTL_ARPBALANCE, arpbalance, CTLFLAG_RW, 159 &carp_opts[CARPCTL_ARPBALANCE], 0, "balance arp responses"); 160 161 static int carp_suppress_preempt = 0; 162 SYSCTL_INT(_net_inet_carp, OID_AUTO, suppress_preempt, CTLFLAG_RD, 163 &carp_suppress_preempt, 0, "Preemption is suppressed"); 164 165 static struct carpstats carpstats; 166 SYSCTL_STRUCT(_net_inet_carp, CARPCTL_STATS, stats, CTLFLAG_RW, 167 &carpstats, carpstats, 168 "CARP statistics (struct carpstats, netinet/ip_carp.h)"); 169 170 #define CARP_LOG(...) do { \ 171 if (carp_opts[CARPCTL_LOG] > 0) \ 172 log(LOG_INFO, __VA_ARGS__); \ 173 } while (0) 174 175 #define CARP_DEBUG(...) do { \ 176 if (carp_opts[CARPCTL_LOG] > 1) \ 177 log(LOG_DEBUG, __VA_ARGS__); \ 178 } while (0) 179 180 static struct lwkt_token carp_tok = LWKT_TOKEN_INITIALIZER(carp_token); 181 182 static void carp_hmac_prepare(struct carp_softc *); 183 static void carp_hmac_generate(struct carp_softc *, uint32_t *, 184 unsigned char *); 185 static int carp_hmac_verify(struct carp_softc *, uint32_t *, 186 unsigned char *); 187 static void carp_setroute(struct carp_softc *, int); 188 static void carp_proto_input_c(struct carp_softc *, struct mbuf *, 189 struct carp_header *, sa_family_t); 190 static int carp_clone_create(struct if_clone *, int, caddr_t); 191 static int carp_clone_destroy(struct ifnet *); 192 static void carp_detach(struct carp_softc *, int, boolean_t); 193 static void carp_prepare_ad(struct carp_softc *, struct carp_header *); 194 static void carp_send_ad_all(void); 195 static void carp_send_ad_timeout(void *); 196 static void carp_send_ad(struct carp_softc *); 197 static void carp_send_arp(struct carp_softc *); 198 static void carp_master_down_timeout(void *); 199 static void carp_master_down(struct carp_softc *); 200 static void carp_setrun(struct carp_softc *, sa_family_t); 201 static void carp_set_state(struct carp_softc *, int); 202 static struct ifnet *carp_forus(struct carp_if *, const uint8_t *); 203 204 static void carp_init(void *); 205 static int carp_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 206 static int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, 207 struct rtentry *); 208 static void carp_start(struct ifnet *); 209 static void carp_serialize(struct ifnet *, enum ifnet_serialize); 210 static void carp_deserialize(struct ifnet *, enum ifnet_serialize); 211 static int carp_tryserialize(struct ifnet *, enum ifnet_serialize); 212 #ifdef INVARIANTS 213 static void carp_serialize_assert(struct ifnet *, enum ifnet_serialize, 214 boolean_t); 215 #endif 216 217 static void carp_multicast_cleanup(struct carp_softc *); 218 static void carp_add_addr(struct carp_softc *, struct ifaddr *); 219 static void carp_del_addr(struct carp_softc *, struct ifaddr *); 220 static void carp_config_addr(struct carp_softc *, struct ifaddr *); 221 static void carp_link_addrs(struct carp_softc *, struct ifnet *, 222 struct ifaddr *); 223 static void carp_unlink_addrs(struct carp_softc *, struct ifnet *, 224 struct ifaddr *); 225 static void carp_update_addrs(struct carp_softc *, struct ifaddr *); 226 227 static int carp_get_vhaddr(struct carp_softc *, struct ifdrv *); 228 static int carp_config_vhaddr(struct carp_softc *, struct carp_vhaddr *, 229 struct in_ifaddr *); 230 static int carp_activate_vhaddr(struct carp_softc *, struct carp_vhaddr *, 231 struct ifnet *, struct in_ifaddr *, int); 232 static void carp_deactivate_vhaddr(struct carp_softc *, 233 struct carp_vhaddr *, boolean_t); 234 static int carp_addroute_vhaddr(struct carp_softc *, struct carp_vhaddr *); 235 static void carp_delroute_vhaddr(struct carp_softc *, struct carp_vhaddr *, 236 boolean_t); 237 238 static void carp_sc_state(struct carp_softc *); 239 #ifdef INET6 240 static void carp_send_na(struct carp_softc *); 241 #ifdef notyet 242 static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); 243 static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); 244 #endif 245 static void carp_multicast6_cleanup(struct carp_softc *); 246 #endif 247 static void carp_stop(struct carp_softc *, int); 248 static void carp_suspend(struct carp_softc *, int); 249 250 static void carp_ifaddr(void *, struct ifnet *, enum ifaddr_event, 251 struct ifaddr *); 252 static void carp_ifdetach(void *, struct ifnet *); 253 254 static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces"); 255 256 static LIST_HEAD(, carp_softc) carpif_list; 257 258 static struct if_clone carp_cloner = 259 IF_CLONE_INITIALIZER(CARP_IFNAME, carp_clone_create, carp_clone_destroy, 260 0, IF_MAXUNIT); 261 262 static uint8_t carp_etheraddr[ETHER_ADDR_LEN] = { 0, 0, 0x5e, 0, 1, 0 }; 263 264 static eventhandler_tag carp_ifdetach_event; 265 static eventhandler_tag carp_ifaddr_event; 266 267 static __inline void 268 carp_insert_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha_new) 269 { 270 struct carp_vhaddr *vha; 271 u_long new_addr, addr; 272 273 KKASSERT((vha_new->vha_flags & CARP_VHAF_ONLIST) == 0); 274 275 /* 276 * Virtual address list is sorted; smaller one first 277 */ 278 new_addr = ntohl(vha_new->vha_ia->ia_addr.sin_addr.s_addr); 279 280 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 281 addr = ntohl(vha->vha_ia->ia_addr.sin_addr.s_addr); 282 283 if (addr > new_addr) 284 break; 285 } 286 if (vha == NULL) 287 TAILQ_INSERT_TAIL(&sc->sc_vha_list, vha_new, vha_link); 288 else 289 TAILQ_INSERT_BEFORE(vha, vha_new, vha_link); 290 vha_new->vha_flags |= CARP_VHAF_ONLIST; 291 } 292 293 static __inline void 294 carp_remove_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha) 295 { 296 KKASSERT(vha->vha_flags & CARP_VHAF_ONLIST); 297 vha->vha_flags &= ~CARP_VHAF_ONLIST; 298 TAILQ_REMOVE(&sc->sc_vha_list, vha, vha_link); 299 } 300 301 static void 302 carp_hmac_prepare(struct carp_softc *sc) 303 { 304 uint8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; 305 uint8_t vhid = sc->sc_vhid & 0xff; 306 int i; 307 #ifdef INET6 308 struct ifaddr_container *ifac; 309 struct in6_addr in6; 310 #endif 311 #ifdef INET 312 struct carp_vhaddr *vha; 313 #endif 314 315 /* XXX: possible race here */ 316 317 /* compute ipad from key */ 318 bzero(sc->sc_pad, sizeof(sc->sc_pad)); 319 bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key)); 320 for (i = 0; i < sizeof(sc->sc_pad); i++) 321 sc->sc_pad[i] ^= 0x36; 322 323 /* precompute first part of inner hash */ 324 SHA1Init(&sc->sc_sha1); 325 SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad)); 326 SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version)); 327 SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type)); 328 SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid)); 329 #ifdef INET 330 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 331 SHA1Update(&sc->sc_sha1, 332 (const uint8_t *)&vha->vha_ia->ia_addr.sin_addr, 333 sizeof(struct in_addr)); 334 } 335 #endif /* INET */ 336 #ifdef INET6 337 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], ifa_link) { 338 struct ifaddr *ifa = ifac->ifa; 339 340 if (ifa->ifa_addr->sa_family == AF_INET6) { 341 in6 = ifatoia6(ifa)->ia_addr.sin6_addr; 342 in6_clearscope(&in6); 343 SHA1Update(&sc->sc_sha1, (void *)&in6, sizeof(in6)); 344 } 345 } 346 #endif /* INET6 */ 347 348 /* convert ipad to opad */ 349 for (i = 0; i < sizeof(sc->sc_pad); i++) 350 sc->sc_pad[i] ^= 0x36 ^ 0x5c; 351 } 352 353 static void 354 carp_hmac_generate(struct carp_softc *sc, uint32_t counter[2], 355 unsigned char md[20]) 356 { 357 SHA1_CTX sha1ctx; 358 359 /* fetch first half of inner hash */ 360 bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)); 361 362 SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter)); 363 SHA1Final(md, &sha1ctx); 364 365 /* outer hash */ 366 SHA1Init(&sha1ctx); 367 SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad)); 368 SHA1Update(&sha1ctx, md, 20); 369 SHA1Final(md, &sha1ctx); 370 } 371 372 static int 373 carp_hmac_verify(struct carp_softc *sc, uint32_t counter[2], 374 unsigned char md[20]) 375 { 376 unsigned char md2[20]; 377 378 carp_hmac_generate(sc, counter, md2); 379 return (bcmp(md, md2, sizeof(md2))); 380 } 381 382 static void 383 carp_setroute(struct carp_softc *sc, int cmd) 384 { 385 #ifdef INET6 386 struct ifaddr_container *ifac; 387 #endif 388 struct carp_vhaddr *vha; 389 390 KKASSERT(cmd == RTM_DELETE || cmd == RTM_ADD); 391 392 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 393 if (vha->vha_iaback == NULL) 394 continue; 395 if (cmd == RTM_DELETE) 396 carp_delroute_vhaddr(sc, vha, FALSE); 397 else 398 carp_addroute_vhaddr(sc, vha); 399 } 400 401 #ifdef INET6 402 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], ifa_link) { 403 struct ifaddr *ifa = ifac->ifa; 404 405 if (ifa->ifa_addr->sa_family == AF_INET6) { 406 if (cmd == RTM_ADD) 407 in6_ifaddloop(ifa); 408 else 409 in6_ifremloop(ifa); 410 } 411 } 412 #endif /* INET6 */ 413 } 414 415 static int 416 carp_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused) 417 { 418 struct carp_softc *sc; 419 struct ifnet *ifp; 420 421 sc = kmalloc(sizeof(*sc), M_CARP, M_WAITOK | M_ZERO); 422 ifp = &sc->sc_if; 423 424 sc->sc_suppress = 0; 425 sc->sc_advbase = CARP_DFLTINTV; 426 sc->sc_vhid = -1; /* required setting */ 427 sc->sc_advskew = 0; 428 sc->sc_init_counter = 1; 429 sc->sc_naddrs = 0; 430 sc->sc_naddrs6 = 0; 431 432 TAILQ_INIT(&sc->sc_vha_list); 433 434 #ifdef INET6 435 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; 436 #endif 437 438 callout_init_mp(&sc->sc_ad_tmo); 439 callout_init_mp(&sc->sc_md_tmo); 440 callout_init_mp(&sc->sc_md6_tmo); 441 442 if_initname(ifp, CARP_IFNAME, unit); 443 ifp->if_softc = sc; 444 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 445 ifp->if_init = carp_init; 446 ifp->if_ioctl = carp_ioctl; 447 ifp->if_start = carp_start; 448 ifp->if_serialize = carp_serialize; 449 ifp->if_deserialize = carp_deserialize; 450 ifp->if_tryserialize = carp_tryserialize; 451 #ifdef INVARIANTS 452 ifp->if_serialize_assert = carp_serialize_assert; 453 #endif 454 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); 455 ifq_set_ready(&ifp->if_snd); 456 457 ether_ifattach(ifp, carp_etheraddr, NULL); 458 459 ifp->if_type = IFT_CARP; 460 ifp->if_output = carp_output; 461 462 carp_gettok(); 463 LIST_INSERT_HEAD(&carpif_list, sc, sc_next); 464 carp_reltok(); 465 466 return (0); 467 } 468 469 static int 470 carp_clone_destroy(struct ifnet *ifp) 471 { 472 struct carp_softc *sc = ifp->if_softc; 473 474 carp_gettok(); 475 476 sc->sc_dead = 1; 477 carp_detach(sc, 1, FALSE); 478 LIST_REMOVE(sc, sc_next); 479 480 carp_reltok(); 481 482 bpfdetach(ifp); 483 if_detach(ifp); 484 485 KASSERT(sc->sc_naddrs == 0, ("certain inet address is still active\n")); 486 kfree(sc, M_CARP); 487 488 return 0; 489 } 490 491 static void 492 carp_detach(struct carp_softc *sc, int detach, boolean_t del_iaback) 493 { 494 struct carp_if *cif; 495 496 carp_suspend(sc, detach); 497 498 carp_multicast_cleanup(sc); 499 #ifdef INET6 500 carp_multicast6_cleanup(sc); 501 #endif 502 503 if (!sc->sc_dead && detach) { 504 struct carp_vhaddr *vha; 505 506 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 507 carp_deactivate_vhaddr(sc, vha, del_iaback); 508 KKASSERT(sc->sc_naddrs == 0); 509 } 510 511 if (sc->sc_carpdev != NULL) { 512 cif = sc->sc_carpdev->if_carp; 513 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); 514 if (TAILQ_EMPTY(&cif->vhif_vrs)) { 515 ifpromisc(sc->sc_carpdev, 0); 516 sc->sc_carpdev->if_carp = NULL; 517 kfree(cif, M_CARP); 518 } 519 sc->sc_carpdev = NULL; 520 sc->sc_ia = NULL; 521 } 522 } 523 524 /* Detach an interface from the carp. */ 525 static void 526 carp_ifdetach(void *arg __unused, struct ifnet *ifp) 527 { 528 struct carp_if *cif = ifp->if_carp; 529 struct carp_softc *sc; 530 531 carp_gettok(); 532 533 while (ifp->if_carp && 534 (sc = TAILQ_FIRST(&cif->vhif_vrs)) != NULL) 535 carp_detach(sc, 1, TRUE); 536 537 carp_reltok(); 538 } 539 540 /* 541 * process input packet. 542 * we have rearranged checks order compared to the rfc, 543 * but it seems more efficient this way or not possible otherwise. 544 */ 545 int 546 carp_proto_input(struct mbuf **mp, int *offp, int proto) 547 { 548 struct mbuf *m = *mp; 549 struct ip *ip = mtod(m, struct ip *); 550 struct ifnet *ifp = m->m_pkthdr.rcvif; 551 struct carp_header *ch; 552 struct carp_softc *sc; 553 int len, iphlen; 554 555 carp_gettok(); 556 557 iphlen = *offp; 558 *mp = NULL; 559 560 carpstats.carps_ipackets++; 561 562 if (!carp_opts[CARPCTL_ALLOW]) { 563 m_freem(m); 564 goto back; 565 } 566 567 /* Check if received on a valid carp interface */ 568 if (ifp->if_type != IFT_CARP) { 569 carpstats.carps_badif++; 570 CARP_LOG("carp_proto_input: packet received on non-carp " 571 "interface: %s\n", ifp->if_xname); 572 m_freem(m); 573 goto back; 574 } 575 576 if (!CARP_IS_RUNNING(ifp)) { 577 carpstats.carps_badif++; 578 CARP_LOG("carp_proto_input: packet received on stopped carp " 579 "interface: %s\n", ifp->if_xname); 580 m_freem(m); 581 goto back; 582 } 583 584 sc = ifp->if_softc; 585 if (sc->sc_carpdev == NULL) { 586 carpstats.carps_badif++; 587 CARP_LOG("carp_proto_input: packet received on defunc carp " 588 "interface: %s\n", ifp->if_xname); 589 m_freem(m); 590 goto back; 591 } 592 593 if (!IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { 594 carpstats.carps_badif++; 595 CARP_LOG("carp_proto_input: non-mcast packet on " 596 "interface: %s\n", ifp->if_xname); 597 m_freem(m); 598 goto back; 599 } 600 601 /* Verify that the IP TTL is CARP_DFLTTL. */ 602 if (ip->ip_ttl != CARP_DFLTTL) { 603 carpstats.carps_badttl++; 604 CARP_LOG("carp_proto_input: received ttl %d != %d on %s\n", 605 ip->ip_ttl, CARP_DFLTTL, ifp->if_xname); 606 m_freem(m); 607 goto back; 608 } 609 610 /* Minimal CARP packet size */ 611 len = iphlen + sizeof(*ch); 612 613 /* 614 * Verify that the received packet length is 615 * not less than the CARP header 616 */ 617 if (m->m_pkthdr.len < len) { 618 carpstats.carps_badlen++; 619 CARP_LOG("packet too short %d on %s\n", m->m_pkthdr.len, 620 ifp->if_xname); 621 m_freem(m); 622 goto back; 623 } 624 625 /* Make sure that CARP header is contiguous */ 626 if (len > m->m_len) { 627 m = m_pullup(m, len); 628 if (m == NULL) { 629 carpstats.carps_hdrops++; 630 CARP_LOG("carp_proto_input: m_pullup failed\n"); 631 goto back; 632 } 633 ip = mtod(m, struct ip *); 634 } 635 ch = (struct carp_header *)((uint8_t *)ip + iphlen); 636 637 /* Verify the CARP checksum */ 638 if (in_cksum_skip(m, len, iphlen)) { 639 carpstats.carps_badsum++; 640 CARP_LOG("carp_proto_input: checksum failed on %s\n", 641 ifp->if_xname); 642 m_freem(m); 643 goto back; 644 } 645 carp_proto_input_c(sc, m, ch, AF_INET); 646 back: 647 carp_reltok(); 648 return(IPPROTO_DONE); 649 } 650 651 #ifdef INET6 652 int 653 carp6_proto_input(struct mbuf **mp, int *offp, int proto) 654 { 655 struct mbuf *m = *mp; 656 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 657 struct ifnet *ifp = m->m_pkthdr.rcvif; 658 struct carp_header *ch; 659 struct carp_softc *sc; 660 u_int len; 661 662 carp_gettok(); 663 664 carpstats.carps_ipackets6++; 665 666 if (!carp_opts[CARPCTL_ALLOW]) { 667 m_freem(m); 668 goto back; 669 } 670 671 /* check if received on a valid carp interface */ 672 if (ifp->if_type != IFT_CARP) { 673 carpstats.carps_badif++; 674 CARP_LOG("carp6_proto_input: packet received on non-carp " 675 "interface: %s\n", ifp->if_xname); 676 m_freem(m); 677 goto back; 678 } 679 680 if (!CARP_IS_RUNNING(ifp)) { 681 carpstats.carps_badif++; 682 CARP_LOG("carp_proto_input: packet received on stopped carp " 683 "interface: %s\n", ifp->if_xname); 684 m_freem(m); 685 goto back; 686 } 687 688 sc = ifp->if_softc; 689 if (sc->sc_carpdev == NULL) { 690 carpstats.carps_badif++; 691 CARP_LOG("carp6_proto_input: packet received on defunc-carp " 692 "interface: %s\n", ifp->if_xname); 693 m_freem(m); 694 goto back; 695 } 696 697 /* verify that the IP TTL is 255 */ 698 if (ip6->ip6_hlim != CARP_DFLTTL) { 699 carpstats.carps_badttl++; 700 CARP_LOG("carp6_proto_input: received ttl %d != 255 on %s\n", 701 ip6->ip6_hlim, ifp->if_xname); 702 m_freem(m); 703 goto back; 704 } 705 706 /* verify that we have a complete carp packet */ 707 len = m->m_len; 708 IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); 709 if (ch == NULL) { 710 carpstats.carps_badlen++; 711 CARP_LOG("carp6_proto_input: packet size %u too small\n", len); 712 goto back; 713 } 714 715 /* verify the CARP checksum */ 716 if (in_cksum_range(m, 0, *offp, sizeof(*ch))) { 717 carpstats.carps_badsum++; 718 CARP_LOG("carp6_proto_input: checksum failed, on %s\n", 719 ifp->if_xname); 720 m_freem(m); 721 goto back; 722 } 723 724 carp_proto_input_c(sc, m, ch, AF_INET6); 725 back: 726 carp_reltok(); 727 return (IPPROTO_DONE); 728 } 729 #endif /* INET6 */ 730 731 static void 732 carp_proto_input_c(struct carp_softc *sc, struct mbuf *m, 733 struct carp_header *ch, sa_family_t af) 734 { 735 struct ifnet *cifp; 736 uint64_t tmp_counter; 737 struct timeval sc_tv, ch_tv; 738 739 if (sc->sc_vhid != ch->carp_vhid) { 740 /* 741 * CARP uses multicast, however, multicast packets 742 * are tapped to all CARP interfaces on the physical 743 * interface receiving the CARP packets, so we don't 744 * update any stats here. 745 */ 746 m_freem(m); 747 return; 748 } 749 cifp = &sc->sc_if; 750 751 /* verify the CARP version. */ 752 if (ch->carp_version != CARP_VERSION) { 753 carpstats.carps_badver++; 754 CARP_LOG("%s; invalid version %d\n", cifp->if_xname, 755 ch->carp_version); 756 m_freem(m); 757 return; 758 } 759 760 /* verify the hash */ 761 if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) { 762 carpstats.carps_badauth++; 763 CARP_LOG("%s: incorrect hash\n", cifp->if_xname); 764 m_freem(m); 765 return; 766 } 767 768 tmp_counter = ntohl(ch->carp_counter[0]); 769 tmp_counter = tmp_counter<<32; 770 tmp_counter += ntohl(ch->carp_counter[1]); 771 772 /* XXX Replay protection goes here */ 773 774 sc->sc_init_counter = 0; 775 sc->sc_counter = tmp_counter; 776 777 sc_tv.tv_sec = sc->sc_advbase; 778 if (carp_suppress_preempt && sc->sc_advskew < 240) 779 sc_tv.tv_usec = 240 * 1000000 / 256; 780 else 781 sc_tv.tv_usec = sc->sc_advskew * 1000000 / 256; 782 ch_tv.tv_sec = ch->carp_advbase; 783 ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; 784 785 switch (sc->sc_state) { 786 case INIT: 787 break; 788 789 case MASTER: 790 /* 791 * If we receive an advertisement from a master who's going to 792 * be more frequent than us, go into BACKUP state. 793 */ 794 if (timevalcmp(&sc_tv, &ch_tv, >) || 795 timevalcmp(&sc_tv, &ch_tv, ==)) { 796 callout_stop(&sc->sc_ad_tmo); 797 CARP_DEBUG("%s: MASTER -> BACKUP " 798 "(more frequent advertisement received)\n", 799 cifp->if_xname); 800 carp_set_state(sc, BACKUP); 801 carp_setrun(sc, 0); 802 carp_setroute(sc, RTM_DELETE); 803 } 804 break; 805 806 case BACKUP: 807 /* 808 * If we're pre-empting masters who advertise slower than us, 809 * and this one claims to be slower, treat him as down. 810 */ 811 if (carp_opts[CARPCTL_PREEMPT] && 812 timevalcmp(&sc_tv, &ch_tv, <)) { 813 CARP_DEBUG("%s: BACKUP -> MASTER " 814 "(preempting a slower master)\n", cifp->if_xname); 815 carp_master_down(sc); 816 break; 817 } 818 819 /* 820 * If the master is going to advertise at such a low frequency 821 * that he's guaranteed to time out, we'd might as well just 822 * treat him as timed out now. 823 */ 824 sc_tv.tv_sec = sc->sc_advbase * 3; 825 if (timevalcmp(&sc_tv, &ch_tv, <)) { 826 CARP_DEBUG("%s: BACKUP -> MASTER (master timed out)\n", 827 cifp->if_xname); 828 carp_master_down(sc); 829 break; 830 } 831 832 /* 833 * Otherwise, we reset the counter and wait for the next 834 * advertisement. 835 */ 836 carp_setrun(sc, af); 837 break; 838 } 839 m_freem(m); 840 } 841 842 struct mbuf * 843 carp_input(void *v, struct mbuf *m) 844 { 845 struct carp_if *cif = v; 846 struct ether_header *eh; 847 struct carp_softc *sc; 848 struct ifnet *ifp; 849 850 ASSERT_LWKT_TOKEN_HELD(&carp_tok); 851 852 eh = mtod(m, struct ether_header *); 853 854 ifp = carp_forus(cif, eh->ether_dhost); 855 if (ifp != NULL) { 856 ether_reinput_oncpu(ifp, m, REINPUT_RUNBPF); 857 return NULL; 858 } 859 860 if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) 861 return m; 862 863 /* 864 * XXX Should really check the list of multicast addresses 865 * for each CARP interface _before_ copying. 866 */ 867 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { 868 struct mbuf *m0; 869 870 if ((sc->sc_if.if_flags & IFF_UP) == 0) 871 continue; 872 873 m0 = m_dup(m, MB_DONTWAIT); 874 if (m0 == NULL) 875 continue; 876 877 ether_reinput_oncpu(&sc->sc_if, m0, REINPUT_RUNBPF); 878 } 879 return m; 880 } 881 882 static void 883 carp_prepare_ad(struct carp_softc *sc, struct carp_header *ch) 884 { 885 if (sc->sc_init_counter) { 886 /* this could also be seconds since unix epoch */ 887 sc->sc_counter = karc4random(); 888 sc->sc_counter = sc->sc_counter << 32; 889 sc->sc_counter += karc4random(); 890 } else { 891 sc->sc_counter++; 892 } 893 894 ch->carp_counter[0] = htonl((sc->sc_counter >> 32) & 0xffffffff); 895 ch->carp_counter[1] = htonl(sc->sc_counter & 0xffffffff); 896 897 carp_hmac_generate(sc, ch->carp_counter, ch->carp_md); 898 } 899 900 static void 901 carp_send_ad_all(void) 902 { 903 struct carp_softc *sc; 904 905 LIST_FOREACH(sc, &carpif_list, sc_next) { 906 if (sc->sc_carpdev == NULL) 907 continue; 908 909 if (CARP_IS_RUNNING(&sc->sc_if) && sc->sc_state == MASTER) 910 carp_send_ad(sc); 911 } 912 } 913 914 static void 915 carp_send_ad_timeout(void *xsc) 916 { 917 carp_gettok(); 918 carp_send_ad(xsc); 919 carp_reltok(); 920 } 921 922 static void 923 carp_send_ad(struct carp_softc *sc) 924 { 925 struct ifnet *cifp = &sc->sc_if; 926 struct carp_header ch; 927 struct timeval tv; 928 struct carp_header *ch_ptr; 929 struct mbuf *m; 930 int len, advbase, advskew; 931 932 if (!CARP_IS_RUNNING(cifp)) { 933 /* Bow out */ 934 advbase = 255; 935 advskew = 255; 936 } else { 937 advbase = sc->sc_advbase; 938 if (!carp_suppress_preempt || sc->sc_advskew > 240) 939 advskew = sc->sc_advskew; 940 else 941 advskew = 240; 942 tv.tv_sec = advbase; 943 tv.tv_usec = advskew * 1000000 / 256; 944 } 945 946 ch.carp_version = CARP_VERSION; 947 ch.carp_type = CARP_ADVERTISEMENT; 948 ch.carp_vhid = sc->sc_vhid; 949 ch.carp_advbase = advbase; 950 ch.carp_advskew = advskew; 951 ch.carp_authlen = 7; /* XXX DEFINE */ 952 ch.carp_pad1 = 0; /* must be zero */ 953 ch.carp_cksum = 0; 954 955 #ifdef INET 956 if (sc->sc_ia != NULL) { 957 struct ip *ip; 958 959 MGETHDR(m, MB_DONTWAIT, MT_HEADER); 960 if (m == NULL) { 961 cifp->if_oerrors++; 962 carpstats.carps_onomem++; 963 /* XXX maybe less ? */ 964 if (advbase != 255 || advskew != 255) 965 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 966 carp_send_ad_timeout, sc); 967 return; 968 } 969 len = sizeof(*ip) + sizeof(ch); 970 m->m_pkthdr.len = len; 971 m->m_pkthdr.rcvif = NULL; 972 m->m_len = len; 973 MH_ALIGN(m, m->m_len); 974 m->m_flags |= M_MCAST; 975 ip = mtod(m, struct ip *); 976 ip->ip_v = IPVERSION; 977 ip->ip_hl = sizeof(*ip) >> 2; 978 ip->ip_tos = IPTOS_LOWDELAY; 979 ip->ip_len = len; 980 ip->ip_id = ip_newid(); 981 ip->ip_off = IP_DF; 982 ip->ip_ttl = CARP_DFLTTL; 983 ip->ip_p = IPPROTO_CARP; 984 ip->ip_sum = 0; 985 ip->ip_src = sc->sc_ia->ia_addr.sin_addr; 986 ip->ip_dst.s_addr = htonl(INADDR_CARP_GROUP); 987 988 ch_ptr = (struct carp_header *)(&ip[1]); 989 bcopy(&ch, ch_ptr, sizeof(ch)); 990 carp_prepare_ad(sc, ch_ptr); 991 ch_ptr->carp_cksum = in_cksum_skip(m, len, sizeof(*ip)); 992 993 getmicrotime(&cifp->if_lastchange); 994 cifp->if_opackets++; 995 cifp->if_obytes += len; 996 carpstats.carps_opackets++; 997 998 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) { 999 cifp->if_oerrors++; 1000 if (sc->sc_sendad_errors < INT_MAX) 1001 sc->sc_sendad_errors++; 1002 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { 1003 carp_suppress_preempt++; 1004 if (carp_suppress_preempt == 1) { 1005 carp_send_ad_all(); 1006 } 1007 } 1008 sc->sc_sendad_success = 0; 1009 } else { 1010 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) { 1011 if (++sc->sc_sendad_success >= 1012 CARP_SENDAD_MIN_SUCCESS) { 1013 carp_suppress_preempt--; 1014 sc->sc_sendad_errors = 0; 1015 } 1016 } else { 1017 sc->sc_sendad_errors = 0; 1018 } 1019 } 1020 } 1021 #endif /* INET */ 1022 #ifdef INET6 1023 if (sc->sc_ia6) { 1024 struct ip6_hdr *ip6; 1025 1026 MGETHDR(m, MB_DONTWAIT, MT_HEADER); 1027 if (m == NULL) { 1028 cifp->if_oerrors++; 1029 carpstats.carps_onomem++; 1030 /* XXX maybe less ? */ 1031 if (advbase != 255 || advskew != 255) 1032 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1033 carp_send_ad_timeout, sc); 1034 return; 1035 } 1036 len = sizeof(*ip6) + sizeof(ch); 1037 m->m_pkthdr.len = len; 1038 m->m_pkthdr.rcvif = NULL; 1039 m->m_len = len; 1040 MH_ALIGN(m, m->m_len); 1041 m->m_flags |= M_MCAST; 1042 ip6 = mtod(m, struct ip6_hdr *); 1043 bzero(ip6, sizeof(*ip6)); 1044 ip6->ip6_vfc |= IPV6_VERSION; 1045 ip6->ip6_hlim = CARP_DFLTTL; 1046 ip6->ip6_nxt = IPPROTO_CARP; 1047 bcopy(&sc->sc_ia6->ia_addr.sin6_addr, &ip6->ip6_src, 1048 sizeof(struct in6_addr)); 1049 /* set the multicast destination */ 1050 1051 ip6->ip6_dst.s6_addr16[0] = htons(0xff02); 1052 ip6->ip6_dst.s6_addr8[15] = 0x12; 1053 if (in6_setscope(&ip6->ip6_dst, sc->sc_carpdev, NULL) != 0) { 1054 cifp->if_oerrors++; 1055 m_freem(m); 1056 CARP_LOG("%s: in6_setscope failed\n", __func__); 1057 return; 1058 } 1059 1060 ch_ptr = (struct carp_header *)(&ip6[1]); 1061 bcopy(&ch, ch_ptr, sizeof(ch)); 1062 carp_prepare_ad(sc, ch_ptr); 1063 ch_ptr->carp_cksum = in_cksum_skip(m, len, sizeof(*ip6)); 1064 1065 getmicrotime(&cifp->if_lastchange); 1066 cifp->if_opackets++; 1067 cifp->if_obytes += len; 1068 carpstats.carps_opackets6++; 1069 1070 if (ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL, NULL)) { 1071 cifp->if_oerrors++; 1072 if (sc->sc_sendad_errors < INT_MAX) 1073 sc->sc_sendad_errors++; 1074 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { 1075 carp_suppress_preempt++; 1076 if (carp_suppress_preempt == 1) { 1077 carp_send_ad_all(); 1078 } 1079 } 1080 sc->sc_sendad_success = 0; 1081 } else { 1082 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) { 1083 if (++sc->sc_sendad_success >= 1084 CARP_SENDAD_MIN_SUCCESS) { 1085 carp_suppress_preempt--; 1086 sc->sc_sendad_errors = 0; 1087 } 1088 } else { 1089 sc->sc_sendad_errors = 0; 1090 } 1091 } 1092 } 1093 #endif /* INET6 */ 1094 1095 if (advbase != 255 || advskew != 255) 1096 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1097 carp_send_ad_timeout, sc); 1098 } 1099 1100 /* 1101 * Broadcast a gratuitous ARP request containing 1102 * the virtual router MAC address for each IP address 1103 * associated with the virtual router. 1104 */ 1105 static void 1106 carp_send_arp(struct carp_softc *sc) 1107 { 1108 const struct carp_vhaddr *vha; 1109 1110 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1111 if (vha->vha_iaback == NULL) 1112 continue; 1113 arp_gratuitous(&sc->sc_if, &vha->vha_ia->ia_ifa); 1114 } 1115 } 1116 1117 #ifdef INET6 1118 static void 1119 carp_send_na(struct carp_softc *sc) 1120 { 1121 struct ifaddr_container *ifac; 1122 struct in6_addr *in6; 1123 static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; 1124 1125 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], ifa_link) { 1126 struct ifaddr *ifa = ifac->ifa; 1127 1128 if (ifa->ifa_addr->sa_family != AF_INET6) 1129 continue; 1130 1131 in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; 1132 nd6_na_output(sc->sc_carpdev, &mcast, in6, 1133 ND_NA_FLAG_OVERRIDE, 1, NULL); 1134 DELAY(1000); /* XXX */ 1135 } 1136 } 1137 #endif /* INET6 */ 1138 1139 static __inline const struct carp_vhaddr * 1140 carp_find_addr(const struct carp_softc *sc, const struct in_addr *addr) 1141 { 1142 struct carp_vhaddr *vha; 1143 1144 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1145 if (vha->vha_iaback == NULL) 1146 continue; 1147 1148 if (vha->vha_ia->ia_addr.sin_addr.s_addr == addr->s_addr) 1149 return vha; 1150 } 1151 return NULL; 1152 } 1153 1154 #ifdef notyet 1155 static int 1156 carp_iamatch_balance(const struct carp_if *cif, const struct in_addr *itaddr, 1157 const struct in_addr *isaddr, uint8_t **enaddr) 1158 { 1159 const struct carp_softc *vh; 1160 int index, count = 0; 1161 1162 /* 1163 * XXX proof of concept implementation. 1164 * We use the source ip to decide which virtual host should 1165 * handle the request. If we're master of that virtual host, 1166 * then we respond, otherwise, just drop the arp packet on 1167 * the floor. 1168 */ 1169 1170 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1171 if (!CARP_IS_RUNNING(&vh->sc_if)) 1172 continue; 1173 1174 if (carp_find_addr(vh, itaddr) != NULL) 1175 count++; 1176 } 1177 if (count == 0) 1178 return 0; 1179 1180 /* this should be a hash, like pf_hash() */ 1181 index = ntohl(isaddr->s_addr) % count; 1182 count = 0; 1183 1184 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1185 if (!CARP_IS_RUNNING(&vh->sc_if)) 1186 continue; 1187 1188 if (carp_find_addr(vh, itaddr) == NULL) 1189 continue; 1190 1191 if (count == index) { 1192 if (vh->sc_state == MASTER) { 1193 *enaddr = IF_LLADDR(&vh->sc_if); 1194 return 1; 1195 } else { 1196 return 0; 1197 } 1198 } 1199 count++; 1200 } 1201 return 0; 1202 } 1203 #endif 1204 1205 int 1206 carp_iamatch(const struct in_ifaddr *ia) 1207 { 1208 const struct carp_softc *sc = ia->ia_ifp->if_softc; 1209 1210 ASSERT_LWKT_TOKEN_HELD(&carp_tok); 1211 1212 #ifdef notyet 1213 if (carp_opts[CARPCTL_ARPBALANCE]) 1214 return carp_iamatch_balance(cif, itaddr, isaddr, enaddr); 1215 #endif 1216 1217 if (!CARP_IS_RUNNING(&sc->sc_if) || sc->sc_state != MASTER) 1218 return 0; 1219 1220 return 1; 1221 } 1222 1223 #ifdef INET6 1224 struct ifaddr * 1225 carp_iamatch6(void *v, struct in6_addr *taddr) 1226 { 1227 struct carp_if *cif = v; 1228 struct carp_softc *vh; 1229 1230 ASSERT_LWKT_TOKEN_HELD(&carp_tok); 1231 1232 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1233 struct ifaddr_container *ifac; 1234 1235 TAILQ_FOREACH(ifac, &vh->sc_if.if_addrheads[mycpuid], 1236 ifa_link) { 1237 struct ifaddr *ifa = ifac->ifa; 1238 1239 if (IN6_ARE_ADDR_EQUAL(taddr, 1240 &ifatoia6(ifa)->ia_addr.sin6_addr) && 1241 CARP_IS_RUNNING(&vh->sc_if) && 1242 vh->sc_state == MASTER) { 1243 return (ifa); 1244 } 1245 } 1246 } 1247 return (NULL); 1248 } 1249 1250 void * 1251 carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) 1252 { 1253 struct m_tag *mtag; 1254 struct carp_if *cif = v; 1255 struct carp_softc *sc; 1256 1257 ASSERT_LWKT_TOKEN_HELD(&carp_tok); 1258 1259 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { 1260 struct ifaddr_container *ifac; 1261 1262 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], 1263 ifa_link) { 1264 struct ifaddr *ifa = ifac->ifa; 1265 1266 if (IN6_ARE_ADDR_EQUAL(taddr, 1267 &ifatoia6(ifa)->ia_addr.sin6_addr) && 1268 CARP_IS_RUNNING(&sc->sc_if)) { 1269 struct ifnet *ifp = &sc->sc_if; 1270 1271 mtag = m_tag_get(PACKET_TAG_CARP, 1272 sizeof(struct ifnet *), MB_DONTWAIT); 1273 if (mtag == NULL) { 1274 /* better a bit than nothing */ 1275 return (IF_LLADDR(ifp)); 1276 } 1277 bcopy(&ifp, (caddr_t)(mtag + 1), 1278 sizeof(struct ifnet *)); 1279 m_tag_prepend(m, mtag); 1280 1281 return (IF_LLADDR(ifp)); 1282 } 1283 } 1284 } 1285 return (NULL); 1286 } 1287 #endif 1288 1289 static struct ifnet * 1290 carp_forus(struct carp_if *cif, const uint8_t *dhost) 1291 { 1292 struct carp_softc *sc; 1293 1294 ASSERT_LWKT_TOKEN_HELD(&carp_tok); 1295 1296 if (memcmp(dhost, carp_etheraddr, ETHER_ADDR_LEN - 1) != 0) 1297 return NULL; 1298 1299 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { 1300 struct ifnet *ifp = &sc->sc_if; 1301 1302 if (CARP_IS_RUNNING(ifp) && sc->sc_state == MASTER && 1303 !bcmp(dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN)) 1304 return ifp; 1305 } 1306 return NULL; 1307 } 1308 1309 static void 1310 carp_master_down_timeout(void *xsc) 1311 { 1312 struct carp_softc *sc = xsc; 1313 1314 CARP_DEBUG("%s: BACKUP -> MASTER (master timed out)\n", 1315 sc->sc_if.if_xname); 1316 carp_gettok(); 1317 carp_master_down(sc); 1318 carp_reltok(); 1319 } 1320 1321 static void 1322 carp_master_down(struct carp_softc *sc) 1323 { 1324 switch (sc->sc_state) { 1325 case INIT: 1326 kprintf("%s: master_down event in INIT state\n", 1327 sc->sc_if.if_xname); 1328 break; 1329 1330 case MASTER: 1331 break; 1332 1333 case BACKUP: 1334 carp_set_state(sc, MASTER); 1335 carp_send_ad(sc); 1336 carp_send_arp(sc); 1337 #ifdef INET6 1338 carp_send_na(sc); 1339 #endif /* INET6 */ 1340 carp_setrun(sc, 0); 1341 carp_setroute(sc, RTM_ADD); 1342 break; 1343 } 1344 } 1345 1346 /* 1347 * When in backup state, af indicates whether to reset the master down timer 1348 * for v4 or v6. If it's set to zero, reset the ones which are already pending. 1349 */ 1350 static void 1351 carp_setrun(struct carp_softc *sc, sa_family_t af) 1352 { 1353 struct ifnet *cifp = &sc->sc_if; 1354 struct timeval tv; 1355 1356 if (sc->sc_carpdev == NULL) { 1357 carp_set_state(sc, INIT); 1358 return; 1359 } 1360 1361 if ((cifp->if_flags & IFF_RUNNING) && sc->sc_vhid > 0 && 1362 (sc->sc_naddrs || sc->sc_naddrs6)) { 1363 /* Nothing */ 1364 } else { 1365 carp_setroute(sc, RTM_DELETE); 1366 return; 1367 } 1368 1369 switch (sc->sc_state) { 1370 case INIT: 1371 if (carp_opts[CARPCTL_PREEMPT] && !carp_suppress_preempt) { 1372 carp_send_ad(sc); 1373 carp_send_arp(sc); 1374 #ifdef INET6 1375 carp_send_na(sc); 1376 #endif /* INET6 */ 1377 CARP_DEBUG("%s: INIT -> MASTER (preempting)\n", 1378 cifp->if_xname); 1379 carp_set_state(sc, MASTER); 1380 carp_setroute(sc, RTM_ADD); 1381 } else { 1382 CARP_DEBUG("%s: INIT -> BACKUP\n", cifp->if_xname); 1383 carp_set_state(sc, BACKUP); 1384 carp_setroute(sc, RTM_DELETE); 1385 carp_setrun(sc, 0); 1386 } 1387 break; 1388 1389 case BACKUP: 1390 callout_stop(&sc->sc_ad_tmo); 1391 tv.tv_sec = 3 * sc->sc_advbase; 1392 tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1393 switch (af) { 1394 #ifdef INET 1395 case AF_INET: 1396 callout_reset(&sc->sc_md_tmo, tvtohz_high(&tv), 1397 carp_master_down_timeout, sc); 1398 break; 1399 #endif /* INET */ 1400 #ifdef INET6 1401 case AF_INET6: 1402 callout_reset(&sc->sc_md6_tmo, tvtohz_high(&tv), 1403 carp_master_down_timeout, sc); 1404 break; 1405 #endif /* INET6 */ 1406 default: 1407 if (sc->sc_naddrs) 1408 callout_reset(&sc->sc_md_tmo, tvtohz_high(&tv), 1409 carp_master_down_timeout, sc); 1410 if (sc->sc_naddrs6) 1411 callout_reset(&sc->sc_md6_tmo, tvtohz_high(&tv), 1412 carp_master_down_timeout, sc); 1413 break; 1414 } 1415 break; 1416 1417 case MASTER: 1418 tv.tv_sec = sc->sc_advbase; 1419 tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1420 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1421 carp_send_ad_timeout, sc); 1422 break; 1423 } 1424 } 1425 1426 static void 1427 carp_multicast_cleanup(struct carp_softc *sc) 1428 { 1429 struct ip_moptions *imo = &sc->sc_imo; 1430 1431 if (imo->imo_num_memberships == 0) 1432 return; 1433 KKASSERT(imo->imo_num_memberships == 1); 1434 1435 in_delmulti(imo->imo_membership[0]); 1436 imo->imo_membership[0] = NULL; 1437 imo->imo_num_memberships = 0; 1438 imo->imo_multicast_ifp = NULL; 1439 } 1440 1441 #ifdef INET6 1442 static void 1443 carp_multicast6_cleanup(struct carp_softc *sc) 1444 { 1445 struct ip6_moptions *im6o = &sc->sc_im6o; 1446 1447 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 1448 struct in6_multi_mship *imm = 1449 LIST_FIRST(&im6o->im6o_memberships); 1450 1451 LIST_REMOVE(imm, i6mm_chain); 1452 in6_leavegroup(imm); 1453 } 1454 im6o->im6o_multicast_ifp = NULL; 1455 } 1456 #endif 1457 1458 static int 1459 carp_get_vhaddr(struct carp_softc *sc, struct ifdrv *ifd) 1460 { 1461 const struct carp_vhaddr *vha; 1462 struct ifcarpvhaddr *carpa, *carpa0; 1463 int count, len, error; 1464 1465 count = 0; 1466 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 1467 ++count; 1468 1469 if (ifd->ifd_len == 0) { 1470 ifd->ifd_len = count * sizeof(*carpa); 1471 return 0; 1472 } else if (count == 0 || ifd->ifd_len < sizeof(*carpa)) { 1473 ifd->ifd_len = 0; 1474 return 0; 1475 } 1476 len = min(ifd->ifd_len, sizeof(*carpa) * count); 1477 KKASSERT(len >= sizeof(*carpa)); 1478 1479 carpa0 = carpa = kmalloc(len, M_TEMP, M_WAITOK | M_NULLOK | M_ZERO); 1480 if (carpa == NULL) 1481 return ENOMEM; 1482 1483 count = 0; 1484 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1485 if (len < sizeof(*carpa)) 1486 break; 1487 1488 carpa->carpa_flags = vha->vha_flags; 1489 carpa->carpa_addr.sin_family = AF_INET; 1490 carpa->carpa_addr.sin_addr = vha->vha_ia->ia_addr.sin_addr; 1491 1492 carpa->carpa_baddr.sin_family = AF_INET; 1493 if (vha->vha_iaback == NULL) { 1494 carpa->carpa_baddr.sin_addr.s_addr = INADDR_ANY; 1495 } else { 1496 carpa->carpa_baddr.sin_addr = 1497 vha->vha_iaback->ia_addr.sin_addr; 1498 } 1499 1500 ++carpa; 1501 ++count; 1502 len -= sizeof(*carpa); 1503 } 1504 ifd->ifd_len = sizeof(*carpa) * count; 1505 KKASSERT(ifd->ifd_len > 0); 1506 1507 error = copyout(carpa0, ifd->ifd_data, ifd->ifd_len); 1508 kfree(carpa0, M_TEMP); 1509 return error; 1510 } 1511 1512 static int 1513 carp_config_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 1514 struct in_ifaddr *ia_del) 1515 { 1516 struct ifnet *ifp; 1517 struct in_ifaddr *ia_if; 1518 struct in_ifaddr_container *iac; 1519 const struct sockaddr_in *sin; 1520 u_long iaddr; 1521 int own; 1522 1523 KKASSERT(vha->vha_ia != NULL); 1524 1525 sin = &vha->vha_ia->ia_addr; 1526 iaddr = ntohl(sin->sin_addr.s_addr); 1527 1528 ia_if = NULL; 1529 own = 0; 1530 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 1531 struct in_ifaddr *ia = iac->ia; 1532 1533 if (ia == ia_del) 1534 continue; 1535 1536 if (ia->ia_ifp->if_type == IFT_CARP) 1537 continue; 1538 1539 if ((ia->ia_ifp->if_flags & IFF_UP) == 0) 1540 continue; 1541 1542 /* and, yeah, we need a multicast-capable iface too */ 1543 if ((ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) 1544 continue; 1545 1546 if ((iaddr & ia->ia_subnetmask) == ia->ia_subnet) { 1547 if (sin->sin_addr.s_addr == 1548 ia->ia_addr.sin_addr.s_addr) 1549 own = 1; 1550 if (ia_if == NULL) 1551 ia_if = ia; 1552 else if (sc->sc_carpdev != NULL && 1553 sc->sc_carpdev == ia->ia_ifp) 1554 ia_if = ia; 1555 } 1556 } 1557 1558 carp_deactivate_vhaddr(sc, vha, FALSE); 1559 if (!ia_if) 1560 return ENOENT; 1561 1562 ifp = ia_if->ia_ifp; 1563 1564 /* XXX Don't allow parent iface to be changed */ 1565 if (sc->sc_carpdev != NULL && sc->sc_carpdev != ifp) 1566 return EEXIST; 1567 1568 return carp_activate_vhaddr(sc, vha, ifp, ia_if, own); 1569 } 1570 1571 static void 1572 carp_add_addr(struct carp_softc *sc, struct ifaddr *carp_ifa) 1573 { 1574 struct carp_vhaddr *vha_new; 1575 struct in_ifaddr *carp_ia; 1576 #ifdef INVARIANTS 1577 struct carp_vhaddr *vha; 1578 #endif 1579 1580 KKASSERT(carp_ifa->ifa_addr->sa_family == AF_INET); 1581 carp_ia = ifatoia(carp_ifa); 1582 1583 #ifdef INVARIANTS 1584 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 1585 KKASSERT(vha->vha_ia != NULL && vha->vha_ia != carp_ia); 1586 #endif 1587 1588 vha_new = kmalloc(sizeof(*vha_new), M_CARP, M_WAITOK | M_ZERO); 1589 vha_new->vha_ia = carp_ia; 1590 carp_insert_vhaddr(sc, vha_new); 1591 1592 if (carp_config_vhaddr(sc, vha_new, NULL) != 0) { 1593 /* 1594 * If the above configuration fails, it may only mean 1595 * that the new address is problematic. However, the 1596 * carp(4) interface may already have several working 1597 * addresses. Since the expected behaviour of 1598 * SIOC[AS]IFADDR is to put the NIC into working state, 1599 * we try starting the state machine manually here with 1600 * the hope that the carp(4)'s previously working 1601 * addresses still could be brought up. 1602 */ 1603 carp_hmac_prepare(sc); 1604 carp_set_state(sc, INIT); 1605 carp_setrun(sc, 0); 1606 } 1607 } 1608 1609 static void 1610 carp_del_addr(struct carp_softc *sc, struct ifaddr *carp_ifa) 1611 { 1612 struct carp_vhaddr *vha; 1613 struct in_ifaddr *carp_ia; 1614 1615 KKASSERT(carp_ifa->ifa_addr->sa_family == AF_INET); 1616 carp_ia = ifatoia(carp_ifa); 1617 1618 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1619 KKASSERT(vha->vha_ia != NULL); 1620 if (vha->vha_ia == carp_ia) 1621 break; 1622 } 1623 KASSERT(vha != NULL, ("no corresponding vhaddr %p\n", carp_ifa)); 1624 1625 /* 1626 * Remove the vhaddr from the list before deactivating 1627 * the vhaddr, so that the HMAC could be correctly 1628 * updated in carp_deactivate_vhaddr() 1629 */ 1630 carp_remove_vhaddr(sc, vha); 1631 1632 carp_deactivate_vhaddr(sc, vha, FALSE); 1633 kfree(vha, M_CARP); 1634 } 1635 1636 static void 1637 carp_config_addr(struct carp_softc *sc, struct ifaddr *carp_ifa) 1638 { 1639 struct carp_vhaddr *vha; 1640 struct in_ifaddr *carp_ia; 1641 1642 KKASSERT(carp_ifa->ifa_addr->sa_family == AF_INET); 1643 carp_ia = ifatoia(carp_ifa); 1644 1645 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1646 KKASSERT(vha->vha_ia != NULL); 1647 if (vha->vha_ia == carp_ia) 1648 break; 1649 } 1650 KASSERT(vha != NULL, ("no corresponding vhaddr %p\n", carp_ifa)); 1651 1652 /* Remove then reinsert, to keep the vhaddr list sorted */ 1653 carp_remove_vhaddr(sc, vha); 1654 carp_insert_vhaddr(sc, vha); 1655 1656 if (carp_config_vhaddr(sc, vha, NULL) != 0) { 1657 /* See the comment in carp_add_addr() */ 1658 carp_hmac_prepare(sc); 1659 carp_set_state(sc, INIT); 1660 carp_setrun(sc, 0); 1661 } 1662 } 1663 1664 #ifdef notyet 1665 1666 #ifdef INET6 1667 static int 1668 carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) 1669 { 1670 struct ifnet *ifp; 1671 struct carp_if *cif; 1672 struct in6_ifaddr *ia, *ia_if; 1673 struct ip6_moptions *im6o = &sc->sc_im6o; 1674 struct in6_multi_mship *imm; 1675 struct in6_addr in6; 1676 int own, error; 1677 1678 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1679 carp_setrun(sc, 0); 1680 return (0); 1681 } 1682 1683 /* we have to do it by hands to check we won't match on us */ 1684 ia_if = NULL; own = 0; 1685 for (ia = in6_ifaddr; ia; ia = ia->ia_next) { 1686 int i; 1687 1688 for (i = 0; i < 4; i++) { 1689 if ((sin6->sin6_addr.s6_addr32[i] & 1690 ia->ia_prefixmask.sin6_addr.s6_addr32[i]) != 1691 (ia->ia_addr.sin6_addr.s6_addr32[i] & 1692 ia->ia_prefixmask.sin6_addr.s6_addr32[i])) 1693 break; 1694 } 1695 /* and, yeah, we need a multicast-capable iface too */ 1696 if (ia->ia_ifp != &sc->sc_if && 1697 (ia->ia_ifp->if_flags & IFF_MULTICAST) && 1698 (i == 4)) { 1699 if (!ia_if) 1700 ia_if = ia; 1701 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 1702 &ia->ia_addr.sin6_addr)) 1703 own++; 1704 } 1705 } 1706 1707 if (!ia_if) 1708 return (EADDRNOTAVAIL); 1709 ia = ia_if; 1710 ifp = ia->ia_ifp; 1711 1712 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 || 1713 (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp)) 1714 return (EADDRNOTAVAIL); 1715 1716 if (!sc->sc_naddrs6) { 1717 im6o->im6o_multicast_ifp = ifp; 1718 1719 /* join CARP multicast address */ 1720 bzero(&in6, sizeof(in6)); 1721 in6.s6_addr16[0] = htons(0xff02); 1722 in6.s6_addr8[15] = 0x12; 1723 if (in6_setscope(&in6, ifp, NULL) != 0) 1724 goto cleanup; 1725 if ((imm = in6_joingroup(ifp, &in6, &error)) == NULL) 1726 goto cleanup; 1727 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); 1728 1729 /* join solicited multicast address */ 1730 bzero(&in6, sizeof(in6)); 1731 in6.s6_addr16[0] = htons(0xff02); 1732 in6.s6_addr32[1] = 0; 1733 in6.s6_addr32[2] = htonl(1); 1734 in6.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3]; 1735 in6.s6_addr8[12] = 0xff; 1736 if (in6_setscope(&in6, ifp, NULL) != 0) 1737 goto cleanup; 1738 if ((imm = in6_joingroup(ifp, &in6, &error)) == NULL) 1739 goto cleanup; 1740 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); 1741 } 1742 1743 if (!ifp->if_carp) { 1744 cif = kmalloc(sizeof(*cif), M_CARP, M_WAITOK | M_ZERO); 1745 1746 if ((error = ifpromisc(ifp, 1))) { 1747 kfree(cif, M_CARP); 1748 goto cleanup; 1749 } 1750 1751 TAILQ_INIT(&cif->vhif_vrs); 1752 ifp->if_carp = cif; 1753 } else { 1754 struct carp_softc *vr; 1755 1756 cif = ifp->if_carp; 1757 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 1758 if (vr != sc && vr->sc_vhid == sc->sc_vhid) { 1759 error = EINVAL; 1760 goto cleanup; 1761 } 1762 } 1763 } 1764 sc->sc_ia6 = ia; 1765 sc->sc_carpdev = ifp; 1766 1767 { /* XXX prevent endless loop if already in queue */ 1768 struct carp_softc *vr, *after = NULL; 1769 int myself = 0; 1770 cif = ifp->if_carp; 1771 1772 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 1773 if (vr == sc) 1774 myself = 1; 1775 if (vr->sc_vhid < sc->sc_vhid) 1776 after = vr; 1777 } 1778 1779 if (!myself) { 1780 /* We're trying to keep things in order */ 1781 if (after == NULL) 1782 TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); 1783 else 1784 TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); 1785 } 1786 } 1787 1788 sc->sc_naddrs6++; 1789 if (own) 1790 sc->sc_advskew = 0; 1791 carp_sc_state(sc); 1792 carp_setrun(sc, 0); 1793 1794 return (0); 1795 1796 cleanup: 1797 /* clean up multicast memberships */ 1798 if (!sc->sc_naddrs6) { 1799 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 1800 imm = LIST_FIRST(&im6o->im6o_memberships); 1801 LIST_REMOVE(imm, i6mm_chain); 1802 in6_leavegroup(imm); 1803 } 1804 } 1805 return (error); 1806 } 1807 1808 static int 1809 carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) 1810 { 1811 int error = 0; 1812 1813 if (!--sc->sc_naddrs6) { 1814 struct carp_if *cif = sc->sc_carpdev->if_carp; 1815 struct ip6_moptions *im6o = &sc->sc_im6o; 1816 1817 callout_stop(&sc->sc_ad_tmo); 1818 sc->sc_vhid = -1; 1819 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 1820 struct in6_multi_mship *imm = 1821 LIST_FIRST(&im6o->im6o_memberships); 1822 1823 LIST_REMOVE(imm, i6mm_chain); 1824 in6_leavegroup(imm); 1825 } 1826 im6o->im6o_multicast_ifp = NULL; 1827 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); 1828 if (TAILQ_EMPTY(&cif->vhif_vrs)) { 1829 sc->sc_carpdev->if_carp = NULL; 1830 kfree(cif, M_IFADDR); 1831 } 1832 } 1833 return (error); 1834 } 1835 #endif /* INET6 */ 1836 1837 #endif 1838 1839 static int 1840 carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr, struct ucred *cr) 1841 { 1842 struct carp_softc *sc = ifp->if_softc, *vr; 1843 struct carpreq carpr; 1844 struct ifaddr *ifa; 1845 struct ifreq *ifr; 1846 struct ifaliasreq *ifra; 1847 struct ifdrv *ifd; 1848 char devname[IFNAMSIZ]; 1849 int error = 0; 1850 1851 carp_gettok(); 1852 1853 ifa = (struct ifaddr *)addr; 1854 ifra = (struct ifaliasreq *)addr; 1855 ifr = (struct ifreq *)addr; 1856 ifd = (struct ifdrv *)addr; 1857 1858 switch (cmd) { 1859 case SIOCSIFFLAGS: 1860 if (ifp->if_flags & IFF_UP) { 1861 if ((ifp->if_flags & IFF_RUNNING) == 0) 1862 carp_init(sc); 1863 } else if (ifp->if_flags & IFF_RUNNING) { 1864 carp_stop(sc, 0); 1865 } 1866 break; 1867 1868 case SIOCSVH: 1869 error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY); 1870 if (error) 1871 break; 1872 error = copyin(ifr->ifr_data, &carpr, sizeof(carpr)); 1873 if (error) 1874 break; 1875 1876 error = 1; 1877 if ((ifp->if_flags & IFF_RUNNING) && 1878 sc->sc_state != INIT && carpr.carpr_state != sc->sc_state) { 1879 switch (carpr.carpr_state) { 1880 case BACKUP: 1881 callout_stop(&sc->sc_ad_tmo); 1882 carp_set_state(sc, BACKUP); 1883 carp_setrun(sc, 0); 1884 carp_setroute(sc, RTM_DELETE); 1885 break; 1886 1887 case MASTER: 1888 carp_master_down(sc); 1889 break; 1890 1891 default: 1892 break; 1893 } 1894 } 1895 if (carpr.carpr_vhid > 0) { 1896 if (carpr.carpr_vhid > 255) { 1897 error = EINVAL; 1898 break; 1899 } 1900 if (sc->sc_carpdev) { 1901 struct carp_if *cif = sc->sc_carpdev->if_carp; 1902 1903 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 1904 if (vr != sc && 1905 vr->sc_vhid == carpr.carpr_vhid) { 1906 carp_reltok(); 1907 return EEXIST; 1908 } 1909 } 1910 } 1911 sc->sc_vhid = carpr.carpr_vhid; 1912 1913 IF_LLADDR(ifp)[5] = sc->sc_vhid; 1914 bcopy(IF_LLADDR(ifp), sc->arpcom.ac_enaddr, 1915 ETHER_ADDR_LEN); 1916 1917 error--; 1918 } 1919 if (carpr.carpr_advbase > 0 || carpr.carpr_advskew > 0) { 1920 if (carpr.carpr_advskew >= 255) { 1921 error = EINVAL; 1922 break; 1923 } 1924 if (carpr.carpr_advbase > 255) { 1925 error = EINVAL; 1926 break; 1927 } 1928 sc->sc_advbase = carpr.carpr_advbase; 1929 sc->sc_advskew = carpr.carpr_advskew; 1930 error--; 1931 } 1932 bcopy(carpr.carpr_key, sc->sc_key, sizeof(sc->sc_key)); 1933 if (error > 0) { 1934 error = EINVAL; 1935 } else { 1936 error = 0; 1937 carp_setrun(sc, 0); 1938 } 1939 break; 1940 1941 case SIOCGVH: 1942 bzero(&carpr, sizeof(carpr)); 1943 carpr.carpr_state = sc->sc_state; 1944 carpr.carpr_vhid = sc->sc_vhid; 1945 carpr.carpr_advbase = sc->sc_advbase; 1946 carpr.carpr_advskew = sc->sc_advskew; 1947 error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY); 1948 if (error == 0) { 1949 bcopy(sc->sc_key, carpr.carpr_key, 1950 sizeof(carpr.carpr_key)); 1951 } 1952 1953 error = copyout(&carpr, ifr->ifr_data, sizeof(carpr)); 1954 break; 1955 1956 case SIOCGDRVSPEC: 1957 switch (ifd->ifd_cmd) { 1958 case CARPGDEVNAME: 1959 if (ifd->ifd_len != sizeof(devname)) 1960 error = EINVAL; 1961 break; 1962 1963 case CARPGVHADDR: 1964 break; 1965 1966 default: 1967 error = EINVAL; 1968 break; 1969 } 1970 if (error) 1971 break; 1972 1973 switch (ifd->ifd_cmd) { 1974 case CARPGVHADDR: 1975 error = carp_get_vhaddr(sc, ifd); 1976 break; 1977 1978 case CARPGDEVNAME: 1979 bzero(devname, sizeof(devname)); 1980 if (sc->sc_carpdev != NULL) { 1981 strlcpy(devname, sc->sc_carpdev->if_xname, 1982 sizeof(devname)); 1983 } 1984 error = copyout(devname, ifd->ifd_data, 1985 sizeof(devname)); 1986 break; 1987 } 1988 break; 1989 1990 default: 1991 error = ether_ioctl(ifp, cmd, addr); 1992 break; 1993 } 1994 carp_hmac_prepare(sc); 1995 1996 carp_reltok(); 1997 return error; 1998 } 1999 2000 static void 2001 carp_init(void *xsc) 2002 { 2003 struct carp_softc *sc = xsc; 2004 2005 carp_gettok(); 2006 2007 sc->sc_if.if_flags |= IFF_RUNNING; 2008 carp_set_state(sc, INIT); 2009 carp_setrun(sc, 0); 2010 2011 carp_reltok(); 2012 } 2013 2014 static int 2015 carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 2016 struct rtentry *rt) 2017 { 2018 struct carp_softc *sc = ifp->if_softc; 2019 int error = 0; 2020 2021 carp_gettok(); 2022 if (sc->sc_carpdev) { 2023 /* 2024 * NOTE: 2025 * CARP's ifp is passed to backing device's 2026 * if_output method. 2027 */ 2028 sc->sc_carpdev->if_output(ifp, m, dst, rt); 2029 } else { 2030 m_freem(m); 2031 error = ENETUNREACH; 2032 } 2033 carp_reltok(); 2034 2035 return error; 2036 } 2037 2038 /* 2039 * Start output on carp interface. This function should never be called. 2040 */ 2041 static void 2042 carp_start(struct ifnet *ifp) 2043 { 2044 panic("%s: start called\n", ifp->if_xname); 2045 } 2046 2047 static void 2048 carp_serialize(struct ifnet *ifp __unused, 2049 enum ifnet_serialize slz __unused) 2050 { 2051 } 2052 2053 static void 2054 carp_deserialize(struct ifnet *ifp __unused, 2055 enum ifnet_serialize slz __unused) 2056 { 2057 } 2058 2059 static int 2060 carp_tryserialize(struct ifnet *ifp __unused, 2061 enum ifnet_serialize slz __unused) 2062 { 2063 return 1; 2064 } 2065 2066 #ifdef INVARIANTS 2067 2068 static void 2069 carp_serialize_assert(struct ifnet *ifp __unused, 2070 enum ifnet_serialize slz __unused, boolean_t serialized __unused) 2071 { 2072 } 2073 2074 #endif /* INVARIANTS */ 2075 2076 static void 2077 carp_set_state(struct carp_softc *sc, int state) 2078 { 2079 struct ifnet *cifp = &sc->sc_if; 2080 2081 if (sc->sc_state == state) 2082 return; 2083 sc->sc_state = state; 2084 2085 switch (sc->sc_state) { 2086 case BACKUP: 2087 cifp->if_link_state = LINK_STATE_DOWN; 2088 break; 2089 2090 case MASTER: 2091 cifp->if_link_state = LINK_STATE_UP; 2092 break; 2093 2094 default: 2095 cifp->if_link_state = LINK_STATE_UNKNOWN; 2096 break; 2097 } 2098 rt_ifmsg(cifp); 2099 } 2100 2101 void 2102 carp_group_demote_adj(struct ifnet *ifp, int adj) 2103 { 2104 struct ifg_list *ifgl; 2105 int *dm; 2106 2107 carp_gettok(); 2108 2109 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { 2110 if (!strcmp(ifgl->ifgl_group->ifg_group, IFG_ALL)) 2111 continue; 2112 dm = &ifgl->ifgl_group->ifg_carp_demoted; 2113 2114 if (*dm + adj >= 0) 2115 *dm += adj; 2116 else 2117 *dm = 0; 2118 2119 if (adj > 0 && *dm == 1) 2120 carp_send_ad_all(); 2121 CARP_LOG("%s demoted group %s to %d", ifp->if_xname, 2122 ifgl->ifgl_group->ifg_group, *dm); 2123 } 2124 2125 carp_reltok(); 2126 } 2127 2128 void 2129 carp_carpdev_state(void *v) 2130 { 2131 struct carp_if *cif = v; 2132 struct carp_softc *sc; 2133 2134 carp_gettok(); 2135 2136 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) 2137 carp_sc_state(sc); 2138 2139 carp_reltok(); 2140 } 2141 2142 static void 2143 carp_sc_state(struct carp_softc *sc) 2144 { 2145 if (!(sc->sc_carpdev->if_flags & IFF_UP)) { 2146 callout_stop(&sc->sc_ad_tmo); 2147 callout_stop(&sc->sc_md_tmo); 2148 callout_stop(&sc->sc_md6_tmo); 2149 carp_set_state(sc, INIT); 2150 carp_setrun(sc, 0); 2151 if (!sc->sc_suppress) { 2152 carp_suppress_preempt++; 2153 if (carp_suppress_preempt == 1) 2154 carp_send_ad_all(); 2155 } 2156 sc->sc_suppress = 1; 2157 } else { 2158 carp_set_state(sc, INIT); 2159 carp_setrun(sc, 0); 2160 if (sc->sc_suppress) 2161 carp_suppress_preempt--; 2162 sc->sc_suppress = 0; 2163 } 2164 } 2165 2166 static void 2167 carp_stop(struct carp_softc *sc, int detach) 2168 { 2169 sc->sc_if.if_flags &= ~IFF_RUNNING; 2170 2171 callout_stop(&sc->sc_ad_tmo); 2172 callout_stop(&sc->sc_md_tmo); 2173 callout_stop(&sc->sc_md6_tmo); 2174 2175 if (!detach && sc->sc_state == MASTER) 2176 carp_send_ad(sc); 2177 2178 if (sc->sc_suppress) 2179 carp_suppress_preempt--; 2180 sc->sc_suppress = 0; 2181 2182 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) 2183 carp_suppress_preempt--; 2184 sc->sc_sendad_errors = 0; 2185 sc->sc_sendad_success = 0; 2186 2187 carp_set_state(sc, INIT); 2188 carp_setrun(sc, 0); 2189 } 2190 2191 static void 2192 carp_suspend(struct carp_softc *sc, int detach) 2193 { 2194 struct ifnet *cifp = &sc->sc_if; 2195 2196 carp_stop(sc, detach); 2197 2198 /* Retain the running state, if we are not dead yet */ 2199 if (!sc->sc_dead && (cifp->if_flags & IFF_UP)) 2200 cifp->if_flags |= IFF_RUNNING; 2201 } 2202 2203 static int 2204 carp_activate_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 2205 struct ifnet *ifp, struct in_ifaddr *ia_if, int own) 2206 { 2207 struct ip_moptions *imo = &sc->sc_imo; 2208 struct carp_if *cif; 2209 struct carp_softc *vr, *after = NULL; 2210 int onlist, error; 2211 #ifdef INVARIANTS 2212 int assert_onlist; 2213 #endif 2214 2215 KKASSERT(vha->vha_ia != NULL); 2216 2217 KASSERT(ia_if != NULL, ("NULL backing address\n")); 2218 KASSERT(vha->vha_iaback == NULL, ("%p is already activated\n", vha)); 2219 KASSERT((vha->vha_flags & CARP_VHAF_OWNER) == 0, 2220 ("inactive vhaddr %p is the address owner\n", vha)); 2221 2222 KASSERT(sc->sc_carpdev == NULL || sc->sc_carpdev == ifp, 2223 ("%s is already on %s\n", sc->sc_if.if_xname, 2224 sc->sc_carpdev->if_xname)); 2225 2226 if (!ifp->if_carp) { 2227 KASSERT(sc->sc_carpdev == NULL, 2228 ("%s is already on %s\n", sc->sc_if.if_xname, 2229 sc->sc_carpdev->if_xname)); 2230 2231 cif = kmalloc(sizeof(*cif), M_CARP, M_WAITOK | M_ZERO); 2232 2233 error = ifpromisc(ifp, 1); 2234 if (error) { 2235 kfree(cif, M_CARP); 2236 return error; 2237 } 2238 2239 TAILQ_INIT(&cif->vhif_vrs); 2240 ifp->if_carp = cif; 2241 } else { 2242 cif = ifp->if_carp; 2243 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 2244 if (vr != sc && vr->sc_vhid == sc->sc_vhid) 2245 return EINVAL; 2246 } 2247 } 2248 2249 #ifdef INVARIANTS 2250 if (sc->sc_carpdev != NULL) 2251 assert_onlist = 1; 2252 else 2253 assert_onlist = 0; 2254 #endif 2255 sc->sc_ia = ia_if; 2256 sc->sc_carpdev = ifp; 2257 2258 cif = ifp->if_carp; 2259 onlist = 0; 2260 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 2261 if (vr == sc) 2262 onlist = 1; 2263 if (vr->sc_vhid < sc->sc_vhid) 2264 after = vr; 2265 } 2266 2267 #ifdef INVARIANTS 2268 if (assert_onlist) { 2269 KASSERT(onlist, ("%s is not on %s carp list\n", 2270 sc->sc_if.if_xname, ifp->if_xname)); 2271 } else { 2272 KASSERT(!onlist, ("%s is already on %s carp list\n", 2273 sc->sc_if.if_xname, ifp->if_xname)); 2274 } 2275 #endif 2276 2277 if (!onlist) { 2278 /* We're trying to keep things in order */ 2279 if (after == NULL) 2280 TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); 2281 else 2282 TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); 2283 } 2284 2285 vha->vha_iaback = ia_if; 2286 sc->sc_naddrs++; 2287 2288 if (own) { 2289 vha->vha_flags |= CARP_VHAF_OWNER; 2290 2291 /* XXX save user configured advskew? */ 2292 sc->sc_advskew = 0; 2293 } 2294 2295 carp_addroute_vhaddr(sc, vha); 2296 2297 /* 2298 * Join the multicast group only after the backing interface 2299 * has been hooked with the CARP interface. 2300 */ 2301 KASSERT(imo->imo_multicast_ifp == NULL || 2302 imo->imo_multicast_ifp == &sc->sc_if, 2303 ("%s didn't leave mcast group on %s\n", 2304 sc->sc_if.if_xname, imo->imo_multicast_ifp->if_xname)); 2305 2306 if (imo->imo_num_memberships == 0) { 2307 struct in_addr addr; 2308 2309 addr.s_addr = htonl(INADDR_CARP_GROUP); 2310 imo->imo_membership[0] = in_addmulti(&addr, &sc->sc_if); 2311 if (imo->imo_membership[0] == NULL) { 2312 carp_deactivate_vhaddr(sc, vha, FALSE); 2313 return ENOBUFS; 2314 } 2315 2316 imo->imo_num_memberships++; 2317 imo->imo_multicast_ifp = &sc->sc_if; 2318 imo->imo_multicast_ttl = CARP_DFLTTL; 2319 imo->imo_multicast_loop = 0; 2320 } 2321 2322 carp_hmac_prepare(sc); 2323 carp_set_state(sc, INIT); 2324 carp_setrun(sc, 0); 2325 return 0; 2326 } 2327 2328 static void 2329 carp_deactivate_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 2330 boolean_t del_iaback) 2331 { 2332 KKASSERT(vha->vha_ia != NULL); 2333 2334 carp_hmac_prepare(sc); 2335 2336 if (vha->vha_iaback == NULL) { 2337 KASSERT((vha->vha_flags & CARP_VHAF_OWNER) == 0, 2338 ("inactive vhaddr %p is the address owner\n", vha)); 2339 return; 2340 } 2341 2342 vha->vha_flags &= ~CARP_VHAF_OWNER; 2343 carp_delroute_vhaddr(sc, vha, del_iaback); 2344 2345 KKASSERT(sc->sc_naddrs > 0); 2346 vha->vha_iaback = NULL; 2347 sc->sc_naddrs--; 2348 if (!sc->sc_naddrs) { 2349 if (sc->sc_naddrs6) { 2350 carp_multicast_cleanup(sc); 2351 sc->sc_ia = NULL; 2352 } else { 2353 carp_detach(sc, 0, del_iaback); 2354 } 2355 } 2356 } 2357 2358 static void 2359 carp_link_addrs(struct carp_softc *sc, struct ifnet *ifp, struct ifaddr *ifa_if) 2360 { 2361 struct carp_vhaddr *vha; 2362 struct in_ifaddr *ia_if; 2363 2364 KKASSERT(ifa_if->ifa_addr->sa_family == AF_INET); 2365 ia_if = ifatoia(ifa_if); 2366 2367 /* 2368 * Test each inactive vhaddr against the newly added address. 2369 * If the newly added address could be the backing address, 2370 * then activate the matching vhaddr. 2371 */ 2372 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 2373 const struct in_ifaddr *ia; 2374 u_long iaddr; 2375 int own; 2376 2377 if (vha->vha_iaback != NULL) 2378 continue; 2379 2380 ia = vha->vha_ia; 2381 iaddr = ntohl(ia->ia_addr.sin_addr.s_addr); 2382 2383 if ((iaddr & ia_if->ia_subnetmask) != ia_if->ia_subnet) 2384 continue; 2385 2386 own = 0; 2387 if (ia->ia_addr.sin_addr.s_addr == 2388 ia_if->ia_addr.sin_addr.s_addr) 2389 own = 1; 2390 2391 carp_activate_vhaddr(sc, vha, ifp, ia_if, own); 2392 } 2393 } 2394 2395 static void 2396 carp_unlink_addrs(struct carp_softc *sc, struct ifnet *ifp, 2397 struct ifaddr *ifa_if) 2398 { 2399 struct carp_vhaddr *vha; 2400 struct in_ifaddr *ia_if; 2401 2402 KKASSERT(ifa_if->ifa_addr->sa_family == AF_INET); 2403 ia_if = ifatoia(ifa_if); 2404 2405 /* 2406 * Ad src address is deleted; set it to NULL. 2407 * Following loop will try pick up a new ad src address 2408 * if one of the vhaddr could retain its backing address. 2409 */ 2410 if (sc->sc_ia == ia_if) 2411 sc->sc_ia = NULL; 2412 2413 /* 2414 * Test each active vhaddr against the deleted address. 2415 * If the deleted address is vhaddr address's backing 2416 * address, then deactivate the vhaddr. 2417 */ 2418 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 2419 if (vha->vha_iaback == NULL) 2420 continue; 2421 2422 if (vha->vha_iaback == ia_if) 2423 carp_deactivate_vhaddr(sc, vha, TRUE); 2424 else if (sc->sc_ia == NULL) 2425 sc->sc_ia = vha->vha_iaback; 2426 } 2427 } 2428 2429 static void 2430 carp_update_addrs(struct carp_softc *sc, struct ifaddr *ifa_del) 2431 { 2432 struct carp_vhaddr *vha; 2433 2434 KKASSERT(sc->sc_carpdev == NULL); 2435 2436 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 2437 carp_config_vhaddr(sc, vha, ifatoia(ifa_del)); 2438 } 2439 2440 static void 2441 carp_ifaddr(void *arg __unused, struct ifnet *ifp, 2442 enum ifaddr_event event, struct ifaddr *ifa) 2443 { 2444 struct carp_softc *sc; 2445 2446 carp_gettok(); 2447 2448 if (ifa->ifa_addr->sa_family != AF_INET) 2449 goto back; 2450 2451 if (ifp->if_type == IFT_CARP) { 2452 /* 2453 * Address is changed on carp(4) interface 2454 */ 2455 switch (event) { 2456 case IFADDR_EVENT_ADD: 2457 carp_add_addr(ifp->if_softc, ifa); 2458 break; 2459 2460 case IFADDR_EVENT_CHANGE: 2461 carp_config_addr(ifp->if_softc, ifa); 2462 break; 2463 2464 case IFADDR_EVENT_DELETE: 2465 carp_del_addr(ifp->if_softc, ifa); 2466 break; 2467 } 2468 goto back; 2469 } 2470 2471 /* 2472 * Address is changed on non-carp(4) interface 2473 */ 2474 if ((ifp->if_flags & IFF_MULTICAST) == 0) 2475 goto back; 2476 2477 LIST_FOREACH(sc, &carpif_list, sc_next) { 2478 if (sc->sc_carpdev != NULL && sc->sc_carpdev != ifp) { 2479 /* Not the parent iface; skip */ 2480 continue; 2481 } 2482 2483 switch (event) { 2484 case IFADDR_EVENT_ADD: 2485 carp_link_addrs(sc, ifp, ifa); 2486 break; 2487 2488 case IFADDR_EVENT_DELETE: 2489 if (sc->sc_carpdev != NULL) { 2490 carp_unlink_addrs(sc, ifp, ifa); 2491 if (sc->sc_carpdev == NULL) { 2492 /* 2493 * We no longer have the parent 2494 * interface, however, certain 2495 * virtual addresses, which are 2496 * not used because they can't 2497 * match the previous parent 2498 * interface's addresses, may now 2499 * match different interface's 2500 * addresses. 2501 */ 2502 carp_update_addrs(sc, ifa); 2503 } 2504 } else { 2505 /* 2506 * The carp(4) interface didn't have a 2507 * parent iface, so it is not possible 2508 * that it will contain any address to 2509 * be unlinked. 2510 */ 2511 } 2512 break; 2513 2514 case IFADDR_EVENT_CHANGE: 2515 if (sc->sc_carpdev == NULL) { 2516 /* 2517 * The carp(4) interface didn't have a 2518 * parent iface, so it is not possible 2519 * that it will contain any address to 2520 * be updated. 2521 */ 2522 carp_link_addrs(sc, ifp, ifa); 2523 } else { 2524 /* 2525 * First try breaking tie with the old 2526 * address. Then see whether we could 2527 * link certain vhaddr to the new address. 2528 * If that fails, i.e. carpdev is NULL, 2529 * we try a global update. 2530 * 2531 * NOTE: The above order is critical. 2532 */ 2533 carp_unlink_addrs(sc, ifp, ifa); 2534 carp_link_addrs(sc, ifp, ifa); 2535 if (sc->sc_carpdev == NULL) { 2536 /* 2537 * See the comment in the above 2538 * IFADDR_EVENT_DELETE block. 2539 */ 2540 carp_update_addrs(sc, NULL); 2541 } 2542 } 2543 break; 2544 } 2545 } 2546 2547 back: 2548 carp_reltok(); 2549 } 2550 2551 void 2552 carp_proto_ctlinput(netmsg_t msg) 2553 { 2554 int cmd = msg->ctlinput.nm_cmd; 2555 struct sockaddr *sa = msg->ctlinput.nm_arg; 2556 struct in_ifaddr_container *iac; 2557 2558 carp_gettok(); 2559 2560 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 2561 struct in_ifaddr *ia = iac->ia; 2562 struct ifnet *ifp = ia->ia_ifp; 2563 2564 if (ifp->if_type == IFT_CARP) 2565 continue; 2566 2567 if (ia->ia_ifa.ifa_addr == sa) { 2568 if (cmd == PRC_IFDOWN) { 2569 carp_ifaddr(NULL, ifp, IFADDR_EVENT_DELETE, 2570 &ia->ia_ifa); 2571 } else if (cmd == PRC_IFUP) { 2572 carp_ifaddr(NULL, ifp, IFADDR_EVENT_ADD, 2573 &ia->ia_ifa); 2574 } 2575 break; 2576 } 2577 } 2578 2579 carp_reltok(); 2580 lwkt_replymsg(&msg->lmsg, 0); 2581 } 2582 2583 void 2584 carp_gettok(void) 2585 { 2586 lwkt_gettoken(&carp_tok); 2587 } 2588 2589 void 2590 carp_reltok(void) 2591 { 2592 lwkt_reltoken(&carp_tok); 2593 } 2594 2595 struct ifnet * 2596 carp_parent(struct ifnet *cifp) 2597 { 2598 struct carp_softc *sc; 2599 2600 ASSERT_LWKT_TOKEN_HELD(&carp_tok); 2601 2602 KKASSERT(cifp->if_type == IFT_CARP); 2603 sc = cifp->if_softc; 2604 2605 return sc->sc_carpdev; 2606 } 2607 2608 #define rtinitflags(x) \ 2609 (((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) \ 2610 ? RTF_HOST : 0) 2611 2612 static int 2613 carp_addroute_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha) 2614 { 2615 struct in_ifaddr *ia, *iaback; 2616 int error; 2617 2618 if (sc->sc_state != MASTER) 2619 return 0; 2620 2621 ia = vha->vha_ia; 2622 KKASSERT(ia != NULL); 2623 2624 iaback = vha->vha_iaback; 2625 KKASSERT(iaback != NULL); 2626 2627 rtinit(&iaback->ia_ifa, RTM_DELETE, rtinitflags(iaback)); 2628 in_ifadown(&iaback->ia_ifa, 1); 2629 iaback->ia_flags &= ~IFA_ROUTE; 2630 2631 error = rtinit(&ia->ia_ifa, RTM_ADD, rtinitflags(ia) | RTF_UP); 2632 if (!error) 2633 ia->ia_flags |= IFA_ROUTE; 2634 return error; 2635 } 2636 2637 static void 2638 carp_delroute_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 2639 boolean_t del_iaback) 2640 { 2641 struct in_ifaddr *ia, *iaback; 2642 2643 ia = vha->vha_ia; 2644 KKASSERT(ia != NULL); 2645 2646 iaback = vha->vha_iaback; 2647 KKASSERT(iaback != NULL); 2648 2649 rtinit(&ia->ia_ifa, RTM_DELETE, rtinitflags(ia)); 2650 in_ifadown(&ia->ia_ifa, 1); 2651 ia->ia_flags &= ~IFA_ROUTE; 2652 2653 if (!del_iaback && (iaback->ia_ifp->if_flags & IFF_UP)) { 2654 int error; 2655 2656 error = rtinit(&iaback->ia_ifa, RTM_ADD, 2657 rtinitflags(iaback) | RTF_UP); 2658 if (!error) 2659 iaback->ia_flags |= IFA_ROUTE; 2660 } 2661 } 2662 2663 static int 2664 carp_modevent(module_t mod, int type, void *data) 2665 { 2666 switch (type) { 2667 case MOD_LOAD: 2668 LIST_INIT(&carpif_list); 2669 carp_ifdetach_event = 2670 EVENTHANDLER_REGISTER(ifnet_detach_event, carp_ifdetach, NULL, 2671 EVENTHANDLER_PRI_ANY); 2672 carp_ifaddr_event = 2673 EVENTHANDLER_REGISTER(ifaddr_event, carp_ifaddr, NULL, 2674 EVENTHANDLER_PRI_FIRST); 2675 if_clone_attach(&carp_cloner); 2676 break; 2677 2678 case MOD_UNLOAD: 2679 EVENTHANDLER_DEREGISTER(ifnet_detach_event, 2680 carp_ifdetach_event); 2681 EVENTHANDLER_DEREGISTER(ifaddr_event, 2682 carp_ifaddr_event); 2683 if_clone_detach(&carp_cloner); 2684 break; 2685 2686 default: 2687 return (EINVAL); 2688 } 2689 return (0); 2690 } 2691 2692 static moduledata_t carp_mod = { 2693 "carp", 2694 carp_modevent, 2695 0 2696 }; 2697 DECLARE_MODULE(carp, carp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 2698