root/netinet6/nd6_rtr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nd6_rs_input
  2. nd6_ra_input
  3. nd6_rtmsg
  4. defrouter_addreq
  5. defrouter_lookup
  6. defrtrlist_del
  7. defrouter_delreq
  8. defrouter_reset
  9. defrouter_select
  10. rtpref
  11. defrtrlist_update
  12. pfxrtr_lookup
  13. pfxrtr_add
  14. pfxrtr_del
  15. nd6_prefix_lookup
  16. nd6_prelist_add
  17. prelist_remove
  18. prelist_update
  19. find_pfxlist_reachable_router
  20. pfxlist_onlink_check
  21. nd6_prefix_onlink
  22. nd6_prefix_offlink
  23. in6_ifadd
  24. in6_init_prefix_ltimes
  25. in6_init_address_ltimes
  26. rt6_flush
  27. rt6_deleteroute
  28. nd6_setdefaultiface

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

/* [<][>][^][v][top][bottom][index][help] */