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 #include <net/netmsg2.h> 64 #include <net/netisr2.h> 65 66 #ifdef INET 67 #include <netinet/in.h> 68 #include <netinet/in_var.h> 69 #include <netinet/in_systm.h> 70 #include <netinet/ip.h> 71 #include <netinet/ip_var.h> 72 #include <netinet/if_ether.h> 73 #endif 74 75 #ifdef INET6 76 #include <netinet/icmp6.h> 77 #include <netinet/ip6.h> 78 #include <netinet6/ip6_var.h> 79 #include <netinet6/scope6_var.h> 80 #include <netinet6/nd6.h> 81 #endif 82 83 #include <netinet/ip_carp.h> 84 85 /* 86 * Note about carp's MP safe approach: 87 * 88 * Brief: carp_softc (softc), carp_softc_container (scc) 89 * 90 * - All configuration operation, e.g. ioctl, add/delete inet addresses 91 * is serialized by netisr0; not by carp's serializer 92 * 93 * - Backing interface's if_carp and carp_softc's relationship: 94 * 95 * +---------+ 96 * if_carp -->| carp_if | 97 * +---------+ 98 * | 99 * | 100 * V +---------+ 101 * +-----+ | | 102 * | scc |-->| softc | 103 * +-----+ | | 104 * | +---------+ 105 * | 106 * V +---------+ 107 * +-----+ | | 108 * | scc |-->| softc | 109 * +-----+ | | 110 * +---------+ 111 * 112 * - if_carp creation, modification and deletion all happen in netisr0, 113 * as stated previously. Since if_carp is accessed by multiple netisrs, 114 * the modification to if_carp is conducted in the following way: 115 * 116 * Adding carp_softc: 117 * 118 * 1) Duplicate the old carp_if to new carp_if (ncif), and insert the 119 * to-be-added carp_softc to the new carp_if (ncif): 120 * 121 * if_carp ncif 122 * | | 123 * V V 124 * +---------+ +---------+ 125 * | carp_if | | carp_if | 126 * +---------+ +---------+ 127 * | | 128 * | | 129 * V +-------+ V 130 * +-----+ | | +-----+ 131 * | scc |---->| softc |<----| scc | 132 * +-----+ | | +-----+ 133 * | +-------+ | 134 * | | 135 * V +-------+ V 136 * +-----+ | | +-----+ 137 * | scc |---->| softc |<----| scc | 138 * +-----+ | | +-----+ 139 * +-------+ | 140 * | 141 * +-------+ V 142 * | | +-----+ 143 * | softc |<----| scc | 144 * | | +-----+ 145 * +-------+ 146 * 147 * 2) Switch save if_carp into ocif and switch if_carp to ncif: 148 * 149 * ocif if_carp 150 * | | 151 * V V 152 * +---------+ +---------+ 153 * | carp_if | | carp_if | 154 * +---------+ +---------+ 155 * | | 156 * | | 157 * V +-------+ V 158 * +-----+ | | +-----+ 159 * | scc |---->| softc |<----| scc | 160 * +-----+ | | +-----+ 161 * | +-------+ | 162 * | | 163 * V +-------+ V 164 * +-----+ | | +-----+ 165 * | scc |---->| softc |<----| scc | 166 * +-----+ | | +-----+ 167 * +-------+ | 168 * | 169 * +-------+ V 170 * | | +-----+ 171 * | softc |<----| scc | 172 * | | +-----+ 173 * +-------+ 174 * 175 * 3) Run netmsg_service_sync(), which will make sure that 176 * ocif is no longer accessed (all network operations 177 * are happened only in network threads). 178 * 4) Free ocif -- only carp_if and scc are freed. 179 * 180 * 181 * Removing carp_softc: 182 * 183 * 1) Duplicate the old carp_if to new carp_if (ncif); the to-be-deleted 184 * carp_softc will not be duplicated. 185 * 186 * if_carp ncif 187 * | | 188 * V V 189 * +---------+ +---------+ 190 * | carp_if | | carp_if | 191 * +---------+ +---------+ 192 * | | 193 * | | 194 * V +-------+ V 195 * +-----+ | | +-----+ 196 * | scc |---->| softc |<----| scc | 197 * +-----+ | | +-----+ 198 * | +-------+ | 199 * | | 200 * V +-------+ | 201 * +-----+ | | | 202 * | scc |---->| softc | | 203 * +-----+ | | | 204 * | +-------+ | 205 * | | 206 * V +-------+ V 207 * +-----+ | | +-----+ 208 * | scc |---->| softc |<----| scc | 209 * +-----+ | | +-----+ 210 * +-------+ 211 * 212 * 2) Switch save if_carp into ocif and switch if_carp to ncif: 213 * 214 * ocif if_carp 215 * | | 216 * V V 217 * +---------+ +---------+ 218 * | carp_if | | carp_if | 219 * +---------+ +---------+ 220 * | | 221 * | | 222 * V +-------+ V 223 * +-----+ | | +-----+ 224 * | scc |---->| softc |<----| scc | 225 * +-----+ | | +-----+ 226 * | +-------+ | 227 * | | 228 * V +-------+ | 229 * +-----+ | | | 230 * | scc |---->| softc | | 231 * +-----+ | | | 232 * | +-------+ | 233 * | | 234 * V +-------+ V 235 * +-----+ | | +-----+ 236 * | scc |---->| softc |<----| scc | 237 * +-----+ | | +-----+ 238 * +-------+ 239 * 240 * 3) Run netmsg_service_sync(), which will make sure that 241 * ocif is no longer accessed (all network operations 242 * are happened only in network threads). 243 * 4) Free ocif -- only carp_if and scc are freed. 244 * 245 * - if_carp accessing: 246 * The accessing code should cache the if_carp in a local temporary 247 * variable and accessing the temporary variable along the code path 248 * instead of accessing if_carp later on. 249 */ 250 251 #define CARP_IFNAME "carp" 252 #define CARP_IS_RUNNING(ifp) \ 253 (((ifp)->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) 254 255 struct carp_softc; 256 257 struct carp_vhaddr { 258 uint32_t vha_flags; /* CARP_VHAF_ */ 259 struct in_ifaddr *vha_ia; /* carp address */ 260 struct in_ifaddr *vha_iaback; /* backing address */ 261 TAILQ_ENTRY(carp_vhaddr) vha_link; 262 }; 263 TAILQ_HEAD(carp_vhaddr_list, carp_vhaddr); 264 265 struct netmsg_carp { 266 struct netmsg_base base; 267 struct ifnet *nc_carpdev; 268 struct carp_softc *nc_softc; 269 void *nc_data; 270 size_t nc_datalen; 271 }; 272 273 struct carp_softc { 274 struct arpcom arpcom; 275 struct ifnet *sc_carpdev; /* parent interface */ 276 struct carp_vhaddr_list sc_vha_list; /* virtual addr list */ 277 278 const struct in_ifaddr *sc_ia; /* primary iface address v4 */ 279 struct ip_moptions sc_imo; 280 281 #ifdef INET6 282 struct in6_ifaddr *sc_ia6; /* primary iface address v6 */ 283 struct ip6_moptions sc_im6o; 284 #endif /* INET6 */ 285 286 enum { INIT = 0, BACKUP, MASTER } 287 sc_state; 288 boolean_t sc_dead; 289 290 int sc_suppress; 291 292 int sc_sendad_errors; 293 #define CARP_SENDAD_MAX_ERRORS 3 294 int sc_sendad_success; 295 #define CARP_SENDAD_MIN_SUCCESS 3 296 297 int sc_vhid; 298 int sc_advskew; 299 int sc_naddrs; /* actually used IPv4 vha */ 300 int sc_naddrs6; 301 int sc_advbase; /* seconds */ 302 int sc_init_counter; 303 uint64_t sc_counter; 304 305 /* authentication */ 306 #define CARP_HMAC_PAD 64 307 unsigned char sc_key[CARP_KEY_LEN]; 308 unsigned char sc_pad[CARP_HMAC_PAD]; 309 SHA1_CTX sc_sha1; 310 311 struct callout sc_ad_tmo; /* advertisement timeout */ 312 struct netmsg_carp sc_ad_msg; /* adv timeout netmsg */ 313 struct callout sc_md_tmo; /* ip4 master down timeout */ 314 struct callout sc_md6_tmo; /* ip6 master down timeout */ 315 struct netmsg_carp sc_md_msg; /* master down timeout netmsg */ 316 317 LIST_ENTRY(carp_softc) sc_next; /* Interface clue */ 318 }; 319 320 #define sc_if arpcom.ac_if 321 322 struct carp_softc_container { 323 TAILQ_ENTRY(carp_softc_container) scc_link; 324 struct carp_softc *scc_softc; 325 }; 326 TAILQ_HEAD(carp_if, carp_softc_container); 327 328 SYSCTL_DECL(_net_inet_carp); 329 330 static int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0, 1 }; /* XXX for now */ 331 SYSCTL_INT(_net_inet_carp, CARPCTL_ALLOW, allow, CTLFLAG_RW, 332 &carp_opts[CARPCTL_ALLOW], 0, "Accept incoming CARP packets"); 333 SYSCTL_INT(_net_inet_carp, CARPCTL_PREEMPT, preempt, CTLFLAG_RW, 334 &carp_opts[CARPCTL_PREEMPT], 0, "high-priority backup preemption mode"); 335 SYSCTL_INT(_net_inet_carp, CARPCTL_LOG, log, CTLFLAG_RW, 336 &carp_opts[CARPCTL_LOG], 0, "log bad carp packets"); 337 SYSCTL_INT(_net_inet_carp, CARPCTL_ARPBALANCE, arpbalance, CTLFLAG_RW, 338 &carp_opts[CARPCTL_ARPBALANCE], 0, "balance arp responses"); 339 SYSCTL_INT(_net_inet_carp, CARPCTL_SETROUTE, setroute, CTLFLAG_RW, 340 &carp_opts[CARPCTL_SETROUTE], 0, "set route"); 341 342 static int carp_suppress_preempt = 0; 343 SYSCTL_INT(_net_inet_carp, OID_AUTO, suppress_preempt, CTLFLAG_RD, 344 &carp_suppress_preempt, 0, "Preemption is suppressed"); 345 346 static int carp_prio_ad = 1; 347 SYSCTL_INT(_net_inet_carp, OID_AUTO, prio_ad, CTLFLAG_RD, 348 &carp_prio_ad, 0, "Prioritize advertisement packet"); 349 350 static struct carpstats carpstats; 351 SYSCTL_STRUCT(_net_inet_carp, CARPCTL_STATS, stats, CTLFLAG_RW, 352 &carpstats, carpstats, 353 "CARP statistics (struct carpstats, netinet/ip_carp.h)"); 354 355 #define CARP_LOG(...) do { \ 356 if (carp_opts[CARPCTL_LOG] > 0) \ 357 log(LOG_INFO, __VA_ARGS__); \ 358 } while (0) 359 360 #define CARP_DEBUG(...) do { \ 361 if (carp_opts[CARPCTL_LOG] > 1) \ 362 log(LOG_DEBUG, __VA_ARGS__); \ 363 } while (0) 364 365 static struct lwkt_token carp_listtok = LWKT_TOKEN_INITIALIZER(carp_list_token); 366 367 static void carp_hmac_prepare(struct carp_softc *); 368 static void carp_hmac_generate(struct carp_softc *, uint32_t *, 369 unsigned char *); 370 static int carp_hmac_verify(struct carp_softc *, uint32_t *, 371 unsigned char *); 372 static void carp_setroute(struct carp_softc *, int); 373 static void carp_proto_input_c(struct carp_softc *, struct mbuf *, 374 struct carp_header *, sa_family_t); 375 static int carp_clone_create(struct if_clone *, int, caddr_t); 376 static int carp_clone_destroy(struct ifnet *); 377 static void carp_detach(struct carp_softc *, boolean_t, boolean_t); 378 static void carp_prepare_ad(struct carp_softc *, struct carp_header *); 379 static void carp_send_ad_all(void); 380 static void carp_send_ad_timeout(void *); 381 static void carp_send_ad(struct carp_softc *); 382 static void carp_send_arp(struct carp_softc *); 383 static void carp_master_down_timeout(void *); 384 static void carp_master_down(struct carp_softc *); 385 static void carp_setrun(struct carp_softc *, sa_family_t); 386 static void carp_set_state(struct carp_softc *, int); 387 static struct ifnet *carp_forus(struct carp_if *, const uint8_t *); 388 389 static void carp_init(void *); 390 static int carp_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 391 static int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, 392 struct rtentry *); 393 static void carp_start(struct ifnet *, struct ifaltq_subque *); 394 395 static void carp_multicast_cleanup(struct carp_softc *); 396 static void carp_add_addr(struct carp_softc *, struct ifaddr *); 397 static void carp_del_addr(struct carp_softc *, struct ifaddr *); 398 static void carp_config_addr(struct carp_softc *, struct ifaddr *); 399 static void carp_link_addrs(struct carp_softc *, struct ifnet *, 400 struct ifaddr *); 401 static void carp_unlink_addrs(struct carp_softc *, struct ifnet *, 402 struct ifaddr *); 403 static void carp_update_addrs(struct carp_softc *, struct ifaddr *); 404 405 static int carp_config_vhaddr(struct carp_softc *, struct carp_vhaddr *, 406 struct in_ifaddr *); 407 static int carp_activate_vhaddr(struct carp_softc *, struct carp_vhaddr *, 408 struct ifnet *, struct in_ifaddr *, int); 409 static void carp_deactivate_vhaddr(struct carp_softc *, 410 struct carp_vhaddr *, boolean_t); 411 static int carp_addroute_vhaddr(struct carp_softc *, struct carp_vhaddr *); 412 static void carp_delroute_vhaddr(struct carp_softc *, struct carp_vhaddr *, 413 boolean_t); 414 415 #ifdef foo 416 static void carp_sc_state(struct carp_softc *); 417 #endif 418 #ifdef INET6 419 static void carp_send_na(struct carp_softc *); 420 #ifdef notyet 421 static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); 422 static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); 423 #endif 424 static void carp_multicast6_cleanup(struct carp_softc *); 425 #endif 426 static void carp_stop(struct carp_softc *, boolean_t); 427 static void carp_suspend(struct carp_softc *, boolean_t); 428 static void carp_ioctl_stop(struct carp_softc *); 429 static int carp_ioctl_setvh(struct carp_softc *, void *, struct ucred *); 430 static void carp_ioctl_ifcap(struct carp_softc *, int); 431 static int carp_ioctl_getvh(struct carp_softc *, void *, struct ucred *); 432 static int carp_ioctl_getdevname(struct carp_softc *, struct ifdrv *); 433 static int carp_ioctl_getvhaddr(struct carp_softc *, struct ifdrv *); 434 435 static struct carp_if *carp_if_remove(struct carp_if *, struct carp_softc *); 436 static struct carp_if *carp_if_insert(struct carp_if *, struct carp_softc *); 437 static void carp_if_free(struct carp_if *); 438 439 static void carp_ifaddr(void *, struct ifnet *, enum ifaddr_event, 440 struct ifaddr *); 441 static void carp_ifdetach(void *, struct ifnet *); 442 443 static void carp_ifdetach_dispatch(netmsg_t); 444 static void carp_clone_destroy_dispatch(netmsg_t); 445 static void carp_init_dispatch(netmsg_t); 446 static void carp_ioctl_stop_dispatch(netmsg_t); 447 static void carp_ioctl_setvh_dispatch(netmsg_t); 448 static void carp_ioctl_ifcap_dispatch(netmsg_t); 449 static void carp_ioctl_getvh_dispatch(netmsg_t); 450 static void carp_ioctl_getdevname_dispatch(netmsg_t); 451 static void carp_ioctl_getvhaddr_dispatch(netmsg_t); 452 static void carp_send_ad_timeout_dispatch(netmsg_t); 453 static void carp_master_down_timeout_dispatch(netmsg_t); 454 455 static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces"); 456 457 static LIST_HEAD(, carp_softc) carpif_list; 458 459 static struct if_clone carp_cloner = 460 IF_CLONE_INITIALIZER(CARP_IFNAME, carp_clone_create, carp_clone_destroy, 461 0, IF_MAXUNIT); 462 463 static const uint8_t carp_etheraddr[ETHER_ADDR_LEN] = 464 { 0, 0, 0x5e, 0, 1, 0 }; 465 466 static eventhandler_tag carp_ifdetach_event; 467 static eventhandler_tag carp_ifaddr_event; 468 469 static __inline void 470 carp_insert_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha_new) 471 { 472 struct carp_vhaddr *vha; 473 u_long new_addr, addr; 474 475 KKASSERT((vha_new->vha_flags & CARP_VHAF_ONLIST) == 0); 476 477 /* 478 * Virtual address list is sorted; smaller one first 479 */ 480 new_addr = ntohl(vha_new->vha_ia->ia_addr.sin_addr.s_addr); 481 482 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 483 addr = ntohl(vha->vha_ia->ia_addr.sin_addr.s_addr); 484 485 if (addr > new_addr) 486 break; 487 } 488 if (vha == NULL) 489 TAILQ_INSERT_TAIL(&sc->sc_vha_list, vha_new, vha_link); 490 else 491 TAILQ_INSERT_BEFORE(vha, vha_new, vha_link); 492 vha_new->vha_flags |= CARP_VHAF_ONLIST; 493 } 494 495 static __inline void 496 carp_remove_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha) 497 { 498 KKASSERT(vha->vha_flags & CARP_VHAF_ONLIST); 499 vha->vha_flags &= ~CARP_VHAF_ONLIST; 500 TAILQ_REMOVE(&sc->sc_vha_list, vha, vha_link); 501 } 502 503 static void 504 carp_hmac_prepare(struct carp_softc *sc) 505 { 506 uint8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; 507 uint8_t vhid = sc->sc_vhid & 0xff; 508 int i; 509 #ifdef INET6 510 struct ifaddr_container *ifac; 511 struct in6_addr in6; 512 #endif 513 #ifdef INET 514 struct carp_vhaddr *vha; 515 #endif 516 517 /* XXX: possible race here */ 518 519 /* compute ipad from key */ 520 bzero(sc->sc_pad, sizeof(sc->sc_pad)); 521 bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key)); 522 for (i = 0; i < sizeof(sc->sc_pad); i++) 523 sc->sc_pad[i] ^= 0x36; 524 525 /* precompute first part of inner hash */ 526 SHA1Init(&sc->sc_sha1); 527 SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad)); 528 SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version)); 529 SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type)); 530 SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid)); 531 #ifdef INET 532 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 533 SHA1Update(&sc->sc_sha1, 534 (const uint8_t *)&vha->vha_ia->ia_addr.sin_addr, 535 sizeof(struct in_addr)); 536 } 537 #endif /* INET */ 538 #ifdef INET6 539 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], ifa_link) { 540 struct ifaddr *ifa = ifac->ifa; 541 542 if (ifa->ifa_addr->sa_family == AF_INET6) { 543 in6 = ifatoia6(ifa)->ia_addr.sin6_addr; 544 in6_clearscope(&in6); 545 SHA1Update(&sc->sc_sha1, (void *)&in6, sizeof(in6)); 546 } 547 } 548 #endif /* INET6 */ 549 550 /* convert ipad to opad */ 551 for (i = 0; i < sizeof(sc->sc_pad); i++) 552 sc->sc_pad[i] ^= 0x36 ^ 0x5c; 553 } 554 555 static void 556 carp_hmac_generate(struct carp_softc *sc, uint32_t counter[2], 557 unsigned char md[20]) 558 { 559 SHA1_CTX sha1ctx; 560 561 /* fetch first half of inner hash */ 562 bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)); 563 564 SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter)); 565 SHA1Final(md, &sha1ctx); 566 567 /* outer hash */ 568 SHA1Init(&sha1ctx); 569 SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad)); 570 SHA1Update(&sha1ctx, md, 20); 571 SHA1Final(md, &sha1ctx); 572 } 573 574 static int 575 carp_hmac_verify(struct carp_softc *sc, uint32_t counter[2], 576 unsigned char md[20]) 577 { 578 unsigned char md2[20]; 579 580 carp_hmac_generate(sc, counter, md2); 581 return (bcmp(md, md2, sizeof(md2))); 582 } 583 584 static void 585 carp_setroute(struct carp_softc *sc, int cmd) 586 { 587 #ifdef INET6 588 struct ifaddr_container *ifac; 589 #endif 590 struct carp_vhaddr *vha; 591 592 KKASSERT(cmd == RTM_DELETE || cmd == RTM_ADD); 593 594 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 595 if (vha->vha_iaback == NULL) 596 continue; 597 if (cmd == RTM_DELETE) 598 carp_delroute_vhaddr(sc, vha, FALSE); 599 else 600 carp_addroute_vhaddr(sc, vha); 601 } 602 603 #ifdef INET6 604 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], ifa_link) { 605 struct ifaddr *ifa = ifac->ifa; 606 607 if (ifa->ifa_addr->sa_family == AF_INET6) { 608 if (cmd == RTM_ADD) 609 in6_ifaddloop(ifa); 610 else 611 in6_ifremloop(ifa); 612 } 613 } 614 #endif /* INET6 */ 615 } 616 617 static int 618 carp_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused) 619 { 620 struct carp_softc *sc; 621 struct ifnet *ifp; 622 623 sc = kmalloc(sizeof(*sc), M_CARP, M_WAITOK | M_ZERO); 624 ifp = &sc->sc_if; 625 626 sc->sc_suppress = 0; 627 sc->sc_advbase = CARP_DFLTINTV; 628 sc->sc_vhid = -1; /* required setting */ 629 sc->sc_advskew = 0; 630 sc->sc_init_counter = 1; 631 sc->sc_naddrs = 0; 632 sc->sc_naddrs6 = 0; 633 634 TAILQ_INIT(&sc->sc_vha_list); 635 636 #ifdef INET6 637 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; 638 #endif 639 640 callout_init_mp(&sc->sc_ad_tmo); 641 netmsg_init(&sc->sc_ad_msg.base, NULL, &netisr_adone_rport, 642 MSGF_DROPABLE | MSGF_PRIORITY, carp_send_ad_timeout_dispatch); 643 sc->sc_ad_msg.nc_softc = sc; 644 645 callout_init_mp(&sc->sc_md_tmo); 646 callout_init_mp(&sc->sc_md6_tmo); 647 netmsg_init(&sc->sc_md_msg.base, NULL, &netisr_adone_rport, 648 MSGF_DROPABLE | MSGF_PRIORITY, carp_master_down_timeout_dispatch); 649 sc->sc_md_msg.nc_softc = sc; 650 651 if_initname(ifp, CARP_IFNAME, unit); 652 ifp->if_softc = sc; 653 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 654 ifp->if_init = carp_init; 655 ifp->if_ioctl = carp_ioctl; 656 ifp->if_start = carp_start; 657 658 ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_TSO; 659 ifp->if_capenable = ifp->if_capabilities; 660 /* 661 * Leave if_hwassist as it is; if_hwassist will be 662 * setup when this carp interface has parent. 663 */ 664 665 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); 666 ifq_set_ready(&ifp->if_snd); 667 668 ether_ifattach(ifp, carp_etheraddr, NULL); 669 670 ifp->if_type = IFT_CARP; 671 ifp->if_output = carp_output; 672 673 lwkt_gettoken(&carp_listtok); 674 LIST_INSERT_HEAD(&carpif_list, sc, sc_next); 675 lwkt_reltoken(&carp_listtok); 676 677 return (0); 678 } 679 680 static void 681 carp_clone_destroy_dispatch(netmsg_t msg) 682 { 683 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 684 struct carp_softc *sc = cmsg->nc_softc; 685 686 sc->sc_dead = TRUE; 687 carp_detach(sc, TRUE, FALSE); 688 689 callout_stop_sync(&sc->sc_ad_tmo); 690 callout_stop_sync(&sc->sc_md_tmo); 691 callout_stop_sync(&sc->sc_md6_tmo); 692 693 crit_enter(); 694 lwkt_dropmsg(&sc->sc_ad_msg.base.lmsg); 695 lwkt_dropmsg(&sc->sc_md_msg.base.lmsg); 696 crit_exit(); 697 698 lwkt_replymsg(&cmsg->base.lmsg, 0); 699 } 700 701 static int 702 carp_clone_destroy(struct ifnet *ifp) 703 { 704 struct carp_softc *sc = ifp->if_softc; 705 struct netmsg_carp cmsg; 706 707 bzero(&cmsg, sizeof(cmsg)); 708 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 709 carp_clone_destroy_dispatch); 710 cmsg.nc_softc = sc; 711 712 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 713 714 lwkt_gettoken(&carp_listtok); 715 LIST_REMOVE(sc, sc_next); 716 lwkt_reltoken(&carp_listtok); 717 718 bpfdetach(ifp); 719 if_detach(ifp); 720 721 KASSERT(sc->sc_naddrs == 0, ("certain inet address is still active")); 722 kfree(sc, M_CARP); 723 724 return 0; 725 } 726 727 static struct carp_if * 728 carp_if_remove(struct carp_if *ocif, struct carp_softc *sc) 729 { 730 struct carp_softc_container *oscc, *scc; 731 struct carp_if *cif; 732 int count = 0; 733 #ifdef INVARIANTS 734 int found = 0; 735 #endif 736 737 TAILQ_FOREACH(oscc, ocif, scc_link) { 738 ++count; 739 #ifdef INVARIANTS 740 if (oscc->scc_softc == sc) 741 found = 1; 742 #endif 743 } 744 KASSERT(found, ("%s carp_softc is not on carp_if", __func__)); 745 746 if (count == 1) { 747 /* Last one is going to be unlinked */ 748 return NULL; 749 } 750 751 cif = kmalloc(sizeof(*cif), M_CARP, M_WAITOK | M_ZERO); 752 TAILQ_INIT(cif); 753 754 TAILQ_FOREACH(oscc, ocif, scc_link) { 755 if (oscc->scc_softc == sc) 756 continue; 757 758 scc = kmalloc(sizeof(*scc), M_CARP, M_WAITOK | M_ZERO); 759 scc->scc_softc = oscc->scc_softc; 760 TAILQ_INSERT_TAIL(cif, scc, scc_link); 761 } 762 763 return cif; 764 } 765 766 static struct carp_if * 767 carp_if_insert(struct carp_if *ocif, struct carp_softc *sc) 768 { 769 struct carp_softc_container *oscc; 770 int onlist; 771 772 onlist = 0; 773 if (ocif != NULL) { 774 TAILQ_FOREACH(oscc, ocif, scc_link) { 775 if (oscc->scc_softc == sc) 776 onlist = 1; 777 } 778 } 779 780 #ifdef INVARIANTS 781 if (sc->sc_carpdev != NULL) { 782 KASSERT(onlist, ("%s is not on %s carp list", 783 sc->sc_if.if_xname, sc->sc_carpdev->if_xname)); 784 } else { 785 KASSERT(!onlist, ("%s is already on carp list", 786 sc->sc_if.if_xname)); 787 } 788 #endif 789 790 if (!onlist) { 791 struct carp_if *cif; 792 struct carp_softc_container *new_scc, *scc; 793 int inserted = 0; 794 795 cif = kmalloc(sizeof(*cif), M_CARP, M_WAITOK | M_ZERO); 796 TAILQ_INIT(cif); 797 798 new_scc = kmalloc(sizeof(*new_scc), M_CARP, M_WAITOK | M_ZERO); 799 new_scc->scc_softc = sc; 800 801 if (ocif != NULL) { 802 TAILQ_FOREACH(oscc, ocif, scc_link) { 803 if (!inserted && 804 oscc->scc_softc->sc_vhid > sc->sc_vhid) { 805 TAILQ_INSERT_TAIL(cif, new_scc, 806 scc_link); 807 inserted = 1; 808 } 809 810 scc = kmalloc(sizeof(*scc), M_CARP, 811 M_WAITOK | M_ZERO); 812 scc->scc_softc = oscc->scc_softc; 813 TAILQ_INSERT_TAIL(cif, scc, scc_link); 814 } 815 } 816 if (!inserted) 817 TAILQ_INSERT_TAIL(cif, new_scc, scc_link); 818 819 return cif; 820 } else { 821 return ocif; 822 } 823 } 824 825 static void 826 carp_if_free(struct carp_if *cif) 827 { 828 struct carp_softc_container *scc; 829 830 while ((scc = TAILQ_FIRST(cif)) != NULL) { 831 TAILQ_REMOVE(cif, scc, scc_link); 832 kfree(scc, M_CARP); 833 } 834 kfree(cif, M_CARP); 835 } 836 837 static void 838 carp_detach(struct carp_softc *sc, boolean_t detach, boolean_t del_iaback) 839 { 840 carp_suspend(sc, detach); 841 842 carp_multicast_cleanup(sc); 843 #ifdef INET6 844 carp_multicast6_cleanup(sc); 845 #endif 846 847 if (!sc->sc_dead && detach) { 848 struct carp_vhaddr *vha; 849 850 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 851 carp_deactivate_vhaddr(sc, vha, del_iaback); 852 KKASSERT(sc->sc_naddrs == 0); 853 } 854 855 if (sc->sc_carpdev != NULL) { 856 struct ifnet *ifp = sc->sc_carpdev; 857 struct carp_if *ocif = ifp->if_carp; 858 859 ifp->if_carp = carp_if_remove(ocif, sc); 860 KASSERT(ifp->if_carp != ocif, 861 ("%s carp_if_remove failed", __func__)); 862 863 sc->sc_carpdev = NULL; 864 sc->sc_ia = NULL; 865 sc->arpcom.ac_if.if_hwassist = 0; 866 867 /* 868 * Make sure that all protocol threads see the 869 * sc_carpdev and if_carp changes 870 */ 871 netmsg_service_sync(); 872 873 if (ifp->if_carp == NULL) { 874 /* 875 * No more carp interfaces using 876 * ifp as the backing interface, 877 * move it out of promiscous mode. 878 */ 879 ifpromisc(ifp, 0); 880 } 881 882 /* 883 * The old carp list could be safely free now, 884 * since no one can access it. 885 */ 886 carp_if_free(ocif); 887 } 888 } 889 890 static void 891 carp_ifdetach_dispatch(netmsg_t msg) 892 { 893 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 894 struct ifnet *ifp = cmsg->nc_carpdev; 895 896 while (ifp->if_carp) { 897 struct carp_softc_container *scc; 898 899 scc = TAILQ_FIRST((struct carp_if *)(ifp->if_carp)); 900 carp_detach(scc->scc_softc, TRUE, TRUE); 901 } 902 lwkt_replymsg(&cmsg->base.lmsg, 0); 903 } 904 905 /* Detach an interface from the carp. */ 906 static void 907 carp_ifdetach(void *arg __unused, struct ifnet *ifp) 908 { 909 struct netmsg_carp cmsg; 910 911 ASSERT_IFNET_NOT_SERIALIZED_ALL(ifp); 912 913 bzero(&cmsg, sizeof(cmsg)); 914 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 915 carp_ifdetach_dispatch); 916 cmsg.nc_carpdev = ifp; 917 918 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 919 } 920 921 /* 922 * process input packet. 923 * we have rearranged checks order compared to the rfc, 924 * but it seems more efficient this way or not possible otherwise. 925 */ 926 int 927 carp_proto_input(struct mbuf **mp, int *offp, int proto) 928 { 929 struct mbuf *m = *mp; 930 struct ip *ip = mtod(m, struct ip *); 931 struct ifnet *ifp = m->m_pkthdr.rcvif; 932 struct carp_header *ch; 933 struct carp_softc *sc; 934 int len, iphlen; 935 936 iphlen = *offp; 937 *mp = NULL; 938 939 carpstats.carps_ipackets++; 940 941 if (!carp_opts[CARPCTL_ALLOW]) { 942 m_freem(m); 943 goto back; 944 } 945 946 /* Check if received on a valid carp interface */ 947 if (ifp->if_type != IFT_CARP) { 948 carpstats.carps_badif++; 949 CARP_LOG("carp_proto_input: packet received on non-carp " 950 "interface: %s\n", ifp->if_xname); 951 m_freem(m); 952 goto back; 953 } 954 955 if (!CARP_IS_RUNNING(ifp)) { 956 carpstats.carps_badif++; 957 CARP_LOG("carp_proto_input: packet received on stopped carp " 958 "interface: %s\n", ifp->if_xname); 959 m_freem(m); 960 goto back; 961 } 962 963 sc = ifp->if_softc; 964 if (sc->sc_carpdev == NULL) { 965 carpstats.carps_badif++; 966 CARP_LOG("carp_proto_input: packet received on defunc carp " 967 "interface: %s\n", ifp->if_xname); 968 m_freem(m); 969 goto back; 970 } 971 972 if (!IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { 973 carpstats.carps_badif++; 974 CARP_LOG("carp_proto_input: non-mcast packet on " 975 "interface: %s\n", ifp->if_xname); 976 m_freem(m); 977 goto back; 978 } 979 980 /* Verify that the IP TTL is CARP_DFLTTL. */ 981 if (ip->ip_ttl != CARP_DFLTTL) { 982 carpstats.carps_badttl++; 983 CARP_LOG("carp_proto_input: received ttl %d != %d on %s\n", 984 ip->ip_ttl, CARP_DFLTTL, ifp->if_xname); 985 m_freem(m); 986 goto back; 987 } 988 989 /* Minimal CARP packet size */ 990 len = iphlen + sizeof(*ch); 991 992 /* 993 * Verify that the received packet length is 994 * not less than the CARP header 995 */ 996 if (m->m_pkthdr.len < len) { 997 carpstats.carps_badlen++; 998 CARP_LOG("packet too short %d on %s\n", m->m_pkthdr.len, 999 ifp->if_xname); 1000 m_freem(m); 1001 goto back; 1002 } 1003 1004 /* Make sure that CARP header is contiguous */ 1005 if (len > m->m_len) { 1006 m = m_pullup(m, len); 1007 if (m == NULL) { 1008 carpstats.carps_hdrops++; 1009 CARP_LOG("carp_proto_input: m_pullup failed\n"); 1010 goto back; 1011 } 1012 ip = mtod(m, struct ip *); 1013 } 1014 ch = (struct carp_header *)((uint8_t *)ip + iphlen); 1015 1016 /* Verify the CARP checksum */ 1017 if (in_cksum_skip(m, len, iphlen)) { 1018 carpstats.carps_badsum++; 1019 CARP_LOG("carp_proto_input: checksum failed on %s\n", 1020 ifp->if_xname); 1021 m_freem(m); 1022 goto back; 1023 } 1024 carp_proto_input_c(sc, m, ch, AF_INET); 1025 back: 1026 return(IPPROTO_DONE); 1027 } 1028 1029 #ifdef INET6 1030 int 1031 carp6_proto_input(struct mbuf **mp, int *offp, int proto) 1032 { 1033 struct mbuf *m = *mp; 1034 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1035 struct ifnet *ifp = m->m_pkthdr.rcvif; 1036 struct carp_header *ch; 1037 struct carp_softc *sc; 1038 u_int len; 1039 1040 carpstats.carps_ipackets6++; 1041 1042 if (!carp_opts[CARPCTL_ALLOW]) { 1043 m_freem(m); 1044 goto back; 1045 } 1046 1047 /* check if received on a valid carp interface */ 1048 if (ifp->if_type != IFT_CARP) { 1049 carpstats.carps_badif++; 1050 CARP_LOG("carp6_proto_input: packet received on non-carp " 1051 "interface: %s\n", ifp->if_xname); 1052 m_freem(m); 1053 goto back; 1054 } 1055 1056 if (!CARP_IS_RUNNING(ifp)) { 1057 carpstats.carps_badif++; 1058 CARP_LOG("carp_proto_input: packet received on stopped carp " 1059 "interface: %s\n", ifp->if_xname); 1060 m_freem(m); 1061 goto back; 1062 } 1063 1064 sc = ifp->if_softc; 1065 if (sc->sc_carpdev == NULL) { 1066 carpstats.carps_badif++; 1067 CARP_LOG("carp6_proto_input: packet received on defunc-carp " 1068 "interface: %s\n", ifp->if_xname); 1069 m_freem(m); 1070 goto back; 1071 } 1072 1073 /* verify that the IP TTL is 255 */ 1074 if (ip6->ip6_hlim != CARP_DFLTTL) { 1075 carpstats.carps_badttl++; 1076 CARP_LOG("carp6_proto_input: received ttl %d != 255 on %s\n", 1077 ip6->ip6_hlim, ifp->if_xname); 1078 m_freem(m); 1079 goto back; 1080 } 1081 1082 /* verify that we have a complete carp packet */ 1083 len = m->m_len; 1084 IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); 1085 if (ch == NULL) { 1086 carpstats.carps_badlen++; 1087 CARP_LOG("carp6_proto_input: packet size %u too small\n", len); 1088 goto back; 1089 } 1090 1091 /* verify the CARP checksum */ 1092 if (in_cksum_range(m, 0, *offp, sizeof(*ch))) { 1093 carpstats.carps_badsum++; 1094 CARP_LOG("carp6_proto_input: checksum failed, on %s\n", 1095 ifp->if_xname); 1096 m_freem(m); 1097 goto back; 1098 } 1099 1100 carp_proto_input_c(sc, m, ch, AF_INET6); 1101 back: 1102 return (IPPROTO_DONE); 1103 } 1104 #endif /* INET6 */ 1105 1106 static void 1107 carp_proto_input_c(struct carp_softc *sc, struct mbuf *m, 1108 struct carp_header *ch, sa_family_t af) 1109 { 1110 struct ifnet *cifp; 1111 uint64_t tmp_counter; 1112 struct timeval sc_tv, ch_tv; 1113 1114 if (sc->sc_vhid != ch->carp_vhid) { 1115 /* 1116 * CARP uses multicast, however, multicast packets 1117 * are tapped to all CARP interfaces on the physical 1118 * interface receiving the CARP packets, so we don't 1119 * update any stats here. 1120 */ 1121 m_freem(m); 1122 return; 1123 } 1124 cifp = &sc->sc_if; 1125 1126 /* verify the CARP version. */ 1127 if (ch->carp_version != CARP_VERSION) { 1128 carpstats.carps_badver++; 1129 CARP_LOG("%s; invalid version %d\n", cifp->if_xname, 1130 ch->carp_version); 1131 m_freem(m); 1132 return; 1133 } 1134 1135 /* verify the hash */ 1136 if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) { 1137 carpstats.carps_badauth++; 1138 CARP_LOG("%s: incorrect hash\n", cifp->if_xname); 1139 m_freem(m); 1140 return; 1141 } 1142 1143 tmp_counter = ntohl(ch->carp_counter[0]); 1144 tmp_counter = tmp_counter<<32; 1145 tmp_counter += ntohl(ch->carp_counter[1]); 1146 1147 /* XXX Replay protection goes here */ 1148 1149 sc->sc_init_counter = 0; 1150 sc->sc_counter = tmp_counter; 1151 1152 sc_tv.tv_sec = sc->sc_advbase; 1153 if (carp_suppress_preempt && sc->sc_advskew < 240) 1154 sc_tv.tv_usec = 240 * 1000000 / 256; 1155 else 1156 sc_tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1157 ch_tv.tv_sec = ch->carp_advbase; 1158 ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; 1159 1160 switch (sc->sc_state) { 1161 case INIT: 1162 break; 1163 1164 case MASTER: 1165 /* 1166 * If we receive an advertisement from a master who's going to 1167 * be more frequent than us, go into BACKUP state. 1168 */ 1169 if (timevalcmp(&sc_tv, &ch_tv, >) || 1170 timevalcmp(&sc_tv, &ch_tv, ==)) { 1171 callout_stop(&sc->sc_ad_tmo); 1172 CARP_DEBUG("%s: MASTER -> BACKUP " 1173 "(more frequent advertisement received)\n", 1174 cifp->if_xname); 1175 carp_set_state(sc, BACKUP); 1176 carp_setrun(sc, 0); 1177 if (carp_opts[CARPCTL_SETROUTE]) 1178 carp_setroute(sc, RTM_DELETE); 1179 } 1180 break; 1181 1182 case BACKUP: 1183 /* 1184 * If we're pre-empting masters who advertise slower than us, 1185 * and this one claims to be slower, treat him as down. 1186 */ 1187 if (carp_opts[CARPCTL_PREEMPT] && 1188 timevalcmp(&sc_tv, &ch_tv, <)) { 1189 CARP_DEBUG("%s: BACKUP -> MASTER " 1190 "(preempting a slower master)\n", cifp->if_xname); 1191 carp_master_down(sc); 1192 break; 1193 } 1194 1195 /* 1196 * If the master is going to advertise at such a low frequency 1197 * that he's guaranteed to time out, we'd might as well just 1198 * treat him as timed out now. 1199 */ 1200 sc_tv.tv_sec = sc->sc_advbase * 3; 1201 if (timevalcmp(&sc_tv, &ch_tv, <)) { 1202 CARP_DEBUG("%s: BACKUP -> MASTER (master timed out)\n", 1203 cifp->if_xname); 1204 carp_master_down(sc); 1205 break; 1206 } 1207 1208 /* 1209 * Otherwise, we reset the counter and wait for the next 1210 * advertisement. 1211 */ 1212 carp_setrun(sc, af); 1213 break; 1214 } 1215 m_freem(m); 1216 } 1217 1218 struct mbuf * 1219 carp_input(void *v, struct mbuf *m) 1220 { 1221 struct carp_if *cif = v; 1222 struct ether_header *eh; 1223 struct carp_softc_container *scc; 1224 struct ifnet *ifp; 1225 1226 eh = mtod(m, struct ether_header *); 1227 1228 ifp = carp_forus(cif, eh->ether_dhost); 1229 if (ifp != NULL) { 1230 ether_reinput_oncpu(ifp, m, REINPUT_RUNBPF); 1231 return NULL; 1232 } 1233 1234 if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) 1235 return m; 1236 1237 /* 1238 * XXX Should really check the list of multicast addresses 1239 * for each CARP interface _before_ copying. 1240 */ 1241 TAILQ_FOREACH(scc, cif, scc_link) { 1242 struct carp_softc *sc = scc->scc_softc; 1243 struct mbuf *m0; 1244 1245 if ((sc->sc_if.if_flags & IFF_UP) == 0) 1246 continue; 1247 1248 m0 = m_dup(m, M_NOWAIT); 1249 if (m0 == NULL) 1250 continue; 1251 1252 ether_reinput_oncpu(&sc->sc_if, m0, REINPUT_RUNBPF); 1253 } 1254 return m; 1255 } 1256 1257 static void 1258 carp_prepare_ad(struct carp_softc *sc, struct carp_header *ch) 1259 { 1260 if (sc->sc_init_counter) { 1261 /* this could also be seconds since unix epoch */ 1262 sc->sc_counter = karc4random(); 1263 sc->sc_counter = sc->sc_counter << 32; 1264 sc->sc_counter += karc4random(); 1265 } else { 1266 sc->sc_counter++; 1267 } 1268 1269 ch->carp_counter[0] = htonl((sc->sc_counter >> 32) & 0xffffffff); 1270 ch->carp_counter[1] = htonl(sc->sc_counter & 0xffffffff); 1271 1272 carp_hmac_generate(sc, ch->carp_counter, ch->carp_md); 1273 } 1274 1275 static void 1276 carp_send_ad_all(void) 1277 { 1278 struct carp_softc *sc; 1279 1280 LIST_FOREACH(sc, &carpif_list, sc_next) { 1281 if (sc->sc_carpdev == NULL) 1282 continue; 1283 1284 if (CARP_IS_RUNNING(&sc->sc_if) && sc->sc_state == MASTER) 1285 carp_send_ad(sc); 1286 } 1287 } 1288 1289 static void 1290 carp_send_ad_timeout(void *xsc) 1291 { 1292 struct carp_softc *sc = xsc; 1293 struct netmsg_carp *cmsg = &sc->sc_ad_msg; 1294 1295 KASSERT(mycpuid == 0, ("%s not on cpu0 but on cpu%d", 1296 __func__, mycpuid)); 1297 1298 crit_enter(); 1299 if (cmsg->base.lmsg.ms_flags & MSGF_DONE) 1300 lwkt_sendmsg_oncpu(netisr_cpuport(0), &cmsg->base.lmsg); 1301 crit_exit(); 1302 } 1303 1304 static void 1305 carp_send_ad_timeout_dispatch(netmsg_t msg) 1306 { 1307 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 1308 struct carp_softc *sc = cmsg->nc_softc; 1309 1310 /* Reply ASAP */ 1311 crit_enter(); 1312 lwkt_replymsg(&cmsg->base.lmsg, 0); 1313 crit_exit(); 1314 1315 carp_send_ad(sc); 1316 } 1317 1318 static void 1319 carp_send_ad(struct carp_softc *sc) 1320 { 1321 struct ifnet *cifp = &sc->sc_if; 1322 struct carp_header ch; 1323 struct timeval tv; 1324 struct carp_header *ch_ptr; 1325 struct mbuf *m; 1326 int len, advbase, advskew; 1327 1328 if (!CARP_IS_RUNNING(cifp)) { 1329 /* Bow out */ 1330 advbase = 255; 1331 advskew = 255; 1332 } else { 1333 advbase = sc->sc_advbase; 1334 if (!carp_suppress_preempt || sc->sc_advskew > 240) 1335 advskew = sc->sc_advskew; 1336 else 1337 advskew = 240; 1338 tv.tv_sec = advbase; 1339 tv.tv_usec = advskew * 1000000 / 256; 1340 } 1341 1342 ch.carp_version = CARP_VERSION; 1343 ch.carp_type = CARP_ADVERTISEMENT; 1344 ch.carp_vhid = sc->sc_vhid; 1345 ch.carp_advbase = advbase; 1346 ch.carp_advskew = advskew; 1347 ch.carp_authlen = 7; /* XXX DEFINE */ 1348 ch.carp_pad1 = 0; /* must be zero */ 1349 ch.carp_cksum = 0; 1350 1351 #ifdef INET 1352 if (sc->sc_ia != NULL) { 1353 struct ip *ip; 1354 1355 MGETHDR(m, M_NOWAIT, MT_HEADER); 1356 if (m == NULL) { 1357 IFNET_STAT_INC(cifp, oerrors, 1); 1358 carpstats.carps_onomem++; 1359 /* XXX maybe less ? */ 1360 if (advbase != 255 || advskew != 255) 1361 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1362 carp_send_ad_timeout, sc); 1363 return; 1364 } 1365 len = sizeof(*ip) + sizeof(ch); 1366 m->m_pkthdr.len = len; 1367 m->m_pkthdr.rcvif = NULL; 1368 m->m_len = len; 1369 MH_ALIGN(m, m->m_len); 1370 m->m_flags |= M_MCAST; 1371 if (carp_prio_ad) 1372 m->m_flags |= M_PRIO; 1373 ip = mtod(m, struct ip *); 1374 ip->ip_v = IPVERSION; 1375 ip->ip_hl = sizeof(*ip) >> 2; 1376 ip->ip_tos = IPTOS_LOWDELAY; 1377 ip->ip_len = len; 1378 ip->ip_id = ip_newid(); 1379 ip->ip_off = IP_DF; 1380 ip->ip_ttl = CARP_DFLTTL; 1381 ip->ip_p = IPPROTO_CARP; 1382 ip->ip_sum = 0; 1383 ip->ip_src = sc->sc_ia->ia_addr.sin_addr; 1384 ip->ip_dst.s_addr = htonl(INADDR_CARP_GROUP); 1385 1386 ch_ptr = (struct carp_header *)(&ip[1]); 1387 bcopy(&ch, ch_ptr, sizeof(ch)); 1388 carp_prepare_ad(sc, ch_ptr); 1389 ch_ptr->carp_cksum = in_cksum_skip(m, len, sizeof(*ip)); 1390 1391 getmicrotime(&cifp->if_lastchange); 1392 IFNET_STAT_INC(cifp, opackets, 1); 1393 IFNET_STAT_INC(cifp, obytes, len); 1394 carpstats.carps_opackets++; 1395 1396 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) { 1397 IFNET_STAT_INC(cifp, oerrors, 1); 1398 if (sc->sc_sendad_errors < INT_MAX) 1399 sc->sc_sendad_errors++; 1400 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { 1401 carp_suppress_preempt++; 1402 if (carp_suppress_preempt == 1) { 1403 carp_send_ad_all(); 1404 } 1405 } 1406 sc->sc_sendad_success = 0; 1407 } else { 1408 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) { 1409 if (++sc->sc_sendad_success >= 1410 CARP_SENDAD_MIN_SUCCESS) { 1411 carp_suppress_preempt--; 1412 sc->sc_sendad_errors = 0; 1413 } 1414 } else { 1415 sc->sc_sendad_errors = 0; 1416 } 1417 } 1418 } 1419 #endif /* INET */ 1420 #ifdef INET6 1421 if (sc->sc_ia6) { 1422 struct ip6_hdr *ip6; 1423 1424 MGETHDR(m, M_NOWAIT, MT_HEADER); 1425 if (m == NULL) { 1426 IFNET_STAT_INC(cifp, oerrors, 1); 1427 carpstats.carps_onomem++; 1428 /* XXX maybe less ? */ 1429 if (advbase != 255 || advskew != 255) 1430 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1431 carp_send_ad_timeout, sc); 1432 return; 1433 } 1434 len = sizeof(*ip6) + sizeof(ch); 1435 m->m_pkthdr.len = len; 1436 m->m_pkthdr.rcvif = NULL; 1437 m->m_len = len; 1438 MH_ALIGN(m, m->m_len); 1439 m->m_flags |= M_MCAST; 1440 ip6 = mtod(m, struct ip6_hdr *); 1441 bzero(ip6, sizeof(*ip6)); 1442 ip6->ip6_vfc |= IPV6_VERSION; 1443 ip6->ip6_hlim = CARP_DFLTTL; 1444 ip6->ip6_nxt = IPPROTO_CARP; 1445 bcopy(&sc->sc_ia6->ia_addr.sin6_addr, &ip6->ip6_src, 1446 sizeof(struct in6_addr)); 1447 /* set the multicast destination */ 1448 1449 ip6->ip6_dst.s6_addr16[0] = htons(0xff02); 1450 ip6->ip6_dst.s6_addr8[15] = 0x12; 1451 if (in6_setscope(&ip6->ip6_dst, sc->sc_carpdev, NULL) != 0) { 1452 IFNET_STAT_INC(cifp, oerrors, 1); 1453 m_freem(m); 1454 CARP_LOG("%s: in6_setscope failed\n", __func__); 1455 return; 1456 } 1457 1458 ch_ptr = (struct carp_header *)(&ip6[1]); 1459 bcopy(&ch, ch_ptr, sizeof(ch)); 1460 carp_prepare_ad(sc, ch_ptr); 1461 ch_ptr->carp_cksum = in_cksum_skip(m, len, sizeof(*ip6)); 1462 1463 getmicrotime(&cifp->if_lastchange); 1464 IFNET_STAT_INC(cifp, opackets, 1); 1465 IFNET_STAT_INC(cifp, obytes, len); 1466 carpstats.carps_opackets6++; 1467 1468 if (ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL, NULL)) { 1469 IFNET_STAT_INC(cifp, oerrors, 1); 1470 if (sc->sc_sendad_errors < INT_MAX) 1471 sc->sc_sendad_errors++; 1472 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { 1473 carp_suppress_preempt++; 1474 if (carp_suppress_preempt == 1) { 1475 carp_send_ad_all(); 1476 } 1477 } 1478 sc->sc_sendad_success = 0; 1479 } else { 1480 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) { 1481 if (++sc->sc_sendad_success >= 1482 CARP_SENDAD_MIN_SUCCESS) { 1483 carp_suppress_preempt--; 1484 sc->sc_sendad_errors = 0; 1485 } 1486 } else { 1487 sc->sc_sendad_errors = 0; 1488 } 1489 } 1490 } 1491 #endif /* INET6 */ 1492 1493 if (advbase != 255 || advskew != 255) 1494 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1495 carp_send_ad_timeout, sc); 1496 } 1497 1498 /* 1499 * Broadcast a gratuitous ARP request containing 1500 * the virtual router MAC address for each IP address 1501 * associated with the virtual router. 1502 */ 1503 static void 1504 carp_send_arp(struct carp_softc *sc) 1505 { 1506 const struct carp_vhaddr *vha; 1507 1508 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1509 if (vha->vha_iaback == NULL) 1510 continue; 1511 arp_gratuitous(&sc->sc_if, &vha->vha_ia->ia_ifa); 1512 } 1513 } 1514 1515 #ifdef INET6 1516 static void 1517 carp_send_na(struct carp_softc *sc) 1518 { 1519 struct ifaddr_container *ifac; 1520 struct in6_addr *in6; 1521 static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; 1522 1523 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], ifa_link) { 1524 struct ifaddr *ifa = ifac->ifa; 1525 1526 if (ifa->ifa_addr->sa_family != AF_INET6) 1527 continue; 1528 1529 in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; 1530 nd6_na_output(sc->sc_carpdev, &mcast, in6, 1531 ND_NA_FLAG_OVERRIDE, 1, NULL); 1532 DELAY(1000); /* XXX */ 1533 } 1534 } 1535 #endif /* INET6 */ 1536 1537 static __inline const struct carp_vhaddr * 1538 carp_find_addr(const struct carp_softc *sc, const struct in_addr *addr) 1539 { 1540 struct carp_vhaddr *vha; 1541 1542 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1543 if (vha->vha_iaback == NULL) 1544 continue; 1545 1546 if (vha->vha_ia->ia_addr.sin_addr.s_addr == addr->s_addr) 1547 return vha; 1548 } 1549 return NULL; 1550 } 1551 1552 #ifdef notyet 1553 static int 1554 carp_iamatch_balance(const struct carp_if *cif, const struct in_addr *itaddr, 1555 const struct in_addr *isaddr, uint8_t **enaddr) 1556 { 1557 const struct carp_softc *vh; 1558 int index, count = 0; 1559 1560 /* 1561 * XXX proof of concept implementation. 1562 * We use the source ip to decide which virtual host should 1563 * handle the request. If we're master of that virtual host, 1564 * then we respond, otherwise, just drop the arp packet on 1565 * the floor. 1566 */ 1567 1568 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1569 if (!CARP_IS_RUNNING(&vh->sc_if)) 1570 continue; 1571 1572 if (carp_find_addr(vh, itaddr) != NULL) 1573 count++; 1574 } 1575 if (count == 0) 1576 return 0; 1577 1578 /* this should be a hash, like pf_hash() */ 1579 index = ntohl(isaddr->s_addr) % count; 1580 count = 0; 1581 1582 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1583 if (!CARP_IS_RUNNING(&vh->sc_if)) 1584 continue; 1585 1586 if (carp_find_addr(vh, itaddr) == NULL) 1587 continue; 1588 1589 if (count == index) { 1590 if (vh->sc_state == MASTER) { 1591 *enaddr = IF_LLADDR(&vh->sc_if); 1592 return 1; 1593 } else { 1594 return 0; 1595 } 1596 } 1597 count++; 1598 } 1599 return 0; 1600 } 1601 #endif 1602 1603 int 1604 carp_iamatch(const struct in_ifaddr *ia) 1605 { 1606 const struct carp_softc *sc = ia->ia_ifp->if_softc; 1607 1608 ASSERT_NETISR0; 1609 1610 #ifdef notyet 1611 if (carp_opts[CARPCTL_ARPBALANCE]) 1612 return carp_iamatch_balance(cif, itaddr, isaddr, enaddr); 1613 #endif 1614 1615 if (!CARP_IS_RUNNING(&sc->sc_if) || sc->sc_state != MASTER) 1616 return 0; 1617 1618 return 1; 1619 } 1620 1621 #ifdef INET6 1622 struct ifaddr * 1623 carp_iamatch6(void *v, struct in6_addr *taddr) 1624 { 1625 #ifdef foo 1626 struct carp_if *cif = v; 1627 struct carp_softc *vh; 1628 1629 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1630 struct ifaddr_container *ifac; 1631 1632 TAILQ_FOREACH(ifac, &vh->sc_if.if_addrheads[mycpuid], 1633 ifa_link) { 1634 struct ifaddr *ifa = ifac->ifa; 1635 1636 if (IN6_ARE_ADDR_EQUAL(taddr, 1637 &ifatoia6(ifa)->ia_addr.sin6_addr) && 1638 CARP_IS_RUNNING(&vh->sc_if) && 1639 vh->sc_state == MASTER) { 1640 return (ifa); 1641 } 1642 } 1643 } 1644 #endif 1645 return (NULL); 1646 } 1647 1648 void * 1649 carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) 1650 { 1651 #ifdef foo 1652 struct m_tag *mtag; 1653 struct carp_if *cif = v; 1654 struct carp_softc *sc; 1655 1656 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { 1657 struct ifaddr_container *ifac; 1658 1659 TAILQ_FOREACH(ifac, &sc->sc_if.if_addrheads[mycpuid], 1660 ifa_link) { 1661 struct ifaddr *ifa = ifac->ifa; 1662 1663 if (IN6_ARE_ADDR_EQUAL(taddr, 1664 &ifatoia6(ifa)->ia_addr.sin6_addr) && 1665 CARP_IS_RUNNING(&sc->sc_if)) { 1666 struct ifnet *ifp = &sc->sc_if; 1667 1668 mtag = m_tag_get(PACKET_TAG_CARP, 1669 sizeof(struct ifnet *), M_NOWAIT); 1670 if (mtag == NULL) { 1671 /* better a bit than nothing */ 1672 return (IF_LLADDR(ifp)); 1673 } 1674 bcopy(&ifp, (caddr_t)(mtag + 1), 1675 sizeof(struct ifnet *)); 1676 m_tag_prepend(m, mtag); 1677 1678 return (IF_LLADDR(ifp)); 1679 } 1680 } 1681 } 1682 #endif 1683 return (NULL); 1684 } 1685 #endif 1686 1687 static struct ifnet * 1688 carp_forus(struct carp_if *cif, const uint8_t *dhost) 1689 { 1690 struct carp_softc_container *scc; 1691 1692 if (memcmp(dhost, carp_etheraddr, ETHER_ADDR_LEN - 1) != 0) 1693 return NULL; 1694 1695 TAILQ_FOREACH(scc, cif, scc_link) { 1696 struct carp_softc *sc = scc->scc_softc; 1697 struct ifnet *ifp = &sc->sc_if; 1698 1699 if (CARP_IS_RUNNING(ifp) && sc->sc_state == MASTER && 1700 !bcmp(dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN)) 1701 return ifp; 1702 } 1703 return NULL; 1704 } 1705 1706 static void 1707 carp_master_down_timeout(void *xsc) 1708 { 1709 struct carp_softc *sc = xsc; 1710 struct netmsg_carp *cmsg = &sc->sc_md_msg; 1711 1712 KASSERT(mycpuid == 0, ("%s not on cpu0 but on cpu%d", 1713 __func__, mycpuid)); 1714 1715 crit_enter(); 1716 if (cmsg->base.lmsg.ms_flags & MSGF_DONE) 1717 lwkt_sendmsg_oncpu(netisr_cpuport(0), &cmsg->base.lmsg); 1718 crit_exit(); 1719 } 1720 1721 static void 1722 carp_master_down_timeout_dispatch(netmsg_t msg) 1723 { 1724 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 1725 struct carp_softc *sc = cmsg->nc_softc; 1726 1727 /* Reply ASAP */ 1728 crit_enter(); 1729 lwkt_replymsg(&cmsg->base.lmsg, 0); 1730 crit_exit(); 1731 1732 CARP_DEBUG("%s: BACKUP -> MASTER (master timed out)\n", 1733 sc->sc_if.if_xname); 1734 carp_master_down(sc); 1735 } 1736 1737 static void 1738 carp_master_down(struct carp_softc *sc) 1739 { 1740 switch (sc->sc_state) { 1741 case INIT: 1742 kprintf("%s: master_down event in INIT state\n", 1743 sc->sc_if.if_xname); 1744 break; 1745 1746 case MASTER: 1747 break; 1748 1749 case BACKUP: 1750 carp_set_state(sc, MASTER); 1751 carp_send_ad(sc); 1752 carp_send_arp(sc); 1753 #ifdef INET6 1754 carp_send_na(sc); 1755 #endif /* INET6 */ 1756 carp_setrun(sc, 0); 1757 if (carp_opts[CARPCTL_SETROUTE]) 1758 carp_setroute(sc, RTM_ADD); 1759 break; 1760 } 1761 } 1762 1763 /* 1764 * When in backup state, af indicates whether to reset the master down timer 1765 * for v4 or v6. If it's set to zero, reset the ones which are already pending. 1766 */ 1767 static void 1768 carp_setrun(struct carp_softc *sc, sa_family_t af) 1769 { 1770 struct ifnet *cifp = &sc->sc_if; 1771 struct timeval tv; 1772 1773 if (sc->sc_carpdev == NULL) { 1774 carp_set_state(sc, INIT); 1775 return; 1776 } 1777 1778 if ((cifp->if_flags & IFF_RUNNING) && sc->sc_vhid > 0 && 1779 (sc->sc_naddrs || sc->sc_naddrs6)) { 1780 /* Nothing */ 1781 } else { 1782 if (carp_opts[CARPCTL_SETROUTE]) 1783 carp_setroute(sc, RTM_DELETE); 1784 return; 1785 } 1786 1787 switch (sc->sc_state) { 1788 case INIT: 1789 if (carp_opts[CARPCTL_PREEMPT] && !carp_suppress_preempt) { 1790 carp_send_ad(sc); 1791 carp_send_arp(sc); 1792 #ifdef INET6 1793 carp_send_na(sc); 1794 #endif /* INET6 */ 1795 CARP_DEBUG("%s: INIT -> MASTER (preempting)\n", 1796 cifp->if_xname); 1797 carp_set_state(sc, MASTER); 1798 if (carp_opts[CARPCTL_SETROUTE]) 1799 carp_setroute(sc, RTM_ADD); 1800 } else { 1801 CARP_DEBUG("%s: INIT -> BACKUP\n", cifp->if_xname); 1802 carp_set_state(sc, BACKUP); 1803 if (carp_opts[CARPCTL_SETROUTE]) 1804 carp_setroute(sc, RTM_DELETE); 1805 carp_setrun(sc, 0); 1806 } 1807 break; 1808 1809 case BACKUP: 1810 callout_stop(&sc->sc_ad_tmo); 1811 tv.tv_sec = 3 * sc->sc_advbase; 1812 tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1813 switch (af) { 1814 #ifdef INET 1815 case AF_INET: 1816 callout_reset(&sc->sc_md_tmo, tvtohz_high(&tv), 1817 carp_master_down_timeout, sc); 1818 break; 1819 #endif /* INET */ 1820 #ifdef INET6 1821 case AF_INET6: 1822 callout_reset(&sc->sc_md6_tmo, tvtohz_high(&tv), 1823 carp_master_down_timeout, sc); 1824 break; 1825 #endif /* INET6 */ 1826 default: 1827 if (sc->sc_naddrs) 1828 callout_reset(&sc->sc_md_tmo, tvtohz_high(&tv), 1829 carp_master_down_timeout, sc); 1830 if (sc->sc_naddrs6) 1831 callout_reset(&sc->sc_md6_tmo, tvtohz_high(&tv), 1832 carp_master_down_timeout, sc); 1833 break; 1834 } 1835 break; 1836 1837 case MASTER: 1838 tv.tv_sec = sc->sc_advbase; 1839 tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1840 callout_reset(&sc->sc_ad_tmo, tvtohz_high(&tv), 1841 carp_send_ad_timeout, sc); 1842 break; 1843 } 1844 } 1845 1846 static void 1847 carp_multicast_cleanup(struct carp_softc *sc) 1848 { 1849 struct ip_moptions *imo = &sc->sc_imo; 1850 1851 if (imo->imo_num_memberships == 0) 1852 return; 1853 KKASSERT(imo->imo_num_memberships == 1); 1854 1855 in_delmulti(imo->imo_membership[0]); 1856 imo->imo_membership[0] = NULL; 1857 imo->imo_num_memberships = 0; 1858 imo->imo_multicast_ifp = NULL; 1859 } 1860 1861 #ifdef INET6 1862 static void 1863 carp_multicast6_cleanup(struct carp_softc *sc) 1864 { 1865 struct ip6_moptions *im6o = &sc->sc_im6o; 1866 1867 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 1868 struct in6_multi_mship *imm = 1869 LIST_FIRST(&im6o->im6o_memberships); 1870 1871 LIST_REMOVE(imm, i6mm_chain); 1872 in6_leavegroup(imm); 1873 } 1874 im6o->im6o_multicast_ifp = NULL; 1875 } 1876 #endif 1877 1878 static void 1879 carp_ioctl_getvhaddr_dispatch(netmsg_t msg) 1880 { 1881 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 1882 struct carp_softc *sc = cmsg->nc_softc; 1883 const struct carp_vhaddr *vha; 1884 struct ifcarpvhaddr *carpa, *carpa0; 1885 int count, len, error = 0; 1886 1887 count = 0; 1888 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 1889 ++count; 1890 1891 if (cmsg->nc_datalen == 0) { 1892 cmsg->nc_datalen = count * sizeof(*carpa); 1893 goto back; 1894 } else if (count == 0 || cmsg->nc_datalen < sizeof(*carpa)) { 1895 cmsg->nc_datalen = 0; 1896 goto back; 1897 } 1898 len = min(cmsg->nc_datalen, sizeof(*carpa) * count); 1899 KKASSERT(len >= sizeof(*carpa)); 1900 1901 carpa0 = carpa = kmalloc(len, M_TEMP, M_WAITOK | M_NULLOK | M_ZERO); 1902 if (carpa == NULL) { 1903 error = ENOMEM; 1904 goto back; 1905 } 1906 1907 count = 0; 1908 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 1909 if (len < sizeof(*carpa)) 1910 break; 1911 1912 carpa->carpa_flags = vha->vha_flags; 1913 carpa->carpa_addr.sin_family = AF_INET; 1914 carpa->carpa_addr.sin_addr = vha->vha_ia->ia_addr.sin_addr; 1915 1916 carpa->carpa_baddr.sin_family = AF_INET; 1917 if (vha->vha_iaback == NULL) { 1918 carpa->carpa_baddr.sin_addr.s_addr = INADDR_ANY; 1919 } else { 1920 carpa->carpa_baddr.sin_addr = 1921 vha->vha_iaback->ia_addr.sin_addr; 1922 } 1923 1924 ++carpa; 1925 ++count; 1926 len -= sizeof(*carpa); 1927 } 1928 cmsg->nc_datalen = sizeof(*carpa) * count; 1929 KKASSERT(cmsg->nc_datalen > 0); 1930 1931 cmsg->nc_data = carpa0; 1932 1933 back: 1934 lwkt_replymsg(&cmsg->base.lmsg, error); 1935 } 1936 1937 static int 1938 carp_ioctl_getvhaddr(struct carp_softc *sc, struct ifdrv *ifd) 1939 { 1940 struct ifnet *ifp = &sc->arpcom.ac_if; 1941 struct netmsg_carp cmsg; 1942 int error; 1943 1944 ASSERT_IFNET_SERIALIZED_ALL(ifp); 1945 ifnet_deserialize_all(ifp); 1946 1947 bzero(&cmsg, sizeof(cmsg)); 1948 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 1949 carp_ioctl_getvhaddr_dispatch); 1950 cmsg.nc_softc = sc; 1951 cmsg.nc_datalen = ifd->ifd_len; 1952 1953 error = lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 1954 1955 if (!error) { 1956 if (cmsg.nc_data != NULL) { 1957 error = copyout(cmsg.nc_data, ifd->ifd_data, 1958 cmsg.nc_datalen); 1959 kfree(cmsg.nc_data, M_TEMP); 1960 } 1961 ifd->ifd_len = cmsg.nc_datalen; 1962 } else { 1963 KASSERT(cmsg.nc_data == NULL, 1964 ("%s temp vhaddr is alloc upon error", __func__)); 1965 } 1966 1967 ifnet_serialize_all(ifp); 1968 return error; 1969 } 1970 1971 static int 1972 carp_config_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 1973 struct in_ifaddr *ia_del) 1974 { 1975 struct ifnet *ifp; 1976 struct in_ifaddr *ia_if; 1977 const struct in_ifaddr *ia_vha; 1978 struct in_ifaddr_container *iac; 1979 int own, ia_match_carpdev; 1980 1981 KKASSERT(vha->vha_ia != NULL); 1982 ia_vha = vha->vha_ia; 1983 1984 ia_if = NULL; 1985 own = 0; 1986 ia_match_carpdev = 0; 1987 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 1988 struct in_ifaddr *ia = iac->ia; 1989 1990 if (ia == ia_del) 1991 continue; 1992 1993 if (ia->ia_ifp->if_type == IFT_CARP) 1994 continue; 1995 1996 if ((ia->ia_ifp->if_flags & IFF_UP) == 0) 1997 continue; 1998 1999 /* and, yeah, we need a multicast-capable iface too */ 2000 if ((ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) 2001 continue; 2002 2003 if (ia_vha->ia_subnetmask == ia->ia_subnetmask && 2004 ia_vha->ia_subnet == ia->ia_subnet) { 2005 if (ia_vha->ia_addr.sin_addr.s_addr == 2006 ia->ia_addr.sin_addr.s_addr) 2007 own = 1; 2008 if (ia_if == NULL) { 2009 ia_if = ia; 2010 } else if (sc->sc_carpdev != NULL && 2011 sc->sc_carpdev == ia->ia_ifp) { 2012 ia_if = ia; 2013 if (ia_if->ia_flags & IFA_ROUTE) { 2014 /* 2015 * Address with prefix route 2016 * is prefered 2017 */ 2018 break; 2019 } 2020 ia_match_carpdev = 1; 2021 } else if (!ia_match_carpdev) { 2022 if (ia->ia_flags & IFA_ROUTE) { 2023 /* 2024 * Address with prefix route 2025 * is prefered over others. 2026 */ 2027 ia_if = ia; 2028 } 2029 } 2030 } 2031 } 2032 2033 carp_deactivate_vhaddr(sc, vha, FALSE); 2034 if (!ia_if) 2035 return ENOENT; 2036 2037 ifp = ia_if->ia_ifp; 2038 2039 /* XXX Don't allow parent iface to be changed */ 2040 if (sc->sc_carpdev != NULL && sc->sc_carpdev != ifp) 2041 return EEXIST; 2042 2043 return carp_activate_vhaddr(sc, vha, ifp, ia_if, own); 2044 } 2045 2046 static void 2047 carp_add_addr(struct carp_softc *sc, struct ifaddr *carp_ifa) 2048 { 2049 struct carp_vhaddr *vha_new; 2050 struct in_ifaddr *carp_ia; 2051 #ifdef INVARIANTS 2052 struct carp_vhaddr *vha; 2053 #endif 2054 2055 KKASSERT(carp_ifa->ifa_addr->sa_family == AF_INET); 2056 carp_ia = ifatoia(carp_ifa); 2057 2058 #ifdef INVARIANTS 2059 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 2060 KKASSERT(vha->vha_ia != NULL && vha->vha_ia != carp_ia); 2061 #endif 2062 2063 vha_new = kmalloc(sizeof(*vha_new), M_CARP, M_WAITOK | M_ZERO); 2064 vha_new->vha_ia = carp_ia; 2065 carp_insert_vhaddr(sc, vha_new); 2066 2067 if (carp_config_vhaddr(sc, vha_new, NULL) != 0) { 2068 /* 2069 * If the above configuration fails, it may only mean 2070 * that the new address is problematic. However, the 2071 * carp(4) interface may already have several working 2072 * addresses. Since the expected behaviour of 2073 * SIOC[AS]IFADDR is to put the NIC into working state, 2074 * we try starting the state machine manually here with 2075 * the hope that the carp(4)'s previously working 2076 * addresses still could be brought up. 2077 */ 2078 carp_hmac_prepare(sc); 2079 carp_set_state(sc, INIT); 2080 carp_setrun(sc, 0); 2081 } 2082 } 2083 2084 static void 2085 carp_del_addr(struct carp_softc *sc, struct ifaddr *carp_ifa) 2086 { 2087 struct carp_vhaddr *vha; 2088 struct in_ifaddr *carp_ia; 2089 2090 KKASSERT(carp_ifa->ifa_addr->sa_family == AF_INET); 2091 carp_ia = ifatoia(carp_ifa); 2092 2093 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 2094 KKASSERT(vha->vha_ia != NULL); 2095 if (vha->vha_ia == carp_ia) 2096 break; 2097 } 2098 KASSERT(vha != NULL, ("no corresponding vhaddr %p", carp_ifa)); 2099 2100 /* 2101 * Remove the vhaddr from the list before deactivating 2102 * the vhaddr, so that the HMAC could be correctly 2103 * updated in carp_deactivate_vhaddr() 2104 */ 2105 carp_remove_vhaddr(sc, vha); 2106 2107 carp_deactivate_vhaddr(sc, vha, FALSE); 2108 kfree(vha, M_CARP); 2109 } 2110 2111 static void 2112 carp_config_addr(struct carp_softc *sc, struct ifaddr *carp_ifa) 2113 { 2114 struct carp_vhaddr *vha; 2115 struct in_ifaddr *carp_ia; 2116 2117 KKASSERT(carp_ifa->ifa_addr->sa_family == AF_INET); 2118 carp_ia = ifatoia(carp_ifa); 2119 2120 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 2121 KKASSERT(vha->vha_ia != NULL); 2122 if (vha->vha_ia == carp_ia) 2123 break; 2124 } 2125 KASSERT(vha != NULL, ("no corresponding vhaddr %p", carp_ifa)); 2126 2127 /* Remove then reinsert, to keep the vhaddr list sorted */ 2128 carp_remove_vhaddr(sc, vha); 2129 carp_insert_vhaddr(sc, vha); 2130 2131 if (carp_config_vhaddr(sc, vha, NULL) != 0) { 2132 /* See the comment in carp_add_addr() */ 2133 carp_hmac_prepare(sc); 2134 carp_set_state(sc, INIT); 2135 carp_setrun(sc, 0); 2136 } 2137 } 2138 2139 #ifdef notyet 2140 2141 #ifdef INET6 2142 static int 2143 carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) 2144 { 2145 struct ifnet *ifp; 2146 struct carp_if *cif; 2147 struct in6_ifaddr *ia, *ia_if; 2148 struct ip6_moptions *im6o = &sc->sc_im6o; 2149 struct in6_multi_mship *imm; 2150 struct in6_addr in6; 2151 int own, error; 2152 2153 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2154 carp_setrun(sc, 0); 2155 return (0); 2156 } 2157 2158 /* we have to do it by hands to check we won't match on us */ 2159 ia_if = NULL; own = 0; 2160 for (ia = in6_ifaddr; ia; ia = ia->ia_next) { 2161 int i; 2162 2163 for (i = 0; i < 4; i++) { 2164 if ((sin6->sin6_addr.s6_addr32[i] & 2165 ia->ia_prefixmask.sin6_addr.s6_addr32[i]) != 2166 (ia->ia_addr.sin6_addr.s6_addr32[i] & 2167 ia->ia_prefixmask.sin6_addr.s6_addr32[i])) 2168 break; 2169 } 2170 /* and, yeah, we need a multicast-capable iface too */ 2171 if (ia->ia_ifp != &sc->sc_if && 2172 (ia->ia_ifp->if_flags & IFF_MULTICAST) && 2173 (i == 4)) { 2174 if (!ia_if) 2175 ia_if = ia; 2176 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 2177 &ia->ia_addr.sin6_addr)) 2178 own++; 2179 } 2180 } 2181 2182 if (!ia_if) 2183 return (EADDRNOTAVAIL); 2184 ia = ia_if; 2185 ifp = ia->ia_ifp; 2186 2187 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 || 2188 (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp)) 2189 return (EADDRNOTAVAIL); 2190 2191 if (!sc->sc_naddrs6) { 2192 im6o->im6o_multicast_ifp = ifp; 2193 2194 /* join CARP multicast address */ 2195 bzero(&in6, sizeof(in6)); 2196 in6.s6_addr16[0] = htons(0xff02); 2197 in6.s6_addr8[15] = 0x12; 2198 if (in6_setscope(&in6, ifp, NULL) != 0) 2199 goto cleanup; 2200 if ((imm = in6_joingroup(ifp, &in6, &error)) == NULL) 2201 goto cleanup; 2202 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); 2203 2204 /* join solicited multicast address */ 2205 bzero(&in6, sizeof(in6)); 2206 in6.s6_addr16[0] = htons(0xff02); 2207 in6.s6_addr32[1] = 0; 2208 in6.s6_addr32[2] = htonl(1); 2209 in6.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3]; 2210 in6.s6_addr8[12] = 0xff; 2211 if (in6_setscope(&in6, ifp, NULL) != 0) 2212 goto cleanup; 2213 if ((imm = in6_joingroup(ifp, &in6, &error)) == NULL) 2214 goto cleanup; 2215 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); 2216 } 2217 2218 #ifdef foo 2219 if (!ifp->if_carp) { 2220 cif = kmalloc(sizeof(*cif), M_CARP, M_WAITOK | M_ZERO); 2221 2222 if ((error = ifpromisc(ifp, 1))) { 2223 kfree(cif, M_CARP); 2224 goto cleanup; 2225 } 2226 2227 TAILQ_INIT(&cif->vhif_vrs); 2228 ifp->if_carp = cif; 2229 } else { 2230 struct carp_softc *vr; 2231 2232 cif = ifp->if_carp; 2233 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 2234 if (vr != sc && vr->sc_vhid == sc->sc_vhid) { 2235 error = EINVAL; 2236 goto cleanup; 2237 } 2238 } 2239 } 2240 #endif 2241 sc->sc_ia6 = ia; 2242 sc->sc_carpdev = ifp; 2243 2244 #ifdef foo 2245 { /* XXX prevent endless loop if already in queue */ 2246 struct carp_softc *vr, *after = NULL; 2247 int myself = 0; 2248 cif = ifp->if_carp; 2249 2250 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 2251 if (vr == sc) 2252 myself = 1; 2253 if (vr->sc_vhid < sc->sc_vhid) 2254 after = vr; 2255 } 2256 2257 if (!myself) { 2258 /* We're trying to keep things in order */ 2259 if (after == NULL) 2260 TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); 2261 else 2262 TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); 2263 } 2264 } 2265 #endif 2266 2267 sc->sc_naddrs6++; 2268 if (own) 2269 sc->sc_advskew = 0; 2270 carp_sc_state(sc); 2271 carp_setrun(sc, 0); 2272 2273 return (0); 2274 2275 cleanup: 2276 /* clean up multicast memberships */ 2277 if (!sc->sc_naddrs6) { 2278 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 2279 imm = LIST_FIRST(&im6o->im6o_memberships); 2280 LIST_REMOVE(imm, i6mm_chain); 2281 in6_leavegroup(imm); 2282 } 2283 } 2284 return (error); 2285 } 2286 2287 static int 2288 carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) 2289 { 2290 int error = 0; 2291 2292 if (!--sc->sc_naddrs6) { 2293 struct carp_if *cif = sc->sc_carpdev->if_carp; 2294 struct ip6_moptions *im6o = &sc->sc_im6o; 2295 2296 callout_stop(&sc->sc_ad_tmo); 2297 sc->sc_vhid = -1; 2298 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 2299 struct in6_multi_mship *imm = 2300 LIST_FIRST(&im6o->im6o_memberships); 2301 2302 LIST_REMOVE(imm, i6mm_chain); 2303 in6_leavegroup(imm); 2304 } 2305 im6o->im6o_multicast_ifp = NULL; 2306 #ifdef foo 2307 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); 2308 if (TAILQ_EMPTY(&cif->vhif_vrs)) { 2309 sc->sc_carpdev->if_carp = NULL; 2310 kfree(cif, M_IFADDR); 2311 } 2312 #endif 2313 } 2314 return (error); 2315 } 2316 #endif /* INET6 */ 2317 2318 #endif 2319 2320 static int 2321 carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr, struct ucred *cr) 2322 { 2323 struct carp_softc *sc = ifp->if_softc; 2324 struct ifreq *ifr = (struct ifreq *)addr; 2325 struct ifdrv *ifd = (struct ifdrv *)addr; 2326 int error = 0; 2327 2328 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2329 2330 switch (cmd) { 2331 case SIOCSIFFLAGS: 2332 if (ifp->if_flags & IFF_UP) { 2333 if ((ifp->if_flags & IFF_RUNNING) == 0) 2334 carp_init(sc); 2335 } else if (ifp->if_flags & IFF_RUNNING) { 2336 carp_ioctl_stop(sc); 2337 } 2338 break; 2339 2340 case SIOCSIFCAP: 2341 carp_ioctl_ifcap(sc, ifr->ifr_reqcap); 2342 break; 2343 2344 case SIOCSVH: 2345 error = carp_ioctl_setvh(sc, ifr->ifr_data, cr); 2346 break; 2347 2348 case SIOCGVH: 2349 error = carp_ioctl_getvh(sc, ifr->ifr_data, cr); 2350 break; 2351 2352 case SIOCGDRVSPEC: 2353 switch (ifd->ifd_cmd) { 2354 case CARPGDEVNAME: 2355 error = carp_ioctl_getdevname(sc, ifd); 2356 break; 2357 2358 case CARPGVHADDR: 2359 error = carp_ioctl_getvhaddr(sc, ifd); 2360 break; 2361 2362 default: 2363 error = EINVAL; 2364 break; 2365 } 2366 break; 2367 2368 default: 2369 error = ether_ioctl(ifp, cmd, addr); 2370 break; 2371 } 2372 2373 return error; 2374 } 2375 2376 static void 2377 carp_ioctl_stop_dispatch(netmsg_t msg) 2378 { 2379 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 2380 struct carp_softc *sc = cmsg->nc_softc; 2381 2382 carp_stop(sc, FALSE); 2383 lwkt_replymsg(&cmsg->base.lmsg, 0); 2384 } 2385 2386 static void 2387 carp_ioctl_stop(struct carp_softc *sc) 2388 { 2389 struct ifnet *ifp = &sc->arpcom.ac_if; 2390 struct netmsg_carp cmsg; 2391 2392 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2393 2394 ifnet_deserialize_all(ifp); 2395 2396 bzero(&cmsg, sizeof(cmsg)); 2397 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 2398 carp_ioctl_stop_dispatch); 2399 cmsg.nc_softc = sc; 2400 2401 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 2402 2403 ifnet_serialize_all(ifp); 2404 } 2405 2406 static void 2407 carp_ioctl_setvh_dispatch(netmsg_t msg) 2408 { 2409 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 2410 struct carp_softc *sc = cmsg->nc_softc; 2411 struct ifnet *ifp = &sc->arpcom.ac_if; 2412 const struct carpreq *carpr = cmsg->nc_data; 2413 int error; 2414 2415 error = 1; 2416 if ((ifp->if_flags & IFF_RUNNING) && 2417 sc->sc_state != INIT && carpr->carpr_state != sc->sc_state) { 2418 switch (carpr->carpr_state) { 2419 case BACKUP: 2420 callout_stop(&sc->sc_ad_tmo); 2421 carp_set_state(sc, BACKUP); 2422 carp_setrun(sc, 0); 2423 if (carp_opts[CARPCTL_SETROUTE]) 2424 carp_setroute(sc, RTM_DELETE); 2425 break; 2426 2427 case MASTER: 2428 carp_master_down(sc); 2429 break; 2430 2431 default: 2432 break; 2433 } 2434 } 2435 if (carpr->carpr_vhid > 0) { 2436 if (carpr->carpr_vhid > 255) { 2437 error = EINVAL; 2438 goto back; 2439 } 2440 if (sc->sc_carpdev) { 2441 struct carp_if *cif = sc->sc_carpdev->if_carp; 2442 struct carp_softc_container *scc; 2443 2444 TAILQ_FOREACH(scc, cif, scc_link) { 2445 struct carp_softc *vr = scc->scc_softc; 2446 2447 if (vr != sc && 2448 vr->sc_vhid == carpr->carpr_vhid) { 2449 error = EEXIST; 2450 goto back; 2451 } 2452 } 2453 } 2454 sc->sc_vhid = carpr->carpr_vhid; 2455 2456 IF_LLADDR(ifp)[5] = sc->sc_vhid; 2457 bcopy(IF_LLADDR(ifp), sc->arpcom.ac_enaddr, 2458 ETHER_ADDR_LEN); 2459 2460 error--; 2461 } 2462 if (carpr->carpr_advbase > 0 || carpr->carpr_advskew > 0) { 2463 if (carpr->carpr_advskew >= 255) { 2464 error = EINVAL; 2465 goto back; 2466 } 2467 if (carpr->carpr_advbase > 255) { 2468 error = EINVAL; 2469 goto back; 2470 } 2471 sc->sc_advbase = carpr->carpr_advbase; 2472 sc->sc_advskew = carpr->carpr_advskew; 2473 error--; 2474 } 2475 bcopy(carpr->carpr_key, sc->sc_key, sizeof(sc->sc_key)); 2476 if (error > 0) { 2477 error = EINVAL; 2478 } else { 2479 error = 0; 2480 carp_setrun(sc, 0); 2481 } 2482 back: 2483 carp_hmac_prepare(sc); 2484 2485 lwkt_replymsg(&cmsg->base.lmsg, error); 2486 } 2487 2488 static int 2489 carp_ioctl_setvh(struct carp_softc *sc, void *udata, struct ucred *cr) 2490 { 2491 struct ifnet *ifp = &sc->arpcom.ac_if; 2492 struct netmsg_carp cmsg; 2493 struct carpreq carpr; 2494 int error; 2495 2496 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2497 ifnet_deserialize_all(ifp); 2498 2499 error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY); 2500 if (error) 2501 goto back; 2502 2503 error = copyin(udata, &carpr, sizeof(carpr)); 2504 if (error) 2505 goto back; 2506 2507 bzero(&cmsg, sizeof(cmsg)); 2508 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 2509 carp_ioctl_setvh_dispatch); 2510 cmsg.nc_softc = sc; 2511 cmsg.nc_data = &carpr; 2512 2513 error = lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 2514 2515 back: 2516 ifnet_serialize_all(ifp); 2517 return error; 2518 } 2519 2520 static void 2521 carp_ioctl_ifcap_dispatch(netmsg_t msg) 2522 { 2523 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 2524 struct carp_softc *sc = cmsg->nc_softc; 2525 struct ifnet *ifp = &sc->arpcom.ac_if; 2526 int reqcap = *((const int *)(cmsg->nc_data)); 2527 int mask; 2528 2529 mask = reqcap ^ ifp->if_capenable; 2530 if (mask & IFCAP_TXCSUM) { 2531 ifp->if_capenable ^= IFCAP_TXCSUM; 2532 if ((ifp->if_capenable & IFCAP_TXCSUM) && 2533 sc->sc_carpdev != NULL) { 2534 ifp->if_hwassist |= 2535 (sc->sc_carpdev->if_hwassist & 2536 (CSUM_IP | CSUM_UDP | CSUM_TCP)); 2537 } else { 2538 ifp->if_hwassist &= ~(CSUM_IP | CSUM_UDP | CSUM_TCP); 2539 } 2540 } 2541 if (mask & IFCAP_TSO) { 2542 ifp->if_capenable ^= IFCAP_TSO; 2543 if ((ifp->if_capenable & IFCAP_TSO) && 2544 sc->sc_carpdev != NULL) { 2545 ifp->if_hwassist |= 2546 (sc->sc_carpdev->if_hwassist & CSUM_TSO); 2547 } else { 2548 ifp->if_hwassist &= ~CSUM_TSO; 2549 } 2550 } 2551 2552 lwkt_replymsg(&cmsg->base.lmsg, 0); 2553 } 2554 2555 static void 2556 carp_ioctl_ifcap(struct carp_softc *sc, int reqcap) 2557 { 2558 struct ifnet *ifp = &sc->arpcom.ac_if; 2559 struct netmsg_carp cmsg; 2560 2561 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2562 ifnet_deserialize_all(ifp); 2563 2564 bzero(&cmsg, sizeof(cmsg)); 2565 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 2566 carp_ioctl_ifcap_dispatch); 2567 cmsg.nc_softc = sc; 2568 cmsg.nc_data = &reqcap; 2569 2570 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 2571 2572 ifnet_serialize_all(ifp); 2573 } 2574 2575 static void 2576 carp_ioctl_getvh_dispatch(netmsg_t msg) 2577 { 2578 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 2579 struct carp_softc *sc = cmsg->nc_softc; 2580 struct carpreq *carpr = cmsg->nc_data; 2581 2582 carpr->carpr_state = sc->sc_state; 2583 carpr->carpr_vhid = sc->sc_vhid; 2584 carpr->carpr_advbase = sc->sc_advbase; 2585 carpr->carpr_advskew = sc->sc_advskew; 2586 bcopy(sc->sc_key, carpr->carpr_key, sizeof(carpr->carpr_key)); 2587 2588 lwkt_replymsg(&cmsg->base.lmsg, 0); 2589 } 2590 2591 static int 2592 carp_ioctl_getvh(struct carp_softc *sc, void *udata, struct ucred *cr) 2593 { 2594 struct ifnet *ifp = &sc->arpcom.ac_if; 2595 struct netmsg_carp cmsg; 2596 struct carpreq carpr; 2597 int error; 2598 2599 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2600 ifnet_deserialize_all(ifp); 2601 2602 bzero(&cmsg, sizeof(cmsg)); 2603 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 2604 carp_ioctl_getvh_dispatch); 2605 cmsg.nc_softc = sc; 2606 cmsg.nc_data = &carpr; 2607 2608 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 2609 2610 error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY); 2611 if (error) 2612 bzero(carpr.carpr_key, sizeof(carpr.carpr_key)); 2613 2614 error = copyout(&carpr, udata, sizeof(carpr)); 2615 2616 ifnet_serialize_all(ifp); 2617 return error; 2618 } 2619 2620 static void 2621 carp_ioctl_getdevname_dispatch(netmsg_t msg) 2622 { 2623 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 2624 struct carp_softc *sc = cmsg->nc_softc; 2625 char *devname = cmsg->nc_data; 2626 2627 bzero(devname, IFNAMSIZ); 2628 if (sc->sc_carpdev != NULL) 2629 strlcpy(devname, sc->sc_carpdev->if_xname, IFNAMSIZ); 2630 2631 lwkt_replymsg(&cmsg->base.lmsg, 0); 2632 } 2633 2634 static int 2635 carp_ioctl_getdevname(struct carp_softc *sc, struct ifdrv *ifd) 2636 { 2637 struct ifnet *ifp = &sc->arpcom.ac_if; 2638 struct netmsg_carp cmsg; 2639 char devname[IFNAMSIZ]; 2640 int error; 2641 2642 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2643 2644 if (ifd->ifd_len != sizeof(devname)) 2645 return EINVAL; 2646 2647 ifnet_deserialize_all(ifp); 2648 2649 bzero(&cmsg, sizeof(cmsg)); 2650 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 2651 carp_ioctl_getdevname_dispatch); 2652 cmsg.nc_softc = sc; 2653 cmsg.nc_data = devname; 2654 2655 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 2656 2657 error = copyout(devname, ifd->ifd_data, sizeof(devname)); 2658 2659 ifnet_serialize_all(ifp); 2660 return error; 2661 } 2662 2663 static void 2664 carp_init_dispatch(netmsg_t msg) 2665 { 2666 struct netmsg_carp *cmsg = (struct netmsg_carp *)msg; 2667 struct carp_softc *sc = cmsg->nc_softc; 2668 2669 sc->sc_if.if_flags |= IFF_RUNNING; 2670 carp_hmac_prepare(sc); 2671 carp_set_state(sc, INIT); 2672 carp_setrun(sc, 0); 2673 2674 lwkt_replymsg(&cmsg->base.lmsg, 0); 2675 } 2676 2677 static void 2678 carp_init(void *xsc) 2679 { 2680 struct carp_softc *sc = xsc; 2681 struct ifnet *ifp = &sc->arpcom.ac_if; 2682 struct netmsg_carp cmsg; 2683 2684 ASSERT_IFNET_SERIALIZED_ALL(ifp); 2685 2686 ifnet_deserialize_all(ifp); 2687 2688 bzero(&cmsg, sizeof(cmsg)); 2689 netmsg_init(&cmsg.base, NULL, &curthread->td_msgport, 0, 2690 carp_init_dispatch); 2691 cmsg.nc_softc = sc; 2692 2693 lwkt_domsg(netisr_cpuport(0), &cmsg.base.lmsg, 0); 2694 2695 ifnet_serialize_all(ifp); 2696 } 2697 2698 static int 2699 carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 2700 struct rtentry *rt) 2701 { 2702 struct carp_softc *sc = ifp->if_softc; 2703 struct ifnet *carpdev; 2704 int error = 0; 2705 2706 carpdev = sc->sc_carpdev; 2707 if (carpdev != NULL) { 2708 if (m->m_flags & M_MCAST) 2709 IFNET_STAT_INC(ifp, omcasts, 1); 2710 IFNET_STAT_INC(ifp, obytes, m->m_pkthdr.len + ETHER_HDR_LEN); 2711 IFNET_STAT_INC(ifp, opackets, 1); 2712 2713 /* 2714 * NOTE: 2715 * CARP's ifp is passed to backing device's 2716 * if_output method. 2717 */ 2718 carpdev->if_output(ifp, m, dst, rt); 2719 } else { 2720 IFNET_STAT_INC(ifp, oerrors, 1); 2721 m_freem(m); 2722 error = ENETUNREACH; 2723 } 2724 return error; 2725 } 2726 2727 /* 2728 * Start output on carp interface. This function should never be called. 2729 */ 2730 static void 2731 carp_start(struct ifnet *ifp, struct ifaltq_subque *ifsq __unused) 2732 { 2733 panic("%s: start called", ifp->if_xname); 2734 } 2735 2736 static void 2737 carp_set_state(struct carp_softc *sc, int state) 2738 { 2739 struct ifnet *cifp = &sc->sc_if; 2740 2741 if (sc->sc_state == state) 2742 return; 2743 sc->sc_state = state; 2744 2745 switch (sc->sc_state) { 2746 case BACKUP: 2747 cifp->if_link_state = LINK_STATE_DOWN; 2748 break; 2749 2750 case MASTER: 2751 cifp->if_link_state = LINK_STATE_UP; 2752 break; 2753 2754 default: 2755 cifp->if_link_state = LINK_STATE_UNKNOWN; 2756 break; 2757 } 2758 rt_ifmsg(cifp); 2759 } 2760 2761 void 2762 carp_group_demote_adj(struct ifnet *ifp, int adj) 2763 { 2764 struct ifg_list *ifgl; 2765 int *dm; 2766 2767 TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { 2768 if (!strcmp(ifgl->ifgl_group->ifg_group, IFG_ALL)) 2769 continue; 2770 dm = &ifgl->ifgl_group->ifg_carp_demoted; 2771 2772 if (*dm + adj >= 0) 2773 *dm += adj; 2774 else 2775 *dm = 0; 2776 2777 if (adj > 0 && *dm == 1) 2778 carp_send_ad_all(); 2779 CARP_LOG("%s demoted group %s to %d", ifp->if_xname, 2780 ifgl->ifgl_group->ifg_group, *dm); 2781 } 2782 } 2783 2784 #ifdef foo 2785 void 2786 carp_carpdev_state(void *v) 2787 { 2788 struct carp_if *cif = v; 2789 struct carp_softc *sc; 2790 2791 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) 2792 carp_sc_state(sc); 2793 } 2794 2795 static void 2796 carp_sc_state(struct carp_softc *sc) 2797 { 2798 if (!(sc->sc_carpdev->if_flags & IFF_UP)) { 2799 callout_stop(&sc->sc_ad_tmo); 2800 callout_stop(&sc->sc_md_tmo); 2801 callout_stop(&sc->sc_md6_tmo); 2802 carp_set_state(sc, INIT); 2803 carp_setrun(sc, 0); 2804 if (!sc->sc_suppress) { 2805 carp_suppress_preempt++; 2806 if (carp_suppress_preempt == 1) 2807 carp_send_ad_all(); 2808 } 2809 sc->sc_suppress = 1; 2810 } else { 2811 carp_set_state(sc, INIT); 2812 carp_setrun(sc, 0); 2813 if (sc->sc_suppress) 2814 carp_suppress_preempt--; 2815 sc->sc_suppress = 0; 2816 } 2817 } 2818 #endif 2819 2820 static void 2821 carp_stop(struct carp_softc *sc, boolean_t detach) 2822 { 2823 sc->sc_if.if_flags &= ~IFF_RUNNING; 2824 2825 callout_stop(&sc->sc_ad_tmo); 2826 callout_stop(&sc->sc_md_tmo); 2827 callout_stop(&sc->sc_md6_tmo); 2828 2829 if (!detach && sc->sc_state == MASTER) 2830 carp_send_ad(sc); 2831 2832 if (sc->sc_suppress) 2833 carp_suppress_preempt--; 2834 sc->sc_suppress = 0; 2835 2836 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) 2837 carp_suppress_preempt--; 2838 sc->sc_sendad_errors = 0; 2839 sc->sc_sendad_success = 0; 2840 2841 carp_set_state(sc, INIT); 2842 carp_setrun(sc, 0); 2843 } 2844 2845 static void 2846 carp_suspend(struct carp_softc *sc, boolean_t detach) 2847 { 2848 struct ifnet *cifp = &sc->sc_if; 2849 2850 carp_stop(sc, detach); 2851 2852 /* Retain the running state, if we are not dead yet */ 2853 if (!sc->sc_dead && (cifp->if_flags & IFF_UP)) 2854 cifp->if_flags |= IFF_RUNNING; 2855 } 2856 2857 static int 2858 carp_activate_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 2859 struct ifnet *ifp, struct in_ifaddr *ia_if, int own) 2860 { 2861 struct ip_moptions *imo = &sc->sc_imo; 2862 struct carp_if *ocif = ifp->if_carp; 2863 int error; 2864 2865 KKASSERT(vha->vha_ia != NULL); 2866 2867 KASSERT(ia_if != NULL, ("NULL backing address")); 2868 KASSERT(vha->vha_iaback == NULL, ("%p is already activated", vha)); 2869 KASSERT((vha->vha_flags & CARP_VHAF_OWNER) == 0, 2870 ("inactive vhaddr %p is the address owner", vha)); 2871 2872 KASSERT(sc->sc_carpdev == NULL || sc->sc_carpdev == ifp, 2873 ("%s is already on %s", sc->sc_if.if_xname, 2874 sc->sc_carpdev->if_xname)); 2875 2876 if (ocif == NULL) { 2877 KASSERT(sc->sc_carpdev == NULL, 2878 ("%s is already on %s", sc->sc_if.if_xname, 2879 sc->sc_carpdev->if_xname)); 2880 2881 error = ifpromisc(ifp, 1); 2882 if (error) 2883 return error; 2884 } else { 2885 struct carp_softc_container *scc; 2886 2887 TAILQ_FOREACH(scc, ocif, scc_link) { 2888 struct carp_softc *vr = scc->scc_softc; 2889 2890 if (vr != sc && vr->sc_vhid == sc->sc_vhid) 2891 return EINVAL; 2892 } 2893 } 2894 2895 ifp->if_carp = carp_if_insert(ocif, sc); 2896 KASSERT(ifp->if_carp != NULL, ("%s carp_if_insert failed", __func__)); 2897 2898 sc->sc_ia = ia_if; 2899 sc->sc_carpdev = ifp; 2900 sc->arpcom.ac_if.if_hwassist = 0; 2901 if (sc->arpcom.ac_if.if_capenable & IFCAP_TXCSUM) { 2902 sc->arpcom.ac_if.if_hwassist |= 2903 (ifp->if_hwassist & (CSUM_IP | CSUM_UDP | CSUM_TCP)); 2904 } 2905 if (sc->arpcom.ac_if.if_capenable & IFCAP_TSO) 2906 sc->arpcom.ac_if.if_hwassist |= (ifp->if_hwassist & CSUM_TSO); 2907 2908 /* 2909 * Make sure that all protocol threads see the sc_carpdev and 2910 * if_carp changes 2911 */ 2912 netmsg_service_sync(); 2913 2914 if (ocif != NULL && ifp->if_carp != ocif) { 2915 /* 2916 * The old carp list could be safely free now, 2917 * since no one can access it. 2918 */ 2919 carp_if_free(ocif); 2920 } 2921 2922 vha->vha_iaback = ia_if; 2923 sc->sc_naddrs++; 2924 2925 if (own) { 2926 vha->vha_flags |= CARP_VHAF_OWNER; 2927 2928 /* XXX save user configured advskew? */ 2929 sc->sc_advskew = 0; 2930 } 2931 2932 carp_addroute_vhaddr(sc, vha); 2933 2934 /* 2935 * Join the multicast group only after the backing interface 2936 * has been hooked with the CARP interface. 2937 */ 2938 KASSERT(imo->imo_multicast_ifp == NULL || 2939 imo->imo_multicast_ifp == &sc->sc_if, 2940 ("%s didn't leave mcast group on %s", 2941 sc->sc_if.if_xname, imo->imo_multicast_ifp->if_xname)); 2942 2943 if (imo->imo_num_memberships == 0) { 2944 struct in_addr addr; 2945 2946 addr.s_addr = htonl(INADDR_CARP_GROUP); 2947 imo->imo_membership[0] = in_addmulti(&addr, &sc->sc_if); 2948 if (imo->imo_membership[0] == NULL) { 2949 carp_deactivate_vhaddr(sc, vha, FALSE); 2950 return ENOBUFS; 2951 } 2952 2953 imo->imo_num_memberships++; 2954 imo->imo_multicast_ifp = &sc->sc_if; 2955 imo->imo_multicast_ttl = CARP_DFLTTL; 2956 imo->imo_multicast_loop = 0; 2957 } 2958 2959 carp_hmac_prepare(sc); 2960 carp_set_state(sc, INIT); 2961 carp_setrun(sc, 0); 2962 return 0; 2963 } 2964 2965 static void 2966 carp_deactivate_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 2967 boolean_t del_iaback) 2968 { 2969 KKASSERT(vha->vha_ia != NULL); 2970 2971 carp_hmac_prepare(sc); 2972 2973 if (vha->vha_iaback == NULL) { 2974 KASSERT((vha->vha_flags & CARP_VHAF_OWNER) == 0, 2975 ("inactive vhaddr %p is the address owner", vha)); 2976 return; 2977 } 2978 2979 vha->vha_flags &= ~CARP_VHAF_OWNER; 2980 carp_delroute_vhaddr(sc, vha, del_iaback); 2981 2982 KKASSERT(sc->sc_naddrs > 0); 2983 vha->vha_iaback = NULL; 2984 sc->sc_naddrs--; 2985 if (!sc->sc_naddrs) { 2986 if (sc->sc_naddrs6) { 2987 carp_multicast_cleanup(sc); 2988 sc->sc_ia = NULL; 2989 } else { 2990 carp_detach(sc, FALSE, del_iaback); 2991 } 2992 } 2993 } 2994 2995 static void 2996 carp_link_addrs(struct carp_softc *sc, struct ifnet *ifp, struct ifaddr *ifa_if) 2997 { 2998 struct carp_vhaddr *vha; 2999 struct in_ifaddr *ia_if; 3000 3001 KKASSERT(ifa_if->ifa_addr->sa_family == AF_INET); 3002 ia_if = ifatoia(ifa_if); 3003 3004 /* 3005 * Test each inactive vhaddr against the newly added address. 3006 * If the newly added address could be the backing address, 3007 * then activate the matching vhaddr. 3008 */ 3009 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 3010 const struct in_ifaddr *ia; 3011 int own; 3012 3013 if (vha->vha_iaback != NULL) 3014 continue; 3015 3016 ia = vha->vha_ia; 3017 if (ia->ia_subnetmask != ia_if->ia_subnetmask || 3018 ia->ia_subnet != ia_if->ia_subnet) 3019 continue; 3020 3021 own = 0; 3022 if (ia->ia_addr.sin_addr.s_addr == 3023 ia_if->ia_addr.sin_addr.s_addr) 3024 own = 1; 3025 3026 carp_activate_vhaddr(sc, vha, ifp, ia_if, own); 3027 } 3028 } 3029 3030 static void 3031 carp_unlink_addrs(struct carp_softc *sc, struct ifnet *ifp, 3032 struct ifaddr *ifa_if) 3033 { 3034 struct carp_vhaddr *vha; 3035 struct in_ifaddr *ia_if; 3036 3037 KKASSERT(ifa_if->ifa_addr->sa_family == AF_INET); 3038 ia_if = ifatoia(ifa_if); 3039 3040 /* 3041 * Ad src address is deleted; set it to NULL. 3042 * Following loop will try pick up a new ad src address 3043 * if one of the vhaddr could retain its backing address. 3044 */ 3045 if (sc->sc_ia == ia_if) 3046 sc->sc_ia = NULL; 3047 3048 /* 3049 * Test each active vhaddr against the deleted address. 3050 * If the deleted address is vhaddr address's backing 3051 * address, then deactivate the vhaddr. 3052 */ 3053 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) { 3054 if (vha->vha_iaback == NULL) 3055 continue; 3056 3057 if (vha->vha_iaback == ia_if) 3058 carp_deactivate_vhaddr(sc, vha, TRUE); 3059 else if (sc->sc_ia == NULL) 3060 sc->sc_ia = vha->vha_iaback; 3061 } 3062 } 3063 3064 static void 3065 carp_update_addrs(struct carp_softc *sc, struct ifaddr *ifa_del) 3066 { 3067 struct carp_vhaddr *vha; 3068 3069 KKASSERT(sc->sc_carpdev == NULL); 3070 3071 TAILQ_FOREACH(vha, &sc->sc_vha_list, vha_link) 3072 carp_config_vhaddr(sc, vha, ifatoia(ifa_del)); 3073 } 3074 3075 static void 3076 carp_ifaddr(void *arg __unused, struct ifnet *ifp, 3077 enum ifaddr_event event, struct ifaddr *ifa) 3078 { 3079 struct carp_softc *sc; 3080 3081 if (ifa->ifa_addr->sa_family != AF_INET) 3082 return; 3083 3084 ASSERT_NETISR0; 3085 3086 if (ifp->if_type == IFT_CARP) { 3087 /* 3088 * Address is changed on carp(4) interface 3089 */ 3090 switch (event) { 3091 case IFADDR_EVENT_ADD: 3092 carp_add_addr(ifp->if_softc, ifa); 3093 break; 3094 3095 case IFADDR_EVENT_CHANGE: 3096 carp_config_addr(ifp->if_softc, ifa); 3097 break; 3098 3099 case IFADDR_EVENT_DELETE: 3100 carp_del_addr(ifp->if_softc, ifa); 3101 break; 3102 } 3103 return; 3104 } 3105 3106 /* 3107 * Address is changed on non-carp(4) interface 3108 */ 3109 if ((ifp->if_flags & IFF_MULTICAST) == 0) 3110 return; 3111 3112 LIST_FOREACH(sc, &carpif_list, sc_next) { 3113 if (sc->sc_carpdev != NULL && sc->sc_carpdev != ifp) { 3114 /* Not the parent iface; skip */ 3115 continue; 3116 } 3117 3118 switch (event) { 3119 case IFADDR_EVENT_ADD: 3120 carp_link_addrs(sc, ifp, ifa); 3121 break; 3122 3123 case IFADDR_EVENT_DELETE: 3124 if (sc->sc_carpdev != NULL) { 3125 carp_unlink_addrs(sc, ifp, ifa); 3126 if (sc->sc_carpdev == NULL) { 3127 /* 3128 * We no longer have the parent 3129 * interface, however, certain 3130 * virtual addresses, which are 3131 * not used because they can't 3132 * match the previous parent 3133 * interface's addresses, may now 3134 * match different interface's 3135 * addresses. 3136 */ 3137 carp_update_addrs(sc, ifa); 3138 } 3139 } else { 3140 /* 3141 * The carp(4) interface didn't have a 3142 * parent iface, so it is not possible 3143 * that it will contain any address to 3144 * be unlinked. 3145 */ 3146 } 3147 break; 3148 3149 case IFADDR_EVENT_CHANGE: 3150 if (sc->sc_carpdev == NULL) { 3151 /* 3152 * The carp(4) interface didn't have a 3153 * parent iface, so it is not possible 3154 * that it will contain any address to 3155 * be updated. 3156 */ 3157 carp_link_addrs(sc, ifp, ifa); 3158 } else { 3159 /* 3160 * First try breaking tie with the old 3161 * address. Then see whether we could 3162 * link certain vhaddr to the new address. 3163 * If that fails, i.e. carpdev is NULL, 3164 * we try a global update. 3165 * 3166 * NOTE: The above order is critical. 3167 */ 3168 carp_unlink_addrs(sc, ifp, ifa); 3169 carp_link_addrs(sc, ifp, ifa); 3170 if (sc->sc_carpdev == NULL) { 3171 /* 3172 * See the comment in the above 3173 * IFADDR_EVENT_DELETE block. 3174 */ 3175 carp_update_addrs(sc, NULL); 3176 } 3177 } 3178 break; 3179 } 3180 } 3181 } 3182 3183 void 3184 carp_proto_ctlinput(netmsg_t msg) 3185 { 3186 int cmd = msg->ctlinput.nm_cmd; 3187 struct sockaddr *sa = msg->ctlinput.nm_arg; 3188 struct in_ifaddr_container *iac; 3189 3190 /* We only process PRC_IFDOWN and PRC_IFUP commands */ 3191 if (cmd != PRC_IFDOWN && cmd != PRC_IFUP) 3192 goto done; 3193 3194 TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { 3195 struct in_ifaddr *ia = iac->ia; 3196 struct ifnet *ifp = ia->ia_ifp; 3197 3198 if (ifp->if_type == IFT_CARP) 3199 continue; 3200 3201 if (ia->ia_ifa.ifa_addr == sa) { 3202 if (cmd == PRC_IFDOWN) { 3203 carp_ifaddr(NULL, ifp, IFADDR_EVENT_DELETE, 3204 &ia->ia_ifa); 3205 } else if (cmd == PRC_IFUP) { 3206 carp_ifaddr(NULL, ifp, IFADDR_EVENT_ADD, 3207 &ia->ia_ifa); 3208 } 3209 break; 3210 } 3211 } 3212 done: 3213 lwkt_replymsg(&msg->lmsg, 0); 3214 } 3215 3216 struct ifnet * 3217 carp_parent(struct ifnet *cifp) 3218 { 3219 struct carp_softc *sc; 3220 3221 KKASSERT(cifp->if_type == IFT_CARP); 3222 sc = cifp->if_softc; 3223 3224 return sc->sc_carpdev; 3225 } 3226 3227 #define rtinitflags(x) \ 3228 (((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) \ 3229 ? RTF_HOST : 0) 3230 3231 static int 3232 carp_addroute_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha) 3233 { 3234 struct in_ifaddr *ia, *iaback; 3235 3236 if (sc->sc_state != MASTER) 3237 return 0; 3238 3239 ia = vha->vha_ia; 3240 KKASSERT(ia != NULL); 3241 3242 iaback = vha->vha_iaback; 3243 KKASSERT(iaback != NULL); 3244 3245 return rtchange(&iaback->ia_ifa, &ia->ia_ifa); 3246 } 3247 3248 static void 3249 carp_delroute_vhaddr(struct carp_softc *sc, struct carp_vhaddr *vha, 3250 boolean_t del_iaback) 3251 { 3252 struct in_ifaddr *ia, *iaback; 3253 3254 ia = vha->vha_ia; 3255 KKASSERT(ia != NULL); 3256 3257 iaback = vha->vha_iaback; 3258 KKASSERT(iaback != NULL); 3259 3260 if (!del_iaback && (iaback->ia_ifp->if_flags & IFF_UP)) { 3261 rtchange(&ia->ia_ifa, &iaback->ia_ifa); 3262 return; 3263 } 3264 3265 rtinit(&ia->ia_ifa, RTM_DELETE, rtinitflags(ia)); 3266 in_ifadown_force(&ia->ia_ifa, 1); 3267 ia->ia_flags &= ~IFA_ROUTE; 3268 } 3269 3270 static int 3271 carp_modevent(module_t mod, int type, void *data) 3272 { 3273 switch (type) { 3274 case MOD_LOAD: 3275 LIST_INIT(&carpif_list); 3276 carp_ifdetach_event = 3277 EVENTHANDLER_REGISTER(ifnet_detach_event, carp_ifdetach, NULL, 3278 EVENTHANDLER_PRI_ANY); 3279 carp_ifaddr_event = 3280 EVENTHANDLER_REGISTER(ifaddr_event, carp_ifaddr, NULL, 3281 EVENTHANDLER_PRI_FIRST); 3282 if_clone_attach(&carp_cloner); 3283 break; 3284 3285 case MOD_UNLOAD: 3286 EVENTHANDLER_DEREGISTER(ifnet_detach_event, 3287 carp_ifdetach_event); 3288 EVENTHANDLER_DEREGISTER(ifaddr_event, 3289 carp_ifaddr_event); 3290 if_clone_detach(&carp_cloner); 3291 break; 3292 3293 default: 3294 return (EINVAL); 3295 } 3296 return (0); 3297 } 3298 3299 static moduledata_t carp_mod = { 3300 "carp", 3301 carp_modevent, 3302 0 3303 }; 3304 DECLARE_MODULE(carp, carp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 3305