[BACK]Return to in6_ifattach.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Annotation of src/sys/netinet6/in6_ifattach.c, Revision 1.61

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

CVSweb <webmaster@jp.NetBSD.org>