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

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

1.1       nbrk        1: /*     $OpenBSD: in6.c,v 1.72 2006/11/17 01:11:23 itojun Exp $ */
                      2: /*     $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun 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: /*
                     34:  * Copyright (c) 1982, 1986, 1991, 1993
                     35:  *     The Regents of the University of California.  All rights reserved.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
                     45:  * 3. Neither the name of the University nor the names of its contributors
                     46:  *    may be used to endorse or promote products derived from this software
                     47:  *    without specific prior written permission.
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  *
                     61:  *     @(#)in.c        8.2 (Berkeley) 11/15/93
                     62:  */
                     63:
                     64: #include <sys/param.h>
                     65: #include <sys/ioctl.h>
                     66: #include <sys/errno.h>
                     67: #include <sys/malloc.h>
                     68: #include <sys/socket.h>
                     69: #include <sys/socketvar.h>
                     70: #include <sys/sockio.h>
                     71: #include <sys/systm.h>
                     72: #include <sys/proc.h>
                     73: #include <sys/time.h>
                     74: #include <sys/kernel.h>
                     75: #include <sys/syslog.h>
                     76:
                     77: #include <net/if.h>
                     78: #include <net/if_types.h>
                     79: #include <net/route.h>
                     80: #include <net/if_dl.h>
                     81:
                     82: #include <netinet/in.h>
                     83: #include <netinet/in_var.h>
                     84: #include <netinet/if_ether.h>
                     85:
                     86: #include <netinet/ip6.h>
                     87: #include <netinet6/ip6_var.h>
                     88: #include <netinet6/nd6.h>
                     89: #include <netinet6/mld6_var.h>
                     90: #ifdef MROUTING
                     91: #include <netinet6/ip6_mroute.h>
                     92: #endif
                     93: #include <netinet6/in6_ifattach.h>
                     94:
                     95: /* backward compatibility for a while... */
                     96: #define COMPAT_IN6IFIOCTL
                     97:
                     98: /*
                     99:  * Definitions of some constant IP6 addresses.
                    100:  */
                    101: const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
                    102: const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
                    103: const struct in6_addr in6addr_intfacelocal_allnodes =
                    104:        IN6ADDR_INTFACELOCAL_ALLNODES_INIT;
                    105: const struct in6_addr in6addr_linklocal_allnodes =
                    106:        IN6ADDR_LINKLOCAL_ALLNODES_INIT;
                    107: const struct in6_addr in6addr_linklocal_allrouters =
                    108:        IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
                    109:
                    110: const struct in6_addr in6mask0 = IN6MASK0;
                    111: const struct in6_addr in6mask32 = IN6MASK32;
                    112: const struct in6_addr in6mask64 = IN6MASK64;
                    113: const struct in6_addr in6mask96 = IN6MASK96;
                    114: const struct in6_addr in6mask128 = IN6MASK128;
                    115:
                    116: static int in6_lifaddr_ioctl(struct socket *, u_long, caddr_t,
                    117:        struct ifnet *, struct proc *);
                    118: static int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
                    119:        struct sockaddr_in6 *, int);
                    120: static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
                    121:
                    122: const struct sockaddr_in6 sa6_any = {sizeof(sa6_any), AF_INET6,
                    123:                                     0, 0, IN6ADDR_ANY_INIT, 0};
                    124:
                    125: /*
                    126:  * This structure is used to keep track of in6_multi chains which belong to
                    127:  * deleted interface addresses.
                    128:  */
                    129: static LIST_HEAD(, multi6_kludge) in6_mk; /* XXX BSS initialization */
                    130:
                    131: struct multi6_kludge {
                    132:        LIST_ENTRY(multi6_kludge) mk_entry;
                    133:        struct ifnet *mk_ifp;
                    134:        struct in6_multihead mk_head;
                    135: };
                    136:
                    137: /*
                    138:  * Subroutine for in6_ifaddloop() and in6_ifremloop().
                    139:  * This routine does actual work.
                    140:  */
                    141: static void
                    142: in6_ifloop_request(int cmd, struct ifaddr *ifa)
                    143: {
                    144:        struct sockaddr_in6 lo_sa;
                    145:        struct sockaddr_in6 all1_sa;
                    146:        struct rtentry *nrt = NULL;
                    147:        int e;
                    148:
                    149:        bzero(&lo_sa, sizeof(lo_sa));
                    150:        bzero(&all1_sa, sizeof(all1_sa));
                    151:        lo_sa.sin6_family = all1_sa.sin6_family = AF_INET6;
                    152:        lo_sa.sin6_len = all1_sa.sin6_len = sizeof(struct sockaddr_in6);
                    153:        lo_sa.sin6_addr = in6addr_loopback;
                    154:        all1_sa.sin6_addr = in6mask128;
                    155:
                    156:        /*
                    157:         * We specify the address itself as the gateway, and set the
                    158:         * RTF_LLINFO flag, so that the corresponding host route would have
                    159:         * the flag, and thus applications that assume traditional behavior
                    160:         * would be happy.  Note that we assume the caller of the function
                    161:         * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
                    162:         * which changes the outgoing interface to the loopback interface.
                    163:         * XXX only table 0 for now
                    164:         */
                    165:        e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
                    166:            (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt, 0);
                    167:        if (e != 0) {
                    168:                log(LOG_ERR, "in6_ifloop_request: "
                    169:                    "%s operation failed for %s (errno=%d)\n",
                    170:                    cmd == RTM_ADD ? "ADD" : "DELETE",
                    171:                    ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
                    172:                    e);
                    173:        }
                    174:
                    175:        /*
                    176:         * Make sure rt_ifa be equal to IFA, the second argument of the
                    177:         * function.
                    178:         * We need this because when we refer to rt_ifa->ia6_flags in
                    179:         * ip6_input, we assume that the rt_ifa points to the address instead
                    180:         * of the loopback address.
                    181:         */
                    182:        if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
                    183:                IFAFREE(nrt->rt_ifa);
                    184:                ifa->ifa_refcnt++;
                    185:                nrt->rt_ifa = ifa;
                    186:        }
                    187:
                    188:        /*
                    189:         * Report the addition/removal of the address to the routing socket.
                    190:         * XXX: since we called rtinit for a p2p interface with a destination,
                    191:         *      we end up reporting twice in such a case.  Should we rather
                    192:         *      omit the second report?
                    193:         */
                    194:        if (nrt) {
                    195:                rt_newaddrmsg(cmd, ifa, e, nrt);
                    196:                if (cmd == RTM_DELETE) {
                    197:                        if (nrt->rt_refcnt <= 0) {
                    198:                                /* XXX: we should free the entry ourselves. */
                    199:                                nrt->rt_refcnt++;
                    200:                                rtfree(nrt);
                    201:                        }
                    202:                } else {
                    203:                        /* the cmd must be RTM_ADD here */
                    204:                        nrt->rt_refcnt--;
                    205:                }
                    206:        }
                    207: }
                    208:
                    209: /*
                    210:  * Add ownaddr as loopback rtentry.  We previously add the route only if
                    211:  * necessary (ex. on a p2p link).  However, since we now manage addresses
                    212:  * separately from prefixes, we should always add the route.  We can't
                    213:  * rely on the cloning mechanism from the corresponding interface route
                    214:  * any more.
                    215:  */
                    216: void
                    217: in6_ifaddloop(struct ifaddr *ifa)
                    218: {
                    219:        struct rtentry *rt;
                    220:
                    221:        /* If there is no loopback entry, allocate one. */
                    222:        rt = rtalloc1(ifa->ifa_addr, 0, 0);
                    223:        if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
                    224:            (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
                    225:                in6_ifloop_request(RTM_ADD, ifa);
                    226:        if (rt)
                    227:                rt->rt_refcnt--;
                    228: }
                    229:
                    230: /*
                    231:  * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
                    232:  * if it exists.
                    233:  */
                    234: void
                    235: in6_ifremloop(struct ifaddr *ifa)
                    236: {
                    237:        struct in6_ifaddr *ia;
                    238:        struct rtentry *rt;
                    239:        int ia_count = 0;
                    240:
                    241:        /*
                    242:         * Some of BSD variants do not remove cloned routes
                    243:         * from an interface direct route, when removing the direct route
                    244:         * (see comments in net/net_osdep.h).  Even for variants that do remove
                    245:         * cloned routes, they could fail to remove the cloned routes when
                    246:         * we handle multple addresses that share a common prefix.
                    247:         * So, we should remove the route corresponding to the deleted address.
                    248:         */
                    249:
                    250:        /*
                    251:         * Delete the entry only if exact one ifa exists.  More than one ifa
                    252:         * can exist if we assign a same single address to multiple
                    253:         * (probably p2p) interfaces.
                    254:         * XXX: we should avoid such a configuration in IPv6...
                    255:         */
                    256:        for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
                    257:                if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
                    258:                        ia_count++;
                    259:                        if (ia_count > 1)
                    260:                                break;
                    261:                }
                    262:        }
                    263:
                    264:        if (ia_count == 1) {
                    265:                /*
                    266:                 * Before deleting, check if a corresponding loopbacked host
                    267:                 * route surely exists.  With this check, we can avoid to
                    268:                 * delete an interface direct route whose destination is same
                    269:                 * as the address being removed.  This can happen when removing
                    270:                 * a subnet-router anycast address on an interface attahced
                    271:                 * to a shared medium.
                    272:                 */
                    273:                rt = rtalloc1(ifa->ifa_addr, 0, 0);
                    274:                if (rt != NULL && (rt->rt_flags & RTF_HOST) != 0 &&
                    275:                    (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
                    276:                        rt->rt_refcnt--;
                    277:                        in6_ifloop_request(RTM_DELETE, ifa);
                    278:                }
                    279:        }
                    280: }
                    281:
                    282: int
                    283: in6_mask2len(mask, lim0)
                    284:        struct in6_addr *mask;
                    285:        u_char *lim0;
                    286: {
                    287:        int x = 0, y;
                    288:        u_char *lim = lim0, *p;
                    289:
                    290:        /* ignore the scope_id part */
                    291:        if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
                    292:                lim = (u_char *)mask + sizeof(*mask);
                    293:        for (p = (u_char *)mask; p < lim; x++, p++) {
                    294:                if (*p != 0xff)
                    295:                        break;
                    296:        }
                    297:        y = 0;
                    298:        if (p < lim) {
                    299:                for (y = 0; y < 8; y++) {
                    300:                        if ((*p & (0x80 >> y)) == 0)
                    301:                                break;
                    302:                }
                    303:        }
                    304:
                    305:        /*
                    306:         * when the limit pointer is given, do a stricter check on the
                    307:         * remaining bits.
                    308:         */
                    309:        if (p < lim) {
                    310:                if (y != 0 && (*p & (0x00ff >> y)) != 0)
                    311:                        return (-1);
                    312:                for (p = p + 1; p < lim; p++)
                    313:                        if (*p != 0)
                    314:                                return (-1);
                    315:        }
                    316:
                    317:        return x * 8 + y;
                    318: }
                    319:
                    320: #define ifa2ia6(ifa)   ((struct in6_ifaddr *)(ifa))
                    321: #define ia62ifa(ia6)   (&((ia6)->ia_ifa))
                    322:
                    323: int
                    324: in6_control(so, cmd, data, ifp, p)
                    325:        struct  socket *so;
                    326:        u_long cmd;
                    327:        caddr_t data;
                    328:        struct ifnet *ifp;
                    329:        struct proc *p;
                    330: {
                    331:        struct  in6_ifreq *ifr = (struct in6_ifreq *)data;
                    332:        struct  in6_ifaddr *ia = NULL;
                    333:        struct  in6_aliasreq *ifra = (struct in6_aliasreq *)data;
                    334:        struct sockaddr_in6 *sa6;
                    335:        int privileged;
                    336:
                    337:        privileged = 0;
                    338:        if ((so->so_state & SS_PRIV) != 0)
                    339:                privileged++;
                    340:
                    341: #ifdef MROUTING
                    342:        switch (cmd) {
                    343:        case SIOCGETSGCNT_IN6:
                    344:        case SIOCGETMIFCNT_IN6:
                    345:                return (mrt6_ioctl(cmd, data));
                    346:        }
                    347: #endif
                    348:
                    349:        if (ifp == NULL)
                    350:                return (EOPNOTSUPP);
                    351:
                    352:        switch (cmd) {
                    353:        case SIOCSNDFLUSH_IN6:
                    354:        case SIOCSPFXFLUSH_IN6:
                    355:        case SIOCSRTRFLUSH_IN6:
                    356:        case SIOCSDEFIFACE_IN6:
                    357:        case SIOCSIFINFO_FLAGS:
                    358:                if (!privileged)
                    359:                        return (EPERM);
                    360:                /* FALLTHROUGH */
                    361:        case OSIOCGIFINFO_IN6:
                    362:        case SIOCGIFINFO_IN6:
                    363:        case SIOCGDRLST_IN6:
                    364:        case SIOCGPRLST_IN6:
                    365:        case SIOCGNBRINFO_IN6:
                    366:        case SIOCGDEFIFACE_IN6:
                    367:                return (nd6_ioctl(cmd, data, ifp));
                    368:        }
                    369:
                    370:        switch (cmd) {
                    371:        case SIOCSIFPREFIX_IN6:
                    372:        case SIOCDIFPREFIX_IN6:
                    373:        case SIOCAIFPREFIX_IN6:
                    374:        case SIOCCIFPREFIX_IN6:
                    375:        case SIOCSGIFPREFIX_IN6:
                    376:        case SIOCGIFPREFIX_IN6:
                    377:                log(LOG_NOTICE,
                    378:                    "prefix ioctls are now invalidated. "
                    379:                    "please use ifconfig.\n");
                    380:                return (EOPNOTSUPP);
                    381:        }
                    382:
                    383:        switch (cmd) {
                    384:        case SIOCALIFADDR:
                    385:        case SIOCDLIFADDR:
                    386:                if (!privileged)
                    387:                        return (EPERM);
                    388:                /* FALLTHROUGH */
                    389:        case SIOCGLIFADDR:
                    390:                return in6_lifaddr_ioctl(so, cmd, data, ifp, p);
                    391:        }
                    392:
                    393:        /*
                    394:         * Find address for this interface, if it exists.
                    395:         *
                    396:         * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
                    397:         * only, and used the first interface address as the target of other
                    398:         * operations (without checking ifra_addr).  This was because netinet
                    399:         * code/API assumed at most 1 interface address per interface.
                    400:         * Since IPv6 allows a node to assign multiple addresses
                    401:         * on a single interface, we almost always look and check the
                    402:         * presence of ifra_addr, and reject invalid ones here.
                    403:         * It also decreases duplicated code among SIOC*_IN6 operations.
                    404:         */
                    405:        switch (cmd) {
                    406:        case SIOCAIFADDR_IN6:
                    407:        case SIOCSIFPHYADDR_IN6:
                    408:                sa6 = &ifra->ifra_addr;
                    409:                break;
                    410:        case SIOCSIFADDR_IN6:
                    411:        case SIOCGIFADDR_IN6:
                    412:        case SIOCSIFDSTADDR_IN6:
                    413:        case SIOCSIFNETMASK_IN6:
                    414:        case SIOCGIFDSTADDR_IN6:
                    415:        case SIOCGIFNETMASK_IN6:
                    416:        case SIOCDIFADDR_IN6:
                    417:        case SIOCGIFPSRCADDR_IN6:
                    418:        case SIOCGIFPDSTADDR_IN6:
                    419:        case SIOCGIFAFLAG_IN6:
                    420:        case SIOCSNDFLUSH_IN6:
                    421:        case SIOCSPFXFLUSH_IN6:
                    422:        case SIOCSRTRFLUSH_IN6:
                    423:        case SIOCGIFALIFETIME_IN6:
                    424:        case SIOCSIFALIFETIME_IN6:
                    425:        case SIOCGIFSTAT_IN6:
                    426:        case SIOCGIFSTAT_ICMP6:
                    427:                sa6 = &ifr->ifr_addr;
                    428:                break;
                    429:        default:
                    430:                sa6 = NULL;
                    431:                break;
                    432:        }
                    433:        if (sa6 && sa6->sin6_family == AF_INET6) {
                    434:                if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
                    435:                        if (sa6->sin6_addr.s6_addr16[1] == 0) {
                    436:                                /* link ID is not embedded by the user */
                    437:                                sa6->sin6_addr.s6_addr16[1] =
                    438:                                    htons(ifp->if_index);
                    439:                        } else if (sa6->sin6_addr.s6_addr16[1] !=
                    440:                            htons(ifp->if_index)) {
                    441:                                return (EINVAL);        /* link ID contradicts */
                    442:                        }
                    443:                        if (sa6->sin6_scope_id) {
                    444:                                if (sa6->sin6_scope_id !=
                    445:                                    (u_int32_t)ifp->if_index)
                    446:                                        return (EINVAL);
                    447:                                sa6->sin6_scope_id = 0; /* XXX: good way? */
                    448:                        }
                    449:                }
                    450:                ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
                    451:        } else
                    452:                ia = NULL;
                    453:
                    454:        switch (cmd) {
                    455:        case SIOCSIFADDR_IN6:
                    456:        case SIOCSIFDSTADDR_IN6:
                    457:        case SIOCSIFNETMASK_IN6:
                    458:                /*
                    459:                 * Since IPv6 allows a node to assign multiple addresses
                    460:                 * on a single interface, SIOCSIFxxx ioctls are deprecated.
                    461:                 */
                    462:                return (EINVAL);
                    463:
                    464:        case SIOCDIFADDR_IN6:
                    465:                /*
                    466:                 * for IPv4, we look for existing in_ifaddr here to allow
                    467:                 * "ifconfig if0 delete" to remove the first IPv4 address on
                    468:                 * the interface.  For IPv6, as the spec allows multiple
                    469:                 * interface address from the day one, we consider "remove the
                    470:                 * first one" semantics to be not preferable.
                    471:                 */
                    472:                if (ia == NULL)
                    473:                        return (EADDRNOTAVAIL);
                    474:                /* FALLTHROUGH */
                    475:        case SIOCAIFADDR_IN6:
                    476:                /*
                    477:                 * We always require users to specify a valid IPv6 address for
                    478:                 * the corresponding operation.
                    479:                 */
                    480:                if (ifra->ifra_addr.sin6_family != AF_INET6 ||
                    481:                    ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
                    482:                        return (EAFNOSUPPORT);
                    483:                if (!privileged)
                    484:                        return (EPERM);
                    485:
                    486:                break;
                    487:
                    488:        case SIOCGIFADDR_IN6:
                    489:                /* This interface is basically deprecated. use SIOCGIFCONF. */
                    490:                /* FALLTHROUGH */
                    491:        case SIOCGIFAFLAG_IN6:
                    492:        case SIOCGIFNETMASK_IN6:
                    493:        case SIOCGIFDSTADDR_IN6:
                    494:        case SIOCGIFALIFETIME_IN6:
                    495:                /* must think again about its semantics */
                    496:                if (ia == NULL)
                    497:                        return (EADDRNOTAVAIL);
                    498:                break;
                    499:        case SIOCSIFALIFETIME_IN6:
                    500:            {
                    501:                struct in6_addrlifetime *lt;
                    502:
                    503:                if (!privileged)
                    504:                        return (EPERM);
                    505:                if (ia == NULL)
                    506:                        return (EADDRNOTAVAIL);
                    507:                /* sanity for overflow - beware unsigned */
                    508:                lt = &ifr->ifr_ifru.ifru_lifetime;
                    509:                if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
                    510:                 && lt->ia6t_vltime + time_second < time_second) {
                    511:                        return EINVAL;
                    512:                }
                    513:                if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
                    514:                 && lt->ia6t_pltime + time_second < time_second) {
                    515:                        return EINVAL;
                    516:                }
                    517:                break;
                    518:            }
                    519:        }
                    520:
                    521:        switch (cmd) {
                    522:
                    523:        case SIOCGIFADDR_IN6:
                    524:                ifr->ifr_addr = ia->ia_addr;
                    525:                break;
                    526:
                    527:        case SIOCGIFDSTADDR_IN6:
                    528:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                    529:                        return (EINVAL);
                    530:                /*
                    531:                 * XXX: should we check if ifa_dstaddr is NULL and return
                    532:                 * an error?
                    533:                 */
                    534:                ifr->ifr_dstaddr = ia->ia_dstaddr;
                    535:                break;
                    536:
                    537:        case SIOCGIFNETMASK_IN6:
                    538:                ifr->ifr_addr = ia->ia_prefixmask;
                    539:                break;
                    540:
                    541:        case SIOCGIFAFLAG_IN6:
                    542:                ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
                    543:                break;
                    544:
                    545:        case SIOCGIFSTAT_IN6:
                    546:                if (ifp == NULL)
                    547:                        return EINVAL;
                    548:                bzero(&ifr->ifr_ifru.ifru_stat,
                    549:                    sizeof(ifr->ifr_ifru.ifru_stat));
                    550:                ifr->ifr_ifru.ifru_stat =
                    551:                    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
                    552:                break;
                    553:
                    554:        case SIOCGIFSTAT_ICMP6:
                    555:                if (ifp == NULL)
                    556:                        return EINVAL;
                    557:                bzero(&ifr->ifr_ifru.ifru_icmp6stat,
                    558:                    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
                    559:                ifr->ifr_ifru.ifru_icmp6stat =
                    560:                    *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
                    561:                break;
                    562:
                    563:        case SIOCGIFALIFETIME_IN6:
                    564:                ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
                    565:                if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
                    566:                        time_t maxexpire;
                    567:                        struct in6_addrlifetime *retlt =
                    568:                            &ifr->ifr_ifru.ifru_lifetime;
                    569:
                    570:                        /*
                    571:                         * XXX: adjust expiration time assuming time_t is
                    572:                         * signed.
                    573:                         */
                    574:                        maxexpire = (-1) &
                    575:                            ~(1 << ((sizeof(maxexpire) * 8) - 1));
                    576:                        if (ia->ia6_lifetime.ia6t_vltime <
                    577:                            maxexpire - ia->ia6_updatetime) {
                    578:                                retlt->ia6t_expire = ia->ia6_updatetime +
                    579:                                    ia->ia6_lifetime.ia6t_vltime;
                    580:                        } else
                    581:                                retlt->ia6t_expire = maxexpire;
                    582:                }
                    583:                if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
                    584:                        time_t maxexpire;
                    585:                        struct in6_addrlifetime *retlt =
                    586:                            &ifr->ifr_ifru.ifru_lifetime;
                    587:
                    588:                        /*
                    589:                         * XXX: adjust expiration time assuming time_t is
                    590:                         * signed.
                    591:                         */
                    592:                        maxexpire = (-1) &
                    593:                            ~(1 << ((sizeof(maxexpire) * 8) - 1));
                    594:                        if (ia->ia6_lifetime.ia6t_pltime <
                    595:                            maxexpire - ia->ia6_updatetime) {
                    596:                                retlt->ia6t_preferred = ia->ia6_updatetime +
                    597:                                    ia->ia6_lifetime.ia6t_pltime;
                    598:                        } else
                    599:                                retlt->ia6t_preferred = maxexpire;
                    600:                }
                    601:                break;
                    602:
                    603:        case SIOCSIFALIFETIME_IN6:
                    604:                ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
                    605:                /* for sanity */
                    606:                if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
                    607:                        ia->ia6_lifetime.ia6t_expire =
                    608:                                time_second + ia->ia6_lifetime.ia6t_vltime;
                    609:                } else
                    610:                        ia->ia6_lifetime.ia6t_expire = 0;
                    611:                if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
                    612:                        ia->ia6_lifetime.ia6t_preferred =
                    613:                                time_second + ia->ia6_lifetime.ia6t_pltime;
                    614:                } else
                    615:                        ia->ia6_lifetime.ia6t_preferred = 0;
                    616:                break;
                    617:
                    618:        case SIOCAIFADDR_IN6:
                    619:        {
                    620:                int i, error = 0;
                    621:                struct nd_prefix pr0, *pr;
                    622:
                    623:                /* reject read-only flags */
                    624:                if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
                    625:                    (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
                    626:                    (ifra->ifra_flags & IN6_IFF_NODAD) != 0 ||
                    627:                    (ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0) {
                    628:                        return (EINVAL);
                    629:                }
                    630:                /*
                    631:                 * first, make or update the interface address structure,
                    632:                 * and link it to the list.
                    633:                 */
                    634:                if ((error = in6_update_ifa(ifp, ifra, ia)) != 0)
                    635:                        return (error);
                    636:                if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
                    637:                    == NULL) {
                    638:                        /*
                    639:                         * this can happen when the user specify the 0 valid
                    640:                         * lifetime.
                    641:                         */
                    642:                        break;
                    643:                }
                    644:
                    645:                /*
                    646:                 * then, make the prefix on-link on the interface.
                    647:                 * XXX: we'd rather create the prefix before the address, but
                    648:                 * we need at least one address to install the corresponding
                    649:                 * interface route, so we configure the address first.
                    650:                 */
                    651:
                    652:                /*
                    653:                 * convert mask to prefix length (prefixmask has already
                    654:                 * been validated in in6_update_ifa().
                    655:                 */
                    656:                bzero(&pr0, sizeof(pr0));
                    657:                pr0.ndpr_ifp = ifp;
                    658:                pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
                    659:                    NULL);
                    660:                if (pr0.ndpr_plen == 128) {
                    661:                        break;  /* we don't need to install a host route. */
                    662:                }
                    663:                pr0.ndpr_prefix = ifra->ifra_addr;
                    664:                pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
                    665:                /* apply the mask for safety. */
                    666:                for (i = 0; i < 4; i++) {
                    667:                        pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
                    668:                            ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
                    669:                }
                    670:                /*
                    671:                 * XXX: since we don't have an API to set prefix (not address)
                    672:                 * lifetimes, we just use the same lifetimes as addresses.
                    673:                 * The (temporarily) installed lifetimes can be overridden by
                    674:                 * later advertised RAs (when accept_rtadv is non 0), which is
                    675:                 * an intended behavior.
                    676:                 */
                    677:                pr0.ndpr_raf_onlink = 1; /* should be configurable? */
                    678:                pr0.ndpr_raf_auto =
                    679:                    ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
                    680:                pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
                    681:                pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
                    682:
                    683:                /* add the prefix if not yet. */
                    684:                if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
                    685:                        /*
                    686:                         * nd6_prelist_add will install the corresponding
                    687:                         * interface route.
                    688:                         */
                    689:                        if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
                    690:                                return (error);
                    691:                        if (pr == NULL) {
                    692:                                log(LOG_ERR, "nd6_prelist_add succeeded but "
                    693:                                    "no prefix\n");
                    694:                                return (EINVAL); /* XXX panic here? */
                    695:                        }
                    696:                }
                    697:
                    698:                /* relate the address to the prefix */
                    699:                if (ia->ia6_ndpr == NULL) {
                    700:                        ia->ia6_ndpr = pr;
                    701:                        pr->ndpr_refcnt++;
                    702:                }
                    703:
                    704:                /*
                    705:                 * this might affect the status of autoconfigured addresses,
                    706:                 * that is, this address might make other addresses detached.
                    707:                 */
                    708:                pfxlist_onlink_check();
                    709:
                    710:                dohooks(ifp->if_addrhooks, 0);
                    711:                break;
                    712:        }
                    713:
                    714:        case SIOCDIFADDR_IN6:
                    715:        {
                    716:                int i = 0, purgeprefix = 0;
                    717:                struct nd_prefix pr0, *pr = NULL;
                    718:
                    719:                /*
                    720:                 * If the address being deleted is the only one that owns
                    721:                 * the corresponding prefix, expire the prefix as well.
                    722:                 * XXX: theoretically, we don't have to worry about such
                    723:                 * relationship, since we separate the address management
                    724:                 * and the prefix management.  We do this, however, to provide
                    725:                 * as much backward compatibility as possible in terms of
                    726:                 * the ioctl operation.
                    727:                 */
                    728:                bzero(&pr0, sizeof(pr0));
                    729:                pr0.ndpr_ifp = ifp;
                    730:                pr0.ndpr_plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr,
                    731:                    NULL);
                    732:                if (pr0.ndpr_plen == 128)
                    733:                        goto purgeaddr;
                    734:                pr0.ndpr_prefix = ia->ia_addr;
                    735:                pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
                    736:                for (i = 0; i < 4; i++) {
                    737:                        pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
                    738:                            ia->ia_prefixmask.sin6_addr.s6_addr32[i];
                    739:                }
                    740:                if ((pr = nd6_prefix_lookup(&pr0)) != NULL &&
                    741:                    pr == ia->ia6_ndpr) {
                    742:                        pr->ndpr_refcnt--;
                    743:                        if (pr->ndpr_refcnt == 0)
                    744:                                purgeprefix = 1;
                    745:                }
                    746:
                    747:          purgeaddr:
                    748:                in6_purgeaddr(&ia->ia_ifa);
                    749:                if (pr && purgeprefix)
                    750:                        prelist_remove(pr);
                    751:                dohooks(ifp->if_addrhooks, 0);
                    752:                break;
                    753:        }
                    754:
                    755:        default:
                    756:                if (ifp == NULL || ifp->if_ioctl == 0)
                    757:                        return (EOPNOTSUPP);
                    758:                return ((*ifp->if_ioctl)(ifp, cmd, data));
                    759:        }
                    760:
                    761:        return (0);
                    762: }
                    763:
                    764: /*
                    765:  * Update parameters of an IPv6 interface address.
                    766:  * If necessary, a new entry is created and linked into address chains.
                    767:  * This function is separated from in6_control().
                    768:  * XXX: should this be performed under splnet()?
                    769:  */
                    770: int
                    771: in6_update_ifa(ifp, ifra, ia)
                    772:        struct ifnet *ifp;
                    773:        struct in6_aliasreq *ifra;
                    774:        struct in6_ifaddr *ia;
                    775: {
                    776:        int error = 0, hostIsNew = 0, plen = -1;
                    777:        struct in6_ifaddr *oia;
                    778:        struct sockaddr_in6 dst6;
                    779:        struct in6_addrlifetime *lt;
                    780:        struct in6_multi_mship *imm;
                    781:        struct rtentry *rt;
                    782:
                    783:        /* Validate parameters */
                    784:        if (ifp == NULL || ifra == NULL) /* this maybe redundant */
                    785:                return (EINVAL);
                    786:
                    787:        /*
                    788:         * The destination address for a p2p link must have a family
                    789:         * of AF_UNSPEC or AF_INET6.
                    790:         */
                    791:        if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
                    792:            ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
                    793:            ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
                    794:                return (EAFNOSUPPORT);
                    795:        /*
                    796:         * validate ifra_prefixmask.  don't check sin6_family, netmask
                    797:         * does not carry fields other than sin6_len.
                    798:         */
                    799:        if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
                    800:                return (EINVAL);
                    801:        /*
                    802:         * Because the IPv6 address architecture is classless, we require
                    803:         * users to specify a (non 0) prefix length (mask) for a new address.
                    804:         * We also require the prefix (when specified) mask is valid, and thus
                    805:         * reject a non-consecutive mask.
                    806:         */
                    807:        if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
                    808:                return (EINVAL);
                    809:        if (ifra->ifra_prefixmask.sin6_len != 0) {
                    810:                plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
                    811:                    (u_char *)&ifra->ifra_prefixmask +
                    812:                    ifra->ifra_prefixmask.sin6_len);
                    813:                if (plen <= 0)
                    814:                        return (EINVAL);
                    815:        } else {
                    816:                /*
                    817:                 * In this case, ia must not be NULL.  We just use its prefix
                    818:                 * length.
                    819:                 */
                    820:                plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
                    821:        }
                    822:        /*
                    823:         * If the destination address on a p2p interface is specified,
                    824:         * and the address is a scoped one, validate/set the scope
                    825:         * zone identifier.
                    826:         */
                    827:        dst6 = ifra->ifra_dstaddr;
                    828:        if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
                    829:            (dst6.sin6_family == AF_INET6)) {
                    830:                /* link-local index check: should be a separate function? */
                    831:                if (IN6_IS_ADDR_LINKLOCAL(&dst6.sin6_addr)) {
                    832:                        if (dst6.sin6_addr.s6_addr16[1] == 0) {
                    833:                                /*
                    834:                                 * interface ID is not embedded by
                    835:                                 * the user
                    836:                                 */
                    837:                                dst6.sin6_addr.s6_addr16[1] =
                    838:                                    htons(ifp->if_index);
                    839:                        } else if (dst6.sin6_addr.s6_addr16[1] !=
                    840:                            htons(ifp->if_index)) {
                    841:                                return (EINVAL);        /* ifid contradicts */
                    842:                        }
                    843:                }
                    844:        }
                    845:        /*
                    846:         * The destination address can be specified only for a p2p or a
                    847:         * loopback interface.  If specified, the corresponding prefix length
                    848:         * must be 128.
                    849:         */
                    850:        if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
                    851: #ifdef FORCE_P2PPLEN
                    852:                int i;
                    853: #endif
                    854:
                    855:                if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
                    856:                        /* XXX: noisy message */
                    857:                        nd6log((LOG_INFO, "in6_update_ifa: a destination can "
                    858:                            "be specified for a p2p or a loopback IF only\n"));
                    859:                        return (EINVAL);
                    860:                }
                    861:                if (plen != 128) {
                    862:                        nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
                    863:                            "be 128 when dstaddr is specified\n"));
                    864: #ifdef FORCE_P2PPLEN
                    865:                        /*
                    866:                         * To be compatible with old configurations,
                    867:                         * such as ifconfig gif0 inet6 2001::1 2001::2
                    868:                         * prefixlen 126, we override the specified
                    869:                         * prefixmask as if the prefix length was 128.
                    870:                         */
                    871:                        ifra->ifra_prefixmask.sin6_len =
                    872:                            sizeof(struct sockaddr_in6);
                    873:                        for (i = 0; i < 4; i++)
                    874:                                ifra->ifra_prefixmask.sin6_addr.s6_addr32[i] =
                    875:                                    0xffffffff;
                    876:                        plen = 128;
                    877: #else
                    878:                        return (EINVAL);
                    879: #endif
                    880:                }
                    881:        }
                    882:        /* lifetime consistency check */
                    883:        lt = &ifra->ifra_lifetime;
                    884:        if (lt->ia6t_pltime > lt->ia6t_vltime)
                    885:                return (EINVAL);
                    886:        if (lt->ia6t_vltime == 0) {
                    887:                /*
                    888:                 * the following log might be noisy, but this is a typical
                    889:                 * configuration mistake or a tool's bug.
                    890:                 */
                    891:                nd6log((LOG_INFO,
                    892:                    "in6_update_ifa: valid lifetime is 0 for %s\n",
                    893:                    ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
                    894:
                    895:                if (ia == NULL)
                    896:                        return (0); /* there's nothing to do */
                    897:        }
                    898:
                    899:        /*
                    900:         * If this is a new address, allocate a new ifaddr and link it
                    901:         * into chains.
                    902:         */
                    903:        if (ia == NULL) {
                    904:                hostIsNew = 1;
                    905:                /*
                    906:                 * When in6_update_ifa() is called in a process of a received
                    907:                 * RA, it is called under an interrupt context.  So, we should
                    908:                 * call malloc with M_NOWAIT.
                    909:                 */
                    910:                ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
                    911:                    M_NOWAIT);
                    912:                if (ia == NULL)
                    913:                        return (ENOBUFS);
                    914:                bzero((caddr_t)ia, sizeof(*ia));
                    915:                LIST_INIT(&ia->ia6_memberships);
                    916:                /* Initialize the address and masks, and put time stamp */
                    917:                ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
                    918:                ia->ia_addr.sin6_family = AF_INET6;
                    919:                ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
                    920:                ia->ia6_createtime = ia->ia6_updatetime = time_second;
                    921:                if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
                    922:                        /*
                    923:                         * XXX: some functions expect that ifa_dstaddr is not
                    924:                         * NULL for p2p interfaces.
                    925:                         */
                    926:                        ia->ia_ifa.ifa_dstaddr =
                    927:                            (struct sockaddr *)&ia->ia_dstaddr;
                    928:                } else {
                    929:                        ia->ia_ifa.ifa_dstaddr = NULL;
                    930:                }
                    931:                ia->ia_ifa.ifa_netmask =
                    932:                    (struct sockaddr *)&ia->ia_prefixmask;
                    933:
                    934:                ia->ia_ifp = ifp;
                    935:                if ((oia = in6_ifaddr) != NULL) {
                    936:                        for ( ; oia->ia_next; oia = oia->ia_next)
                    937:                                continue;
                    938:                        oia->ia_next = ia;
                    939:                } else
                    940:                        in6_ifaddr = ia;
                    941:                TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
                    942:                                  ifa_list);
                    943:        }
                    944:
                    945:        /* set prefix mask */
                    946:        if (ifra->ifra_prefixmask.sin6_len) {
                    947:                /*
                    948:                 * We prohibit changing the prefix length of an existing
                    949:                 * address, because
                    950:                 * + such an operation should be rare in IPv6, and
                    951:                 * + the operation would confuse prefix management.
                    952:                 */
                    953:                if (ia->ia_prefixmask.sin6_len &&
                    954:                    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
                    955:                        nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
                    956:                            " existing (%s) address should not be changed\n",
                    957:                            ip6_sprintf(&ia->ia_addr.sin6_addr)));
                    958:                        error = EINVAL;
                    959:                        goto unlink;
                    960:                }
                    961:                ia->ia_prefixmask = ifra->ifra_prefixmask;
                    962:        }
                    963:
                    964:        /*
                    965:         * If a new destination address is specified, scrub the old one and
                    966:         * install the new destination.  Note that the interface must be
                    967:         * p2p or loopback (see the check above.)
                    968:         */
                    969:        if (dst6.sin6_family == AF_INET6 &&
                    970:            !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
                    971:                int e;
                    972:
                    973:                if ((ia->ia_flags & IFA_ROUTE) != 0 &&
                    974:                    (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
                    975:                        nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
                    976:                            "a route to the old destination: %s\n",
                    977:                            ip6_sprintf(&ia->ia_addr.sin6_addr)));
                    978:                        /* proceed anyway... */
                    979:                } else
                    980:                        ia->ia_flags &= ~IFA_ROUTE;
                    981:                ia->ia_dstaddr = dst6;
                    982:        }
                    983:
                    984:        /*
                    985:         * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
                    986:         * to see if the address is deprecated or invalidated, but initialize
                    987:         * these members for applications.
                    988:         */
                    989:        ia->ia6_lifetime = ifra->ifra_lifetime;
                    990:        if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
                    991:                ia->ia6_lifetime.ia6t_expire =
                    992:                    time_second + ia->ia6_lifetime.ia6t_vltime;
                    993:        } else
                    994:                ia->ia6_lifetime.ia6t_expire = 0;
                    995:        if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
                    996:                ia->ia6_lifetime.ia6t_preferred =
                    997:                    time_second + ia->ia6_lifetime.ia6t_pltime;
                    998:        } else
                    999:                ia->ia6_lifetime.ia6t_preferred = 0;
                   1000:
                   1001:        /* reset the interface and routing table appropriately. */
                   1002:        if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
                   1003:                goto unlink;
                   1004:
                   1005:        /*
                   1006:         * configure address flags.
                   1007:         */
                   1008:        ia->ia6_flags = ifra->ifra_flags;
                   1009:        /*
                   1010:         * backward compatibility - if IN6_IFF_DEPRECATED is set from the
                   1011:         * userland, make it deprecated.
                   1012:         */
                   1013:        if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
                   1014:                ia->ia6_lifetime.ia6t_pltime = 0;
                   1015:                ia->ia6_lifetime.ia6t_preferred = time_second;
                   1016:        }
                   1017:        /*
                   1018:         * Make the address tentative before joining multicast addresses,
                   1019:         * so that corresponding MLD responses would not have a tentative
                   1020:         * source address.
                   1021:         */
                   1022:        ia->ia6_flags &= ~IN6_IFF_DUPLICATED;   /* safety */
                   1023:        if (hostIsNew && in6if_do_dad(ifp))
                   1024:                ia->ia6_flags |= IN6_IFF_TENTATIVE;
                   1025:
                   1026:        /*
                   1027:         * We are done if we have simply modified an existing address.
                   1028:         */
                   1029:        if (!hostIsNew)
                   1030:                return (error);
                   1031:
                   1032:        /*
                   1033:         * Beyond this point, we should call in6_purgeaddr upon an error,
                   1034:         * not just go to unlink.
                   1035:         */
                   1036:
                   1037:        /* join necessary multiast groups */
                   1038:        if ((ifp->if_flags & IFF_MULTICAST) != 0) {
                   1039:                struct sockaddr_in6 mltaddr, mltmask;
                   1040:
                   1041:                /* join solicited multicast addr for new host id */
                   1042:                struct sockaddr_in6 llsol;
                   1043:
                   1044:                bzero(&llsol, sizeof(llsol));
                   1045:                llsol.sin6_family = AF_INET6;
                   1046:                llsol.sin6_len = sizeof(llsol);
                   1047:                llsol.sin6_addr.s6_addr16[0] = htons(0xff02);
                   1048:                llsol.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
                   1049:                llsol.sin6_addr.s6_addr32[1] = 0;
                   1050:                llsol.sin6_addr.s6_addr32[2] = htonl(1);
                   1051:                llsol.sin6_addr.s6_addr32[3] =
                   1052:                    ifra->ifra_addr.sin6_addr.s6_addr32[3];
                   1053:                llsol.sin6_addr.s6_addr8[12] = 0xff;
                   1054:                imm = in6_joingroup(ifp, &llsol.sin6_addr, &error);
                   1055:                if (!imm) {
                   1056:                        nd6log((LOG_ERR, "in6_update_ifa: "
                   1057:                            "addmulti failed for %s on %s (errno=%d)\n",
                   1058:                            ip6_sprintf(&llsol.sin6_addr),
                   1059:                            ifp->if_xname, error));
                   1060:                        goto cleanup;
                   1061:                }
                   1062:                LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
                   1063:
                   1064:                bzero(&mltmask, sizeof(mltmask));
                   1065:                mltmask.sin6_len = sizeof(struct sockaddr_in6);
                   1066:                mltmask.sin6_family = AF_INET6;
                   1067:                mltmask.sin6_addr = in6mask32;
                   1068:
                   1069:                /*
                   1070:                 * join link-local all-nodes address
                   1071:                 */
                   1072:                bzero(&mltaddr, sizeof(mltaddr));
                   1073:                mltaddr.sin6_len = sizeof(struct sockaddr_in6);
                   1074:                mltaddr.sin6_family = AF_INET6;
                   1075:                mltaddr.sin6_addr = in6addr_linklocal_allnodes;
                   1076:                mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
                   1077:                mltaddr.sin6_scope_id = 0;
                   1078:
                   1079:                /*
                   1080:                 * XXX: do we really need this automatic routes?
                   1081:                 * We should probably reconsider this stuff.  Most applications
                   1082:                 * actually do not need the routes, since they usually specify
                   1083:                 * the outgoing interface.
                   1084:                 */
                   1085:                rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0);
                   1086:                if (rt) {
                   1087:                        /*
                   1088:                         * 32bit came from "mltmask"
                   1089:                         */
                   1090:                        if (memcmp(&mltaddr.sin6_addr,
                   1091:                            &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
                   1092:                            32 / 8)) {
                   1093:                                RTFREE(rt);
                   1094:                                rt = NULL;
                   1095:                        }
                   1096:                }
                   1097:                if (!rt) {
                   1098:                        struct rt_addrinfo info;
                   1099:
                   1100:                        bzero(&info, sizeof(info));
                   1101:                        info.rti_info[RTAX_DST] = (struct sockaddr *)&mltaddr;
                   1102:                        info.rti_info[RTAX_GATEWAY] =
                   1103:                            (struct sockaddr *)&ia->ia_addr;
                   1104:                        info.rti_info[RTAX_NETMASK] =
                   1105:                            (struct sockaddr *)&mltmask;
                   1106:                        info.rti_info[RTAX_IFA] =
                   1107:                            (struct sockaddr *)&ia->ia_addr;
                   1108:                        /* XXX: we need RTF_CLONING to fake nd6_rtrequest */
                   1109:                        info.rti_flags = RTF_UP | RTF_CLONING;
                   1110:                        error = rtrequest1(RTM_ADD, &info, NULL, 0);
                   1111:                        if (error)
                   1112:                                goto cleanup;
                   1113:                } else {
                   1114:                        RTFREE(rt);
                   1115:                }
                   1116:                imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
                   1117:                if (!imm) {
                   1118:                        nd6log((LOG_WARNING,
                   1119:                            "in6_update_ifa: addmulti failed for "
                   1120:                            "%s on %s (errno=%d)\n",
                   1121:                            ip6_sprintf(&mltaddr.sin6_addr),
                   1122:                            ifp->if_xname, error));
                   1123:                        goto cleanup;
                   1124:                }
                   1125:                LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
                   1126:
                   1127:                /*
                   1128:                 * join node information group address
                   1129:                 */
                   1130:                if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) == 0) {
                   1131:                        imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
                   1132:                        if (!imm) {
                   1133:                                nd6log((LOG_WARNING, "in6_update_ifa: "
                   1134:                                    "addmulti failed for %s on %s (errno=%d)\n",
                   1135:                                    ip6_sprintf(&mltaddr.sin6_addr),
                   1136:                                    ifp->if_xname, error));
                   1137:                                /* XXX not very fatal, go on... */
                   1138:                        } else {
                   1139:                                LIST_INSERT_HEAD(&ia->ia6_memberships,
                   1140:                                    imm, i6mm_chain);
                   1141:                        }
                   1142:                }
                   1143:
                   1144:                /*
                   1145:                 * join interface-local all-nodes address.
                   1146:                 * (ff01::1%ifN, and ff01::%ifN/32)
                   1147:                 */
                   1148:                bzero(&mltaddr.sin6_addr, sizeof(mltaddr.sin6_addr));
                   1149:                mltaddr.sin6_len = sizeof(struct sockaddr_in6);
                   1150:                mltaddr.sin6_family = AF_INET6;
                   1151:                mltaddr.sin6_addr = in6addr_intfacelocal_allnodes;
                   1152:                mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
                   1153:                mltaddr.sin6_scope_id = 0;
                   1154:
                   1155:                /* XXX: again, do we really need the route? */
                   1156:                rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0);
                   1157:                if (rt) {
                   1158:                        /* 32bit came from "mltmask" */
                   1159:                        if (memcmp(&mltaddr.sin6_addr,
                   1160:                            &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
                   1161:                            32 / 8)) {
                   1162:                                RTFREE(rt);
                   1163:                                rt = NULL;
                   1164:                        }
                   1165:                }
                   1166:                if (!rt) {
                   1167:                        struct rt_addrinfo info;
                   1168:
                   1169:                        bzero(&info, sizeof(info));
                   1170:                        info.rti_info[RTAX_DST] = (struct sockaddr *)&mltaddr;
                   1171:                        info.rti_info[RTAX_GATEWAY] =
                   1172:                            (struct sockaddr *)&ia->ia_addr;
                   1173:                        info.rti_info[RTAX_NETMASK] =
                   1174:                            (struct sockaddr *)&mltmask;
                   1175:                        info.rti_info[RTAX_IFA] =
                   1176:                            (struct sockaddr *)&ia->ia_addr;
                   1177:                        info.rti_flags = RTF_UP | RTF_CLONING;
                   1178:                        error = rtrequest1(RTM_ADD, &info, NULL, 0);
                   1179:                        if (error)
                   1180:                                goto cleanup;
                   1181:                } else {
                   1182:                        RTFREE(rt);
                   1183:                }
                   1184:                imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
                   1185:                if (!imm) {
                   1186:                        nd6log((LOG_WARNING, "in6_update_ifa: "
                   1187:                            "addmulti failed for %s on %s (errno=%d)\n",
                   1188:                            ip6_sprintf(&mltaddr.sin6_addr),
                   1189:                            ifp->if_xname, error));
                   1190:                        goto cleanup;
                   1191:                }
                   1192:                LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
                   1193:        }
                   1194:
                   1195:        /*
                   1196:         * Perform DAD, if needed.
                   1197:         * XXX It may be of use, if we can administratively
                   1198:         * disable DAD.
                   1199:         */
                   1200:        if (hostIsNew && in6if_do_dad(ifp) &&
                   1201:            (ifra->ifra_flags & IN6_IFF_NODAD) == 0)
                   1202:        {
                   1203:                nd6_dad_start((struct ifaddr *)ia, NULL);
                   1204:        }
                   1205:
                   1206:        return (error);
                   1207:
                   1208:   unlink:
                   1209:        /*
                   1210:         * XXX: if a change of an existing address failed, keep the entry
                   1211:         * anyway.
                   1212:         */
                   1213:        if (hostIsNew)
                   1214:                in6_unlink_ifa(ia, ifp);
                   1215:        return (error);
                   1216:
                   1217:   cleanup:
                   1218:        in6_purgeaddr(&ia->ia_ifa);
                   1219:        return error;
                   1220: }
                   1221:
                   1222: void
                   1223: in6_purgeaddr(ifa)
                   1224:        struct ifaddr *ifa;
                   1225: {
                   1226:        struct ifnet *ifp = ifa->ifa_ifp;
                   1227:        struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
                   1228:        struct in6_multi_mship *imm;
                   1229:
                   1230:        /* stop DAD processing */
                   1231:        nd6_dad_stop(ifa);
                   1232:
                   1233:        /*
                   1234:         * delete route to the destination of the address being purged.
                   1235:         * The interface must be p2p or loopback in this case.
                   1236:         */
                   1237:        if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
                   1238:                int e;
                   1239:
                   1240:                if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
                   1241:                    != 0) {
                   1242:                        log(LOG_ERR, "in6_purgeaddr: failed to remove "
                   1243:                            "a route to the p2p destination: %s on %s, "
                   1244:                            "errno=%d\n",
                   1245:                            ip6_sprintf(&ia->ia_addr.sin6_addr), ifp->if_xname,
                   1246:                            e);
                   1247:                        /* proceed anyway... */
                   1248:                } else
                   1249:                        ia->ia_flags &= ~IFA_ROUTE;
                   1250:        }
                   1251:
                   1252:        /* Remove ownaddr's loopback rtentry, if it exists. */
                   1253:        in6_ifremloop(&(ia->ia_ifa));
                   1254:
                   1255:        /*
                   1256:         * leave from multicast groups we have joined for the interface
                   1257:         */
                   1258:        while (!LIST_EMPTY(&ia->ia6_memberships)) {
                   1259:                imm = LIST_FIRST(&ia->ia6_memberships);
                   1260:                LIST_REMOVE(imm, i6mm_chain);
                   1261:                in6_leavegroup(imm);
                   1262:        }
                   1263:
                   1264:        in6_unlink_ifa(ia, ifp);
                   1265: }
                   1266:
                   1267: static void
                   1268: in6_unlink_ifa(ia, ifp)
                   1269:        struct in6_ifaddr *ia;
                   1270:        struct ifnet *ifp;
                   1271: {
                   1272:        struct in6_ifaddr *oia;
                   1273:        int     s = splnet();
                   1274:
                   1275:        TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
                   1276:
                   1277:        oia = ia;
                   1278:        if (oia == (ia = in6_ifaddr))
                   1279:                in6_ifaddr = ia->ia_next;
                   1280:        else {
                   1281:                while (ia->ia_next && (ia->ia_next != oia))
                   1282:                        ia = ia->ia_next;
                   1283:                if (ia->ia_next)
                   1284:                        ia->ia_next = oia->ia_next;
                   1285:                else {
                   1286:                        /* search failed */
                   1287:                        printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
                   1288:                }
                   1289:        }
                   1290:
                   1291:        if (!LIST_EMPTY(&oia->ia6_multiaddrs)) {
                   1292:                in6_savemkludge(oia);
                   1293:        }
                   1294:
                   1295:        /*
                   1296:         * When an autoconfigured address is being removed, release the
                   1297:         * reference to the base prefix.  Also, since the release might
                   1298:         * affect the status of other (detached) addresses, call
                   1299:         * pfxlist_onlink_check().
                   1300:         */
                   1301:        if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
                   1302:                if (oia->ia6_ndpr == NULL) {
                   1303:                        log(LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
                   1304:                            "%p has no prefix\n", oia);
                   1305:                } else {
                   1306:                        oia->ia6_ndpr->ndpr_refcnt--;
                   1307:                        oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
                   1308:                        oia->ia6_ndpr = NULL;
                   1309:                }
                   1310:
                   1311:                pfxlist_onlink_check();
                   1312:        }
                   1313:
                   1314:        /*
                   1315:         * release another refcnt for the link from in6_ifaddr.
                   1316:         * Note that we should decrement the refcnt at least once for all *BSD.
                   1317:         */
                   1318:        IFAFREE(&oia->ia_ifa);
                   1319:
                   1320:        splx(s);
                   1321: }
                   1322:
                   1323: void
                   1324: in6_purgeif(ifp)
                   1325:        struct ifnet *ifp;
                   1326: {
                   1327:        struct ifaddr *ifa, *nifa;
                   1328:
                   1329:        for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa)
                   1330:        {
                   1331:                nifa = TAILQ_NEXT(ifa, ifa_list);
                   1332:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   1333:                        continue;
                   1334:                in6_purgeaddr(ifa);
                   1335:        }
                   1336:
                   1337:        in6_ifdetach(ifp);
                   1338: }
                   1339:
                   1340: /*
                   1341:  * SIOC[GAD]LIFADDR.
                   1342:  *     SIOCGLIFADDR: get first address. (?)
                   1343:  *     SIOCGLIFADDR with IFLR_PREFIX:
                   1344:  *             get first address that matches the specified prefix.
                   1345:  *     SIOCALIFADDR: add the specified address.
                   1346:  *     SIOCALIFADDR with IFLR_PREFIX:
                   1347:  *             add the specified prefix, filling hostid part from
                   1348:  *             the first link-local address.  prefixlen must be <= 64.
                   1349:  *     SIOCDLIFADDR: delete the specified address.
                   1350:  *     SIOCDLIFADDR with IFLR_PREFIX:
                   1351:  *             delete the first address that matches the specified prefix.
                   1352:  * return values:
                   1353:  *     EINVAL on invalid parameters
                   1354:  *     EADDRNOTAVAIL on prefix match failed/specified address not found
                   1355:  *     other values may be returned from in6_ioctl()
                   1356:  *
                   1357:  * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
                   1358:  * this is to accommodate address naming scheme other than RFC2374,
                   1359:  * in the future.
                   1360:  * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
                   1361:  * address encoding scheme. (see figure on page 8)
                   1362:  */
                   1363: static int
                   1364: in6_lifaddr_ioctl(so, cmd, data, ifp, p)
                   1365:        struct socket *so;
                   1366:        u_long cmd;
                   1367:        caddr_t data;
                   1368:        struct ifnet *ifp;
                   1369:        struct proc *p;
                   1370: {
                   1371:        struct if_laddrreq *iflr = (struct if_laddrreq *)data;
                   1372:        struct ifaddr *ifa;
                   1373:        struct sockaddr *sa;
                   1374:
                   1375:        /* sanity checks */
                   1376:        if (!data || !ifp) {
                   1377:                panic("invalid argument to in6_lifaddr_ioctl");
                   1378:                /* NOTREACHED */
                   1379:        }
                   1380:
                   1381:        switch (cmd) {
                   1382:        case SIOCGLIFADDR:
                   1383:                /* address must be specified on GET with IFLR_PREFIX */
                   1384:                if ((iflr->flags & IFLR_PREFIX) == 0)
                   1385:                        break;
                   1386:                /* FALLTHROUGH */
                   1387:        case SIOCALIFADDR:
                   1388:        case SIOCDLIFADDR:
                   1389:                /* address must be specified on ADD and DELETE */
                   1390:                sa = (struct sockaddr *)&iflr->addr;
                   1391:                if (sa->sa_family != AF_INET6)
                   1392:                        return EINVAL;
                   1393:                if (sa->sa_len != sizeof(struct sockaddr_in6))
                   1394:                        return EINVAL;
                   1395:                /* XXX need improvement */
                   1396:                sa = (struct sockaddr *)&iflr->dstaddr;
                   1397:                if (sa->sa_family && sa->sa_family != AF_INET6)
                   1398:                        return EINVAL;
                   1399:                if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
                   1400:                        return EINVAL;
                   1401:                break;
                   1402:        default: /* shouldn't happen */
                   1403: #if 0
                   1404:                panic("invalid cmd to in6_lifaddr_ioctl");
                   1405:                /* NOTREACHED */
                   1406: #else
                   1407:                return EOPNOTSUPP;
                   1408: #endif
                   1409:        }
                   1410:        if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
                   1411:                return EINVAL;
                   1412:
                   1413:        switch (cmd) {
                   1414:        case SIOCALIFADDR:
                   1415:            {
                   1416:                struct in6_aliasreq ifra;
                   1417:                struct in6_addr *hostid = NULL;
                   1418:                int prefixlen;
                   1419:
                   1420:                if ((iflr->flags & IFLR_PREFIX) != 0) {
                   1421:                        struct sockaddr_in6 *sin6;
                   1422:
                   1423:                        /*
                   1424:                         * hostid is to fill in the hostid part of the
                   1425:                         * address.  hostid points to the first link-local
                   1426:                         * address attached to the interface.
                   1427:                         */
                   1428:                        ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
                   1429:                        if (!ifa)
                   1430:                                return EADDRNOTAVAIL;
                   1431:                        hostid = IFA_IN6(ifa);
                   1432:
                   1433:                        /* prefixlen must be <= 64. */
                   1434:                        if (64 < iflr->prefixlen)
                   1435:                                return EINVAL;
                   1436:                        prefixlen = iflr->prefixlen;
                   1437:
                   1438:                        /* hostid part must be zero. */
                   1439:                        sin6 = (struct sockaddr_in6 *)&iflr->addr;
                   1440:                        if (sin6->sin6_addr.s6_addr32[2] != 0
                   1441:                         || sin6->sin6_addr.s6_addr32[3] != 0) {
                   1442:                                return EINVAL;
                   1443:                        }
                   1444:                } else
                   1445:                        prefixlen = iflr->prefixlen;
                   1446:
                   1447:                /* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
                   1448:                bzero(&ifra, sizeof(ifra));
                   1449:                bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
                   1450:
                   1451:                bcopy(&iflr->addr, &ifra.ifra_addr,
                   1452:                    ((struct sockaddr *)&iflr->addr)->sa_len);
                   1453:                if (hostid) {
                   1454:                        /* fill in hostid part */
                   1455:                        ifra.ifra_addr.sin6_addr.s6_addr32[2] =
                   1456:                            hostid->s6_addr32[2];
                   1457:                        ifra.ifra_addr.sin6_addr.s6_addr32[3] =
                   1458:                            hostid->s6_addr32[3];
                   1459:                }
                   1460:
                   1461:                if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {   /*XXX*/
                   1462:                        bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
                   1463:                            ((struct sockaddr *)&iflr->dstaddr)->sa_len);
                   1464:                        if (hostid) {
                   1465:                                ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
                   1466:                                    hostid->s6_addr32[2];
                   1467:                                ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
                   1468:                                    hostid->s6_addr32[3];
                   1469:                        }
                   1470:                }
                   1471:
                   1472:                ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
                   1473:                in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
                   1474:
                   1475:                ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
                   1476:                return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, p);
                   1477:            }
                   1478:        case SIOCGLIFADDR:
                   1479:        case SIOCDLIFADDR:
                   1480:            {
                   1481:                struct in6_ifaddr *ia;
                   1482:                struct in6_addr mask, candidate, match;
                   1483:                struct sockaddr_in6 *sin6;
                   1484:                int cmp;
                   1485:
                   1486:                bzero(&mask, sizeof(mask));
                   1487:                if (iflr->flags & IFLR_PREFIX) {
                   1488:                        /* lookup a prefix rather than address. */
                   1489:                        in6_prefixlen2mask(&mask, iflr->prefixlen);
                   1490:
                   1491:                        sin6 = (struct sockaddr_in6 *)&iflr->addr;
                   1492:                        bcopy(&sin6->sin6_addr, &match, sizeof(match));
                   1493:                        match.s6_addr32[0] &= mask.s6_addr32[0];
                   1494:                        match.s6_addr32[1] &= mask.s6_addr32[1];
                   1495:                        match.s6_addr32[2] &= mask.s6_addr32[2];
                   1496:                        match.s6_addr32[3] &= mask.s6_addr32[3];
                   1497:
                   1498:                        /* if you set extra bits, that's wrong */
                   1499:                        if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
                   1500:                                return EINVAL;
                   1501:
                   1502:                        cmp = 1;
                   1503:                } else {
                   1504:                        if (cmd == SIOCGLIFADDR) {
                   1505:                                /* on getting an address, take the 1st match */
                   1506:                                cmp = 0;        /* XXX */
                   1507:                        } else {
                   1508:                                /* on deleting an address, do exact match */
                   1509:                                in6_prefixlen2mask(&mask, 128);
                   1510:                                sin6 = (struct sockaddr_in6 *)&iflr->addr;
                   1511:                                bcopy(&sin6->sin6_addr, &match, sizeof(match));
                   1512:
                   1513:                                cmp = 1;
                   1514:                        }
                   1515:                }
                   1516:
                   1517:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1518:                        if (ifa->ifa_addr->sa_family != AF_INET6)
                   1519:                                continue;
                   1520:                        if (!cmp)
                   1521:                                break;
                   1522:
                   1523:                        bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
                   1524:                        candidate.s6_addr32[0] &= mask.s6_addr32[0];
                   1525:                        candidate.s6_addr32[1] &= mask.s6_addr32[1];
                   1526:                        candidate.s6_addr32[2] &= mask.s6_addr32[2];
                   1527:                        candidate.s6_addr32[3] &= mask.s6_addr32[3];
                   1528:                        if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
                   1529:                                break;
                   1530:                }
                   1531:                if (!ifa)
                   1532:                        return EADDRNOTAVAIL;
                   1533:                ia = ifa2ia6(ifa);
                   1534:
                   1535:                if (cmd == SIOCGLIFADDR) {
                   1536:                        /* fill in the if_laddrreq structure */
                   1537:                        bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
                   1538:                        if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
                   1539:                                bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
                   1540:                                    ia->ia_dstaddr.sin6_len);
                   1541:                        } else
                   1542:                                bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
                   1543:
                   1544:                        iflr->prefixlen =
                   1545:                            in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
                   1546:
                   1547:                        iflr->flags = ia->ia6_flags;    /*XXX*/
                   1548:
                   1549:                        return 0;
                   1550:                } else {
                   1551:                        struct in6_aliasreq ifra;
                   1552:
                   1553:                        /* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
                   1554:                        bzero(&ifra, sizeof(ifra));
                   1555:                        bcopy(iflr->iflr_name, ifra.ifra_name,
                   1556:                            sizeof(ifra.ifra_name));
                   1557:
                   1558:                        bcopy(&ia->ia_addr, &ifra.ifra_addr,
                   1559:                            ia->ia_addr.sin6_len);
                   1560:                        if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
                   1561:                                bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
                   1562:                                    ia->ia_dstaddr.sin6_len);
                   1563:                        } else {
                   1564:                                bzero(&ifra.ifra_dstaddr,
                   1565:                                    sizeof(ifra.ifra_dstaddr));
                   1566:                        }
                   1567:                        bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
                   1568:                            ia->ia_prefixmask.sin6_len);
                   1569:
                   1570:                        ifra.ifra_flags = ia->ia6_flags;
                   1571:                        return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
                   1572:                            ifp, p);
                   1573:                }
                   1574:            }
                   1575:        }
                   1576:
                   1577:        return EOPNOTSUPP;      /* just for safety */
                   1578: }
                   1579:
                   1580: /*
                   1581:  * Initialize an interface's intetnet6 address
                   1582:  * and routing table entry.
                   1583:  */
                   1584: static int
                   1585: in6_ifinit(ifp, ia, sin6, newhost)
                   1586:        struct ifnet *ifp;
                   1587:        struct in6_ifaddr *ia;
                   1588:        struct sockaddr_in6 *sin6;
                   1589:        int newhost;
                   1590: {
                   1591:        int     error = 0, plen, ifacount = 0;
                   1592:        int     s = splnet();
                   1593:        struct ifaddr *ifa;
                   1594:
                   1595:        /*
                   1596:         * Give the interface a chance to initialize
                   1597:         * if this is its first address (or it is a CARP interface)
                   1598:         * and to validate the address if necessary.
                   1599:         */
                   1600:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1601:                if (ifa->ifa_addr == NULL)
                   1602:                        continue;       /* just for safety */
                   1603:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   1604:                        continue;
                   1605:                ifacount++;
                   1606:        }
                   1607:
                   1608:        ia->ia_addr = *sin6;
                   1609:
                   1610:        if ((ifacount <= 1 || ifp->if_type == IFT_CARP) && ifp->if_ioctl &&
                   1611:            (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
                   1612:                splx(s);
                   1613:                return (error);
                   1614:        }
                   1615:        splx(s);
                   1616:
                   1617:        ia->ia_ifa.ifa_metric = ifp->if_metric;
                   1618:
                   1619:        /* we could do in(6)_socktrim here, but just omit it at this moment. */
                   1620:
                   1621:        /*
                   1622:         * Special case:
                   1623:         * If the destination address is specified for a point-to-point
                   1624:         * interface, install a route to the destination as an interface
                   1625:         * direct route.
                   1626:         */
                   1627:        plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
                   1628:        if (plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) {
                   1629:                if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
                   1630:                                    RTF_UP | RTF_HOST)) != 0)
                   1631:                        return (error);
                   1632:                ia->ia_flags |= IFA_ROUTE;
                   1633:        }
                   1634:
                   1635:        /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
                   1636:        if (newhost) {
                   1637:                /* set the rtrequest function to create llinfo */
                   1638:                ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
                   1639:                in6_ifaddloop(&(ia->ia_ifa));
                   1640:        }
                   1641:
                   1642:        if (ifp->if_flags & IFF_MULTICAST)
                   1643:                in6_restoremkludge(ia, ifp);
                   1644:
                   1645:        return (error);
                   1646: }
                   1647:
                   1648: /*
                   1649:  * Multicast address kludge:
                   1650:  * If there were any multicast addresses attached to this interface address,
                   1651:  * either move them to another address on this interface, or save them until
                   1652:  * such time as this interface is reconfigured for IPv6.
                   1653:  */
                   1654: void
                   1655: in6_savemkludge(oia)
                   1656:        struct in6_ifaddr *oia;
                   1657: {
                   1658:        struct in6_ifaddr *ia;
                   1659:        struct in6_multi *in6m, *next;
                   1660:
                   1661:        IFP_TO_IA6(oia->ia_ifp, ia);
                   1662:        if (ia) {       /* there is another address */
                   1663:                for (in6m = LIST_FIRST(&oia->ia6_multiaddrs);
                   1664:                    in6m != LIST_END(&oia->ia6_multiaddrs); in6m = next) {
                   1665:                        next = LIST_NEXT(in6m, in6m_entry);
                   1666:                        IFAFREE(&in6m->in6m_ia->ia_ifa);
                   1667:                        ia->ia_ifa.ifa_refcnt++;
                   1668:                        in6m->in6m_ia = ia;
                   1669:                        LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
                   1670:                }
                   1671:        } else {        /* last address on this if deleted, save */
                   1672:                struct multi6_kludge *mk;
                   1673:
                   1674:                LIST_FOREACH(mk, &in6_mk, mk_entry) {
                   1675:                        if (mk->mk_ifp == oia->ia_ifp)
                   1676:                                break;
                   1677:                }
                   1678:                if (mk == NULL) /* this should not happen! */
                   1679:                        panic("in6_savemkludge: no kludge space");
                   1680:
                   1681:                for (in6m = LIST_FIRST(&oia->ia6_multiaddrs);
                   1682:                    in6m != LIST_END(&oia->ia6_multiaddrs); in6m = next) {
                   1683:                        next = LIST_NEXT(in6m, in6m_entry);
                   1684:                        IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
                   1685:                        in6m->in6m_ia = NULL;
                   1686:                        LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
                   1687:                }
                   1688:        }
                   1689: }
                   1690:
                   1691: /*
                   1692:  * Continuation of multicast address hack:
                   1693:  * If there was a multicast group list previously saved for this interface,
                   1694:  * then we re-attach it to the first address configured on the i/f.
                   1695:  */
                   1696: void
                   1697: in6_restoremkludge(ia, ifp)
                   1698:        struct in6_ifaddr *ia;
                   1699:        struct ifnet *ifp;
                   1700: {
                   1701:        struct multi6_kludge *mk;
                   1702:
                   1703:        LIST_FOREACH(mk, &in6_mk, mk_entry) {
                   1704:                if (mk->mk_ifp == ifp) {
                   1705:                        struct in6_multi *in6m, *next;
                   1706:
                   1707:                        for (in6m = LIST_FIRST(&mk->mk_head);
                   1708:                            in6m != LIST_END(&mk->mk_head);
                   1709:                            in6m = next) {
                   1710:                                next = LIST_NEXT(in6m, in6m_entry);
                   1711:                                in6m->in6m_ia = ia;
                   1712:                                ia->ia_ifa.ifa_refcnt++;
                   1713:                                LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
                   1714:                                                 in6m, in6m_entry);
                   1715:                        }
                   1716:                        LIST_INIT(&mk->mk_head);
                   1717:                        break;
                   1718:                }
                   1719:        }
                   1720: }
                   1721:
                   1722: /*
                   1723:  * Allocate space for the kludge at interface initialization time.
                   1724:  * Formerly, we dynamically allocated the space in in6_savemkludge() with
                   1725:  * malloc(M_WAITOK).  However, it was wrong since the function could be called
                   1726:  * under an interrupt context (software timer on address lifetime expiration).
                   1727:  * Also, we cannot just give up allocating the strucutre, since the group
                   1728:  * membership structure is very complex and we need to keep it anyway.
                   1729:  * Of course, this function MUST NOT be called under an interrupt context.
                   1730:  * Specifically, it is expected to be called only from in6_ifattach(), though
                   1731:  * it is a global function.
                   1732:  */
                   1733: void
                   1734: in6_createmkludge(ifp)
                   1735:        struct ifnet *ifp;
                   1736: {
                   1737:        struct multi6_kludge *mk;
                   1738:
                   1739:        LIST_FOREACH(mk, &in6_mk, mk_entry) {
                   1740:                /* If we've already had one, do not allocate. */
                   1741:                if (mk->mk_ifp == ifp)
                   1742:                        return;
                   1743:        }
                   1744:
                   1745:        mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK);
                   1746:
                   1747:        bzero(mk, sizeof(*mk));
                   1748:        LIST_INIT(&mk->mk_head);
                   1749:        mk->mk_ifp = ifp;
                   1750:        LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
                   1751: }
                   1752:
                   1753: void
                   1754: in6_purgemkludge(ifp)
                   1755:        struct ifnet *ifp;
                   1756: {
                   1757:        struct multi6_kludge *mk;
                   1758:        struct in6_multi *in6m;
                   1759:
                   1760:        LIST_FOREACH(mk, &in6_mk, mk_entry) {
                   1761:                if (mk->mk_ifp != ifp)
                   1762:                        continue;
                   1763:
                   1764:                /* leave from all multicast groups joined */
                   1765:                while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL)
                   1766:                        in6_delmulti(in6m);
                   1767:                LIST_REMOVE(mk, mk_entry);
                   1768:                free(mk, M_IPMADDR);
                   1769:                break;
                   1770:        }
                   1771: }
                   1772:
                   1773: /*
                   1774:  * Add an address to the list of IP6 multicast addresses for a
                   1775:  * given interface.
                   1776:  */
                   1777: struct in6_multi *
                   1778: in6_addmulti(maddr6, ifp, errorp)
                   1779:        struct in6_addr *maddr6;
                   1780:        struct ifnet *ifp;
                   1781:        int *errorp;
                   1782: {
                   1783:        struct  in6_ifaddr *ia;
                   1784:        struct  in6_ifreq ifr;
                   1785:        struct  in6_multi *in6m;
                   1786:        int     s = splsoftnet();
                   1787:
                   1788:        *errorp = 0;
                   1789:        /*
                   1790:         * See if address already in list.
                   1791:         */
                   1792:        IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
                   1793:        if (in6m != NULL) {
                   1794:                /*
                   1795:                 * Found it; just increment the refrence count.
                   1796:                 */
                   1797:                in6m->in6m_refcount++;
                   1798:        } else {
                   1799:                /*
                   1800:                 * New address; allocate a new multicast record
                   1801:                 * and link it into the interface's multicast list.
                   1802:                 */
                   1803:                in6m = (struct in6_multi *)
                   1804:                        malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
                   1805:                if (in6m == NULL) {
                   1806:                        splx(s);
                   1807:                        *errorp = ENOBUFS;
                   1808:                        return (NULL);
                   1809:                }
                   1810:                in6m->in6m_addr = *maddr6;
                   1811:                in6m->in6m_ifp = ifp;
                   1812:                in6m->in6m_refcount = 1;
                   1813:                IFP_TO_IA6(ifp, ia);
                   1814:                if (ia == NULL) {
                   1815:                        free(in6m, M_IPMADDR);
                   1816:                        splx(s);
                   1817:                        *errorp = EADDRNOTAVAIL; /* appropriate? */
                   1818:                        return (NULL);
                   1819:                }
                   1820:                in6m->in6m_ia = ia;
                   1821:                ia->ia_ifa.ifa_refcnt++; /* gain a reference */
                   1822:                LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
                   1823:
                   1824:                /*
                   1825:                 * Ask the network driver to update its multicast reception
                   1826:                 * filter appropriately for the new address.
                   1827:                 */
                   1828:                bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
                   1829:                ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
                   1830:                ifr.ifr_addr.sin6_family = AF_INET6;
                   1831:                ifr.ifr_addr.sin6_addr = *maddr6;
                   1832:                if (ifp->if_ioctl == NULL)
                   1833:                        *errorp = ENXIO; /* XXX: appropriate? */
                   1834:                else
                   1835:                        *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,
                   1836:                            (caddr_t)&ifr);
                   1837:                if (*errorp) {
                   1838:                        LIST_REMOVE(in6m, in6m_entry);
                   1839:                        free(in6m, M_IPMADDR);
                   1840:                        IFAFREE(&ia->ia_ifa);
                   1841:                        splx(s);
                   1842:                        return (NULL);
                   1843:                }
                   1844:                /*
                   1845:                 * Let MLD6 know that we have joined a new IP6 multicast
                   1846:                 * group.
                   1847:                 */
                   1848:                mld6_start_listening(in6m);
                   1849:        }
                   1850:        splx(s);
                   1851:        return (in6m);
                   1852: }
                   1853:
                   1854: /*
                   1855:  * Delete a multicast address record.
                   1856:  */
                   1857: void
                   1858: in6_delmulti(in6m)
                   1859:        struct in6_multi *in6m;
                   1860: {
                   1861:        struct  in6_ifreq ifr;
                   1862:        int     s = splsoftnet();
                   1863:
                   1864:        if (--in6m->in6m_refcount == 0) {
                   1865:                /*
                   1866:                 * No remaining claims to this record; let MLD6 know
                   1867:                 * that we are leaving the multicast group.
                   1868:                 */
                   1869:                mld6_stop_listening(in6m);
                   1870:
                   1871:                /*
                   1872:                 * Unlink from list.
                   1873:                 */
                   1874:                LIST_REMOVE(in6m, in6m_entry);
                   1875:                if (in6m->in6m_ia) {
                   1876:                        IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
                   1877:                }
                   1878:
                   1879:                /*
                   1880:                 * Notify the network driver to update its multicast
                   1881:                 * reception filter.
                   1882:                 */
                   1883:                bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
                   1884:                ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
                   1885:                ifr.ifr_addr.sin6_family = AF_INET6;
                   1886:                ifr.ifr_addr.sin6_addr = in6m->in6m_addr;
                   1887:                (*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,
                   1888:                                            SIOCDELMULTI, (caddr_t)&ifr);
                   1889:                free(in6m, M_IPMADDR);
                   1890:        }
                   1891:        splx(s);
                   1892: }
                   1893:
                   1894: struct in6_multi_mship *
                   1895: in6_joingroup(ifp, addr, errorp)
                   1896:        struct ifnet *ifp;
                   1897:        struct in6_addr *addr;
                   1898:        int *errorp;
                   1899: {
                   1900:        struct in6_multi_mship *imm;
                   1901:
                   1902:        imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);
                   1903:        if (!imm) {
                   1904:                *errorp = ENOBUFS;
                   1905:                return NULL;
                   1906:        }
                   1907:        imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);
                   1908:        if (!imm->i6mm_maddr) {
                   1909:                /* *errorp is alrady set */
                   1910:                free(imm, M_IPMADDR);
                   1911:                return NULL;
                   1912:        }
                   1913:        return imm;
                   1914: }
                   1915:
                   1916: int
                   1917: in6_leavegroup(imm)
                   1918:        struct in6_multi_mship *imm;
                   1919: {
                   1920:
                   1921:        if (imm->i6mm_maddr)
                   1922:                in6_delmulti(imm->i6mm_maddr);
                   1923:        free(imm,  M_IPMADDR);
                   1924:        return 0;
                   1925: }
                   1926:
                   1927: /*
                   1928:  * Find an IPv6 interface link-local address specific to an interface.
                   1929:  */
                   1930: struct in6_ifaddr *
                   1931: in6ifa_ifpforlinklocal(ifp, ignoreflags)
                   1932:        struct ifnet *ifp;
                   1933:        int ignoreflags;
                   1934: {
                   1935:        struct ifaddr *ifa;
                   1936:
                   1937:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1938:                if (ifa->ifa_addr == NULL)
                   1939:                        continue;       /* just for safety */
                   1940:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   1941:                        continue;
                   1942:                if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
                   1943:                        if ((((struct in6_ifaddr *)ifa)->ia6_flags &
                   1944:                             ignoreflags) != 0)
                   1945:                                continue;
                   1946:                        break;
                   1947:                }
                   1948:        }
                   1949:
                   1950:        return ((struct in6_ifaddr *)ifa);
                   1951: }
                   1952:
                   1953:
                   1954: /*
                   1955:  * find the internet address corresponding to a given interface and address.
                   1956:  */
                   1957: struct in6_ifaddr *
                   1958: in6ifa_ifpwithaddr(ifp, addr)
                   1959:        struct ifnet *ifp;
                   1960:        struct in6_addr *addr;
                   1961: {
                   1962:        struct ifaddr *ifa;
                   1963:
                   1964:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   1965:                if (ifa->ifa_addr == NULL)
                   1966:                        continue;       /* just for safety */
                   1967:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   1968:                        continue;
                   1969:                if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
                   1970:                        break;
                   1971:        }
                   1972:
                   1973:        return ((struct in6_ifaddr *)ifa);
                   1974: }
                   1975:
                   1976: /*
                   1977:  * Convert IP6 address to printable (loggable) representation.
                   1978:  */
                   1979: static char digits[] = "0123456789abcdef";
                   1980: static int ip6round = 0;
                   1981: char *
                   1982: ip6_sprintf(addr)
                   1983:        struct in6_addr *addr;
                   1984: {
                   1985:        static char ip6buf[8][48];
                   1986:        int i;
                   1987:        char *cp;
                   1988:        u_short *a = (u_short *)addr;
                   1989:        u_char *d;
                   1990:        int dcolon = 0;
                   1991:
                   1992:        ip6round = (ip6round + 1) & 7;
                   1993:        cp = ip6buf[ip6round];
                   1994:
                   1995:        for (i = 0; i < 8; i++) {
                   1996:                if (dcolon == 1) {
                   1997:                        if (*a == 0) {
                   1998:                                if (i == 7)
                   1999:                                        *cp++ = ':';
                   2000:                                a++;
                   2001:                                continue;
                   2002:                        } else
                   2003:                                dcolon = 2;
                   2004:                }
                   2005:                if (*a == 0) {
                   2006:                        if (dcolon == 0 && *(a + 1) == 0) {
                   2007:                                if (i == 0)
                   2008:                                        *cp++ = ':';
                   2009:                                *cp++ = ':';
                   2010:                                dcolon = 1;
                   2011:                        } else {
                   2012:                                *cp++ = '0';
                   2013:                                *cp++ = ':';
                   2014:                        }
                   2015:                        a++;
                   2016:                        continue;
                   2017:                }
                   2018:                d = (u_char *)a;
                   2019:                *cp++ = digits[*d >> 4];
                   2020:                *cp++ = digits[*d++ & 0xf];
                   2021:                *cp++ = digits[*d >> 4];
                   2022:                *cp++ = digits[*d & 0xf];
                   2023:                *cp++ = ':';
                   2024:                a++;
                   2025:        }
                   2026:        *--cp = 0;
                   2027:        return (ip6buf[ip6round]);
                   2028: }
                   2029:
                   2030: /*
                   2031:  * Get a scope of the address. Node-local, link-local, site-local or global.
                   2032:  */
                   2033: int
                   2034: in6_addrscope (addr)
                   2035: struct in6_addr *addr;
                   2036: {
                   2037:        int scope;
                   2038:
                   2039:        if (addr->s6_addr8[0] == 0xfe) {
                   2040:                scope = addr->s6_addr8[1] & 0xc0;
                   2041:
                   2042:                switch (scope) {
                   2043:                case 0x80:
                   2044:                        return IPV6_ADDR_SCOPE_LINKLOCAL;
                   2045:                        break;
                   2046:                case 0xc0:
                   2047:                        return IPV6_ADDR_SCOPE_SITELOCAL;
                   2048:                        break;
                   2049:                default:
                   2050:                        return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
                   2051:                        break;
                   2052:                }
                   2053:        }
                   2054:
                   2055:
                   2056:        if (addr->s6_addr8[0] == 0xff) {
                   2057:                scope = addr->s6_addr8[1] & 0x0f;
                   2058:
                   2059:                /*
                   2060:                 * due to other scope such as reserved,
                   2061:                 * return scope doesn't work.
                   2062:                 */
                   2063:                switch (scope) {
                   2064:                case IPV6_ADDR_SCOPE_INTFACELOCAL:
                   2065:                        return IPV6_ADDR_SCOPE_INTFACELOCAL;
                   2066:                        break;
                   2067:                case IPV6_ADDR_SCOPE_LINKLOCAL:
                   2068:                        return IPV6_ADDR_SCOPE_LINKLOCAL;
                   2069:                        break;
                   2070:                case IPV6_ADDR_SCOPE_SITELOCAL:
                   2071:                        return IPV6_ADDR_SCOPE_SITELOCAL;
                   2072:                        break;
                   2073:                default:
                   2074:                        return IPV6_ADDR_SCOPE_GLOBAL;
                   2075:                        break;
                   2076:                }
                   2077:        }
                   2078:
                   2079:        if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
                   2080:                if (addr->s6_addr8[15] == 1) /* loopback */
                   2081:                        return IPV6_ADDR_SCOPE_INTFACELOCAL;
                   2082:                if (addr->s6_addr8[15] == 0) /* unspecified */
                   2083:                        return IPV6_ADDR_SCOPE_LINKLOCAL;
                   2084:        }
                   2085:
                   2086:        return IPV6_ADDR_SCOPE_GLOBAL;
                   2087: }
                   2088:
                   2089: int
                   2090: in6_addr2scopeid(ifp, addr)
                   2091:        struct ifnet *ifp;      /* must not be NULL */
                   2092:        struct in6_addr *addr;  /* must not be NULL */
                   2093: {
                   2094:        int scope = in6_addrscope(addr);
                   2095:
                   2096:        switch(scope) {
                   2097:        case IPV6_ADDR_SCOPE_INTFACELOCAL:
                   2098:        case IPV6_ADDR_SCOPE_LINKLOCAL:
                   2099:                /* XXX: we do not distinguish between a link and an I/F. */
                   2100:                return (ifp->if_index);
                   2101:
                   2102:        case IPV6_ADDR_SCOPE_SITELOCAL:
                   2103:                return (0);     /* XXX: invalid. */
                   2104:
                   2105:        default:
                   2106:                return (0);     /* XXX: treat as global. */
                   2107:        }
                   2108: }
                   2109:
                   2110: int
                   2111: in6_is_addr_deprecated(sa6)
                   2112:        struct sockaddr_in6 *sa6;
                   2113: {
                   2114:        struct in6_ifaddr *ia;
                   2115:
                   2116:        for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
                   2117:                if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
                   2118:                    &sa6->sin6_addr) &&
                   2119:                    (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
                   2120:                        return (1); /* true */
                   2121:
                   2122:                /* XXX: do we still have to go thru the rest of the list? */
                   2123:        }
                   2124:
                   2125:        return (0);             /* false */
                   2126: }
                   2127:
                   2128: /*
                   2129:  * return length of part which dst and src are equal
                   2130:  * hard coding...
                   2131:  */
                   2132: int
                   2133: in6_matchlen(src, dst)
                   2134: struct in6_addr *src, *dst;
                   2135: {
                   2136:        int match = 0;
                   2137:        u_char *s = (u_char *)src, *d = (u_char *)dst;
                   2138:        u_char *lim = s + 16, r;
                   2139:
                   2140:        while (s < lim)
                   2141:                if ((r = (*d++ ^ *s++)) != 0) {
                   2142:                        while (r < 128) {
                   2143:                                match++;
                   2144:                                r <<= 1;
                   2145:                        }
                   2146:                        break;
                   2147:                } else
                   2148:                        match += 8;
                   2149:        return match;
                   2150: }
                   2151:
                   2152: int
                   2153: in6_are_prefix_equal(p1, p2, len)
                   2154:        struct in6_addr *p1, *p2;
                   2155:        int len;
                   2156: {
                   2157:        int bytelen, bitlen;
                   2158:
                   2159:        /* sanity check */
                   2160:        if (0 > len || len > 128) {
                   2161:                log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
                   2162:                    len);
                   2163:                return (0);
                   2164:        }
                   2165:
                   2166:        bytelen = len / 8;
                   2167:        bitlen = len % 8;
                   2168:
                   2169:        if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
                   2170:                return (0);
                   2171:        /* len == 128 is ok because bitlen == 0 then */
                   2172:        if (bitlen != 0 &&
                   2173:            p1->s6_addr[bytelen] >> (8 - bitlen) !=
                   2174:            p2->s6_addr[bytelen] >> (8 - bitlen))
                   2175:                return (0);
                   2176:
                   2177:        return (1);
                   2178: }
                   2179:
                   2180: void
                   2181: in6_prefixlen2mask(maskp, len)
                   2182:        struct in6_addr *maskp;
                   2183:        int len;
                   2184: {
                   2185:        u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
                   2186:        int bytelen, bitlen, i;
                   2187:
                   2188:        /* sanity check */
                   2189:        if (0 > len || len > 128) {
                   2190:                log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
                   2191:                    len);
                   2192:                return;
                   2193:        }
                   2194:
                   2195:        bzero(maskp, sizeof(*maskp));
                   2196:        bytelen = len / 8;
                   2197:        bitlen = len % 8;
                   2198:        for (i = 0; i < bytelen; i++)
                   2199:                maskp->s6_addr[i] = 0xff;
                   2200:        /* len == 128 is ok because bitlen == 0 then */
                   2201:        if (bitlen)
                   2202:                maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
                   2203: }
                   2204:
                   2205: /*
                   2206:  * return the best address out of the same scope
                   2207:  */
                   2208: struct in6_ifaddr *
                   2209: in6_ifawithscope(oifp, dst)
                   2210:        struct ifnet *oifp;
                   2211:        struct in6_addr *dst;
                   2212: {
                   2213:        int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0;
                   2214:        int blen = -1;
                   2215:        struct ifaddr *ifa;
                   2216:        struct ifnet *ifp;
                   2217:        struct in6_ifaddr *ifa_best = NULL;
                   2218:
                   2219:        if (oifp == NULL) {
                   2220:                printf("in6_ifawithscope: output interface is not specified\n");
                   2221:                return (NULL);
                   2222:        }
                   2223:
                   2224:        /*
                   2225:         * We search for all addresses on all interfaces from the beginning.
                   2226:         * Comparing an interface with the outgoing interface will be done
                   2227:         * only at the final stage of tiebreaking.
                   2228:         */
                   2229:        for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
                   2230:        {
                   2231:                /*
                   2232:                 * We can never take an address that breaks the scope zone
                   2233:                 * of the destination.
                   2234:                 */
                   2235:                if (in6_addr2scopeid(ifp, dst) != in6_addr2scopeid(oifp, dst))
                   2236:                        continue;
                   2237:
                   2238:                TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   2239:                        int tlen = -1, dscopecmp, bscopecmp, matchcmp;
                   2240:
                   2241:                        if (ifa->ifa_addr->sa_family != AF_INET6)
                   2242:                                continue;
                   2243:
                   2244:                        src_scope = in6_addrscope(IFA_IN6(ifa));
                   2245:
                   2246: #ifdef ADDRSELECT_DEBUG                /* should be removed after stabilization */
                   2247:                        dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
                   2248:                        printf("in6_ifawithscope: dst=%s bestaddr=%s, "
                   2249:                               "newaddr=%s, scope=%x, dcmp=%d, bcmp=%d, "
                   2250:                               "matchlen=%d, flgs=%x\n",
                   2251:                               ip6_sprintf(dst),
                   2252:                               ifa_best ? ip6_sprintf(&ifa_best->ia_addr.sin6_addr) : "none",
                   2253:                               ip6_sprintf(IFA_IN6(ifa)), src_scope,
                   2254:                               dscopecmp,
                   2255:                               ifa_best ? IN6_ARE_SCOPE_CMP(src_scope, best_scope) : -1,
                   2256:                               in6_matchlen(IFA_IN6(ifa), dst),
                   2257:                               ((struct in6_ifaddr *)ifa)->ia6_flags);
                   2258: #endif
                   2259:
                   2260:                        /*
                   2261:                         * Don't use an address before completing DAD
                   2262:                         * nor a duplicated address.
                   2263:                         */
                   2264:                        if (((struct in6_ifaddr *)ifa)->ia6_flags &
                   2265:                            IN6_IFF_NOTREADY)
                   2266:                                continue;
                   2267:
                   2268:                        /* XXX: is there any case to allow anycasts? */
                   2269:                        if (((struct in6_ifaddr *)ifa)->ia6_flags &
                   2270:                            IN6_IFF_ANYCAST)
                   2271:                                continue;
                   2272:
                   2273:                        if (((struct in6_ifaddr *)ifa)->ia6_flags &
                   2274:                            IN6_IFF_DETACHED)
                   2275:                                continue;
                   2276:
                   2277:                        /*
                   2278:                         * If this is the first address we find,
                   2279:                         * keep it anyway.
                   2280:                         */
                   2281:                        if (ifa_best == NULL)
                   2282:                                goto replace;
                   2283:
                   2284:                        /*
                   2285:                         * ifa_best is never NULL beyond this line except
                   2286:                         * within the block labeled "replace".
                   2287:                         */
                   2288:
                   2289:                        /*
                   2290:                         * If ifa_best has a smaller scope than dst and
                   2291:                         * the current address has a larger one than
                   2292:                         * (or equal to) dst, always replace ifa_best.
                   2293:                         * Also, if the current address has a smaller scope
                   2294:                         * than dst, ignore it unless ifa_best also has a
                   2295:                         * smaller scope.
                   2296:                         */
                   2297:                        if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0 &&
                   2298:                            IN6_ARE_SCOPE_CMP(src_scope, dst_scope) >= 0)
                   2299:                                goto replace;
                   2300:                        if (IN6_ARE_SCOPE_CMP(src_scope, dst_scope) < 0 &&
                   2301:                            IN6_ARE_SCOPE_CMP(best_scope, dst_scope) >= 0)
                   2302:                                continue;
                   2303:
                   2304:                        /*
                   2305:                         * A deprecated address SHOULD NOT be used in new
                   2306:                         * communications if an alternate (non-deprecated)
                   2307:                         * address is available and has sufficient scope.
                   2308:                         * RFC 2462, Section 5.5.4.
                   2309:                         */
                   2310:                        if (((struct in6_ifaddr *)ifa)->ia6_flags &
                   2311:                            IN6_IFF_DEPRECATED) {
                   2312:                                /*
                   2313:                                 * Ignore any deprecated addresses if
                   2314:                                 * specified by configuration.
                   2315:                                 */
                   2316:                                if (!ip6_use_deprecated)
                   2317:                                        continue;
                   2318:
                   2319:                                /*
                   2320:                                 * If we have already found a non-deprecated
                   2321:                                 * candidate, just ignore deprecated addresses.
                   2322:                                 */
                   2323:                                if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED)
                   2324:                                    == 0)
                   2325:                                        continue;
                   2326:                        }
                   2327:
                   2328:                        /*
                   2329:                         * A non-deprecated address is always preferred
                   2330:                         * to a deprecated one regardless of scopes and
                   2331:                         * address matching.
                   2332:                         */
                   2333:                        if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) &&
                   2334:                            (((struct in6_ifaddr *)ifa)->ia6_flags &
                   2335:                             IN6_IFF_DEPRECATED) == 0)
                   2336:                                goto replace;
                   2337:
                   2338:                        /*
                   2339:                         * At this point, we have two cases:
                   2340:                         * 1. we are looking at a non-deprecated address,
                   2341:                         *    and ifa_best is also non-deprecated.
                   2342:                         * 2. we are looking at a deprecated address,
                   2343:                         *    and ifa_best is also deprecated.
                   2344:                         * Also, we do not have to consider a case where
                   2345:                         * the scope of if_best is larger(smaller) than dst and
                   2346:                         * the scope of the current address is smaller(larger)
                   2347:                         * than dst. Such a case has already been covered.
                   2348:                         * Tiebreaking is done according to the following
                   2349:                         * items:
                   2350:                         * - the scope comparison between the address and
                   2351:                         *   dst (dscopecmp)
                   2352:                         * - the scope comparison between the address and
                   2353:                         *   ifa_best (bscopecmp)
                   2354:                         * - if the address match dst longer than ifa_best
                   2355:                         *   (matchcmp)
                   2356:                         * - if the address is on the outgoing I/F (outI/F)
                   2357:                         *
                   2358:                         * Roughly speaking, the selection policy is
                   2359:                         * - the most important item is scope. The same scope
                   2360:                         *   is best. Then search for a larger scope.
                   2361:                         *   Smaller scopes are the last resort.
                   2362:                         * - A deprecated address is chosen only when we have
                   2363:                         *   no address that has an enough scope, but is
                   2364:                         *   prefered to any addresses of smaller scopes.
                   2365:                         * - Longest address match against dst is considered
                   2366:                         *   only for addresses that has the same scope of dst.
                   2367:                         * - If there is no other reasons to choose one,
                   2368:                         *   addresses on the outgoing I/F are preferred.
                   2369:                         *
                   2370:                         * The precise decision table is as follows:
                   2371:                         * dscopecmp bscopecmp matchcmp outI/F | replace?
                   2372:                         *    !equal     equal      N/A    Yes |      Yes (1)
                   2373:                         *    !equal     equal      N/A     No |       No (2)
                   2374:                         *    larger    larger      N/A    N/A |       No (3)
                   2375:                         *    larger   smaller      N/A    N/A |      Yes (4)
                   2376:                         *   smaller    larger      N/A    N/A |      Yes (5)
                   2377:                         *   smaller   smaller      N/A    N/A |       No (6)
                   2378:                         *     equal   smaller      N/A    N/A |      Yes (7)
                   2379:                         *     equal    larger       (already done)
                   2380:                         *     equal     equal   larger    N/A |      Yes (8)
                   2381:                         *     equal     equal  smaller    N/A |       No (9)
                   2382:                         *     equal     equal    equal    Yes |      Yes (a)
                   2383:                         *     eaual     eqaul    equal     No |       No (b)
                   2384:                         */
                   2385:                        dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
                   2386:                        bscopecmp = IN6_ARE_SCOPE_CMP(src_scope, best_scope);
                   2387:
                   2388:                        if (dscopecmp && bscopecmp == 0) {
                   2389:                                if (oifp == ifp) /* (1) */
                   2390:                                        goto replace;
                   2391:                                continue; /* (2) */
                   2392:                        }
                   2393:                        if (dscopecmp > 0) {
                   2394:                                if (bscopecmp > 0) /* (3) */
                   2395:                                        continue;
                   2396:                                goto replace; /* (4) */
                   2397:                        }
                   2398:                        if (dscopecmp < 0) {
                   2399:                                if (bscopecmp > 0) /* (5) */
                   2400:                                        goto replace;
                   2401:                                continue; /* (6) */
                   2402:                        }
                   2403:
                   2404:                        /* now dscopecmp must be 0 */
                   2405:                        if (bscopecmp < 0)
                   2406:                                goto replace; /* (7) */
                   2407:
                   2408:                        /*
                   2409:                         * At last both dscopecmp and bscopecmp must be 0.
                   2410:                         * We need address matching against dst for
                   2411:                         * tiebreaking.
                   2412:                         */
                   2413:                        tlen = in6_matchlen(IFA_IN6(ifa), dst);
                   2414:                        matchcmp = tlen - blen;
                   2415:                        if (matchcmp > 0) /* (8) */
                   2416:                                goto replace;
                   2417:                        if (matchcmp < 0) /* (9) */
                   2418:                                continue;
                   2419:                        if (oifp == ifp) /* (a) */
                   2420:                                goto replace;
                   2421:                        continue; /* (b) */
                   2422:
                   2423:                  replace:
                   2424:                        ifa_best = (struct in6_ifaddr *)ifa;
                   2425:                        blen = tlen >= 0 ? tlen :
                   2426:                                in6_matchlen(IFA_IN6(ifa), dst);
                   2427:                        best_scope = in6_addrscope(&ifa_best->ia_addr.sin6_addr);
                   2428:                }
                   2429:        }
                   2430:
                   2431:        /* count statistics for future improvements */
                   2432:        if (ifa_best == NULL)
                   2433:                ip6stat.ip6s_sources_none++;
                   2434:        else {
                   2435:                if (oifp == ifa_best->ia_ifp)
                   2436:                        ip6stat.ip6s_sources_sameif[best_scope]++;
                   2437:                else
                   2438:                        ip6stat.ip6s_sources_otherif[best_scope]++;
                   2439:
                   2440:                if (best_scope == dst_scope)
                   2441:                        ip6stat.ip6s_sources_samescope[best_scope]++;
                   2442:                else
                   2443:                        ip6stat.ip6s_sources_otherscope[best_scope]++;
                   2444:
                   2445:                if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
                   2446:                        ip6stat.ip6s_sources_deprecated[best_scope]++;
                   2447:        }
                   2448:
                   2449:        return (ifa_best);
                   2450: }
                   2451:
                   2452: /*
                   2453:  * return the best address out of the same scope. if no address was
                   2454:  * found, return the first valid address from designated IF.
                   2455:  */
                   2456: struct in6_ifaddr *
                   2457: in6_ifawithifp(ifp, dst)
                   2458:        struct ifnet *ifp;
                   2459:        struct in6_addr *dst;
                   2460: {
                   2461:        int dst_scope = in6_addrscope(dst), blen = -1, tlen;
                   2462:        struct ifaddr *ifa;
                   2463:        struct in6_ifaddr *besta = 0;
                   2464:        struct in6_ifaddr *dep[2];      /*last-resort: deprecated*/
                   2465:
                   2466:        dep[0] = dep[1] = NULL;
                   2467:
                   2468:        /*
                   2469:         * We first look for addresses in the same scope.
                   2470:         * If there is one, return it.
                   2471:         * If two or more, return one which matches the dst longest.
                   2472:         * If none, return one of global addresses assigned other ifs.
                   2473:         */
                   2474:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   2475:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   2476:                        continue;
                   2477:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
                   2478:                        continue; /* XXX: is there any case to allow anycast? */
                   2479:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
                   2480:                        continue; /* don't use this interface */
                   2481:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
                   2482:                        continue;
                   2483:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
                   2484:                        if (ip6_use_deprecated)
                   2485:                                dep[0] = (struct in6_ifaddr *)ifa;
                   2486:                        continue;
                   2487:                }
                   2488:
                   2489:                if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
                   2490:                        /*
                   2491:                         * call in6_matchlen() as few as possible
                   2492:                         */
                   2493:                        if (besta) {
                   2494:                                if (blen == -1)
                   2495:                                        blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
                   2496:                                tlen = in6_matchlen(IFA_IN6(ifa), dst);
                   2497:                                if (tlen > blen) {
                   2498:                                        blen = tlen;
                   2499:                                        besta = (struct in6_ifaddr *)ifa;
                   2500:                                }
                   2501:                        } else
                   2502:                                besta = (struct in6_ifaddr *)ifa;
                   2503:                }
                   2504:        }
                   2505:        if (besta)
                   2506:                return (besta);
                   2507:
                   2508:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   2509:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   2510:                        continue;
                   2511:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
                   2512:                        continue; /* XXX: is there any case to allow anycast? */
                   2513:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
                   2514:                        continue; /* don't use this interface */
                   2515:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
                   2516:                        continue;
                   2517:                if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
                   2518:                        if (ip6_use_deprecated)
                   2519:                                dep[1] = (struct in6_ifaddr *)ifa;
                   2520:                        continue;
                   2521:                }
                   2522:
                   2523:                return (struct in6_ifaddr *)ifa;
                   2524:        }
                   2525:
                   2526:        /* use the last-resort values, that are, deprecated addresses */
                   2527:        if (dep[0])
                   2528:                return dep[0];
                   2529:        if (dep[1])
                   2530:                return dep[1];
                   2531:
                   2532:        return NULL;
                   2533: }
                   2534:
                   2535: /*
                   2536:  * perform DAD when interface becomes IFF_UP.
                   2537:  */
                   2538: void
                   2539: in6_if_up(ifp)
                   2540:        struct ifnet *ifp;
                   2541: {
                   2542:        struct ifaddr *ifa;
                   2543:        struct in6_ifaddr *ia;
                   2544:        int dad_delay;          /* delay ticks before DAD output */
                   2545:
                   2546:        /*
                   2547:         * special cases, like 6to4, are handled in in6_ifattach
                   2548:         */
                   2549:        in6_ifattach(ifp, NULL);
                   2550:
                   2551:        dad_delay = 0;
                   2552:        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
                   2553:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   2554:                        continue;
                   2555:                ia = (struct in6_ifaddr *)ifa;
                   2556:                if (ia->ia6_flags & IN6_IFF_TENTATIVE)
                   2557:                        nd6_dad_start(ifa, &dad_delay);
                   2558:        }
                   2559: }
                   2560:
                   2561: int
                   2562: in6if_do_dad(ifp)
                   2563:        struct ifnet *ifp;
                   2564: {
                   2565:        if ((ifp->if_flags & IFF_LOOPBACK) != 0)
                   2566:                return (0);
                   2567:
                   2568:        switch (ifp->if_type) {
                   2569:        case IFT_FAITH:
                   2570:                /*
                   2571:                 * These interfaces do not have the IFF_LOOPBACK flag,
                   2572:                 * but loop packets back.  We do not have to do DAD on such
                   2573:                 * interfaces.  We should even omit it, because loop-backed
                   2574:                 * NS would confuse the DAD procedure.
                   2575:                 */
                   2576:                return (0);
                   2577:        default:
                   2578:                /*
                   2579:                 * Our DAD routine requires the interface up and running.
                   2580:                 * However, some interfaces can be up before the RUNNING
                   2581:                 * status.  Additionaly, users may try to assign addresses
                   2582:                 * before the interface becomes up (or running).
                   2583:                 * We simply skip DAD in such a case as a work around.
                   2584:                 * XXX: we should rather mark "tentative" on such addresses,
                   2585:                 * and do DAD after the interface becomes ready.
                   2586:                 */
                   2587:                if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
                   2588:                    (IFF_UP|IFF_RUNNING))
                   2589:                        return (0);
                   2590:
                   2591:                return (1);
                   2592:        }
                   2593: }
                   2594:
                   2595: /*
                   2596:  * Calculate max IPv6 MTU through all the interfaces and store it
                   2597:  * to in6_maxmtu.
                   2598:  */
                   2599: void
                   2600: in6_setmaxmtu()
                   2601: {
                   2602:        unsigned long maxmtu = 0;
                   2603:        struct ifnet *ifp;
                   2604:
                   2605:        for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
                   2606:        {
                   2607:                /* this function can be called during ifnet initialization */
                   2608:                if (!ifp->if_afdata[AF_INET6])
                   2609:                        continue;
                   2610:                if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
                   2611:                    IN6_LINKMTU(ifp) > maxmtu)
                   2612:                        maxmtu = IN6_LINKMTU(ifp);
                   2613:        }
                   2614:        if (maxmtu)          /* update only when maxmtu is positive */
                   2615:                in6_maxmtu = maxmtu;
                   2616: }
                   2617:
                   2618: void *
                   2619: in6_domifattach(ifp)
                   2620:        struct ifnet *ifp;
                   2621: {
                   2622:        struct in6_ifextra *ext;
                   2623:
                   2624:        ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
                   2625:        bzero(ext, sizeof(*ext));
                   2626:
                   2627:        ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
                   2628:            M_IFADDR, M_WAITOK);
                   2629:        bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
                   2630:
                   2631:        ext->icmp6_ifstat =
                   2632:            (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
                   2633:            M_IFADDR, M_WAITOK);
                   2634:        bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
                   2635:
                   2636:        ext->nd_ifinfo = nd6_ifattach(ifp);
                   2637:        return ext;
                   2638: }
                   2639:
                   2640: void
                   2641: in6_domifdetach(ifp, aux)
                   2642:        struct ifnet *ifp;
                   2643:        void *aux;
                   2644: {
                   2645:        struct in6_ifextra *ext = (struct in6_ifextra *)aux;
                   2646:
                   2647:        nd6_ifdetach(ext->nd_ifinfo);
                   2648:        free(ext->in6_ifstat, M_IFADDR);
                   2649:        free(ext->icmp6_ifstat, M_IFADDR);
                   2650:        free(ext, M_IFADDR);
                   2651: }

CVSweb