root/netinet/ip_carp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. carp_hmac_prepare
  2. carp_hmac_prepare_ctx
  3. carp_hmac_generate
  4. carp_hmac_verify
  5. carp_setroute
  6. carp_proto_input
  7. carp6_proto_input
  8. carp_proto_input_c
  9. carp_sysctl
  10. carpattach
  11. carp_clone_create
  12. carp_clone_destroy
  13. carpdetach
  14. carp_ifdetach
  15. carp_prepare_ad
  16. carp_send_ad_all
  17. carp_send_ad
  18. carp_send_arp
  19. carp_send_na
  20. carp_hash
  21. carp_addrcount
  22. carp_update_lsmask
  23. carp_iamatch
  24. carp_iamatch6
  25. carp_ourether
  26. carp_input
  27. carp_lsdrop
  28. carp_master_down
  29. carp_setrun
  30. carp_multicast_cleanup
  31. carp_set_ifp
  32. carp_set_enaddr
  33. carp_addr_updated
  34. carp_set_addr
  35. carp_join_multicast
  36. carp_set_addr6
  37. carp_join_multicast6
  38. carp_ioctl
  39. carp_ifgroup_ioctl
  40. carp_ifgattr_ioctl
  41. carp_start
  42. carp_output
  43. carp_set_state
  44. carp_group_demote_adj
  45. carp_group_demote_count
  46. carp_carpdev_state
  47. carp_ether_addmulti
  48. carp_ether_delmulti
  49. carp_ether_purgemulti

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

/* [<][>][^][v][top][bottom][index][help] */