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