[BACK]Return to ip_carp.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/ip_carp.c, Revision 1.1.1.1

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

CVSweb