The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_carp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ip_carp.c,v 1.26.10.2 2009/06/09 17:31:46 snj Exp $    */
    2 /*      $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $   */
    3 
    4 /*
    5  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
    6  * Copyright (c) 2003 Ryan McBride. All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
   21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   23  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   26  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   27  * THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.26.10.2 2009/06/09 17:31:46 snj Exp $");
   32 
   33 /*
   34  * TODO:
   35  *      - iface reconfigure
   36  *      - support for hardware checksum calculations;
   37  *
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/proc.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/callout.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/errno.h>
   48 #include <sys/device.h>
   49 #include <sys/time.h>
   50 #include <sys/kernel.h>
   51 #include <sys/kauth.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/ucred.h>
   54 #include <sys/syslog.h>
   55 #include <sys/acct.h>
   56 
   57 #include <sys/cpu.h>
   58 
   59 #include <net/if.h>
   60 #include <net/pfil.h>
   61 #include <net/if_types.h>
   62 #include <net/if_ether.h>
   63 #include <net/route.h>
   64 #include <net/netisr.h>
   65 #include <net/net_stats.h>
   66 #include <netinet/if_inarp.h>
   67 
   68 #include <machine/stdarg.h>
   69 
   70 #if NFDDI > 0
   71 #include <net/if_fddi.h>
   72 #endif
   73 #if NTOKEN > 0
   74 #include <net/if_token.h>
   75 #endif
   76 
   77 #ifdef INET
   78 #include <netinet/in.h>
   79 #include <netinet/in_systm.h>
   80 #include <netinet/in_var.h>
   81 #include <netinet/ip.h>
   82 #include <netinet/ip_var.h>
   83 
   84 #include <net/if_dl.h>
   85 #endif
   86 
   87 #ifdef INET6
   88 #include <netinet/icmp6.h>
   89 #include <netinet/ip6.h>
   90 #include <netinet6/ip6_var.h>
   91 #include <netinet6/nd6.h>
   92 #include <netinet6/scope6_var.h>
   93 #endif
   94 
   95 #include "bpfilter.h"
   96 #if NBPFILTER > 0
   97 #include <net/bpf.h>
   98 #endif
   99 
  100 #include <sys/sha1.h>
  101 
  102 #include <netinet/ip_carp.h>
  103 
  104 struct carp_mc_entry {
  105         LIST_ENTRY(carp_mc_entry)       mc_entries;
  106         union {
  107                 struct ether_multi      *mcu_enm;
  108         } mc_u;
  109         struct sockaddr_storage         mc_addr;
  110 };
  111 #define mc_enm  mc_u.mcu_enm
  112 
  113 struct carp_softc {
  114         struct ethercom sc_ac;
  115 #define sc_if           sc_ac.ec_if
  116 #define sc_carpdev      sc_ac.ec_if.if_carpdev
  117         int ah_cookie;
  118         int lh_cookie;
  119         struct ip_moptions sc_imo;
  120 #ifdef INET6
  121         struct ip6_moptions sc_im6o;
  122 #endif /* INET6 */
  123         TAILQ_ENTRY(carp_softc) sc_list;
  124 
  125         enum { INIT = 0, BACKUP, MASTER }       sc_state;
  126 
  127         int sc_suppress;
  128         int sc_bow_out;
  129 
  130         int sc_sendad_errors;
  131 #define CARP_SENDAD_MAX_ERRORS  3
  132         int sc_sendad_success;
  133 #define CARP_SENDAD_MIN_SUCCESS 3
  134 
  135         int sc_vhid;
  136         int sc_advskew;
  137         int sc_naddrs;
  138         int sc_naddrs6;
  139         int sc_advbase;         /* seconds */
  140         int sc_init_counter;
  141         u_int64_t sc_counter;
  142 
  143         /* authentication */
  144 #define CARP_HMAC_PAD   64
  145         unsigned char sc_key[CARP_KEY_LEN];
  146         unsigned char sc_pad[CARP_HMAC_PAD];
  147         SHA1_CTX sc_sha1;
  148         u_int32_t sc_hashkey[2];
  149 
  150         struct callout sc_ad_tmo;       /* advertisement timeout */
  151         struct callout sc_md_tmo;       /* master down timeout */
  152         struct callout sc_md6_tmo;      /* master down timeout */
  153 
  154         LIST_HEAD(__carp_mchead, carp_mc_entry) carp_mc_listhead;
  155 };
  156 
  157 int carp_suppress_preempt = 0;
  158 int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 0, 0 };       /* XXX for now */
  159 
  160 static percpu_t *carpstat_percpu;
  161 
  162 #define CARP_STATINC(x)         _NET_STATINC(carpstat_percpu, x)
  163 
  164 struct carp_if {
  165         TAILQ_HEAD(, carp_softc) vhif_vrs;
  166         int vhif_nvrs;
  167 
  168         struct ifnet *vhif_ifp;
  169 };
  170 
  171 #define CARP_LOG(sc, s)                                                 \
  172         if (carp_opts[CARPCTL_LOG]) {                                   \
  173                 if (sc)                                                 \
  174                         log(LOG_INFO, "%s: ",                           \
  175                             (sc)->sc_if.if_xname);                      \
  176                 else                                                    \
  177                         log(LOG_INFO, "carp: ");                        \
  178                 addlog s;                                               \
  179                 addlog("\n");                                           \
  180         }
  181 
  182 void    carp_hmac_prepare(struct carp_softc *);
  183 void    carp_hmac_generate(struct carp_softc *, u_int32_t *,
  184             unsigned char *);
  185 int     carp_hmac_verify(struct carp_softc *, u_int32_t *,
  186             unsigned char *);
  187 void    carp_setroute(struct carp_softc *, int);
  188 void    carp_proto_input_c(struct mbuf *, struct carp_header *, sa_family_t);
  189 void    carpattach(int);
  190 void    carpdetach(struct carp_softc *);
  191 int     carp_prepare_ad(struct mbuf *, struct carp_softc *,
  192             struct carp_header *);
  193 void    carp_send_ad_all(void);
  194 void    carp_send_ad(void *);
  195 void    carp_send_arp(struct carp_softc *);
  196 void    carp_master_down(void *);
  197 int     carp_ioctl(struct ifnet *, u_long, void *);
  198 void    carp_start(struct ifnet *);
  199 void    carp_setrun(struct carp_softc *, sa_family_t);
  200 void    carp_set_state(struct carp_softc *, int);
  201 int     carp_addrcount(struct carp_if *, struct in_ifaddr *, int);
  202 enum    { CARP_COUNT_MASTER, CARP_COUNT_RUNNING };
  203 
  204 void    carp_multicast_cleanup(struct carp_softc *);
  205 int     carp_set_ifp(struct carp_softc *, struct ifnet *);
  206 void    carp_set_enaddr(struct carp_softc *);
  207 void    carp_addr_updated(void *);
  208 u_int32_t       carp_hash(struct carp_softc *, u_char *);
  209 int     carp_set_addr(struct carp_softc *, struct sockaddr_in *);
  210 int     carp_join_multicast(struct carp_softc *);
  211 #ifdef INET6
  212 void    carp_send_na(struct carp_softc *);
  213 int     carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *);
  214 int     carp_join_multicast6(struct carp_softc *);
  215 #endif
  216 int     carp_clone_create(struct if_clone *, int);
  217 int     carp_clone_destroy(struct ifnet *);
  218 int     carp_ether_addmulti(struct carp_softc *, struct ifreq *);
  219 int     carp_ether_delmulti(struct carp_softc *, struct ifreq *);
  220 void    carp_ether_purgemulti(struct carp_softc *);
  221 
  222 struct if_clone carp_cloner =
  223     IF_CLONE_INITIALIZER("carp", carp_clone_create, carp_clone_destroy);
  224 
  225 static __inline u_int16_t
  226 carp_cksum(struct mbuf *m, int len)
  227 {
  228         return (in_cksum(m, len));
  229 }
  230 
  231 void
  232 carp_hmac_prepare(struct carp_softc *sc)
  233 {
  234         u_int8_t carp_version = CARP_VERSION, type = CARP_ADVERTISEMENT;
  235         u_int8_t vhid = sc->sc_vhid & 0xff;
  236         SHA1_CTX sha1ctx;
  237         u_int32_t kmd[5];
  238         struct ifaddr *ifa;
  239         int i, found;
  240         struct in_addr last, cur, in;
  241 #ifdef INET6
  242         struct in6_addr last6, cur6, in6;
  243 #endif /* INET6 */
  244 
  245         /* compute ipad from key */
  246         bzero(sc->sc_pad, sizeof(sc->sc_pad));
  247         bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key));
  248         for (i = 0; i < sizeof(sc->sc_pad); i++)
  249                 sc->sc_pad[i] ^= 0x36;
  250 
  251         /* precompute first part of inner hash */
  252         SHA1Init(&sc->sc_sha1);
  253         SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad));
  254         SHA1Update(&sc->sc_sha1, (void *)&carp_version, sizeof(carp_version));
  255         SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type));
  256 
  257         /* generate a key for the arpbalance hash, before the vhid is hashed */
  258         bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx));
  259         SHA1Final((unsigned char *)kmd, &sha1ctx);
  260         sc->sc_hashkey[0] = kmd[0] ^ kmd[1];
  261         sc->sc_hashkey[1] = kmd[2] ^ kmd[3];
  262 
  263         /* the rest of the precomputation */
  264         SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid));
  265 
  266         /* Hash the addresses from smallest to largest, not interface order */
  267 #ifdef INET
  268         cur.s_addr = 0;
  269         do {
  270                 found = 0;
  271                 last = cur;
  272                 cur.s_addr = 0xffffffff;
  273                 IFADDR_FOREACH(ifa, &sc->sc_if) {
  274                         in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
  275                         if (ifa->ifa_addr->sa_family == AF_INET &&
  276                             ntohl(in.s_addr) > ntohl(last.s_addr) &&
  277                             ntohl(in.s_addr) < ntohl(cur.s_addr)) {
  278                                 cur.s_addr = in.s_addr;
  279                                 found++;
  280                         }
  281                 }
  282                 if (found)
  283                         SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur));
  284         } while (found);
  285 #endif /* INET */
  286 
  287 #ifdef INET6
  288         memset(&cur6, 0x00, sizeof(cur6));
  289         do {
  290                 found = 0;
  291                 last6 = cur6;
  292                 memset(&cur6, 0xff, sizeof(cur6));
  293                 IFADDR_FOREACH(ifa, &sc->sc_if) {
  294                         in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
  295                         if (IN6_IS_ADDR_LINKLOCAL(&in6))
  296                                 in6.s6_addr16[1] = 0;
  297                         if (ifa->ifa_addr->sa_family == AF_INET6 &&
  298                             memcmp(&in6, &last6, sizeof(in6)) > 0 &&
  299                             memcmp(&in6, &cur6, sizeof(in6)) < 0) {
  300                                 cur6 = in6;
  301                                 found++;
  302                         }
  303                 }
  304                 if (found)
  305                         SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6));
  306         } while (found);
  307 #endif /* INET6 */
  308 
  309         /* convert ipad to opad */
  310         for (i = 0; i < sizeof(sc->sc_pad); i++)
  311                 sc->sc_pad[i] ^= 0x36 ^ 0x5c;
  312 }
  313 
  314 void
  315 carp_hmac_generate(struct carp_softc *sc, u_int32_t counter[2],
  316     unsigned char md[20])
  317 {
  318         SHA1_CTX sha1ctx;
  319 
  320         /* fetch first half of inner hash */
  321         bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx));
  322 
  323         SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter));
  324         SHA1Final(md, &sha1ctx);
  325 
  326         /* outer hash */
  327         SHA1Init(&sha1ctx);
  328         SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad));
  329         SHA1Update(&sha1ctx, md, 20);
  330         SHA1Final(md, &sha1ctx);
  331 }
  332 
  333 int
  334 carp_hmac_verify(struct carp_softc *sc, u_int32_t counter[2],
  335     unsigned char md[20])
  336 {
  337         unsigned char md2[20];
  338 
  339         carp_hmac_generate(sc, counter, md2);
  340 
  341         return (bcmp(md, md2, sizeof(md2)));
  342 }
  343 
  344 void
  345 carp_setroute(struct carp_softc *sc, int cmd)
  346 {
  347         struct ifaddr *ifa;
  348         int s;
  349 
  350         s = splsoftnet();
  351         IFADDR_FOREACH(ifa, &sc->sc_if) {
  352                 switch (ifa->ifa_addr->sa_family) {
  353                 case AF_INET: {
  354                         int count = 0;
  355                         struct rtentry *rt;
  356                         int hr_otherif, nr_ourif;
  357 
  358                         /*
  359                          * Avoid screwing with the routes if there are other
  360                          * carp interfaces which are master and have the same
  361                          * address.
  362                          */
  363                         if (sc->sc_carpdev != NULL &&
  364                             sc->sc_carpdev->if_carp != NULL) {
  365                                 count = carp_addrcount(
  366                                     (struct carp_if *)sc->sc_carpdev->if_carp,
  367                                     ifatoia(ifa), CARP_COUNT_MASTER);
  368                                 if ((cmd == RTM_ADD && count != 1) ||
  369                                     (cmd == RTM_DELETE && count != 0))
  370                                         continue;
  371                         }
  372 
  373                         /* Remove the existing host route, if any */
  374                         rtrequest(RTM_DELETE, ifa->ifa_addr,
  375                             ifa->ifa_addr, ifa->ifa_netmask,
  376                             RTF_HOST, NULL);
  377 
  378                         rt = NULL;
  379                         (void)rtrequest(RTM_GET, ifa->ifa_addr, ifa->ifa_addr,
  380                             ifa->ifa_netmask, RTF_HOST, &rt);
  381                         hr_otherif = (rt && rt->rt_ifp != &sc->sc_if &&
  382                             rt->rt_flags & (RTF_CLONING|RTF_CLONED));
  383                         if (rt != NULL) {
  384                                 RTFREE(rt);
  385                                 rt = NULL;
  386                         }
  387 
  388                         /* Check for a network route on our interface */
  389 
  390                         rt = NULL;
  391                         (void)rtrequest(RTM_GET, ifa->ifa_addr, ifa->ifa_addr,
  392                             ifa->ifa_netmask, 0, &rt);
  393                         nr_ourif = (rt && rt->rt_ifp == &sc->sc_if);
  394 
  395                         switch (cmd) {
  396                         case RTM_ADD:
  397                                 if (hr_otherif) {
  398                                         ifa->ifa_rtrequest = NULL;
  399                                         ifa->ifa_flags &= ~RTF_CLONING;
  400 
  401                                         rtrequest(RTM_ADD, ifa->ifa_addr,
  402                                             ifa->ifa_addr, ifa->ifa_netmask,
  403                                             RTF_UP | RTF_HOST, NULL);
  404                                 }
  405                                 if (!hr_otherif || nr_ourif || !rt) {
  406                                         if (nr_ourif && !(rt->rt_flags &
  407                                             RTF_CLONING))
  408                                                 rtrequest(RTM_DELETE,
  409                                                     ifa->ifa_addr,
  410                                                     ifa->ifa_addr,
  411                                                     ifa->ifa_netmask, 0, NULL);
  412 
  413                                         ifa->ifa_rtrequest = arp_rtrequest;
  414                                         ifa->ifa_flags |= RTF_CLONING;
  415 
  416                                         if (rtrequest(RTM_ADD, ifa->ifa_addr,
  417                                             ifa->ifa_addr, ifa->ifa_netmask, 0,
  418                                             NULL) == 0)
  419                                                 ifa->ifa_flags |= IFA_ROUTE;
  420                                 }
  421                                 break;
  422                         case RTM_DELETE:
  423                                 break;
  424                         default:
  425                                 break;
  426                         }
  427                         if (rt != NULL) {
  428                                 RTFREE(rt);
  429                                 rt = NULL;
  430                         }
  431                         break;
  432                 }
  433 
  434 #ifdef INET6
  435                 case AF_INET6:
  436                         if (cmd == RTM_ADD)
  437                                 in6_ifaddloop(ifa);
  438                         else
  439                                 in6_ifremloop(ifa);
  440                         break;
  441 #endif /* INET6 */
  442                 default:
  443                         break;
  444                 }
  445         }
  446         splx(s);
  447 }
  448 
  449 /*
  450  * process input packet.
  451  * we have rearranged checks order compared to the rfc,
  452  * but it seems more efficient this way or not possible otherwise.
  453  */
  454 void
  455 carp_proto_input(struct mbuf *m, ...)
  456 {
  457         struct ip *ip = mtod(m, struct ip *);
  458         struct carp_softc *sc = NULL;
  459         struct carp_header *ch;
  460         int iplen, len, hlen;
  461         va_list ap;
  462 
  463         va_start(ap, m);
  464         hlen = va_arg(ap, int);
  465         va_end(ap);
  466 
  467         CARP_STATINC(CARP_STAT_IPACKETS);
  468 
  469         if (!carp_opts[CARPCTL_ALLOW]) {
  470                 m_freem(m);
  471                 return;
  472         }
  473 
  474         /* check if received on a valid carp interface */
  475         if (m->m_pkthdr.rcvif->if_type != IFT_CARP) {
  476                 CARP_STATINC(CARP_STAT_BADIF);
  477                 CARP_LOG(sc, ("packet received on non-carp interface: %s",
  478                     m->m_pkthdr.rcvif->if_xname));
  479                 m_freem(m);
  480                 return;
  481         }
  482 
  483         /* verify that the IP TTL is 255.  */
  484         if (ip->ip_ttl != CARP_DFLTTL) {
  485                 CARP_STATINC(CARP_STAT_BADTTL);
  486                 CARP_LOG(sc, ("received ttl %d != %d on %s", ip->ip_ttl,
  487                     CARP_DFLTTL, m->m_pkthdr.rcvif->if_xname));
  488                 m_freem(m);
  489                 return;
  490         }
  491 
  492         /*
  493          * verify that the received packet length is
  494          * equal to the CARP header
  495          */
  496         iplen = ip->ip_hl << 2;
  497         len = iplen + sizeof(*ch);
  498         if (len > m->m_pkthdr.len) {
  499                 CARP_STATINC(CARP_STAT_BADLEN);
  500                 CARP_LOG(sc, ("packet too short %d on %s", m->m_pkthdr.len,
  501                     m->m_pkthdr.rcvif->if_xname));
  502                 m_freem(m);
  503                 return;
  504         }
  505 
  506         if ((m = m_pullup(m, len)) == NULL) {
  507                 CARP_STATINC(CARP_STAT_HDROPS);
  508                 return;
  509         }
  510         ip = mtod(m, struct ip *);
  511         ch = (struct carp_header *)((char *)ip + iplen);
  512         /* verify the CARP checksum */
  513         m->m_data += iplen;
  514         if (carp_cksum(m, len - iplen)) {
  515                 CARP_STATINC(CARP_STAT_BADSUM);
  516                 CARP_LOG(sc, ("checksum failed on %s",
  517                     m->m_pkthdr.rcvif->if_xname));
  518                 m_freem(m);
  519                 return;
  520         }
  521         m->m_data -= iplen;
  522 
  523         carp_proto_input_c(m, ch, AF_INET);
  524 }
  525 
  526 #ifdef INET6
  527 int
  528 carp6_proto_input(struct mbuf **mp, int *offp, int proto)
  529 {
  530         struct mbuf *m = *mp;
  531         struct carp_softc *sc = NULL;
  532         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  533         struct carp_header *ch;
  534         u_int len;
  535 
  536         CARP_STATINC(CARP_STAT_IPACKETS6);
  537 
  538         if (!carp_opts[CARPCTL_ALLOW]) {
  539                 m_freem(m);
  540                 return (IPPROTO_DONE);
  541         }
  542 
  543         /* check if received on a valid carp interface */
  544         if (m->m_pkthdr.rcvif->if_type != IFT_CARP) {
  545                 CARP_STATINC(CARP_STAT_BADIF);
  546                 CARP_LOG(sc, ("packet received on non-carp interface: %s",
  547                     m->m_pkthdr.rcvif->if_xname));
  548                 m_freem(m);
  549                 return (IPPROTO_DONE);
  550         }
  551 
  552         /* verify that the IP TTL is 255 */
  553         if (ip6->ip6_hlim != CARP_DFLTTL) {
  554                 CARP_STATINC(CARP_STAT_BADTTL);
  555                 CARP_LOG(sc, ("received ttl %d != %d on %s", ip6->ip6_hlim,
  556                     CARP_DFLTTL, m->m_pkthdr.rcvif->if_xname));
  557                 m_freem(m);
  558                 return (IPPROTO_DONE);
  559         }
  560 
  561         /* verify that we have a complete carp packet */
  562         len = m->m_len;
  563         IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch));
  564         if (ch == NULL) {
  565                 CARP_STATINC(CARP_STAT_BADLEN);
  566                 CARP_LOG(sc, ("packet size %u too small", len));
  567                 return (IPPROTO_DONE);
  568         }
  569 
  570 
  571         /* verify the CARP checksum */
  572         m->m_data += *offp;
  573         if (carp_cksum(m, sizeof(*ch))) {
  574                 CARP_STATINC(CARP_STAT_BADSUM);
  575                 CARP_LOG(sc, ("checksum failed, on %s",
  576                     m->m_pkthdr.rcvif->if_xname));
  577                 m_freem(m);
  578                 return (IPPROTO_DONE);
  579         }
  580         m->m_data -= *offp;
  581 
  582         carp_proto_input_c(m, ch, AF_INET6);
  583         return (IPPROTO_DONE);
  584 }
  585 #endif /* INET6 */
  586 
  587 void
  588 carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
  589 {
  590         struct carp_softc *sc;
  591         u_int64_t tmp_counter;
  592         struct timeval sc_tv, ch_tv;
  593 
  594         TAILQ_FOREACH(sc, &((struct carp_if *)
  595             m->m_pkthdr.rcvif->if_carpdev->if_carp)->vhif_vrs, sc_list)
  596                 if (sc->sc_vhid == ch->carp_vhid)
  597                         break;
  598 
  599         if (!sc || (sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
  600             (IFF_UP|IFF_RUNNING)) {
  601                 CARP_STATINC(CARP_STAT_BADVHID);
  602                 m_freem(m);
  603                 return;
  604         }
  605 
  606         /*
  607          * Check if our own advertisement was duplicated
  608          * from a non simplex interface.
  609          * XXX If there is no address on our physical interface
  610          * there is no way to distinguish our ads from the ones
  611          * another carp host might have sent us.
  612          */
  613         if ((sc->sc_carpdev->if_flags & IFF_SIMPLEX) == 0) {
  614                 struct sockaddr sa;
  615                 struct ifaddr *ifa;
  616 
  617                 bzero(&sa, sizeof(sa));
  618                 sa.sa_family = af;
  619                 ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev);
  620 
  621                 if (ifa && af == AF_INET) {
  622                         struct ip *ip = mtod(m, struct ip *);
  623                         if (ip->ip_src.s_addr ==
  624                                         ifatoia(ifa)->ia_addr.sin_addr.s_addr) {
  625                                 m_freem(m);
  626                                 return;
  627                         }
  628                 }
  629 #ifdef INET6
  630                 if (ifa && af == AF_INET6) {
  631                         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  632                         struct in6_addr in6_src, in6_found;
  633 
  634                         in6_src = ip6->ip6_src;
  635                         in6_found = ifatoia6(ifa)->ia_addr.sin6_addr;
  636                         if (IN6_IS_ADDR_LINKLOCAL(&in6_src))
  637                                 in6_src.s6_addr16[1] = 0;
  638                         if (IN6_IS_ADDR_LINKLOCAL(&in6_found))
  639                                 in6_found.s6_addr16[1] = 0;
  640                         if (IN6_ARE_ADDR_EQUAL(&in6_src, &in6_found)) {
  641                                 m_freem(m);
  642                                 return;
  643                         }
  644                 }
  645 #endif /* INET6 */
  646         }
  647 
  648         microtime(&sc->sc_if.if_lastchange);
  649         sc->sc_if.if_ipackets++;
  650         sc->sc_if.if_ibytes += m->m_pkthdr.len;
  651 
  652         /* verify the CARP version. */
  653         if (ch->carp_version != CARP_VERSION) {
  654                 CARP_STATINC(CARP_STAT_BADVER);
  655                 sc->sc_if.if_ierrors++;
  656                 CARP_LOG(sc, ("invalid version %d != %d",
  657                     ch->carp_version, CARP_VERSION));
  658                 m_freem(m);
  659                 return;
  660         }
  661 
  662         /* verify the hash */
  663         if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) {
  664                 CARP_STATINC(CARP_STAT_BADAUTH);
  665                 sc->sc_if.if_ierrors++;
  666                 CARP_LOG(sc, ("incorrect hash"));
  667                 m_freem(m);
  668                 return;
  669         }
  670 
  671         tmp_counter = ntohl(ch->carp_counter[0]);
  672         tmp_counter = tmp_counter<<32;
  673         tmp_counter += ntohl(ch->carp_counter[1]);
  674 
  675         /* XXX Replay protection goes here */
  676 
  677         sc->sc_init_counter = 0;
  678         sc->sc_counter = tmp_counter;
  679 
  680 
  681         sc_tv.tv_sec = sc->sc_advbase;
  682         if (carp_suppress_preempt && sc->sc_advskew <  240)
  683                 sc_tv.tv_usec = 240 * 1000000 / 256;
  684         else
  685                 sc_tv.tv_usec = sc->sc_advskew * 1000000 / 256;
  686         ch_tv.tv_sec = ch->carp_advbase;
  687         ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256;
  688 
  689         switch (sc->sc_state) {
  690         case INIT:
  691                 break;
  692         case MASTER:
  693                 /*
  694                  * If we receive an advertisement from a backup who's going to
  695                  * be more frequent than us, go into BACKUP state.
  696                  */
  697                 if (timercmp(&sc_tv, &ch_tv, >) ||
  698                     timercmp(&sc_tv, &ch_tv, ==)) {
  699                         callout_stop(&sc->sc_ad_tmo);
  700                         CARP_LOG(sc, ("MASTER -> BACKUP (more frequent advertisement received)"));
  701                         carp_set_state(sc, BACKUP);
  702                         carp_setrun(sc, 0);
  703                         carp_setroute(sc, RTM_DELETE);
  704                 }
  705                 break;
  706         case BACKUP:
  707                 /*
  708                  * If we're pre-empting masters who advertise slower than us,
  709                  * and this one claims to be slower, treat him as down.
  710                  */
  711                 if (carp_opts[CARPCTL_PREEMPT] && timercmp(&sc_tv, &ch_tv, <)) {
  712                         CARP_LOG(sc, ("BACKUP -> MASTER (preempting a slower master)"));
  713                         carp_master_down(sc);
  714                         break;
  715                 }
  716 
  717                 /*
  718                  *  If the master is going to advertise at such a low frequency
  719                  *  that he's guaranteed to time out, we'd might as well just
  720                  *  treat him as timed out now.
  721                  */
  722                 sc_tv.tv_sec = sc->sc_advbase * 3;
  723                 if (timercmp(&sc_tv, &ch_tv, <)) {
  724                         CARP_LOG(sc, ("BACKUP -> MASTER (master timed out)"));
  725                         carp_master_down(sc);
  726                         break;
  727                 }
  728 
  729                 /*
  730                  * Otherwise, we reset the counter and wait for the next
  731                  * advertisement.
  732                  */
  733                 carp_setrun(sc, af);
  734                 break;
  735         }
  736 
  737         m_freem(m);
  738         return;
  739 }
  740 
  741 /*
  742  * Interface side of the CARP implementation.
  743  */
  744 
  745 /* ARGSUSED */
  746 void
  747 carpattach(int n)
  748 {
  749         if_clone_attach(&carp_cloner);
  750 
  751         carpstat_percpu = percpu_alloc(sizeof(uint64_t) * CARP_NSTATS);
  752 }
  753 
  754 int
  755 carp_clone_create(struct if_clone *ifc, int unit)
  756 {
  757         extern int ifqmaxlen;
  758         struct carp_softc *sc;
  759         struct ifnet *ifp;
  760 
  761         sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
  762         if (!sc)
  763                 return (ENOMEM);
  764         bzero(sc, sizeof(*sc));
  765 
  766         sc->sc_suppress = 0;
  767         sc->sc_advbase = CARP_DFLTINTV;
  768         sc->sc_vhid = -1;       /* required setting */
  769         sc->sc_advskew = 0;
  770         sc->sc_init_counter = 1;
  771         sc->sc_naddrs = sc->sc_naddrs6 = 0;
  772 #ifdef INET6
  773         sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL;
  774 #endif /* INET6 */
  775 
  776         callout_init(&sc->sc_ad_tmo, 0);
  777         callout_init(&sc->sc_md_tmo, 0);
  778         callout_init(&sc->sc_md6_tmo, 0);
  779 
  780         callout_setfunc(&sc->sc_ad_tmo, carp_send_ad, sc);
  781         callout_setfunc(&sc->sc_md_tmo, carp_master_down, sc);
  782         callout_setfunc(&sc->sc_md6_tmo, carp_master_down, sc);
  783 
  784         LIST_INIT(&sc->carp_mc_listhead);
  785         ifp = &sc->sc_if;
  786         ifp->if_softc = sc;
  787         snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
  788             unit);
  789         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  790         ifp->if_ioctl = carp_ioctl;
  791         ifp->if_start = carp_start;
  792         ifp->if_output = carp_output;
  793         ifp->if_type = IFT_CARP;
  794         ifp->if_addrlen = ETHER_ADDR_LEN;
  795         ifp->if_hdrlen = ETHER_HDR_LEN;
  796         ifp->if_mtu = ETHERMTU;
  797         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  798         IFQ_SET_READY(&ifp->if_snd);
  799         if_attach(ifp);
  800 
  801         if_alloc_sadl(ifp);
  802         ifp->if_broadcastaddr = etherbroadcastaddr;
  803         carp_set_enaddr(sc);
  804         LIST_INIT(&sc->sc_ac.ec_multiaddrs);
  805 #if NBPFILTER > 0
  806         bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
  807 #endif
  808         return (0);
  809 }
  810 
  811 int
  812 carp_clone_destroy(struct ifnet *ifp)
  813 {
  814         struct carp_softc *sc = ifp->if_softc;
  815 
  816         carpdetach(ifp->if_softc);
  817         ether_ifdetach(ifp);
  818         if_detach(ifp);
  819         callout_destroy(&sc->sc_ad_tmo);
  820         callout_destroy(&sc->sc_md_tmo);
  821         callout_destroy(&sc->sc_md6_tmo);
  822         free(ifp->if_softc, M_DEVBUF);
  823 
  824         return (0);
  825 }
  826 
  827 void
  828 carpdetach(struct carp_softc *sc)
  829 {
  830         struct carp_if *cif;
  831         int s;
  832 
  833         callout_stop(&sc->sc_ad_tmo);
  834         callout_stop(&sc->sc_md_tmo);
  835         callout_stop(&sc->sc_md6_tmo);
  836 
  837         if (sc->sc_suppress)
  838                 carp_suppress_preempt--;
  839         sc->sc_suppress = 0;
  840 
  841         if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS)
  842                 carp_suppress_preempt--;
  843         sc->sc_sendad_errors = 0;
  844 
  845         carp_set_state(sc, INIT);
  846         sc->sc_if.if_flags &= ~IFF_UP;
  847         carp_setrun(sc, 0);
  848         carp_multicast_cleanup(sc);
  849 
  850         s = splnet();
  851         if (sc->sc_carpdev != NULL) {
  852                 /* XXX linkstatehook removal */
  853                 cif = (struct carp_if *)sc->sc_carpdev->if_carp;
  854                 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list);
  855                 if (!--cif->vhif_nvrs) {
  856                         ifpromisc(sc->sc_carpdev, 0);
  857                         sc->sc_carpdev->if_carp = NULL;
  858                         FREE(cif, M_IFADDR);
  859                 }
  860         }
  861         sc->sc_carpdev = NULL;
  862         splx(s);
  863 }
  864 
  865 /* Detach an interface from the carp. */
  866 void
  867 carp_ifdetach(struct ifnet *ifp)
  868 {
  869         struct carp_softc *sc, *nextsc;
  870         struct carp_if *cif = (struct carp_if *)ifp->if_carp;
  871 
  872         for (sc = TAILQ_FIRST(&cif->vhif_vrs); sc; sc = nextsc) {
  873                 nextsc = TAILQ_NEXT(sc, sc_list);
  874                 carpdetach(sc);
  875         }
  876 }
  877 
  878 int
  879 carp_prepare_ad(struct mbuf *m, struct carp_softc *sc,
  880     struct carp_header *ch)
  881 {
  882         if (sc->sc_init_counter) {
  883                 /* this could also be seconds since unix epoch */
  884                 sc->sc_counter = arc4random();
  885                 sc->sc_counter = sc->sc_counter << 32;
  886                 sc->sc_counter += arc4random();
  887         } else
  888                 sc->sc_counter++;
  889 
  890         ch->carp_counter[0] = htonl((sc->sc_counter>>32)&0xffffffff);
  891         ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff);
  892 
  893         carp_hmac_generate(sc, ch->carp_counter, ch->carp_md);
  894 
  895         return (0);
  896 }
  897 
  898 void
  899 carp_send_ad_all(void)
  900 {
  901         struct ifnet *ifp;
  902         struct carp_if *cif;
  903         struct carp_softc *vh;
  904 
  905         TAILQ_FOREACH(ifp, &ifnet, if_list) {
  906                 if (ifp->if_carp == NULL || ifp->if_type == IFT_CARP)
  907                         continue;
  908 
  909                 cif = (struct carp_if *)ifp->if_carp;
  910                 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
  911                         if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) ==
  912                             (IFF_UP|IFF_RUNNING) && vh->sc_state == MASTER)
  913                                 carp_send_ad(vh);
  914                 }
  915         }
  916 }
  917 
  918 
  919 void
  920 carp_send_ad(void *v)
  921 {
  922         struct carp_header ch;
  923         struct timeval tv;
  924         struct carp_softc *sc = v;
  925         struct carp_header *ch_ptr;
  926         struct mbuf *m;
  927         int error, len, advbase, advskew, s;
  928         struct ifaddr *ifa;
  929         struct sockaddr sa;
  930 
  931         s = splsoftnet();
  932 
  933         advbase = advskew = 0; /* Sssssh compiler */
  934         if (sc->sc_carpdev == NULL) {
  935                 sc->sc_if.if_oerrors++;
  936                 goto retry_later;
  937         }
  938 
  939         /* bow out if we've gone to backup (the carp interface is going down) */
  940         if (sc->sc_bow_out) {
  941                 sc->sc_bow_out = 0;
  942                 advbase = 255;
  943                 advskew = 255;
  944         } else {
  945                 advbase = sc->sc_advbase;
  946                 if (!carp_suppress_preempt || sc->sc_advskew > 240)
  947                         advskew = sc->sc_advskew;
  948                 else
  949                         advskew = 240;
  950                 tv.tv_sec = advbase;
  951                 tv.tv_usec = advskew * 1000000 / 256;
  952         }
  953 
  954         ch.carp_version = CARP_VERSION;
  955         ch.carp_type = CARP_ADVERTISEMENT;
  956         ch.carp_vhid = sc->sc_vhid;
  957         ch.carp_advbase = advbase;
  958         ch.carp_advskew = advskew;
  959         ch.carp_authlen = 7;    /* XXX DEFINE */
  960         ch.carp_pad1 = 0;       /* must be zero */
  961         ch.carp_cksum = 0;
  962 
  963 
  964 #ifdef INET
  965         if (sc->sc_naddrs) {
  966                 struct ip *ip;
  967 
  968                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
  969                 if (m == NULL) {
  970                         sc->sc_if.if_oerrors++;
  971                         CARP_STATINC(CARP_STAT_ONOMEM);
  972                         /* XXX maybe less ? */
  973                         goto retry_later;
  974                 }
  975                 len = sizeof(*ip) + sizeof(ch);
  976                 m->m_pkthdr.len = len;
  977                 m->m_pkthdr.rcvif = NULL;
  978                 m->m_len = len;
  979                 MH_ALIGN(m, m->m_len);
  980                 m->m_flags |= M_MCAST;
  981                 ip = mtod(m, struct ip *);
  982                 ip->ip_v = IPVERSION;
  983                 ip->ip_hl = sizeof(*ip) >> 2;
  984                 ip->ip_tos = IPTOS_LOWDELAY;
  985                 ip->ip_len = htons(len);
  986                 ip->ip_id = 0;  /* no need for id, we don't support fragments */
  987                 ip->ip_off = htons(IP_DF);
  988                 ip->ip_ttl = CARP_DFLTTL;
  989                 ip->ip_p = IPPROTO_CARP;
  990                 ip->ip_sum = 0;
  991 
  992                 bzero(&sa, sizeof(sa));
  993                 sa.sa_family = AF_INET;
  994                 ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev);
  995                 if (ifa == NULL)
  996                         ip->ip_src.s_addr = 0;
  997                 else
  998                         ip->ip_src.s_addr =
  999                             ifatoia(ifa)->ia_addr.sin_addr.s_addr;
 1000                 ip->ip_dst.s_addr = INADDR_CARP_GROUP;
 1001 
 1002                 ch_ptr = (struct carp_header *)(&ip[1]);
 1003                 bcopy(&ch, ch_ptr, sizeof(ch));
 1004                 if (carp_prepare_ad(m, sc, ch_ptr))
 1005                         goto retry_later;
 1006 
 1007                 m->m_data += sizeof(*ip);
 1008                 ch_ptr->carp_cksum = carp_cksum(m, len - sizeof(*ip));
 1009                 m->m_data -= sizeof(*ip);
 1010 
 1011                 microtime(&sc->sc_if.if_lastchange);
 1012                 sc->sc_if.if_opackets++;
 1013                 sc->sc_if.if_obytes += len;
 1014                 CARP_STATINC(CARP_STAT_OPACKETS);
 1015 
 1016                 error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo,
 1017                     NULL);
 1018                 if (error) {
 1019                         if (error == ENOBUFS)
 1020                                 CARP_STATINC(CARP_STAT_ONOMEM);
 1021                         else
 1022                                 CARP_LOG(sc, ("ip_output failed: %d", error));
 1023                         sc->sc_if.if_oerrors++;
 1024                         if (sc->sc_sendad_errors < INT_MAX)
 1025                                 sc->sc_sendad_errors++;
 1026                         if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) {
 1027                                 carp_suppress_preempt++;
 1028                                 if (carp_suppress_preempt == 1)
 1029                                         carp_send_ad_all();
 1030                         }
 1031                         sc->sc_sendad_success = 0;
 1032                 } else {
 1033                         if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) {
 1034                                 if (++sc->sc_sendad_success >=
 1035                                     CARP_SENDAD_MIN_SUCCESS) {
 1036                                         carp_suppress_preempt--;
 1037                                         sc->sc_sendad_errors = 0;
 1038                                 }
 1039                         } else
 1040                                 sc->sc_sendad_errors = 0;
 1041                 }
 1042         }
 1043 #endif /* INET */
 1044 #ifdef INET6
 1045         if (sc->sc_naddrs6) {
 1046                 struct ip6_hdr *ip6;
 1047 
 1048                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
 1049                 if (m == NULL) {
 1050                         sc->sc_if.if_oerrors++;
 1051                         CARP_STATINC(CARP_STAT_ONOMEM);
 1052                         /* XXX maybe less ? */
 1053                         goto retry_later;
 1054                 }
 1055                 len = sizeof(*ip6) + sizeof(ch);
 1056                 m->m_pkthdr.len = len;
 1057                 m->m_pkthdr.rcvif = NULL;
 1058                 m->m_len = len;
 1059                 MH_ALIGN(m, m->m_len);
 1060                 m->m_flags |= M_MCAST;
 1061                 ip6 = mtod(m, struct ip6_hdr *);
 1062                 bzero(ip6, sizeof(*ip6));
 1063                 ip6->ip6_vfc |= IPV6_VERSION;
 1064                 ip6->ip6_hlim = CARP_DFLTTL;
 1065                 ip6->ip6_nxt = IPPROTO_CARP;
 1066 
 1067                 /* set the source address */
 1068                 bzero(&sa, sizeof(sa));
 1069                 sa.sa_family = AF_INET6;
 1070                 ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev);
 1071                 if (ifa == NULL)        /* This should never happen with IPv6 */
 1072                         bzero(&ip6->ip6_src, sizeof(struct in6_addr));
 1073                 else
 1074                         bcopy(ifatoia6(ifa)->ia_addr.sin6_addr.s6_addr,
 1075                             &ip6->ip6_src, sizeof(struct in6_addr));
 1076                 /* set the multicast destination */
 1077 
 1078                 ip6->ip6_dst.s6_addr16[0] = htons(0xff02);
 1079                 ip6->ip6_dst.s6_addr8[15] = 0x12;
 1080                 if (in6_setscope(&ip6->ip6_dst, sc->sc_carpdev, NULL) != 0) {
 1081                         sc->sc_if.if_oerrors++;
 1082                         m_freem(m);
 1083                         CARP_LOG(sc, ("in6_setscope failed"));
 1084                         goto retry_later;
 1085                 }
 1086 
 1087                 ch_ptr = (struct carp_header *)(&ip6[1]);
 1088                 bcopy(&ch, ch_ptr, sizeof(ch));
 1089                 if (carp_prepare_ad(m, sc, ch_ptr))
 1090                         goto retry_later;
 1091 
 1092                 m->m_data += sizeof(*ip6);
 1093                 ch_ptr->carp_cksum = carp_cksum(m, len - sizeof(*ip6));
 1094                 m->m_data -= sizeof(*ip6);
 1095 
 1096                 microtime(&sc->sc_if.if_lastchange);
 1097                 sc->sc_if.if_opackets++;
 1098                 sc->sc_if.if_obytes += len;
 1099                 CARP_STATINC(CARP_STAT_OPACKETS6);
 1100 
 1101                 error = ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL, NULL);
 1102                 if (error) {
 1103                         if (error == ENOBUFS)
 1104                                 CARP_STATINC(CARP_STAT_ONOMEM);
 1105                         else
 1106                                 CARP_LOG(sc, ("ip6_output failed: %d", error));
 1107                         sc->sc_if.if_oerrors++;
 1108                         if (sc->sc_sendad_errors < INT_MAX)
 1109                                 sc->sc_sendad_errors++;
 1110                         if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) {
 1111                                 carp_suppress_preempt++;
 1112                                 if (carp_suppress_preempt == 1)
 1113                                         carp_send_ad_all();
 1114                         }
 1115                         sc->sc_sendad_success = 0;
 1116                 } else {
 1117                         if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS) {
 1118                                 if (++sc->sc_sendad_success >=
 1119                                     CARP_SENDAD_MIN_SUCCESS) {
 1120                                         carp_suppress_preempt--;
 1121                                         sc->sc_sendad_errors = 0;
 1122                                 }
 1123                         } else
 1124                                 sc->sc_sendad_errors = 0;
 1125                 }
 1126         }
 1127 #endif /* INET6 */
 1128 
 1129 retry_later:
 1130         splx(s);
 1131         if (advbase != 255 || advskew != 255)
 1132                 callout_schedule(&sc->sc_ad_tmo, tvtohz(&tv));
 1133 }
 1134 
 1135 /*
 1136  * Broadcast a gratuitous ARP request containing
 1137  * the virtual router MAC address for each IP address
 1138  * associated with the virtual router.
 1139  */
 1140 void
 1141 carp_send_arp(struct carp_softc *sc)
 1142 {
 1143         struct ifaddr *ifa;
 1144         struct in_addr *in;
 1145         int s = splsoftnet();
 1146 
 1147         IFADDR_FOREACH(ifa, &sc->sc_if) {
 1148 
 1149                 if (ifa->ifa_addr->sa_family != AF_INET)
 1150                         continue;
 1151 
 1152                 in = &ifatoia(ifa)->ia_addr.sin_addr;
 1153                 arprequest(sc->sc_carpdev, in, in, CLLADDR(sc->sc_if.if_sadl));
 1154                 DELAY(1000);    /* XXX */
 1155         }
 1156         splx(s);
 1157 }
 1158 
 1159 #ifdef INET6
 1160 void
 1161 carp_send_na(struct carp_softc *sc)
 1162 {
 1163         struct ifaddr *ifa;
 1164         struct in6_addr *in6;
 1165         static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
 1166         int s = splsoftnet();
 1167 
 1168         IFADDR_FOREACH(ifa, &sc->sc_if) {
 1169 
 1170                 if (ifa->ifa_addr->sa_family != AF_INET6)
 1171                         continue;
 1172 
 1173                 in6 = &ifatoia6(ifa)->ia_addr.sin6_addr;
 1174                 nd6_na_output(sc->sc_carpdev, &mcast, in6,
 1175                     ND_NA_FLAG_OVERRIDE, 1, NULL);
 1176                 DELAY(1000);    /* XXX */
 1177         }
 1178         splx(s);
 1179 }
 1180 #endif /* INET6 */
 1181 
 1182 /*
 1183  * Based on bridge_hash() in if_bridge.c
 1184  */
 1185 #define mix(a,b,c) \
 1186         do {                                            \
 1187                 a -= b; a -= c; a ^= (c >> 13);         \
 1188                 b -= c; b -= a; b ^= (a << 8);          \
 1189                 c -= a; c -= b; c ^= (b >> 13);         \
 1190                 a -= b; a -= c; a ^= (c >> 12);         \
 1191                 b -= c; b -= a; b ^= (a << 16);         \
 1192                 c -= a; c -= b; c ^= (b >> 5);          \
 1193                 a -= b; a -= c; a ^= (c >> 3);          \
 1194                 b -= c; b -= a; b ^= (a << 10);         \
 1195                 c -= a; c -= b; c ^= (b >> 15);         \
 1196         } while (0)
 1197 
 1198 u_int32_t
 1199 carp_hash(struct carp_softc *sc, u_char *src)
 1200 {
 1201         u_int32_t a = 0x9e3779b9, b = sc->sc_hashkey[0], c = sc->sc_hashkey[1];
 1202 
 1203         c += sc->sc_key[3] << 24;
 1204         c += sc->sc_key[2] << 16;
 1205         c += sc->sc_key[1] << 8;
 1206         c += sc->sc_key[0];
 1207         b += src[5] << 8;
 1208         b += src[4];
 1209         a += src[3] << 24;
 1210         a += src[2] << 16;
 1211         a += src[1] << 8;
 1212         a += src[0];
 1213 
 1214         mix(a, b, c);
 1215         return (c);
 1216 }
 1217 
 1218 int
 1219 carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type)
 1220 {
 1221         struct carp_softc *vh;
 1222         struct ifaddr *ifa;
 1223         int count = 0;
 1224 
 1225         TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
 1226                 if ((type == CARP_COUNT_RUNNING &&
 1227                     (vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) ==
 1228                     (IFF_UP|IFF_RUNNING)) ||
 1229                     (type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) {
 1230                         IFADDR_FOREACH(ifa, &vh->sc_if) {
 1231                                 if (ifa->ifa_addr->sa_family == AF_INET &&
 1232                                     ia->ia_addr.sin_addr.s_addr ==
 1233                                     ifatoia(ifa)->ia_addr.sin_addr.s_addr)
 1234                                         count++;
 1235                         }
 1236                 }
 1237         }
 1238         return (count);
 1239 }
 1240 
 1241 int
 1242 carp_iamatch(struct in_ifaddr *ia, u_char *src,
 1243     u_int32_t *count, u_int32_t index)
 1244 {
 1245         struct carp_softc *sc = ia->ia_ifp->if_softc;
 1246 
 1247         if (carp_opts[CARPCTL_ARPBALANCE]) {
 1248                 /*
 1249                  * We use the source ip to decide which virtual host should
 1250                  * handle the request. If we're master of that virtual host,
 1251                  * then we respond, otherwise, just drop the arp packet on
 1252                  * the floor.
 1253                  */
 1254 
 1255                 /* Count the elegible carp interfaces with this address */
 1256                 if (*count == 0)
 1257                         *count = carp_addrcount(
 1258                             (struct carp_if *)ia->ia_ifp->if_carpdev->if_carp,
 1259                             ia, CARP_COUNT_RUNNING);
 1260 
 1261                 /* This should never happen, but... */
 1262                 if (*count == 0)
 1263                         return (0);
 1264 
 1265                 if (carp_hash(sc, src) % *count == index - 1 &&
 1266                     sc->sc_state == MASTER) {
 1267                         return (1);
 1268                 }
 1269         } else {
 1270                 if (sc->sc_state == MASTER)
 1271                         return (1);
 1272         }
 1273 
 1274         return (0);
 1275 }
 1276 
 1277 #ifdef INET6
 1278 struct ifaddr *
 1279 carp_iamatch6(void *v, struct in6_addr *taddr)
 1280 {
 1281         struct carp_if *cif = v;
 1282         struct carp_softc *vh;
 1283         struct ifaddr *ifa;
 1284 
 1285         TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
 1286                 IFADDR_FOREACH(ifa, &vh->sc_if) {
 1287                         if (IN6_ARE_ADDR_EQUAL(taddr,
 1288                             &ifatoia6(ifa)->ia_addr.sin6_addr) &&
 1289                             ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) ==
 1290                             (IFF_UP|IFF_RUNNING)) && vh->sc_state == MASTER)
 1291                                 return (ifa);
 1292                 }
 1293         }
 1294 
 1295         return (NULL);
 1296 }
 1297 #endif /* INET6 */
 1298 
 1299 struct ifnet *
 1300 carp_ourether(void *v, struct ether_header *eh, u_char iftype, int src)
 1301 {
 1302         struct carp_if *cif = (struct carp_if *)v;
 1303         struct carp_softc *vh;
 1304         u_int8_t *ena;
 1305 
 1306         if (src)
 1307                 ena = (u_int8_t *)&eh->ether_shost;
 1308         else
 1309                 ena = (u_int8_t *)&eh->ether_dhost;
 1310 
 1311         switch (iftype) {
 1312         case IFT_ETHER:
 1313         case IFT_FDDI:
 1314                 if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1)
 1315                         return (NULL);
 1316                 break;
 1317         case IFT_ISO88025:
 1318                 if (ena[0] != 3 || ena[1] || ena[4] || ena[5])
 1319                         return (NULL);
 1320                 break;
 1321         default:
 1322                 return (NULL);
 1323                 break;
 1324         }
 1325 
 1326         TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list)
 1327                 if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) ==
 1328                     (IFF_UP|IFF_RUNNING) && vh->sc_state == MASTER &&
 1329                     !bcmp(ena, CLLADDR(vh->sc_if.if_sadl),
 1330                     ETHER_ADDR_LEN)) {
 1331                         return (&vh->sc_if);
 1332                     }
 1333 
 1334         return (NULL);
 1335 }
 1336 
 1337 int
 1338 carp_input(struct mbuf *m, u_int8_t *shost, u_int8_t *dhost, u_int16_t etype)
 1339 {
 1340         struct ether_header eh;
 1341         struct carp_if *cif = (struct carp_if *)m->m_pkthdr.rcvif->if_carp;
 1342         struct ifnet *ifp;
 1343 
 1344         bcopy(shost, &eh.ether_shost, sizeof(eh.ether_shost));
 1345         bcopy(dhost, &eh.ether_dhost, sizeof(eh.ether_dhost));
 1346         eh.ether_type = etype;
 1347 
 1348         if (m->m_flags & (M_BCAST|M_MCAST)) {
 1349                 struct carp_softc *vh;
 1350                 struct mbuf *m0;
 1351 
 1352                 /*
 1353                  * XXX Should really check the list of multicast addresses
 1354                  * for each CARP interface _before_ copying.
 1355                  */
 1356                 TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
 1357                         m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
 1358                         if (m0 == NULL)
 1359                                 continue;
 1360                         m0->m_pkthdr.rcvif = &vh->sc_if;
 1361                         ether_input(&vh->sc_if, m0);
 1362                 }
 1363                 return (1);
 1364         }
 1365 
 1366         ifp = carp_ourether(cif, &eh, m->m_pkthdr.rcvif->if_type, 0);
 1367         if (ifp == NULL) {
 1368                 return (1);
 1369         }
 1370 
 1371         m->m_pkthdr.rcvif = ifp;
 1372 
 1373 #if NBPFILTER > 0
 1374         if (ifp->if_bpf)
 1375                 bpf_mtap(ifp->if_bpf, m);
 1376 #endif
 1377         ifp->if_ipackets++;
 1378         ether_input(ifp, m);
 1379         return (0);
 1380 }
 1381 
 1382 void
 1383 carp_master_down(void *v)
 1384 {
 1385         struct carp_softc *sc = v;
 1386 
 1387         switch (sc->sc_state) {
 1388         case INIT:
 1389                 printf("%s: master_down event in INIT state\n",
 1390                     sc->sc_if.if_xname);
 1391                 break;
 1392         case MASTER:
 1393                 break;
 1394         case BACKUP:
 1395                 CARP_LOG(sc, ("INIT -> MASTER (preempting)"));
 1396                 carp_set_state(sc, MASTER);
 1397                 carp_send_ad(sc);
 1398                 carp_send_arp(sc);
 1399 #ifdef INET6
 1400                 carp_send_na(sc);
 1401 #endif /* INET6 */
 1402                 carp_setrun(sc, 0);
 1403                 carp_setroute(sc, RTM_ADD);
 1404                 break;
 1405         }
 1406 }
 1407 
 1408 /*
 1409  * When in backup state, af indicates whether to reset the master down timer
 1410  * for v4 or v6. If it's set to zero, reset the ones which are already pending.
 1411  */
 1412 void
 1413 carp_setrun(struct carp_softc *sc, sa_family_t af)
 1414 {
 1415         struct timeval tv;
 1416 
 1417         if (sc->sc_carpdev == NULL) {
 1418                 sc->sc_if.if_flags &= ~IFF_RUNNING;
 1419                 carp_set_state(sc, INIT);
 1420                 return;
 1421         }
 1422 
 1423         if (sc->sc_if.if_flags & IFF_UP && sc->sc_vhid > 0 &&
 1424             (sc->sc_naddrs || sc->sc_naddrs6) && !sc->sc_suppress) {
 1425                 sc->sc_if.if_flags |= IFF_RUNNING;
 1426         } else {
 1427                 sc->sc_if.if_flags &= ~IFF_RUNNING;
 1428                 carp_setroute(sc, RTM_DELETE);
 1429                 return;
 1430         }
 1431 
 1432         switch (sc->sc_state) {
 1433         case INIT:
 1434                 carp_set_state(sc, BACKUP);
 1435                 carp_setroute(sc, RTM_DELETE);
 1436                 carp_setrun(sc, 0);
 1437                 break;
 1438         case BACKUP:
 1439                 callout_stop(&sc->sc_ad_tmo);
 1440                 tv.tv_sec = 3 * sc->sc_advbase;
 1441                 tv.tv_usec = sc->sc_advskew * 1000000 / 256;
 1442                 switch (af) {
 1443 #ifdef INET
 1444                 case AF_INET:
 1445                         callout_schedule(&sc->sc_md_tmo, tvtohz(&tv));
 1446                         break;
 1447 #endif /* INET */
 1448 #ifdef INET6
 1449                 case AF_INET6:
 1450                         callout_schedule(&sc->sc_md6_tmo, tvtohz(&tv));
 1451                         break;
 1452 #endif /* INET6 */
 1453                 default:
 1454                         if (sc->sc_naddrs)
 1455                                 callout_schedule(&sc->sc_md_tmo, tvtohz(&tv));
 1456                         if (sc->sc_naddrs6)
 1457                                 callout_schedule(&sc->sc_md6_tmo, tvtohz(&tv));
 1458                         break;
 1459                 }
 1460                 break;
 1461         case MASTER:
 1462                 tv.tv_sec = sc->sc_advbase;
 1463                 tv.tv_usec = sc->sc_advskew * 1000000 / 256;
 1464                 callout_schedule(&sc->sc_ad_tmo, tvtohz(&tv));
 1465                 break;
 1466         }
 1467 }
 1468 
 1469 void
 1470 carp_multicast_cleanup(struct carp_softc *sc)
 1471 {
 1472         struct ip_moptions *imo = &sc->sc_imo;
 1473 #ifdef INET6
 1474         struct ip6_moptions *im6o = &sc->sc_im6o;
 1475 #endif
 1476         u_int16_t n = imo->imo_num_memberships;
 1477 
 1478         /* Clean up our own multicast memberships */
 1479         while (n-- > 0) {
 1480                 if (imo->imo_membership[n] != NULL) {
 1481                         in_delmulti(imo->imo_membership[n]);
 1482                         imo->imo_membership[n] = NULL;
 1483                 }
 1484         }
 1485         imo->imo_num_memberships = 0;
 1486         imo->imo_multicast_ifp = NULL;
 1487 
 1488 #ifdef INET6
 1489         while (!LIST_EMPTY(&im6o->im6o_memberships)) {
 1490                 struct in6_multi_mship *imm =
 1491                     LIST_FIRST(&im6o->im6o_memberships);
 1492 
 1493                 LIST_REMOVE(imm, i6mm_chain);
 1494                 in6_leavegroup(imm);
 1495         }
 1496         im6o->im6o_multicast_ifp = NULL;
 1497 #endif
 1498 
 1499         /* And any other multicast memberships */
 1500         carp_ether_purgemulti(sc);
 1501 }
 1502 
 1503 int
 1504 carp_set_ifp(struct carp_softc *sc, struct ifnet *ifp)
 1505 {
 1506         struct carp_if *cif, *ncif = NULL;
 1507         struct carp_softc *vr, *after = NULL;
 1508         int myself = 0, error = 0;
 1509         int s;
 1510 
 1511         if (ifp == sc->sc_carpdev)
 1512                 return (0);
 1513 
 1514         if (ifp != NULL) {
 1515                 if ((ifp->if_flags & IFF_MULTICAST) == 0)
 1516                         return (EADDRNOTAVAIL);
 1517 
 1518                 if (ifp->if_type == IFT_CARP)
 1519                         return (EINVAL);
 1520 
 1521                 if (ifp->if_carp == NULL) {
 1522                         MALLOC(ncif, struct carp_if *, sizeof(*cif),
 1523                             M_IFADDR, M_NOWAIT);
 1524                         if (ncif == NULL)
 1525                                 return (ENOBUFS);
 1526                         if ((error = ifpromisc(ifp, 1))) {
 1527                                 FREE(ncif, M_IFADDR);
 1528                                 return (error);
 1529                         }
 1530 
 1531                         ncif->vhif_ifp = ifp;
 1532                         TAILQ_INIT(&ncif->vhif_vrs);
 1533                 } else {
 1534                         cif = (struct carp_if *)ifp->if_carp;
 1535                         TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list)
 1536                                 if (vr != sc && vr->sc_vhid == sc->sc_vhid)
 1537                                         return (EINVAL);
 1538                 }
 1539 
 1540                 /* detach from old interface */
 1541                 if (sc->sc_carpdev != NULL)
 1542                         carpdetach(sc);
 1543 
 1544                 /* join multicast groups */
 1545                 if (sc->sc_naddrs < 0 &&
 1546                     (error = carp_join_multicast(sc)) != 0) {
 1547                         if (ncif != NULL)
 1548                                 FREE(ncif, M_IFADDR);
 1549                         return (error);
 1550                 }
 1551 
 1552 #ifdef INET6
 1553                 if (sc->sc_naddrs6 < 0 &&
 1554                     (error = carp_join_multicast6(sc)) != 0) {
 1555                         if (ncif != NULL)
 1556                                 FREE(ncif, M_IFADDR);
 1557                         carp_multicast_cleanup(sc);
 1558                         return (error);
 1559                 }
 1560 #endif
 1561 
 1562                 /* attach carp interface to physical interface */
 1563                 if (ncif != NULL)
 1564                         ifp->if_carp = (void *)ncif;
 1565                 sc->sc_carpdev = ifp;
 1566                 cif = (struct carp_if *)ifp->if_carp;
 1567                 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) {
 1568                         if (vr == sc)
 1569                                 myself = 1;
 1570                         if (vr->sc_vhid < sc->sc_vhid)
 1571                                 after = vr;
 1572                 }
 1573 
 1574                 if (!myself) {
 1575                         /* We're trying to keep things in order */
 1576                         if (after == NULL) {
 1577                                 TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list);
 1578                         } else {
 1579                                 TAILQ_INSERT_AFTER(&cif->vhif_vrs, after,
 1580                                     sc, sc_list);
 1581                         }
 1582                         cif->vhif_nvrs++;
 1583                 }
 1584                 if (sc->sc_naddrs || sc->sc_naddrs6)
 1585                         sc->sc_if.if_flags |= IFF_UP;
 1586                 carp_set_enaddr(sc);
 1587                 s = splnet();
 1588                 /* XXX linkstatehooks establish */
 1589                 carp_carpdev_state(ifp);
 1590                 splx(s);
 1591         } else {
 1592                 carpdetach(sc);
 1593                 sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
 1594         }
 1595         return (0);
 1596 }
 1597 
 1598 void
 1599 carp_set_enaddr(struct carp_softc *sc)
 1600 {
 1601         uint8_t enaddr[ETHER_ADDR_LEN];
 1602         if (sc->sc_carpdev && sc->sc_carpdev->if_type == IFT_ISO88025) {
 1603                 enaddr[0] = 3;
 1604                 enaddr[1] = 0;
 1605                 enaddr[2] = 0x40 >> (sc->sc_vhid - 1);
 1606                 enaddr[3] = 0x40000 >> (sc->sc_vhid - 1);
 1607                 enaddr[4] = 0;
 1608                 enaddr[5] = 0;
 1609         } else {
 1610                 enaddr[0] = 0;
 1611                 enaddr[1] = 0;
 1612                 enaddr[2] = 0x5e;
 1613                 enaddr[3] = 0;
 1614                 enaddr[4] = 1;
 1615                 enaddr[5] = sc->sc_vhid;
 1616         }
 1617         if_set_sadl(&sc->sc_if, enaddr, sizeof(enaddr));
 1618 }
 1619 
 1620 void
 1621 carp_addr_updated(void *v)
 1622 {
 1623         struct carp_softc *sc = (struct carp_softc *) v;
 1624         struct ifaddr *ifa;
 1625         int new_naddrs = 0, new_naddrs6 = 0;
 1626 
 1627         IFADDR_FOREACH(ifa, &sc->sc_if) {
 1628                 if (ifa->ifa_addr->sa_family == AF_INET)
 1629                         new_naddrs++;
 1630                 else if (ifa->ifa_addr->sa_family == AF_INET6)
 1631                         new_naddrs6++;
 1632         }
 1633 
 1634         /* Handle a callback after SIOCDIFADDR */
 1635         if (new_naddrs < sc->sc_naddrs || new_naddrs6 < sc->sc_naddrs6) {
 1636                 struct in_addr mc_addr;
 1637                 struct in_multi *inm;
 1638 
 1639                 sc->sc_naddrs = new_naddrs;
 1640                 sc->sc_naddrs6 = new_naddrs6;
 1641 
 1642                 /* Re-establish multicast membership removed by in_control */
 1643                 mc_addr.s_addr = INADDR_CARP_GROUP;
 1644                 IN_LOOKUP_MULTI(mc_addr, &sc->sc_if, inm);
 1645                 if (inm == NULL) {
 1646                         bzero(&sc->sc_imo, sizeof(sc->sc_imo));
 1647 
 1648                         if (sc->sc_carpdev != NULL && sc->sc_naddrs > 0)
 1649                                 carp_join_multicast(sc);
 1650                 }
 1651 
 1652                 if (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) {
 1653                         sc->sc_if.if_flags &= ~IFF_UP;
 1654                         carp_set_state(sc, INIT);
 1655                 } else
 1656                         carp_hmac_prepare(sc);
 1657         }
 1658 
 1659         carp_setrun(sc, 0);
 1660 }
 1661 
 1662 int
 1663 carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
 1664 {
 1665         struct ifnet *ifp = sc->sc_carpdev;
 1666         struct in_ifaddr *ia, *ia_if;
 1667         int error = 0;
 1668 
 1669         if (sin->sin_addr.s_addr == 0) {
 1670                 if (!(sc->sc_if.if_flags & IFF_UP))
 1671                         carp_set_state(sc, INIT);
 1672                 if (sc->sc_naddrs)
 1673                         sc->sc_if.if_flags |= IFF_UP;
 1674                 carp_setrun(sc, 0);
 1675                 return (0);
 1676         }
 1677 
 1678         /* we have to do this by hand to ensure we don't match on ourselves */
 1679         ia_if = NULL;
 1680         for (ia = TAILQ_FIRST(&in_ifaddrhead); ia;
 1681             ia = TAILQ_NEXT(ia, ia_list)) {
 1682 
 1683                 /* and, yeah, we need a multicast-capable iface too */
 1684                 if (ia->ia_ifp != &sc->sc_if &&
 1685                     ia->ia_ifp->if_type != IFT_CARP &&
 1686                     (ia->ia_ifp->if_flags & IFF_MULTICAST) &&
 1687                     (sin->sin_addr.s_addr & ia->ia_subnetmask) ==
 1688                     ia->ia_subnet) {
 1689                         if (!ia_if)
 1690                                 ia_if = ia;
 1691                 }
 1692         }
 1693 
 1694         if (ia_if) {
 1695                 ia = ia_if;
 1696                 if (ifp) {
 1697                         if (ifp != ia->ia_ifp)
 1698                                 return (EADDRNOTAVAIL);
 1699                 } else {
 1700                         ifp = ia->ia_ifp;
 1701                 }
 1702         }
 1703 
 1704         if ((error = carp_set_ifp(sc, ifp)))
 1705                 return (error);
 1706 
 1707         if (sc->sc_carpdev == NULL)
 1708                 return (EADDRNOTAVAIL);
 1709 
 1710         if (sc->sc_naddrs == 0 && (error = carp_join_multicast(sc)) != 0)
 1711                 return (error);
 1712 
 1713         sc->sc_naddrs++;
 1714         if (sc->sc_carpdev != NULL)
 1715                 sc->sc_if.if_flags |= IFF_UP;
 1716 
 1717         carp_set_state(sc, INIT);
 1718         carp_setrun(sc, 0);
 1719 
 1720         /*
 1721          * Hook if_addrhooks so that we get a callback after in_ifinit has run,
 1722          * to correct any inappropriate routes that it inserted.
 1723          */
 1724         if (sc->ah_cookie == 0) {
 1725                 /* XXX link address hook */
 1726         }
 1727 
 1728         return (0);
 1729 }
 1730 
 1731 int
 1732 carp_join_multicast(struct carp_softc *sc)
 1733 {
 1734         struct ip_moptions *imo = &sc->sc_imo, tmpimo;
 1735         struct in_addr addr;
 1736 
 1737         bzero(&tmpimo, sizeof(tmpimo));
 1738         addr.s_addr = INADDR_CARP_GROUP;
 1739         if ((tmpimo.imo_membership[0] =
 1740             in_addmulti(&addr, &sc->sc_if)) == NULL) {
 1741                 return (ENOBUFS);
 1742         }
 1743 
 1744         imo->imo_membership[0] = tmpimo.imo_membership[0];
 1745         imo->imo_num_memberships = 1;
 1746         imo->imo_multicast_ifp = &sc->sc_if;
 1747         imo->imo_multicast_ttl = CARP_DFLTTL;
 1748         imo->imo_multicast_loop = 0;
 1749         return (0);
 1750 }
 1751 
 1752 
 1753 #ifdef INET6
 1754 int
 1755 carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
 1756 {
 1757         struct ifnet *ifp = sc->sc_carpdev;
 1758         struct in6_ifaddr *ia, *ia_if;
 1759         int error = 0;
 1760 
 1761         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 1762                 if (!(sc->sc_if.if_flags & IFF_UP))
 1763                         carp_set_state(sc, INIT);
 1764                 if (sc->sc_naddrs6)
 1765                         sc->sc_if.if_flags |= IFF_UP;
 1766                 carp_setrun(sc, 0);
 1767                 return (0);
 1768         }
 1769 
 1770         /* we have to do this by hand to ensure we don't match on ourselves */
 1771         ia_if = NULL;
 1772         for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
 1773                 int i;
 1774 
 1775                 for (i = 0; i < 4; i++) {
 1776                         if ((sin6->sin6_addr.s6_addr32[i] &
 1777                             ia->ia_prefixmask.sin6_addr.s6_addr32[i]) !=
 1778                             (ia->ia_addr.sin6_addr.s6_addr32[i] &
 1779                             ia->ia_prefixmask.sin6_addr.s6_addr32[i]))
 1780                                 break;
 1781                 }
 1782                 /* and, yeah, we need a multicast-capable iface too */
 1783                 if (ia->ia_ifp != &sc->sc_if &&
 1784                     ia->ia_ifp->if_type != IFT_CARP &&
 1785                     (ia->ia_ifp->if_flags & IFF_MULTICAST) &&
 1786                     (i == 4)) {
 1787                         if (!ia_if)
 1788                                 ia_if = ia;
 1789                 }
 1790         }
 1791 
 1792         if (ia_if) {
 1793                 ia = ia_if;
 1794                 if (sc->sc_carpdev) {
 1795                         if (sc->sc_carpdev != ia->ia_ifp)
 1796                                 return (EADDRNOTAVAIL);
 1797                 } else {
 1798                         ifp = ia->ia_ifp;
 1799                 }
 1800         }
 1801 
 1802         if ((error = carp_set_ifp(sc, ifp)))
 1803                 return (error);
 1804 
 1805         if (sc->sc_carpdev == NULL)
 1806                 return (EADDRNOTAVAIL);
 1807 
 1808         if (sc->sc_naddrs6 == 0 && (error = carp_join_multicast6(sc)) != 0)
 1809                 return (error);
 1810 
 1811         sc->sc_naddrs6++;
 1812         if (sc->sc_carpdev != NULL)
 1813                 sc->sc_if.if_flags |= IFF_UP;
 1814         carp_set_state(sc, INIT);
 1815         carp_setrun(sc, 0);
 1816 
 1817         return (0);
 1818 }
 1819 
 1820 int
 1821 carp_join_multicast6(struct carp_softc *sc)
 1822 {
 1823         struct in6_multi_mship *imm, *imm2;
 1824         struct ip6_moptions *im6o = &sc->sc_im6o;
 1825         struct sockaddr_in6 addr6;
 1826         int error;
 1827 
 1828         /* Join IPv6 CARP multicast group */
 1829         bzero(&addr6, sizeof(addr6));
 1830         addr6.sin6_family = AF_INET6;
 1831         addr6.sin6_len = sizeof(addr6);
 1832         addr6.sin6_addr.s6_addr16[0] = htons(0xff02);
 1833         addr6.sin6_addr.s6_addr16[1] = htons(sc->sc_if.if_index);
 1834         addr6.sin6_addr.s6_addr8[15] = 0x12;
 1835         if ((imm = in6_joingroup(&sc->sc_if,
 1836             &addr6.sin6_addr, &error, 0)) == NULL) {
 1837                 return (error);
 1838         }
 1839         /* join solicited multicast address */
 1840         bzero(&addr6.sin6_addr, sizeof(addr6.sin6_addr));
 1841         addr6.sin6_addr.s6_addr16[0] = htons(0xff02);
 1842         addr6.sin6_addr.s6_addr16[1] = htons(sc->sc_if.if_index);
 1843         addr6.sin6_addr.s6_addr32[1] = 0;
 1844         addr6.sin6_addr.s6_addr32[2] = htonl(1);
 1845         addr6.sin6_addr.s6_addr32[3] = 0;
 1846         addr6.sin6_addr.s6_addr8[12] = 0xff;
 1847         if ((imm2 = in6_joingroup(&sc->sc_if,
 1848             &addr6.sin6_addr, &error, 0)) == NULL) {
 1849                 in6_leavegroup(imm);
 1850                 return (error);
 1851         }
 1852 
 1853         /* apply v6 multicast membership */
 1854         im6o->im6o_multicast_ifp = &sc->sc_if;
 1855         if (imm)
 1856                 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm,
 1857                     i6mm_chain);
 1858         if (imm2)
 1859                 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm2,
 1860                     i6mm_chain);
 1861 
 1862         return (0);
 1863 }
 1864 
 1865 #endif /* INET6 */
 1866 
 1867 int
 1868 carp_ioctl(struct ifnet *ifp, u_long cmd, void *addr)
 1869 {
 1870         struct lwp *l = curlwp;         /* XXX */
 1871         struct carp_softc *sc = ifp->if_softc, *vr;
 1872         struct carpreq carpr;
 1873         struct ifaddr *ifa;
 1874         struct ifreq *ifr;
 1875         struct ifnet *cdev = NULL;
 1876         int error = 0;
 1877 
 1878         ifa = (struct ifaddr *)addr;
 1879         ifr = (struct ifreq *)addr;
 1880 
 1881         switch (cmd) {
 1882         case SIOCSIFADDR:
 1883                 switch (ifa->ifa_addr->sa_family) {
 1884 #ifdef INET
 1885                 case AF_INET:
 1886                         sc->sc_if.if_flags |= IFF_UP;
 1887                         bcopy(ifa->ifa_addr, ifa->ifa_dstaddr,
 1888                             sizeof(struct sockaddr));
 1889                         error = carp_set_addr(sc, satosin(ifa->ifa_addr));
 1890                         break;
 1891 #endif /* INET */
 1892 #ifdef INET6
 1893                 case AF_INET6:
 1894                         sc->sc_if.if_flags|= IFF_UP;
 1895                         error = carp_set_addr6(sc, satosin6(ifa->ifa_addr));
 1896                         break;
 1897 #endif /* INET6 */
 1898                 default:
 1899                         error = EAFNOSUPPORT;
 1900                         break;
 1901                 }
 1902                 break;
 1903 
 1904         case SIOCSIFFLAGS:
 1905                 if (sc->sc_state != INIT && !(ifr->ifr_flags & IFF_UP)) {
 1906                         callout_stop(&sc->sc_ad_tmo);
 1907                         callout_stop(&sc->sc_md_tmo);
 1908                         callout_stop(&sc->sc_md6_tmo);
 1909                         if (sc->sc_state == MASTER) {
 1910                                 /* we need the interface up to bow out */
 1911                                 sc->sc_if.if_flags |= IFF_UP;
 1912                                 sc->sc_bow_out = 1;
 1913                                 carp_send_ad(sc);
 1914                         }
 1915                         sc->sc_if.if_flags &= ~IFF_UP;
 1916                         carp_set_state(sc, INIT);
 1917                         carp_setrun(sc, 0);
 1918                 } else if (sc->sc_state == INIT && (ifr->ifr_flags & IFF_UP)) {
 1919                         sc->sc_if.if_flags |= IFF_UP;
 1920                         carp_setrun(sc, 0);
 1921                 }
 1922                 break;
 1923 
 1924         case SIOCSVH:
 1925                 if (l == NULL)
 1926                         break;
 1927                 if ((error = kauth_authorize_network(l->l_cred,
 1928                     KAUTH_NETWORK_INTERFACE,
 1929                     KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
 1930                     NULL)) != 0)
 1931                         break;
 1932                 if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr)))
 1933                         break;
 1934                 error = 1;
 1935                 if (carpr.carpr_carpdev[0] != '\0' &&
 1936                     (cdev = ifunit(carpr.carpr_carpdev)) == NULL)
 1937                         return (EINVAL);
 1938                 if ((error = carp_set_ifp(sc, cdev)))
 1939                         return (error);
 1940                 if (sc->sc_state != INIT && carpr.carpr_state != sc->sc_state) {
 1941                         switch (carpr.carpr_state) {
 1942                         case BACKUP:
 1943                                 callout_stop(&sc->sc_ad_tmo);
 1944                                 carp_set_state(sc, BACKUP);
 1945                                 carp_setrun(sc, 0);
 1946                                 carp_setroute(sc, RTM_DELETE);
 1947                                 break;
 1948                         case MASTER:
 1949                                 carp_master_down(sc);
 1950                                 break;
 1951                         default:
 1952                                 break;
 1953                         }
 1954                 }
 1955                 if (carpr.carpr_vhid > 0) {
 1956                         if (carpr.carpr_vhid > 255) {
 1957                                 error = EINVAL;
 1958                                 break;
 1959                         }
 1960                         if (sc->sc_carpdev) {
 1961                                 struct carp_if *cif;
 1962                                 cif = (struct carp_if *)sc->sc_carpdev->if_carp;
 1963                                 TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list)
 1964                                         if (vr != sc &&
 1965                                             vr->sc_vhid == carpr.carpr_vhid)
 1966                                                 return (EINVAL);
 1967                         }
 1968                         sc->sc_vhid = carpr.carpr_vhid;
 1969                         carp_set_enaddr(sc);
 1970                         carp_set_state(sc, INIT);
 1971                         error--;
 1972                 }
 1973                 if (carpr.carpr_advbase > 0 || carpr.carpr_advskew > 0) {
 1974                         if (carpr.carpr_advskew > 254) {
 1975                                 error = EINVAL;
 1976                                 break;
 1977                         }
 1978                         if (carpr.carpr_advbase > 255) {
 1979                                 error = EINVAL;
 1980                                 break;
 1981                         }
 1982                         sc->sc_advbase = carpr.carpr_advbase;
 1983                         sc->sc_advskew = carpr.carpr_advskew;
 1984                         error--;
 1985                 }
 1986                 bcopy(carpr.carpr_key, sc->sc_key, sizeof(sc->sc_key));
 1987                 if (error > 0)
 1988                         error = EINVAL;
 1989                 else {
 1990                         error = 0;
 1991                         carp_setrun(sc, 0);
 1992                 }
 1993                 break;
 1994 
 1995         case SIOCGVH:
 1996                 bzero(&carpr, sizeof(carpr));
 1997                 if (sc->sc_carpdev != NULL)
 1998                         strlcpy(carpr.carpr_carpdev, sc->sc_carpdev->if_xname,
 1999                             IFNAMSIZ);
 2000                 carpr.carpr_state = sc->sc_state;
 2001                 carpr.carpr_vhid = sc->sc_vhid;
 2002                 carpr.carpr_advbase = sc->sc_advbase;
 2003                 carpr.carpr_advskew = sc->sc_advskew;
 2004 
 2005                 if ((l == NULL) || (error = kauth_authorize_network(l->l_cred,
 2006                     KAUTH_NETWORK_INTERFACE,
 2007                     KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
 2008                     NULL)) != 0)
 2009                         bcopy(sc->sc_key, carpr.carpr_key,
 2010                             sizeof(carpr.carpr_key));
 2011                 error = copyout(&carpr, ifr->ifr_data, sizeof(carpr));
 2012                 break;
 2013 
 2014         case SIOCADDMULTI:
 2015                 error = carp_ether_addmulti(sc, ifr);
 2016                 break;
 2017 
 2018         case SIOCDELMULTI:
 2019                 error = carp_ether_delmulti(sc, ifr);
 2020                 break;
 2021 
 2022         default:
 2023                 error = EINVAL;
 2024         }
 2025 
 2026         carp_hmac_prepare(sc);
 2027         return (error);
 2028 }
 2029 
 2030 
 2031 /*
 2032  * Start output on carp interface. This function should never be called.
 2033  */
 2034 void
 2035 carp_start(struct ifnet *ifp)
 2036 {
 2037 #ifdef DEBUG
 2038         printf("%s: start called\n", ifp->if_xname);
 2039 #endif
 2040 }
 2041 
 2042 int
 2043 carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa,
 2044     struct rtentry *rt)
 2045 {
 2046         struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc);
 2047 
 2048         if (sc->sc_carpdev != NULL && sc->sc_state == MASTER) {
 2049                 return (sc->sc_carpdev->if_output(ifp, m, sa, rt));
 2050         } else {
 2051                 m_freem(m);
 2052                 return (ENETUNREACH);
 2053         }
 2054 }
 2055 
 2056 void
 2057 carp_set_state(struct carp_softc *sc, int state)
 2058 {
 2059         static const char *carp_states[] = { CARP_STATES };
 2060         if (sc->sc_state == state)
 2061                 return;
 2062 
 2063         CARP_LOG(sc, ("state transition from: %s -> to: %s", carp_states[sc->sc_state], carp_states[state]));
 2064 
 2065         sc->sc_state = state;
 2066         switch (state) {
 2067         case BACKUP:
 2068                 sc->sc_if.if_link_state = LINK_STATE_DOWN;
 2069                 break;
 2070         case MASTER:
 2071                 sc->sc_if.if_link_state = LINK_STATE_UP;
 2072                 break;
 2073         default:
 2074                 sc->sc_if.if_link_state = LINK_STATE_UNKNOWN;
 2075                 break;
 2076         }
 2077         rt_ifmsg(&sc->sc_if);
 2078 }
 2079 
 2080 void
 2081 carp_carpdev_state(void *v)
 2082 {
 2083         struct carp_if *cif;
 2084         struct carp_softc *sc;
 2085         struct ifnet *ifp = v;
 2086 
 2087         if (ifp->if_type == IFT_CARP)
 2088                 return;
 2089 
 2090         cif = (struct carp_if *)ifp->if_carp;
 2091 
 2092         TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) {
 2093                 int suppressed = sc->sc_suppress;
 2094 
 2095                 if (sc->sc_carpdev->if_link_state == LINK_STATE_DOWN ||
 2096                     !(sc->sc_carpdev->if_flags & IFF_UP)) {
 2097                         sc->sc_if.if_flags &= ~IFF_RUNNING;
 2098                         callout_stop(&sc->sc_ad_tmo);
 2099                         callout_stop(&sc->sc_md_tmo);
 2100                         callout_stop(&sc->sc_md6_tmo);
 2101                         carp_set_state(sc, INIT);
 2102                         sc->sc_suppress = 1;
 2103                         carp_setrun(sc, 0);
 2104                         if (!suppressed) {
 2105                                 carp_suppress_preempt++;
 2106                                 if (carp_suppress_preempt == 1)
 2107                                         carp_send_ad_all();
 2108                         }
 2109                 } else {
 2110                         carp_set_state(sc, INIT);
 2111                         sc->sc_suppress = 0;
 2112                         carp_setrun(sc, 0);
 2113                         if (suppressed)
 2114                                 carp_suppress_preempt--;
 2115                 }
 2116         }
 2117 }
 2118 
 2119 int
 2120 carp_ether_addmulti(struct carp_softc *sc, struct ifreq *ifr)
 2121 {
 2122         const struct sockaddr *sa = ifreq_getaddr(SIOCADDMULTI, ifr);
 2123         struct ifnet *ifp;
 2124         struct carp_mc_entry *mc;
 2125         u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
 2126         int error;
 2127 
 2128         ifp = sc->sc_carpdev;
 2129         if (ifp == NULL)
 2130                 return (EINVAL);
 2131 
 2132         error = ether_addmulti(sa, &sc->sc_ac);
 2133         if (error != ENETRESET)
 2134                 return (error);
 2135 
 2136         /*
 2137          * This is new multicast address.  We have to tell parent
 2138          * about it.  Also, remember this multicast address so that
 2139          * we can delete them on unconfigure.
 2140          */
 2141         MALLOC(mc, struct carp_mc_entry *, sizeof(struct carp_mc_entry),
 2142             M_DEVBUF, M_NOWAIT);
 2143         if (mc == NULL) {
 2144                 error = ENOMEM;
 2145                 goto alloc_failed;
 2146         }
 2147 
 2148         /*
 2149          * As ether_addmulti() returns ENETRESET, following two
 2150          * statement shouldn't fail.
 2151          */
 2152         (void)ether_multiaddr(sa, addrlo, addrhi);
 2153         ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, mc->mc_enm);
 2154         memcpy(&mc->mc_addr, sa, sa->sa_len);
 2155         LIST_INSERT_HEAD(&sc->carp_mc_listhead, mc, mc_entries);
 2156 
 2157         error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (void *)ifr);
 2158         if (error != 0)
 2159                 goto ioctl_failed;
 2160 
 2161         return (error);
 2162 
 2163  ioctl_failed:
 2164         LIST_REMOVE(mc, mc_entries);
 2165         FREE(mc, M_DEVBUF);
 2166  alloc_failed:
 2167         (void)ether_delmulti(sa, &sc->sc_ac);
 2168 
 2169         return (error);
 2170 }
 2171 
 2172 int
 2173 carp_ether_delmulti(struct carp_softc *sc, struct ifreq *ifr)
 2174 {
 2175         const struct sockaddr *sa = ifreq_getaddr(SIOCDELMULTI, ifr);
 2176         struct ifnet *ifp;
 2177         struct ether_multi *enm;
 2178         struct carp_mc_entry *mc;
 2179         u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
 2180         int error;
 2181 
 2182         ifp = sc->sc_carpdev;
 2183         if (ifp == NULL)
 2184                 return (EINVAL);
 2185 
 2186         /*
 2187          * Find a key to lookup carp_mc_entry.  We have to do this
 2188          * before calling ether_delmulti for obvious reason.
 2189          */
 2190         if ((error = ether_multiaddr(sa, addrlo, addrhi)) != 0)
 2191                 return (error);
 2192         ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, enm);
 2193         if (enm == NULL)
 2194                 return (EINVAL);
 2195 
 2196         LIST_FOREACH(mc, &sc->carp_mc_listhead, mc_entries)
 2197                 if (mc->mc_enm == enm)
 2198                         break;
 2199 
 2200         /* We won't delete entries we didn't add */
 2201         if (mc == NULL)
 2202                 return (EINVAL);
 2203 
 2204         error = ether_delmulti(sa, &sc->sc_ac);
 2205         if (error != ENETRESET)
 2206                 return (error);
 2207 
 2208         /* We no longer use this multicast address.  Tell parent so. */
 2209         error = (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (void *)ifr);
 2210         if (error == 0) {
 2211                 /* And forget about this address. */
 2212                 LIST_REMOVE(mc, mc_entries);
 2213                 FREE(mc, M_DEVBUF);
 2214         } else
 2215                 (void)ether_addmulti(sa, &sc->sc_ac);
 2216         return (error);
 2217 }
 2218 
 2219 /*
 2220  * Delete any multicast address we have asked to add from parent
 2221  * interface.  Called when the carp is being unconfigured.
 2222  */
 2223 void
 2224 carp_ether_purgemulti(struct carp_softc *sc)
 2225 {
 2226         struct ifnet *ifp = sc->sc_carpdev;             /* Parent. */
 2227         struct carp_mc_entry *mc;
 2228         union {
 2229                 struct ifreq ifreq;
 2230                 struct {
 2231                         char ifr_name[IFNAMSIZ];
 2232                         struct sockaddr_storage ifr_ss;
 2233                 } ifreq_storage;
 2234         } u;
 2235         struct ifreq *ifr = &u.ifreq;
 2236 
 2237         if (ifp == NULL)
 2238                 return;
 2239 
 2240         memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
 2241         while ((mc = LIST_FIRST(&sc->carp_mc_listhead)) != NULL) {
 2242                 memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
 2243                 (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (void *)ifr);
 2244                 LIST_REMOVE(mc, mc_entries);
 2245                 FREE(mc, M_DEVBUF);
 2246         }
 2247 }
 2248 
 2249 static int
 2250 sysctl_net_inet_carp_stats(SYSCTLFN_ARGS)
 2251 {
 2252 
 2253         return (NETSTAT_SYSCTL(carpstat_percpu, CARP_NSTATS));
 2254 }
 2255 
 2256 SYSCTL_SETUP(sysctl_net_inet_carp_setup, "sysctl net.inet.carp subtree setup")
 2257 {
 2258 
 2259         sysctl_createv(clog, 0, NULL, NULL,
 2260                        CTLFLAG_PERMANENT,
 2261                        CTLTYPE_NODE, "net", NULL,
 2262                        NULL, 0, NULL, 0,
 2263                        CTL_NET, CTL_EOL);
 2264         sysctl_createv(clog, 0, NULL, NULL,
 2265                        CTLFLAG_PERMANENT,
 2266                        CTLTYPE_NODE, "inet", NULL,
 2267                        NULL, 0, NULL, 0,
 2268                        CTL_NET, PF_INET, CTL_EOL);
 2269         sysctl_createv(clog, 0, NULL, NULL,
 2270                        CTLFLAG_PERMANENT,
 2271                        CTLTYPE_NODE, "carp",
 2272                        SYSCTL_DESCR("CARP related settings"),
 2273                        NULL, 0, NULL, 0,
 2274                        CTL_NET, PF_INET, IPPROTO_CARP, CTL_EOL);
 2275 
 2276         sysctl_createv(clog, 0, NULL, NULL,
 2277                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 2278                        CTLTYPE_INT, "preempt",
 2279                        SYSCTL_DESCR("Enable CARP Preempt"),
 2280                        NULL, 0, &carp_opts[CARPCTL_PREEMPT], 0,
 2281                        CTL_NET, PF_INET, IPPROTO_CARP,
 2282                        CTL_CREATE, CTL_EOL);
 2283         sysctl_createv(clog, 0, NULL, NULL,
 2284                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 2285                        CTLTYPE_INT, "arpbalance",
 2286                        SYSCTL_DESCR("Enable ARP balancing"),
 2287                        NULL, 0, &carp_opts[CARPCTL_ARPBALANCE], 0,
 2288                        CTL_NET, PF_INET, IPPROTO_CARP,
 2289                        CTL_CREATE, CTL_EOL);
 2290         sysctl_createv(clog, 0, NULL, NULL,
 2291                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 2292                        CTLTYPE_INT, "allow",
 2293                        SYSCTL_DESCR("Enable CARP"),
 2294                        NULL, 0, &carp_opts[CARPCTL_ALLOW], 0,
 2295                        CTL_NET, PF_INET, IPPROTO_CARP,
 2296                        CTL_CREATE, CTL_EOL);
 2297         sysctl_createv(clog, 0, NULL, NULL,
 2298                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 2299                        CTLTYPE_INT, "log",
 2300                        SYSCTL_DESCR("CARP logging"),
 2301                        NULL, 0, &carp_opts[CARPCTL_LOG], 0,
 2302                        CTL_NET, PF_INET, IPPROTO_CARP,
 2303                        CTL_CREATE, CTL_EOL);
 2304         sysctl_createv(clog, 0, NULL, NULL,
 2305                        CTLFLAG_PERMANENT,
 2306                        CTLTYPE_STRUCT, "stats",
 2307                        SYSCTL_DESCR("CARP statistics"),
 2308                        sysctl_net_inet_carp_stats, 0, NULL, 0,
 2309                        CTL_NET, PF_INET, IPPROTO_CARP, CARPCTL_STATS,
 2310                        CTL_EOL);
 2311 }

Cache object: d41968aaff4150ae5645a0949a3f14f8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.