[BACK]Return to in6_ifattach.c CVS log [TXT][DIR] Up to [local] / sys / netinet6

Annotation of sys/netinet6/in6_ifattach.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: in6_ifattach.c,v 1.45 2007/06/08 09:31:38 henning Exp $       */
                      2: /*     $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $  */
                      3:
                      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the project nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <sys/param.h>
                     34: #include <sys/systm.h>
                     35: #include <sys/malloc.h>
                     36: #include <sys/socket.h>
                     37: #include <sys/sockio.h>
                     38: #include <sys/kernel.h>
                     39: #include <sys/syslog.h>
                     40:
                     41: #include <crypto/md5.h>
                     42:
                     43: #include <net/if.h>
                     44: #include <net/if_dl.h>
                     45: #include <net/if_types.h>
                     46: #include <net/route.h>
                     47:
                     48: #include <netinet/in.h>
                     49: #include <netinet/in_var.h>
                     50: #include <netinet/if_ether.h>
                     51:
                     52: #include <netinet/ip6.h>
                     53: #include <netinet6/ip6_var.h>
                     54: #include <netinet6/in6_ifattach.h>
                     55: #include <netinet6/ip6_var.h>
                     56: #include <netinet6/nd6.h>
                     57: #ifdef MROUTING
                     58: #include <netinet6/ip6_mroute.h>
                     59: #endif
                     60:
                     61: unsigned long in6_maxmtu = 0;
                     62:
                     63: int ip6_auto_linklocal = 1;    /* enable by default */
                     64:
                     65: static int get_rand_ifid(struct ifnet *, struct in6_addr *);
                     66: static int get_hw_ifid(struct ifnet *, struct in6_addr *);
                     67: static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
                     68: static int in6_ifattach_loopback(struct ifnet *);
                     69:
                     70: #define EUI64_GBIT     0x01
                     71: #define EUI64_UBIT     0x02
                     72: #define EUI64_TO_IFID(in6)     do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
                     73: #define EUI64_GROUP(in6)       ((in6)->s6_addr[8] & EUI64_GBIT)
                     74: #define EUI64_INDIVIDUAL(in6)  (!EUI64_GROUP(in6))
                     75: #define EUI64_LOCAL(in6)       ((in6)->s6_addr[8] & EUI64_UBIT)
                     76: #define EUI64_UNIVERSAL(in6)   (!EUI64_LOCAL(in6))
                     77:
                     78: #define IFID_LOCAL(in6)                (!EUI64_LOCAL(in6))
                     79: #define IFID_UNIVERSAL(in6)    (!EUI64_UNIVERSAL(in6))
                     80:
                     81: /*
                     82:  * Generate a last-resort interface identifier, when the machine has no
                     83:  * IEEE802/EUI64 address sources.
                     84:  * The goal here is to get an interface identifier that is
                     85:  * (1) random enough and (2) does not change across reboot.
                     86:  * We currently use MD5(hostname) for it.
                     87:  */
                     88: static int
                     89: get_rand_ifid(ifp, in6)
                     90:        struct ifnet *ifp;
                     91:        struct in6_addr *in6;   /* upper 64bits are preserved */
                     92: {
                     93:        MD5_CTX ctxt;
                     94:        u_int8_t digest[16];
                     95:
                     96: #if 0
                     97:        /* we need at least several letters as seed for ifid */
                     98:        if (hostnamelen < 3)
                     99:                return -1;
                    100: #endif
                    101:
                    102:        /* generate 8 bytes of pseudo-random value. */
                    103:        bzero(&ctxt, sizeof(ctxt));
                    104:        MD5Init(&ctxt);
                    105:        MD5Update(&ctxt, hostname, hostnamelen);
                    106:        MD5Final(digest, &ctxt);
                    107:
                    108:        /* assumes sizeof(digest) > sizeof(ifid) */
                    109:        bcopy(digest, &in6->s6_addr[8], 8);
                    110:
                    111:        /* make sure to set "u" bit to local, and "g" bit to individual. */
                    112:        in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
                    113:        in6->s6_addr[8] |= EUI64_UBIT;  /* u bit to "local" */
                    114:
                    115:        /* convert EUI64 into IPv6 interface identifier */
                    116:        EUI64_TO_IFID(in6);
                    117:
                    118:        return 0;
                    119: }
                    120:
                    121: /*
                    122:  * Get interface identifier for the specified interface.
                    123:  * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
                    124:  */
                    125: static int
                    126: get_hw_ifid(ifp, in6)
                    127:        struct ifnet *ifp;
                    128:        struct in6_addr *in6;   /* upper 64bits are preserved */
                    129: {
                    130:        struct ifaddr *ifa;
                    131:        struct sockaddr_dl *sdl;
                    132:        char *addr;
                    133:        size_t addrlen;
                    134:        static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
                    135:        static u_int8_t allone[8] =
                    136:                { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
                    137:
                    138:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                    139:                if (ifa->ifa_addr->sa_family != AF_LINK)
                    140:                        continue;
                    141:                sdl = (struct sockaddr_dl *)ifa->ifa_addr;
                    142:                if (sdl == NULL)
                    143:                        continue;
                    144:                if (sdl->sdl_alen == 0)
                    145:                        continue;
                    146:
                    147:                goto found;
                    148:        }
                    149:
                    150:        return -1;
                    151:
                    152: found:
                    153:        addr = LLADDR(sdl);
                    154:        addrlen = sdl->sdl_alen;
                    155:
                    156:        switch (ifp->if_type) {
                    157:        case IFT_IEEE1394:
                    158:        case IFT_IEEE80211:
                    159:                /* IEEE1394 uses 16byte length address starting with EUI64 */
                    160:                if (addrlen > 8)
                    161:                        addrlen = 8;
                    162:                break;
                    163:        default:
                    164:                break;
                    165:        }
                    166:
                    167:        /* get EUI64 */
                    168:        switch (ifp->if_type) {
                    169:        /* IEEE802/EUI64 cases - what others? */
                    170:        case IFT_ETHER:
                    171:        case IFT_CARP:
                    172:        case IFT_FDDI:
                    173:        case IFT_ATM:
                    174:        case IFT_IEEE1394:
                    175:        case IFT_IEEE80211:
                    176:                /* look at IEEE802/EUI64 only */
                    177:                if (addrlen != 8 && addrlen != 6)
                    178:                        return -1;
                    179:
                    180:                /*
                    181:                 * check for invalid MAC address - on bsdi, we see it a lot
                    182:                 * since wildboar configures all-zero MAC on pccard before
                    183:                 * card insertion.
                    184:                 */
                    185:                if (bcmp(addr, allzero, addrlen) == 0)
                    186:                        return -1;
                    187:                if (bcmp(addr, allone, addrlen) == 0)
                    188:                        return -1;
                    189:
                    190:                /* make EUI64 address */
                    191:                if (addrlen == 8)
                    192:                        bcopy(addr, &in6->s6_addr[8], 8);
                    193:                else if (addrlen == 6) {
                    194:                        in6->s6_addr[8] = addr[0];
                    195:                        in6->s6_addr[9] = addr[1];
                    196:                        in6->s6_addr[10] = addr[2];
                    197:                        in6->s6_addr[11] = 0xff;
                    198:                        in6->s6_addr[12] = 0xfe;
                    199:                        in6->s6_addr[13] = addr[3];
                    200:                        in6->s6_addr[14] = addr[4];
                    201:                        in6->s6_addr[15] = addr[5];
                    202:                }
                    203:                break;
                    204:
                    205:        case IFT_GIF:
                    206:                /*
                    207:                 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
                    208:                 * however, IPv4 address is not very suitable as unique
                    209:                 * identifier source (can be renumbered).
                    210:                 * we don't do this.
                    211:                 */
                    212:                return -1;
                    213:
                    214:        default:
                    215:                return -1;
                    216:        }
                    217:
                    218:        /* sanity check: g bit must not indicate "group" */
                    219:        if (EUI64_GROUP(in6))
                    220:                return -1;
                    221:
                    222:        /* convert EUI64 into IPv6 interface identifier */
                    223:        EUI64_TO_IFID(in6);
                    224:
                    225:        /*
                    226:         * sanity check: ifid must not be all zero, avoid conflict with
                    227:         * subnet router anycast
                    228:         */
                    229:        if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
                    230:            bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
                    231:                return -1;
                    232:        }
                    233:
                    234:        return 0;
                    235: }
                    236:
                    237: /*
                    238:  * Get interface identifier for the specified interface.  If it is not
                    239:  * available on ifp0, borrow interface identifier from other information
                    240:  * sources.
                    241:  */
                    242: static int
                    243: get_ifid(ifp0, altifp, in6)
                    244:        struct ifnet *ifp0;
                    245:        struct ifnet *altifp;   /* secondary EUI64 source */
                    246:        struct in6_addr *in6;
                    247: {
                    248:        struct ifnet *ifp;
                    249:
                    250:        /* first, try to get it from the interface itself */
                    251:        if (get_hw_ifid(ifp0, in6) == 0) {
                    252:                nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
                    253:                    ifp0->if_xname));
                    254:                goto success;
                    255:        }
                    256:
                    257:        /* try secondary EUI64 source. this basically is for ATM PVC */
                    258:        if (altifp && get_hw_ifid(altifp, in6) == 0) {
                    259:                nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
                    260:                    ifp0->if_xname, altifp->if_xname));
                    261:                goto success;
                    262:        }
                    263:
                    264:        /* next, try to get it from some other hardware interface */
                    265:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
                    266:                if (ifp == ifp0)
                    267:                        continue;
                    268:                if (get_hw_ifid(ifp, in6) != 0)
                    269:                        continue;
                    270:
                    271:                /*
                    272:                 * to borrow ifid from other interface, ifid needs to be
                    273:                 * globally unique
                    274:                 */
                    275:                if (IFID_UNIVERSAL(in6)) {
                    276:                        nd6log((LOG_DEBUG,
                    277:                            "%s: borrow interface identifier from %s\n",
                    278:                            ifp0->if_xname, ifp->if_xname));
                    279:                        goto success;
                    280:                }
                    281:        }
                    282:
                    283:        /* last resort: get from random number source */
                    284:        if (get_rand_ifid(ifp, in6) == 0) {
                    285:                nd6log((LOG_DEBUG,
                    286:                    "%s: interface identifier generated by random number\n",
                    287:                    ifp0->if_xname));
                    288:                goto success;
                    289:        }
                    290:
                    291:        printf("%s: failed to get interface identifier\n", ifp0->if_xname);
                    292:        return -1;
                    293:
                    294: success:
                    295:        nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
                    296:            ifp0->if_xname, in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
                    297:            in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
                    298:            in6->s6_addr[14], in6->s6_addr[15]));
                    299:        return 0;
                    300: }
                    301:
                    302: int
                    303: in6_ifattach_linklocal(ifp, altifp)
                    304:        struct ifnet *ifp;
                    305:        struct ifnet *altifp;   /*secondary EUI64 source*/
                    306: {
                    307:        struct in6_ifaddr *ia;
                    308:        struct in6_aliasreq ifra;
                    309:        struct nd_prefix pr0;
                    310:        int i, error;
                    311:
                    312:        /*
                    313:         * configure link-local address.
                    314:         */
                    315:        bzero(&ifra, sizeof(ifra));
                    316:
                    317:        /*
                    318:         * in6_update_ifa() does not use ifra_name, but we accurately set it
                    319:         * for safety.
                    320:         */
                    321:        strncpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name));
                    322:
                    323:        ifra.ifra_addr.sin6_family = AF_INET6;
                    324:        ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
                    325:        ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
                    326:        ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
                    327:        ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
                    328:        if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
                    329:                ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
                    330:                ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
                    331:        } else {
                    332:                if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
                    333:                        nd6log((LOG_ERR,
                    334:                            "%s: no ifid available\n", ifp->if_xname));
                    335:                        return (-1);
                    336:                }
                    337:        }
                    338:
                    339:        ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
                    340:        ifra.ifra_prefixmask.sin6_family = AF_INET6;
                    341:        ifra.ifra_prefixmask.sin6_addr = in6mask64;
                    342:        /* link-local addresses should NEVER expire. */
                    343:        ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
                    344:        ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
                    345:
                    346:        /*
                    347:         * Do not let in6_update_ifa() do DAD, since we need a random delay
                    348:         * before sending an NS at the first time the interface becomes up.
                    349:         * Instead, in6_if_up() will start DAD with a proper random delay.
                    350:         */
                    351:        ifra.ifra_flags |= IN6_IFF_NODAD;
                    352:
                    353:        /*
                    354:         * Now call in6_update_ifa() to do a bunch of procedures to configure
                    355:         * a link-local address. In the case of CARP, we may be called after
                    356:         * one has already been configured, so check if it's already there
                    357:         * with in6ifa_ifpforlinklocal() and clobber it if it exists.
                    358:         */
                    359:        if ((error = in6_update_ifa(ifp, &ifra,
                    360:             in6ifa_ifpforlinklocal(ifp, 0))) != 0) {
                    361:                /*
                    362:                 * XXX: When the interface does not support IPv6, this call
                    363:                 * would fail in the SIOCSIFADDR ioctl.  I believe the
                    364:                 * notification is rather confusing in this case, so just
                    365:                 * suppress it.  (jinmei@kame.net 20010130)
                    366:                 */
                    367:                if (error != EAFNOSUPPORT)
                    368:                        nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
                    369:                            "configure a link-local address on %s "
                    370:                            "(errno=%d)\n",
                    371:                            ifp->if_xname, error));
                    372:                return (-1);
                    373:        }
                    374:
                    375:        /*
                    376:         * Adjust ia6_flags so that in6_if_up will perform DAD.
                    377:         * XXX: Some P2P interfaces seem not to send packets just after
                    378:         * becoming up, so we skip p2p interfaces for safety.
                    379:         */
                    380:        ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
                    381: #ifdef DIAGNOSTIC
                    382:        if (!ia) {
                    383:                panic("ia == NULL in in6_ifattach_linklocal");
                    384:                /* NOTREACHED */
                    385:        }
                    386: #endif
                    387:        if (in6if_do_dad(ifp) && ((ifp->if_flags & IFF_POINTOPOINT) ||
                    388:            (ifp->if_type == IFT_CARP)) == 0) {
                    389:                ia->ia6_flags &= ~IN6_IFF_NODAD;
                    390:                ia->ia6_flags |= IN6_IFF_TENTATIVE;
                    391:        }
                    392:
                    393:        /*
                    394:         * Make the link-local prefix (fe80::/64%link) as on-link.
                    395:         * Since we'd like to manage prefixes separately from addresses,
                    396:         * we make an ND6 prefix structure for the link-local prefix,
                    397:         * and add it to the prefix list as a never-expire prefix.
                    398:         * XXX: this change might affect some existing code base...
                    399:         */
                    400:        bzero(&pr0, sizeof(pr0));
                    401:        pr0.ndpr_ifp = ifp;
                    402:        /* this should be 64 at this moment. */
                    403:        pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
                    404:        pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr;
                    405:        pr0.ndpr_prefix = ifra.ifra_addr;
                    406:        /* apply the mask for safety. (nd6_prelist_add will apply it again) */
                    407:        for (i = 0; i < 4; i++) {
                    408:                pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
                    409:                    in6mask64.s6_addr32[i];
                    410:        }
                    411:        /*
                    412:         * Initialize parameters.  The link-local prefix must always be
                    413:         * on-link, and its lifetimes never expire.
                    414:         */
                    415:        pr0.ndpr_raf_onlink = 1;
                    416:        pr0.ndpr_raf_auto = 1;  /* probably meaningless */
                    417:        pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
                    418:        pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
                    419:        /*
                    420:         * Since there is no other link-local addresses, nd6_prefix_lookup()
                    421:         * probably returns NULL.  However, we cannot always expect the result.
                    422:         * For example, if we first remove the (only) existing link-local
                    423:         * address, and then reconfigure another one, the prefix is still
                    424:         * valid with referring to the old link-local address.
                    425:         */
                    426:        if (nd6_prefix_lookup(&pr0) == NULL) {
                    427:                if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
                    428:                        return (error);
                    429:        }
                    430:
                    431:        return 0;
                    432: }
                    433:
                    434: static int
                    435: in6_ifattach_loopback(ifp)
                    436:        struct ifnet *ifp;      /* must be IFT_LOOP */
                    437: {
                    438:        struct in6_aliasreq ifra;
                    439:        int error;
                    440:
                    441:        bzero(&ifra, sizeof(ifra));
                    442:
                    443:        /*
                    444:         * in6_update_ifa() does not use ifra_name, but we accurately set it
                    445:         * for safety.
                    446:         */
                    447:        strncpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name));
                    448:
                    449:        ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
                    450:        ifra.ifra_prefixmask.sin6_family = AF_INET6;
                    451:        ifra.ifra_prefixmask.sin6_addr = in6mask128;
                    452:
                    453:        /*
                    454:         * Always initialize ia_dstaddr (= broadcast address) to loopback
                    455:         * address.  Follows IPv4 practice - see in_ifinit().
                    456:         */
                    457:        ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
                    458:        ifra.ifra_dstaddr.sin6_family = AF_INET6;
                    459:        ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
                    460:
                    461:        ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
                    462:        ifra.ifra_addr.sin6_family = AF_INET6;
                    463:        ifra.ifra_addr.sin6_addr = in6addr_loopback;
                    464:
                    465:        /* the loopback  address should NEVER expire. */
                    466:        ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
                    467:        ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
                    468:
                    469:        /* we don't need to perform DAD on loopback interfaces. */
                    470:        ifra.ifra_flags |= IN6_IFF_NODAD;
                    471:
                    472:        /*
                    473:         * We are sure that this is a newly assigned address, so we can set
                    474:         * NULL to the 3rd arg.
                    475:         */
                    476:        if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
                    477:                nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
                    478:                    "the loopback address on %s (errno=%d)\n",
                    479:                    ifp->if_xname, error));
                    480:                return (-1);
                    481:        }
                    482:
                    483:        return 0;
                    484: }
                    485:
                    486: /*
                    487:  * compute NI group address, based on the current hostname setting.
                    488:  * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
                    489:  *
                    490:  * when ifp == NULL, the caller is responsible for filling scopeid.
                    491:  */
                    492: int
                    493: in6_nigroup(ifp, name, namelen, sa6)
                    494:        struct ifnet *ifp;
                    495:        const char *name;
                    496:        int namelen;
                    497:        struct sockaddr_in6 *sa6;
                    498: {
                    499:        const char *p;
                    500:        u_int8_t *q;
                    501:        MD5_CTX ctxt;
                    502:        u_int8_t digest[16];
                    503:        u_int8_t l;
                    504:        u_int8_t n[64]; /* a single label must not exceed 63 chars */
                    505:
                    506:        if (!namelen || !name)
                    507:                return -1;
                    508:
                    509:        p = name;
                    510:        while (p && *p && *p != '.' && p - name < namelen)
                    511:                p++;
                    512:        if (p - name > sizeof(n) - 1)
                    513:                return -1;      /* label too long */
                    514:        l = p - name;
                    515:        strncpy((char *)n, name, l);
                    516:        n[(int)l] = '\0';
                    517:        for (q = n; *q; q++) {
                    518:                if ('A' <= *q && *q <= 'Z')
                    519:                        *q = *q - 'A' + 'a';
                    520:        }
                    521:
                    522:        /* generate 8 bytes of pseudo-random value. */
                    523:        bzero(&ctxt, sizeof(ctxt));
                    524:        MD5Init(&ctxt);
                    525:        MD5Update(&ctxt, &l, sizeof(l));
                    526:        MD5Update(&ctxt, n, l);
                    527:        MD5Final(digest, &ctxt);
                    528:
                    529:        bzero(sa6, sizeof(*sa6));
                    530:        sa6->sin6_family = AF_INET6;
                    531:        sa6->sin6_len = sizeof(*sa6);
                    532:        sa6->sin6_addr.s6_addr16[0] = htons(0xff02);
                    533:        sa6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
                    534:        sa6->sin6_addr.s6_addr8[11] = 2;
                    535:        bcopy(digest, &sa6->sin6_addr.s6_addr32[3],
                    536:            sizeof(sa6->sin6_addr.s6_addr32[3]));
                    537:
                    538:        return 0;
                    539: }
                    540:
                    541: /*
                    542:  * XXX multiple loopback interface needs more care.  for instance,
                    543:  * nodelocal address needs to be configured onto only one of them.
                    544:  * XXX multiple link-local address case
                    545:  */
                    546: void
                    547: in6_ifattach(ifp, altifp)
                    548:        struct ifnet *ifp;
                    549:        struct ifnet *altifp;   /* secondary EUI64 source */
                    550: {
                    551:        struct in6_ifaddr *ia;
                    552:        struct in6_addr in6;
                    553:
                    554:        /* some of the interfaces are inherently not IPv6 capable */
                    555:        switch (ifp->if_type) {
                    556:        case IFT_BRIDGE:
                    557:        case IFT_ENC:
                    558:        case IFT_PFLOG:
                    559:        case IFT_PFSYNC:
                    560:                return;
                    561:        }
                    562:
                    563:        /*
                    564:         * if link mtu is too small, don't try to configure IPv6.
                    565:         * remember there could be some link-layer that has special
                    566:         * fragmentation logic.
                    567:         */
                    568:        if (ifp->if_mtu < IPV6_MMTU) {
                    569:                nd6log((LOG_INFO, "in6_ifattach: "
                    570:                    "%s has too small MTU, IPv6 not enabled\n",
                    571:                    ifp->if_xname));
                    572:                return;
                    573:        }
                    574:
                    575:        /* create a multicast kludge storage (if we have not had one) */
                    576:        in6_createmkludge(ifp);
                    577:
                    578:        /*
                    579:         * quirks based on interface type
                    580:         */
                    581:        switch (ifp->if_type) {
                    582:        /* we attach a link-local address when a vhid is assigned */
                    583:        case IFT_CARP:
                    584:                return;
                    585:        default:
                    586:                break;
                    587:        }
                    588:
                    589:        /*
                    590:         * usually, we require multicast capability to the interface
                    591:         */
                    592:        if ((ifp->if_flags & IFF_MULTICAST) == 0) {
                    593:                nd6log((LOG_INFO, "in6_ifattach: "
                    594:                    "%s is not multicast capable, IPv6 not enabled\n",
                    595:                    ifp->if_xname));
                    596:                return;
                    597:        }
                    598:
                    599:        /*
                    600:         * assign loopback address for loopback interface.
                    601:         * XXX multiple loopback interface case.
                    602:         */
                    603:        if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
                    604:                in6 = in6addr_loopback;
                    605:                if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
                    606:                        if (in6_ifattach_loopback(ifp) != 0)
                    607:                                return;
                    608:                }
                    609:        }
                    610:
                    611:        /*
                    612:         * assign a link-local address, if there's none.
                    613:         */
                    614:        if (ip6_auto_linklocal) {
                    615:                ia = in6ifa_ifpforlinklocal(ifp, 0);
                    616:                if (ia == NULL) {
                    617:                        if (in6_ifattach_linklocal(ifp, altifp) == 0) {
                    618:                                /* linklocal address assigned */
                    619:                        } else {
                    620:                                /* failed to assign linklocal address. bark? */
                    621:                        }
                    622:                }
                    623:        }
                    624: }
                    625:
                    626: /*
                    627:  * NOTE: in6_ifdetach() does not support loopback if at this moment.
                    628:  */
                    629: void
                    630: in6_ifdetach(ifp)
                    631:        struct ifnet *ifp;
                    632: {
                    633:        struct in6_ifaddr *ia, *oia;
                    634:        struct ifaddr *ifa, *next;
                    635:        struct rtentry *rt;
                    636:        short rtflags;
                    637:        struct sockaddr_in6 sin6;
                    638:        struct in6_multi_mship *imm;
                    639:
                    640: #ifdef MROUTING
                    641:        /* remove ip6_mrouter stuff */
                    642:        ip6_mrouter_detach(ifp);
                    643: #endif
                    644:
                    645:        /* remove neighbor management table */
                    646:        nd6_purge(ifp);
                    647:
                    648:        /* nuke any of IPv6 addresses we have */
                    649:        for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
                    650:            ifa != TAILQ_END(&ifp->if_addrlist); ifa = next) {
                    651:                next = TAILQ_NEXT(ifa, ifa_list);
                    652:                if (ifa->ifa_addr->sa_family != AF_INET6)
                    653:                        continue;
                    654:                in6_purgeaddr(ifa);
                    655:        }
                    656:
                    657:        /* undo everything done by in6_ifattach(), just in case */
                    658:        for (ifa = TAILQ_FIRST(&ifp->if_addrlist);
                    659:            ifa != TAILQ_END(&ifp->if_addrlist); ifa = next) {
                    660:                next = TAILQ_NEXT(ifa, ifa_list);
                    661:
                    662:                if (ifa->ifa_addr->sa_family != AF_INET6
                    663:                 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
                    664:                        continue;
                    665:                }
                    666:
                    667:                ia = (struct in6_ifaddr *)ifa;
                    668:
                    669:                /*
                    670:                 * leave from multicast groups we have joined for the interface
                    671:                 */
                    672:                while (!LIST_EMPTY(&ia->ia6_memberships)) {
                    673:                        imm = LIST_FIRST(&ia->ia6_memberships);
                    674:                        LIST_REMOVE(imm, i6mm_chain);
                    675:                        in6_leavegroup(imm);
                    676:                }
                    677:
                    678:                /* remove from the routing table */
                    679:                if ((ia->ia_flags & IFA_ROUTE) &&
                    680:                    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0))) {
                    681:                        rtflags = rt->rt_flags;
                    682:                        rtfree(rt);
                    683:                        rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
                    684:                            (struct sockaddr *)&ia->ia_addr,
                    685:                            (struct sockaddr *)&ia->ia_prefixmask,
                    686:                            rtflags, (struct rtentry **)0, 0);
                    687:                }
                    688:
                    689:                /* remove from the linked list */
                    690:                TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
                    691:                IFAFREE(&ia->ia_ifa);
                    692:
                    693:                /* also remove from the IPv6 address chain(itojun&jinmei) */
                    694:                oia = ia;
                    695:                if (oia == (ia = in6_ifaddr))
                    696:                        in6_ifaddr = ia->ia_next;
                    697:                else {
                    698:                        while (ia->ia_next && (ia->ia_next != oia))
                    699:                                ia = ia->ia_next;
                    700:                        if (ia->ia_next)
                    701:                                ia->ia_next = oia->ia_next;
                    702:                        else {
                    703:                                nd6log((LOG_ERR,
                    704:                                    "%s: didn't unlink in6ifaddr from list\n",
                    705:                                    ifp->if_xname));
                    706:                        }
                    707:                }
                    708:
                    709:                IFAFREE(&oia->ia_ifa);
                    710:        }
                    711:
                    712:        /* cleanup multicast address kludge table, if there is any */
                    713:        in6_purgemkludge(ifp);
                    714:
                    715:        /*
                    716:         * remove neighbor management table.  we call it twice just to make
                    717:         * sure we nuke everything.  maybe we need just one call.
                    718:         * XXX: since the first call did not release addresses, some prefixes
                    719:         * might remain.  We should call nd6_purge() again to release the
                    720:         * prefixes after removing all addresses above.
                    721:         * (Or can we just delay calling nd6_purge until at this point?)
                    722:         */
                    723:        nd6_purge(ifp);
                    724:
                    725:        /* remove route to link-local allnodes multicast (ff02::1) */
                    726:        bzero(&sin6, sizeof(sin6));
                    727:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                    728:        sin6.sin6_family = AF_INET6;
                    729:        sin6.sin6_addr = in6addr_linklocal_allnodes;
                    730:        sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
                    731:        rt = rtalloc1((struct sockaddr *)&sin6, 0, 0);
                    732:        if (rt && rt->rt_ifp == ifp) {
                    733:                rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
                    734:                    rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0, 0);
                    735:                rtfree(rt);
                    736:        }
                    737: }

CVSweb