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

Annotation of src/sys/netinet6/nd6_rtr.c, Revision 1.142

1.142   ! maxv        1: /*     $NetBSD: nd6_rtr.c,v 1.141 2018/05/01 07:21:39 maxv Exp $       */
1.20      itojun      2: /*     $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $        */
1.3       thorpej     3:
1.2       itojun      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
1.16      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.16      itojun     19:  *
1.2       itojun     20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
1.27      lukem      32:
                     33: #include <sys/cdefs.h>
1.142   ! maxv       34: __KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.141 2018/05/01 07:21:39 maxv Exp $");
1.134     msaitoh    35:
                     36: #ifdef _KERNEL_OPT
                     37: #include "opt_net_mpsafe.h"
                     38: #endif
1.2       itojun     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/malloc.h>
                     43: #include <sys/mbuf.h>
                     44: #include <sys/socket.h>
                     45: #include <sys/sockio.h>
                     46: #include <sys/time.h>
                     47: #include <sys/kernel.h>
                     48: #include <sys/errno.h>
                     49: #include <sys/ioctl.h>
                     50: #include <sys/syslog.h>
1.82      tls        51: #include <sys/cprng.h>
1.2       itojun     52:
                     53: #include <net/if.h>
                     54: #include <net/if_types.h>
                     55: #include <net/if_dl.h>
                     56:
                     57: #include <netinet/in.h>
                     58: #include <netinet6/in6_var.h>
1.56      rpaulo     59: #include <netinet6/in6_ifattach.h>
1.11      itojun     60: #include <netinet/ip6.h>
1.2       itojun     61: #include <netinet6/ip6_var.h>
                     62: #include <netinet6/nd6.h>
1.11      itojun     63: #include <netinet/icmp6.h>
1.75      thorpej    64: #include <netinet6/icmp6_private.h>
1.54      rpaulo     65: #include <netinet6/scope6_var.h>
1.2       itojun     66:
1.68      dyoung     67: static int rtpref(struct nd_defrouter *);
                     68: static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
                     69: static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
                     70:     struct mbuf *, int);
1.118     ozaki-r    71: static struct in6_ifaddr *in6_ifadd(struct nd_prefixctl *, int, struct psref *);
1.68      dyoung     72: static struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *,
                     73:        struct nd_defrouter *);
                     74: static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
                     75: static void pfxrtr_del(struct nd_pfxrouter *);
1.32      itojun     76: static struct nd_pfxrouter *find_pfxlist_reachable_router
1.68      dyoung     77:        (struct nd_prefix *);
1.121     ozaki-r    78:
                     79: static void defrouter_addreq(struct nd_defrouter *);
1.68      dyoung     80: static void defrouter_delreq(struct nd_defrouter *);
                     81:
                     82: static int in6_init_prefix_ltimes(struct nd_prefix *);
1.83      christos   83: static void in6_init_address_ltimes(struct nd_prefix *,
                     84:        struct in6_addrlifetime *);
                     85: static void purge_detached(struct ifnet *);
1.2       itojun     86:
1.120     ozaki-r    87: static int rt6_deleteroute_matcher(struct rtentry *, void *);
1.2       itojun     88:
1.121     ozaki-r    89: static int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *,
                     90:        struct nd_prefix **);
                     91: static int nd6_prefix_onlink(struct nd_prefix *);
                     92: static int nd6_prefix_offlink(struct nd_prefix *);
                     93: static struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *);
                     94:
1.2       itojun     95: extern int nd6_recalc_reachtm_interval;
                     96:
1.56      rpaulo     97: int ip6_use_tempaddr = 0;
                     98:
                     99: int ip6_desync_factor;
                    100: u_int32_t ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
                    101: u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
                    102: int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
                    103:
1.81      spz       104: int nd6_numroutes = 0;
                    105:
1.56      rpaulo    106: /* RTPREF_MEDIUM has to be 0! */
                    107: #define RTPREF_HIGH    1
                    108: #define RTPREF_MEDIUM  0
                    109: #define RTPREF_LOW     (-1)
                    110: #define RTPREF_RESERVED        (-2)
                    111: #define RTPREF_INVALID (-3)    /* internal */
                    112:
1.101     ozaki-r   113: static inline bool
                    114: nd6_is_llinfo_probreach(struct nd_defrouter *dr)
                    115: {
1.105     ozaki-r   116:        struct llentry *ln = NULL;
1.101     ozaki-r   117:
1.108     ozaki-r   118:        ln = nd6_lookup(&dr->rtaddr, dr->ifp, false);
                    119:        if (ln == NULL)
1.101     ozaki-r   120:                return false;
1.108     ozaki-r   121:
                    122:        if (!ND6_IS_LLINFO_PROBREACH(ln)) {
                    123:                LLE_RUNLOCK(ln);
1.101     ozaki-r   124:                return false;
1.108     ozaki-r   125:        }
1.101     ozaki-r   126:
1.108     ozaki-r   127:        LLE_RUNLOCK(ln);
1.101     ozaki-r   128:        return true;
                    129: }
                    130:
1.2       itojun    131: /*
                    132:  * Receive Router Solicitation Message - just for routers.
1.81      spz       133:  * Router solicitation/advertisement is mostly managed by a userland program
1.2       itojun    134:  * (rtadvd) so here we have no function like nd6_ra_output().
                    135:  *
                    136:  * Based on RFC 2461
                    137:  */
                    138: void
1.64      christos  139: nd6_rs_input(struct mbuf *m, int off, int icmp6len)
1.2       itojun    140: {
1.111     ozaki-r   141:        struct ifnet *ifp;
                    142:        struct nd_ifinfo *ndi;
1.2       itojun    143:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1.12      itojun    144:        struct nd_router_solicit *nd_rs;
1.2       itojun    145:        struct in6_addr saddr6 = ip6->ip6_src;
                    146:        char *lladdr = NULL;
                    147:        int lladdrlen = 0;
                    148:        union nd_opts ndopts;
1.111     ozaki-r   149:        struct psref psref;
1.130     ryo       150:        char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1.111     ozaki-r   151:
                    152:        ifp = m_get_rcvif_psref(m, &psref);
                    153:        if (ifp == NULL)
                    154:                goto freeit;
                    155:
                    156:        ndi = ND_IFINFO(ifp);
1.2       itojun    157:
                    158:        /* If I'm not a router, ignore it. */
1.80      dyoung    159:        if (nd6_accepts_rtadv(ndi) || !ip6_forwarding)
1.12      itojun    160:                goto freeit;
1.2       itojun    161:
                    162:        /* Sanity checks */
                    163:        if (ip6->ip6_hlim != 255) {
1.107     ozaki-r   164:                nd6log(LOG_ERR, "invalid hlim (%d) from %s to %s on %s\n",
1.131     christos  165:                    ip6->ip6_hlim, IN6_PRINT(ip6bufs, &ip6->ip6_src),
                    166:                    IN6_PRINT(ip6bufd, &ip6->ip6_dst), if_name(ifp));
1.20      itojun    167:                goto bad;
1.2       itojun    168:        }
                    169:
                    170:        /*
                    171:         * Don't update the neighbor cache, if src = ::.
                    172:         * This indicates that the src has no IP address assigned yet.
                    173:         */
                    174:        if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
1.12      itojun    175:                goto freeit;
                    176:
                    177:        IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
                    178:        if (nd_rs == NULL) {
1.75      thorpej   179:                ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
1.142   ! maxv      180:                m_put_rcvif_psref(ifp, &psref);
1.2       itojun    181:                return;
1.12      itojun    182:        }
1.2       itojun    183:
                    184:        icmp6len -= sizeof(*nd_rs);
                    185:        nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
                    186:        if (nd6_options(&ndopts) < 0) {
1.107     ozaki-r   187:                nd6log(LOG_INFO, "invalid ND option, ignored\n");
1.20      itojun    188:                /* nd6_options have incremented stats */
1.12      itojun    189:                goto freeit;
1.2       itojun    190:        }
                    191:
                    192:        if (ndopts.nd_opts_src_lladdr) {
                    193:                lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
                    194:                lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
                    195:        }
                    196:
                    197:        if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
1.107     ozaki-r   198:                nd6log(LOG_INFO, "lladdrlen mismatch for %s "
1.2       itojun    199:                    "(if %d, RS packet %d)\n",
1.131     christos  200:                    IN6_PRINT(ip6bufs, &saddr6),
1.130     ryo       201:                    ifp->if_addrlen, lladdrlen - 2);
1.20      itojun    202:                goto bad;
1.2       itojun    203:        }
                    204:
1.6       itojun    205:        nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
1.12      itojun    206:
                    207:  freeit:
1.111     ozaki-r   208:        m_put_rcvif_psref(ifp, &psref);
1.12      itojun    209:        m_freem(m);
1.20      itojun    210:        return;
                    211:
                    212:  bad:
1.75      thorpej   213:        ICMP6_STATINC(ICMP6_STAT_BADRS);
1.111     ozaki-r   214:        m_put_rcvif_psref(ifp, &psref);
1.20      itojun    215:        m_freem(m);
1.2       itojun    216: }
                    217:
                    218: /*
                    219:  * Receive Router Advertisement Message.
                    220:  *
                    221:  * Based on RFC 2461
                    222:  * TODO: on-link bit on prefix information
                    223:  * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
                    224:  */
                    225: void
1.64      christos  226: nd6_ra_input(struct mbuf *m, int off, int icmp6len)
1.2       itojun    227: {
1.111     ozaki-r   228:        struct ifnet *ifp;
                    229:        struct nd_ifinfo *ndi;
1.2       itojun    230:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1.12      itojun    231:        struct nd_router_advert *nd_ra;
1.2       itojun    232:        struct in6_addr saddr6 = ip6->ip6_src;
                    233: #if 0
                    234:        struct in6_addr daddr6 = ip6->ip6_dst;
1.12      itojun    235:        int flags; /* = nd_ra->nd_ra_flags_reserved; */
1.2       itojun    236:        int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0);
                    237:        int is_other = ((flags & ND_RA_FLAG_OTHER) != 0);
                    238: #endif
1.56      rpaulo    239:        int mcast = 0;
1.2       itojun    240:        union nd_opts ndopts;
                    241:        struct nd_defrouter *dr;
1.111     ozaki-r   242:        struct psref psref;
1.130     ryo       243:        char ip6buf[INET6_ADDRSTRLEN], ip6buf2[INET6_ADDRSTRLEN];
1.111     ozaki-r   244:
                    245:        ifp = m_get_rcvif_psref(m, &psref);
                    246:        if (ifp == NULL)
                    247:                goto freeit;
1.2       itojun    248:
1.111     ozaki-r   249:        ndi = ND_IFINFO(ifp);
1.32      itojun    250:        /*
1.81      spz       251:         * We only accept RAs when
                    252:         * the system-wide variable allows the acceptance, and the
1.33      itojun    253:         * per-interface variable allows RAs on the receiving interface.
1.32      itojun    254:         */
1.80      dyoung    255:        if (!nd6_accepts_rtadv(ndi))
1.32      itojun    256:                goto freeit;
1.2       itojun    257:
                    258:        if (ip6->ip6_hlim != 255) {
1.107     ozaki-r   259:                nd6log(LOG_ERR, "invalid hlim (%d) from %s to %s on %s\n",
1.131     christos  260:                    ip6->ip6_hlim, IN6_PRINT(ip6buf, &ip6->ip6_src),
                    261:                    IN6_PRINT(ip6buf2, &ip6->ip6_dst), if_name(ifp));
1.20      itojun    262:                goto bad;
1.2       itojun    263:        }
                    264:
                    265:        if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
1.107     ozaki-r   266:                nd6log(LOG_ERR, "src %s is not link-local\n",
1.131     christos  267:                    IN6_PRINT(ip6buf, &saddr6));
1.20      itojun    268:                goto bad;
1.12      itojun    269:        }
                    270:
                    271:        IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
                    272:        if (nd_ra == NULL) {
1.75      thorpej   273:                ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
1.111     ozaki-r   274:                m_put_rcvif_psref(ifp, &psref);
1.2       itojun    275:                return;
                    276:        }
                    277:
                    278:        icmp6len -= sizeof(*nd_ra);
                    279:        nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
                    280:        if (nd6_options(&ndopts) < 0) {
1.107     ozaki-r   281:                nd6log(LOG_INFO, "invalid ND option, ignored\n");
1.20      itojun    282:                /* nd6_options have incremented stats */
1.12      itojun    283:                goto freeit;
1.2       itojun    284:        }
                    285:
                    286:     {
1.52      christos  287:        struct nd_defrouter drtr;
1.2       itojun    288:        u_int32_t advreachable = nd_ra->nd_ra_reachable;
                    289:
1.56      rpaulo    290:        /* remember if this is a multicasted advertisement */
                    291:        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
                    292:                mcast = 1;
                    293:
                    294:        memset(&drtr, 0, sizeof(drtr));
1.52      christos  295:        drtr.rtaddr = saddr6;
                    296:        drtr.flags  = nd_ra->nd_ra_flags_reserved;
1.58      rpaulo    297:        drtr.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
1.102     ozaki-r   298:        drtr.expire = time_uptime + drtr.rtlifetime;
1.52      christos  299:        drtr.ifp = ifp;
1.2       itojun    300:        /* unspecified or not? (RFC 2461 6.3.4) */
                    301:        if (advreachable) {
                    302:                NTOHL(advreachable);
                    303:                if (advreachable <= MAX_REACHABLE_TIME &&
                    304:                    ndi->basereachable != advreachable) {
                    305:                        ndi->basereachable = advreachable;
                    306:                        ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
                    307:                        ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
                    308:                }
                    309:        }
                    310:        if (nd_ra->nd_ra_retransmit)
                    311:                ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
1.99      roy       312:        if (nd_ra->nd_ra_curhoplimit) {
                    313:                if (ndi->chlim < nd_ra->nd_ra_curhoplimit)
                    314:                        ndi->chlim = nd_ra->nd_ra_curhoplimit;
                    315:                else if (ndi->chlim != nd_ra->nd_ra_curhoplimit)
                    316:                        log(LOG_ERR, "nd_ra_input: lower CurHopLimit sent from "
                    317:                           "%s on %s (current=%d, received=%d), ignored\n",
1.131     christos  318:                           IN6_PRINT(ip6buf, &ip6->ip6_src),
1.99      roy       319:                           if_name(ifp), ndi->chlim, nd_ra->nd_ra_curhoplimit);
                    320:        }
1.136     ozaki-r   321:        IFNET_LOCK(ifp);
1.128     ozaki-r   322:        ND6_WLOCK();
1.52      christos  323:        dr = defrtrlist_update(&drtr);
1.2       itojun    324:     }
                    325:
                    326:        /*
                    327:         * prefix
                    328:         */
                    329:        if (ndopts.nd_opts_pi) {
                    330:                struct nd_opt_hdr *pt;
1.32      itojun    331:                struct nd_opt_prefix_info *pi = NULL;
1.94      matt      332:                struct nd_prefixctl prc;
1.2       itojun    333:
                    334:                for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
                    335:                     pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
1.63      christos  336:                     pt = (struct nd_opt_hdr *)((char *)pt +
1.2       itojun    337:                                                (pt->nd_opt_len << 3))) {
                    338:                        if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
                    339:                                continue;
                    340:                        pi = (struct nd_opt_prefix_info *)pt;
                    341:
                    342:                        if (pi->nd_opt_pi_len != 4) {
1.107     ozaki-r   343:                                nd6log(LOG_INFO, "invalid option "
1.22      itojun    344:                                    "len %d for prefix information option, "
1.107     ozaki-r   345:                                    "ignored\n", pi->nd_opt_pi_len);
1.2       itojun    346:                                continue;
                    347:                        }
                    348:
                    349:                        if (128 < pi->nd_opt_pi_prefix_len) {
1.107     ozaki-r   350:                                nd6log(LOG_INFO, "invalid prefix "
1.22      itojun    351:                                    "len %d for prefix information option, "
1.107     ozaki-r   352:                                    "ignored\n", pi->nd_opt_pi_prefix_len);
1.2       itojun    353:                                continue;
                    354:                        }
                    355:
                    356:                        if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
                    357:                         || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
1.107     ozaki-r   358:                                nd6log(LOG_INFO,
                    359:                                    "invalid prefix %s, ignored\n",
1.131     christos  360:                                    IN6_PRINT(ip6buf, &pi->nd_opt_pi_prefix));
1.2       itojun    361:                                continue;
                    362:                        }
                    363:
1.94      matt      364:                        memset(&prc, 0, sizeof(prc));
                    365:                        sockaddr_in6_init(&prc.ndprc_prefix,
1.69      dyoung    366:                            &pi->nd_opt_pi_prefix, 0, 0, 0);
1.111     ozaki-r   367:                        prc.ndprc_ifp = ifp;
1.2       itojun    368:
1.94      matt      369:                        prc.ndprc_raf_onlink = (pi->nd_opt_pi_flags_reserved &
1.56      rpaulo    370:                            ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
1.94      matt      371:                        prc.ndprc_raf_auto = (pi->nd_opt_pi_flags_reserved &
1.56      rpaulo    372:                            ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
1.94      matt      373:                        prc.ndprc_plen = pi->nd_opt_pi_prefix_len;
                    374:                        prc.ndprc_vltime = ntohl(pi->nd_opt_pi_valid_time);
                    375:                        prc.ndprc_pltime = ntohl(pi->nd_opt_pi_preferred_time);
1.2       itojun    376:
1.94      matt      377:                        (void)prelist_update(&prc, dr, m, mcast);
1.2       itojun    378:                }
                    379:        }
1.128     ozaki-r   380:        ND6_UNLOCK();
1.136     ozaki-r   381:        IFNET_UNLOCK(ifp);
1.2       itojun    382:
                    383:        /*
                    384:         * MTU
                    385:         */
                    386:        if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
1.32      itojun    387:                u_long mtu;
1.30      itojun    388:                u_long maxmtu;
1.2       itojun    389:
1.32      itojun    390:                mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
                    391:
1.2       itojun    392:                /* lower bound */
                    393:                if (mtu < IPV6_MMTU) {
1.107     ozaki-r   394:                        nd6log(LOG_INFO, "bogus mtu option "
1.32      itojun    395:                            "mtu=%lu sent from %s, ignoring\n",
1.131     christos  396:                            mtu, IN6_PRINT(ip6buf, &ip6->ip6_src));
1.2       itojun    397:                        goto skip;
                    398:                }
                    399:
                    400:                /* upper bound */
1.30      itojun    401:                maxmtu = (ndi->maxmtu && ndi->maxmtu < ifp->if_mtu)
                    402:                    ? ndi->maxmtu : ifp->if_mtu;
                    403:                if (mtu <= maxmtu) {
                    404:                        int change = (ndi->linkmtu != mtu);
                    405:
                    406:                        ndi->linkmtu = mtu;
                    407:                        if (change) /* in6_maxmtu may change */
                    408:                                in6_setmaxmtu();
1.2       itojun    409:                } else {
1.107     ozaki-r   410:                        nd6log(LOG_INFO,
                    411:                            "bogus mtu mtu=%lu sent from %s; "
1.30      itojun    412:                            "exceeds maxmtu %lu, ignoring\n",
1.131     christos  413:                            mtu, IN6_PRINT(ip6buf, &ip6->ip6_src), maxmtu);
1.2       itojun    414:                }
                    415:        }
                    416:
                    417:  skip:
1.33      itojun    418:
1.2       itojun    419:        /*
1.26      itojun    420:         * Source link layer address
1.2       itojun    421:         */
                    422:     {
                    423:        char *lladdr = NULL;
                    424:        int lladdrlen = 0;
1.33      itojun    425:
1.2       itojun    426:        if (ndopts.nd_opts_src_lladdr) {
                    427:                lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
                    428:                lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
                    429:        }
                    430:
                    431:        if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
1.107     ozaki-r   432:                nd6log(LOG_INFO, "lladdrlen mismatch for %s "
1.131     christos  433:                    "(if %d, RA packet %d)\n", IN6_PRINT(ip6buf, &saddr6),
1.107     ozaki-r   434:                    ifp->if_addrlen, lladdrlen - 2);
1.20      itojun    435:                goto bad;
1.2       itojun    436:        }
                    437:
1.6       itojun    438:        nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
1.7       itojun    439:
                    440:        /*
                    441:         * Installing a link-layer address might change the state of the
                    442:         * router's neighbor cache, which might also affect our on-link
                    443:         * detection of adveritsed prefixes.
                    444:         */
1.128     ozaki-r   445:        ND6_WLOCK();
1.123     ozaki-r   446:        nd6_pfxlist_onlink_check();
1.128     ozaki-r   447:        ND6_UNLOCK();
1.2       itojun    448:     }
1.12      itojun    449:
1.20      itojun    450:  freeit:
1.111     ozaki-r   451:        m_put_rcvif_psref(ifp, &psref);
1.20      itojun    452:        m_freem(m);
                    453:        return;
                    454:
                    455:  bad:
1.75      thorpej   456:        ICMP6_STATINC(ICMP6_STAT_BADRA);
1.111     ozaki-r   457:        m_put_rcvif_psref(ifp, &psref);
1.12      itojun    458:        m_freem(m);
1.2       itojun    459: }
                    460:
                    461: /*
1.45      wiz       462:  * default router list processing sub routines
1.2       itojun    463:  */
1.121     ozaki-r   464: static void
1.94      matt      465: defrouter_addreq(struct nd_defrouter *newdr)
1.2       itojun    466: {
1.76      dyoung    467:        union {
                    468:                struct sockaddr_in6 sin6;
                    469:                struct sockaddr sa;
                    470:        } def, mask, gate;
1.138     ozaki-r   471: #ifndef NET_MPSAFE
1.137     ozaki-r   472:        int s;
1.138     ozaki-r   473: #endif
1.32      itojun    474:        int error;
1.2       itojun    475:
1.56      rpaulo    476:        memset(&def, 0, sizeof(def));
                    477:        memset(&mask, 0, sizeof(mask));
                    478:        memset(&gate, 0,sizeof(gate)); /* for safety */
1.2       itojun    479:
1.76      dyoung    480:        def.sin6.sin6_len = mask.sin6.sin6_len = gate.sin6.sin6_len =
1.32      itojun    481:            sizeof(struct sockaddr_in6);
1.76      dyoung    482:        def.sin6.sin6_family = mask.sin6.sin6_family = gate.sin6.sin6_family = AF_INET6;
1.94      matt      483:        gate.sin6.sin6_addr = newdr->rtaddr;
1.32      itojun    484: #ifndef SCOPEDROUTING
1.76      dyoung    485:        gate.sin6.sin6_scope_id = 0;    /* XXX */
1.32      itojun    486: #endif
1.2       itojun    487:
1.138     ozaki-r   488: #ifndef NET_MPSAFE
1.137     ozaki-r   489:        s = splsoftnet();
1.138     ozaki-r   490: #endif
1.101     ozaki-r   491:        error = rtrequest_newmsg(RTM_ADD, &def.sa, &gate.sa, &mask.sa,
                    492:            RTF_GATEWAY);
                    493:        if (error == 0) {
1.81      spz       494:                nd6_numroutes++;
1.101     ozaki-r   495:                newdr->installed = 1;
1.32      itojun    496:        }
1.138     ozaki-r   497: #ifndef NET_MPSAFE
1.137     ozaki-r   498:        splx(s);
1.138     ozaki-r   499: #endif
1.2       itojun    500:        return;
                    501: }
                    502:
                    503: struct nd_defrouter *
1.123     ozaki-r   504: nd6_defrouter_lookup(const struct in6_addr *addr, struct ifnet *ifp)
1.2       itojun    505: {
                    506:        struct nd_defrouter *dr;
                    507:
1.128     ozaki-r   508:        ND6_ASSERT_LOCK();
                    509:
1.124     ozaki-r   510:        ND_DEFROUTER_LIST_FOREACH(dr) {
1.66      dyoung    511:                if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
                    512:                        break;
1.7       itojun    513:        }
1.2       itojun    514:
1.66      dyoung    515:        return dr;              /* search failed */
1.2       itojun    516: }
                    517:
                    518: void
1.123     ozaki-r   519: nd6_defrtrlist_del(struct nd_defrouter *dr, struct in6_ifextra *ext)
1.2       itojun    520: {
                    521:        struct nd_defrouter *deldr = NULL;
                    522:        struct nd_prefix *pr;
1.96      martin    523:        struct nd_ifinfo *ndi;
                    524:
1.128     ozaki-r   525:        ND6_ASSERT_WLOCK();
                    526:
1.96      martin    527:        if (ext == NULL)
                    528:                ext = dr->ifp->if_afdata[AF_INET6];
                    529:
                    530:        /* detach already in progress, can not do anything */
                    531:        if (ext == NULL)
                    532:                return;
                    533:
                    534:        ndi = ext->nd_ifinfo;
1.2       itojun    535:
                    536:        /*
                    537:         * Flush all the routing table entries that use the router
                    538:         * as a next hop.
                    539:         */
1.79      tonnerre  540:        /* XXX: better condition? */
1.80      dyoung    541:        if (!ip6_forwarding && nd6_accepts_rtadv(ndi))
1.123     ozaki-r   542:                nd6_rt_flush(&dr->rtaddr, dr->ifp);
1.32      itojun    543:
                    544:        if (dr->installed) {
                    545:                deldr = dr;
                    546:                defrouter_delreq(dr);
1.2       itojun    547:        }
1.124     ozaki-r   548:        ND_DEFROUTER_LIST_REMOVE(dr);
1.2       itojun    549:
                    550:        /*
                    551:         * Also delete all the pointers to the router in each prefix lists.
                    552:         */
1.125     ozaki-r   553:        ND_PREFIX_LIST_FOREACH(pr) {
1.2       itojun    554:                struct nd_pfxrouter *pfxrtr;
                    555:                if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
                    556:                        pfxrtr_del(pfxrtr);
                    557:        }
1.123     ozaki-r   558:        nd6_pfxlist_onlink_check();
1.2       itojun    559:
                    560:        /*
1.7       itojun    561:         * If the router is the primary one, choose a new one.
1.123     ozaki-r   562:         * Note that nd6_defrouter_select() will remove the current gateway
1.7       itojun    563:         * from the routing table.
1.2       itojun    564:         */
                    565:        if (deldr)
1.123     ozaki-r   566:                nd6_defrouter_select();
1.7       itojun    567:
1.83      christos  568:        ext->ndefrouters--;
                    569:        if (ext->ndefrouters < 0) {
1.123     ozaki-r   570:                log(LOG_WARNING, "nd6_defrtrlist_del: negative count on %s\n",
1.83      christos  571:                    dr->ifp->if_xname);
                    572:        }
                    573:
1.2       itojun    574:        free(dr, M_IP6NDP);
                    575: }
                    576:
1.7       itojun    577: /*
1.32      itojun    578:  * Remove the default route for a given router.
1.123     ozaki-r   579:  * This is just a subroutine function for nd6_defrouter_select(), and should
1.32      itojun    580:  * not be called from anywhere else.
                    581:  */
                    582: static void
1.64      christos  583: defrouter_delreq(struct nd_defrouter *dr)
1.32      itojun    584: {
1.76      dyoung    585:        union {
                    586:                struct sockaddr_in6 sin6;
                    587:                struct sockaddr sa;
                    588:        } def, mask, gw;
1.101     ozaki-r   589:        int error;
1.32      itojun    590:
1.76      dyoung    591:        memset(&def, 0, sizeof(def));
                    592:        memset(&mask, 0, sizeof(mask));
                    593:        memset(&gw, 0, sizeof(gw));     /* for safety */
1.32      itojun    594:
1.76      dyoung    595:        def.sin6.sin6_len = mask.sin6.sin6_len = gw.sin6.sin6_len =
1.32      itojun    596:            sizeof(struct sockaddr_in6);
1.76      dyoung    597:        def.sin6.sin6_family = mask.sin6.sin6_family = gw.sin6.sin6_family = AF_INET6;
                    598:        gw.sin6.sin6_addr = dr->rtaddr;
1.32      itojun    599: #ifndef SCOPEDROUTING
1.76      dyoung    600:        gw.sin6.sin6_scope_id = 0;      /* XXX */
1.32      itojun    601: #endif
                    602:
1.101     ozaki-r   603:        error = rtrequest_newmsg(RTM_DELETE, &def.sa, &gw.sa, &mask.sa,
                    604:            RTF_GATEWAY);
                    605:        if (error == 0)
1.100     ozaki-r   606:                nd6_numroutes--;
1.32      itojun    607:
1.35      itojun    608:        dr->installed = 0;
1.32      itojun    609: }
                    610:
                    611: /*
                    612:  * remove all default routes from default router list
                    613:  */
                    614: void
1.123     ozaki-r   615: nd6_defrouter_reset(void)
1.32      itojun    616: {
                    617:        struct nd_defrouter *dr;
                    618:
1.128     ozaki-r   619:        ND6_ASSERT_WLOCK();
                    620:
1.124     ozaki-r   621:        ND_DEFROUTER_LIST_FOREACH(dr)
1.32      itojun    622:                defrouter_delreq(dr);
                    623:
                    624:        /*
                    625:         * XXX should we also nuke any default routers in the kernel, by
                    626:         * going through them by rtalloc1()?
                    627:         */
                    628: }
                    629:
                    630: /*
                    631:  * Default Router Selection according to Section 6.3.6 of RFC 2461 and
                    632:  * draft-ietf-ipngwg-router-selection:
                    633:  * 1) Routers that are reachable or probably reachable should be preferred.
                    634:  *    If we have more than one (probably) reachable router, prefer ones
                    635:  *    with the highest router preference.
1.7       itojun    636:  * 2) When no routers on the list are known to be reachable or
                    637:  *    probably reachable, routers SHOULD be selected in a round-robin
1.32      itojun    638:  *    fashion, regardless of router preference values.
1.7       itojun    639:  * 3) If the Default Router List is empty, assume that all
                    640:  *    destinations are on-link.
1.32      itojun    641:  *
                    642:  * We assume nd_defrouter is sorted by router preference value.
                    643:  * Since the code below covers both with and without router preference cases,
                    644:  * we do not need to classify the cases by ifdef.
                    645:  *
                    646:  * At this moment, we do not try to install more than one default router,
                    647:  * even when the multipath routing is available, because we're not sure about
                    648:  * the benefits for stub hosts comparing to the risk of making the code
                    649:  * complicated and the possibility of introducing bugs.
1.7       itojun    650:  */
                    651: void
1.123     ozaki-r   652: nd6_defrouter_select(void)
1.7       itojun    653: {
1.79      tonnerre  654:        struct nd_ifinfo *ndi;
1.32      itojun    655:        struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
1.7       itojun    656:
1.128     ozaki-r   657:        ND6_ASSERT_WLOCK();
                    658:
1.7       itojun    659:        /*
1.32      itojun    660:         * This function should be called only when acting as an autoconfigured
                    661:         * host.  Although the remaining part of this function is not effective
                    662:         * if the node is not an autoconfigured host, we explicitly exclude
                    663:         * such cases here for safety.
1.7       itojun    664:         */
1.79      tonnerre  665:        if (ip6_forwarding) {
1.107     ozaki-r   666:                nd6log(LOG_WARNING, "called unexpectedly (forwarding=%d, "
                    667:                    "accept_rtadv=%d)\n", ip6_forwarding, ip6_accept_rtadv);
1.32      itojun    668:                return;
1.7       itojun    669:        }
                    670:
1.32      itojun    671:        /*
                    672:         * Let's handle easy case (3) first:
1.49      itojun    673:         * If default router list is empty, there's nothing to be done.
1.32      itojun    674:         */
1.128     ozaki-r   675:        if (ND_DEFROUTER_LIST_EMPTY())
1.32      itojun    676:                return;
                    677:
                    678:        /*
                    679:         * Search for a (probably) reachable router from the list.
                    680:         * We just pick up the first reachable one (if any), assuming that
                    681:         * the ordering rule of the list described in defrtrlist_update().
                    682:         */
1.124     ozaki-r   683:        ND_DEFROUTER_LIST_FOREACH(dr) {
1.79      tonnerre  684:                ndi = ND_IFINFO(dr->ifp);
1.80      dyoung    685:                if (nd6_accepts_rtadv(ndi))
1.79      tonnerre  686:                        continue;
                    687:
1.56      rpaulo    688:                if (selected_dr == NULL &&
1.101     ozaki-r   689:                    nd6_is_llinfo_probreach(dr))
1.32      itojun    690:                        selected_dr = dr;
                    691:
                    692:                if (dr->installed && !installed_dr)
                    693:                        installed_dr = dr;
                    694:                else if (dr->installed && installed_dr) {
                    695:                        /* this should not happen.  warn for diagnosis. */
1.123     ozaki-r   696:                        log(LOG_ERR, "nd6_defrouter_select: more than one router"
1.32      itojun    697:                            " is installed\n");
                    698:                }
                    699:        }
                    700:        /*
                    701:         * If none of the default routers was found to be reachable,
                    702:         * round-robin the list regardless of preference.
                    703:         * Otherwise, if we have an installed router, check if the selected
                    704:         * (reachable) router should really be preferred to the installed one.
                    705:         * We only prefer the new router when the old one is not reachable
                    706:         * or when the new one has a really higher preference value.
                    707:         */
1.56      rpaulo    708:        if (selected_dr == NULL) {
1.124     ozaki-r   709:                if (installed_dr == NULL ||
                    710:                    ND_DEFROUTER_LIST_NEXT(installed_dr) == NULL)
                    711:                        selected_dr = ND_DEFROUTER_LIST_FIRST();
1.32      itojun    712:                else
1.124     ozaki-r   713:                        selected_dr = ND_DEFROUTER_LIST_NEXT(installed_dr);
1.32      itojun    714:        } else if (installed_dr &&
1.101     ozaki-r   715:            nd6_is_llinfo_probreach(installed_dr) &&
1.32      itojun    716:            rtpref(selected_dr) <= rtpref(installed_dr)) {
                    717:                selected_dr = installed_dr;
                    718:        }
                    719:
                    720:        /*
                    721:         * If the selected router is different than the installed one,
                    722:         * remove the installed router and install the selected one.
                    723:         * Note that the selected router is never NULL here.
                    724:         */
                    725:        if (installed_dr != selected_dr) {
                    726:                if (installed_dr)
                    727:                        defrouter_delreq(installed_dr);
                    728:                defrouter_addreq(selected_dr);
1.7       itojun    729:        }
                    730:
                    731:        return;
                    732: }
                    733:
1.32      itojun    734: /*
                    735:  * for default router selection
                    736:  * regards router-preference field as a 2-bit signed integer
                    737:  */
                    738: static int
                    739: rtpref(struct nd_defrouter *dr)
                    740: {
                    741:        switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
                    742:        case ND_RA_FLAG_RTPREF_HIGH:
1.56      rpaulo    743:                return (RTPREF_HIGH);
1.32      itojun    744:        case ND_RA_FLAG_RTPREF_MEDIUM:
1.58      rpaulo    745:        case ND_RA_FLAG_RTPREF_RSV:
1.56      rpaulo    746:                return (RTPREF_MEDIUM);
1.32      itojun    747:        case ND_RA_FLAG_RTPREF_LOW:
1.56      rpaulo    748:                return (RTPREF_LOW);
1.32      itojun    749:        default:
                    750:                /*
                    751:                 * This case should never happen.  If it did, it would mean a
                    752:                 * serious bug of kernel internal.  We thus always bark here.
                    753:                 * Or, can we even panic?
                    754:                 */
1.56      rpaulo    755:                log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->flags);
                    756:                return (RTPREF_INVALID);
1.32      itojun    757:        }
                    758:        /* NOTREACHED */
                    759: }
                    760:
1.2       itojun    761: static struct nd_defrouter *
1.94      matt      762: defrtrlist_update(struct nd_defrouter *newdr)
1.2       itojun    763: {
1.127     ozaki-r   764:        struct nd_defrouter *dr, *n, *ret = NULL;
1.94      matt      765:        struct in6_ifextra *ext = newdr->ifp->if_afdata[AF_INET6];
1.128     ozaki-r   766:
                    767:        ND6_ASSERT_WLOCK();
1.2       itojun    768:
1.123     ozaki-r   769:        if ((dr = nd6_defrouter_lookup(&newdr->rtaddr, newdr->ifp)) != NULL) {
1.2       itojun    770:                /* entry exists */
1.94      matt      771:                if (newdr->rtlifetime == 0) {
1.123     ozaki-r   772:                        nd6_defrtrlist_del(dr, ext);
1.2       itojun    773:                        dr = NULL;
                    774:                } else {
1.32      itojun    775:                        int oldpref = rtpref(dr);
                    776:
1.2       itojun    777:                        /* override */
1.94      matt      778:                        dr->flags = newdr->flags; /* xxx flag check */
                    779:                        dr->rtlifetime = newdr->rtlifetime;
                    780:                        dr->expire = newdr->expire;
1.32      itojun    781:
                    782:                        /*
                    783:                         * If the preference does not change, there's no need
                    784:                         * to sort the entries.
                    785:                         */
1.94      matt      786:                        if (rtpref(newdr) == oldpref) {
1.127     ozaki-r   787:                                ret = dr;
                    788:                                goto out;
1.32      itojun    789:                        }
                    790:
                    791:                        /*
                    792:                         * preferred router may be changed, so relocate
                    793:                         * this router.
                    794:                         * XXX: calling TAILQ_REMOVE directly is a bad manner.
1.123     ozaki-r   795:                         * However, since nd6_defrtrlist_del() has many side
1.32      itojun    796:                         * effects, we intentionally do so here.
1.123     ozaki-r   797:                         * nd6_defrouter_select() below will handle routing
1.32      itojun    798:                         * changes later.
                    799:                         */
1.124     ozaki-r   800:                        ND_DEFROUTER_LIST_REMOVE(dr);
1.32      itojun    801:                        n = dr;
                    802:                        goto insert;
1.2       itojun    803:                }
1.127     ozaki-r   804:                ret = dr;
                    805:                goto out;
1.2       itojun    806:        }
                    807:
1.127     ozaki-r   808:        if (ip6_maxifdefrouters >= 0 && ext->ndefrouters >= ip6_maxifdefrouters)
                    809:                goto out;
1.83      christos  810:
1.2       itojun    811:        /* entry does not exist */
1.127     ozaki-r   812:        if (newdr->rtlifetime == 0)
                    813:                goto out;
1.2       itojun    814:
1.81      spz       815:        if (ip6_rtadv_maxroutes <= nd6_numroutes) {
                    816:                ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
1.127     ozaki-r   817:                goto out;
1.81      spz       818:        }
                    819:
1.2       itojun    820:        n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
1.127     ozaki-r   821:        if (n == NULL)
                    822:                goto out;
1.78      cegger    823:        memset(n, 0, sizeof(*n));
1.94      matt      824:        *n = *newdr;
1.7       itojun    825:
1.32      itojun    826: insert:
1.7       itojun    827:        /*
1.32      itojun    828:         * Insert the new router in the Default Router List;
                    829:         * The Default Router List should be in the descending order
                    830:         * of router-preferece.  Routers with the same preference are
                    831:         * sorted in the arriving time order.
1.7       itojun    832:         */
1.32      itojun    833:
                    834:        /* insert at the end of the group */
1.124     ozaki-r   835:        ND_DEFROUTER_LIST_FOREACH(dr) {
1.32      itojun    836:                if (rtpref(n) > rtpref(dr))
                    837:                        break;
                    838:        }
                    839:        if (dr)
1.124     ozaki-r   840:                ND_DEFROUTER_LIST_INSERT_BEFORE(dr, n);
1.32      itojun    841:        else
1.124     ozaki-r   842:                ND_DEFROUTER_LIST_INSERT_TAIL(n);
1.32      itojun    843:
1.123     ozaki-r   844:        nd6_defrouter_select();
1.32      itojun    845:
1.83      christos  846:        ext->ndefrouters++;
                    847:
1.127     ozaki-r   848:        ret = n;
                    849: out:
                    850:        return ret;
1.2       itojun    851: }
                    852:
                    853: static struct nd_pfxrouter *
1.64      christos  854: pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
1.2       itojun    855: {
                    856:        struct nd_pfxrouter *search;
1.33      itojun    857:
1.128     ozaki-r   858:        ND6_ASSERT_LOCK();
                    859:
1.62      dyoung    860:        LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
1.2       itojun    861:                if (search->router == dr)
                    862:                        break;
                    863:        }
                    864:
1.36      itojun    865:        return (search);
1.2       itojun    866: }
                    867:
                    868: static void
1.64      christos  869: pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
1.2       itojun    870: {
1.94      matt      871:        struct nd_pfxrouter *newpfr;
1.2       itojun    872:
1.128     ozaki-r   873:        ND6_ASSERT_WLOCK();
                    874:
1.94      matt      875:        newpfr = malloc(sizeof(*newpfr), M_IP6NDP, M_NOWAIT|M_ZERO);
                    876:        if (newpfr == NULL)
1.2       itojun    877:                return;
1.94      matt      878:        newpfr->router = dr;
1.2       itojun    879:
1.94      matt      880:        LIST_INSERT_HEAD(&pr->ndpr_advrtrs, newpfr, pfr_entry);
1.2       itojun    881:
1.123     ozaki-r   882:        nd6_pfxlist_onlink_check();
1.2       itojun    883: }
                    884:
                    885: static void
1.64      christos  886: pfxrtr_del(struct nd_pfxrouter *pfr)
1.2       itojun    887: {
                    888:        LIST_REMOVE(pfr, pfr_entry);
                    889:        free(pfr, M_IP6NDP);
                    890: }
                    891:
1.121     ozaki-r   892: static struct nd_prefix *
1.64      christos  893: nd6_prefix_lookup(struct nd_prefixctl *key)
1.2       itojun    894: {
                    895:        struct nd_prefix *search;
                    896:
1.125     ozaki-r   897:        ND_PREFIX_LIST_FOREACH(search) {
1.94      matt      898:                if (key->ndprc_ifp == search->ndpr_ifp &&
                    899:                    key->ndprc_plen == search->ndpr_plen &&
                    900:                    in6_are_prefix_equal(&key->ndprc_prefix.sin6_addr,
                    901:                    &search->ndpr_prefix.sin6_addr, key->ndprc_plen)) {
1.2       itojun    902:                        break;
                    903:                }
                    904:        }
                    905:
1.36      itojun    906:        return (search);
1.2       itojun    907: }
                    908:
1.83      christos  909: static void
                    910: purge_detached(struct ifnet *ifp)
                    911: {
                    912:        struct nd_prefix *pr, *pr_next;
                    913:        struct in6_ifaddr *ia;
1.93      ozaki-r   914:        struct ifaddr *ifa, *ifa_next;
1.83      christos  915:
1.128     ozaki-r   916: restart:
                    917:        ND6_ASSERT_WLOCK();
                    918:
1.126     ozaki-r   919:        ND_PREFIX_LIST_FOREACH_SAFE(pr, pr_next) {
1.118     ozaki-r   920:                int s;
1.83      christos  921:
                    922:                /*
                    923:                 * This function is called when we need to make more room for
                    924:                 * new prefixes rather than keeping old, possibly stale ones.
                    925:                 * Detached prefixes would be a good candidate; if all routers
                    926:                 * that advertised the prefix expired, the prefix is also
                    927:                 * probably stale.
                    928:                 */
                    929:                if (pr->ndpr_ifp != ifp ||
                    930:                    IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
                    931:                    ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
                    932:                    !LIST_EMPTY(&pr->ndpr_advrtrs)))
                    933:                        continue;
                    934:
1.118     ozaki-r   935:                s = pserialize_read_enter();
1.115     ozaki-r   936:                for (ifa = IFADDR_READER_FIRST(ifp); ifa; ifa = ifa_next) {
                    937:                        ifa_next = IFADDR_READER_NEXT(ifa);
1.83      christos  938:                        if (ifa->ifa_addr->sa_family != AF_INET6)
                    939:                                continue;
                    940:                        ia = (struct in6_ifaddr *)ifa;
                    941:                        if ((ia->ia6_flags & IN6_IFF_AUTOCONF) ==
                    942:                            IN6_IFF_AUTOCONF && ia->ia6_ndpr == pr) {
1.118     ozaki-r   943:                                pserialize_read_exit(s);
1.128     ozaki-r   944:                                ND6_UNLOCK();
                    945:
                    946:                                /* in6_purgeaddr may destroy pr. */
1.83      christos  947:                                in6_purgeaddr(ifa);
1.128     ozaki-r   948:
                    949:                                ND6_WLOCK();
1.118     ozaki-r   950:                                goto restart;
1.83      christos  951:                        }
                    952:                }
1.118     ozaki-r   953:                pserialize_read_exit(s);
                    954:
1.128     ozaki-r   955:                KASSERT(pr->ndpr_refcnt == 0);
                    956:                nd6_prelist_remove(pr);
1.83      christos  957:        }
                    958: }
1.121     ozaki-r   959:
                    960: static int
1.94      matt      961: nd6_prelist_add(struct nd_prefixctl *prc, struct nd_defrouter *dr,
1.64      christos  962:        struct nd_prefix **newp)
1.2       itojun    963: {
1.94      matt      964:        struct nd_prefix *newpr = NULL;
1.138     ozaki-r   965:        int i;
1.56      rpaulo    966:        int error;
1.94      matt      967:        struct in6_ifextra *ext = prc->ndprc_ifp->if_afdata[AF_INET6];
1.83      christos  968:
1.128     ozaki-r   969:        ND6_ASSERT_WLOCK();
                    970:
1.83      christos  971:        if (ip6_maxifprefixes >= 0) {
                    972:                if (ext->nprefixes >= ip6_maxifprefixes / 2)
1.94      matt      973:                        purge_detached(prc->ndprc_ifp);
1.83      christos  974:                if (ext->nprefixes >= ip6_maxifprefixes)
                    975:                        return ENOMEM;
                    976:        }
1.2       itojun    977:
1.56      rpaulo    978:        error = 0;
1.94      matt      979:        newpr = malloc(sizeof(*newpr), M_IP6NDP, M_NOWAIT|M_ZERO);
                    980:        if (newpr == NULL)
1.2       itojun    981:                return ENOMEM;
1.94      matt      982:        newpr->ndpr_ifp = prc->ndprc_ifp;
                    983:        newpr->ndpr_prefix = prc->ndprc_prefix;
                    984:        newpr->ndpr_plen = prc->ndprc_plen;
                    985:        newpr->ndpr_vltime = prc->ndprc_vltime;
                    986:        newpr->ndpr_pltime = prc->ndprc_pltime;
                    987:        newpr->ndpr_flags = prc->ndprc_flags;
                    988:        if ((error = in6_init_prefix_ltimes(newpr)) != 0) {
                    989:                free(newpr, M_IP6NDP);
1.56      rpaulo    990:                return(error);
                    991:        }
1.102     ozaki-r   992:        newpr->ndpr_lastupdate = time_uptime;
1.32      itojun    993:        if (newp != NULL)
1.94      matt      994:                *newp = newpr;
1.2       itojun    995:
1.55      rpaulo    996:        /* initialization */
1.94      matt      997:        LIST_INIT(&newpr->ndpr_advrtrs);
                    998:        in6_prefixlen2mask(&newpr->ndpr_mask, newpr->ndpr_plen);
1.2       itojun    999:        /* make prefix in the canonical form */
1.94      matt     1000:        for (i = 0; i < 4; i++) {
                   1001:                newpr->ndpr_prefix.sin6_addr.s6_addr32[i] &=
                   1002:                    newpr->ndpr_mask.s6_addr32[i];
                   1003:        }
1.2       itojun   1004:
                   1005:        /* link ndpr_entry to nd_prefix list */
1.125     ozaki-r  1006:        ND_PREFIX_LIST_INSERT_HEAD(newpr);
1.2       itojun   1007:
1.32      itojun   1008:        /* ND_OPT_PI_FLAG_ONLINK processing */
1.94      matt     1009:        if (newpr->ndpr_raf_onlink) {
1.32      itojun   1010:                int e;
                   1011:
1.94      matt     1012:                if ((e = nd6_prefix_onlink(newpr)) != 0) {
1.130     ryo      1013:                        char ip6buf[INET6_ADDRSTRLEN];
1.107     ozaki-r  1014:                        nd6log(LOG_ERR, "failed to make "
1.32      itojun   1015:                            "the prefix %s/%d on-link on %s (errno=%d)\n",
1.131     christos 1016:                            IN6_PRINT(ip6buf, &prc->ndprc_prefix.sin6_addr),
1.107     ozaki-r  1017:                            prc->ndprc_plen, if_name(prc->ndprc_ifp), e);
1.32      itojun   1018:                        /* proceed anyway. XXX: is it correct? */
                   1019:                }
                   1020:        }
                   1021:
1.2       itojun   1022:        if (dr)
1.94      matt     1023:                pfxrtr_add(newpr, dr);
1.2       itojun   1024:
1.83      christos 1025:        ext->nprefixes++;
                   1026:
1.2       itojun   1027:        return 0;
                   1028: }
                   1029:
                   1030: void
1.128     ozaki-r  1031: nd6_prefix_unref(struct nd_prefix *pr)
                   1032: {
                   1033:
                   1034:        ND6_WLOCK();
                   1035:        pr->ndpr_refcnt--;
                   1036:        if (pr->ndpr_refcnt == 0)
                   1037:                nd6_prelist_remove(pr);
                   1038:        ND6_UNLOCK();
                   1039: }
                   1040:
                   1041: void
1.132     ozaki-r  1042: nd6_invalidate_prefix(struct nd_prefix *pr)
1.2       itojun   1043: {
1.132     ozaki-r  1044:        int e;
1.32      itojun   1045:
1.128     ozaki-r  1046:        ND6_ASSERT_WLOCK();
                   1047:
1.32      itojun   1048:        /* make sure to invalidate the prefix until it is really freed. */
                   1049:        pr->ndpr_vltime = 0;
                   1050:        pr->ndpr_pltime = 0;
                   1051: #if 0
                   1052:        /*
                   1053:         * Though these flags are now meaningless, we'd rather keep the value
                   1054:         * not to confuse users when executing "ndp -p".
                   1055:         */
                   1056:        pr->ndpr_raf_onlink = 0;
                   1057:        pr->ndpr_raf_auto = 0;
                   1058: #endif
                   1059:        if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
                   1060:            (e = nd6_prefix_offlink(pr)) != 0) {
1.130     ryo      1061:                char ip6buf[INET6_ADDRSTRLEN];
1.107     ozaki-r  1062:                nd6log(LOG_ERR,
                   1063:                    "failed to make %s/%d offlink on %s, errno=%d\n",
1.131     christos 1064:                    IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.107     ozaki-r  1065:                    pr->ndpr_plen, if_name(pr->ndpr_ifp), e);
1.32      itojun   1066:                /* what should we do? */
                   1067:        }
1.132     ozaki-r  1068: }
                   1069:
                   1070: void
                   1071: nd6_prelist_remove(struct nd_prefix *pr)
                   1072: {
                   1073:        struct nd_pfxrouter *pfr, *next;
                   1074:        struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
                   1075:
                   1076:        ND6_ASSERT_WLOCK();
                   1077:        KASSERT(pr->ndpr_refcnt == 0);
                   1078:
                   1079:        nd6_invalidate_prefix(pr);
1.32      itojun   1080:
1.2       itojun   1081:        /* unlink ndpr_entry from nd_prefix list */
1.125     ozaki-r  1082:        ND_PREFIX_LIST_REMOVE(pr);
1.2       itojun   1083:
                   1084:        /* free list of routers that adversed the prefix */
1.62      dyoung   1085:        for (pfr = LIST_FIRST(&pr->ndpr_advrtrs); pfr != NULL; pfr = next) {
                   1086:                next = LIST_NEXT(pfr, pfr_entry);
1.2       itojun   1087:
                   1088:                free(pfr, M_IP6NDP);
                   1089:        }
1.83      christos 1090:
1.86      christos 1091:        if (ext) {
                   1092:                ext->nprefixes--;
                   1093:                if (ext->nprefixes < 0) {
1.123     ozaki-r  1094:                        log(LOG_WARNING, "nd6_prelist_remove: negative count on "
1.86      christos 1095:                            "%s\n", pr->ndpr_ifp->if_xname);
                   1096:                }
1.83      christos 1097:        }
1.21      itojun   1098:
1.2       itojun   1099:        free(pr, M_IP6NDP);
                   1100:
1.123     ozaki-r  1101:        nd6_pfxlist_onlink_check();
1.2       itojun   1102: }
                   1103:
1.56      rpaulo   1104: static int
1.94      matt     1105: prelist_update(struct nd_prefixctl *newprc,
1.64      christos 1106:        struct nd_defrouter *dr, /* may be NULL */
                   1107:        struct mbuf *m,
                   1108:        int mcast)
1.2       itojun   1109: {
1.114     ozaki-r  1110:        struct in6_ifaddr *ia6_match = NULL;
1.32      itojun   1111:        struct ifaddr *ifa;
1.94      matt     1112:        struct ifnet *ifp = newprc->ndprc_ifp;
1.2       itojun   1113:        struct nd_prefix *pr;
                   1114:        int error = 0;
                   1115:        int auth;
1.32      itojun   1116:        struct in6_addrlifetime lt6_tmp;
1.118     ozaki-r  1117:        int ss;
1.130     ryo      1118:        char ip6buf[INET6_ADDRSTRLEN];
1.2       itojun   1119:
1.140     maxv     1120:        KASSERT(m != NULL);
1.128     ozaki-r  1121:        ND6_ASSERT_WLOCK();
                   1122:
1.140     maxv     1123:        auth = (m->m_flags & M_AUTHIPHDR) ? 1 : 0;
1.2       itojun   1124:
1.94      matt     1125:        if ((pr = nd6_prefix_lookup(newprc)) != NULL) {
1.32      itojun   1126:                /*
1.94      matt     1127:                 * nd6_prefix_lookup() ensures that pr and newprc have the same
1.32      itojun   1128:                 * prefix on a same interface.
                   1129:                 */
                   1130:
                   1131:                /*
                   1132:                 * Update prefix information.  Note that the on-link (L) bit
                   1133:                 * and the autonomous (A) bit should NOT be changed from 1
                   1134:                 * to 0.
                   1135:                 */
1.94      matt     1136:                if (newprc->ndprc_raf_onlink == 1)
1.32      itojun   1137:                        pr->ndpr_raf_onlink = 1;
1.94      matt     1138:                if (newprc->ndprc_raf_auto == 1)
1.32      itojun   1139:                        pr->ndpr_raf_auto = 1;
1.94      matt     1140:                if (newprc->ndprc_raf_onlink) {
                   1141:                        pr->ndpr_vltime = newprc->ndprc_vltime;
                   1142:                        pr->ndpr_pltime = newprc->ndprc_pltime;
1.56      rpaulo   1143:                        (void)in6_init_prefix_ltimes(pr); /* XXX error case? */
1.102     ozaki-r  1144:                        pr->ndpr_lastupdate = time_uptime;
1.32      itojun   1145:                }
                   1146:
1.94      matt     1147:                if (newprc->ndprc_raf_onlink &&
1.32      itojun   1148:                    (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
                   1149:                        int e;
                   1150:
                   1151:                        if ((e = nd6_prefix_onlink(pr)) != 0) {
1.107     ozaki-r  1152:                                nd6log(LOG_ERR,
                   1153:                                    "failed to make "
1.32      itojun   1154:                                    "the prefix %s/%d on-link on %s "
1.107     ozaki-r  1155:                                    "(errno=%d)\n",
1.131     christos 1156:                                    IN6_PRINT(ip6buf,
1.130     ryo      1157:                                    &pr->ndpr_prefix.sin6_addr),
1.107     ozaki-r  1158:                                    pr->ndpr_plen, if_name(pr->ndpr_ifp), e);
1.32      itojun   1159:                                /* proceed anyway. XXX: is it correct? */
                   1160:                        }
                   1161:                }
                   1162:
                   1163:                if (dr && pfxrtr_lookup(pr, dr) == NULL)
                   1164:                        pfxrtr_add(pr, dr);
                   1165:        } else {
                   1166:                struct nd_prefix *newpr = NULL;
                   1167:
1.94      matt     1168:                if (newprc->ndprc_vltime == 0)
1.2       itojun   1169:                        goto end;
1.94      matt     1170:                if (newprc->ndprc_raf_onlink == 0 && newprc->ndprc_raf_auto == 0)
1.32      itojun   1171:                        goto end;
                   1172:
1.81      spz      1173:                if (ip6_rtadv_maxroutes <= nd6_numroutes) {
                   1174:                        ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
                   1175:                        goto end;
                   1176:                }
                   1177:
1.94      matt     1178:                error = nd6_prelist_add(newprc, dr, &newpr);
1.32      itojun   1179:                if (error != 0 || newpr == NULL) {
1.107     ozaki-r  1180:                        nd6log(LOG_NOTICE,
                   1181:                            "nd6_prelist_add failed for %s/%d on %s "
                   1182:                            "errno=%d, returnpr=%p\n",
1.131     christos 1183:                            IN6_PRINT(ip6buf, &newprc->ndprc_prefix.sin6_addr),
1.94      matt     1184:                            newprc->ndprc_plen, if_name(newprc->ndprc_ifp),
1.107     ozaki-r  1185:                            error, newpr);
1.32      itojun   1186:                        goto end; /* we should just give up in this case. */
1.2       itojun   1187:                }
                   1188:
                   1189:                /*
1.32      itojun   1190:                 * XXX: from the ND point of view, we can ignore a prefix
                   1191:                 * with the on-link bit being zero.  However, we need a
                   1192:                 * prefix structure for references from autoconfigured
                   1193:                 * addresses.  Thus, we explicitly make sure that the prefix
                   1194:                 * itself expires now.
1.2       itojun   1195:                 */
1.32      itojun   1196:                if (newpr->ndpr_raf_onlink == 0) {
                   1197:                        newpr->ndpr_vltime = 0;
                   1198:                        newpr->ndpr_pltime = 0;
                   1199:                        in6_init_prefix_ltimes(newpr);
                   1200:                }
1.2       itojun   1201:
1.32      itojun   1202:                pr = newpr;
                   1203:        }
                   1204:
                   1205:        /*
                   1206:         * Address autoconfiguration based on Section 5.5.3 of RFC 2462.
                   1207:         * Note that pr must be non NULL at this point.
                   1208:         */
                   1209:
                   1210:        /* 5.5.3 (a). Ignore the prefix without the A bit set. */
1.94      matt     1211:        if (!newprc->ndprc_raf_auto)
1.32      itojun   1212:                goto end;
1.2       itojun   1213:
1.32      itojun   1214:        /*
                   1215:         * 5.5.3 (b). the link-local prefix should have been ignored in
                   1216:         * nd6_ra_input.
                   1217:         */
1.2       itojun   1218:
1.56      rpaulo   1219:        /* 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime. */
1.94      matt     1220:        if (newprc->ndprc_pltime > newprc->ndprc_vltime) {
1.56      rpaulo   1221:                error = EINVAL; /* XXX: won't be used */
                   1222:                goto end;
                   1223:        }
1.2       itojun   1224:
1.32      itojun   1225:        /*
1.56      rpaulo   1226:         * 5.5.3 (d).  If the prefix advertised is not equal to the prefix of
                   1227:         * an address configured by stateless autoconfiguration already in the
                   1228:         * list of addresses associated with the interface, and the Valid
                   1229:         * Lifetime is not 0, form an address.  We first check if we have
                   1230:         * a matching prefix.
                   1231:         * Note: we apply a clarification in rfc2462bis-02 here.  We only
                   1232:         * consider autoconfigured addresses while RFC2462 simply said
                   1233:         * "address".
1.32      itojun   1234:         */
1.118     ozaki-r  1235:        ss = pserialize_read_enter();
1.115     ozaki-r  1236:        IFADDR_READER_FOREACH(ifa, ifp) {
1.114     ozaki-r  1237:                struct in6_ifaddr *ia6;
1.56      rpaulo   1238:                u_int32_t remaininglifetime;
1.2       itojun   1239:
1.32      itojun   1240:                if (ifa->ifa_addr->sa_family != AF_INET6)
                   1241:                        continue;
1.2       itojun   1242:
1.114     ozaki-r  1243:                ia6 = (struct in6_ifaddr *)ifa;
1.2       itojun   1244:
1.32      itojun   1245:                /*
1.56      rpaulo   1246:                 * We only consider autoconfigured addresses as per rfc2462bis.
                   1247:                 */
1.114     ozaki-r  1248:                if (!(ia6->ia6_flags & IN6_IFF_AUTOCONF))
1.56      rpaulo   1249:                        continue;
                   1250:
                   1251:                /*
1.32      itojun   1252:                 * Spec is not clear here, but I believe we should concentrate
                   1253:                 * on unicast (i.e. not anycast) addresses.
                   1254:                 * XXX: other ia6_flags? detached or duplicated?
                   1255:                 */
1.114     ozaki-r  1256:                if ((ia6->ia6_flags & IN6_IFF_ANYCAST) != 0)
1.32      itojun   1257:                        continue;
1.33      itojun   1258:
1.56      rpaulo   1259:                /*
                   1260:                 * Ignore the address if it is not associated with a prefix
                   1261:                 * or is associated with a prefix that is different from this
                   1262:                 * one.  (pr is never NULL here)
                   1263:                 */
1.114     ozaki-r  1264:                if (ia6->ia6_ndpr != pr)
1.32      itojun   1265:                        continue;
1.7       itojun   1266:
1.32      itojun   1267:                if (ia6_match == NULL) /* remember the first one */
1.114     ozaki-r  1268:                        ia6_match = ia6;
1.2       itojun   1269:
1.32      itojun   1270:                /*
                   1271:                 * An already autoconfigured address matched.  Now that we
                   1272:                 * are sure there is at least one matched address, we can
                   1273:                 * proceed to 5.5.3. (e): update the lifetimes according to the
                   1274:                 * "two hours" rule and the privacy extension.
1.56      rpaulo   1275:                 * We apply some clarifications in rfc2462bis:
                   1276:                 * - use remaininglifetime instead of storedlifetime as a
                   1277:                 *   variable name
                   1278:                 * - remove the dead code in the "two-hour" rule
1.32      itojun   1279:                 */
                   1280: #define TWOHOUR                (120*60)
1.114     ozaki-r  1281:                lt6_tmp = ia6->ia6_lifetime;
1.32      itojun   1282:                if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
1.56      rpaulo   1283:                        remaininglifetime = ND6_INFINITE_LIFETIME;
1.114     ozaki-r  1284:                else if (time_uptime - ia6->ia6_updatetime >
1.32      itojun   1285:                         lt6_tmp.ia6t_vltime) {
                   1286:                        /*
                   1287:                         * The case of "invalid" address.  We should usually
                   1288:                         * not see this case.
                   1289:                         */
1.56      rpaulo   1290:                        remaininglifetime = 0;
1.32      itojun   1291:                } else
1.56      rpaulo   1292:                        remaininglifetime = lt6_tmp.ia6t_vltime -
1.114     ozaki-r  1293:                            (time_uptime - ia6->ia6_updatetime);
1.56      rpaulo   1294:
                   1295:                /* when not updating, keep the current stored lifetime. */
                   1296:                lt6_tmp.ia6t_vltime = remaininglifetime;
                   1297:
1.94      matt     1298:                if (TWOHOUR < newprc->ndprc_vltime ||
                   1299:                    remaininglifetime < newprc->ndprc_vltime) {
                   1300:                        lt6_tmp.ia6t_vltime = newprc->ndprc_vltime;
1.56      rpaulo   1301:                } else if (remaininglifetime <= TWOHOUR) {
                   1302:                        if (auth)
1.94      matt     1303:                                lt6_tmp.ia6t_vltime = newprc->ndprc_vltime;
1.32      itojun   1304:                } else {
                   1305:                        /*
1.94      matt     1306:                         * newprc->ndprc_vltime <= TWOHOUR &&
1.56      rpaulo   1307:                         * TWOHOUR < remaininglifetime
1.32      itojun   1308:                         */
                   1309:                        lt6_tmp.ia6t_vltime = TWOHOUR;
1.2       itojun   1310:                }
                   1311:
1.32      itojun   1312:                /* The 2 hour rule is not imposed for preferred lifetime. */
1.94      matt     1313:                lt6_tmp.ia6t_pltime = newprc->ndprc_pltime;
1.2       itojun   1314:
1.32      itojun   1315:                in6_init_address_ltimes(pr, &lt6_tmp);
1.2       itojun   1316:
1.56      rpaulo   1317:                /*
                   1318:                 * We need to treat lifetimes for temporary addresses
                   1319:                 * differently, according to
                   1320:                 * draft-ietf-ipv6-privacy-addrs-v2-01.txt 3.3 (1);
                   1321:                 * we only update the lifetimes when they are in the maximum
                   1322:                 * intervals.
                   1323:                 */
1.114     ozaki-r  1324:                if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
1.56      rpaulo   1325:                        u_int32_t maxvltime, maxpltime;
                   1326:
                   1327:                        if (ip6_temp_valid_lifetime >
1.114     ozaki-r  1328:                            (u_int32_t)((time_uptime - ia6->ia6_createtime) +
1.56      rpaulo   1329:                            ip6_desync_factor)) {
                   1330:                                maxvltime = ip6_temp_valid_lifetime -
1.114     ozaki-r  1331:                                    (time_uptime - ia6->ia6_createtime) -
1.56      rpaulo   1332:                                    ip6_desync_factor;
                   1333:                        } else
                   1334:                                maxvltime = 0;
                   1335:                        if (ip6_temp_preferred_lifetime >
1.114     ozaki-r  1336:                            (u_int32_t)((time_uptime - ia6->ia6_createtime) +
1.56      rpaulo   1337:                            ip6_desync_factor)) {
                   1338:                                maxpltime = ip6_temp_preferred_lifetime -
1.114     ozaki-r  1339:                                    (time_uptime - ia6->ia6_createtime) -
1.56      rpaulo   1340:                                    ip6_desync_factor;
                   1341:                        } else
                   1342:                                maxpltime = 0;
                   1343:
                   1344:                        if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME ||
                   1345:                            lt6_tmp.ia6t_vltime > maxvltime) {
                   1346:                                lt6_tmp.ia6t_vltime = maxvltime;
                   1347:                        }
                   1348:                        if (lt6_tmp.ia6t_pltime == ND6_INFINITE_LIFETIME ||
                   1349:                            lt6_tmp.ia6t_pltime > maxpltime) {
                   1350:                                lt6_tmp.ia6t_pltime = maxpltime;
                   1351:                        }
                   1352:                }
                   1353:
1.114     ozaki-r  1354:                ia6->ia6_lifetime = lt6_tmp;
                   1355:                ia6->ia6_updatetime = time_uptime;
1.32      itojun   1356:        }
1.118     ozaki-r  1357:        pserialize_read_exit(ss);
                   1358:
1.94      matt     1359:        if (ia6_match == NULL && newprc->ndprc_vltime) {
1.56      rpaulo   1360:                int ifidlen;
1.114     ozaki-r  1361:                struct in6_ifaddr *ia6;
1.118     ozaki-r  1362:                struct psref psref;
1.56      rpaulo   1363:
1.2       itojun   1364:                /*
1.56      rpaulo   1365:                 * 5.5.3 (d) (continued)
1.32      itojun   1366:                 * No address matched and the valid lifetime is non-zero.
                   1367:                 * Create a new address.
1.2       itojun   1368:                 */
1.56      rpaulo   1369:
                   1370:                /*
                   1371:                 * Prefix Length check:
                   1372:                 * If the sum of the prefix length and interface identifier
                   1373:                 * length does not equal 128 bits, the Prefix Information
                   1374:                 * option MUST be ignored.  The length of the interface
                   1375:                 * identifier is defined in a separate link-type specific
                   1376:                 * document.
                   1377:                 */
                   1378:                ifidlen = in6_if2idlen(ifp);
                   1379:                if (ifidlen < 0) {
                   1380:                        /* this should not happen, so we always log it. */
1.106     ozaki-r  1381:                        log(LOG_ERR, "%s: IFID undefined (%s)\n",
                   1382:                            __func__, if_name(ifp));
1.56      rpaulo   1383:                        goto end;
                   1384:                }
                   1385:                if (ifidlen + pr->ndpr_plen != 128) {
1.107     ozaki-r  1386:                        nd6log(LOG_INFO,
                   1387:                            "invalid prefixlen %d for %s, ignored\n",
                   1388:                            pr->ndpr_plen, if_name(ifp));
1.56      rpaulo   1389:                        goto end;
                   1390:                }
                   1391:
1.118     ozaki-r  1392:                if ((ia6 = in6_ifadd(newprc, mcast, &psref)) != NULL) {
1.32      itojun   1393:                        /*
1.94      matt     1394:                         * note that we should use pr (not newprc) for reference.
1.32      itojun   1395:                         */
                   1396:                        pr->ndpr_refcnt++;
                   1397:                        ia6->ia6_ndpr = pr;
1.2       itojun   1398:
1.119     roy      1399:                        /* toggle onlink state if the address was assigned
                   1400:                         * a prefix route. */
                   1401:                        if (ia6->ia_flags & IFA_ROUTE)
                   1402:                                pr->ndpr_stateflags |= NDPRF_ONLINK;
                   1403:
1.32      itojun   1404:                        /*
1.56      rpaulo   1405:                         * draft-ietf-ipngwg-temp-addresses-v2-00 3.3 (2).
                   1406:                         * When a new public address is created as described
                   1407:                         * in RFC2462, also create a new temporary address.
                   1408:                         *
                   1409:                         * draft-ietf-ipngwg-temp-addresses-v2-00 3.5.
                   1410:                         * When an interface connects to a new link, a new
                   1411:                         * randomized interface identifier should be generated
                   1412:                         * immediately together with a new set of temporary
                   1413:                         * addresses.  Thus, we specifiy 1 as the 2nd arg of
                   1414:                         * in6_tmpifadd().
                   1415:                         */
                   1416:                        if (ip6_use_tempaddr) {
                   1417:                                int e;
                   1418:                                if ((e = in6_tmpifadd(ia6, 1, 1)) != 0) {
1.107     ozaki-r  1419:                                        nd6log(LOG_NOTICE,
                   1420:                                            "failed to create a temporary "
                   1421:                                            "address, errno=%d\n", e);
1.56      rpaulo   1422:                                }
                   1423:                        }
1.118     ozaki-r  1424:                        ia6_release(ia6, &psref);
1.56      rpaulo   1425:
                   1426:                        /*
1.32      itojun   1427:                         * A newly added address might affect the status
                   1428:                         * of other addresses, so we check and update it.
                   1429:                         * XXX: what if address duplication happens?
                   1430:                         */
1.123     ozaki-r  1431:                        nd6_pfxlist_onlink_check();
1.32      itojun   1432:                } else {
                   1433:                        /* just set an error. do not bark here. */
                   1434:                        error = EADDRNOTAVAIL; /* XXX: might be unused. */
                   1435:                }
1.2       itojun   1436:        }
                   1437:
                   1438:  end:
                   1439:        return error;
                   1440: }
                   1441:
                   1442: /*
1.7       itojun   1443:  * A supplement function used in the on-link detection below;
                   1444:  * detect if a given prefix has a (probably) reachable advertising router.
                   1445:  * XXX: lengthy function name...
                   1446:  */
                   1447: static struct nd_pfxrouter *
1.64      christos 1448: find_pfxlist_reachable_router(struct nd_prefix *pr)
1.7       itojun   1449: {
                   1450:        struct nd_pfxrouter *pfxrtr;
                   1451:
                   1452:        for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
                   1453:             pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1.89      roy      1454:                if (pfxrtr->router->ifp->if_flags & IFF_UP &&
                   1455:                    pfxrtr->router->ifp->if_link_state != LINK_STATE_DOWN &&
1.101     ozaki-r  1456:                    nd6_is_llinfo_probreach(pfxrtr->router))
1.7       itojun   1457:                        break;  /* found */
                   1458:        }
                   1459:
1.36      itojun   1460:        return (pfxrtr);
1.7       itojun   1461: }
                   1462:
                   1463: /*
1.2       itojun   1464:  * Check if each prefix in the prefix list has at least one available router
1.25      itojun   1465:  * that advertised the prefix (a router is "available" if its neighbor cache
                   1466:  * entry is reachable or probably reachable).
1.7       itojun   1467:  * If the check fails, the prefix may be off-link, because, for example,
1.2       itojun   1468:  * we have moved from the network but the lifetime of the prefix has not
1.25      itojun   1469:  * expired yet.  So we should not use the prefix if there is another prefix
                   1470:  * that has an available router.
                   1471:  * But, if there is no prefix that has an available router, we still regards
                   1472:  * all the prefixes as on-link.  This is because we can't tell if all the
1.2       itojun   1473:  * routers are simply dead or if we really moved from the network and there
                   1474:  * is no router around us.
                   1475:  */
1.7       itojun   1476: void
1.123     ozaki-r  1477: nd6_pfxlist_onlink_check(void)
1.2       itojun   1478: {
                   1479:        struct nd_prefix *pr;
1.114     ozaki-r  1480:        struct in6_ifaddr *ia;
1.56      rpaulo   1481:        struct nd_defrouter *dr;
                   1482:        struct nd_pfxrouter *pfxrtr = NULL;
1.118     ozaki-r  1483:        int s;
1.130     ryo      1484:        char ip6buf[INET6_ADDRSTRLEN];
1.2       itojun   1485:
1.128     ozaki-r  1486:        ND6_ASSERT_WLOCK();
                   1487:
1.7       itojun   1488:        /*
                   1489:         * Check if there is a prefix that has a reachable advertising
                   1490:         * router.
                   1491:         */
1.125     ozaki-r  1492:        ND_PREFIX_LIST_FOREACH(pr) {
1.32      itojun   1493:                if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
1.2       itojun   1494:                        break;
1.7       itojun   1495:        }
1.56      rpaulo   1496:        /*
                   1497:         * If we have no such prefix, check whether we still have a router
                   1498:         * that does not advertise any prefixes.
                   1499:         */
                   1500:        if (pr == NULL) {
1.124     ozaki-r  1501:                ND_DEFROUTER_LIST_FOREACH(dr) {
1.56      rpaulo   1502:                        struct nd_prefix *pr0;
                   1503:
1.125     ozaki-r  1504:                        ND_PREFIX_LIST_FOREACH(pr0) {
1.56      rpaulo   1505:                                if ((pfxrtr = pfxrtr_lookup(pr0, dr)) != NULL)
                   1506:                                        break;
                   1507:                        }
                   1508:                        if (pfxrtr)
                   1509:                                break;
                   1510:                }
                   1511:        }
1.124     ozaki-r  1512:        if (pr != NULL || (!ND_DEFROUTER_LIST_EMPTY() && !pfxrtr)) {
1.2       itojun   1513:                /*
1.32      itojun   1514:                 * There is at least one prefix that has a reachable router,
                   1515:                 * or at least a router which probably does not advertise
                   1516:                 * any prefixes.  The latter would be the case when we move
                   1517:                 * to a new link where we have a router that does not provide
                   1518:                 * prefixes and we configure an address by hand.
                   1519:                 * Detach prefixes which have no reachable advertising
                   1520:                 * router, and attach other prefixes.
1.2       itojun   1521:                 */
1.125     ozaki-r  1522:                ND_PREFIX_LIST_FOREACH(pr) {
1.32      itojun   1523:                        /* XXX: a link-local prefix should never be detached */
                   1524:                        if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
                   1525:                                continue;
                   1526:
                   1527:                        /*
                   1528:                         * we aren't interested in prefixes without the L bit
                   1529:                         * set.
                   1530:                         */
                   1531:                        if (pr->ndpr_raf_onlink == 0)
                   1532:                                continue;
                   1533:
                   1534:                        if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
                   1535:                            find_pfxlist_reachable_router(pr) == NULL)
                   1536:                                pr->ndpr_stateflags |= NDPRF_DETACHED;
                   1537:                        if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
                   1538:                            find_pfxlist_reachable_router(pr) != 0)
                   1539:                                pr->ndpr_stateflags &= ~NDPRF_DETACHED;
                   1540:                }
                   1541:        } else {
                   1542:                /* there is no prefix that has a reachable router */
1.125     ozaki-r  1543:                ND_PREFIX_LIST_FOREACH(pr) {
1.32      itojun   1544:                        if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
                   1545:                                continue;
                   1546:
                   1547:                        if (pr->ndpr_raf_onlink == 0)
                   1548:                                continue;
                   1549:
                   1550:                        if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
                   1551:                                pr->ndpr_stateflags &= ~NDPRF_DETACHED;
                   1552:                }
                   1553:        }
                   1554:
                   1555:        /*
                   1556:         * Remove each interface route associated with a (just) detached
                   1557:         * prefix, and reinstall the interface route for a (just) attached
                   1558:         * prefix.  Note that all attempt of reinstallation does not
                   1559:         * necessarily success, when a same prefix is shared among multiple
                   1560:         * interfaces.  Such cases will be handled in nd6_prefix_onlink,
                   1561:         * so we don't have to care about them.
                   1562:         */
1.125     ozaki-r  1563:        ND_PREFIX_LIST_FOREACH(pr) {
1.32      itojun   1564:                int e;
                   1565:
                   1566:                if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
                   1567:                        continue;
                   1568:
                   1569:                if (pr->ndpr_raf_onlink == 0)
                   1570:                        continue;
                   1571:
                   1572:                if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
                   1573:                    (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
                   1574:                        if ((e = nd6_prefix_offlink(pr)) != 0) {
1.107     ozaki-r  1575:                                nd6log(LOG_ERR,
                   1576:                                    "failed to make %s/%d offlink, errno=%d\n",
1.131     christos 1577:                                    IN6_PRINT(ip6buf,
1.130     ryo      1578:                                    &pr->ndpr_prefix.sin6_addr),
1.107     ozaki-r  1579:                                    pr->ndpr_plen, e);
1.2       itojun   1580:                        }
                   1581:                }
1.32      itojun   1582:                if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
                   1583:                    (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
                   1584:                    pr->ndpr_raf_onlink) {
                   1585:                        if ((e = nd6_prefix_onlink(pr)) != 0) {
1.107     ozaki-r  1586:                                nd6log(LOG_ERR,
                   1587:                                    "failed to make %s/%d onlink, errno=%d\n",
1.131     christos 1588:                                    IN6_PRINT(ip6buf,
1.130     ryo      1589:                                    &pr->ndpr_prefix.sin6_addr),
1.107     ozaki-r  1590:                                    pr->ndpr_plen, e);
1.32      itojun   1591:                        }
                   1592:                }
                   1593:        }
                   1594:
                   1595:        /*
                   1596:         * Changes on the prefix status might affect address status as well.
                   1597:         * Make sure that all addresses derived from an attached prefix are
                   1598:         * attached, and that all addresses derived from a detached prefix are
                   1599:         * detached.  Note, however, that a manually configured address should
                   1600:         * always be attached.
                   1601:         * The precise detection logic is same as the one for prefixes.
                   1602:         */
1.118     ozaki-r  1603:        s = pserialize_read_enter();
1.114     ozaki-r  1604:        IN6_ADDRLIST_READER_FOREACH(ia) {
                   1605:                if (!(ia->ia6_flags & IN6_IFF_AUTOCONF))
1.32      itojun   1606:                        continue;
                   1607:
1.114     ozaki-r  1608:                if (ia->ia6_ndpr == NULL) {
1.32      itojun   1609:                        /*
                   1610:                         * This can happen when we first configure the address
                   1611:                         * (i.e. the address exists, but the prefix does not).
                   1612:                         * XXX: complicated relationships...
                   1613:                         */
                   1614:                        continue;
                   1615:                }
                   1616:
1.114     ozaki-r  1617:                if (find_pfxlist_reachable_router(ia->ia6_ndpr))
1.32      itojun   1618:                        break;
                   1619:        }
1.118     ozaki-r  1620:        pserialize_read_exit(s);
1.114     ozaki-r  1621:
                   1622:        if (ia) {
1.118     ozaki-r  1623:                int bound = curlwp_bind();
                   1624:
                   1625:                s = pserialize_read_enter();
1.114     ozaki-r  1626:                IN6_ADDRLIST_READER_FOREACH(ia) {
1.118     ozaki-r  1627:                        struct ifaddr *ifa = (struct ifaddr *)ia;
                   1628:                        struct psref psref;
                   1629:
1.114     ozaki-r  1630:                        if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1.32      itojun   1631:                                continue;
                   1632:
1.114     ozaki-r  1633:                        if (ia->ia6_ndpr == NULL) /* XXX: see above. */
1.32      itojun   1634:                                continue;
                   1635:
1.118     ozaki-r  1636:                        ia6_acquire(ia, &psref);
                   1637:                        pserialize_read_exit(s);
                   1638:
1.114     ozaki-r  1639:                        if (find_pfxlist_reachable_router(ia->ia6_ndpr)) {
                   1640:                                if (ia->ia6_flags & IN6_IFF_DETACHED) {
                   1641:                                        ia->ia6_flags &= ~IN6_IFF_DETACHED;
                   1642:                                        ia->ia6_flags |= IN6_IFF_TENTATIVE;
1.118     ozaki-r  1643:                                        nd6_dad_start(ifa,
1.56      rpaulo   1644:                                            0);
1.87      roy      1645:                                        /* We will notify the routing socket
                   1646:                                         * of the DAD result, so no need to
                   1647:                                         * here */
1.56      rpaulo   1648:                                }
                   1649:                        } else {
1.114     ozaki-r  1650:                                if ((ia->ia6_flags & IN6_IFF_DETACHED) == 0) {
                   1651:                                        ia->ia6_flags |= IN6_IFF_DETACHED;
1.97      roy      1652:                                        rt_newaddrmsg(RTM_NEWADDR,
1.118     ozaki-r  1653:                                            ifa, 0, NULL);
1.56      rpaulo   1654:                                }
                   1655:                        }
1.118     ozaki-r  1656:
                   1657:                        s = pserialize_read_enter();
                   1658:                        ia6_release(ia, &psref);
1.2       itojun   1659:                }
1.118     ozaki-r  1660:                pserialize_read_exit(s);
                   1661:                curlwp_bindx(bound);
1.2       itojun   1662:        }
                   1663:        else {
1.118     ozaki-r  1664:                int bound = curlwp_bind();
                   1665:
                   1666:                s = pserialize_read_enter();
1.114     ozaki-r  1667:                IN6_ADDRLIST_READER_FOREACH(ia) {
                   1668:                        if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1.32      itojun   1669:                                continue;
                   1670:
1.114     ozaki-r  1671:                        if (ia->ia6_flags & IN6_IFF_DETACHED) {
1.118     ozaki-r  1672:                                struct ifaddr *ifa = (struct ifaddr *)ia;
                   1673:                                struct psref psref;
                   1674:
1.114     ozaki-r  1675:                                ia->ia6_flags &= ~IN6_IFF_DETACHED;
                   1676:                                ia->ia6_flags |= IN6_IFF_TENTATIVE;
1.118     ozaki-r  1677:
                   1678:                                ia6_acquire(ia, &psref);
                   1679:                                pserialize_read_exit(s);
                   1680:
1.56      rpaulo   1681:                                /* Do we need a delay in this case? */
1.118     ozaki-r  1682:                                nd6_dad_start(ifa, 0);
                   1683:
                   1684:                                s = pserialize_read_enter();
                   1685:                                ia6_release(ia, &psref);
1.56      rpaulo   1686:                        }
1.32      itojun   1687:                }
1.118     ozaki-r  1688:                pserialize_read_exit(s);
                   1689:                curlwp_bindx(bound);
1.2       itojun   1690:        }
                   1691: }
                   1692:
1.121     ozaki-r  1693: static int
1.64      christos 1694: nd6_prefix_onlink(struct nd_prefix *pr)
1.2       itojun   1695: {
1.32      itojun   1696:        struct ifaddr *ifa;
                   1697:        struct ifnet *ifp = pr->ndpr_ifp;
                   1698:        struct sockaddr_in6 mask6;
                   1699:        struct nd_prefix *opr;
                   1700:        u_long rtflags;
                   1701:        int error = 0;
1.118     ozaki-r  1702:        struct psref psref;
                   1703:        int bound;
1.130     ryo      1704:        char ip6buf[INET6_ADDRSTRLEN];
                   1705:        char ip6bufp[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
1.32      itojun   1706:
1.128     ozaki-r  1707:        ND6_ASSERT_WLOCK();
                   1708:
1.32      itojun   1709:        /* sanity check */
                   1710:        if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1.107     ozaki-r  1711:                nd6log(LOG_ERR, "%s/%d is already on-link\n",
1.131     christos 1712:                    IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.130     ryo      1713:                    pr->ndpr_plen);
1.51      itojun   1714:                return (EEXIST);
1.32      itojun   1715:        }
                   1716:
                   1717:        /*
                   1718:         * Add the interface route associated with the prefix.  Before
                   1719:         * installing the route, check if there's the same prefix on another
                   1720:         * interface, and the prefix has already installed the interface route.
                   1721:         * Although such a configuration is expected to be rare, we explicitly
                   1722:         * allow it.
                   1723:         */
1.125     ozaki-r  1724:        ND_PREFIX_LIST_FOREACH(opr) {
1.32      itojun   1725:                if (opr == pr)
                   1726:                        continue;
                   1727:
                   1728:                if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0)
                   1729:                        continue;
                   1730:
                   1731:                if (opr->ndpr_plen == pr->ndpr_plen &&
                   1732:                    in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
                   1733:                    &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen))
1.36      itojun   1734:                        return (0);
1.32      itojun   1735:        }
                   1736:
                   1737:        /*
                   1738:         * We prefer link-local addresses as the associated interface address.
                   1739:         */
                   1740:        /* search for a link-local addr */
1.118     ozaki-r  1741:        bound = curlwp_bind();
                   1742:        ifa = (struct ifaddr *)in6ifa_ifpforlinklocal_psref(ifp,
                   1743:            IN6_IFF_NOTREADY | IN6_IFF_ANYCAST, &psref);
1.32      itojun   1744:        if (ifa == NULL) {
1.118     ozaki-r  1745:                int s = pserialize_read_enter();
1.115     ozaki-r  1746:                IFADDR_READER_FOREACH(ifa, ifp) {
1.32      itojun   1747:                        if (ifa->ifa_addr->sa_family == AF_INET6)
                   1748:                                break;
                   1749:                }
1.118     ozaki-r  1750:                if (ifa != NULL)
                   1751:                        ifa_acquire(ifa, &psref);
                   1752:                pserialize_read_exit(s);
1.32      itojun   1753:                /* should we care about ia6_flags? */
                   1754:        }
                   1755:        if (ifa == NULL) {
                   1756:                /*
                   1757:                 * This can still happen, when, for example, we receive an RA
                   1758:                 * containing a prefix with the L bit set and the A bit clear,
                   1759:                 * after removing all IPv6 addresses on the receiving
                   1760:                 * interface.  This should, of course, be rare though.
                   1761:                 */
1.107     ozaki-r  1762:                nd6log(LOG_NOTICE, "failed to find any ifaddr"
1.32      itojun   1763:                    " to add route for a prefix(%s/%d) on %s\n",
1.131     christos 1764:                    IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.107     ozaki-r  1765:                    pr->ndpr_plen, if_name(ifp));
1.118     ozaki-r  1766:                curlwp_bindx(bound);
1.36      itojun   1767:                return (0);
1.32      itojun   1768:        }
1.2       itojun   1769:
                   1770:        /*
1.32      itojun   1771:         * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
                   1772:         * ifa->ifa_rtrequest = nd6_rtrequest;
1.2       itojun   1773:         */
1.78      cegger   1774:        memset(&mask6, 0, sizeof(mask6));
1.85      joerg    1775:        mask6.sin6_family = AF_INET6;
1.32      itojun   1776:        mask6.sin6_len = sizeof(mask6);
                   1777:        mask6.sin6_addr = pr->ndpr_mask;
                   1778:        /* rtrequest() will probably set RTF_UP, but we're not sure. */
                   1779:        rtflags = ifa->ifa_flags | RTF_UP;
                   1780:        if (nd6_need_cache(ifp)) {
                   1781:                /* explicitly set in case ifa_flags does not set the flag. */
1.108     ozaki-r  1782:                rtflags |= RTF_CONNECTED;
1.32      itojun   1783:        } else {
                   1784:                /*
                   1785:                 * explicitly clear the cloning bit in case ifa_flags sets it.
                   1786:                 */
1.108     ozaki-r  1787:                rtflags &= ~RTF_CONNECTED;
1.32      itojun   1788:        }
1.116     ozaki-r  1789:        error = rtrequest_newmsg(RTM_ADD, sin6tosa(&pr->ndpr_prefix),
                   1790:            ifa->ifa_addr, sin6tosa(&mask6), rtflags);
1.32      itojun   1791:        if (error == 0) {
1.101     ozaki-r  1792:                nd6_numroutes++;
1.32      itojun   1793:                pr->ndpr_stateflags |= NDPRF_ONLINK;
                   1794:        } else {
1.107     ozaki-r  1795:                nd6log(LOG_ERR, "failed to add route for a"
1.32      itojun   1796:                    " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
                   1797:                    "errno = %d\n",
1.131     christos 1798:                    IN6_PRINT(ip6bufp, &pr->ndpr_prefix.sin6_addr),
1.32      itojun   1799:                    pr->ndpr_plen, if_name(ifp),
1.131     christos 1800:                    IN6_PRINT(ip6buf,
1.130     ryo      1801:                    &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
1.131     christos 1802:                    IN6_PRINT(ip6bufm, &mask6.sin6_addr), rtflags, error);
1.32      itojun   1803:        }
1.118     ozaki-r  1804:        ifa_release(ifa, &psref);
                   1805:        curlwp_bindx(bound);
1.32      itojun   1806:
1.36      itojun   1807:        return (error);
1.32      itojun   1808: }
                   1809:
1.121     ozaki-r  1810: static int
1.64      christos 1811: nd6_prefix_offlink(struct nd_prefix *pr)
1.32      itojun   1812: {
                   1813:        int error = 0;
                   1814:        struct ifnet *ifp = pr->ndpr_ifp;
                   1815:        struct nd_prefix *opr;
                   1816:        struct sockaddr_in6 sa6, mask6;
1.130     ryo      1817:        char ip6buf[INET6_ADDRSTRLEN];
1.32      itojun   1818:
1.128     ozaki-r  1819:        ND6_ASSERT_WLOCK();
                   1820:
1.32      itojun   1821:        /* sanity check */
                   1822:        if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1.107     ozaki-r  1823:                nd6log(LOG_ERR, "%s/%d is already off-link\n",
1.131     christos 1824:                    IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.130     ryo      1825:                    pr->ndpr_plen);
1.36      itojun   1826:                return (EEXIST);
1.32      itojun   1827:        }
                   1828:
1.69      dyoung   1829:        sockaddr_in6_init(&sa6, &pr->ndpr_prefix.sin6_addr, 0, 0, 0);
                   1830:        sockaddr_in6_init(&mask6, &pr->ndpr_mask, 0, 0, 0);
1.116     ozaki-r  1831:        error = rtrequest_newmsg(RTM_DELETE, sin6tosa(&sa6), NULL,
                   1832:            sin6tosa(&mask6), 0);
1.32      itojun   1833:        if (error == 0) {
                   1834:                pr->ndpr_stateflags &= ~NDPRF_ONLINK;
1.101     ozaki-r  1835:                nd6_numroutes--;
1.2       itojun   1836:
1.32      itojun   1837:                /*
                   1838:                 * There might be the same prefix on another interface,
                   1839:                 * the prefix which could not be on-link just because we have
                   1840:                 * the interface route (see comments in nd6_prefix_onlink).
                   1841:                 * If there's one, try to make the prefix on-link on the
                   1842:                 * interface.
                   1843:                 */
1.125     ozaki-r  1844:                ND_PREFIX_LIST_FOREACH(opr) {
1.32      itojun   1845:                        if (opr == pr)
                   1846:                                continue;
1.2       itojun   1847:
1.32      itojun   1848:                        if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0)
                   1849:                                continue;
1.2       itojun   1850:
1.32      itojun   1851:                        /*
                   1852:                         * KAME specific: detached prefixes should not be
                   1853:                         * on-link.
                   1854:                         */
                   1855:                        if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0)
                   1856:                                continue;
1.2       itojun   1857:
1.32      itojun   1858:                        if (opr->ndpr_plen == pr->ndpr_plen &&
                   1859:                            in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
                   1860:                            &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
                   1861:                                int e;
                   1862:
                   1863:                                if ((e = nd6_prefix_onlink(opr)) != 0) {
1.107     ozaki-r  1864:                                        nd6log(LOG_ERR, "failed to "
1.32      itojun   1865:                                            "recover a prefix %s/%d from %s "
                   1866:                                            "to %s (errno = %d)\n",
1.131     christos 1867:                                            IN6_PRINT(ip6buf,
1.130     ryo      1868:                                            &opr->ndpr_prefix.sin6_addr),
1.32      itojun   1869:                                            opr->ndpr_plen, if_name(ifp),
1.107     ozaki-r  1870:                                            if_name(opr->ndpr_ifp), e);
1.32      itojun   1871:                                }
                   1872:                        }
                   1873:                }
                   1874:        } else {
                   1875:                /* XXX: can we still set the NDPRF_ONLINK flag? */
1.107     ozaki-r  1876:                nd6log(LOG_ERR, "failed to delete route: "
1.32      itojun   1877:                    "%s/%d on %s (errno = %d)\n",
1.131     christos 1878:                    IN6_PRINT(ip6buf, &sa6.sin6_addr), pr->ndpr_plen,
1.130     ryo      1879:                    if_name(ifp),
1.107     ozaki-r  1880:                    error);
1.2       itojun   1881:        }
                   1882:
1.101     ozaki-r  1883:        return error;
1.2       itojun   1884: }
                   1885:
                   1886: static struct in6_ifaddr *
1.118     ozaki-r  1887: in6_ifadd(struct nd_prefixctl *prc, int mcast, struct psref *psref)
1.2       itojun   1888: {
1.94      matt     1889:        struct ifnet *ifp = prc->ndprc_ifp;
1.2       itojun   1890:        struct ifaddr *ifa;
1.32      itojun   1891:        struct in6_aliasreq ifra;
                   1892:        struct in6_ifaddr *ia, *ib;
                   1893:        int error, plen0;
1.2       itojun   1894:        struct in6_addr mask;
1.94      matt     1895:        int prefixlen = prc->ndprc_plen;
1.56      rpaulo   1896:        int updateflags;
1.118     ozaki-r  1897:        int s;
1.130     ryo      1898:        char ip6buf[INET6_ADDRSTRLEN];
1.2       itojun   1899:
1.128     ozaki-r  1900:        ND6_ASSERT_WLOCK();
                   1901:
1.31      itojun   1902:        in6_prefixlen2mask(&mask, prefixlen);
1.2       itojun   1903:
1.32      itojun   1904:        /*
                   1905:         * find a link-local address (will be interface ID).
                   1906:         * Is it really mandatory? Theoretically, a global or a site-local
                   1907:         * address can be configured without a link-local address, if we
                   1908:         * have a unique interface identifier...
                   1909:         *
                   1910:         * it is not mandatory to have a link-local address, we can generate
                   1911:         * interface identifier on the fly.  we do this because:
                   1912:         * (1) it should be the easiest way to find interface identifier.
                   1913:         * (2) RFC2462 5.4 suggesting the use of the same interface identifier
                   1914:         * for multiple addresses on a single interface, and possible shortcut
                   1915:         * of DAD.  we omitted DAD for this reason in the past.
                   1916:         * (3) a user can prevent autoconfiguration of global address
                   1917:         * by removing link-local address by hand (this is partly because we
1.55      rpaulo   1918:         * don't have other way to control the use of IPv6 on an interface.
1.32      itojun   1919:         * this has been our design choice - cf. NRL's "ifconfig auto").
                   1920:         * (4) it is easier to manage when an interface has addresses
                   1921:         * with the same interface identifier, than to have multiple addresses
                   1922:         * with different interface identifiers.
                   1923:         */
1.118     ozaki-r  1924:        s = pserialize_read_enter();
1.32      itojun   1925:        ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */
1.2       itojun   1926:        if (ifa)
                   1927:                ib = (struct in6_ifaddr *)ifa;
1.118     ozaki-r  1928:        else {
                   1929:                pserialize_read_exit(s);
1.2       itojun   1930:                return NULL;
1.118     ozaki-r  1931:        }
1.2       itojun   1932:
                   1933: #if 0 /* don't care link local addr state, and always do DAD */
                   1934:        /* if link-local address is not eligible, do not autoconfigure. */
                   1935:        if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
                   1936:                printf("in6_ifadd: link-local address not ready\n");
                   1937:                return NULL;
                   1938:        }
                   1939: #endif
                   1940:
                   1941:        /* prefixlen + ifidlen must be equal to 128 */
1.32      itojun   1942:        plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL);
                   1943:        if (prefixlen != plen0) {
1.107     ozaki-r  1944:                nd6log(LOG_INFO, "wrong prefixlen for %s "
1.32      itojun   1945:                    "(prefix=%d ifid=%d)\n",
1.107     ozaki-r  1946:                    if_name(ifp), prefixlen, 128 - plen0);
1.118     ozaki-r  1947:                pserialize_read_exit(s);
1.2       itojun   1948:                return NULL;
                   1949:        }
                   1950:
                   1951:        /* make ifaddr */
                   1952:
1.56      rpaulo   1953:        memset(&ifra, 0, sizeof(ifra));
1.32      itojun   1954:        /*
                   1955:         * in6_update_ifa() does not use ifra_name, but we accurately set it
                   1956:         * for safety.
                   1957:         */
                   1958:        strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
1.94      matt     1959:        sockaddr_in6_init(&ifra.ifra_addr, &prc->ndprc_prefix.sin6_addr, 0, 0, 0);
1.32      itojun   1960:        /* prefix */
                   1961:        ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
                   1962:        ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
                   1963:        ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
                   1964:        ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1.2       itojun   1965:
                   1966:        /* interface ID */
1.32      itojun   1967:        ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
                   1968:            (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
                   1969:        ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
                   1970:            (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
                   1971:        ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
                   1972:            (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
                   1973:        ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
                   1974:            (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
1.118     ozaki-r  1975:        pserialize_read_exit(s);
1.33      itojun   1976:
1.32      itojun   1977:        /* new prefix mask. */
1.69      dyoung   1978:        sockaddr_in6_init(&ifra.ifra_prefixmask, &mask, 0, 0, 0);
1.2       itojun   1979:
1.56      rpaulo   1980:        /* lifetimes */
1.94      matt     1981:        ifra.ifra_lifetime.ia6t_vltime = prc->ndprc_vltime;
                   1982:        ifra.ifra_lifetime.ia6t_pltime = prc->ndprc_pltime;
1.2       itojun   1983:
1.32      itojun   1984:        /* XXX: scope zone ID? */
1.2       itojun   1985:
1.32      itojun   1986:        ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
1.2       itojun   1987:
1.56      rpaulo   1988:        /*
                   1989:         * Make sure that we do not have this address already.  This should
                   1990:         * usually not happen, but we can still see this case, e.g., if we
                   1991:         * have manually configured the exact address to be configured.
                   1992:         */
1.118     ozaki-r  1993:        s = pserialize_read_enter();
1.56      rpaulo   1994:        if (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr) != NULL) {
                   1995:                /* this should be rare enough to make an explicit log */
                   1996:                log(LOG_INFO, "in6_ifadd: %s is already configured\n",
1.131     christos 1997:                    IN6_PRINT(ip6buf, &ifra.ifra_addr.sin6_addr));
1.118     ozaki-r  1998:                pserialize_read_exit(s);
1.56      rpaulo   1999:                return (NULL);
                   2000:        }
1.118     ozaki-r  2001:        pserialize_read_exit(s);
1.56      rpaulo   2002:
                   2003:        /*
                   2004:         * Allocate ifaddr structure, link into chain, etc.
                   2005:         * If we are going to create a new address upon receiving a multicasted
                   2006:         * RA, we need to impose a random delay before starting DAD.
                   2007:         * [draft-ietf-ipv6-rfc2462bis-02.txt, Section 5.4.2]
                   2008:         */
                   2009:        updateflags = 0;
                   2010:        if (mcast)
                   2011:                updateflags |= IN6_IFAUPDATE_DADDELAY;
1.129     christos 2012:        if ((error = in6_update_ifa(ifp, &ifra, updateflags)) != 0) {
1.107     ozaki-r  2013:                nd6log(LOG_ERR, "failed to make ifaddr %s on %s (errno=%d)\n",
1.131     christos 2014:                    IN6_PRINT(ip6buf, &ifra.ifra_addr.sin6_addr), if_name(ifp),
1.107     ozaki-r  2015:                    error);
1.36      itojun   2016:                return (NULL);  /* ifaddr must not have been allocated. */
1.32      itojun   2017:        }
1.2       itojun   2018:
1.118     ozaki-r  2019:        ia = in6ifa_ifpwithaddr_psref(ifp, &ifra.ifra_addr.sin6_addr, psref);
1.2       itojun   2020:
1.36      itojun   2021:        return (ia);            /* this is always non-NULL */
1.2       itojun   2022: }
                   2023:
                   2024: int
1.64      christos 2025: in6_tmpifadd(
                   2026:        const struct in6_ifaddr *ia0, /* corresponding public address */
                   2027:        int forcegen,
                   2028:        int dad_delay)
1.56      rpaulo   2029: {
                   2030:        struct ifnet *ifp = ia0->ia_ifa.ifa_ifp;
                   2031:        struct in6_ifaddr *newia, *ia;
                   2032:        struct in6_aliasreq ifra;
                   2033:        int i, error;
                   2034:        int trylimit = 3;       /* XXX: adhoc value */
                   2035:        int updateflags;
                   2036:        u_int32_t randid[2];
                   2037:        u_int32_t vltime0, pltime0;
1.117     ozaki-r  2038:        int s;
1.56      rpaulo   2039:
1.128     ozaki-r  2040:        ND6_ASSERT_WLOCK();
                   2041:
1.56      rpaulo   2042:        memset(&ifra, 0, sizeof(ifra));
                   2043:        strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
                   2044:        ifra.ifra_addr = ia0->ia_addr;
                   2045:        /* copy prefix mask */
                   2046:        ifra.ifra_prefixmask = ia0->ia_prefixmask;
                   2047:        /* clear the old IFID */
                   2048:        for (i = 0; i < 4; i++) {
                   2049:                ifra.ifra_addr.sin6_addr.s6_addr32[i] &=
                   2050:                    ifra.ifra_prefixmask.sin6_addr.s6_addr32[i];
                   2051:        }
                   2052:
                   2053:   again:
                   2054:        if (in6_get_tmpifid(ifp, (u_int8_t *)randid,
                   2055:            (const u_int8_t *)&ia0->ia_addr.sin6_addr.s6_addr[8], forcegen)) {
1.107     ozaki-r  2056:                nd6log(LOG_NOTICE, "failed to find a good random IFID\n");
1.56      rpaulo   2057:                return (EINVAL);
                   2058:        }
                   2059:        ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
                   2060:            (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
                   2061:        ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
                   2062:            (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));
                   2063:
                   2064:        /*
                   2065:         * in6_get_tmpifid() quite likely provided a unique interface ID.
                   2066:         * However, we may still have a chance to see collision, because
                   2067:         * there may be a time lag between generation of the ID and generation
                   2068:         * of the address.  So, we'll do one more sanity check.
                   2069:         */
1.117     ozaki-r  2070:        s = pserialize_read_enter();
1.113     ozaki-r  2071:        IN6_ADDRLIST_READER_FOREACH(ia) {
1.56      rpaulo   2072:                if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
                   2073:                    &ifra.ifra_addr.sin6_addr)) {
1.117     ozaki-r  2074:                        pserialize_read_exit(s);
1.56      rpaulo   2075:                        if (trylimit-- == 0) {
                   2076:                                /*
                   2077:                                 * Give up.  Something strange should have
                   2078:                                 * happened.
                   2079:                                 */
1.107     ozaki-r  2080:                                nd6log(LOG_NOTICE,
                   2081:                                    "failed to find a unique random IFID\n");
1.56      rpaulo   2082:                                return (EEXIST);
                   2083:                        }
                   2084:                        forcegen = 1;
                   2085:                        goto again;
                   2086:                }
                   2087:        }
1.117     ozaki-r  2088:        pserialize_read_exit(s);
1.56      rpaulo   2089:
                   2090:        /*
                   2091:         * The Valid Lifetime is the lower of the Valid Lifetime of the
                   2092:          * public address or TEMP_VALID_LIFETIME.
                   2093:         * The Preferred Lifetime is the lower of the Preferred Lifetime
                   2094:          * of the public address or TEMP_PREFERRED_LIFETIME -
                   2095:          * DESYNC_FACTOR.
                   2096:         */
                   2097:        if (ia0->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
                   2098:                vltime0 = IFA6_IS_INVALID(ia0) ? 0 :
                   2099:                    (ia0->ia6_lifetime.ia6t_vltime -
1.102     ozaki-r  2100:                    (time_uptime - ia0->ia6_updatetime));
1.56      rpaulo   2101:                if (vltime0 > ip6_temp_valid_lifetime)
                   2102:                        vltime0 = ip6_temp_valid_lifetime;
                   2103:        } else
                   2104:                vltime0 = ip6_temp_valid_lifetime;
                   2105:        if (ia0->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
                   2106:                pltime0 = IFA6_IS_DEPRECATED(ia0) ? 0 :
                   2107:                    (ia0->ia6_lifetime.ia6t_pltime -
1.102     ozaki-r  2108:                    (time_uptime - ia0->ia6_updatetime));
1.56      rpaulo   2109:                if (pltime0 > ip6_temp_preferred_lifetime - ip6_desync_factor){
                   2110:                        pltime0 = ip6_temp_preferred_lifetime -
                   2111:                            ip6_desync_factor;
                   2112:                }
                   2113:        } else
                   2114:                pltime0 = ip6_temp_preferred_lifetime - ip6_desync_factor;
                   2115:        ifra.ifra_lifetime.ia6t_vltime = vltime0;
                   2116:        ifra.ifra_lifetime.ia6t_pltime = pltime0;
                   2117:
                   2118:        /*
                   2119:         * A temporary address is created only if this calculated Preferred
                   2120:         * Lifetime is greater than REGEN_ADVANCE time units.
                   2121:         */
                   2122:        if (ifra.ifra_lifetime.ia6t_pltime <= ip6_temp_regen_advance)
                   2123:                return (0);
                   2124:
                   2125:        /* XXX: scope zone ID? */
                   2126:
                   2127:        ifra.ifra_flags |= (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY);
                   2128:
                   2129:        /* allocate ifaddr structure, link into chain, etc. */
                   2130:        updateflags = 0;
1.57      rpaulo   2131:        if (dad_delay)
1.56      rpaulo   2132:                updateflags |= IN6_IFAUPDATE_DADDELAY;
1.129     christos 2133:        if ((error = in6_update_ifa(ifp, &ifra, updateflags)) != 0)
1.56      rpaulo   2134:                return (error);
                   2135:
1.118     ozaki-r  2136:        s = pserialize_read_enter();
1.56      rpaulo   2137:        newia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
                   2138:        if (newia == NULL) {    /* XXX: can it happen? */
1.118     ozaki-r  2139:                pserialize_read_exit(s);
1.107     ozaki-r  2140:                nd6log(LOG_ERR,
                   2141:                    "ifa update succeeded, but we got no ifaddr\n");
1.56      rpaulo   2142:                return (EINVAL); /* XXX */
                   2143:        }
                   2144:        newia->ia6_ndpr = ia0->ia6_ndpr;
                   2145:        newia->ia6_ndpr->ndpr_refcnt++;
1.118     ozaki-r  2146:        pserialize_read_exit(s);
1.56      rpaulo   2147:
                   2148:        /*
                   2149:         * A newly added address might affect the status of other addresses.
                   2150:         * XXX: when the temporary address is generated with a new public
                   2151:         * address, the onlink check is redundant.  However, it would be safe
                   2152:         * to do the check explicitly everywhere a new address is generated,
                   2153:         * and, in fact, we surely need the check when we create a new
                   2154:         * temporary address due to deprecation of an old temporary address.
                   2155:         */
1.123     ozaki-r  2156:        nd6_pfxlist_onlink_check();
1.56      rpaulo   2157:
                   2158:        return (0);
                   2159: }
                   2160:
                   2161: static int
1.2       itojun   2162: in6_init_prefix_ltimes(struct nd_prefix *ndpr)
                   2163: {
1.7       itojun   2164:
1.128     ozaki-r  2165:        ND6_ASSERT_WLOCK();
                   2166:
1.26      itojun   2167:        /* check if preferred lifetime > valid lifetime.  RFC2462 5.5.3 (c) */
1.2       itojun   2168:        if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
1.107     ozaki-r  2169:                nd6log(LOG_INFO, "preferred lifetime"
1.2       itojun   2170:                    "(%d) is greater than valid lifetime(%d)\n",
1.107     ozaki-r  2171:                    (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime);
1.2       itojun   2172:                return (EINVAL);
                   2173:        }
1.7       itojun   2174:        if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
1.2       itojun   2175:                ndpr->ndpr_preferred = 0;
                   2176:        else
1.102     ozaki-r  2177:                ndpr->ndpr_preferred = time_uptime + ndpr->ndpr_pltime;
1.7       itojun   2178:        if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
1.2       itojun   2179:                ndpr->ndpr_expire = 0;
                   2180:        else
1.102     ozaki-r  2181:                ndpr->ndpr_expire = time_uptime + ndpr->ndpr_vltime;
1.2       itojun   2182:
                   2183:        return 0;
                   2184: }
                   2185:
                   2186: static void
1.94      matt     2187: in6_init_address_ltimes(struct nd_prefix *newpr,
1.60      christos 2188:     struct in6_addrlifetime *lt6)
1.2       itojun   2189: {
1.7       itojun   2190:
                   2191:        /* Valid lifetime must not be updated unless explicitly specified. */
1.32      itojun   2192:        /* init ia6t_expire */
                   2193:        if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
                   2194:                lt6->ia6t_expire = 0;
                   2195:        else {
1.102     ozaki-r  2196:                lt6->ia6t_expire = time_uptime;
1.32      itojun   2197:                lt6->ia6t_expire += lt6->ia6t_vltime;
1.2       itojun   2198:        }
1.7       itojun   2199:
1.2       itojun   2200:        /* init ia6t_preferred */
1.7       itojun   2201:        if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1.2       itojun   2202:                lt6->ia6t_preferred = 0;
                   2203:        else {
1.102     ozaki-r  2204:                lt6->ia6t_preferred = time_uptime;
1.2       itojun   2205:                lt6->ia6t_preferred += lt6->ia6t_pltime;
                   2206:        }
                   2207: }
                   2208:
                   2209: /*
                   2210:  * Delete all the routing table entries that use the specified gateway.
                   2211:  * XXX: this function causes search through all entries of routing table, so
1.16      itojun   2212:  * it shouldn't be called when acting as a router.
1.2       itojun   2213:  */
                   2214: void
1.123     ozaki-r  2215: nd6_rt_flush(struct in6_addr *gateway, struct ifnet *ifp)
1.2       itojun   2216: {
1.138     ozaki-r  2217: #ifndef NET_MPSAFE
1.137     ozaki-r  2218:        int s = splsoftnet();
1.138     ozaki-r  2219: #endif
1.2       itojun   2220:
                   2221:        /* We'll care only link-local addresses */
1.138     ozaki-r  2222:        if (!IN6_IS_ADDR_LINKLOCAL(gateway))
                   2223:                goto out;
1.2       itojun   2224:
1.120     ozaki-r  2225:        rt_delete_matched_entries(AF_INET6, rt6_deleteroute_matcher, gateway);
1.138     ozaki-r  2226:
                   2227: out:
                   2228: #ifndef NET_MPSAFE
1.137     ozaki-r  2229:        splx(s);
1.138     ozaki-r  2230: #endif
                   2231:        return; /* XXX gcc */
1.2       itojun   2232: }
                   2233:
                   2234: static int
1.120     ozaki-r  2235: rt6_deleteroute_matcher(struct rtentry *rt, void *arg)
1.2       itojun   2236: {
                   2237:        struct in6_addr *gate = (struct in6_addr *)arg;
                   2238:
                   2239:        if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
1.36      itojun   2240:                return (0);
1.2       itojun   2241:
1.104     ozaki-r  2242:        if (!IN6_ARE_ADDR_EQUAL(gate, &satosin6(rt->rt_gateway)->sin6_addr))
1.36      itojun   2243:                return (0);
1.26      itojun   2244:
                   2245:        /*
1.32      itojun   2246:         * Do not delete a static route.
                   2247:         * XXX: this seems to be a bit ad-hoc. Should we consider the
                   2248:         * 'cloned' bit instead?
                   2249:         */
                   2250:        if ((rt->rt_flags & RTF_STATIC) != 0)
1.36      itojun   2251:                return (0);
1.32      itojun   2252:
                   2253:        /*
1.2       itojun   2254:         * We delete only host route. This means, in particular, we don't
                   2255:         * delete default route.
                   2256:         */
                   2257:        if ((rt->rt_flags & RTF_HOST) == 0)
1.36      itojun   2258:                return (0);
1.2       itojun   2259:
1.120     ozaki-r  2260:        return 1;
1.2       itojun   2261: }

CVSweb <webmaster@jp.NetBSD.org>