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


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

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

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

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

Cache object: 6f029c06c6b53d0d8428b1a047962d38


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


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