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

Annotation of src/sys/netinet6/nd6.c, Revision 1.130

1.130   ! dyoung      1: /*     $NetBSD: nd6.c,v 1.129 2008/10/24 16:54:18 dyoung Exp $ */
1.65      itojun      2: /*     $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $   */
1.4       thorpej     3:
1.2       itojun      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
1.25      itojun      7:  *
1.2       itojun      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the project nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
1.25      itojun     19:  *
1.2       itojun     20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
1.55      lukem      33: #include <sys/cdefs.h>
1.130   ! dyoung     34: __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.129 2008/10/24 16:54:18 dyoung Exp $");
1.87      itojun     35:
                     36: #include "opt_ipsec.h"
1.2       itojun     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
1.20      thorpej    40: #include <sys/callout.h>
1.2       itojun     41: #include <sys/malloc.h>
                     42: #include <sys/mbuf.h>
                     43: #include <sys/socket.h>
1.126     ad         44: #include <sys/socketvar.h>
1.2       itojun     45: #include <sys/sockio.h>
                     46: #include <sys/time.h>
                     47: #include <sys/kernel.h>
1.18      itojun     48: #include <sys/protosw.h>
1.2       itojun     49: #include <sys/errno.h>
                     50: #include <sys/ioctl.h>
                     51: #include <sys/syslog.h>
                     52: #include <sys/queue.h>
                     53:
                     54: #include <net/if.h>
                     55: #include <net/if_dl.h>
                     56: #include <net/if_types.h>
                     57: #include <net/route.h>
1.62      itojun     58: #include <net/if_ether.h>
                     59: #include <net/if_fddi.h>
                     60: #include <net/if_arc.h>
1.2       itojun     61:
                     62: #include <netinet/in.h>
                     63: #include <netinet6/in6_var.h>
1.17      itojun     64: #include <netinet/ip6.h>
1.2       itojun     65: #include <netinet6/ip6_var.h>
1.96      rpaulo     66: #include <netinet6/scope6_var.h>
1.2       itojun     67: #include <netinet6/nd6.h>
1.17      itojun     68: #include <netinet/icmp6.h>
1.125     thorpej    69: #include <netinet6/icmp6_private.h>
1.87      itojun     70:
                     71: #ifdef IPSEC
                     72: #include <netinet6/ipsec.h>
                     73: #endif
1.2       itojun     74:
1.12      itojun     75: #include <net/net_osdep.h>
                     76:
1.2       itojun     77: #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */
                     78: #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */
                     79:
                     80: /* timer values */
                     81: int    nd6_prune       = 1;    /* walk list every 1 seconds */
                     82: int    nd6_delay       = 5;    /* delay first probe time 5 second */
                     83: int    nd6_umaxtries   = 3;    /* maximum unicast query */
                     84: int    nd6_mmaxtries   = 3;    /* maximum multicast query */
                     85: int    nd6_useloopback = 1;    /* use loopback interface for local traffic */
1.42      itojun     86: int    nd6_gctimer     = (60 * 60 * 24); /* 1 day: garbage collection timer */
1.2       itojun     87:
1.12      itojun     88: /* preventing too many loops in ND option parsing */
                     89: int nd6_maxndopt = 10; /* max # of ND options allowed */
                     90:
1.31      itojun     91: int nd6_maxnudhint = 0;        /* max # of subsequent upper layer hints */
                     92:
1.99      rpaulo     93: int nd6_maxqueuelen = 1; /* max # of packets cached in unresolved ND entries */
                     94:
1.36      itojun     95: #ifdef ND6_DEBUG
                     96: int nd6_debug = 1;
                     97: #else
                     98: int nd6_debug = 0;
                     99: #endif
                    100:
1.2       itojun    101: /* for debugging? */
                    102: static int nd6_inuse, nd6_allocated;
                    103:
1.104     christos  104: struct llinfo_nd6 llinfo_nd6 = {
                    105:        .ln_prev = &llinfo_nd6,
                    106:        .ln_next = &llinfo_nd6,
                    107: };
1.12      itojun    108: struct nd_drhead nd_defrouter;
1.2       itojun    109: struct nd_prhead nd_prefix = { 0 };
                    110:
                    111: int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;
1.122     dyoung    112: static const struct sockaddr_in6 all1_sa = {
                    113:          .sin6_family = AF_INET6
                    114:        , .sin6_len = sizeof(struct sockaddr_in6)
                    115:        , .sin6_addr = {.s6_addr = {0xff, 0xff, 0xff, 0xff,
                    116:                                    0xff, 0xff, 0xff, 0xff,
                    117:                                    0xff, 0xff, 0xff, 0xff,
                    118:                                    0xff, 0xff, 0xff, 0xff}}
                    119: };
1.2       itojun    120:
1.121     dyoung    121: static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
                    122: static void nd6_slowtimo(void *);
                    123: static int regen_tmpaddr(struct in6_ifaddr *);
                    124: static struct llinfo_nd6 *nd6_free(struct rtentry *, int);
                    125: static void nd6_llinfo_timer(void *);
                    126: static void clear_llinfo_pqueue(struct llinfo_nd6 *);
1.2       itojun    127:
1.116     ad        128: callout_t nd6_slowtimo_ch;
                    129: callout_t nd6_timer_ch;
                    130: extern callout_t in6_tmpaddrtimer_ch;
1.20      thorpej   131:
1.121     dyoung    132: static int fill_drlist(void *, size_t *, size_t);
                    133: static int fill_prlist(void *, size_t *, size_t);
1.79      thorpej   134:
                    135: MALLOC_DEFINE(M_IP6NDP, "NDP", "IPv6 Neighbour Discovery");
1.65      itojun    136:
1.2       itojun    137: void
1.112     dyoung    138: nd6_init(void)
1.2       itojun    139: {
                    140:        static int nd6_init_done = 0;
                    141:
                    142:        if (nd6_init_done) {
                    143:                log(LOG_NOTICE, "nd6_init called more than once(ignored)\n");
                    144:                return;
                    145:        }
1.12      itojun    146:
                    147:        /* initialization of the default router list */
                    148:        TAILQ_INIT(&nd_defrouter);
                    149:
1.2       itojun    150:        nd6_init_done = 1;
                    151:
1.126     ad        152:        callout_init(&nd6_slowtimo_ch, CALLOUT_MPSAFE);
                    153:        callout_init(&nd6_timer_ch, CALLOUT_MPSAFE);
1.116     ad        154:
1.2       itojun    155:        /* start timer */
1.20      thorpej   156:        callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
                    157:            nd6_slowtimo, NULL);
1.2       itojun    158: }
                    159:
1.58      itojun    160: struct nd_ifinfo *
1.112     dyoung    161: nd6_ifattach(struct ifnet *ifp)
1.2       itojun    162: {
1.58      itojun    163:        struct nd_ifinfo *nd;
1.2       itojun    164:
1.58      itojun    165:        nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK);
1.129     dyoung    166:        memset(nd, 0, sizeof(*nd));
1.2       itojun    167:
1.58      itojun    168:        nd->initialized = 1;
1.2       itojun    169:
1.58      itojun    170:        nd->chlim = IPV6_DEFHLIM;
                    171:        nd->basereachable = REACHABLE_TIME;
                    172:        nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
                    173:        nd->retrans = RETRANS_TIMER;
1.65      itojun    174:        /*
                    175:         * Note that the default value of ip6_accept_rtadv is 0, which means
                    176:         * we won't accept RAs by default even if we set ND6_IFF_ACCEPT_RTADV
                    177:         * here.
                    178:         */
                    179:        nd->flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);
1.61      itojun    180:
                    181:        /* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
                    182:        nd6_setmtu0(ifp, nd);
1.2       itojun    183:
1.58      itojun    184:        return nd;
                    185: }
1.21      itojun    186:
1.58      itojun    187: void
1.112     dyoung    188: nd6_ifdetach(struct nd_ifinfo *nd)
1.58      itojun    189: {
1.21      itojun    190:
1.58      itojun    191:        free(nd, M_IP6NDP);
1.2       itojun    192: }
                    193:
                    194: void
1.112     dyoung    195: nd6_setmtu(struct ifnet *ifp)
1.61      itojun    196: {
                    197:        nd6_setmtu0(ifp, ND_IFINFO(ifp));
                    198: }
                    199:
                    200: void
1.112     dyoung    201: nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi)
1.2       itojun    202: {
1.61      itojun    203:        u_int32_t omaxmtu;
                    204:
                    205:        omaxmtu = ndi->maxmtu;
1.2       itojun    206:
1.40      itojun    207:        switch (ifp->if_type) {
1.62      itojun    208:        case IFT_ARCNET:
                    209:                ndi->maxmtu = MIN(ARC_PHDS_MAXMTU, ifp->if_mtu); /* RFC2497 */
1.39      itojun    210:                break;
1.58      itojun    211:        case IFT_FDDI:
                    212:                ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu);
                    213:                break;
1.39      itojun    214:        default:
                    215:                ndi->maxmtu = ifp->if_mtu;
                    216:                break;
1.2       itojun    217:        }
                    218:
1.61      itojun    219:        /*
                    220:         * Decreasing the interface MTU under IPV6 minimum MTU may cause
                    221:         * undesirable situation.  We thus notify the operator of the change
                    222:         * explicitly.  The check for omaxmtu is necessary to restrict the
1.63      itojun    223:         * log to the case of changing the MTU, not initializing it.
1.61      itojun    224:         */
                    225:        if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) {
1.81      christos  226:                log(LOG_NOTICE, "nd6_setmtu0: new link MTU on %s (%lu) is too"
                    227:                    " small for IPv6 which needs %lu\n",
                    228:                    if_name(ifp), (unsigned long)ndi->maxmtu, (unsigned long)
                    229:                    IPV6_MMTU);
1.2       itojun    230:        }
1.58      itojun    231:
                    232:        if (ndi->maxmtu > in6_maxmtu)
                    233:                in6_setmaxmtu(); /* check all interfaces just in case */
1.2       itojun    234: }
                    235:
                    236: void
1.112     dyoung    237: nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts)
1.2       itojun    238: {
1.58      itojun    239:
1.129     dyoung    240:        memset(ndopts, 0, sizeof(*ndopts));
1.2       itojun    241:        ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
                    242:        ndopts->nd_opts_last
                    243:                = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
                    244:
                    245:        if (icmp6len == 0) {
                    246:                ndopts->nd_opts_done = 1;
                    247:                ndopts->nd_opts_search = NULL;
                    248:        }
                    249: }
                    250:
                    251: /*
                    252:  * Take one ND option.
                    253:  */
                    254: struct nd_opt_hdr *
1.112     dyoung    255: nd6_option(union nd_opts *ndopts)
1.2       itojun    256: {
                    257:        struct nd_opt_hdr *nd_opt;
                    258:        int olen;
                    259:
1.99      rpaulo    260:        if (ndopts == NULL)
1.76      provos    261:                panic("ndopts == NULL in nd6_option");
1.99      rpaulo    262:        if (ndopts->nd_opts_last == NULL)
1.76      provos    263:                panic("uninitialized ndopts in nd6_option");
1.99      rpaulo    264:        if (ndopts->nd_opts_search == NULL)
1.2       itojun    265:                return NULL;
                    266:        if (ndopts->nd_opts_done)
                    267:                return NULL;
                    268:
                    269:        nd_opt = ndopts->nd_opts_search;
                    270:
1.40      itojun    271:        /* make sure nd_opt_len is inside the buffer */
1.111     christos  272:        if ((void *)&nd_opt->nd_opt_len >= (void *)ndopts->nd_opts_last) {
1.129     dyoung    273:                memset(ndopts, 0, sizeof(*ndopts));
1.40      itojun    274:                return NULL;
                    275:        }
                    276:
1.2       itojun    277:        olen = nd_opt->nd_opt_len << 3;
                    278:        if (olen == 0) {
                    279:                /*
                    280:                 * Message validation requires that all included
                    281:                 * options have a length that is greater than zero.
                    282:                 */
1.129     dyoung    283:                memset(ndopts, 0, sizeof(*ndopts));
1.2       itojun    284:                return NULL;
                    285:        }
                    286:
1.111     christos  287:        ndopts->nd_opts_search = (struct nd_opt_hdr *)((char *)nd_opt + olen);
1.40      itojun    288:        if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
                    289:                /* option overruns the end of buffer, invalid */
1.129     dyoung    290:                memset(ndopts, 0, sizeof(*ndopts));
1.40      itojun    291:                return NULL;
                    292:        } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
                    293:                /* reached the end of options chain */
1.2       itojun    294:                ndopts->nd_opts_done = 1;
                    295:                ndopts->nd_opts_search = NULL;
                    296:        }
                    297:        return nd_opt;
                    298: }
                    299:
                    300: /*
                    301:  * Parse multiple ND options.
                    302:  * This function is much easier to use, for ND routines that do not need
                    303:  * multiple options of the same type.
                    304:  */
                    305: int
1.112     dyoung    306: nd6_options(union nd_opts *ndopts)
1.2       itojun    307: {
                    308:        struct nd_opt_hdr *nd_opt;
                    309:        int i = 0;
                    310:
1.99      rpaulo    311:        if (ndopts == NULL)
1.76      provos    312:                panic("ndopts == NULL in nd6_options");
1.99      rpaulo    313:        if (ndopts->nd_opts_last == NULL)
1.76      provos    314:                panic("uninitialized ndopts in nd6_options");
1.99      rpaulo    315:        if (ndopts->nd_opts_search == NULL)
1.2       itojun    316:                return 0;
1.99      rpaulo    317:
1.2       itojun    318:        while (1) {
                    319:                nd_opt = nd6_option(ndopts);
1.99      rpaulo    320:                if (nd_opt == NULL && ndopts->nd_opts_last == NULL) {
1.2       itojun    321:                        /*
                    322:                         * Message validation requires that all included
                    323:                         * options have a length that is greater than zero.
                    324:                         */
1.125     thorpej   325:                        ICMP6_STATINC(ICMP6_STAT_ND_BADOPT);
1.129     dyoung    326:                        memset(ndopts, 0, sizeof(*ndopts));
1.2       itojun    327:                        return -1;
                    328:                }
                    329:
1.99      rpaulo    330:                if (nd_opt == NULL)
1.2       itojun    331:                        goto skip1;
                    332:
                    333:                switch (nd_opt->nd_opt_type) {
                    334:                case ND_OPT_SOURCE_LINKADDR:
                    335:                case ND_OPT_TARGET_LINKADDR:
                    336:                case ND_OPT_MTU:
                    337:                case ND_OPT_REDIRECTED_HEADER:
                    338:                        if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
1.36      itojun    339:                                nd6log((LOG_INFO,
                    340:                                    "duplicated ND6 option found (type=%d)\n",
                    341:                                    nd_opt->nd_opt_type));
1.2       itojun    342:                                /* XXX bark? */
                    343:                        } else {
                    344:                                ndopts->nd_opt_array[nd_opt->nd_opt_type]
                    345:                                        = nd_opt;
                    346:                        }
                    347:                        break;
                    348:                case ND_OPT_PREFIX_INFORMATION:
                    349:                        if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
                    350:                                ndopts->nd_opt_array[nd_opt->nd_opt_type]
                    351:                                        = nd_opt;
                    352:                        }
                    353:                        ndopts->nd_opts_pi_end =
                    354:                                (struct nd_opt_prefix_info *)nd_opt;
                    355:                        break;
                    356:                default:
                    357:                        /*
                    358:                         * Unknown options must be silently ignored,
1.109     christos  359:                         * to accommodate future extension to the protocol.
1.2       itojun    360:                         */
1.36      itojun    361:                        nd6log((LOG_DEBUG,
1.2       itojun    362:                            "nd6_options: unsupported option %d - "
1.36      itojun    363:                            "option ignored\n", nd_opt->nd_opt_type));
1.2       itojun    364:                }
                    365:
                    366: skip1:
                    367:                i++;
1.12      itojun    368:                if (i > nd6_maxndopt) {
1.125     thorpej   369:                        ICMP6_STATINC(ICMP6_STAT_ND_TOOMANYOPT);
1.36      itojun    370:                        nd6log((LOG_INFO, "too many loop in nd opt\n"));
1.2       itojun    371:                        break;
                    372:                }
                    373:
                    374:                if (ndopts->nd_opts_done)
                    375:                        break;
                    376:        }
                    377:
                    378:        return 0;
                    379: }
                    380:
                    381: /*
1.86      itojun    382:  * ND6 timer routine to handle ND6 entries
1.2       itojun    383:  */
                    384: void
1.112     dyoung    385: nd6_llinfo_settimer(struct llinfo_nd6 *ln, long xtick)
1.86      itojun    386: {
                    387:        int s;
                    388:
                    389:        s = splsoftnet();
                    390:
1.94      christos  391:        if (xtick < 0) {
1.86      itojun    392:                ln->ln_expire = 0;
                    393:                ln->ln_ntick = 0;
                    394:                callout_stop(&ln->ln_timer_ch);
                    395:        } else {
1.103     kardel    396:                ln->ln_expire = time_second + xtick / hz;
1.94      christos  397:                if (xtick > INT_MAX) {
                    398:                        ln->ln_ntick = xtick - INT_MAX;
1.86      itojun    399:                        callout_reset(&ln->ln_timer_ch, INT_MAX,
                    400:                            nd6_llinfo_timer, ln);
                    401:                } else {
                    402:                        ln->ln_ntick = 0;
1.94      christos  403:                        callout_reset(&ln->ln_timer_ch, xtick,
1.86      itojun    404:                            nd6_llinfo_timer, ln);
                    405:                }
                    406:        }
                    407:
                    408:        splx(s);
                    409: }
                    410:
                    411: static void
1.112     dyoung    412: nd6_llinfo_timer(void *arg)
1.2       itojun    413: {
1.38      itojun    414:        struct llinfo_nd6 *ln;
1.86      itojun    415:        struct rtentry *rt;
                    416:        const struct sockaddr_in6 *dst;
1.65      itojun    417:        struct ifnet *ifp;
1.86      itojun    418:        struct nd_ifinfo *ndi = NULL;
1.63      itojun    419:
1.126     ad        420:        mutex_enter(softnet_lock);
                    421:        KERNEL_LOCK(1, NULL);
1.2       itojun    422:
1.86      itojun    423:        ln = (struct llinfo_nd6 *)arg;
                    424:
                    425:        if (ln->ln_ntick > 0) {
1.97      dyoung    426:                nd6_llinfo_settimer(ln, ln->ln_ntick);
1.126     ad        427:                KERNEL_UNLOCK_ONE(NULL);
                    428:                mutex_exit(softnet_lock);
1.86      itojun    429:                return;
                    430:        }
                    431:
                    432:        if ((rt = ln->ln_rt) == NULL)
                    433:                panic("ln->ln_rt == NULL");
                    434:        if ((ifp = rt->rt_ifp) == NULL)
                    435:                panic("ln->ln_rt->rt_ifp == NULL");
                    436:        ndi = ND_IFINFO(ifp);
1.117     dyoung    437:        dst = satocsin6(rt_getkey(rt));
1.86      itojun    438:
                    439:        /* sanity check */
                    440:        if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
                    441:                panic("rt_llinfo(%p) is not equal to ln(%p)",
                    442:                      rt->rt_llinfo, ln);
                    443:        if (!dst)
                    444:                panic("dst=0 in nd6_timer(ln=%p)", ln);
                    445:
                    446:        switch (ln->ln_state) {
                    447:        case ND6_LLINFO_INCOMPLETE:
                    448:                if (ln->ln_asked < nd6_mmaxtries) {
                    449:                        ln->ln_asked++;
                    450:                        nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
                    451:                        nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
                    452:                } else {
                    453:                        struct mbuf *m = ln->ln_hold;
                    454:                        if (m) {
1.100     rpaulo    455:                                struct mbuf *m0;
                    456:
1.86      itojun    457:                                /*
1.96      rpaulo    458:                                 * assuming every packet in ln_hold has
                    459:                                 * the same IP header
1.86      itojun    460:                                 */
1.100     rpaulo    461:                                m0 = m->m_nextpkt;
                    462:                                m->m_nextpkt = NULL;
1.96      rpaulo    463:                                icmp6_error2(m, ICMP6_DST_UNREACH,
                    464:                                    ICMP6_DST_UNREACH_ADDR, 0, rt->rt_ifp);
1.100     rpaulo    465:
                    466:                                ln->ln_hold = m0;
                    467:                                clear_llinfo_pqueue(ln);
                    468:                        }
1.86      itojun    469:                        (void)nd6_free(rt, 0);
                    470:                        ln = NULL;
1.2       itojun    471:                }
1.86      itojun    472:                break;
                    473:        case ND6_LLINFO_REACHABLE:
                    474:                if (!ND6_LLINFO_PERMANENT(ln)) {
                    475:                        ln->ln_state = ND6_LLINFO_STALE;
                    476:                        nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.2       itojun    477:                }
1.86      itojun    478:                break;
1.2       itojun    479:
1.86      itojun    480:        case ND6_LLINFO_STALE:
                    481:                /* Garbage Collection(RFC 2461 5.3) */
                    482:                if (!ND6_LLINFO_PERMANENT(ln)) {
                    483:                        (void)nd6_free(rt, 1);
                    484:                        ln = NULL;
1.2       itojun    485:                }
1.86      itojun    486:                break;
1.54      itojun    487:
1.86      itojun    488:        case ND6_LLINFO_DELAY:
                    489:                if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
                    490:                        /* We need NUD */
                    491:                        ln->ln_asked = 1;
                    492:                        ln->ln_state = ND6_LLINFO_PROBE;
                    493:                        nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
                    494:                        nd6_ns_output(ifp, &dst->sin6_addr,
                    495:                            &dst->sin6_addr, ln, 0);
                    496:                } else {
                    497:                        ln->ln_state = ND6_LLINFO_STALE; /* XXX */
                    498:                        nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
                    499:                }
                    500:                break;
                    501:        case ND6_LLINFO_PROBE:
                    502:                if (ln->ln_asked < nd6_umaxtries) {
                    503:                        ln->ln_asked++;
                    504:                        nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
                    505:                        nd6_ns_output(ifp, &dst->sin6_addr,
                    506:                            &dst->sin6_addr, ln, 0);
                    507:                } else {
                    508:                        (void)nd6_free(rt, 0);
                    509:                        ln = NULL;
                    510:                }
                    511:                break;
                    512:        }
1.65      itojun    513:
1.126     ad        514:        KERNEL_UNLOCK_ONE(NULL);
                    515:        mutex_exit(softnet_lock);
1.86      itojun    516: }
1.42      itojun    517:
1.86      itojun    518: /*
                    519:  * ND6 timer routine to expire default route list and prefix list
                    520:  */
                    521: void
1.107     christos  522: nd6_timer(void *ignored_arg)
1.86      itojun    523: {
1.108     dyoung    524:        struct nd_defrouter *next_dr, *dr;
                    525:        struct nd_prefix *next_pr, *pr;
1.86      itojun    526:        struct in6_ifaddr *ia6, *nia6;
1.99      rpaulo    527:        struct in6_addrlifetime *lt6;
1.42      itojun    528:
1.86      itojun    529:        callout_reset(&nd6_timer_ch, nd6_prune * hz,
                    530:            nd6_timer, NULL);
1.63      itojun    531:
1.126     ad        532:        mutex_enter(softnet_lock);
                    533:        KERNEL_LOCK(1, NULL);
                    534:
1.43      itojun    535:        /* expire default router list */
1.108     dyoung    536:
                    537:        for (dr = TAILQ_FIRST(&nd_defrouter); dr != NULL; dr = next_dr) {
                    538:                next_dr = TAILQ_NEXT(dr, dr_entry);
1.103     kardel    539:                if (dr->expire && dr->expire < time_second) {
1.2       itojun    540:                        defrtrlist_del(dr);
1.31      itojun    541:                }
1.2       itojun    542:        }
                    543:
1.65      itojun    544:        /*
                    545:         * expire interface addresses.
                    546:         * in the past the loop was inside prefix expiry processing.
                    547:         * However, from a stricter speci-confrmance standpoint, we should
                    548:         * rather separate address lifetimes and prefix lifetimes.
                    549:         */
1.99      rpaulo    550:   addrloop:
1.65      itojun    551:        for (ia6 = in6_ifaddr; ia6; ia6 = nia6) {
                    552:                nia6 = ia6->ia_next;
                    553:                /* check address lifetime */
1.99      rpaulo    554:                lt6 = &ia6->ia6_lifetime;
1.65      itojun    555:                if (IFA6_IS_INVALID(ia6)) {
1.99      rpaulo    556:                        int regen = 0;
                    557:
                    558:                        /*
                    559:                         * If the expiring address is temporary, try
                    560:                         * regenerating a new one.  This would be useful when
                    561:                         * we suspended a laptop PC, then turned it on after a
                    562:                         * period that could invalidate all temporary
                    563:                         * addresses.  Although we may have to restart the
                    564:                         * loop (see below), it must be after purging the
                    565:                         * address.  Otherwise, we'd see an infinite loop of
                    566:                         * regeneration.
                    567:                         */
                    568:                        if (ip6_use_tempaddr &&
                    569:                            (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
                    570:                                if (regen_tmpaddr(ia6) == 0)
                    571:                                        regen = 1;
                    572:                        }
                    573:
                    574:                        in6_purgeaddr(&ia6->ia_ifa);
                    575:
                    576:                        if (regen)
                    577:                                goto addrloop; /* XXX: see below */
                    578:                } else if (IFA6_IS_DEPRECATED(ia6)) {
                    579:                        int oldflags = ia6->ia6_flags;
                    580:
                    581:                        ia6->ia6_flags |= IN6_IFF_DEPRECATED;
                    582:
                    583:                        /*
                    584:                         * If a temporary address has just become deprecated,
                    585:                         * regenerate a new one if possible.
                    586:                         */
                    587:                        if (ip6_use_tempaddr &&
                    588:                            (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
                    589:                            (oldflags & IN6_IFF_DEPRECATED) == 0) {
                    590:
                    591:                                if (regen_tmpaddr(ia6) == 0) {
                    592:                                        /*
                    593:                                         * A new temporary address is
                    594:                                         * generated.
                    595:                                         * XXX: this means the address chain
                    596:                                         * has changed while we are still in
                    597:                                         * the loop.  Although the change
                    598:                                         * would not cause disaster (because
                    599:                                         * it's not a deletion, but an
                    600:                                         * addition,) we'd rather restart the
                    601:                                         * loop just for safety.  Or does this
                    602:                                         * significantly reduce performance??
                    603:                                         */
                    604:                                        goto addrloop;
                    605:                                }
                    606:                        }
1.65      itojun    607:                } else {
                    608:                        /*
                    609:                         * A new RA might have made a deprecated address
                    610:                         * preferred.
                    611:                         */
                    612:                        ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
1.2       itojun    613:                }
1.65      itojun    614:        }
1.2       itojun    615:
1.65      itojun    616:        /* expire prefix list */
1.108     dyoung    617:        for (pr = LIST_FIRST(&nd_prefix); pr != NULL; pr = next_pr) {
                    618:                next_pr = LIST_NEXT(pr, ndpr_entry);
1.2       itojun    619:                /*
                    620:                 * check prefix lifetime.
                    621:                 * since pltime is just for autoconf, pltime processing for
                    622:                 * prefix is not necessary.
                    623:                 */
1.65      itojun    624:                if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
1.103     kardel    625:                    time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
1.2       itojun    626:
                    627:                        /*
                    628:                         * address expiration and prefix expiration are
1.65      itojun    629:                         * separate.  NEVER perform in6_purgeaddr here.
1.2       itojun    630:                         */
                    631:
                    632:                        prelist_remove(pr);
1.108     dyoung    633:                }
1.2       itojun    634:        }
1.126     ad        635:
                    636:        KERNEL_UNLOCK_ONE(NULL);
                    637:        mutex_exit(softnet_lock);
1.16      itojun    638: }
                    639:
1.112     dyoung    640: /* ia6: deprecated/invalidated temporary address */
1.99      rpaulo    641: static int
1.112     dyoung    642: regen_tmpaddr(struct in6_ifaddr *ia6)
1.99      rpaulo    643: {
                    644:        struct ifaddr *ifa;
                    645:        struct ifnet *ifp;
                    646:        struct in6_ifaddr *public_ifa6 = NULL;
                    647:
                    648:        ifp = ia6->ia_ifa.ifa_ifp;
1.123     dyoung    649:        IFADDR_FOREACH(ifa, ifp) {
1.99      rpaulo    650:                struct in6_ifaddr *it6;
                    651:
                    652:                if (ifa->ifa_addr->sa_family != AF_INET6)
                    653:                        continue;
                    654:
                    655:                it6 = (struct in6_ifaddr *)ifa;
                    656:
                    657:                /* ignore no autoconf addresses. */
                    658:                if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
                    659:                        continue;
                    660:
                    661:                /* ignore autoconf addresses with different prefixes. */
                    662:                if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr)
                    663:                        continue;
                    664:
                    665:                /*
                    666:                 * Now we are looking at an autoconf address with the same
                    667:                 * prefix as ours.  If the address is temporary and is still
                    668:                 * preferred, do not create another one.  It would be rare, but
                    669:                 * could happen, for example, when we resume a laptop PC after
                    670:                 * a long period.
                    671:                 */
                    672:                if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
                    673:                    !IFA6_IS_DEPRECATED(it6)) {
                    674:                        public_ifa6 = NULL;
                    675:                        break;
                    676:                }
                    677:
                    678:                /*
                    679:                 * This is a public autoconf address that has the same prefix
                    680:                 * as ours.  If it is preferred, keep it.  We can't break the
                    681:                 * loop here, because there may be a still-preferred temporary
                    682:                 * address with the prefix.
                    683:                 */
                    684:                if (!IFA6_IS_DEPRECATED(it6))
                    685:                    public_ifa6 = it6;
                    686:        }
                    687:
                    688:        if (public_ifa6 != NULL) {
                    689:                int e;
                    690:
                    691:                /*
                    692:                 * Random factor is introduced in the preferred lifetime, so
                    693:                 * we do not need additional delay (3rd arg to in6_tmpifadd).
                    694:                 */
                    695:                if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
                    696:                        log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
                    697:                            " tmp addr, errno=%d\n", e);
1.112     dyoung    698:                        return -1;
1.99      rpaulo    699:                }
1.112     dyoung    700:                return 0;
1.99      rpaulo    701:        }
                    702:
1.112     dyoung    703:        return -1;
1.99      rpaulo    704: }
                    705:
1.16      itojun    706: /*
                    707:  * Nuke neighbor cache/prefix/default router management table, right before
                    708:  * ifp goes away.
                    709:  */
                    710: void
1.112     dyoung    711: nd6_purge(struct ifnet *ifp)
1.16      itojun    712: {
                    713:        struct llinfo_nd6 *ln, *nln;
1.65      itojun    714:        struct nd_defrouter *dr, *ndr;
1.16      itojun    715:        struct nd_prefix *pr, *npr;
                    716:
1.65      itojun    717:        /*
                    718:         * Nuke default router list entries toward ifp.
                    719:         * We defer removal of default router list entries that is installed
                    720:         * in the routing table, in order to keep additional side effects as
                    721:         * small as possible.
                    722:         */
1.129     dyoung    723:        for (dr = TAILQ_FIRST(&nd_defrouter); dr != NULL; dr = ndr) {
1.65      itojun    724:                ndr = TAILQ_NEXT(dr, dr_entry);
                    725:                if (dr->installed)
                    726:                        continue;
                    727:
                    728:                if (dr->ifp == ifp)
                    729:                        defrtrlist_del(dr);
                    730:        }
1.129     dyoung    731:        for (dr = TAILQ_FIRST(&nd_defrouter); dr != NULL; dr = ndr) {
1.65      itojun    732:                ndr = TAILQ_NEXT(dr, dr_entry);
                    733:                if (!dr->installed)
                    734:                        continue;
                    735:
1.16      itojun    736:                if (dr->ifp == ifp)
                    737:                        defrtrlist_del(dr);
                    738:        }
                    739:
                    740:        /* Nuke prefix list entries toward ifp */
1.108     dyoung    741:        for (pr = LIST_FIRST(&nd_prefix); pr != NULL; pr = npr) {
                    742:                npr = LIST_NEXT(pr, ndpr_entry);
1.16      itojun    743:                if (pr->ndpr_ifp == ifp) {
1.65      itojun    744:                        /*
1.92      tron      745:                         * Because if_detach() does *not* release prefixes
                    746:                         * while purging addresses the reference count will
                    747:                         * still be above zero. We therefore reset it to
                    748:                         * make sure that the prefix really gets purged.
                    749:                         */
                    750:                        pr->ndpr_refcnt = 0;
                    751:                        /*
1.65      itojun    752:                         * Previously, pr->ndpr_addr is removed as well,
                    753:                         * but I strongly believe we don't have to do it.
                    754:                         * nd6_purge() is only called from in6_ifdetach(),
                    755:                         * which removes all the associated interface addresses
                    756:                         * by itself.
                    757:                         * (jinmei@kame.net 20010129)
                    758:                         */
1.16      itojun    759:                        prelist_remove(pr);
                    760:                }
                    761:        }
                    762:
                    763:        /* cancel default outgoing interface setting */
                    764:        if (nd6_defifindex == ifp->if_index)
                    765:                nd6_setdefaultiface(0);
                    766:
1.48      itojun    767:        if (!ip6_forwarding && ip6_accept_rtadv) { /* XXX: too restrictive? */
                    768:                /* refresh default router list */
                    769:                defrouter_select();
                    770:        }
1.16      itojun    771:
                    772:        /*
                    773:         * Nuke neighbor cache entries for the ifp.
                    774:         * Note that rt->rt_ifp may not be the same as ifp,
                    775:         * due to KAME goto ours hack.  See RTM_RESOLVE case in
1.18      itojun    776:         * nd6_rtrequest(), and ip6_input().
1.16      itojun    777:         */
                    778:        ln = llinfo_nd6.ln_next;
1.129     dyoung    779:        while (ln != NULL && ln != &llinfo_nd6) {
1.16      itojun    780:                struct rtentry *rt;
1.118     dyoung    781:                const struct sockaddr_dl *sdl;
1.16      itojun    782:
                    783:                nln = ln->ln_next;
                    784:                rt = ln->ln_rt;
                    785:                if (rt && rt->rt_gateway &&
                    786:                    rt->rt_gateway->sa_family == AF_LINK) {
1.118     dyoung    787:                        sdl = satocsdl(rt->rt_gateway);
1.16      itojun    788:                        if (sdl->sdl_index == ifp->if_index)
1.54      itojun    789:                                nln = nd6_free(rt, 0);
1.16      itojun    790:                }
                    791:                ln = nln;
                    792:        }
1.2       itojun    793: }
                    794:
                    795: struct rtentry *
1.112     dyoung    796: nd6_lookup(const struct in6_addr *addr6, int create, struct ifnet *ifp)
1.2       itojun    797: {
                    798:        struct rtentry *rt;
                    799:        struct sockaddr_in6 sin6;
                    800:
1.122     dyoung    801:        sockaddr_in6_init(&sin6, addr6, 0, 0, 0);
1.13      itojun    802:        rt = rtalloc1((struct sockaddr *)&sin6, create);
1.129     dyoung    803:        if (rt != NULL && (rt->rt_flags & RTF_LLINFO) == 0) {
1.2       itojun    804:                /*
                    805:                 * This is the case for the default route.
1.25      itojun    806:                 * If we want to create a neighbor cache for the address, we
1.2       itojun    807:                 * should free the route for the destination and allocate an
                    808:                 * interface route.
                    809:                 */
                    810:                if (create) {
                    811:                        RTFREE(rt);
1.99      rpaulo    812:                        rt = NULL;
1.2       itojun    813:                }
                    814:        }
1.112     dyoung    815:        if (rt != NULL)
                    816:                ;
                    817:        else if (create && ifp) {
                    818:                int e;
1.25      itojun    819:
1.112     dyoung    820:                /*
                    821:                 * If no route is available and create is set,
                    822:                 * we allocate a host route for the destination
                    823:                 * and treat it like an interface route.
                    824:                 * This hack is necessary for a neighbor which can't
                    825:                 * be covered by our own prefix.
                    826:                 */
                    827:                struct ifaddr *ifa =
                    828:                    ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp);
                    829:                if (ifa == NULL)
                    830:                        return NULL;
1.2       itojun    831:
1.112     dyoung    832:                /*
                    833:                 * Create a new route.  RTF_LLINFO is necessary
                    834:                 * to create a Neighbor Cache entry for the
                    835:                 * destination in nd6_rtrequest which will be
                    836:                 * called in rtrequest via ifa->ifa_rtrequest.
                    837:                 */
1.122     dyoung    838:                if ((e = rtrequest(RTM_ADD, (const struct sockaddr *)&sin6,
                    839:                    ifa->ifa_addr, (const struct sockaddr *)&all1_sa,
1.112     dyoung    840:                    (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) &
                    841:                    ~RTF_CLONING, &rt)) != 0) {
1.54      itojun    842: #if 0
1.112     dyoung    843:                        log(LOG_ERR,
                    844:                            "nd6_lookup: failed to add route for a "
                    845:                            "neighbor(%s), errno=%d\n",
                    846:                            ip6_sprintf(addr6), e);
1.54      itojun    847: #endif
1.112     dyoung    848:                        return NULL;
                    849:                }
                    850:                if (rt == NULL)
                    851:                        return NULL;
                    852:                if (rt->rt_llinfo) {
                    853:                        struct llinfo_nd6 *ln =
                    854:                            (struct llinfo_nd6 *)rt->rt_llinfo;
                    855:                        ln->ln_state = ND6_LLINFO_NOSTATE;
                    856:                }
                    857:        } else
                    858:                return NULL;
1.2       itojun    859:        rt->rt_refcnt--;
1.12      itojun    860:        /*
                    861:         * Validation for the entry.
1.65      itojun    862:         * Note that the check for rt_llinfo is necessary because a cloned
                    863:         * route from a parent route that has the L flag (e.g. the default
                    864:         * route to a p2p interface) may have the flag, too, while the
                    865:         * destination is not actually a neighbor.
1.12      itojun    866:         * XXX: we can't use rt->rt_ifp to check for the interface, since
                    867:         *      it might be the loopback interface if the entry is for our
                    868:         *      own address on a non-loopback interface. Instead, we should
1.65      itojun    869:         *      use rt->rt_ifa->ifa_ifp, which would specify the REAL
                    870:         *      interface.
1.99      rpaulo    871:         * Note also that ifa_ifp and ifp may differ when we connect two
                    872:         * interfaces to a same link, install a link prefix to an interface,
                    873:         * and try to install a neighbor cache on an interface that does not
                    874:         * have a route to the prefix.
1.12      itojun    875:         */
1.2       itojun    876:        if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
1.65      itojun    877:            rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
1.12      itojun    878:            (ifp && rt->rt_ifa->ifa_ifp != ifp)) {
1.2       itojun    879:                if (create) {
1.77      itojun    880:                        nd6log((LOG_DEBUG,
1.65      itojun    881:                            "nd6_lookup: failed to lookup %s (if = %s)\n",
                    882:                            ip6_sprintf(addr6),
1.77      itojun    883:                            ifp ? if_name(ifp) : "unspec"));
1.2       itojun    884:                }
1.112     dyoung    885:                return NULL;
1.2       itojun    886:        }
1.112     dyoung    887:        return rt;
1.6       itojun    888: }
                    889:
                    890: /*
                    891:  * Detect if a given IPv6 address identifies a neighbor on a given link.
1.25      itojun    892:  * XXX: should take care of the destination of a p2p link?
1.6       itojun    893:  */
                    894: int
1.110     dyoung    895: nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
1.6       itojun    896: {
1.65      itojun    897:        struct nd_prefix *pr;
1.6       itojun    898:
1.29      itojun    899:        /*
                    900:         * A link-local address is always a neighbor.
1.52      itojun    901:         * XXX: a link does not necessarily specify a single interface.
1.29      itojun    902:         */
1.96      rpaulo    903:        if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
                    904:                struct sockaddr_in6 sin6_copy;
                    905:                u_int32_t zone;
                    906:
                    907:                /*
                    908:                 * We need sin6_copy since sa6_recoverscope() may modify the
                    909:                 * content (XXX).
                    910:                 */
                    911:                sin6_copy = *addr;
                    912:                if (sa6_recoverscope(&sin6_copy))
1.112     dyoung    913:                        return 0; /* XXX: should be impossible */
1.96      rpaulo    914:                if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone))
1.112     dyoung    915:                        return 0;
1.96      rpaulo    916:                if (sin6_copy.sin6_scope_id == zone)
1.112     dyoung    917:                        return 1;
1.96      rpaulo    918:                else
1.112     dyoung    919:                        return 0;
1.96      rpaulo    920:        }
1.6       itojun    921:
                    922:        /*
1.65      itojun    923:         * If the address matches one of our on-link prefixes, it should be a
                    924:         * neighbor.
1.6       itojun    925:         */
1.108     dyoung    926:        LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
1.65      itojun    927:                if (pr->ndpr_ifp != ifp)
                    928:                        continue;
                    929:
                    930:                if (!(pr->ndpr_stateflags & NDPRF_ONLINK))
                    931:                        continue;
                    932:
                    933:                if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
                    934:                    &addr->sin6_addr, &pr->ndpr_mask))
1.112     dyoung    935:                        return 1;
1.65      itojun    936:        }
1.6       itojun    937:
1.65      itojun    938:        /*
                    939:         * If the default router list is empty, all addresses are regarded
                    940:         * as on-link, and thus, as a neighbor.
                    941:         * XXX: we restrict the condition to hosts, because routers usually do
                    942:         * not have the "default router list".
                    943:         */
                    944:        if (!ip6_forwarding && TAILQ_FIRST(&nd_defrouter) == NULL &&
                    945:            nd6_defifindex == ifp->if_index) {
1.112     dyoung    946:                return 1;
1.6       itojun    947:        }
                    948:
                    949:        /*
                    950:         * Even if the address matches none of our addresses, it might be
                    951:         * in the neighbor cache.
                    952:         */
1.88      simonb    953:        if (nd6_lookup(&addr->sin6_addr, 0, ifp) != NULL)
1.112     dyoung    954:                return 1;
1.6       itojun    955:
1.112     dyoung    956:        return 0;
1.2       itojun    957: }
                    958:
                    959: /*
                    960:  * Free an nd6 llinfo entry.
1.54      itojun    961:  * Since the function would cause significant changes in the kernel, DO NOT
                    962:  * make it global, unless you have a strong reason for the change, and are sure
                    963:  * that the change is safe.
1.2       itojun    964:  */
1.54      itojun    965: static struct llinfo_nd6 *
1.112     dyoung    966: nd6_free(struct rtentry *rt, int gc)
1.2       itojun    967: {
1.37      itojun    968:        struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
1.117     dyoung    969:        struct in6_addr in6 = satocsin6(rt_getkey(rt))->sin6_addr;
1.12      itojun    970:        struct nd_defrouter *dr;
1.2       itojun    971:
1.18      itojun    972:        /*
1.54      itojun    973:         * we used to have pfctlinput(PRC_HOSTDEAD) here.
                    974:         * even though it is not harmful, it was not really necessary.
1.18      itojun    975:         */
                    976:
1.86      itojun    977:        /* cancel timer */
                    978:        nd6_llinfo_settimer(ln, -1);
                    979:
1.85      itojun    980:        if (!ip6_forwarding) {
1.2       itojun    981:                int s;
1.5       itojun    982:                s = splsoftnet();
1.117     dyoung    983:                dr = defrouter_lookup(&satocsin6(rt_getkey(rt))->sin6_addr,
1.65      itojun    984:                    rt->rt_ifp);
1.54      itojun    985:
                    986:                if (dr != NULL && dr->expire &&
                    987:                    ln->ln_state == ND6_LLINFO_STALE && gc) {
                    988:                        /*
                    989:                         * If the reason for the deletion is just garbage
                    990:                         * collection, and the neighbor is an active default
                    991:                         * router, do not delete it.  Instead, reset the GC
                    992:                         * timer using the router's lifetime.
                    993:                         * Simply deleting the entry would affect default
                    994:                         * router selection, which is not necessarily a good
                    995:                         * thing, especially when we're using router preference
                    996:                         * values.
                    997:                         * XXX: the check for ln_state would be redundant,
                    998:                         *      but we intentionally keep it just in case.
                    999:                         */
1.103     kardel   1000:                        if (dr->expire > time_second)
1.86      itojun   1001:                                nd6_llinfo_settimer(ln,
1.103     kardel   1002:                                    (dr->expire - time_second) * hz);
1.86      itojun   1003:                        else
                   1004:                                nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.54      itojun   1005:                        splx(s);
1.112     dyoung   1006:                        return ln->ln_next;
1.54      itojun   1007:                }
                   1008:
1.12      itojun   1009:                if (ln->ln_router || dr) {
                   1010:                        /*
                   1011:                         * rt6_flush must be called whether or not the neighbor
                   1012:                         * is in the Default Router List.
                   1013:                         * See a corresponding comment in nd6_na_input().
                   1014:                         */
                   1015:                        rt6_flush(&in6, rt->rt_ifp);
                   1016:                }
                   1017:
                   1018:                if (dr) {
                   1019:                        /*
                   1020:                         * Unreachablity of a router might affect the default
                   1021:                         * router selection and on-link detection of advertised
                   1022:                         * prefixes.
                   1023:                         */
                   1024:
1.2       itojun   1025:                        /*
1.12      itojun   1026:                         * Temporarily fake the state to choose a new default
                   1027:                         * router and to perform on-link determination of
1.54      itojun   1028:                         * prefixes correctly.
1.12      itojun   1029:                         * Below the state will be set correctly,
                   1030:                         * or the entry itself will be deleted.
1.2       itojun   1031:                         */
1.12      itojun   1032:                        ln->ln_state = ND6_LLINFO_INCOMPLETE;
                   1033:
1.54      itojun   1034:                        /*
                   1035:                         * Since defrouter_select() does not affect the
                   1036:                         * on-link determination and MIP6 needs the check
                   1037:                         * before the default router selection, we perform
                   1038:                         * the check now.
                   1039:                         */
                   1040:                        pfxlist_onlink_check();
                   1041:
1.65      itojun   1042:                        /*
                   1043:                         * refresh default router list
                   1044:                         */
                   1045:                        defrouter_select();
1.2       itojun   1046:                }
                   1047:                splx(s);
                   1048:        }
1.12      itojun   1049:
1.37      itojun   1050:        /*
                   1051:         * Before deleting the entry, remember the next entry as the
                   1052:         * return value.  We need this because pfxlist_onlink_check() above
                   1053:         * might have freed other entries (particularly the old next entry) as
1.52      itojun   1054:         * a side effect (XXX).
1.37      itojun   1055:         */
                   1056:        next = ln->ln_next;
                   1057:
                   1058:        /*
                   1059:         * Detach the route from the routing tree and the list of neighbor
                   1060:         * caches, and disable the route entry not to be used in already
                   1061:         * cached routes.
                   1062:         */
1.129     dyoung   1063:        rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0, NULL);
1.37      itojun   1064:
1.112     dyoung   1065:        return next;
1.2       itojun   1066: }
                   1067:
                   1068: /*
                   1069:  * Upper-layer reachability hint for Neighbor Unreachability Detection.
                   1070:  *
1.98      rpaulo   1071:  * XXX cost-effective methods?
1.2       itojun   1072:  */
                   1073: void
1.112     dyoung   1074: nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
1.2       itojun   1075: {
                   1076:        struct llinfo_nd6 *ln;
                   1077:
                   1078:        /*
                   1079:         * If the caller specified "rt", use that.  Otherwise, resolve the
                   1080:         * routing table by supplied "dst6".
                   1081:         */
1.99      rpaulo   1082:        if (rt == NULL) {
                   1083:                if (dst6 == NULL)
1.2       itojun   1084:                        return;
1.99      rpaulo   1085:                if ((rt = nd6_lookup(dst6, 0, NULL)) == NULL)
1.2       itojun   1086:                        return;
                   1087:        }
                   1088:
1.31      itojun   1089:        if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
                   1090:            (rt->rt_flags & RTF_LLINFO) == 0 ||
                   1091:            !rt->rt_llinfo || !rt->rt_gateway ||
                   1092:            rt->rt_gateway->sa_family != AF_LINK) {
1.2       itojun   1093:                /* This is not a host route. */
                   1094:                return;
                   1095:        }
                   1096:
                   1097:        ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1.22      itojun   1098:        if (ln->ln_state < ND6_LLINFO_REACHABLE)
1.2       itojun   1099:                return;
                   1100:
1.31      itojun   1101:        /*
                   1102:         * if we get upper-layer reachability confirmation many times,
                   1103:         * it is possible we have false information.
                   1104:         */
                   1105:        if (!force) {
                   1106:                ln->ln_byhint++;
                   1107:                if (ln->ln_byhint > nd6_maxnudhint)
                   1108:                        return;
                   1109:        }
                   1110:
1.2       itojun   1111:        ln->ln_state = ND6_LLINFO_REACHABLE;
1.86      itojun   1112:        if (!ND6_LLINFO_PERMANENT(ln)) {
                   1113:                nd6_llinfo_settimer(ln,
                   1114:                    (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
                   1115:        }
1.2       itojun   1116: }
                   1117:
                   1118: void
1.130   ! dyoung   1119: nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
1.2       itojun   1120: {
                   1121:        struct sockaddr *gate = rt->rt_gateway;
                   1122:        struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
                   1123:        struct ifnet *ifp = rt->rt_ifp;
1.119     dyoung   1124:        uint8_t namelen = strlen(ifp->if_xname), addrlen = ifp->if_addrlen;
1.2       itojun   1125:        struct ifaddr *ifa;
                   1126:
1.128     dyoung   1127:        RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.117     dyoung   1128:
1.65      itojun   1129:        if ((rt->rt_flags & RTF_GATEWAY) != 0)
1.2       itojun   1130:                return;
                   1131:
1.54      itojun   1132:        if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
1.128     dyoung   1133:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.54      itojun   1134:                /*
                   1135:                 * This is probably an interface direct route for a link
                   1136:                 * which does not need neighbor caches (e.g. fe80::%lo0/64).
                   1137:                 * We do not need special treatment below for such a route.
                   1138:                 * Moreover, the RTF_LLINFO flag which would be set below
                   1139:                 * would annoy the ndp(8) command.
                   1140:                 */
                   1141:                return;
                   1142:        }
                   1143:
1.65      itojun   1144:        if (req == RTM_RESOLVE &&
                   1145:            (nd6_need_cache(ifp) == 0 || /* stf case */
1.117     dyoung   1146:             !nd6_is_addr_neighbor(satocsin6(rt_getkey(rt)), ifp))) {
1.128     dyoung   1147:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.65      itojun   1148:                /*
                   1149:                 * FreeBSD and BSD/OS often make a cloned host route based
                   1150:                 * on a less-specific route (e.g. the default route).
                   1151:                 * If the less specific route does not have a "gateway"
                   1152:                 * (this is the case when the route just goes to a p2p or an
                   1153:                 * stf interface), we'll mistakenly make a neighbor cache for
                   1154:                 * the host route, and will see strange neighbor solicitation
                   1155:                 * for the corresponding destination.  In order to avoid the
                   1156:                 * confusion, we check if the destination of the route is
                   1157:                 * a neighbor in terms of neighbor discovery, and stop the
                   1158:                 * process if not.  Additionally, we remove the LLINFO flag
                   1159:                 * so that ndp(8) will not try to get the neighbor information
                   1160:                 * of the destination.
                   1161:                 */
                   1162:                rt->rt_flags &= ~RTF_LLINFO;
                   1163:                return;
                   1164:        }
                   1165:
1.2       itojun   1166:        switch (req) {
                   1167:        case RTM_ADD:
1.128     dyoung   1168:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2       itojun   1169:                /*
                   1170:                 * There is no backward compatibility :)
                   1171:                 *
                   1172:                 * if ((rt->rt_flags & RTF_HOST) == 0 &&
                   1173:                 *     SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
                   1174:                 *         rt->rt_flags |= RTF_CLONING;
                   1175:                 */
1.84      itojun   1176:                if ((rt->rt_flags & RTF_CLONING) ||
1.129     dyoung   1177:                    ((rt->rt_flags & RTF_LLINFO) && ln == NULL)) {
1.120     dyoung   1178:                        union {
                   1179:                                struct sockaddr sa;
                   1180:                                struct sockaddr_dl sdl;
                   1181:                                struct sockaddr_storage ss;
                   1182:                        } u;
1.2       itojun   1183:                        /*
1.84      itojun   1184:                         * Case 1: This route should come from a route to
                   1185:                         * interface (RTF_CLONING case) or the route should be
                   1186:                         * treated as on-link but is currently not
1.129     dyoung   1187:                         * (RTF_LLINFO && ln == NULL case).
1.2       itojun   1188:                         */
1.120     dyoung   1189:                        sockaddr_dl_init(&u.sdl, sizeof(u.ss),
                   1190:                            ifp->if_index, ifp->if_type,
                   1191:                            NULL, namelen, NULL, addrlen);
                   1192:                        rt_setgate(rt, &u.sa);
1.119     dyoung   1193:                        gate = rt->rt_gateway;
1.128     dyoung   1194:                        RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.129     dyoung   1195:                        if (ln != NULL)
1.86      itojun   1196:                                nd6_llinfo_settimer(ln, 0);
1.128     dyoung   1197:                        RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.65      itojun   1198:                        if ((rt->rt_flags & RTF_CLONING) != 0)
1.2       itojun   1199:                                break;
                   1200:                }
1.128     dyoung   1201:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.18      itojun   1202:                /*
                   1203:                 * In IPv4 code, we try to annonuce new RTF_ANNOUNCE entry here.
                   1204:                 * We don't do that here since llinfo is not ready yet.
                   1205:                 *
                   1206:                 * There are also couple of other things to be discussed:
                   1207:                 * - unsolicited NA code needs improvement beforehand
                   1208:                 * - RFC2461 says we MAY send multicast unsolicited NA
                   1209:                 *   (7.2.6 paragraph 4), however, it also says that we
                   1210:                 *   SHOULD provide a mechanism to prevent multicast NA storm.
                   1211:                 *   we don't have anything like it right now.
1.38      itojun   1212:                 *   note that the mechanism needs a mutual agreement
1.18      itojun   1213:                 *   between proxies, which means that we need to implement
1.38      itojun   1214:                 *   a new protocol, or a new kludge.
                   1215:                 * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA.
1.18      itojun   1216:                 *   we need to check ip6forwarding before sending it.
                   1217:                 *   (or should we allow proxy ND configuration only for
                   1218:                 *   routers?  there's no mention about proxy ND from hosts)
                   1219:                 */
                   1220: #if 0
                   1221:                /* XXX it does not work */
1.2       itojun   1222:                if (rt->rt_flags & RTF_ANNOUNCE)
                   1223:                        nd6_na_output(ifp,
1.118     dyoung   1224:                              &satocsin6(rt_getkey(rt))->sin6_addr,
                   1225:                              &satocsin6(rt_getkey(rt))->sin6_addr,
1.18      itojun   1226:                              ip6_forwarding ? ND_NA_FLAG_ROUTER : 0,
                   1227:                              1, NULL);
                   1228: #endif
1.2       itojun   1229:                /* FALLTHROUGH */
                   1230:        case RTM_RESOLVE:
1.65      itojun   1231:                if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
1.128     dyoung   1232:                        RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.26      itojun   1233:                        /*
                   1234:                         * Address resolution isn't necessary for a point to
                   1235:                         * point link, so we can skip this test for a p2p link.
                   1236:                         */
                   1237:                        if (gate->sa_family != AF_LINK ||
1.119     dyoung   1238:                            gate->sa_len <
                   1239:                            sockaddr_dl_measure(namelen, addrlen)) {
1.26      itojun   1240:                                log(LOG_DEBUG,
1.36      itojun   1241:                                    "nd6_rtrequest: bad gateway value: %s\n",
                   1242:                                    if_name(ifp));
1.26      itojun   1243:                                break;
                   1244:                        }
1.118     dyoung   1245:                        satosdl(gate)->sdl_type = ifp->if_type;
                   1246:                        satosdl(gate)->sdl_index = ifp->if_index;
1.128     dyoung   1247:                        RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2       itojun   1248:                }
1.26      itojun   1249:                if (ln != NULL)
1.2       itojun   1250:                        break;  /* This happens on a route change */
1.128     dyoung   1251:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2       itojun   1252:                /*
                   1253:                 * Case 2: This route may come from cloning, or a manual route
                   1254:                 * add with a LL address.
                   1255:                 */
                   1256:                R_Malloc(ln, struct llinfo_nd6 *, sizeof(*ln));
1.129     dyoung   1257:                rt->rt_llinfo = ln;
1.128     dyoung   1258:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.99      rpaulo   1259:                if (ln == NULL) {
1.2       itojun   1260:                        log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n");
                   1261:                        break;
                   1262:                }
1.128     dyoung   1263:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2       itojun   1264:                nd6_inuse++;
                   1265:                nd6_allocated++;
1.129     dyoung   1266:                memset(ln, 0, sizeof(*ln));
1.2       itojun   1267:                ln->ln_rt = rt;
1.126     ad       1268:                callout_init(&ln->ln_timer_ch, CALLOUT_MPSAFE);
1.2       itojun   1269:                /* this is required for "ndp" command. - shin */
                   1270:                if (req == RTM_ADD) {
                   1271:                        /*
                   1272:                         * gate should have some valid AF_LINK entry,
                   1273:                         * and ln->ln_expire should have some lifetime
                   1274:                         * which is specified by ndp command.
                   1275:                         */
                   1276:                        ln->ln_state = ND6_LLINFO_REACHABLE;
1.31      itojun   1277:                        ln->ln_byhint = 0;
1.2       itojun   1278:                } else {
1.25      itojun   1279:                        /*
1.2       itojun   1280:                         * When req == RTM_RESOLVE, rt is created and
                   1281:                         * initialized in rtrequest(), so rt_expire is 0.
                   1282:                         */
1.12      itojun   1283:                        ln->ln_state = ND6_LLINFO_NOSTATE;
1.86      itojun   1284:                        nd6_llinfo_settimer(ln, 0);
1.2       itojun   1285:                }
1.128     dyoung   1286:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2       itojun   1287:                rt->rt_flags |= RTF_LLINFO;
1.3       itojun   1288:                ln->ln_next = llinfo_nd6.ln_next;
                   1289:                llinfo_nd6.ln_next = ln;
                   1290:                ln->ln_prev = &llinfo_nd6;
                   1291:                ln->ln_next->ln_prev = ln;
1.2       itojun   1292:
1.128     dyoung   1293:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2       itojun   1294:                /*
1.117     dyoung   1295:                 * check if rt_getkey(rt) is an address assigned
1.2       itojun   1296:                 * to the interface.
                   1297:                 */
1.119     dyoung   1298:                ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp,
1.118     dyoung   1299:                    &satocsin6(rt_getkey(rt))->sin6_addr);
1.128     dyoung   1300:                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.129     dyoung   1301:                if (ifa != NULL) {
1.119     dyoung   1302:                        const void *mac;
1.86      itojun   1303:                        nd6_llinfo_settimer(ln, -1);
1.2       itojun   1304:                        ln->ln_state = ND6_LLINFO_REACHABLE;
1.31      itojun   1305:                        ln->ln_byhint = 0;
1.119     dyoung   1306:                        if ((mac = nd6_ifptomac(ifp)) != NULL) {
1.118     dyoung   1307:                                /* XXX check for error */
1.119     dyoung   1308:                                (void)sockaddr_dl_setaddr(satosdl(gate),
                   1309:                                    gate->sa_len, mac, ifp->if_addrlen);
1.2       itojun   1310:                        }
                   1311:                        if (nd6_useloopback) {
1.119     dyoung   1312:                                ifp = rt->rt_ifp = lo0ifp;      /* XXX */
1.2       itojun   1313:                                /*
                   1314:                                 * Make sure rt_ifa be equal to the ifaddr
                   1315:                                 * corresponding to the address.
                   1316:                                 * We need this because when we refer
                   1317:                                 * rt_ifa->ia6_flags in ip6_input, we assume
                   1318:                                 * that the rt_ifa points to the address instead
                   1319:                                 * of the loopback address.
                   1320:                                 */
1.106     dyoung   1321:                                if (ifa != rt->rt_ifa)
                   1322:                                        rt_replace_ifa(rt, ifa);
1.113     dyoung   1323:                                rt->rt_flags &= ~RTF_CLONED;
1.2       itojun   1324:                        }
1.18      itojun   1325:                } else if (rt->rt_flags & RTF_ANNOUNCE) {
1.86      itojun   1326:                        nd6_llinfo_settimer(ln, -1);
1.18      itojun   1327:                        ln->ln_state = ND6_LLINFO_REACHABLE;
1.31      itojun   1328:                        ln->ln_byhint = 0;
1.18      itojun   1329:
                   1330:                        /* join solicited node multicast for proxy ND */
                   1331:                        if (ifp->if_flags & IFF_MULTICAST) {
                   1332:                                struct in6_addr llsol;
                   1333:                                int error;
                   1334:
1.118     dyoung   1335:                                llsol = satocsin6(rt_getkey(rt))->sin6_addr;
1.96      rpaulo   1336:                                llsol.s6_addr32[0] = htonl(0xff020000);
1.18      itojun   1337:                                llsol.s6_addr32[1] = 0;
                   1338:                                llsol.s6_addr32[2] = htonl(1);
                   1339:                                llsol.s6_addr8[12] = 0xff;
1.96      rpaulo   1340:                                if (in6_setscope(&llsol, ifp, NULL))
                   1341:                                        break;
1.99      rpaulo   1342:                                if (!in6_addmulti(&llsol, ifp, &error, 0)) {
1.54      itojun   1343:                                        nd6log((LOG_ERR, "%s: failed to join "
                   1344:                                            "%s (errno=%d)\n", if_name(ifp),
                   1345:                                            ip6_sprintf(&llsol), error));
1.46      itojun   1346:                                }
1.18      itojun   1347:                        }
1.2       itojun   1348:                }
                   1349:                break;
                   1350:
                   1351:        case RTM_DELETE:
1.99      rpaulo   1352:                if (ln == NULL)
1.2       itojun   1353:                        break;
1.18      itojun   1354:                /* leave from solicited node multicast for proxy ND */
                   1355:                if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
                   1356:                    (ifp->if_flags & IFF_MULTICAST) != 0) {
                   1357:                        struct in6_addr llsol;
                   1358:                        struct in6_multi *in6m;
                   1359:
1.118     dyoung   1360:                        llsol = satocsin6(rt_getkey(rt))->sin6_addr;
1.96      rpaulo   1361:                        llsol.s6_addr32[0] = htonl(0xff020000);
1.18      itojun   1362:                        llsol.s6_addr32[1] = 0;
                   1363:                        llsol.s6_addr32[2] = htonl(1);
                   1364:                        llsol.s6_addr8[12] = 0xff;
1.96      rpaulo   1365:                        if (in6_setscope(&llsol, ifp, NULL) == 0) {
                   1366:                                IN6_LOOKUP_MULTI(llsol, ifp, in6m);
                   1367:                                if (in6m)
                   1368:                                        in6_delmulti(in6m);
1.104     christos 1369:                        }
1.18      itojun   1370:                }
1.2       itojun   1371:                nd6_inuse--;
1.3       itojun   1372:                ln->ln_next->ln_prev = ln->ln_prev;
                   1373:                ln->ln_prev->ln_next = ln->ln_next;
                   1374:                ln->ln_prev = NULL;
1.86      itojun   1375:                nd6_llinfo_settimer(ln, -1);
1.2       itojun   1376:                rt->rt_llinfo = 0;
                   1377:                rt->rt_flags &= ~RTF_LLINFO;
1.100     rpaulo   1378:                clear_llinfo_pqueue(ln);
1.129     dyoung   1379:                Free(ln);
1.2       itojun   1380:        }
                   1381: }
                   1382:
                   1383: int
1.112     dyoung   1384: nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
1.2       itojun   1385: {
                   1386:        struct in6_drlist *drl = (struct in6_drlist *)data;
1.65      itojun   1387:        struct in6_oprlist *oprl = (struct in6_oprlist *)data;
1.2       itojun   1388:        struct in6_ndireq *ndi = (struct in6_ndireq *)data;
                   1389:        struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
1.12      itojun   1390:        struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
1.65      itojun   1391:        struct nd_defrouter *dr;
1.2       itojun   1392:        struct nd_prefix *pr;
                   1393:        struct rtentry *rt;
                   1394:        int i = 0, error = 0;
                   1395:        int s;
                   1396:
                   1397:        switch (cmd) {
                   1398:        case SIOCGDRLST_IN6:
1.65      itojun   1399:                /*
                   1400:                 * obsolete API, use sysctl under net.inet6.icmp6
                   1401:                 */
1.129     dyoung   1402:                memset(drl, 0, sizeof(*drl));
1.5       itojun   1403:                s = splsoftnet();
1.108     dyoung   1404:                TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
                   1405:                        if (i >= DRLSTSIZ)
                   1406:                                break;
1.2       itojun   1407:                        drl->defrouter[i].rtaddr = dr->rtaddr;
1.96      rpaulo   1408:                        in6_clearscope(&drl->defrouter[i].rtaddr);
1.2       itojun   1409:
                   1410:                        drl->defrouter[i].flags = dr->flags;
                   1411:                        drl->defrouter[i].rtlifetime = dr->rtlifetime;
                   1412:                        drl->defrouter[i].expire = dr->expire;
                   1413:                        drl->defrouter[i].if_index = dr->ifp->if_index;
                   1414:                        i++;
                   1415:                }
                   1416:                splx(s);
                   1417:                break;
                   1418:        case SIOCGPRLST_IN6:
1.18      itojun   1419:                /*
1.65      itojun   1420:                 * obsolete API, use sysctl under net.inet6.icmp6
                   1421:                 *
                   1422:                 * XXX the structure in6_prlist was changed in backward-
                   1423:                 * incompatible manner.  in6_oprlist is used for SIOCGPRLST_IN6,
                   1424:                 * in6_prlist is used for nd6_sysctl() - fill_prlist().
                   1425:                 */
                   1426:                /*
1.18      itojun   1427:                 * XXX meaning of fields, especialy "raflags", is very
                   1428:                 * differnet between RA prefix list and RR/static prefix list.
                   1429:                 * how about separating ioctls into two?
                   1430:                 */
1.129     dyoung   1431:                memset(oprl, 0, sizeof(*oprl));
1.5       itojun   1432:                s = splsoftnet();
1.108     dyoung   1433:                LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
1.2       itojun   1434:                        struct nd_pfxrouter *pfr;
                   1435:                        int j;
                   1436:
1.108     dyoung   1437:                        if (i >= PRLSTSIZ)
                   1438:                                break;
1.65      itojun   1439:                        oprl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
                   1440:                        oprl->prefix[i].raflags = pr->ndpr_raf;
                   1441:                        oprl->prefix[i].prefixlen = pr->ndpr_plen;
                   1442:                        oprl->prefix[i].vltime = pr->ndpr_vltime;
                   1443:                        oprl->prefix[i].pltime = pr->ndpr_pltime;
                   1444:                        oprl->prefix[i].if_index = pr->ndpr_ifp->if_index;
1.99      rpaulo   1445:                        if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
                   1446:                                oprl->prefix[i].expire = 0;
                   1447:                        else {
                   1448:                                time_t maxexpire;
                   1449:
                   1450:                                /* XXX: we assume time_t is signed. */
                   1451:                                maxexpire = (-1) &
                   1452:                                    ~((time_t)1 <<
                   1453:                                    ((sizeof(maxexpire) * 8) - 1));
                   1454:                                if (pr->ndpr_vltime <
                   1455:                                    maxexpire - pr->ndpr_lastupdate) {
                   1456:                                        oprl->prefix[i].expire =
                   1457:                                                 pr->ndpr_lastupdate +
                   1458:                                                pr->ndpr_vltime;
                   1459:                                } else
                   1460:                                        oprl->prefix[i].expire = maxexpire;
                   1461:                        }
1.2       itojun   1462:
                   1463:                        j = 0;
1.108     dyoung   1464:                        LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
1.2       itojun   1465:                                if (j < DRLSTSIZ) {
1.65      itojun   1466: #define RTRADDR oprl->prefix[i].advrtr[j]
1.2       itojun   1467:                                        RTRADDR = pfr->router->rtaddr;
1.96      rpaulo   1468:                                        in6_clearscope(&RTRADDR);
1.2       itojun   1469: #undef RTRADDR
                   1470:                                }
                   1471:                                j++;
                   1472:                        }
1.65      itojun   1473:                        oprl->prefix[i].advrtrs = j;
                   1474:                        oprl->prefix[i].origin = PR_ORIG_RA;
1.2       itojun   1475:
                   1476:                        i++;
                   1477:                }
1.18      itojun   1478:                splx(s);
1.12      itojun   1479:
1.2       itojun   1480:                break;
1.58      itojun   1481:        case OSIOCGIFINFO_IN6:
1.99      rpaulo   1482: #define ND     ndi->ndi
1.58      itojun   1483:                /* XXX: old ndp(8) assumes a positive value for linkmtu. */
1.99      rpaulo   1484:                memset(&ND, 0, sizeof(ND));
                   1485:                ND.linkmtu = IN6_LINKMTU(ifp);
                   1486:                ND.maxmtu = ND_IFINFO(ifp)->maxmtu;
                   1487:                ND.basereachable = ND_IFINFO(ifp)->basereachable;
                   1488:                ND.reachable = ND_IFINFO(ifp)->reachable;
                   1489:                ND.retrans = ND_IFINFO(ifp)->retrans;
                   1490:                ND.flags = ND_IFINFO(ifp)->flags;
                   1491:                ND.recalctm = ND_IFINFO(ifp)->recalctm;
                   1492:                ND.chlim = ND_IFINFO(ifp)->chlim;
1.58      itojun   1493:                break;
1.2       itojun   1494:        case SIOCGIFINFO_IN6:
1.99      rpaulo   1495:                ND = *ND_IFINFO(ifp);
1.2       itojun   1496:                break;
1.99      rpaulo   1497:        case SIOCSIFINFO_IN6:
                   1498:                /*
                   1499:                 * used to change host variables from userland.
                   1500:                 * intented for a use on router to reflect RA configurations.
                   1501:                 */
                   1502:                /* 0 means 'unspecified' */
                   1503:                if (ND.linkmtu != 0) {
                   1504:                        if (ND.linkmtu < IPV6_MMTU ||
                   1505:                            ND.linkmtu > IN6_LINKMTU(ifp)) {
                   1506:                                error = EINVAL;
                   1507:                                break;
                   1508:                        }
                   1509:                        ND_IFINFO(ifp)->linkmtu = ND.linkmtu;
                   1510:                }
                   1511:
                   1512:                if (ND.basereachable != 0) {
                   1513:                        int obasereachable = ND_IFINFO(ifp)->basereachable;
                   1514:
                   1515:                        ND_IFINFO(ifp)->basereachable = ND.basereachable;
                   1516:                        if (ND.basereachable != obasereachable)
                   1517:                                ND_IFINFO(ifp)->reachable =
                   1518:                                    ND_COMPUTE_RTIME(ND.basereachable);
                   1519:                }
                   1520:                if (ND.retrans != 0)
                   1521:                        ND_IFINFO(ifp)->retrans = ND.retrans;
                   1522:                if (ND.chlim != 0)
                   1523:                        ND_IFINFO(ifp)->chlim = ND.chlim;
                   1524:                /* FALLTHROUGH */
1.26      itojun   1525:        case SIOCSIFINFO_FLAGS:
1.99      rpaulo   1526:                ND_IFINFO(ifp)->flags = ND.flags;
1.26      itojun   1527:                break;
1.99      rpaulo   1528: #undef ND
1.12      itojun   1529:        case SIOCSNDFLUSH_IN6:  /* XXX: the ioctl name is confusing... */
1.65      itojun   1530:                /* sync kernel routing table with the default router list */
                   1531:                defrouter_reset();
1.12      itojun   1532:                defrouter_select();
1.2       itojun   1533:                break;
                   1534:        case SIOCSPFXFLUSH_IN6:
1.65      itojun   1535:        {
1.2       itojun   1536:                /* flush all the prefix advertised by routers */
1.94      christos 1537:                struct nd_prefix *pfx, *next;
1.2       itojun   1538:
1.5       itojun   1539:                s = splsoftnet();
1.108     dyoung   1540:                for (pfx = LIST_FIRST(&nd_prefix); pfx; pfx = next) {
1.65      itojun   1541:                        struct in6_ifaddr *ia, *ia_next;
                   1542:
1.108     dyoung   1543:                        next = LIST_NEXT(pfx, ndpr_entry);
1.65      itojun   1544:
1.94      christos 1545:                        if (IN6_IS_ADDR_LINKLOCAL(&pfx->ndpr_prefix.sin6_addr))
1.65      itojun   1546:                                continue; /* XXX */
                   1547:
                   1548:                        /* do we really have to remove addresses as well? */
                   1549:                        for (ia = in6_ifaddr; ia; ia = ia_next) {
                   1550:                                /* ia might be removed.  keep the next ptr. */
                   1551:                                ia_next = ia->ia_next;
                   1552:
                   1553:                                if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
                   1554:                                        continue;
                   1555:
1.94      christos 1556:                                if (ia->ia6_ndpr == pfx)
1.65      itojun   1557:                                        in6_purgeaddr(&ia->ia_ifa);
                   1558:                        }
1.94      christos 1559:                        prelist_remove(pfx);
1.2       itojun   1560:                }
                   1561:                splx(s);
                   1562:                break;
1.65      itojun   1563:        }
1.2       itojun   1564:        case SIOCSRTRFLUSH_IN6:
1.65      itojun   1565:        {
1.2       itojun   1566:                /* flush all the default routers */
1.94      christos 1567:                struct nd_defrouter *drtr, *next;
1.2       itojun   1568:
1.5       itojun   1569:                s = splsoftnet();
1.65      itojun   1570:                defrouter_reset();
1.94      christos 1571:                for (drtr = TAILQ_FIRST(&nd_defrouter); drtr; drtr = next) {
                   1572:                        next = TAILQ_NEXT(drtr, dr_entry);
                   1573:                        defrtrlist_del(drtr);
1.2       itojun   1574:                }
1.65      itojun   1575:                defrouter_select();
1.2       itojun   1576:                splx(s);
                   1577:                break;
1.65      itojun   1578:        }
1.2       itojun   1579:        case SIOCGNBRINFO_IN6:
1.99      rpaulo   1580:        {
1.12      itojun   1581:                struct llinfo_nd6 *ln;
                   1582:                struct in6_addr nb_addr = nbi->addr; /* make local for safety */
                   1583:
1.96      rpaulo   1584:                if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
1.112     dyoung   1585:                        return error;
1.2       itojun   1586:
1.12      itojun   1587:                s = splsoftnet();
1.65      itojun   1588:                if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL ||
                   1589:                    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) {
1.12      itojun   1590:                        error = EINVAL;
                   1591:                        splx(s);
                   1592:                        break;
                   1593:                }
                   1594:                nbi->state = ln->ln_state;
                   1595:                nbi->asked = ln->ln_asked;
                   1596:                nbi->isrouter = ln->ln_router;
                   1597:                nbi->expire = ln->ln_expire;
                   1598:                splx(s);
1.63      itojun   1599:
1.12      itojun   1600:                break;
1.65      itojun   1601:        }
1.12      itojun   1602:        case SIOCGDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
                   1603:                ndif->ifindex = nd6_defifindex;
                   1604:                break;
                   1605:        case SIOCSDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
1.112     dyoung   1606:                return nd6_setdefaultiface(ndif->ifindex);
1.2       itojun   1607:        }
1.112     dyoung   1608:        return error;
1.2       itojun   1609: }
                   1610:
1.115     dyoung   1611: void
                   1612: nd6_llinfo_release_pkts(struct llinfo_nd6 *ln, struct ifnet *ifp,
                   1613:     struct rtentry *rt)
                   1614: {
                   1615:        struct mbuf *m_hold, *m_hold_next;
                   1616:
                   1617:        for (m_hold = ln->ln_hold, ln->ln_hold = NULL;
                   1618:             m_hold != NULL;
                   1619:             m_hold = m_hold_next) {
                   1620:                m_hold_next = m_hold->m_nextpkt;
                   1621:                m_hold->m_nextpkt = NULL;
                   1622:
                   1623:                /*
                   1624:                 * we assume ifp is not a p2p here, so
                   1625:                 * just set the 2nd argument as the
                   1626:                 * 1st one.
                   1627:                 */
1.117     dyoung   1628:                nd6_output(ifp, ifp, m_hold, satocsin6(rt_getkey(rt)), rt);
1.115     dyoung   1629:        }
                   1630: }
                   1631:
1.2       itojun   1632: /*
                   1633:  * Create neighbor cache entry and cache link-layer address,
1.52      itojun   1634:  * on reception of inbound ND6 packets.  (RS/RA/NS/redirect)
1.2       itojun   1635:  */
                   1636: struct rtentry *
1.105     christos 1637: nd6_cache_lladdr(
                   1638:     struct ifnet *ifp,
                   1639:     struct in6_addr *from,
                   1640:     char *lladdr,
1.107     christos 1641:     int lladdrlen,
1.105     christos 1642:     int type,  /* ICMP6 type */
                   1643:     int code   /* type dependent information */
                   1644: )
1.2       itojun   1645: {
                   1646:        struct rtentry *rt = NULL;
                   1647:        struct llinfo_nd6 *ln = NULL;
                   1648:        int is_newentry;
                   1649:        struct sockaddr_dl *sdl = NULL;
                   1650:        int do_update;
                   1651:        int olladdr;
                   1652:        int llchange;
                   1653:        int newstate = 0;
                   1654:
1.99      rpaulo   1655:        if (ifp == NULL)
1.2       itojun   1656:                panic("ifp == NULL in nd6_cache_lladdr");
1.99      rpaulo   1657:        if (from == NULL)
1.2       itojun   1658:                panic("from == NULL in nd6_cache_lladdr");
                   1659:
                   1660:        /* nothing must be updated for unspecified address */
                   1661:        if (IN6_IS_ADDR_UNSPECIFIED(from))
                   1662:                return NULL;
                   1663:
                   1664:        /*
                   1665:         * Validation about ifp->if_addrlen and lladdrlen must be done in
                   1666:         * the caller.
                   1667:         *
                   1668:         * XXX If the link does not have link-layer adderss, what should
                   1669:         * we do? (ifp->if_addrlen == 0)
                   1670:         * Spec says nothing in sections for RA, RS and NA.  There's small
                   1671:         * description on it in NS section (RFC 2461 7.2.3).
                   1672:         */
                   1673:
                   1674:        rt = nd6_lookup(from, 0, ifp);
1.99      rpaulo   1675:        if (rt == NULL) {
1.2       itojun   1676: #if 0
                   1677:                /* nothing must be done if there's no lladdr */
                   1678:                if (!lladdr || !lladdrlen)
                   1679:                        return NULL;
                   1680: #endif
                   1681:
                   1682:                rt = nd6_lookup(from, 1, ifp);
                   1683:                is_newentry = 1;
1.43      itojun   1684:        } else {
                   1685:                /* do nothing if static ndp is set */
                   1686:                if (rt->rt_flags & RTF_STATIC)
                   1687:                        return NULL;
1.2       itojun   1688:                is_newentry = 0;
1.43      itojun   1689:        }
1.2       itojun   1690:
1.99      rpaulo   1691:        if (rt == NULL)
1.2       itojun   1692:                return NULL;
                   1693:        if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
                   1694: fail:
1.54      itojun   1695:                (void)nd6_free(rt, 0);
1.2       itojun   1696:                return NULL;
                   1697:        }
                   1698:        ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1.99      rpaulo   1699:        if (ln == NULL)
1.2       itojun   1700:                goto fail;
1.99      rpaulo   1701:        if (rt->rt_gateway == NULL)
1.2       itojun   1702:                goto fail;
                   1703:        if (rt->rt_gateway->sa_family != AF_LINK)
                   1704:                goto fail;
1.118     dyoung   1705:        sdl = satosdl(rt->rt_gateway);
1.2       itojun   1706:
                   1707:        olladdr = (sdl->sdl_alen) ? 1 : 0;
                   1708:        if (olladdr && lladdr) {
1.118     dyoung   1709:                if (memcmp(lladdr, CLLADDR(sdl), ifp->if_addrlen))
1.2       itojun   1710:                        llchange = 1;
                   1711:                else
                   1712:                        llchange = 0;
                   1713:        } else
                   1714:                llchange = 0;
                   1715:
                   1716:        /*
                   1717:         * newentry olladdr  lladdr  llchange   (*=record)
                   1718:         *      0       n       n       --      (1)
                   1719:         *      0       y       n       --      (2)
                   1720:         *      0       n       y       --      (3) * STALE
                   1721:         *      0       y       y       n       (4) *
                   1722:         *      0       y       y       y       (5) * STALE
                   1723:         *      1       --      n       --      (6)   NOSTATE(= PASSIVE)
                   1724:         *      1       --      y       --      (7) * STALE
                   1725:         */
                   1726:
1.52      itojun   1727:        if (lladdr) {           /* (3-5) and (7) */
1.2       itojun   1728:                /*
                   1729:                 * Record source link-layer address
                   1730:                 * XXX is it dependent to ifp->if_type?
                   1731:                 */
1.118     dyoung   1732:                /* XXX check for error */
1.119     dyoung   1733:                (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, lladdr,
                   1734:                    ifp->if_addrlen);
1.2       itojun   1735:        }
                   1736:
                   1737:        if (!is_newentry) {
1.65      itojun   1738:                if ((!olladdr && lladdr) ||             /* (3) */
                   1739:                    (olladdr && lladdr && llchange)) {  /* (5) */
1.2       itojun   1740:                        do_update = 1;
                   1741:                        newstate = ND6_LLINFO_STALE;
1.52      itojun   1742:                } else                                  /* (1-2,4) */
1.2       itojun   1743:                        do_update = 0;
                   1744:        } else {
                   1745:                do_update = 1;
1.99      rpaulo   1746:                if (lladdr == NULL)                     /* (6) */
1.2       itojun   1747:                        newstate = ND6_LLINFO_NOSTATE;
1.52      itojun   1748:                else                                    /* (7) */
1.2       itojun   1749:                        newstate = ND6_LLINFO_STALE;
                   1750:        }
                   1751:
                   1752:        if (do_update) {
                   1753:                /*
                   1754:                 * Update the state of the neighbor cache.
                   1755:                 */
                   1756:                ln->ln_state = newstate;
                   1757:
                   1758:                if (ln->ln_state == ND6_LLINFO_STALE) {
1.44      itojun   1759:                        /*
                   1760:                         * XXX: since nd6_output() below will cause
                   1761:                         * state tansition to DELAY and reset the timer,
                   1762:                         * we must set the timer now, although it is actually
                   1763:                         * meaningless.
                   1764:                         */
1.86      itojun   1765:                        nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.44      itojun   1766:
1.115     dyoung   1767:                        nd6_llinfo_release_pkts(ln, ifp, rt);
1.2       itojun   1768:                } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
                   1769:                        /* probe right away */
1.86      itojun   1770:                        nd6_llinfo_settimer((void *)ln, 0);
1.2       itojun   1771:                }
                   1772:        }
                   1773:
                   1774:        /*
                   1775:         * ICMP6 type dependent behavior.
                   1776:         *
                   1777:         * NS: clear IsRouter if new entry
                   1778:         * RS: clear IsRouter
                   1779:         * RA: set IsRouter if there's lladdr
                   1780:         * redir: clear IsRouter if new entry
                   1781:         *
                   1782:         * RA case, (1):
                   1783:         * The spec says that we must set IsRouter in the following cases:
                   1784:         * - If lladdr exist, set IsRouter.  This means (1-5).
                   1785:         * - If it is old entry (!newentry), set IsRouter.  This means (7).
                   1786:         * So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
                   1787:         * A quetion arises for (1) case.  (1) case has no lladdr in the
                   1788:         * neighbor cache, this is similar to (6).
                   1789:         * This case is rare but we figured that we MUST NOT set IsRouter.
                   1790:         *
                   1791:         * newentry olladdr  lladdr  llchange       NS  RS  RA  redir
1.8       itojun   1792:         *                                                      D R
                   1793:         *      0       n       n       --      (1)     c   ?     s
                   1794:         *      0       y       n       --      (2)     c   s     s
                   1795:         *      0       n       y       --      (3)     c   s     s
                   1796:         *      0       y       y       n       (4)     c   s     s
                   1797:         *      0       y       y       y       (5)     c   s     s
                   1798:         *      1       --      n       --      (6) c   c       c s
                   1799:         *      1       --      y       --      (7) c   c   s   c s
1.2       itojun   1800:         *
                   1801:         *                                      (c=clear s=set)
                   1802:         */
                   1803:        switch (type & 0xff) {
                   1804:        case ND_NEIGHBOR_SOLICIT:
                   1805:                /*
                   1806:                 * New entry must have is_router flag cleared.
                   1807:                 */
1.52      itojun   1808:                if (is_newentry)        /* (6-7) */
1.8       itojun   1809:                        ln->ln_router = 0;
                   1810:                break;
                   1811:        case ND_REDIRECT:
                   1812:                /*
                   1813:                 * If the icmp is a redirect to a better router, always set the
1.52      itojun   1814:                 * is_router flag.  Otherwise, if the entry is newly created,
                   1815:                 * clear the flag.  [RFC 2461, sec 8.3]
1.8       itojun   1816:                 */
                   1817:                if (code == ND_REDIRECT_ROUTER)
                   1818:                        ln->ln_router = 1;
1.52      itojun   1819:                else if (is_newentry) /* (6-7) */
1.2       itojun   1820:                        ln->ln_router = 0;
                   1821:                break;
                   1822:        case ND_ROUTER_SOLICIT:
                   1823:                /*
                   1824:                 * is_router flag must always be cleared.
                   1825:                 */
                   1826:                ln->ln_router = 0;
                   1827:                break;
                   1828:        case ND_ROUTER_ADVERT:
                   1829:                /*
                   1830:                 * Mark an entry with lladdr as a router.
                   1831:                 */
1.65      itojun   1832:                if ((!is_newentry && (olladdr || lladdr)) ||    /* (2-5) */
                   1833:                    (is_newentry && lladdr)) {                  /* (7) */
1.2       itojun   1834:                        ln->ln_router = 1;
                   1835:                }
                   1836:                break;
                   1837:        }
1.47      itojun   1838:
                   1839:        /*
                   1840:         * When the link-layer address of a router changes, select the
                   1841:         * best router again.  In particular, when the neighbor entry is newly
                   1842:         * created, it might affect the selection policy.
                   1843:         * Question: can we restrict the first condition to the "is_newentry"
                   1844:         * case?
                   1845:         * XXX: when we hear an RA from a new router with the link-layer
                   1846:         * address option, defrouter_select() is called twice, since
                   1847:         * defrtrlist_update called the function as well.  However, I believe
                   1848:         * we can compromise the overhead, since it only happens the first
                   1849:         * time.
1.52      itojun   1850:         * XXX: although defrouter_select() should not have a bad effect
                   1851:         * for those are not autoconfigured hosts, we explicitly avoid such
                   1852:         * cases for safety.
1.47      itojun   1853:         */
1.49      itojun   1854:        if (do_update && ln->ln_router && !ip6_forwarding && ip6_accept_rtadv)
1.47      itojun   1855:                defrouter_select();
1.2       itojun   1856:
                   1857:        return rt;
                   1858: }
                   1859:
                   1860: static void
1.107     christos 1861: nd6_slowtimo(void *ignored_arg)
1.2       itojun   1862: {
1.38      itojun   1863:        struct nd_ifinfo *nd6if;
1.58      itojun   1864:        struct ifnet *ifp;
1.2       itojun   1865:
1.126     ad       1866:        mutex_enter(softnet_lock);
                   1867:        KERNEL_LOCK(1, NULL);
                   1868:        callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
1.20      thorpej  1869:            nd6_slowtimo, NULL);
1.108     dyoung   1870:        TAILQ_FOREACH(ifp, &ifnet, if_list) {
1.58      itojun   1871:                nd6if = ND_IFINFO(ifp);
1.2       itojun   1872:                if (nd6if->basereachable && /* already initialized */
                   1873:                    (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
                   1874:                        /*
                   1875:                         * Since reachable time rarely changes by router
                   1876:                         * advertisements, we SHOULD insure that a new random
                   1877:                         * value gets recomputed at least once every few hours.
                   1878:                         * (RFC 2461, 6.3.4)
                   1879:                         */
                   1880:                        nd6if->recalctm = nd6_recalc_reachtm_interval;
                   1881:                        nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
                   1882:                }
                   1883:        }
1.126     ad       1884:        KERNEL_UNLOCK_ONE(NULL);
                   1885:        mutex_exit(softnet_lock);
1.2       itojun   1886: }
                   1887:
                   1888: #define senderr(e) { error = (e); goto bad;}
                   1889: int
1.112     dyoung   1890: nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
1.114     dyoung   1891:     const struct sockaddr_in6 *dst, struct rtentry *rt0)
1.2       itojun   1892: {
1.38      itojun   1893:        struct mbuf *m = m0;
                   1894:        struct rtentry *rt = rt0;
1.29      itojun   1895:        struct sockaddr_in6 *gw6 = NULL;
1.2       itojun   1896:        struct llinfo_nd6 *ln = NULL;
                   1897:        int error = 0;
                   1898:
                   1899:        if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
                   1900:                goto sendpkt;
                   1901:
1.54      itojun   1902:        if (nd6_need_cache(ifp) == 0)
1.2       itojun   1903:                goto sendpkt;
                   1904:
                   1905:        /*
1.98      rpaulo   1906:         * next hop determination.  This routine is derived from ether_output.
1.2       itojun   1907:         */
                   1908:        if (rt) {
                   1909:                if ((rt->rt_flags & RTF_UP) == 0) {
1.114     dyoung   1910:                        if ((rt0 = rt = rtalloc1(sin6tocsa(dst), 1)) != NULL) {
1.2       itojun   1911:                                rt->rt_refcnt--;
1.90      itojun   1912:                                if (rt->rt_ifp != ifp)
                   1913:                                        senderr(EHOSTUNREACH);
1.25      itojun   1914:                        } else
1.2       itojun   1915:                                senderr(EHOSTUNREACH);
                   1916:                }
1.29      itojun   1917:
1.2       itojun   1918:                if (rt->rt_flags & RTF_GATEWAY) {
1.29      itojun   1919:                        gw6 = (struct sockaddr_in6 *)rt->rt_gateway;
                   1920:
                   1921:                        /*
                   1922:                         * We skip link-layer address resolution and NUD
                   1923:                         * if the gateway is not a neighbor from ND point
1.65      itojun   1924:                         * of view, regardless of the value of nd_ifinfo.flags.
1.56      itojun   1925:                         * The second condition is a bit tricky; we skip
1.29      itojun   1926:                         * if the gateway is our own address, which is
                   1927:                         * sometimes used to install a route to a p2p link.
                   1928:                         */
                   1929:                        if (!nd6_is_addr_neighbor(gw6, ifp) ||
                   1930:                            in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
                   1931:                                /*
                   1932:                                 * We allow this kind of tricky route only
                   1933:                                 * when the outgoing interface is p2p.
                   1934:                                 * XXX: we may need a more generic rule here.
                   1935:                                 */
                   1936:                                if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
                   1937:                                        senderr(EHOSTUNREACH);
                   1938:
                   1939:                                goto sendpkt;
                   1940:                        }
                   1941:
1.127     dyoung   1942:                        if (rt->rt_gwroute == NULL)
1.2       itojun   1943:                                goto lookup;
                   1944:                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
                   1945:                                rtfree(rt); rt = rt0;
1.50      itojun   1946:                        lookup:
                   1947:                                rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
1.127     dyoung   1948:                                if ((rt = rt->rt_gwroute) == NULL)
1.2       itojun   1949:                                        senderr(EHOSTUNREACH);
1.50      itojun   1950:                                /* the "G" test below also prevents rt == rt0 */
                   1951:                                if ((rt->rt_flags & RTF_GATEWAY) ||
                   1952:                                    (rt->rt_ifp != ifp)) {
                   1953:                                        rt->rt_refcnt--;
1.127     dyoung   1954:                                        rt0->rt_gwroute = NULL;
1.50      itojun   1955:                                        senderr(EHOSTUNREACH);
                   1956:                                }
1.2       itojun   1957:                        }
                   1958:                }
                   1959:        }
                   1960:
                   1961:        /*
                   1962:         * Address resolution or Neighbor Unreachability Detection
                   1963:         * for the next hop.
                   1964:         * At this point, the destination of the packet must be a unicast
                   1965:         * or an anycast address(i.e. not a multicast).
                   1966:         */
                   1967:
                   1968:        /* Look up the neighbor cache for the nexthop */
1.127     dyoung   1969:        if (rt != NULL && (rt->rt_flags & RTF_LLINFO) != 0)
1.2       itojun   1970:                ln = (struct llinfo_nd6 *)rt->rt_llinfo;
                   1971:        else {
1.29      itojun   1972:                /*
                   1973:                 * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
1.52      itojun   1974:                 * the condition below is not very efficient.  But we believe
1.29      itojun   1975:                 * it is tolerable, because this should be a rare case.
                   1976:                 */
                   1977:                if (nd6_is_addr_neighbor(dst, ifp) &&
                   1978:                    (rt = nd6_lookup(&dst->sin6_addr, 1, ifp)) != NULL)
1.2       itojun   1979:                        ln = (struct llinfo_nd6 *)rt->rt_llinfo;
                   1980:        }
1.99      rpaulo   1981:        if (ln == NULL || rt == NULL) {
1.29      itojun   1982:                if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
1.58      itojun   1983:                    !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
1.29      itojun   1984:                        log(LOG_DEBUG,
                   1985:                            "nd6_output: can't allocate llinfo for %s "
                   1986:                            "(ln=%p, rt=%p)\n",
                   1987:                            ip6_sprintf(&dst->sin6_addr), ln, rt);
                   1988:                        senderr(EIO);   /* XXX: good error? */
                   1989:                }
                   1990:
                   1991:                goto sendpkt;   /* send anyway */
1.2       itojun   1992:        }
                   1993:
1.26      itojun   1994:        /* We don't have to do link-layer address resolution on a p2p link. */
                   1995:        if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
1.42      itojun   1996:            ln->ln_state < ND6_LLINFO_REACHABLE) {
1.26      itojun   1997:                ln->ln_state = ND6_LLINFO_STALE;
1.86      itojun   1998:                nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.42      itojun   1999:        }
1.2       itojun   2000:
                   2001:        /*
                   2002:         * The first time we send a packet to a neighbor whose entry is
                   2003:         * STALE, we have to change the state to DELAY and a sets a timer to
                   2004:         * expire in DELAY_FIRST_PROBE_TIME seconds to ensure do
                   2005:         * neighbor unreachability detection on expiration.
                   2006:         * (RFC 2461 7.3.3)
                   2007:         */
                   2008:        if (ln->ln_state == ND6_LLINFO_STALE) {
                   2009:                ln->ln_asked = 0;
                   2010:                ln->ln_state = ND6_LLINFO_DELAY;
1.99      rpaulo   2011:                nd6_llinfo_settimer(ln, (long)nd6_delay * hz);
1.2       itojun   2012:        }
                   2013:
                   2014:        /*
                   2015:         * If the neighbor cache entry has a state other than INCOMPLETE
1.52      itojun   2016:         * (i.e. its link-layer address is already resolved), just
1.2       itojun   2017:         * send the packet.
                   2018:         */
                   2019:        if (ln->ln_state > ND6_LLINFO_INCOMPLETE)
                   2020:                goto sendpkt;
                   2021:
                   2022:        /*
                   2023:         * There is a neighbor cache entry, but no ethernet address
1.99      rpaulo   2024:         * response yet.  Append this latest packet to the end of the
                   2025:         * packet queue in the mbuf, unless the number of the packet
                   2026:         * does not exceed nd6_maxqueuelen.  When it exceeds nd6_maxqueuelen,
                   2027:         * the oldest packet in the queue will be removed.
1.2       itojun   2028:         */
1.41      itojun   2029:        if (ln->ln_state == ND6_LLINFO_NOSTATE)
1.2       itojun   2030:                ln->ln_state = ND6_LLINFO_INCOMPLETE;
1.99      rpaulo   2031:        if (ln->ln_hold) {
                   2032:                struct mbuf *m_hold;
                   2033:                int i;
                   2034:
                   2035:                i = 0;
                   2036:                for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) {
                   2037:                        i++;
                   2038:                        if (m_hold->m_nextpkt == NULL) {
                   2039:                                m_hold->m_nextpkt = m;
                   2040:                                break;
                   2041:                        }
                   2042:                }
                   2043:                while (i >= nd6_maxqueuelen) {
                   2044:                        m_hold = ln->ln_hold;
                   2045:                        ln->ln_hold = ln->ln_hold->m_nextpkt;
1.100     rpaulo   2046:                        m_freem(m_hold);
1.99      rpaulo   2047:                        i--;
                   2048:                }
                   2049:        } else {
                   2050:                ln->ln_hold = m;
                   2051:        }
                   2052:
1.64      itojun   2053:        /*
                   2054:         * If there has been no NS for the neighbor after entering the
                   2055:         * INCOMPLETE state, send the first solicitation.
                   2056:         */
1.86      itojun   2057:        if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
1.64      itojun   2058:                ln->ln_asked++;
1.86      itojun   2059:                nd6_llinfo_settimer(ln,
                   2060:                    (long)ND_IFINFO(ifp)->retrans * hz / 1000);
1.64      itojun   2061:                nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
1.2       itojun   2062:        }
1.112     dyoung   2063:        return 0;
1.63      itojun   2064:
1.2       itojun   2065:   sendpkt:
1.99      rpaulo   2066:        /* discard the packet if IPv6 operation is disabled on the interface */
                   2067:        if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
                   2068:                error = ENETDOWN; /* better error? */
                   2069:                goto bad;
                   2070:        }
1.30      itojun   2071:
1.78      itojun   2072: #ifdef IPSEC
                   2073:        /* clean ipsec history once it goes out of the node */
                   2074:        ipsec_delaux(m);
                   2075: #endif
1.127     dyoung   2076:        if ((ifp->if_flags & IFF_LOOPBACK) != 0)
1.114     dyoung   2077:                return (*ifp->if_output)(origifp, m, sin6tocsa(dst), rt);
                   2078:        return (*ifp->if_output)(ifp, m, sin6tocsa(dst), rt);
1.25      itojun   2079:
1.2       itojun   2080:   bad:
1.114     dyoung   2081:        if (m != NULL)
1.2       itojun   2082:                m_freem(m);
1.112     dyoung   2083:        return error;
1.63      itojun   2084: }
1.2       itojun   2085: #undef senderr
1.54      itojun   2086:
                   2087: int
1.112     dyoung   2088: nd6_need_cache(struct ifnet *ifp)
1.54      itojun   2089: {
                   2090:        /*
                   2091:         * XXX: we currently do not make neighbor cache on any interface
                   2092:         * other than ARCnet, Ethernet, FDDI and GIF.
                   2093:         *
                   2094:         * RFC2893 says:
                   2095:         * - unidirectional tunnels needs no ND
                   2096:         */
                   2097:        switch (ifp->if_type) {
                   2098:        case IFT_ARCNET:
                   2099:        case IFT_ETHER:
                   2100:        case IFT_FDDI:
                   2101:        case IFT_IEEE1394:
1.102     liamjfoy 2102:        case IFT_CARP:
1.54      itojun   2103:        case IFT_GIF:           /* XXX need more cases? */
1.99      rpaulo   2104:        case IFT_PPP:
                   2105:        case IFT_TUNNEL:
1.112     dyoung   2106:                return 1;
1.54      itojun   2107:        default:
1.112     dyoung   2108:                return 0;
1.54      itojun   2109:        }
                   2110: }
1.2       itojun   2111:
                   2112: int
1.110     dyoung   2113: nd6_storelladdr(const struct ifnet *ifp, const struct rtentry *rt,
1.127     dyoung   2114:     struct mbuf *m, const struct sockaddr *dst, uint8_t *lldst,
1.110     dyoung   2115:     size_t dstsize)
1.2       itojun   2116: {
1.110     dyoung   2117:        const struct sockaddr_dl *sdl;
1.2       itojun   2118:
                   2119:        if (m->m_flags & M_MCAST) {
                   2120:                switch (ifp->if_type) {
                   2121:                case IFT_ETHER:
1.63      itojun   2122:                case IFT_FDDI:
1.118     dyoung   2123:                        ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr,
                   2124:                            lldst);
1.110     dyoung   2125:                        return 1;
1.33      onoe     2126:                case IFT_IEEE1394:
1.118     dyoung   2127:                        memcpy(lldst, ifp->if_broadcastaddr,
                   2128:                            MIN(dstsize, ifp->if_addrlen));
1.110     dyoung   2129:                        return 1;
1.9       is       2130:                case IFT_ARCNET:
1.110     dyoung   2131:                        *lldst = 0;
                   2132:                        return 1;
1.2       itojun   2133:                default:
1.43      itojun   2134:                        m_freem(m);
1.110     dyoung   2135:                        return 0;
1.2       itojun   2136:                }
                   2137:        }
                   2138:
1.32      itojun   2139:        if (rt == NULL) {
                   2140:                /* this could happen, if we could not allocate memory */
1.43      itojun   2141:                m_freem(m);
1.110     dyoung   2142:                return 0;
1.32      itojun   2143:        }
                   2144:        if (rt->rt_gateway->sa_family != AF_LINK) {
1.110     dyoung   2145:                printf("%s: something odd happens\n", __func__);
1.43      itojun   2146:                m_freem(m);
1.110     dyoung   2147:                return 0;
1.2       itojun   2148:        }
1.118     dyoung   2149:        sdl = satocsdl(rt->rt_gateway);
1.110     dyoung   2150:        if (sdl->sdl_alen == 0 || sdl->sdl_alen > dstsize) {
1.24      itojun   2151:                /* this should be impossible, but we bark here for debugging */
1.110     dyoung   2152:                printf("%s: sdl_alen == 0, dst=%s, if=%s\n", __func__,
1.118     dyoung   2153:                    ip6_sprintf(&satocsin6(dst)->sin6_addr), if_name(ifp));
1.43      itojun   2154:                m_freem(m);
1.110     dyoung   2155:                return 0;
1.23      itojun   2156:        }
1.2       itojun   2157:
1.110     dyoung   2158:        memcpy(lldst, CLLADDR(sdl), MIN(dstsize, sdl->sdl_alen));
                   2159:        return 1;
1.65      itojun   2160: }
                   2161:
1.100     rpaulo   2162: static void
1.112     dyoung   2163: clear_llinfo_pqueue(struct llinfo_nd6 *ln)
1.100     rpaulo   2164: {
                   2165:        struct mbuf *m_hold, *m_hold_next;
                   2166:
                   2167:        for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) {
                   2168:                m_hold_next = m_hold->m_nextpkt;
                   2169:                m_hold->m_nextpkt = NULL;
                   2170:                m_freem(m_hold);
                   2171:        }
                   2172:
                   2173:        ln->ln_hold = NULL;
                   2174:        return;
                   2175: }
                   2176:
1.65      itojun   2177: int
1.105     christos 2178: nd6_sysctl(
                   2179:     int name,
                   2180:     void *oldp,        /* syscall arg, need copyout */
                   2181:     size_t *oldlenp,
                   2182:     void *newp,        /* syscall arg, need copyin */
1.107     christos 2183:     size_t newlen
1.105     christos 2184: )
1.65      itojun   2185: {
1.69      itojun   2186:        void *p;
1.88      simonb   2187:        size_t ol;
1.65      itojun   2188:        int error;
                   2189:
                   2190:        error = 0;
                   2191:
                   2192:        if (newp)
                   2193:                return EPERM;
                   2194:        if (oldp && !oldlenp)
                   2195:                return EINVAL;
                   2196:        ol = oldlenp ? *oldlenp : 0;
                   2197:
1.69      itojun   2198:        if (oldp) {
                   2199:                p = malloc(*oldlenp, M_TEMP, M_WAITOK);
1.99      rpaulo   2200:                if (p == NULL)
1.69      itojun   2201:                        return ENOMEM;
                   2202:        } else
                   2203:                p = NULL;
1.65      itojun   2204:        switch (name) {
                   2205:        case ICMPV6CTL_ND6_DRLIST:
1.69      itojun   2206:                error = fill_drlist(p, oldlenp, ol);
1.99      rpaulo   2207:                if (!error && p != NULL && oldp != NULL)
1.71      itojun   2208:                        error = copyout(p, oldp, *oldlenp);
1.65      itojun   2209:                break;
                   2210:
                   2211:        case ICMPV6CTL_ND6_PRLIST:
1.69      itojun   2212:                error = fill_prlist(p, oldlenp, ol);
1.99      rpaulo   2213:                if (!error && p != NULL && oldp != NULL)
1.71      itojun   2214:                        error = copyout(p, oldp, *oldlenp);
1.65      itojun   2215:                break;
                   2216:
1.99      rpaulo   2217:        case ICMPV6CTL_ND6_MAXQLEN:
                   2218:                break;
                   2219:
1.65      itojun   2220:        default:
                   2221:                error = ENOPROTOOPT;
                   2222:                break;
                   2223:        }
1.69      itojun   2224:        if (p)
                   2225:                free(p, M_TEMP);
1.65      itojun   2226:
1.112     dyoung   2227:        return error;
1.65      itojun   2228: }
                   2229:
                   2230: static int
1.112     dyoung   2231: fill_drlist(void *oldp, size_t *oldlenp, size_t ol)
1.65      itojun   2232: {
                   2233:        int error = 0, s;
                   2234:        struct in6_defrouter *d = NULL, *de = NULL;
                   2235:        struct nd_defrouter *dr;
                   2236:        size_t l;
                   2237:
                   2238:        s = splsoftnet();
1.66      itojun   2239:
1.65      itojun   2240:        if (oldp) {
                   2241:                d = (struct in6_defrouter *)oldp;
1.111     christos 2242:                de = (struct in6_defrouter *)((char *)oldp + *oldlenp);
1.65      itojun   2243:        }
                   2244:        l = 0;
                   2245:
1.108     dyoung   2246:        TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
1.65      itojun   2247:
                   2248:                if (oldp && d + 1 <= de) {
1.122     dyoung   2249:                        memset(d, 0, sizeof(*d));
                   2250:                        sockaddr_in6_init(&d->rtaddr, &dr->rtaddr, 0, 0, 0);
1.96      rpaulo   2251:                        if (sa6_recoverscope(&d->rtaddr)) {
                   2252:                                log(LOG_ERR,
                   2253:                                    "scope error in router list (%s)\n",
                   2254:                                    ip6_sprintf(&d->rtaddr.sin6_addr));
                   2255:                                /* XXX: press on... */
                   2256:                        }
1.65      itojun   2257:                        d->flags = dr->flags;
                   2258:                        d->rtlifetime = dr->rtlifetime;
                   2259:                        d->expire = dr->expire;
                   2260:                        d->if_index = dr->ifp->if_index;
                   2261:                }
                   2262:
                   2263:                l += sizeof(*d);
                   2264:                if (d)
                   2265:                        d++;
                   2266:        }
                   2267:
                   2268:        if (oldp) {
                   2269:                if (l > ol)
                   2270:                        error = ENOMEM;
1.101     christos 2271:        }
                   2272:        if (oldlenp)
1.111     christos 2273:                *oldlenp = l;   /* (void *)d - (void *)oldp */
1.65      itojun   2274:
                   2275:        splx(s);
                   2276:
1.112     dyoung   2277:        return error;
1.65      itojun   2278: }
                   2279:
                   2280: static int
1.112     dyoung   2281: fill_prlist(void *oldp, size_t *oldlenp, size_t ol)
1.65      itojun   2282: {
                   2283:        int error = 0, s;
                   2284:        struct nd_prefix *pr;
                   2285:        struct in6_prefix *p = NULL;
                   2286:        struct in6_prefix *pe = NULL;
                   2287:        size_t l;
                   2288:
                   2289:        s = splsoftnet();
                   2290:
                   2291:        if (oldp) {
                   2292:                p = (struct in6_prefix *)oldp;
1.111     christos 2293:                pe = (struct in6_prefix *)((char *)oldp + *oldlenp);
1.65      itojun   2294:        }
                   2295:        l = 0;
                   2296:
1.108     dyoung   2297:        LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
1.65      itojun   2298:                u_short advrtrs;
                   2299:                size_t advance;
                   2300:                struct sockaddr_in6 *sin6;
                   2301:                struct sockaddr_in6 *s6;
                   2302:                struct nd_pfxrouter *pfr;
                   2303:
                   2304:                if (oldp && p + 1 <= pe)
                   2305:                {
1.129     dyoung   2306:                        memset(p, 0, sizeof(*p));
1.65      itojun   2307:                        sin6 = (struct sockaddr_in6 *)(p + 1);
                   2308:
                   2309:                        p->prefix = pr->ndpr_prefix;
1.96      rpaulo   2310:                        if (sa6_recoverscope(&p->prefix)) {
1.65      itojun   2311:                                log(LOG_ERR,
                   2312:                                    "scope error in prefix list (%s)\n",
                   2313:                                    ip6_sprintf(&p->prefix.sin6_addr));
1.96      rpaulo   2314:                                /* XXX: press on... */
                   2315:                        }
1.65      itojun   2316:                        p->raflags = pr->ndpr_raf;
                   2317:                        p->prefixlen = pr->ndpr_plen;
                   2318:                        p->vltime = pr->ndpr_vltime;
                   2319:                        p->pltime = pr->ndpr_pltime;
                   2320:                        p->if_index = pr->ndpr_ifp->if_index;
                   2321:                        if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
                   2322:                                p->expire = 0;
                   2323:                        else {
                   2324:                                time_t maxexpire;
                   2325:
                   2326:                                /* XXX: we assume time_t is signed. */
                   2327:                                maxexpire = (-1) &
1.99      rpaulo   2328:                                    ~((time_t)1 <<
                   2329:                                    ((sizeof(maxexpire) * 8) - 1));
1.65      itojun   2330:                                if (pr->ndpr_vltime <
                   2331:                                    maxexpire - pr->ndpr_lastupdate) {
                   2332:                                        p->expire = pr->ndpr_lastupdate +
                   2333:                                                pr->ndpr_vltime;
                   2334:                                } else
                   2335:                                        p->expire = maxexpire;
                   2336:                        }
                   2337:                        p->refcnt = pr->ndpr_refcnt;
                   2338:                        p->flags = pr->ndpr_stateflags;
                   2339:                        p->origin = PR_ORIG_RA;
                   2340:                        advrtrs = 0;
1.108     dyoung   2341:                        LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
1.65      itojun   2342:                                if ((void *)&sin6[advrtrs + 1] > (void *)pe) {
                   2343:                                        advrtrs++;
                   2344:                                        continue;
                   2345:                                }
                   2346:                                s6 = &sin6[advrtrs];
1.122     dyoung   2347:                                sockaddr_in6_init(s6, &pfr->router->rtaddr,
                   2348:                                    0, 0, 0);
1.96      rpaulo   2349:                                if (sa6_recoverscope(s6)) {
                   2350:                                        log(LOG_ERR,
                   2351:                                            "scope error in "
                   2352:                                            "prefix list (%s)\n",
                   2353:                                            ip6_sprintf(&pfr->router->rtaddr));
                   2354:                                }
1.65      itojun   2355:                                advrtrs++;
                   2356:                        }
                   2357:                        p->advrtrs = advrtrs;
                   2358:                }
                   2359:                else {
                   2360:                        advrtrs = 0;
1.108     dyoung   2361:                        LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
1.65      itojun   2362:                                advrtrs++;
                   2363:                }
                   2364:
                   2365:                advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
                   2366:                l += advance;
                   2367:                if (p)
1.111     christos 2368:                        p = (struct in6_prefix *)((char *)p + advance);
1.65      itojun   2369:        }
                   2370:
                   2371:        if (oldp) {
1.111     christos 2372:                *oldlenp = l;   /* (void *)d - (void *)oldp */
1.65      itojun   2373:                if (l > ol)
                   2374:                        error = ENOMEM;
                   2375:        } else
                   2376:                *oldlenp = l;
                   2377:
                   2378:        splx(s);
                   2379:
1.112     dyoung   2380:        return error;
1.2       itojun   2381: }

CVSweb <webmaster@jp.NetBSD.org>