The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/nd6_rtr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: nd6_rtr.c,v 1.51 2004/11/17 03:20:53 itojun Exp $      */
    2 /*      $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $        */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.51 2004/11/17 03:20:53 itojun Exp $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/malloc.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/socket.h>
   41 #include <sys/sockio.h>
   42 #include <sys/time.h>
   43 #include <sys/kernel.h>
   44 #include <sys/errno.h>
   45 #include <sys/ioctl.h>
   46 #include <sys/syslog.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_types.h>
   50 #include <net/if_dl.h>
   51 #include <net/route.h>
   52 #include <net/radix.h>
   53 
   54 #include <netinet/in.h>
   55 #include <netinet6/in6_var.h>
   56 #include <netinet/ip6.h>
   57 #include <netinet6/ip6_var.h>
   58 #include <netinet6/nd6.h>
   59 #include <netinet/icmp6.h>
   60 
   61 #include <net/net_osdep.h>
   62 
   63 #define SDL(s)  ((struct sockaddr_dl *)s)
   64 
   65 static int rtpref __P((struct nd_defrouter *));
   66 static struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *));
   67 static struct in6_ifaddr *in6_ifadd __P((struct nd_prefix *));
   68 static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
   69         struct nd_defrouter *));
   70 static void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *));
   71 static void pfxrtr_del __P((struct nd_pfxrouter *));
   72 static struct nd_pfxrouter *find_pfxlist_reachable_router
   73         __P((struct nd_prefix *));
   74 static void defrouter_delreq __P((struct nd_defrouter *));
   75 static void nd6_rtmsg __P((int, struct rtentry *));
   76 
   77 static void in6_init_address_ltimes __P((struct nd_prefix *ndpr,
   78         struct in6_addrlifetime *lt6));
   79 
   80 static int rt6_deleteroute __P((struct radix_node *, void *));
   81 
   82 extern int nd6_recalc_reachtm_interval;
   83 
   84 static struct ifnet *nd6_defifp;
   85 int nd6_defifindex;
   86 
   87 /*
   88  * Receive Router Solicitation Message - just for routers.
   89  * Router solicitation/advertisement is mostly managed by userland program
   90  * (rtadvd) so here we have no function like nd6_ra_output().
   91  *
   92  * Based on RFC 2461
   93  */
   94 void
   95 nd6_rs_input(m, off, icmp6len)
   96         struct  mbuf *m;
   97         int off, icmp6len;
   98 {
   99         struct ifnet *ifp = m->m_pkthdr.rcvif;
  100         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  101         struct nd_router_solicit *nd_rs;
  102         struct in6_addr saddr6 = ip6->ip6_src;
  103 #if 0
  104         struct in6_addr daddr6 = ip6->ip6_dst;
  105 #endif
  106         char *lladdr = NULL;
  107         int lladdrlen = 0;
  108 #if 0
  109         struct sockaddr_dl *sdl = (struct sockaddr_dl *)NULL;
  110         struct llinfo_nd6 *ln = (struct llinfo_nd6 *)NULL;
  111         struct rtentry *rt = NULL;
  112         int is_newentry;
  113 #endif
  114         union nd_opts ndopts;
  115 
  116         /* If I'm not a router, ignore it. */
  117         if (ip6_accept_rtadv != 0 || !ip6_forwarding)
  118                 goto freeit;
  119 
  120         /* Sanity checks */
  121         if (ip6->ip6_hlim != 255) {
  122                 nd6log((LOG_ERR,
  123                     "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
  124                     ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
  125                     ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
  126                 goto bad;
  127         }
  128 
  129         /*
  130          * Don't update the neighbor cache, if src = ::.
  131          * This indicates that the src has no IP address assigned yet.
  132          */
  133         if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
  134                 goto freeit;
  135 
  136         IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
  137         if (nd_rs == NULL) {
  138                 icmp6stat.icp6s_tooshort++;
  139                 return;
  140         }
  141 
  142         icmp6len -= sizeof(*nd_rs);
  143         nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
  144         if (nd6_options(&ndopts) < 0) {
  145                 nd6log((LOG_INFO,
  146                     "nd6_rs_input: invalid ND option, ignored\n"));
  147                 /* nd6_options have incremented stats */
  148                 goto freeit;
  149         }
  150 
  151         if (ndopts.nd_opts_src_lladdr) {
  152                 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
  153                 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
  154         }
  155 
  156         if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
  157                 nd6log((LOG_INFO,
  158                     "nd6_rs_input: lladdrlen mismatch for %s "
  159                     "(if %d, RS packet %d)\n",
  160                     ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2));
  161                 goto bad;
  162         }
  163 
  164         nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
  165 
  166  freeit:
  167         m_freem(m);
  168         return;
  169 
  170  bad:
  171         icmp6stat.icp6s_badrs++;
  172         m_freem(m);
  173 }
  174 
  175 /*
  176  * Receive Router Advertisement Message.
  177  *
  178  * Based on RFC 2461
  179  * TODO: on-link bit on prefix information
  180  * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
  181  */
  182 void
  183 nd6_ra_input(m, off, icmp6len)
  184         struct  mbuf *m;
  185         int off, icmp6len;
  186 {
  187         struct ifnet *ifp = m->m_pkthdr.rcvif;
  188         struct nd_ifinfo *ndi = ND_IFINFO(ifp);
  189         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  190         struct nd_router_advert *nd_ra;
  191         struct in6_addr saddr6 = ip6->ip6_src;
  192 #if 0
  193         struct in6_addr daddr6 = ip6->ip6_dst;
  194         int flags; /* = nd_ra->nd_ra_flags_reserved; */
  195         int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0);
  196         int is_other = ((flags & ND_RA_FLAG_OTHER) != 0);
  197 #endif
  198         union nd_opts ndopts;
  199         struct nd_defrouter *dr;
  200 
  201         /*
  202          * We only accept RAs only when
  203          * the system-wide variable allows the acceptance, and
  204          * per-interface variable allows RAs on the receiving interface.
  205          */
  206         if (ip6_accept_rtadv == 0)
  207                 goto freeit;
  208         if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV))
  209                 goto freeit;
  210 
  211         if (ip6->ip6_hlim != 255) {
  212                 nd6log((LOG_ERR,
  213                     "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
  214                     ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
  215                     ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
  216                 goto bad;
  217         }
  218 
  219         if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
  220                 nd6log((LOG_ERR,
  221                     "nd6_ra_input: src %s is not link-local\n",
  222                     ip6_sprintf(&saddr6)));
  223                 goto bad;
  224         }
  225 
  226         IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
  227         if (nd_ra == NULL) {
  228                 icmp6stat.icp6s_tooshort++;
  229                 return;
  230         }
  231 
  232         icmp6len -= sizeof(*nd_ra);
  233         nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
  234         if (nd6_options(&ndopts) < 0) {
  235                 nd6log((LOG_INFO,
  236                     "nd6_ra_input: invalid ND option, ignored\n"));
  237                 /* nd6_options have incremented stats */
  238                 goto freeit;
  239         }
  240 
  241     {
  242         struct nd_defrouter dr0;
  243         u_int32_t advreachable = nd_ra->nd_ra_reachable;
  244 
  245         Bzero(&dr0, sizeof(dr0));
  246         dr0.rtaddr = saddr6;
  247         dr0.flags  = nd_ra->nd_ra_flags_reserved;
  248         dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
  249         dr0.expire = time.tv_sec + dr0.rtlifetime;
  250         dr0.ifp = ifp;
  251         /* unspecified or not? (RFC 2461 6.3.4) */
  252         if (advreachable) {
  253                 NTOHL(advreachable);
  254                 if (advreachable <= MAX_REACHABLE_TIME &&
  255                     ndi->basereachable != advreachable) {
  256                         ndi->basereachable = advreachable;
  257                         ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
  258                         ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
  259                 }
  260         }
  261         if (nd_ra->nd_ra_retransmit)
  262                 ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
  263         if (nd_ra->nd_ra_curhoplimit)
  264                 ndi->chlim = nd_ra->nd_ra_curhoplimit;
  265         dr = defrtrlist_update(&dr0);
  266     }
  267 
  268         /*
  269          * prefix
  270          */
  271         if (ndopts.nd_opts_pi) {
  272                 struct nd_opt_hdr *pt;
  273                 struct nd_opt_prefix_info *pi = NULL;
  274                 struct nd_prefix pr;
  275 
  276                 for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
  277                      pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
  278                      pt = (struct nd_opt_hdr *)((caddr_t)pt +
  279                                                 (pt->nd_opt_len << 3))) {
  280                         if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
  281                                 continue;
  282                         pi = (struct nd_opt_prefix_info *)pt;
  283 
  284                         if (pi->nd_opt_pi_len != 4) {
  285                                 nd6log((LOG_INFO,
  286                                     "nd6_ra_input: invalid option "
  287                                     "len %d for prefix information option, "
  288                                     "ignored\n", pi->nd_opt_pi_len));
  289                                 continue;
  290                         }
  291 
  292                         if (128 < pi->nd_opt_pi_prefix_len) {
  293                                 nd6log((LOG_INFO,
  294                                     "nd6_ra_input: invalid prefix "
  295                                     "len %d for prefix information option, "
  296                                     "ignored\n", pi->nd_opt_pi_prefix_len));
  297                                 continue;
  298                         }
  299 
  300                         if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
  301                          || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
  302                                 nd6log((LOG_INFO,
  303                                     "nd6_ra_input: invalid prefix "
  304                                     "%s, ignored\n",
  305                                     ip6_sprintf(&pi->nd_opt_pi_prefix)));
  306                                 continue;
  307                         }
  308 
  309                         /* aggregatable unicast address, rfc2374 */
  310                         if ((pi->nd_opt_pi_prefix.s6_addr8[0] & 0xe0) == 0x20
  311                          && pi->nd_opt_pi_prefix_len != 64) {
  312                                 nd6log((LOG_INFO,
  313                                     "nd6_ra_input: invalid prefixlen "
  314                                     "%d for rfc2374 prefix %s, ignored\n",
  315                                     pi->nd_opt_pi_prefix_len,
  316                                     ip6_sprintf(&pi->nd_opt_pi_prefix)));
  317                                 continue;
  318                         }
  319 
  320                         bzero(&pr, sizeof(pr));
  321                         pr.ndpr_prefix.sin6_family = AF_INET6;
  322                         pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
  323                         pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
  324                         pr.ndpr_ifp = (struct ifnet *)m->m_pkthdr.rcvif;
  325 
  326                         pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
  327                              ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
  328                         pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
  329                              ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
  330                         pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
  331                         pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
  332                         pr.ndpr_pltime = ntohl(pi->nd_opt_pi_preferred_time);
  333                         pr.ndpr_lastupdate = time.tv_sec;
  334 
  335                         if (in6_init_prefix_ltimes(&pr))
  336                                 continue; /* prefix lifetime init failed */
  337 
  338                         (void)prelist_update(&pr, dr, m);
  339                 }
  340         }
  341 
  342         /*
  343          * MTU
  344          */
  345         if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
  346                 u_long mtu;
  347                 u_long maxmtu;
  348 
  349                 mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
  350 
  351                 /* lower bound */
  352                 if (mtu < IPV6_MMTU) {
  353                         nd6log((LOG_INFO, "nd6_ra_input: bogus mtu option "
  354                             "mtu=%lu sent from %s, ignoring\n",
  355                             mtu, ip6_sprintf(&ip6->ip6_src)));
  356                         goto skip;
  357                 }
  358 
  359                 /* upper bound */
  360                 maxmtu = (ndi->maxmtu && ndi->maxmtu < ifp->if_mtu)
  361                     ? ndi->maxmtu : ifp->if_mtu;
  362                 if (mtu <= maxmtu) {
  363                         int change = (ndi->linkmtu != mtu);
  364 
  365                         ndi->linkmtu = mtu;
  366                         if (change) /* in6_maxmtu may change */
  367                                 in6_setmaxmtu();
  368                 } else {
  369                         nd6log((LOG_INFO, "nd6_ra_input: bogus mtu "
  370                             "mtu=%lu sent from %s; "
  371                             "exceeds maxmtu %lu, ignoring\n",
  372                             mtu, ip6_sprintf(&ip6->ip6_src), maxmtu));
  373                 }
  374         }
  375 
  376  skip:
  377 
  378         /*
  379          * Source link layer address
  380          */
  381     {
  382         char *lladdr = NULL;
  383         int lladdrlen = 0;
  384 
  385         if (ndopts.nd_opts_src_lladdr) {
  386                 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
  387                 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
  388         }
  389 
  390         if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
  391                 nd6log((LOG_INFO,
  392                     "nd6_ra_input: lladdrlen mismatch for %s "
  393                     "(if %d, RA packet %d)\n", ip6_sprintf(&saddr6),
  394                     ifp->if_addrlen, lladdrlen - 2));
  395                 goto bad;
  396         }
  397 
  398         nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
  399 
  400         /*
  401          * Installing a link-layer address might change the state of the
  402          * router's neighbor cache, which might also affect our on-link
  403          * detection of adveritsed prefixes.
  404          */
  405         pfxlist_onlink_check();
  406     }
  407 
  408  freeit:
  409         m_freem(m);
  410         return;
  411 
  412  bad:
  413         icmp6stat.icp6s_badra++;
  414         m_freem(m);
  415 }
  416 
  417 /*
  418  * default router list processing sub routines
  419  */
  420 
  421 /* tell the change to user processes watching the routing socket. */
  422 static void
  423 nd6_rtmsg(cmd, rt)
  424         int cmd;
  425         struct rtentry *rt;
  426 {
  427         struct rt_addrinfo info;
  428 
  429         bzero((caddr_t)&info, sizeof(info));
  430         info.rti_info[RTAX_DST] = rt_key(rt);
  431         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  432         info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  433         if (rt->rt_ifp) {
  434                 info.rti_info[RTAX_IFP] =
  435                     TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr;
  436                 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
  437         }
  438 
  439         rt_missmsg(cmd, &info, rt->rt_flags, 0);
  440 }
  441 
  442 void
  443 defrouter_addreq(new)
  444         struct nd_defrouter *new;
  445 {
  446         struct sockaddr_in6 def, mask, gate;
  447         struct rtentry *newrt = NULL;
  448         int s;
  449         int error;
  450 
  451         Bzero(&def, sizeof(def));
  452         Bzero(&mask, sizeof(mask));
  453         Bzero(&gate, sizeof(gate)); /* for safety */
  454 
  455         def.sin6_len = mask.sin6_len = gate.sin6_len =
  456             sizeof(struct sockaddr_in6);
  457         def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
  458         gate.sin6_addr = new->rtaddr;
  459 #ifndef SCOPEDROUTING
  460         gate.sin6_scope_id = 0; /* XXX */
  461 #endif
  462 
  463         s = splsoftnet();
  464         error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
  465             (struct sockaddr *)&gate, (struct sockaddr *)&mask,
  466             RTF_GATEWAY, &newrt);
  467         if (newrt) {
  468                 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
  469                 newrt->rt_refcnt--;
  470         }
  471         if (error == 0)
  472                 new->installed = 1;
  473         splx(s);
  474         return;
  475 }
  476 
  477 struct nd_defrouter *
  478 defrouter_lookup(addr, ifp)
  479         struct in6_addr *addr;
  480         struct ifnet *ifp;
  481 {
  482         struct nd_defrouter *dr;
  483 
  484         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
  485              dr = TAILQ_NEXT(dr, dr_entry)) {
  486                 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) {
  487                         return (dr);
  488                 }
  489         }
  490 
  491         return (NULL);          /* search failed */
  492 }
  493 
  494 void
  495 defrtrlist_del(dr)
  496         struct nd_defrouter *dr;
  497 {
  498         struct nd_defrouter *deldr = NULL;
  499         struct nd_prefix *pr;
  500 
  501         /*
  502          * Flush all the routing table entries that use the router
  503          * as a next hop.
  504          */
  505         if (!ip6_forwarding && ip6_accept_rtadv) /* XXX: better condition? */
  506                 rt6_flush(&dr->rtaddr, dr->ifp);
  507 
  508         if (dr->installed) {
  509                 deldr = dr;
  510                 defrouter_delreq(dr);
  511         }
  512         TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
  513 
  514         /*
  515          * Also delete all the pointers to the router in each prefix lists.
  516          */
  517         for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
  518                 struct nd_pfxrouter *pfxrtr;
  519                 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
  520                         pfxrtr_del(pfxrtr);
  521         }
  522         pfxlist_onlink_check();
  523 
  524         /*
  525          * If the router is the primary one, choose a new one.
  526          * Note that defrouter_select() will remove the current gateway
  527          * from the routing table.
  528          */
  529         if (deldr)
  530                 defrouter_select();
  531 
  532         free(dr, M_IP6NDP);
  533 }
  534 
  535 /*
  536  * Remove the default route for a given router.
  537  * This is just a subroutine function for defrouter_select(), and should
  538  * not be called from anywhere else.
  539  */
  540 static void
  541 defrouter_delreq(dr)
  542         struct nd_defrouter *dr;
  543 {
  544         struct sockaddr_in6 def, mask, gw;
  545         struct rtentry *oldrt = NULL;
  546 
  547 #ifdef DIAGNOSTIC
  548         if (!dr)
  549                 panic("dr == NULL in defrouter_delreq");
  550 #endif
  551 
  552         Bzero(&def, sizeof(def));
  553         Bzero(&mask, sizeof(mask));
  554         Bzero(&gw, sizeof(gw)); /* for safety */
  555 
  556         def.sin6_len = mask.sin6_len = gw.sin6_len =
  557             sizeof(struct sockaddr_in6);
  558         def.sin6_family = mask.sin6_family = gw.sin6_family = AF_INET6;
  559         gw.sin6_addr = dr->rtaddr;
  560 #ifndef SCOPEDROUTING
  561         gw.sin6_scope_id = 0;   /* XXX */
  562 #endif
  563 
  564         rtrequest(RTM_DELETE, (struct sockaddr *)&def,
  565             (struct sockaddr *)&gw,
  566             (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt);
  567         if (oldrt) {
  568                 nd6_rtmsg(RTM_DELETE, oldrt);
  569                 if (oldrt->rt_refcnt <= 0) {
  570                         /*
  571                          * XXX: borrowed from the RTM_DELETE case of
  572                          * rtrequest().
  573                          */
  574                         oldrt->rt_refcnt++;
  575                         rtfree(oldrt);
  576                 }
  577         }
  578 
  579         dr->installed = 0;
  580 }
  581 
  582 /*
  583  * remove all default routes from default router list
  584  */
  585 void
  586 defrouter_reset()
  587 {
  588         struct nd_defrouter *dr;
  589 
  590         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
  591              dr = TAILQ_NEXT(dr, dr_entry))
  592                 defrouter_delreq(dr);
  593 
  594         /*
  595          * XXX should we also nuke any default routers in the kernel, by
  596          * going through them by rtalloc1()?
  597          */
  598 }
  599 
  600 /*
  601  * Default Router Selection according to Section 6.3.6 of RFC 2461 and
  602  * draft-ietf-ipngwg-router-selection:
  603  * 1) Routers that are reachable or probably reachable should be preferred.
  604  *    If we have more than one (probably) reachable router, prefer ones
  605  *    with the highest router preference.
  606  * 2) When no routers on the list are known to be reachable or
  607  *    probably reachable, routers SHOULD be selected in a round-robin
  608  *    fashion, regardless of router preference values.
  609  * 3) If the Default Router List is empty, assume that all
  610  *    destinations are on-link.
  611  *
  612  * We assume nd_defrouter is sorted by router preference value.
  613  * Since the code below covers both with and without router preference cases,
  614  * we do not need to classify the cases by ifdef.
  615  *
  616  * At this moment, we do not try to install more than one default router,
  617  * even when the multipath routing is available, because we're not sure about
  618  * the benefits for stub hosts comparing to the risk of making the code
  619  * complicated and the possibility of introducing bugs.
  620  */
  621 void
  622 defrouter_select()
  623 {
  624         int s = splsoftnet();
  625         struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
  626         struct rtentry *rt = NULL;
  627         struct llinfo_nd6 *ln = NULL;
  628 
  629         /*
  630          * This function should be called only when acting as an autoconfigured
  631          * host.  Although the remaining part of this function is not effective
  632          * if the node is not an autoconfigured host, we explicitly exclude
  633          * such cases here for safety.
  634          */
  635         if (ip6_forwarding || !ip6_accept_rtadv) {
  636                 nd6log((LOG_WARNING,
  637                     "defrouter_select: called unexpectedly (forwarding=%d, "
  638                     "accept_rtadv=%d)\n", ip6_forwarding, ip6_accept_rtadv));
  639                 splx(s);
  640                 return;
  641         }
  642 
  643         /*
  644          * Let's handle easy case (3) first:
  645          * If default router list is empty, there's nothing to be done.
  646          */
  647         if (!TAILQ_FIRST(&nd_defrouter)) {
  648                 splx(s);
  649                 return;
  650         }
  651 
  652         /*
  653          * Search for a (probably) reachable router from the list.
  654          * We just pick up the first reachable one (if any), assuming that
  655          * the ordering rule of the list described in defrtrlist_update().
  656          */
  657         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
  658              dr = TAILQ_NEXT(dr, dr_entry)) {
  659                 if (!selected_dr &&
  660                     (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
  661                     (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
  662                     ND6_IS_LLINFO_PROBREACH(ln)) {
  663                         selected_dr = dr;
  664                 }
  665 
  666                 if (dr->installed && !installed_dr)
  667                         installed_dr = dr;
  668                 else if (dr->installed && installed_dr) {
  669                         /* this should not happen.  warn for diagnosis. */
  670                         log(LOG_ERR, "defrouter_select: more than one router"
  671                             " is installed\n");
  672                 }
  673         }
  674         /*
  675          * If none of the default routers was found to be reachable,
  676          * round-robin the list regardless of preference.
  677          * Otherwise, if we have an installed router, check if the selected
  678          * (reachable) router should really be preferred to the installed one.
  679          * We only prefer the new router when the old one is not reachable
  680          * or when the new one has a really higher preference value.
  681          */
  682         if (!selected_dr) {
  683                 if (!installed_dr || !TAILQ_NEXT(installed_dr, dr_entry))
  684                         selected_dr = TAILQ_FIRST(&nd_defrouter);
  685                 else
  686                         selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
  687         } else if (installed_dr &&
  688             (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
  689             (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
  690             ND6_IS_LLINFO_PROBREACH(ln) &&
  691             rtpref(selected_dr) <= rtpref(installed_dr)) {
  692                 selected_dr = installed_dr;
  693         }
  694 
  695         /*
  696          * If the selected router is different than the installed one,
  697          * remove the installed router and install the selected one.
  698          * Note that the selected router is never NULL here.
  699          */
  700         if (installed_dr != selected_dr) {
  701                 if (installed_dr)
  702                         defrouter_delreq(installed_dr);
  703                 defrouter_addreq(selected_dr);
  704         }
  705 
  706         splx(s);
  707         return;
  708 }
  709 
  710 /*
  711  * for default router selection
  712  * regards router-preference field as a 2-bit signed integer
  713  */
  714 static int
  715 rtpref(struct nd_defrouter *dr)
  716 {
  717 #ifdef RTPREF
  718         switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
  719         case ND_RA_FLAG_RTPREF_HIGH:
  720                 return RTPREF_HIGH;
  721         case ND_RA_FLAG_RTPREF_MEDIUM:
  722         case ND_RA_FLAG_RTPREF_RSV:
  723                 return RTPREF_MEDIUM;
  724         case ND_RA_FLAG_RTPREF_LOW:
  725                 return RTPREF_LOW;
  726         default:
  727                 /*
  728                  * This case should never happen.  If it did, it would mean a
  729                  * serious bug of kernel internal.  We thus always bark here.
  730                  * Or, can we even panic?
  731                  */
  732                 log(LOG_ERR, "rtpref: impossible RA flag %x", dr->flags);
  733                 return RTPREF_INVALID;
  734         }
  735         /* NOTREACHED */
  736 #else
  737         return 0;
  738 #endif
  739 }
  740 
  741 static struct nd_defrouter *
  742 defrtrlist_update(new)
  743         struct nd_defrouter *new;
  744 {
  745         struct nd_defrouter *dr, *n;
  746         int s = splsoftnet();
  747 
  748         if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
  749                 /* entry exists */
  750                 if (new->rtlifetime == 0) {
  751                         defrtrlist_del(dr);
  752                         dr = NULL;
  753                 } else {
  754                         int oldpref = rtpref(dr);
  755 
  756                         /* override */
  757                         dr->flags = new->flags; /* xxx flag check */
  758                         dr->rtlifetime = new->rtlifetime;
  759                         dr->expire = new->expire;
  760 
  761                         /*
  762                          * If the preference does not change, there's no need
  763                          * to sort the entries.
  764                          */
  765                         if (rtpref(new) == oldpref) {
  766                                 splx(s);
  767                                 return (dr);
  768                         }
  769 
  770                         /*
  771                          * preferred router may be changed, so relocate
  772                          * this router.
  773                          * XXX: calling TAILQ_REMOVE directly is a bad manner.
  774                          * However, since defrtrlist_del() has many side
  775                          * effects, we intentionally do so here.
  776                          * defrouter_select() below will handle routing
  777                          * changes later.
  778                          */
  779                         TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
  780                         n = dr;
  781                         goto insert;
  782                 }
  783                 splx(s);
  784                 return (dr);
  785         }
  786 
  787         /* entry does not exist */
  788         if (new->rtlifetime == 0) {
  789                 splx(s);
  790                 return (NULL);
  791         }
  792 
  793         n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
  794         if (n == NULL) {
  795                 splx(s);
  796                 return (NULL);
  797         }
  798         bzero(n, sizeof(*n));
  799         *n = *new;
  800 
  801 insert:
  802         /*
  803          * Insert the new router in the Default Router List;
  804          * The Default Router List should be in the descending order
  805          * of router-preferece.  Routers with the same preference are
  806          * sorted in the arriving time order.
  807          */
  808 
  809         /* insert at the end of the group */
  810         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
  811              dr = TAILQ_NEXT(dr, dr_entry)) {
  812                 if (rtpref(n) > rtpref(dr))
  813                         break;
  814         }
  815         if (dr)
  816                 TAILQ_INSERT_BEFORE(dr, n, dr_entry);
  817         else
  818                 TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
  819 
  820         defrouter_select();
  821 
  822         splx(s);
  823 
  824         return (n);
  825 }
  826 
  827 static struct nd_pfxrouter *
  828 pfxrtr_lookup(pr, dr)
  829         struct nd_prefix *pr;
  830         struct nd_defrouter *dr;
  831 {
  832         struct nd_pfxrouter *search;
  833 
  834         for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
  835                 if (search->router == dr)
  836                         break;
  837         }
  838 
  839         return (search);
  840 }
  841 
  842 static void
  843 pfxrtr_add(pr, dr)
  844         struct nd_prefix *pr;
  845         struct nd_defrouter *dr;
  846 {
  847         struct nd_pfxrouter *new;
  848 
  849         new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
  850         if (new == NULL)
  851                 return;
  852         bzero(new, sizeof(*new));
  853         new->router = dr;
  854 
  855         LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
  856 
  857         pfxlist_onlink_check();
  858 }
  859 
  860 static void
  861 pfxrtr_del(pfr)
  862         struct nd_pfxrouter *pfr;
  863 {
  864         LIST_REMOVE(pfr, pfr_entry);
  865         free(pfr, M_IP6NDP);
  866 }
  867 
  868 struct nd_prefix *
  869 nd6_prefix_lookup(pr)
  870         struct nd_prefix *pr;
  871 {
  872         struct nd_prefix *search;
  873 
  874         for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
  875                 if (pr->ndpr_ifp == search->ndpr_ifp &&
  876                     pr->ndpr_plen == search->ndpr_plen &&
  877                     in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
  878                     &search->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
  879                         break;
  880                 }
  881         }
  882 
  883         return (search);
  884 }
  885 
  886 int
  887 nd6_prelist_add(pr, dr, newp)
  888         struct nd_prefix *pr, **newp;
  889         struct nd_defrouter *dr;
  890 {
  891         struct nd_prefix *new = NULL;
  892         int i, s;
  893 
  894         new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
  895         if (new == NULL)
  896                 return ENOMEM;
  897         bzero(new, sizeof(*new));
  898         *new = *pr;
  899         if (newp != NULL)
  900                 *newp = new;
  901 
  902         /* initilization */
  903         LIST_INIT(&new->ndpr_advrtrs);
  904         in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
  905         /* make prefix in the canonical form */
  906         for (i = 0; i < 4; i++)
  907                 new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
  908                     new->ndpr_mask.s6_addr32[i];
  909 
  910         s = splsoftnet();
  911         /* link ndpr_entry to nd_prefix list */
  912         LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
  913         splx(s);
  914 
  915         /* ND_OPT_PI_FLAG_ONLINK processing */
  916         if (new->ndpr_raf_onlink) {
  917                 int e;
  918 
  919                 if ((e = nd6_prefix_onlink(new)) != 0) {
  920                         nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
  921                             "the prefix %s/%d on-link on %s (errno=%d)\n",
  922                             ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
  923                             pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
  924                         /* proceed anyway. XXX: is it correct? */
  925                 }
  926         }
  927 
  928         if (dr)
  929                 pfxrtr_add(new, dr);
  930 
  931         return 0;
  932 }
  933 
  934 void
  935 prelist_remove(pr)
  936         struct nd_prefix *pr;
  937 {
  938         struct nd_pfxrouter *pfr, *next;
  939         int e, s;
  940 
  941         /* make sure to invalidate the prefix until it is really freed. */
  942         pr->ndpr_vltime = 0;
  943         pr->ndpr_pltime = 0;
  944 #if 0
  945         /*
  946          * Though these flags are now meaningless, we'd rather keep the value
  947          * not to confuse users when executing "ndp -p".
  948          */
  949         pr->ndpr_raf_onlink = 0;
  950         pr->ndpr_raf_auto = 0;
  951 #endif
  952         if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
  953             (e = nd6_prefix_offlink(pr)) != 0) {
  954                 nd6log((LOG_ERR, "prelist_remove: failed to make %s/%d offlink "
  955                     "on %s, errno=%d\n",
  956                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
  957                     pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
  958                 /* what should we do? */
  959         }
  960 
  961         if (pr->ndpr_refcnt > 0)
  962                 return;         /* notice here? */
  963 
  964         s = splsoftnet();
  965         /* unlink ndpr_entry from nd_prefix list */
  966         LIST_REMOVE(pr, ndpr_entry);
  967 
  968         /* free list of routers that adversed the prefix */
  969         for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
  970                 next = pfr->pfr_next;
  971 
  972                 free(pfr, M_IP6NDP);
  973         }
  974         splx(s);
  975 
  976         free(pr, M_IP6NDP);
  977 
  978         pfxlist_onlink_check();
  979 }
  980 
  981 int
  982 prelist_update(new, dr, m)
  983         struct nd_prefix *new;
  984         struct nd_defrouter *dr; /* may be NULL */
  985         struct mbuf *m;
  986 {
  987         struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL;
  988         struct ifaddr *ifa;
  989         struct ifnet *ifp = new->ndpr_ifp;
  990         struct nd_prefix *pr;
  991         int s = splsoftnet();
  992         int error = 0;
  993         int auth;
  994         struct in6_addrlifetime lt6_tmp;
  995 
  996         auth = 0;
  997         if (m) {
  998                 /*
  999                  * Authenticity for NA consists authentication for
 1000                  * both IP header and IP datagrams, doesn't it ?
 1001                  */
 1002 #if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
 1003                 auth = (m->m_flags & M_AUTHIPHDR
 1004                      && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
 1005 #endif
 1006         }
 1007 
 1008         if ((pr = nd6_prefix_lookup(new)) != NULL) {
 1009                 /*
 1010                  * nd6_prefix_lookup() ensures that pr and new have the same
 1011                  * prefix on a same interface.
 1012                  */
 1013 
 1014                 /*
 1015                  * Update prefix information.  Note that the on-link (L) bit
 1016                  * and the autonomous (A) bit should NOT be changed from 1
 1017                  * to 0.
 1018                  */
 1019                 if (new->ndpr_raf_onlink == 1)
 1020                         pr->ndpr_raf_onlink = 1;
 1021                 if (new->ndpr_raf_auto == 1)
 1022                         pr->ndpr_raf_auto = 1;
 1023                 if (new->ndpr_raf_onlink) {
 1024                         pr->ndpr_vltime = new->ndpr_vltime;
 1025                         pr->ndpr_pltime = new->ndpr_pltime;
 1026                         pr->ndpr_preferred = new->ndpr_preferred;
 1027                         pr->ndpr_expire = new->ndpr_expire;
 1028                         pr->ndpr_lastupdate = new->ndpr_lastupdate;
 1029                 }
 1030 
 1031                 if (new->ndpr_raf_onlink &&
 1032                     (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
 1033                         int e;
 1034 
 1035                         if ((e = nd6_prefix_onlink(pr)) != 0) {
 1036                                 nd6log((LOG_ERR,
 1037                                     "prelist_update: failed to make "
 1038                                     "the prefix %s/%d on-link on %s "
 1039                                     "(errno=%d)\n",
 1040                                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
 1041                                     pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
 1042                                 /* proceed anyway. XXX: is it correct? */
 1043                         }
 1044                 }
 1045 
 1046                 if (dr && pfxrtr_lookup(pr, dr) == NULL)
 1047                         pfxrtr_add(pr, dr);
 1048         } else {
 1049                 struct nd_prefix *newpr = NULL;
 1050 
 1051                 if (new->ndpr_vltime == 0)
 1052                         goto end;
 1053                 if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
 1054                         goto end;
 1055 
 1056                 error = nd6_prelist_add(new, dr, &newpr);
 1057                 if (error != 0 || newpr == NULL) {
 1058                         nd6log((LOG_NOTICE, "prelist_update: "
 1059                             "nd6_prelist_add failed for %s/%d on %s "
 1060                             "errno=%d, returnpr=%p\n",
 1061                             ip6_sprintf(&new->ndpr_prefix.sin6_addr),
 1062                             new->ndpr_plen, if_name(new->ndpr_ifp),
 1063                             error, newpr));
 1064                         goto end; /* we should just give up in this case. */
 1065                 }
 1066 
 1067                 /*
 1068                  * XXX: from the ND point of view, we can ignore a prefix
 1069                  * with the on-link bit being zero.  However, we need a
 1070                  * prefix structure for references from autoconfigured
 1071                  * addresses.  Thus, we explicitly make sure that the prefix
 1072                  * itself expires now.
 1073                  */
 1074                 if (newpr->ndpr_raf_onlink == 0) {
 1075                         newpr->ndpr_vltime = 0;
 1076                         newpr->ndpr_pltime = 0;
 1077                         in6_init_prefix_ltimes(newpr);
 1078                 }
 1079 
 1080                 pr = newpr;
 1081         }
 1082 
 1083         /*
 1084          * Address autoconfiguration based on Section 5.5.3 of RFC 2462.
 1085          * Note that pr must be non NULL at this point.
 1086          */
 1087 
 1088         /* 5.5.3 (a). Ignore the prefix without the A bit set. */
 1089         if (!new->ndpr_raf_auto)
 1090                 goto end;
 1091 
 1092         /*
 1093          * 5.5.3 (b). the link-local prefix should have been ignored in
 1094          * nd6_ra_input.
 1095          */
 1096 
 1097         /*
 1098          * 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime.
 1099          * This should have been done in nd6_ra_input.
 1100          */
 1101 
 1102         /*
 1103          * 5.5.3 (d). If the prefix advertised does not match the prefix of an
 1104          * address already in the list, and the Valid Lifetime is not 0,
 1105          * form an address.  Note that even a manually configured address
 1106          * should reject autoconfiguration of a new address.
 1107          */
 1108         for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
 1109         {
 1110                 struct in6_ifaddr *ifa6;
 1111                 int ifa_plen;
 1112                 u_int32_t storedlifetime;
 1113 
 1114                 if (ifa->ifa_addr->sa_family != AF_INET6)
 1115                         continue;
 1116 
 1117                 ifa6 = (struct in6_ifaddr *)ifa;
 1118 
 1119                 /*
 1120                  * Spec is not clear here, but I believe we should concentrate
 1121                  * on unicast (i.e. not anycast) addresses.
 1122                  * XXX: other ia6_flags? detached or duplicated?
 1123                  */
 1124                 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0)
 1125                         continue;
 1126 
 1127                 ifa_plen = in6_mask2len(&ifa6->ia_prefixmask.sin6_addr, NULL);
 1128                 if (ifa_plen != new->ndpr_plen ||
 1129                     !in6_are_prefix_equal(&ifa6->ia_addr.sin6_addr,
 1130                     &new->ndpr_prefix.sin6_addr, ifa_plen))
 1131                         continue;
 1132 
 1133                 if (ia6_match == NULL) /* remember the first one */
 1134                         ia6_match = ifa6;
 1135 
 1136                 if ((ifa6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
 1137                         continue;
 1138 
 1139                 /*
 1140                  * An already autoconfigured address matched.  Now that we
 1141                  * are sure there is at least one matched address, we can
 1142                  * proceed to 5.5.3. (e): update the lifetimes according to the
 1143                  * "two hours" rule and the privacy extension.
 1144                  */
 1145 #define TWOHOUR         (120*60)
 1146                 /*
 1147                  * RFC2462 introduces the notion of StoredLifetime to the
 1148                  * "two hours" rule as follows:
 1149                  *   the Lifetime associated with the previously autoconfigured
 1150                  *   address.
 1151                  * Our interpretation of this definition is "the remaining
 1152                  * lifetime to expiration at the evaluation time".  One might
 1153                  * be wondering if this interpretation is really conform to the
 1154                  * RFC, because the text can read that "Lifetimes" are never
 1155                  * decreased, and our definition of the "storedlifetime" below
 1156                  * essentially reduces the "Valid Lifetime" advertised in the
 1157                  * previous RA.  But, this is due to the wording of the text,
 1158                  * and our interpretation is the same as an author's intention.
 1159                  * See the discussion in the IETF ipngwg ML in August 2001,
 1160                  * with the Subject "StoredLifetime in RFC 2462".
 1161                  */
 1162                 lt6_tmp = ifa6->ia6_lifetime;
 1163                 if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
 1164                         storedlifetime = ND6_INFINITE_LIFETIME;
 1165                 else if (time.tv_sec - ifa6->ia6_updatetime >
 1166                          lt6_tmp.ia6t_vltime) {
 1167                         /*
 1168                          * The case of "invalid" address.  We should usually
 1169                          * not see this case.
 1170                          */
 1171                         storedlifetime = 0;
 1172                 } else
 1173                         storedlifetime = lt6_tmp.ia6t_vltime -
 1174                                 (time.tv_sec - ifa6->ia6_updatetime);
 1175                 if (TWOHOUR < new->ndpr_vltime ||
 1176                     storedlifetime < new->ndpr_vltime) {
 1177                         lt6_tmp.ia6t_vltime = new->ndpr_vltime;
 1178                 } else if (storedlifetime <= TWOHOUR
 1179 #if 0
 1180                            /*
 1181                             * This condition is logically redundant, so we just
 1182                             * omit it.
 1183                             * See IPng 6712, 6717, and 6721.
 1184                             */
 1185                            && new->ndpr_vltime <= storedlifetime
 1186 #endif
 1187                         ) {
 1188                         if (auth) {
 1189                                 lt6_tmp.ia6t_vltime = new->ndpr_vltime;
 1190                         }
 1191                 } else {
 1192                         /*
 1193                          * new->ndpr_vltime <= TWOHOUR &&
 1194                          * TWOHOUR < storedlifetime
 1195                          */
 1196                         lt6_tmp.ia6t_vltime = TWOHOUR;
 1197                 }
 1198 
 1199                 /* The 2 hour rule is not imposed for preferred lifetime. */
 1200                 lt6_tmp.ia6t_pltime = new->ndpr_pltime;
 1201 
 1202                 in6_init_address_ltimes(pr, &lt6_tmp);
 1203 
 1204                 ifa6->ia6_lifetime = lt6_tmp;
 1205                 ifa6->ia6_updatetime = time.tv_sec;
 1206         }
 1207         if (ia6_match == NULL && new->ndpr_vltime) {
 1208                 /*
 1209                  * No address matched and the valid lifetime is non-zero.
 1210                  * Create a new address.
 1211                  */
 1212                 if ((ia6 = in6_ifadd(new)) != NULL) {
 1213                         /*
 1214                          * note that we should use pr (not new) for reference.
 1215                          */
 1216                         pr->ndpr_refcnt++;
 1217                         ia6->ia6_ndpr = pr;
 1218 
 1219                         /*
 1220                          * A newly added address might affect the status
 1221                          * of other addresses, so we check and update it.
 1222                          * XXX: what if address duplication happens?
 1223                          */
 1224                         pfxlist_onlink_check();
 1225                 } else {
 1226                         /* just set an error. do not bark here. */
 1227                         error = EADDRNOTAVAIL; /* XXX: might be unused. */
 1228                 }
 1229         }
 1230 
 1231  end:
 1232         splx(s);
 1233         return error;
 1234 }
 1235 
 1236 /*
 1237  * A supplement function used in the on-link detection below;
 1238  * detect if a given prefix has a (probably) reachable advertising router.
 1239  * XXX: lengthy function name...
 1240  */
 1241 static struct nd_pfxrouter *
 1242 find_pfxlist_reachable_router(pr)
 1243         struct nd_prefix *pr;
 1244 {
 1245         struct nd_pfxrouter *pfxrtr;
 1246         struct rtentry *rt;
 1247         struct llinfo_nd6 *ln;
 1248 
 1249         for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
 1250              pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
 1251                 if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
 1252                     pfxrtr->router->ifp)) &&
 1253                     (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
 1254                     ND6_IS_LLINFO_PROBREACH(ln))
 1255                         break;  /* found */
 1256         }
 1257 
 1258         return (pfxrtr);
 1259 }
 1260 
 1261 /*
 1262  * Check if each prefix in the prefix list has at least one available router
 1263  * that advertised the prefix (a router is "available" if its neighbor cache
 1264  * entry is reachable or probably reachable).
 1265  * If the check fails, the prefix may be off-link, because, for example,
 1266  * we have moved from the network but the lifetime of the prefix has not
 1267  * expired yet.  So we should not use the prefix if there is another prefix
 1268  * that has an available router.
 1269  * But, if there is no prefix that has an available router, we still regards
 1270  * all the prefixes as on-link.  This is because we can't tell if all the
 1271  * routers are simply dead or if we really moved from the network and there
 1272  * is no router around us.
 1273  */
 1274 void
 1275 pfxlist_onlink_check()
 1276 {
 1277         struct nd_prefix *pr;
 1278         struct in6_ifaddr *ifa;
 1279 
 1280         /*
 1281          * Check if there is a prefix that has a reachable advertising
 1282          * router.
 1283          */
 1284         for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
 1285                 if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
 1286                         break;
 1287         }
 1288         if (pr != NULL || TAILQ_FIRST(&nd_defrouter) != NULL) {
 1289                 /*
 1290                  * There is at least one prefix that has a reachable router,
 1291                  * or at least a router which probably does not advertise
 1292                  * any prefixes.  The latter would be the case when we move
 1293                  * to a new link where we have a router that does not provide
 1294                  * prefixes and we configure an address by hand.
 1295                  * Detach prefixes which have no reachable advertising
 1296                  * router, and attach other prefixes.
 1297                  */
 1298                 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
 1299                         /* XXX: a link-local prefix should never be detached */
 1300                         if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
 1301                                 continue;
 1302 
 1303                         /*
 1304                          * we aren't interested in prefixes without the L bit
 1305                          * set.
 1306                          */
 1307                         if (pr->ndpr_raf_onlink == 0)
 1308                                 continue;
 1309 
 1310                         if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
 1311                             find_pfxlist_reachable_router(pr) == NULL)
 1312                                 pr->ndpr_stateflags |= NDPRF_DETACHED;
 1313                         if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
 1314                             find_pfxlist_reachable_router(pr) != 0)
 1315                                 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
 1316                 }
 1317         } else {
 1318                 /* there is no prefix that has a reachable router */
 1319                 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
 1320                         if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
 1321                                 continue;
 1322 
 1323                         if (pr->ndpr_raf_onlink == 0)
 1324                                 continue;
 1325 
 1326                         if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
 1327                                 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
 1328                 }
 1329         }
 1330 
 1331         /*
 1332          * Remove each interface route associated with a (just) detached
 1333          * prefix, and reinstall the interface route for a (just) attached
 1334          * prefix.  Note that all attempt of reinstallation does not
 1335          * necessarily success, when a same prefix is shared among multiple
 1336          * interfaces.  Such cases will be handled in nd6_prefix_onlink,
 1337          * so we don't have to care about them.
 1338          */
 1339         for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
 1340                 int e;
 1341 
 1342                 if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
 1343                         continue;
 1344 
 1345                 if (pr->ndpr_raf_onlink == 0)
 1346                         continue;
 1347 
 1348                 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
 1349                     (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
 1350                         if ((e = nd6_prefix_offlink(pr)) != 0) {
 1351                                 nd6log((LOG_ERR,
 1352                                     "pfxlist_onlink_check: failed to "
 1353                                     "make %s/%d offlink, errno=%d\n",
 1354                                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
 1355                                     pr->ndpr_plen, e));
 1356                         }
 1357                 }
 1358                 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
 1359                     (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
 1360                     pr->ndpr_raf_onlink) {
 1361                         if ((e = nd6_prefix_onlink(pr)) != 0) {
 1362                                 nd6log((LOG_ERR,
 1363                                     "pfxlist_onlink_check: failed to "
 1364                                     "make %s/%d offlink, errno=%d\n",
 1365                                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
 1366                                     pr->ndpr_plen, e));
 1367                         }
 1368                 }
 1369         }
 1370 
 1371         /*
 1372          * Changes on the prefix status might affect address status as well.
 1373          * Make sure that all addresses derived from an attached prefix are
 1374          * attached, and that all addresses derived from a detached prefix are
 1375          * detached.  Note, however, that a manually configured address should
 1376          * always be attached.
 1377          * The precise detection logic is same as the one for prefixes.
 1378          */
 1379         for (ifa = in6_ifaddr; ifa; ifa = ifa->ia_next) {
 1380                 if (!(ifa->ia6_flags & IN6_IFF_AUTOCONF))
 1381                         continue;
 1382 
 1383                 if (ifa->ia6_ndpr == NULL) {
 1384                         /*
 1385                          * This can happen when we first configure the address
 1386                          * (i.e. the address exists, but the prefix does not).
 1387                          * XXX: complicated relationships...
 1388                          */
 1389                         continue;
 1390                 }
 1391 
 1392                 if (find_pfxlist_reachable_router(ifa->ia6_ndpr))
 1393                         break;
 1394         }
 1395         if (ifa) {
 1396                 for (ifa = in6_ifaddr; ifa; ifa = ifa->ia_next) {
 1397                         if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0)
 1398                                 continue;
 1399 
 1400                         if (ifa->ia6_ndpr == NULL) /* XXX: see above. */
 1401                                 continue;
 1402 
 1403                         if (find_pfxlist_reachable_router(ifa->ia6_ndpr))
 1404                                 ifa->ia6_flags &= ~IN6_IFF_DETACHED;
 1405                         else
 1406                                 ifa->ia6_flags |= IN6_IFF_DETACHED;
 1407                 }
 1408         }
 1409         else {
 1410                 for (ifa = in6_ifaddr; ifa; ifa = ifa->ia_next) {
 1411                         if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0)
 1412                                 continue;
 1413 
 1414                         ifa->ia6_flags &= ~IN6_IFF_DETACHED;
 1415                 }
 1416         }
 1417 }
 1418 
 1419 int
 1420 nd6_prefix_onlink(pr)
 1421         struct nd_prefix *pr;
 1422 {
 1423         struct ifaddr *ifa;
 1424         struct ifnet *ifp = pr->ndpr_ifp;
 1425         struct sockaddr_in6 mask6;
 1426         struct nd_prefix *opr;
 1427         u_long rtflags;
 1428         int error = 0;
 1429         struct rtentry *rt = NULL;
 1430 
 1431         /* sanity check */
 1432         if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
 1433                 nd6log((LOG_ERR,
 1434                     "nd6_prefix_onlink: %s/%d is already on-link\n",
 1435                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen));
 1436                 return (EEXIST);
 1437         }
 1438 
 1439         /*
 1440          * Add the interface route associated with the prefix.  Before
 1441          * installing the route, check if there's the same prefix on another
 1442          * interface, and the prefix has already installed the interface route.
 1443          * Although such a configuration is expected to be rare, we explicitly
 1444          * allow it.
 1445          */
 1446         for (opr = nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
 1447                 if (opr == pr)
 1448                         continue;
 1449 
 1450                 if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0)
 1451                         continue;
 1452 
 1453                 if (opr->ndpr_plen == pr->ndpr_plen &&
 1454                     in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
 1455                     &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen))
 1456                         return (0);
 1457         }
 1458 
 1459         /*
 1460          * We prefer link-local addresses as the associated interface address.
 1461          */
 1462         /* search for a link-local addr */
 1463         ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
 1464             IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
 1465         if (ifa == NULL) {
 1466                 /* XXX: freebsd does not have ifa_ifwithaf */
 1467                 for (ifa = ifp->if_addrlist.tqh_first;
 1468                      ifa;
 1469                      ifa = ifa->ifa_list.tqe_next)
 1470                 {
 1471                         if (ifa->ifa_addr->sa_family == AF_INET6)
 1472                                 break;
 1473                 }
 1474                 /* should we care about ia6_flags? */
 1475         }
 1476         if (ifa == NULL) {
 1477                 /*
 1478                  * This can still happen, when, for example, we receive an RA
 1479                  * containing a prefix with the L bit set and the A bit clear,
 1480                  * after removing all IPv6 addresses on the receiving
 1481                  * interface.  This should, of course, be rare though.
 1482                  */
 1483                 nd6log((LOG_NOTICE,
 1484                     "nd6_prefix_onlink: failed to find any ifaddr"
 1485                     " to add route for a prefix(%s/%d) on %s\n",
 1486                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
 1487                     pr->ndpr_plen, if_name(ifp)));
 1488                 return (0);
 1489         }
 1490 
 1491         /*
 1492          * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
 1493          * ifa->ifa_rtrequest = nd6_rtrequest;
 1494          */
 1495         bzero(&mask6, sizeof(mask6));
 1496         mask6.sin6_len = sizeof(mask6);
 1497         mask6.sin6_addr = pr->ndpr_mask;
 1498         /* rtrequest() will probably set RTF_UP, but we're not sure. */
 1499         rtflags = ifa->ifa_flags | RTF_UP;
 1500         if (nd6_need_cache(ifp)) {
 1501                 /* explicitly set in case ifa_flags does not set the flag. */
 1502                 rtflags |= RTF_CLONING;
 1503         } else {
 1504                 /*
 1505                  * explicitly clear the cloning bit in case ifa_flags sets it.
 1506                  */
 1507                 rtflags &= ~RTF_CLONING;
 1508         }
 1509         error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
 1510             ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
 1511         if (error == 0) {
 1512                 if (rt != NULL) /* this should be non NULL, though */
 1513                         nd6_rtmsg(RTM_ADD, rt);
 1514                 pr->ndpr_stateflags |= NDPRF_ONLINK;
 1515         } else {
 1516                 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
 1517                     " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
 1518                     "errno = %d\n",
 1519                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
 1520                     pr->ndpr_plen, if_name(ifp),
 1521                     ip6_sprintf(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
 1522                     ip6_sprintf(&mask6.sin6_addr), rtflags, error));
 1523         }
 1524 
 1525         if (rt != NULL)
 1526                 rt->rt_refcnt--;
 1527 
 1528         return (error);
 1529 }
 1530 
 1531 int
 1532 nd6_prefix_offlink(pr)
 1533         struct nd_prefix *pr;
 1534 {
 1535         int error = 0;
 1536         struct ifnet *ifp = pr->ndpr_ifp;
 1537         struct nd_prefix *opr;
 1538         struct sockaddr_in6 sa6, mask6;
 1539         struct rtentry *rt = NULL;
 1540 
 1541         /* sanity check */
 1542         if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
 1543                 nd6log((LOG_ERR,
 1544                     "nd6_prefix_offlink: %s/%d is already off-link\n",
 1545                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen));
 1546                 return (EEXIST);
 1547         }
 1548 
 1549         bzero(&sa6, sizeof(sa6));
 1550         sa6.sin6_family = AF_INET6;
 1551         sa6.sin6_len = sizeof(sa6);
 1552         bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
 1553             sizeof(struct in6_addr));
 1554         bzero(&mask6, sizeof(mask6));
 1555         mask6.sin6_family = AF_INET6;
 1556         mask6.sin6_len = sizeof(sa6);
 1557         bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
 1558         error = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
 1559             (struct sockaddr *)&mask6, 0, &rt);
 1560         if (error == 0) {
 1561                 pr->ndpr_stateflags &= ~NDPRF_ONLINK;
 1562 
 1563                 /* report the route deletion to the routing socket. */
 1564                 if (rt != NULL)
 1565                         nd6_rtmsg(RTM_DELETE, rt);
 1566 
 1567                 /*
 1568                  * There might be the same prefix on another interface,
 1569                  * the prefix which could not be on-link just because we have
 1570                  * the interface route (see comments in nd6_prefix_onlink).
 1571                  * If there's one, try to make the prefix on-link on the
 1572                  * interface.
 1573                  */
 1574                 for (opr = nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
 1575                         if (opr == pr)
 1576                                 continue;
 1577 
 1578                         if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0)
 1579                                 continue;
 1580 
 1581                         /*
 1582                          * KAME specific: detached prefixes should not be
 1583                          * on-link.
 1584                          */
 1585                         if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0)
 1586                                 continue;
 1587 
 1588                         if (opr->ndpr_plen == pr->ndpr_plen &&
 1589                             in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
 1590                             &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
 1591                                 int e;
 1592 
 1593                                 if ((e = nd6_prefix_onlink(opr)) != 0) {
 1594                                         nd6log((LOG_ERR,
 1595                                             "nd6_prefix_offlink: failed to "
 1596                                             "recover a prefix %s/%d from %s "
 1597                                             "to %s (errno = %d)\n",
 1598                                             ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
 1599                                             opr->ndpr_plen, if_name(ifp),
 1600                                             if_name(opr->ndpr_ifp), e));
 1601                                 }
 1602                         }
 1603                 }
 1604         } else {
 1605                 /* XXX: can we still set the NDPRF_ONLINK flag? */
 1606                 nd6log((LOG_ERR,
 1607                     "nd6_prefix_offlink: failed to delete route: "
 1608                     "%s/%d on %s (errno = %d)\n",
 1609                     ip6_sprintf(&sa6.sin6_addr), pr->ndpr_plen, if_name(ifp),
 1610                     error));
 1611         }
 1612 
 1613         if (rt != NULL) {
 1614                 if (rt->rt_refcnt <= 0) {
 1615                         /* XXX: we should free the entry ourselves. */
 1616                         rt->rt_refcnt++;
 1617                         rtfree(rt);
 1618                 }
 1619         }
 1620 
 1621         return (error);
 1622 }
 1623 
 1624 static struct in6_ifaddr *
 1625 in6_ifadd(pr)
 1626         struct nd_prefix *pr;
 1627 {
 1628         struct ifnet *ifp = pr->ndpr_ifp;
 1629         struct ifaddr *ifa;
 1630         struct in6_aliasreq ifra;
 1631         struct in6_ifaddr *ia, *ib;
 1632         int error, plen0;
 1633         struct in6_addr mask;
 1634         int prefixlen = pr->ndpr_plen;
 1635 
 1636         in6_prefixlen2mask(&mask, prefixlen);
 1637 
 1638         /*
 1639          * find a link-local address (will be interface ID).
 1640          * Is it really mandatory? Theoretically, a global or a site-local
 1641          * address can be configured without a link-local address, if we
 1642          * have a unique interface identifier...
 1643          *
 1644          * it is not mandatory to have a link-local address, we can generate
 1645          * interface identifier on the fly.  we do this because:
 1646          * (1) it should be the easiest way to find interface identifier.
 1647          * (2) RFC2462 5.4 suggesting the use of the same interface identifier
 1648          * for multiple addresses on a single interface, and possible shortcut
 1649          * of DAD.  we omitted DAD for this reason in the past.
 1650          * (3) a user can prevent autoconfiguration of global address
 1651          * by removing link-local address by hand (this is partly because we
 1652          * don't have other way to control the use of IPv6 on a interface.
 1653          * this has been our design choice - cf. NRL's "ifconfig auto").
 1654          * (4) it is easier to manage when an interface has addresses
 1655          * with the same interface identifier, than to have multiple addresses
 1656          * with different interface identifiers.
 1657          */
 1658         ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */
 1659         if (ifa)
 1660                 ib = (struct in6_ifaddr *)ifa;
 1661         else
 1662                 return NULL;
 1663 
 1664 #if 0 /* don't care link local addr state, and always do DAD */
 1665         /* if link-local address is not eligible, do not autoconfigure. */
 1666         if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
 1667                 printf("in6_ifadd: link-local address not ready\n");
 1668                 return NULL;
 1669         }
 1670 #endif
 1671 
 1672         /* prefixlen + ifidlen must be equal to 128 */
 1673         plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL);
 1674         if (prefixlen != plen0) {
 1675                 nd6log((LOG_ERR, "in6_ifadd: wrong prefixlen for %s"
 1676                     "(prefix=%d ifid=%d)\n",
 1677                     if_name(ifp), prefixlen, 128 - plen0));
 1678                 return NULL;
 1679         }
 1680 
 1681         /* make ifaddr */
 1682 
 1683         bzero(&ifra, sizeof(ifra));
 1684         /*
 1685          * in6_update_ifa() does not use ifra_name, but we accurately set it
 1686          * for safety.
 1687          */
 1688         strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
 1689         ifra.ifra_addr.sin6_family = AF_INET6;
 1690         ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
 1691         /* prefix */
 1692         bcopy(&pr->ndpr_prefix.sin6_addr, &ifra.ifra_addr.sin6_addr,
 1693             sizeof(ifra.ifra_addr.sin6_addr));
 1694         ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
 1695         ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
 1696         ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
 1697         ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
 1698 
 1699         /* interface ID */
 1700         ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
 1701             (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
 1702         ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
 1703             (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
 1704         ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
 1705             (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
 1706         ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
 1707             (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
 1708 
 1709         /* new prefix mask. */
 1710         ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
 1711         ifra.ifra_prefixmask.sin6_family = AF_INET6;
 1712         bcopy(&mask, &ifra.ifra_prefixmask.sin6_addr,
 1713             sizeof(ifra.ifra_prefixmask.sin6_addr));
 1714 
 1715         /*
 1716          * lifetime.
 1717          * XXX: in6_init_address_ltimes would override these values later.
 1718          * We should reconsider this logic.
 1719          */
 1720         ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime;
 1721         ifra.ifra_lifetime.ia6t_pltime = pr->ndpr_pltime;
 1722 
 1723         /* XXX: scope zone ID? */
 1724 
 1725         ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
 1726 
 1727         /* allocate ifaddr structure, link into chain, etc. */
 1728         if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
 1729                 nd6log((LOG_ERR,
 1730                     "in6_ifadd: failed to make ifaddr %s on %s (errno=%d)\n",
 1731                     ip6_sprintf(&ifra.ifra_addr.sin6_addr), if_name(ifp),
 1732                     error));
 1733                 return (NULL);  /* ifaddr must not have been allocated. */
 1734         }
 1735 
 1736         ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
 1737 
 1738         return (ia);            /* this is always non-NULL */
 1739 }
 1740 
 1741 int
 1742 in6_init_prefix_ltimes(struct nd_prefix *ndpr)
 1743 {
 1744 
 1745         /* check if preferred lifetime > valid lifetime.  RFC2462 5.5.3 (c) */
 1746         if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
 1747                 nd6log((LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime"
 1748                     "(%d) is greater than valid lifetime(%d)\n",
 1749                     (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime));
 1750                 return (EINVAL);
 1751         }
 1752         if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
 1753                 ndpr->ndpr_preferred = 0;
 1754         else
 1755                 ndpr->ndpr_preferred = time.tv_sec + ndpr->ndpr_pltime;
 1756         if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
 1757                 ndpr->ndpr_expire = 0;
 1758         else
 1759                 ndpr->ndpr_expire = time.tv_sec + ndpr->ndpr_vltime;
 1760 
 1761         return 0;
 1762 }
 1763 
 1764 static void
 1765 in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6)
 1766 {
 1767 
 1768         /* Valid lifetime must not be updated unless explicitly specified. */
 1769         /* init ia6t_expire */
 1770         if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
 1771                 lt6->ia6t_expire = 0;
 1772         else {
 1773                 lt6->ia6t_expire = time.tv_sec;
 1774                 lt6->ia6t_expire += lt6->ia6t_vltime;
 1775         }
 1776 
 1777         /* init ia6t_preferred */
 1778         if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
 1779                 lt6->ia6t_preferred = 0;
 1780         else {
 1781                 lt6->ia6t_preferred = time.tv_sec;
 1782                 lt6->ia6t_preferred += lt6->ia6t_pltime;
 1783         }
 1784 }
 1785 
 1786 /*
 1787  * Delete all the routing table entries that use the specified gateway.
 1788  * XXX: this function causes search through all entries of routing table, so
 1789  * it shouldn't be called when acting as a router.
 1790  */
 1791 void
 1792 rt6_flush(gateway, ifp)
 1793         struct in6_addr *gateway;
 1794         struct ifnet *ifp;
 1795 {
 1796         struct radix_node_head *rnh = rt_tables[AF_INET6];
 1797         int s = splsoftnet();
 1798 
 1799         /* We'll care only link-local addresses */
 1800         if (!IN6_IS_ADDR_LINKLOCAL(gateway)) {
 1801                 splx(s);
 1802                 return;
 1803         }
 1804         /* XXX: hack for KAME's link-local address kludge */
 1805         gateway->s6_addr16[1] = htons(ifp->if_index);
 1806 
 1807         rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
 1808         splx(s);
 1809 }
 1810 
 1811 static int
 1812 rt6_deleteroute(rn, arg)
 1813         struct radix_node *rn;
 1814         void *arg;
 1815 {
 1816 #define SIN6(s) ((struct sockaddr_in6 *)s)
 1817         struct rtentry *rt = (struct rtentry *)rn;
 1818         struct in6_addr *gate = (struct in6_addr *)arg;
 1819 
 1820         if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
 1821                 return (0);
 1822 
 1823         if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr))
 1824                 return (0);
 1825 
 1826         /*
 1827          * Do not delete a static route.
 1828          * XXX: this seems to be a bit ad-hoc. Should we consider the
 1829          * 'cloned' bit instead?
 1830          */
 1831         if ((rt->rt_flags & RTF_STATIC) != 0)
 1832                 return (0);
 1833 
 1834         /*
 1835          * We delete only host route. This means, in particular, we don't
 1836          * delete default route.
 1837          */
 1838         if ((rt->rt_flags & RTF_HOST) == 0)
 1839                 return (0);
 1840 
 1841         return (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
 1842             rt_mask(rt), rt->rt_flags, 0));
 1843 #undef SIN6
 1844 }
 1845 
 1846 int
 1847 nd6_setdefaultiface(ifindex)
 1848         int ifindex;
 1849 {
 1850         int error = 0;
 1851 
 1852         if (ifindex < 0 || if_indexlim <= ifindex)
 1853                 return (EINVAL);
 1854         if (ifindex != 0 && !ifindex2ifnet[ifindex])
 1855                 return (EINVAL);
 1856 
 1857         if (nd6_defifindex != ifindex) {
 1858                 nd6_defifindex = ifindex;
 1859                 if (nd6_defifindex > 0) {
 1860                         nd6_defifp = ifindex2ifnet[nd6_defifindex];
 1861                 } else
 1862                         nd6_defifp = NULL;
 1863         }
 1864 
 1865         return (error);
 1866 }

Cache object: 1e7f357b4aed3c01af16ca31b1dc1cc5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.