ip_carp.c revision 142446
1254721Semaste/* $FreeBSD: head/sys/netinet/ip_carp.c 142446 2005-02-25 10:09:44Z glebius $ */ 2254721Semaste 3254721Semaste/* 4254721Semaste * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 5254721Semaste * Copyright (c) 2003 Ryan McBride. All rights reserved. 6254721Semaste * 7254721Semaste * Redistribution and use in source and binary forms, with or without 8254721Semaste * modification, are permitted provided that the following conditions 9254721Semaste * are met: 10254721Semaste * 1. Redistributions of source code must retain the above copyright 11254721Semaste * notice, this list of conditions and the following disclaimer. 12254721Semaste * 2. Redistributions in binary form must reproduce the above copyright 13254721Semaste * notice, this list of conditions and the following disclaimer in the 14254721Semaste * documentation and/or other materials provided with the distribution. 15254721Semaste * 16254721Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17254721Semaste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18254721Semaste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19254721Semaste * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20254721Semaste * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21254721Semaste * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22254721Semaste * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23254721Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24254721Semaste * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25254721Semaste * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26254721Semaste * THE POSSIBILITY OF SUCH DAMAGE. 27254721Semaste */ 28254721Semaste 29254721Semaste#include "opt_carp.h" 30254721Semaste#include "opt_bpf.h" 31254721Semaste#include "opt_inet.h" 32254721Semaste#include "opt_inet6.h" 33254721Semaste 34254721Semaste#include <sys/types.h> 35254721Semaste#include <sys/param.h> 36254721Semaste#include <sys/systm.h> 37254721Semaste#include <sys/conf.h> 38254721Semaste#include <sys/kernel.h> 39254721Semaste#include <sys/limits.h> 40254721Semaste#include <sys/malloc.h> 41254721Semaste#include <sys/mbuf.h> 42254721Semaste#include <sys/module.h> 43254721Semaste#include <sys/time.h> 44254721Semaste#include <sys/proc.h> 45254721Semaste#include <sys/sysctl.h> 46254721Semaste#include <sys/syslog.h> 47254721Semaste#include <sys/signalvar.h> 48254721Semaste#include <sys/filio.h> 49254721Semaste#include <sys/sockio.h> 50254721Semaste 51254721Semaste#include <sys/socket.h> 52254721Semaste#include <sys/vnode.h> 53254721Semaste 54254721Semaste#include <machine/stdarg.h> 55254721Semaste 56254721Semaste#include <net/bpf.h> 57254721Semaste#include <net/ethernet.h> 58254721Semaste#include <net/fddi.h> 59254721Semaste#include <net/iso88025.h> 60254721Semaste#include <net/if.h> 61254721Semaste#include <net/if_clone.h> 62254721Semaste#include <net/if_types.h> 63254721Semaste#include <net/route.h> 64254721Semaste 65254721Semaste#ifdef INET 66254721Semaste#include <netinet/in.h> 67254721Semaste#include <netinet/in_var.h> 68254721Semaste#include <netinet/in_systm.h> 69254721Semaste#include <netinet/ip.h> 70254721Semaste#include <netinet/ip_var.h> 71254721Semaste#include <netinet/if_ether.h> 72254721Semaste#include <machine/in_cksum.h> 73254721Semaste#endif 74254721Semaste 75254721Semaste#ifdef INET6 76254721Semaste#include <netinet/icmp6.h> 77254721Semaste#include <netinet/ip6.h> 78254721Semaste#include <netinet6/ip6_var.h> 79254721Semaste#include <netinet6/nd6.h> 80254721Semaste#include <net/if_dl.h> 81254721Semaste#endif 82254721Semaste 83254721Semaste#include <crypto/sha1.h> 84254721Semaste#include <netinet/ip_carp.h> 85254721Semaste 86254721Semaste#define CARP_IFNAME "carp" 87static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces"); 88SYSCTL_DECL(_net_inet_carp); 89 90struct carp_softc { 91 struct arpcom sc_ac; /* Interface clue */ 92 int if_flags; /* UP/DOWN */ 93 struct ifnet *sc_ifp; /* Parent */ 94 struct in_ifaddr *sc_ia; /* primary iface address */ 95 struct ip_moptions sc_imo; 96#ifdef INET6 97 struct in6_ifaddr *sc_ia6; /* primary iface address v6 */ 98 struct ip6_moptions sc_im6o; 99#endif /* INET6 */ 100 TAILQ_ENTRY(carp_softc) sc_list; 101 102 enum { INIT = 0, BACKUP, MASTER } sc_state; 103 104 int sc_flags_backup; 105 int sc_suppress; 106 107 int sc_sendad_errors; 108#define CARP_SENDAD_MAX_ERRORS 3 109 int sc_sendad_success; 110#define CARP_SENDAD_MIN_SUCCESS 3 111 112 int sc_vhid; 113 int sc_advskew; 114 int sc_naddrs; 115 int sc_naddrs6; 116 int sc_advbase; /* seconds */ 117 int sc_init_counter; 118 u_int64_t sc_counter; 119 120 /* authentication */ 121#define CARP_HMAC_PAD 64 122 unsigned char sc_key[CARP_KEY_LEN]; 123 unsigned char sc_pad[CARP_HMAC_PAD]; 124 SHA1_CTX sc_sha1; 125 126 struct callout sc_ad_tmo; /* advertisement timeout */ 127 struct callout sc_md_tmo; /* master down timeout */ 128 struct callout sc_md6_tmo; /* master down timeout */ 129 130 LIST_ENTRY(carp_softc) sc_next; /* Interface clue */ 131}; 132#define sc_if sc_ac.ac_if 133 134int carp_suppress_preempt = 0; 135int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0 }; /* XXX for now */ 136SYSCTL_INT(_net_inet_carp, CARPCTL_ALLOW, allow, CTLFLAG_RW, 137 &carp_opts[CARPCTL_ALLOW], 0, "Accept incoming CARP packets"); 138SYSCTL_INT(_net_inet_carp, CARPCTL_PREEMPT, preempt, CTLFLAG_RW, 139 &carp_opts[CARPCTL_PREEMPT], 0, "high-priority backup preemption mode"); 140SYSCTL_INT(_net_inet_carp, CARPCTL_LOG, log, CTLFLAG_RW, 141 &carp_opts[CARPCTL_LOG], 0, "log bad carp packets"); 142SYSCTL_INT(_net_inet_carp, CARPCTL_ARPBALANCE, arpbalance, CTLFLAG_RW, 143 &carp_opts[CARPCTL_ARPBALANCE], 0, "balance arp responses"); 144 145struct carpstats carpstats; 146SYSCTL_STRUCT(_net_inet_carp, CARPCTL_STATS, stats, CTLFLAG_RW, 147 &carpstats, carpstats, 148 "CARP statistics (struct carpstats, netinet/ip_carp.h)"); 149 150struct carp_if { 151 TAILQ_HEAD(, carp_softc) vhif_vrs; 152 int vhif_nvrs; 153 154 struct ifnet *vhif_ifp; 155 struct mtx vhif_mtx; 156}; 157/* lock per carp_if queue */ 158#define CARP_LOCK_INIT(cif) mtx_init(&(cif)->vhif_mtx, "carp", \ 159 NULL, MTX_DEF) 160#define CARP_LOCK_DESTROY(cif) mtx_destroy(&(cif->vhif_mtx)) 161#define CARP_LOCK_ASSERT(cif) mtx_assert(&(cif)->vhif_mtx, MA_OWNED) 162#define CARP_LOCK(cif) mtx_lock(&(cif)->vhif_mtx) 163#define CARP_UNLOCK(cif) mtx_unlock(&(cif)->vhif_mtx) 164 165#define CARP_LOG(...) \ 166 if (carp_opts[CARPCTL_LOG] > 0) \ 167 log(LOG_INFO, __VA_ARGS__); \ 168 169#define CARP_DEBUG(...) \ 170 if (carp_opts[CARPCTL_LOG] > 1) \ 171 log(LOG_DEBUG, __VA_ARGS__); \ 172 173void carp_hmac_prepare(struct carp_softc *); 174void carp_hmac_generate(struct carp_softc *, u_int32_t *, 175 unsigned char *); 176int carp_hmac_verify(struct carp_softc *, u_int32_t *, 177 unsigned char *); 178void carp_setroute(struct carp_softc *, int); 179void carp_input_c(struct mbuf *, struct carp_header *, sa_family_t); 180int carp_clone_create(struct if_clone *, int); 181void carp_clone_destroy(struct ifnet *); 182void carpdetach(struct carp_softc *); 183int carp_prepare_ad(struct mbuf *, struct carp_softc *, 184 struct carp_header *); 185void carp_send_ad_all(void); 186void carp_send_ad(void *); 187void carp_send_arp(struct carp_softc *); 188void carp_master_down(void *); 189int carp_ioctl(struct ifnet *, u_long, caddr_t); 190static int carp_looutput(struct ifnet *, struct mbuf *, struct sockaddr *, 191 struct rtentry *); 192void carp_start(struct ifnet *); 193void carp_setrun(struct carp_softc *, sa_family_t); 194void carp_set_state(struct carp_softc *, int); 195int carp_addrcount(struct carp_if *, struct in_ifaddr *, int); 196enum { CARP_COUNT_MASTER, CARP_COUNT_RUNNING }; 197 198int carp_set_addr(struct carp_softc *, struct sockaddr_in *); 199int carp_del_addr(struct carp_softc *, struct sockaddr_in *); 200#ifdef INET6 201void carp_send_na(struct carp_softc *); 202int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); 203int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); 204#endif 205 206static LIST_HEAD(, carp_softc) carpif_list; 207IFC_SIMPLE_DECLARE(carp, 0); 208 209static __inline u_int16_t 210carp_cksum(struct mbuf *m, int len) 211{ 212 return (in_cksum(m, len)); 213} 214 215void 216carp_hmac_prepare(struct carp_softc *sc) 217{ 218 u_int8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; 219 u_int8_t vhid = sc->sc_vhid & 0xff; 220 struct ifaddr *ifa; 221 int i; 222#ifdef INET6 223 struct in6_addr in6; 224#endif 225 226 /* compute ipad from key */ 227 bzero(sc->sc_pad, sizeof(sc->sc_pad)); 228 bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key)); 229 for (i = 0; i < sizeof(sc->sc_pad); i++) 230 sc->sc_pad[i] ^= 0x36; 231 232 /* precompute first part of inner hash */ 233 SHA1Init(&sc->sc_sha1); 234 SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad)); 235 SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version)); 236 SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type)); 237 SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid)); 238#ifdef INET 239 TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { 240 if (ifa->ifa_addr->sa_family == AF_INET) 241 SHA1Update(&sc->sc_sha1, 242 (void *)&ifatoia(ifa)->ia_addr.sin_addr.s_addr, 243 sizeof(struct in_addr)); 244 } 245#endif /* INET */ 246#ifdef INET6 247 TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { 248 if (ifa->ifa_addr->sa_family == AF_INET6) { 249 in6 = ifatoia6(ifa)->ia_addr.sin6_addr; 250 if (IN6_IS_ADDR_LINKLOCAL(&in6)) 251 in6.s6_addr16[1] = 0; 252 SHA1Update(&sc->sc_sha1, (void *)&in6, sizeof(in6)); 253 } 254 } 255#endif /* INET6 */ 256 257 /* convert ipad to opad */ 258 for (i = 0; i < sizeof(sc->sc_pad); i++) 259 sc->sc_pad[i] ^= 0x36 ^ 0x5c; 260} 261 262void 263carp_hmac_generate(struct carp_softc *sc, u_int32_t counter[2], 264 unsigned char md[20]) 265{ 266 SHA1_CTX sha1ctx; 267 268 /* fetch first half of inner hash */ 269 bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)); 270 271 SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter)); 272 SHA1Final(md, &sha1ctx); 273 274 /* outer hash */ 275 SHA1Init(&sha1ctx); 276 SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad)); 277 SHA1Update(&sha1ctx, md, 20); 278 SHA1Final(md, &sha1ctx); 279} 280 281int 282carp_hmac_verify(struct carp_softc *sc, u_int32_t counter[2], 283 unsigned char md[20]) 284{ 285 unsigned char md2[20]; 286 287 carp_hmac_generate(sc, counter, md2); 288 289 return (bcmp(md, md2, sizeof(md2))); 290} 291 292void 293carp_setroute(struct carp_softc *sc, int cmd) 294{ 295 struct ifaddr *ifa; 296 int s; 297 298 s = splnet(); 299 TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { 300 if (ifa->ifa_addr->sa_family == AF_INET && sc->sc_ifp != NULL) { 301 int count = carp_addrcount( 302 (struct carp_if *)sc->sc_ifp->if_carp, 303 ifatoia(ifa), CARP_COUNT_MASTER); 304 305 if ((cmd == RTM_ADD && count == 1) || 306 (cmd == RTM_DELETE && count == 0)) 307 rtinit(ifa, cmd, RTF_UP | RTF_HOST); 308 } 309#ifdef INET6 310 if (ifa->ifa_addr->sa_family == AF_INET6) { 311 if (cmd == RTM_ADD) 312 in6_ifaddloop(ifa); 313 else 314 in6_ifremloop(ifa); 315 } 316#endif /* INET6 */ 317 } 318 splx(s); 319} 320 321int 322carp_clone_create(struct if_clone *ifc, int unit) 323{ 324 325 struct carp_softc *sc; 326 struct ifnet *ifp; 327 328 MALLOC(sc, struct carp_softc *, sizeof(*sc), M_CARP, M_WAITOK|M_ZERO); 329 330 sc->sc_flags_backup = 0; 331 sc->sc_suppress = 0; 332 sc->sc_advbase = CARP_DFLTINTV; 333 sc->sc_vhid = -1; /* required setting */ 334 sc->sc_advskew = 0; 335 sc->sc_init_counter = 1; 336 sc->sc_naddrs = sc->sc_naddrs6 = 0; /* M_ZERO? */ 337#ifdef INET6 338 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; 339#endif 340 341 callout_init(&sc->sc_ad_tmo, 0); 342 callout_init(&sc->sc_md_tmo, 0); 343 callout_init(&sc->sc_md6_tmo, 0); 344 345 ifp = &sc->sc_if; 346 ifp->if_softc = sc; 347 if_initname(ifp, CARP_IFNAME, unit); 348 ifp->if_mtu = ETHERMTU; 349 ifp->if_flags = 0; 350 ifp->if_ioctl = carp_ioctl; 351 ifp->if_output = carp_looutput; 352 ifp->if_start = carp_start; 353 ifp->if_type = IFT_CARP; 354 ifp->if_snd.ifq_maxlen = ifqmaxlen; 355 ifp->if_hdrlen = 0; 356 if_attach(ifp); 357 LIST_INSERT_HEAD(&carpif_list, sc, sc_next); 358 bpfattach(&sc->sc_if, DLT_LOOP, sizeof(u_int32_t)); 359 return (0); 360} 361 362void 363carp_clone_destroy(struct ifnet *ifp) 364{ 365 struct carp_softc *sc = ifp->if_softc; 366 struct carp_if *cif; 367 struct ip_moptions *imo = &sc->sc_imo; 368#ifdef INET6 369 struct ip6_moptions *im6o = &sc->sc_im6o; 370#endif 371 372/* carpdetach(sc); */ 373 374 callout_stop(&sc->sc_ad_tmo); 375 callout_stop(&sc->sc_md_tmo); 376 callout_stop(&sc->sc_md6_tmo); 377 378 if (imo->imo_num_memberships) { 379 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 380 imo->imo_multicast_ifp = NULL; 381 } 382#ifdef INET6 383 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 384 struct in6_multi_mship *imm = 385 LIST_FIRST(&im6o->im6o_memberships); 386 LIST_REMOVE(imm, i6mm_chain); 387 in6_leavegroup(imm); 388 } 389 im6o->im6o_multicast_ifp = NULL; 390#endif 391 392 /* Remove ourself from parents if_carp queue */ 393 if (sc->sc_ifp && (cif = sc->sc_ifp->if_carp)) { 394 CARP_LOCK(cif); 395 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); 396 if (!--cif->vhif_nvrs) { 397 sc->sc_ifp->if_carp = NULL; 398 CARP_LOCK_DESTROY(cif); 399 FREE(cif, M_CARP); 400 ifpromisc(sc->sc_ifp, 0); 401 } else { 402 CARP_UNLOCK(cif); 403 } 404 } 405 406 bpfdetach(ifp); 407 if_detach(ifp); 408 LIST_REMOVE(sc, sc_next); 409 free(sc, M_CARP); 410} 411 412/* 413 * process input packet. 414 * we have rearranged checks order compared to the rfc, 415 * but it seems more efficient this way or not possible otherwise. 416 */ 417void 418carp_input(struct mbuf *m, int hlen) 419{ 420 struct ip *ip = mtod(m, struct ip *); 421 struct carp_header *ch; 422 int iplen, len; 423 424 carpstats.carps_ipackets++; 425 426 if (!carp_opts[CARPCTL_ALLOW]) { 427 m_freem(m); 428 return; 429 } 430 431 /* check if received on a valid carp interface */ 432 if (m->m_pkthdr.rcvif->if_carp == NULL) { 433 carpstats.carps_badif++; 434 CARP_LOG("carp_input: packet received on non-carp interface: %s", 435 m->m_pkthdr.rcvif->if_xname); 436 m_freem(m); 437 return; 438 } 439 440 /* verify that the IP TTL is 255. */ 441 if (ip->ip_ttl != CARP_DFLTTL) { 442 carpstats.carps_badttl++; 443 CARP_LOG("carp_input: received ttl %d != 255i on %s", 444 ip->ip_ttl, 445 m->m_pkthdr.rcvif->if_xname); 446 m_freem(m); 447 return; 448 } 449 450 iplen = ip->ip_hl << 2; 451 452 if (m->m_pkthdr.len < iplen + sizeof(*ch)) { 453 carpstats.carps_badlen++; 454 CARP_LOG("carp_input: received len %zd < " 455 "sizeof(struct carp_header)", 456 m->m_len - sizeof(struct ip)); 457 m_freem(m); 458 return; 459 } 460 461 if (iplen + sizeof(*ch) < m->m_len) { 462 if ((m = m_pullup(m, iplen + sizeof(*ch))) == NULL) { 463 carpstats.carps_hdrops++; 464 CARP_LOG("carp_input: pullup failed"); 465 return; 466 } 467 ip = mtod(m, struct ip *); 468 } 469 ch = (struct carp_header *)((char *)ip + iplen); 470 471 /* 472 * verify that the received packet length is 473 * equal to the CARP header 474 */ 475 len = iplen + sizeof(*ch); 476 if (len > m->m_pkthdr.len) { 477 carpstats.carps_badlen++; 478 CARP_LOG("carp_input: packet too short %d on %s", 479 m->m_pkthdr.len, 480 m->m_pkthdr.rcvif->if_xname); 481 m_freem(m); 482 return; 483 } 484 485 if ((m = m_pullup(m, len)) == NULL) { 486 carpstats.carps_hdrops++; 487 return; 488 } 489 ip = mtod(m, struct ip *); 490 ch = (struct carp_header *)((char *)ip + iplen); 491 492 /* verify the CARP checksum */ 493 m->m_data += iplen; 494 if (carp_cksum(m, len - iplen)) { 495 carpstats.carps_badsum++; 496 CARP_LOG("carp_input: checksum failed on %s", 497 m->m_pkthdr.rcvif->if_xname); 498 m_freem(m); 499 return; 500 } 501 m->m_data -= iplen; 502 503 carp_input_c(m, ch, AF_INET); 504} 505 506#ifdef INET6 507int 508carp6_input(struct mbuf **mp, int *offp, int proto) 509{ 510 struct mbuf *m = *mp; 511 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 512 struct carp_header *ch; 513 u_int len; 514 515 carpstats.carps_ipackets6++; 516 517 if (!carp_opts[CARPCTL_ALLOW]) { 518 m_freem(m); 519 return (IPPROTO_DONE); 520 } 521 522 /* check if received on a valid carp interface */ 523 if (m->m_pkthdr.rcvif->if_carp == NULL) { 524 carpstats.carps_badif++; 525 CARP_LOG("carp6_input: packet received on non-carp " 526 "interface: %s", 527 m->m_pkthdr.rcvif->if_xname); 528 m_freem(m); 529 return (IPPROTO_DONE); 530 } 531 532 /* verify that the IP TTL is 255 */ 533 if (ip6->ip6_hlim != CARP_DFLTTL) { 534 carpstats.carps_badttl++; 535 CARP_LOG("carp6_input: received ttl %d != 255 on %s", 536 ip6->ip6_hlim, 537 m->m_pkthdr.rcvif->if_xname); 538 m_freem(m); 539 return (IPPROTO_DONE); 540 } 541 542 /* verify that we have a complete carp packet */ 543 len = m->m_len; 544 IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); 545 if (ch == NULL) { 546 carpstats.carps_badlen++; 547 CARP_LOG("carp6_input: packet size %u too small on %s", len, 548 m->m_pkthdr.rcvif->if_xname); 549 return (IPPROTO_DONE); 550 } 551 552 553 /* verify the CARP checksum */ 554 m->m_data += *offp; 555 if (carp_cksum(m, sizeof(*ch))) { 556 carpstats.carps_badsum++; 557 CARP_LOG("carp6_input: checksum failed, on %s", 558 m->m_pkthdr.rcvif->if_xname); 559 m_freem(m); 560 return (IPPROTO_DONE); 561 } 562 m->m_data -= *offp; 563 564 carp_input_c(m, ch, AF_INET6); 565 return (IPPROTO_DONE); 566} 567#endif /* INET6 */ 568 569void 570carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) 571{ 572 struct ifnet *ifp = m->m_pkthdr.rcvif; 573 struct carp_softc *sc; 574 u_int64_t tmp_counter; 575 struct timeval sc_tv, ch_tv; 576 577 /* verify that the VHID is valid on the receiving interface */ 578 CARP_LOCK(ifp->if_carp); 579 TAILQ_FOREACH(sc, &((struct carp_if *)ifp->if_carp)->vhif_vrs, sc_list) 580 if (sc->sc_vhid == ch->carp_vhid) 581 break; 582 CARP_UNLOCK(ifp->if_carp); 583 if (!sc || (sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != 584 (IFF_UP|IFF_RUNNING)) { 585 carpstats.carps_badvhid++; 586 m_freem(m); 587 return; 588 } 589 590 getmicrotime(&sc->sc_if.if_lastchange); 591 sc->sc_if.if_ipackets++; 592 sc->sc_if.if_ibytes += m->m_pkthdr.len; 593 594 if (sc->sc_if.if_bpf) { 595 /* 596 * We need to prepend the address family as 597 * a four byte field. Cons up a dummy header 598 * to pacify bpf. This is safe because bpf 599 * will only read from the mbuf (i.e., it won't 600 * try to free it or keep a pointer to it). 601 */ 602 struct mbuf m0; 603 struct ip *ip = mtod(m, struct ip *); 604 u_int32_t maf = htonl(af); 605 606 m0.m_next = m; 607 m0.m_len = sizeof(maf); 608 m0.m_data = (char *)&maf; 609 /* BPF wants net byte order */ 610 ip->ip_len = htonl(ip->ip_len); 611 ip->ip_off = htonl(ip->ip_off); 612 BPF_MTAP(&sc->sc_if, &m0); 613 } 614 615 /* verify the CARP version. */ 616 if (ch->carp_version != CARP_VERSION) { 617 carpstats.carps_badver++; 618 sc->sc_if.if_ierrors++; 619 CARP_LOG("%s; invalid version %d", 620 sc->sc_if.if_xname, 621 ch->carp_version); 622 m_freem(m); 623 return; 624 } 625 626 /* verify the hash */ 627 if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) { 628 carpstats.carps_badauth++; 629 sc->sc_if.if_ierrors++; 630 CARP_LOG("%s: incorrect hash", sc->sc_if.if_xname); 631 m_freem(m); 632 return; 633 } 634 635 tmp_counter = ntohl(ch->carp_counter[0]); 636 tmp_counter = tmp_counter<<32; 637 tmp_counter += ntohl(ch->carp_counter[1]); 638 639 /* XXX Replay protection goes here */ 640 641 sc->sc_init_counter = 0; 642 sc->sc_counter = tmp_counter; 643 644 sc_tv.tv_sec = sc->sc_advbase; 645 if (carp_suppress_preempt && sc->sc_advskew < 240) 646 sc_tv.tv_usec = 240 * 1000000 / 256; 647 else 648 sc_tv.tv_usec = sc->sc_advskew * 1000000 / 256; 649 ch_tv.tv_sec = ch->carp_advbase; 650 ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; 651 652 switch (sc->sc_state) { 653 case INIT: 654 break; 655 case MASTER: 656 /* 657 * If we receive an advertisement from a master who's going to 658 * be more frequent than us, go into BACKUP state. 659 */ 660 if (timevalcmp(&sc_tv, &ch_tv, >) || 661 timevalcmp(&sc_tv, &ch_tv, ==)) { 662 callout_stop(&sc->sc_ad_tmo); 663 CARP_DEBUG("%s: MASTER -> BACKUP " 664 "(more frequent advertisement received)", 665 sc->sc_if.if_xname); 666 carp_set_state(sc, BACKUP); 667 carp_setrun(sc, 0); 668 carp_setroute(sc, RTM_DELETE); 669 } 670 break; 671 case BACKUP: 672 /* 673 * If we're pre-empting masters who advertise slower than us, 674 * and this one claims to be slower, treat him as down. 675 */ 676 if (carp_opts[CARPCTL_PREEMPT] && 677 timevalcmp(&sc_tv, &ch_tv, <)) { 678 CARP_DEBUG("%s: BACKUP -> MASTER " 679 "(preempting a slower master)", 680 sc->sc_if.if_xname); 681 carp_master_down(sc); 682 break; 683 } 684 685 /* 686 * If the master is going to advertise at such a low frequency 687 * that he's guaranteed to time out, we'd might as well just 688 * treat him as timed out now. 689 */ 690 sc_tv.tv_sec = sc->sc_advbase * 3; 691 if (timevalcmp(&sc_tv, &ch_tv, <)) { 692 CARP_DEBUG("%s: BACKUP -> MASTER " 693 "(master timed out)", 694 sc->sc_if.if_xname); 695 carp_master_down(sc); 696 break; 697 } 698 699 /* 700 * Otherwise, we reset the counter and wait for the next 701 * advertisement. 702 */ 703 carp_setrun(sc, af); 704 break; 705 } 706 707 m_freem(m); 708 return; 709} 710 711void 712carpdetach(struct carp_softc *sc) 713{ 714 struct ifaddr *ifa; 715 716 callout_stop(&sc->sc_ad_tmo); 717 callout_stop(&sc->sc_md_tmo); 718 callout_stop(&sc->sc_md6_tmo); 719 720 while ((ifa = TAILQ_FIRST(&sc->sc_if.if_addrlist)) != NULL) 721 if (ifa->ifa_addr->sa_family == AF_INET) { 722 struct in_ifaddr *ia = ifatoia(ifa); 723 724 carp_del_addr(sc, &ia->ia_addr); 725 726 /* ripped screaming from in_control(SIOCDIFADDR) */ 727 in_ifscrub(&sc->sc_if, ia); 728 TAILQ_REMOVE(&sc->sc_if.if_addrlist, ifa, ifa_link); 729 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link); 730 IFAFREE((&ia->ia_ifa)); 731 } 732} 733 734/* Detach an interface from the carp. */ 735void 736carp_ifdetach(struct ifnet *ifp) 737{ 738 struct carp_softc *sc; 739 struct carp_if *cif = (struct carp_if *)ifp->if_carp; 740 741 CARP_LOCK(cif); 742 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) 743 carpdetach(sc); 744 CARP_UNLOCK(cif); 745} 746 747int 748carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch) 749{ 750 struct m_tag *mtag; 751 struct ifnet *ifp = &sc->sc_if; 752 753 if (sc->sc_init_counter) { 754 /* this could also be seconds since unix epoch */ 755 sc->sc_counter = arc4random(); 756 sc->sc_counter = sc->sc_counter << 32; 757 sc->sc_counter += arc4random(); 758 } else 759 sc->sc_counter++; 760 761 ch->carp_counter[0] = htonl((sc->sc_counter>>32)&0xffffffff); 762 ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff); 763 764 carp_hmac_generate(sc, ch->carp_counter, ch->carp_md); 765 766 /* Tag packet for carp_output */ 767 mtag = m_tag_get(PACKET_TAG_CARP, sizeof(struct ifnet *), M_NOWAIT); 768 if (mtag == NULL) { 769 m_freem(m); 770 sc->sc_if.if_oerrors++; 771 return (ENOMEM); 772 } 773 bcopy(&ifp, (caddr_t)(mtag + 1), sizeof(struct ifnet *)); 774 m_tag_prepend(m, mtag); 775 776 return (0); 777} 778 779void 780carp_send_ad_all(void) 781{ 782 struct ifnet *ifp; 783 struct carp_if *cif; 784 struct carp_softc *vh; 785 786 TAILQ_FOREACH(ifp, &ifnet, if_list) { 787 if (ifp->if_carp == NULL) 788 continue; 789 790 cif = (struct carp_if *)ifp->if_carp; 791 CARP_LOCK(cif); 792 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 793 if ((vh->sc_ac.ac_if.if_flags & (IFF_UP|IFF_RUNNING)) && 794 vh->sc_state == MASTER) 795 carp_send_ad(vh); 796 } 797 CARP_UNLOCK(cif); 798 } 799} 800 801void 802carp_send_ad(void *v) 803{ 804 struct carp_header ch; 805 struct timeval tv; 806 struct carp_softc *sc = v; 807 struct carp_header *ch_ptr; 808 struct mbuf *m; 809 int len, advbase, advskew; 810 811 /* bow out if we've lost our UPness or RUNNINGuiness */ 812 if ((sc->sc_if.if_flags & 813 (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 814 advbase = 255; 815 advskew = 255; 816 } else { 817 advbase = sc->sc_advbase; 818 if (!carp_suppress_preempt || sc->sc_advskew > 240) 819 advskew = sc->sc_advskew; 820 else 821 advskew = 240; 822 tv.tv_sec = advbase; 823 tv.tv_usec = advskew * 1000000 / 256; 824 } 825 826 ch.carp_version = CARP_VERSION; 827 ch.carp_type = CARP_ADVERTISEMENT; 828 ch.carp_vhid = sc->sc_vhid; 829 ch.carp_advbase = advbase; 830 ch.carp_advskew = advskew; 831 ch.carp_authlen = 7; /* XXX DEFINE */ 832 ch.carp_pad1 = 0; /* must be zero */ 833 ch.carp_cksum = 0; 834 835#ifdef INET 836 if (sc->sc_ia) { 837 struct ip *ip; 838 839 MGETHDR(m, M_DONTWAIT, MT_HEADER); 840 if (m == NULL) { 841 sc->sc_ac.ac_if.if_oerrors++; 842 carpstats.carps_onomem++; 843 /* XXX maybe less ? */ 844 if (advbase != 255 || advskew != 255) 845 callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), 846 carp_send_ad, sc); 847 return; 848 } 849 len = sizeof(*ip) + sizeof(ch); 850 m->m_pkthdr.len = len; 851 m->m_pkthdr.rcvif = NULL; 852 m->m_len = len; 853 MH_ALIGN(m, m->m_len); 854 m->m_flags |= M_MCAST; 855 ip = mtod(m, struct ip *); 856 ip->ip_v = IPVERSION; 857 ip->ip_hl = sizeof(*ip) >> 2; 858 ip->ip_tos = IPTOS_LOWDELAY; 859 ip->ip_len = len; 860 ip->ip_id = ip_newid(); 861 ip->ip_off = IP_DF; 862 ip->ip_ttl = CARP_DFLTTL; 863 ip->ip_p = IPPROTO_CARP; 864 ip->ip_sum = 0; 865 ip->ip_src.s_addr = sc->sc_ia->ia_addr.sin_addr.s_addr; 866 ip->ip_dst.s_addr = htonl(INADDR_CARP_GROUP); 867 868 ch_ptr = (struct carp_header *)(&ip[1]); 869 bcopy(&ch, ch_ptr, sizeof(ch)); 870 if (carp_prepare_ad(m, sc, ch_ptr)) 871 return; 872 873 m->m_data += sizeof(*ip); 874 ch_ptr->carp_cksum = carp_cksum(m, len - sizeof(*ip)); 875 m->m_data -= sizeof(*ip); 876 877 getmicrotime(&sc->sc_if.if_lastchange); 878 sc->sc_ac.ac_if.if_opackets++; 879 sc->sc_ac.ac_if.if_obytes += len; 880 carpstats.carps_opackets++; 881 882 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) { 883 sc->sc_if.if_oerrors++; 884 if (sc->sc_sendad_errors < INT_MAX) 885 sc->sc_sendad_errors++; 886 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { 887 carp_suppress_preempt++; 888 if (carp_suppress_preempt == 1) 889 carp_send_ad_all(); 890 } 891 sc->sc_sendad_success = 0; 892 } else { 893 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) { 894 if (++sc->sc_sendad_success >= 895 CARP_SENDAD_MIN_SUCCESS) { 896 carp_suppress_preempt--; 897 sc->sc_sendad_errors = 0; 898 } 899 } else 900 sc->sc_sendad_errors = 0; 901 } 902 } 903#endif /* INET */ 904#ifdef INET6 905 if (sc->sc_ia6) { 906 struct ip6_hdr *ip6; 907 908 MGETHDR(m, M_DONTWAIT, MT_HEADER); 909 if (m == NULL) { 910 sc->sc_ac.ac_if.if_oerrors++; 911 carpstats.carps_onomem++; 912 /* XXX maybe less ? */ 913 if (advbase != 255 || advskew != 255) 914 callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), 915 carp_send_ad, sc); 916 return; 917 } 918 len = sizeof(*ip6) + sizeof(ch); 919 m->m_pkthdr.len = len; 920 m->m_pkthdr.rcvif = NULL; 921 m->m_len = len; 922 MH_ALIGN(m, m->m_len); 923 m->m_flags |= M_MCAST; 924 ip6 = mtod(m, struct ip6_hdr *); 925 bzero(ip6, sizeof(*ip6)); 926 ip6->ip6_vfc |= IPV6_VERSION; 927 ip6->ip6_hlim = CARP_DFLTTL; 928 ip6->ip6_nxt = IPPROTO_CARP; 929 bcopy(&sc->sc_ia6->ia_addr.sin6_addr, &ip6->ip6_src, 930 sizeof(struct in6_addr)); 931 /* set the multicast destination */ 932 933 ip6->ip6_dst.s6_addr8[0] = 0xff; 934 ip6->ip6_dst.s6_addr8[1] = 0x02; 935 ip6->ip6_dst.s6_addr8[15] = 0x12; 936 937 ch_ptr = (struct carp_header *)(&ip6[1]); 938 bcopy(&ch, ch_ptr, sizeof(ch)); 939 if (carp_prepare_ad(m, sc, ch_ptr)) 940 return; 941 942 m->m_data += sizeof(*ip6); 943 ch_ptr->carp_cksum = carp_cksum(m, len - sizeof(*ip6)); 944 m->m_data -= sizeof(*ip6); 945 946 getmicrotime(&sc->sc_if.if_lastchange); 947 sc->sc_if.if_opackets++; 948 sc->sc_if.if_obytes += len; 949 carpstats.carps_opackets6++; 950 951 if (ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL, NULL)) { 952 sc->sc_if.if_oerrors++; 953 if (sc->sc_sendad_errors < INT_MAX) 954 sc->sc_sendad_errors++; 955 if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { 956 carp_suppress_preempt++; 957 if (carp_suppress_preempt == 1) 958 carp_send_ad_all(); 959 } 960 sc->sc_sendad_success = 0; 961 } else { 962 if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) { 963 if (++sc->sc_sendad_success >= 964 CARP_SENDAD_MIN_SUCCESS) { 965 carp_suppress_preempt--; 966 sc->sc_sendad_errors = 0; 967 } 968 } else 969 sc->sc_sendad_errors = 0; 970 } 971 } 972#endif /* INET6 */ 973 974 if (advbase != 255 || advskew != 255) 975 callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), 976 carp_send_ad, sc); 977 978} 979 980/* 981 * Broadcast a gratuitous ARP request containing 982 * the virtual router MAC address for each IP address 983 * associated with the virtual router. 984 */ 985void 986carp_send_arp(struct carp_softc *sc) 987{ 988 struct ifaddr *ifa; 989 990 TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { 991 992 if (ifa->ifa_addr->sa_family != AF_INET) 993 continue; 994 995/* arprequest(sc->sc_ifp, &in, &in, sc->sc_ac.ac_enaddr); */ 996 arp_ifinit2(sc->sc_ifp, ifa, sc->sc_ac.ac_enaddr); 997 998 DELAY(1000); /* XXX */ 999 } 1000} 1001 1002#ifdef INET6 1003void 1004carp_send_na(struct carp_softc *sc) 1005{ 1006 struct ifaddr *ifa; 1007 struct in6_addr *in6; 1008 static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; 1009 1010 TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { 1011 1012 if (ifa->ifa_addr->sa_family != AF_INET6) 1013 continue; 1014 1015 in6 = &ifatoia6(ifa)->ia_addr.sin6_addr; 1016 nd6_na_output(sc->sc_ifp, &mcast, in6, 1017 ND_NA_FLAG_OVERRIDE, 1, NULL); 1018 DELAY(1000); /* XXX */ 1019 } 1020} 1021#endif /* INET6 */ 1022 1023int 1024carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type) 1025{ 1026 struct carp_softc *vh; 1027 struct ifaddr *ifa; 1028 int count = 0; 1029 1030 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1031 if ((type == CARP_COUNT_RUNNING && 1032 (vh->sc_ac.ac_if.if_flags & (IFF_UP|IFF_RUNNING)) == 1033 (IFF_UP|IFF_RUNNING)) || 1034 (type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) { 1035 TAILQ_FOREACH(ifa, &vh->sc_ac.ac_if.if_addrlist, 1036 ifa_list) { 1037 if (ifa->ifa_addr->sa_family == AF_INET && 1038 ia->ia_addr.sin_addr.s_addr == 1039 ifatoia(ifa)->ia_addr.sin_addr.s_addr) 1040 count++; 1041 } 1042 } 1043 } 1044 return (count); 1045} 1046 1047int 1048carp_iamatch(void *v, struct in_ifaddr *ia, 1049 struct in_addr *isaddr, u_int8_t **enaddr) 1050{ 1051 struct carp_if *cif = v; 1052 struct carp_softc *vh; 1053 int index, count = 0; 1054 struct ifaddr *ifa; 1055 1056 CARP_LOCK(cif); 1057 1058 if (carp_opts[CARPCTL_ARPBALANCE]) { 1059 /* 1060 * XXX proof of concept implementation. 1061 * We use the source ip to decide which virtual host should 1062 * handle the request. If we're master of that virtual host, 1063 * then we respond, otherwise, just drop the arp packet on 1064 * the floor. 1065 */ 1066 count = carp_addrcount(cif, ia, CARP_COUNT_RUNNING); 1067 if (count == 0) { 1068 /* should never reach this */ 1069 CARP_UNLOCK(cif); 1070 return (0); 1071 } 1072 1073 /* this should be a hash, like pf_hash() */ 1074 index = isaddr->s_addr % count; 1075 count = 0; 1076 1077 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1078 if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == 1079 (IFF_UP|IFF_RUNNING)) { 1080 TAILQ_FOREACH(ifa, &vh->sc_if.if_addrlist, 1081 ifa_list) { 1082 if (ifa->ifa_addr->sa_family == 1083 AF_INET && 1084 ia->ia_addr.sin_addr.s_addr == 1085 ifatoia(ifa)->ia_addr.sin_addr.s_addr) { 1086 if (count == index) { 1087 if (vh->sc_state == 1088 MASTER) { 1089 *enaddr = vh->sc_ac.ac_enaddr; 1090 CARP_UNLOCK(cif); 1091 return (1); 1092 } else { 1093 CARP_UNLOCK(cif); 1094 return (0); 1095 } 1096 } 1097 count++; 1098 } 1099 } 1100 } 1101 } 1102 } else { 1103 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1104 if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == 1105 (IFF_UP|IFF_RUNNING) && ia->ia_ifp == 1106 &vh->sc_if) { 1107 *enaddr = vh->sc_ac.ac_enaddr; 1108 CARP_UNLOCK(cif); 1109 return (1); 1110 } 1111 } 1112 } 1113 CARP_UNLOCK(cif); 1114 return (0); 1115} 1116 1117#ifdef INET6 1118struct ifaddr * 1119carp_iamatch6(void *v, struct in6_addr *taddr) 1120{ 1121 struct carp_if *cif = v; 1122 struct carp_softc *vh; 1123 struct ifaddr *ifa; 1124 1125 CARP_LOCK(cif); 1126 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { 1127 TAILQ_FOREACH(ifa, &vh->sc_if.if_addrlist, ifa_list) { 1128 if (IN6_ARE_ADDR_EQUAL(taddr, 1129 &ifatoia6(ifa)->ia_addr.sin6_addr) && 1130 ((vh->sc_if.if_flags & 1131 (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))) { 1132 CARP_UNLOCK(cif); 1133 return (ifa); 1134 } 1135 } 1136 } 1137 CARP_UNLOCK(cif); 1138 1139 return (NULL); 1140} 1141 1142void * 1143carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) 1144{ 1145 struct m_tag *mtag; 1146 struct carp_if *cif = v; 1147 struct carp_softc *sc; 1148 struct ifaddr *ifa; 1149 1150 CARP_LOCK(cif); 1151 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { 1152 TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { 1153 if (IN6_ARE_ADDR_EQUAL(taddr, 1154 &ifatoia6(ifa)->ia_addr.sin6_addr) && 1155 ((sc->sc_if.if_flags & 1156 (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))) { 1157 struct ifnet *ifp = &sc->sc_if; 1158 mtag = m_tag_get(PACKET_TAG_CARP, 1159 sizeof(struct ifnet *), M_NOWAIT); 1160 if (mtag == NULL) { 1161 /* better a bit than nothing */ 1162 CARP_UNLOCK(cif); 1163 return (sc->sc_ac.ac_enaddr); 1164 } 1165 bcopy(&ifp, (caddr_t)(mtag + 1), 1166 sizeof(struct ifnet *)); 1167 m_tag_prepend(m, mtag); 1168 1169 CARP_UNLOCK(cif); 1170 return (sc->sc_ac.ac_enaddr); 1171 } 1172 } 1173 } 1174 CARP_UNLOCK(cif); 1175 1176 return (NULL); 1177} 1178#endif 1179 1180struct ifnet * 1181carp_forus(void *v, void *dhost) 1182{ 1183 struct carp_if *cif = v; 1184 struct carp_softc *vh; 1185 u_int8_t *ena = dhost; 1186 1187 if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1) 1188 return (NULL); 1189 1190 CARP_LOCK(cif); 1191 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) 1192 if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == 1193 (IFF_UP|IFF_RUNNING) && vh->sc_state == MASTER && 1194 !bcmp(dhost, vh->sc_ac.ac_enaddr, ETHER_ADDR_LEN)) { 1195 CARP_UNLOCK(cif); 1196 return (&vh->sc_if); 1197 } 1198 1199 CARP_UNLOCK(cif); 1200 return (NULL); 1201} 1202 1203void 1204carp_master_down(void *v) 1205{ 1206 struct carp_softc *sc = v; 1207 1208 switch (sc->sc_state) { 1209 case INIT: 1210 printf("%s: master_down event in INIT state\n", 1211 sc->sc_if.if_xname); 1212 break; 1213 case MASTER: 1214 break; 1215 case BACKUP: 1216 carp_set_state(sc, MASTER); 1217 carp_send_ad(sc); 1218 carp_send_arp(sc); 1219#ifdef INET6 1220 carp_send_na(sc); 1221#endif /* INET6 */ 1222 carp_setrun(sc, 0); 1223 carp_setroute(sc, RTM_ADD); 1224 break; 1225 } 1226} 1227 1228/* 1229 * When in backup state, af indicates whether to reset the master down timer 1230 * for v4 or v6. If it's set to zero, reset the ones which are already pending. 1231 */ 1232void 1233carp_setrun(struct carp_softc *sc, sa_family_t af) 1234{ 1235 struct timeval tv; 1236 1237 if (sc->sc_if.if_flags & IFF_UP && 1238 sc->sc_vhid > 0 && (sc->sc_naddrs || sc->sc_naddrs6)) 1239 sc->sc_if.if_flags |= IFF_RUNNING; 1240 else { 1241 sc->sc_if.if_flags &= ~IFF_RUNNING; 1242 carp_setroute(sc, RTM_DELETE); 1243 return; 1244 } 1245 1246 switch (sc->sc_state) { 1247 case INIT: 1248 if (carp_opts[CARPCTL_PREEMPT] && !carp_suppress_preempt) { 1249 carp_send_ad(sc); 1250 carp_send_arp(sc); 1251#ifdef INET6 1252 carp_send_na(sc); 1253#endif /* INET6 */ 1254 CARP_DEBUG("%s: INIT -> MASTER (preempting)", 1255 sc->sc_if.if_xname); 1256 carp_set_state(sc, MASTER); 1257 carp_setroute(sc, RTM_ADD); 1258 } else { 1259 CARP_DEBUG("%s: INIT -> BACKUP", sc->sc_if.if_xname); 1260 carp_set_state(sc, BACKUP); 1261 carp_setroute(sc, RTM_DELETE); 1262 carp_setrun(sc, 0); 1263 } 1264 break; 1265 case BACKUP: 1266 callout_stop(&sc->sc_ad_tmo); 1267 tv.tv_sec = 3 * sc->sc_advbase; 1268 tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1269 switch (af) { 1270#ifdef INET 1271 case AF_INET: 1272 callout_reset(&sc->sc_md_tmo, tvtohz(&tv), 1273 carp_master_down, sc); 1274 break; 1275#endif /* INET */ 1276#ifdef INET6 1277 case AF_INET6: 1278 callout_reset(&sc->sc_md6_tmo, tvtohz(&tv), 1279 carp_master_down, sc); 1280 break; 1281#endif /* INET6 */ 1282 default: 1283 if (sc->sc_naddrs) 1284 callout_reset(&sc->sc_md_tmo, tvtohz(&tv), 1285 carp_master_down, sc); 1286 if (sc->sc_naddrs6) 1287 callout_reset(&sc->sc_md6_tmo, tvtohz(&tv), 1288 carp_master_down, sc); 1289 break; 1290 } 1291 break; 1292 case MASTER: 1293 tv.tv_sec = sc->sc_advbase; 1294 tv.tv_usec = sc->sc_advskew * 1000000 / 256; 1295 callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), 1296 carp_send_ad, sc); 1297 break; 1298 } 1299} 1300 1301int 1302carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) 1303{ 1304 struct ifnet *ifp; 1305 struct carp_if *cif; 1306 struct in_ifaddr *ia, *ia_if; 1307 struct ip_moptions *imo = &sc->sc_imo; 1308 struct in_addr addr; 1309 u_long iaddr = htonl(sin->sin_addr.s_addr); 1310 int own, error; 1311 1312 if (sin->sin_addr.s_addr == 0) { 1313 if (!(sc->sc_if.if_flags & IFF_UP)) 1314 carp_set_state(sc, INIT); 1315 if (sc->sc_naddrs) 1316 sc->sc_if.if_flags |= IFF_UP; 1317 carp_setrun(sc, 0); 1318 return (0); 1319 } 1320 1321 /* we have to do it by hands to check we won't match on us */ 1322 ia_if = NULL; own = 0; 1323 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { 1324 /* and, yeah, we need a multicast-capable iface too */ 1325 if (ia->ia_ifp != &sc->sc_if && 1326 (ia->ia_ifp->if_flags & IFF_MULTICAST) && 1327 (iaddr & ia->ia_subnetmask) == ia->ia_subnet) { 1328 if (!ia_if) 1329 ia_if = ia; 1330 if (sin->sin_addr.s_addr == 1331 ia->ia_addr.sin_addr.s_addr) 1332 own++; 1333 } 1334 } 1335 1336 if (!ia_if) 1337 return (EADDRNOTAVAIL); 1338 1339 ia = ia_if; 1340 ifp = ia->ia_ifp; 1341 1342 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 || 1343 (imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp)) 1344 return (EADDRNOTAVAIL); 1345 1346 if (imo->imo_num_memberships == 0) { 1347 addr.s_addr = htonl(INADDR_CARP_GROUP); 1348 if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) == NULL) 1349 return (ENOBUFS); 1350 imo->imo_num_memberships++; 1351 imo->imo_multicast_ifp = ifp; 1352 imo->imo_multicast_ttl = CARP_DFLTTL; 1353 imo->imo_multicast_loop = 0; 1354 } 1355 1356 if (!ifp->if_carp) { 1357 1358 MALLOC(cif, struct carp_if *, sizeof(*cif), M_CARP, 1359 M_WAITOK|M_ZERO); 1360 if (!cif) { 1361 error = ENOBUFS; 1362 goto cleanup; 1363 } 1364 if ((error = ifpromisc(ifp, 1))) { 1365 FREE(cif, M_CARP); 1366 goto cleanup; 1367 } 1368 1369 CARP_LOCK_INIT(cif); 1370 CARP_LOCK(cif); 1371 cif->vhif_ifp = ifp; 1372 TAILQ_INIT(&cif->vhif_vrs); 1373 ifp->if_carp = cif; 1374 1375 } else { 1376 struct carp_softc *vr; 1377 1378 cif = (struct carp_if *)ifp->if_carp; 1379 CARP_LOCK(cif); 1380 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) 1381 if (vr != sc && vr->sc_vhid == sc->sc_vhid) { 1382 CARP_UNLOCK(cif); 1383 error = EINVAL; 1384 goto cleanup; 1385 } 1386 } 1387 sc->sc_ia = ia; 1388 sc->sc_ifp = ifp; 1389 1390 { /* XXX prevent endless loop if already in queue */ 1391 struct carp_softc *vr, *after = NULL; 1392 int myself = 0; 1393 cif = (struct carp_if *)ifp->if_carp; 1394 1395 /* XXX: cif should not change, right? So we still hold the lock */ 1396 CARP_LOCK_ASSERT(cif); 1397 1398 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 1399 if (vr == sc) 1400 myself = 1; 1401 if (vr->sc_vhid < sc->sc_vhid) 1402 after = vr; 1403 } 1404 1405 if (!myself) { 1406 /* We're trying to keep things in order */ 1407 if (after == NULL) { 1408 TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); 1409 } else { 1410 TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); 1411 } 1412 cif->vhif_nvrs++; 1413 } 1414 } 1415 1416 CARP_UNLOCK(cif); 1417 1418 sc->sc_naddrs++; 1419 sc->sc_if.if_flags |= IFF_UP; 1420 if (own) 1421 sc->sc_advskew = 0; 1422 carp_carpdev_state(cif); 1423 carp_setrun(sc, 0); 1424 1425 return (0); 1426 1427cleanup: 1428 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1429 return (error); 1430} 1431 1432int 1433carp_del_addr(struct carp_softc *sc, struct sockaddr_in *sin) 1434{ 1435 int error = 0; 1436 1437 if (!--sc->sc_naddrs) { 1438 struct carp_if *cif = (struct carp_if *)sc->sc_ifp->if_carp; 1439 struct ip_moptions *imo = &sc->sc_imo; 1440 1441 callout_stop(&sc->sc_ad_tmo); 1442 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 1443 sc->sc_vhid = -1; 1444 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); 1445 imo->imo_multicast_ifp = NULL; 1446 CARP_LOCK(cif); 1447 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); 1448 if (!--cif->vhif_nvrs) { 1449 sc->sc_ifp->if_carp = NULL; 1450 CARP_LOCK_DESTROY(cif); 1451 FREE(cif, M_IFADDR); 1452 } else { 1453 CARP_UNLOCK(cif); 1454 } 1455 } 1456 1457 return (error); 1458} 1459 1460#ifdef INET6 1461int 1462carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) 1463{ 1464 struct ifnet *ifp; 1465 struct carp_if *cif; 1466 struct in6_ifaddr *ia, *ia_if; 1467 struct ip6_moptions *im6o = &sc->sc_im6o; 1468 struct in6_multi_mship *imm; 1469 struct sockaddr_in6 addr; 1470 int own, error; 1471 1472 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1473 if (!(sc->sc_if.if_flags & IFF_UP)) 1474 carp_set_state(sc, INIT); 1475 if (sc->sc_naddrs6) 1476 sc->sc_if.if_flags |= IFF_UP; 1477 carp_setrun(sc, 0); 1478 return (0); 1479 } 1480 1481 /* we have to do it by hands to check we won't match on us */ 1482 ia_if = NULL; own = 0; 1483 for (ia = in6_ifaddr; ia; ia = ia->ia_next) { 1484 int i; 1485 1486 for (i = 0; i < 4; i++) { 1487 if ((sin6->sin6_addr.s6_addr32[i] & 1488 ia->ia_prefixmask.sin6_addr.s6_addr32[i]) != 1489 (ia->ia_addr.sin6_addr.s6_addr32[i] & 1490 ia->ia_prefixmask.sin6_addr.s6_addr32[i])) 1491 break; 1492 } 1493 /* and, yeah, we need a multicast-capable iface too */ 1494 if (ia->ia_ifp != &sc->sc_ac.ac_if && 1495 (ia->ia_ifp->if_flags & IFF_MULTICAST) && 1496 (i == 4)) { 1497 if (!ia_if) 1498 ia_if = ia; 1499 if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 1500 &ia->ia_addr.sin6_addr)) 1501 own++; 1502 } 1503 } 1504 1505 if (!ia_if) 1506 return (EADDRNOTAVAIL); 1507 ia = ia_if; 1508 ifp = ia->ia_ifp; 1509 1510 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 || 1511 (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp)) 1512 return (EADDRNOTAVAIL); 1513 1514 if (!sc->sc_naddrs6) { 1515 im6o->im6o_multicast_ifp = ifp; 1516 1517 /* join CARP multicast address */ 1518 bzero(&addr, sizeof(addr)); 1519 addr.sin6_family = AF_INET6; 1520 addr.sin6_len = sizeof(addr); 1521 addr.sin6_addr.s6_addr16[0] = htons(0xff02); 1522 addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1523 addr.sin6_addr.s6_addr8[15] = 0x12; 1524 if ((imm = in6_joingroup(ifp, &addr.sin6_addr, &error)) == NULL) 1525 goto cleanup; 1526 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); 1527 1528 /* join solicited multicast address */ 1529 bzero(&addr.sin6_addr, sizeof(addr.sin6_addr)); 1530 addr.sin6_addr.s6_addr16[0] = htons(0xff02); 1531 addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1532 addr.sin6_addr.s6_addr32[1] = 0; 1533 addr.sin6_addr.s6_addr32[2] = htonl(1); 1534 addr.sin6_addr.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3]; 1535 addr.sin6_addr.s6_addr8[12] = 0xff; 1536 if ((imm = in6_joingroup(ifp, &addr.sin6_addr, &error)) == NULL) 1537 goto cleanup; 1538 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); 1539 } 1540 1541 if (!ifp->if_carp) { 1542 MALLOC(cif, struct carp_if *, sizeof(*cif), M_CARP, 1543 M_WAITOK|M_ZERO); 1544 if (!cif) { 1545 error = ENOBUFS; 1546 goto cleanup; 1547 } 1548 if ((error = ifpromisc(ifp, 1))) { 1549 FREE(cif, M_CARP); 1550 goto cleanup; 1551 } 1552 1553 CARP_LOCK_INIT(cif); 1554 CARP_LOCK(cif); 1555 cif->vhif_ifp = ifp; 1556 TAILQ_INIT(&cif->vhif_vrs); 1557 ifp->if_carp = cif; 1558 1559 } else { 1560 struct carp_softc *vr; 1561 1562 cif = (struct carp_if *)ifp->if_carp; 1563 CARP_LOCK(cif); 1564 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) 1565 if (vr != sc && vr->sc_vhid == sc->sc_vhid) { 1566 CARP_UNLOCK(cif); 1567 error = EINVAL; 1568 goto cleanup; 1569 } 1570 } 1571 sc->sc_ia6 = ia; 1572 sc->sc_ifp = ifp; 1573 1574 { /* XXX prevent endless loop if already in queue */ 1575 struct carp_softc *vr, *after = NULL; 1576 int myself = 0; 1577 cif = (struct carp_if *)ifp->if_carp; 1578 CARP_LOCK_ASSERT(cif); 1579 1580 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { 1581 if (vr == sc) 1582 myself = 1; 1583 if (vr->sc_vhid < sc->sc_vhid) 1584 after = vr; 1585 } 1586 1587 if (!myself) { 1588 /* We're trying to keep things in order */ 1589 if (after == NULL) { 1590 TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); 1591 } else { 1592 TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); 1593 } 1594 cif->vhif_nvrs++; 1595 } 1596 } 1597 1598 CARP_UNLOCK(cif); 1599 sc->sc_naddrs6++; 1600 sc->sc_ac.ac_if.if_flags |= IFF_UP; 1601 if (own) 1602 sc->sc_advskew = 0; 1603 carp_set_state(sc, INIT); 1604 carp_setrun(sc, 0); 1605 1606 return (0); 1607 1608cleanup: 1609 /* clean up multicast memberships */ 1610 if (!sc->sc_naddrs6) { 1611 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 1612 imm = LIST_FIRST(&im6o->im6o_memberships); 1613 LIST_REMOVE(imm, i6mm_chain); 1614 in6_leavegroup(imm); 1615 } 1616 } 1617 return (error); 1618} 1619 1620int 1621carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) 1622{ 1623 int error = 0; 1624 1625 if (!--sc->sc_naddrs6) { 1626 struct carp_if *cif = (struct carp_if *)sc->sc_ifp->if_carp; 1627 struct ip6_moptions *im6o = &sc->sc_im6o; 1628 1629 callout_stop(&sc->sc_ad_tmo); 1630 sc->sc_ac.ac_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 1631 sc->sc_vhid = -1; 1632 CARP_LOCK(cif); 1633 while (!LIST_EMPTY(&im6o->im6o_memberships)) { 1634 struct in6_multi_mship *imm = 1635 LIST_FIRST(&im6o->im6o_memberships); 1636 1637 LIST_REMOVE(imm, i6mm_chain); 1638 in6_leavegroup(imm); 1639 } 1640 im6o->im6o_multicast_ifp = NULL; 1641 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); 1642 if (!--cif->vhif_nvrs) { 1643 CARP_LOCK_DESTROY(cif); 1644 sc->sc_ifp->if_carp = NULL; 1645 FREE(cif, M_IFADDR); 1646 } else 1647 CARP_UNLOCK(cif); 1648 } 1649 1650 return (error); 1651} 1652#endif /* INET6 */ 1653 1654int 1655carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) 1656{ 1657 struct carp_softc *sc = ifp->if_softc, *vr; 1658 struct carpreq carpr; 1659 struct ifaddr *ifa; 1660 struct ifreq *ifr; 1661 struct ifaliasreq *ifra; 1662 int error = 0; 1663 1664 ifa = (struct ifaddr *)addr; 1665 ifra = (struct ifaliasreq *)addr; 1666 ifr = (struct ifreq *)addr; 1667 1668 switch (cmd) { 1669 case SIOCSIFADDR: 1670 switch (ifa->ifa_addr->sa_family) { 1671#ifdef INET 1672 case AF_INET: 1673 sc->sc_if.if_flags |= IFF_UP; 1674 bcopy(ifa->ifa_addr, ifa->ifa_dstaddr, 1675 sizeof(struct sockaddr)); 1676 error = carp_set_addr(sc, satosin(ifa->ifa_addr)); 1677 break; 1678#endif /* INET */ 1679#ifdef INET6 1680 case AF_INET6: 1681 sc->sc_if.if_flags |= IFF_UP; 1682 error = carp_set_addr6(sc, satosin6(ifa->ifa_addr)); 1683 break; 1684#endif /* INET6 */ 1685 default: 1686 error = EAFNOSUPPORT; 1687 break; 1688 } 1689 break; 1690 1691 case SIOCAIFADDR: 1692 switch (ifa->ifa_addr->sa_family) { 1693#ifdef INET 1694 case AF_INET: 1695 sc->sc_if.if_flags |= IFF_UP; 1696 bcopy(ifa->ifa_addr, ifa->ifa_dstaddr, 1697 sizeof(struct sockaddr)); 1698 error = carp_set_addr(sc, satosin(&ifra->ifra_addr)); 1699 break; 1700#endif /* INET */ 1701#ifdef INET6 1702 case AF_INET6: 1703 sc->sc_if.if_flags |= IFF_UP; 1704 error = carp_set_addr6(sc, satosin6(&ifra->ifra_addr)); 1705 break; 1706#endif /* INET6 */ 1707 default: 1708 error = EAFNOSUPPORT; 1709 break; 1710 } 1711 break; 1712 1713 case SIOCDIFADDR: 1714 sc->if_flags &= ~IFF_UP; 1715 switch (ifa->ifa_addr->sa_family) { 1716#ifdef INET 1717 case AF_INET: 1718 error = carp_del_addr(sc, satosin(&ifra->ifra_addr)); 1719 break; 1720#endif /* INET */ 1721#ifdef INET6 1722 case AF_INET6: 1723 error = carp_del_addr6(sc, satosin6(&ifra->ifra_addr)); 1724 break; 1725#endif /* INET6 */ 1726 default: 1727 error = EAFNOSUPPORT; 1728 break; 1729 } 1730 break; 1731 1732 case SIOCSIFFLAGS: 1733 if (sc->sc_state != INIT && !(ifr->ifr_flags & IFF_UP)) { 1734 sc->if_flags &= ~IFF_UP; 1735 callout_stop(&sc->sc_ad_tmo); 1736 callout_stop(&sc->sc_md_tmo); 1737 callout_stop(&sc->sc_md6_tmo); 1738 if (sc->sc_state == MASTER) 1739 carp_send_ad(sc); 1740 carp_set_state(sc, INIT); 1741 carp_setrun(sc, 0); 1742 } else if (sc->sc_state == INIT && (ifr->ifr_flags & IFF_UP)) { 1743 sc->sc_if.if_flags |= IFF_UP; 1744 carp_setrun(sc, 0); 1745 } 1746 break; 1747 1748 case SIOCSVH: 1749 if ((error = suser(curthread)) != 0) 1750 break; 1751 if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr))) 1752 break; 1753 error = 1; 1754 if (sc->sc_state != INIT && carpr.carpr_state != sc->sc_state) { 1755 switch (carpr.carpr_state) { 1756 case BACKUP: 1757 callout_stop(&sc->sc_ad_tmo); 1758 carp_set_state(sc, BACKUP); 1759 carp_setrun(sc, 0); 1760 carp_setroute(sc, RTM_DELETE); 1761 break; 1762 case MASTER: 1763 carp_master_down(sc); 1764 break; 1765 default: 1766 break; 1767 } 1768 } 1769 if (carpr.carpr_vhid > 0) { 1770 if (carpr.carpr_vhid > 255) { 1771 error = EINVAL; 1772 break; 1773 } 1774 if (sc->sc_ifp) { 1775 struct carp_if *cif; 1776 cif = (struct carp_if *)sc->sc_ifp->if_carp; 1777 CARP_LOCK(cif); 1778 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) 1779 if (vr != sc && 1780 vr->sc_vhid == carpr.carpr_vhid) { 1781 CARP_UNLOCK(cif); 1782 return EINVAL; 1783 } 1784 CARP_UNLOCK(cif); 1785 } 1786 sc->sc_vhid = carpr.carpr_vhid; 1787 sc->sc_ac.ac_enaddr[0] = 0; 1788 sc->sc_ac.ac_enaddr[1] = 0; 1789 sc->sc_ac.ac_enaddr[2] = 0x5e; 1790 sc->sc_ac.ac_enaddr[3] = 0; 1791 sc->sc_ac.ac_enaddr[4] = 1; 1792 sc->sc_ac.ac_enaddr[5] = sc->sc_vhid; 1793 error--; 1794 } 1795 if (carpr.carpr_advbase > 0 || carpr.carpr_advskew > 0) { 1796 if (carpr.carpr_advskew >= 255) { 1797 error = EINVAL; 1798 break; 1799 } 1800 if (carpr.carpr_advbase > 255) { 1801 error = EINVAL; 1802 break; 1803 } 1804 sc->sc_advbase = carpr.carpr_advbase; 1805 sc->sc_advskew = carpr.carpr_advskew; 1806 error--; 1807 } 1808 bcopy(carpr.carpr_key, sc->sc_key, sizeof(sc->sc_key)); 1809 if (error > 0) 1810 error = EINVAL; 1811 else { 1812 error = 0; 1813 carp_setrun(sc, 0); 1814 } 1815 break; 1816 1817 case SIOCGVH: 1818 bzero(&carpr, sizeof(carpr)); 1819 carpr.carpr_state = sc->sc_state; 1820 carpr.carpr_vhid = sc->sc_vhid; 1821 carpr.carpr_advbase = sc->sc_advbase; 1822 carpr.carpr_advskew = sc->sc_advskew; 1823 if (suser(curthread) == 0) 1824 bcopy(sc->sc_key, carpr.carpr_key, 1825 sizeof(carpr.carpr_key)); 1826 error = copyout(&carpr, ifr->ifr_data, sizeof(carpr)); 1827 break; 1828 1829 default: 1830 error = EINVAL; 1831 } 1832 1833 carp_hmac_prepare(sc); 1834 return (error); 1835} 1836 1837/* 1838 * XXX: this is looutput. We should eventually use it from there. 1839 */ 1840static int 1841carp_looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 1842 struct rtentry *rt) 1843{ 1844 M_ASSERTPKTHDR(m); /* check if we have the packet header */ 1845 1846 if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { 1847 m_freem(m); 1848 return (rt->rt_flags & RTF_BLACKHOLE ? 0 : 1849 rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 1850 } 1851 1852 ifp->if_opackets++; 1853 ifp->if_obytes += m->m_pkthdr.len; 1854#if 1 /* XXX */ 1855 switch (dst->sa_family) { 1856 case AF_INET: 1857 case AF_INET6: 1858 case AF_IPX: 1859 case AF_APPLETALK: 1860 break; 1861 default: 1862 printf("carp_looutput: af=%d unexpected\n", dst->sa_family); 1863 m_freem(m); 1864 return (EAFNOSUPPORT); 1865 } 1866#endif 1867 return(if_simloop(ifp, m, dst->sa_family, 0)); 1868} 1869 1870/* 1871 * Start output on carp interface. This function should never be called. 1872 */ 1873void 1874carp_start(struct ifnet *ifp) 1875{ 1876#ifdef DEBUG 1877 printf("%s: start called\n", ifp->if_xname); 1878#endif 1879} 1880 1881int 1882carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, 1883 struct rtentry *rt) 1884{ 1885 struct m_tag *mtag; 1886 struct carp_softc *sc; 1887 struct ifnet *carp_ifp; 1888 1889 if (!sa) 1890 return (0); 1891 1892 switch (sa->sa_family) { 1893#ifdef INET 1894 case AF_INET: 1895 break; 1896#endif /* INET */ 1897#ifdef INET6 1898 case AF_INET6: 1899 break; 1900#endif /* INET6 */ 1901 default: 1902 return (0); 1903 } 1904 1905 mtag = m_tag_find(m, PACKET_TAG_CARP, NULL); 1906 if (mtag == NULL) 1907 return (0); 1908 1909 bcopy(mtag + 1, &carp_ifp, sizeof(struct ifnet *)); 1910 sc = carp_ifp->if_softc; 1911 1912 /* Set the source MAC address to Virtual Router MAC Address */ 1913 switch (ifp->if_type) { 1914 case IFT_ETHER: { 1915 struct ether_header *eh; 1916 1917 eh = mtod(m, struct ether_header *); 1918 eh->ether_shost[0] = 0; 1919 eh->ether_shost[1] = 0; 1920 eh->ether_shost[2] = 0x5e; 1921 eh->ether_shost[3] = 0; 1922 eh->ether_shost[4] = 1; 1923 eh->ether_shost[5] = sc->sc_vhid; 1924 } 1925 break; 1926 case IFT_FDDI: { 1927 struct fddi_header *fh; 1928 1929 fh = mtod(m, struct fddi_header *); 1930 fh->fddi_shost[0] = 0; 1931 fh->fddi_shost[1] = 0; 1932 fh->fddi_shost[2] = 0x5e; 1933 fh->fddi_shost[3] = 0; 1934 fh->fddi_shost[4] = 1; 1935 fh->fddi_shost[5] = sc->sc_vhid; 1936 } 1937 break; 1938 case IFT_ISO88025: { 1939 struct iso88025_header *th; 1940 th = mtod(m, struct iso88025_header *); 1941 th->iso88025_shost[0] = 3; 1942 th->iso88025_shost[1] = 0; 1943 th->iso88025_shost[2] = 0x40 >> (sc->sc_vhid - 1); 1944 th->iso88025_shost[3] = 0x40000 >> (sc->sc_vhid - 1); 1945 th->iso88025_shost[4] = 0; 1946 th->iso88025_shost[5] = 0; 1947 } 1948 break; 1949 default: 1950 printf("%s: carp is not supported for this interface type\n", 1951 ifp->if_xname); 1952 return (EOPNOTSUPP); 1953 } 1954 1955 return (0); 1956} 1957 1958void 1959carp_set_state(struct carp_softc *sc, int state) 1960{ 1961 if (sc->sc_state == state) 1962 return; 1963 1964 sc->sc_state = state; 1965 switch (state) { 1966 case BACKUP: 1967 sc->sc_ac.ac_if.if_link_state = LINK_STATE_DOWN; 1968 break; 1969 case MASTER: 1970 sc->sc_ac.ac_if.if_link_state = LINK_STATE_UP; 1971 break; 1972 default: 1973 sc->sc_ac.ac_if.if_link_state = LINK_STATE_UNKNOWN; 1974 break; 1975 } 1976 rt_ifmsg(&sc->sc_ac.ac_if); 1977} 1978 1979void 1980carp_carpdev_state(void *v) 1981{ 1982 struct carp_if *cif = v; 1983 struct carp_softc *sc; 1984 1985 CARP_LOCK(cif); 1986 TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { 1987 if (sc->sc_ifp->if_link_state != LINK_STATE_UP || 1988 !(sc->sc_ifp->if_flags & IFF_UP)) { 1989 sc->sc_flags_backup = sc->sc_if.if_flags; 1990 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); 1991 callout_stop(&sc->sc_ad_tmo); 1992 callout_stop(&sc->sc_md_tmo); 1993 callout_stop(&sc->sc_md6_tmo); 1994 carp_set_state(sc, INIT); 1995 carp_setrun(sc, 0); 1996 if (!sc->sc_suppress) { 1997 carp_suppress_preempt++; 1998 if (carp_suppress_preempt == 1) 1999 carp_send_ad_all(); 2000 } 2001 sc->sc_suppress = 1; 2002 } else { 2003 sc->sc_if.if_flags |= sc->sc_flags_backup; 2004 carp_set_state(sc, INIT); 2005 carp_setrun(sc, 0); 2006 if (sc->sc_suppress) 2007 carp_suppress_preempt--; 2008 sc->sc_suppress = 0; 2009 } 2010 } 2011 CARP_UNLOCK(cif); 2012} 2013 2014static int 2015carp_modevent(module_t mod, int type, void *data) 2016{ 2017 int error = 0; 2018 2019 switch (type) { 2020 case MOD_LOAD: 2021 LIST_INIT(&carpif_list); 2022 if_clone_attach(&carp_cloner); 2023 printf("carp: attached\n"); 2024 break; 2025 2026 case MOD_UNLOAD: 2027 if_clone_detach(&carp_cloner); 2028 while (!LIST_EMPTY(&carpif_list)) 2029 carp_clone_destroy( 2030 &LIST_FIRST(&carpif_list)->sc_if); 2031 break; 2032 2033 default: 2034 error = EINVAL; 2035 break; 2036 } 2037 2038 return error; 2039} 2040 2041static moduledata_t carp_mod = { 2042 "carp", 2043 carp_modevent, 2044 0 2045}; 2046 2047DECLARE_MODULE(carp, carp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 2048