1 /* $NetBSD: nd6_rtr.c,v 1.17 2000/06/13 04:35:29 itojun Exp $ */ 2 /* $KAME: nd6_rtr.c,v 1.40 2000/06/13 03:02:29 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 #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 45 #include <net/if.h> 46 #include <net/if_types.h> 47 #include <net/if_dl.h> 48 #include <net/route.h> 49 #include <net/radix.h> 50 51 #include <netinet/in.h> 52 #include <netinet6/in6_var.h> 53 #include <netinet/ip6.h> 54 #include <netinet6/ip6_var.h> 55 #include <netinet6/nd6.h> 56 #include <netinet/icmp6.h> 57 58 #include <net/net_osdep.h> 59 60 #define SDL(s) ((struct sockaddr_dl *)s) 61 62 static struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *)); 63 static int prelist_add __P((struct nd_prefix *, struct nd_defrouter *)); 64 static struct nd_prefix *prefix_lookup __P((struct nd_prefix *)); 65 static struct in6_ifaddr *in6_ifadd __P((struct ifnet *, struct in6_addr *, 66 struct in6_addr *, int)); 67 static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *, 68 struct nd_defrouter *)); 69 static void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *)); 70 static void pfxrtr_del __P((struct nd_pfxrouter *)); 71 static struct nd_pfxrouter *find_pfxlist_reachable_router __P((struct nd_prefix *)); 72 static void nd6_detach_prefix __P((struct nd_prefix *)); 73 static void nd6_attach_prefix __P((struct nd_prefix *)); 74 static void defrouter_addifreq __P((struct ifnet *)); 75 76 static void in6_init_address_ltimes __P((struct nd_prefix *ndpr, 77 struct in6_addrlifetime *lt6, 78 int update_vltime)); 79 80 static int rt6_deleteroute __P((struct radix_node *, void *)); 81 82 extern int nd6_recalc_reachtm_interval; 83 84 struct ifnet *nd6_defifp; 85 int nd6_defifindex; 86 87 /* 88 * Receive Router Solicitation Message - just for routers. 89 * Router solicitation/advertisement is mostly managed by userland program 90 * (rtadvd) so here we have no function like nd6_ra_output(). 91 * 92 * Based on RFC 2461 93 */ 94 void 95 nd6_rs_input(m, off, icmp6len) 96 struct mbuf *m; 97 int off, icmp6len; 98 { 99 struct ifnet *ifp = m->m_pkthdr.rcvif; 100 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 101 struct nd_router_solicit *nd_rs; 102 struct in6_addr saddr6 = ip6->ip6_src; 103 #if 0 104 struct in6_addr daddr6 = ip6->ip6_dst; 105 #endif 106 char *lladdr = NULL; 107 int lladdrlen = 0; 108 #if 0 109 struct sockaddr_dl *sdl = (struct sockaddr_dl *)NULL; 110 struct llinfo_nd6 *ln = (struct llinfo_nd6 *)NULL; 111 struct rtentry *rt = NULL; 112 int is_newentry; 113 #endif 114 union nd_opts ndopts; 115 116 /* If I'm not a router, ignore it. */ 117 if (ip6_accept_rtadv != 0 || ip6_forwarding != 1) 118 goto freeit; 119 120 /* Sanity checks */ 121 if (ip6->ip6_hlim != 255) { 122 log(LOG_ERR, 123 "nd6_rs_input: invalid hlim %d\n", ip6->ip6_hlim); 124 goto freeit; 125 } 126 127 /* 128 * Don't update the neighbor cache, if src = ::. 129 * This indicates that the src has no IP address assigned yet. 130 */ 131 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) 132 goto freeit; 133 134 #ifndef PULLDOWN_TEST 135 IP6_EXTHDR_CHECK(m, off, icmp6len,); 136 nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off); 137 #else 138 IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len); 139 if (nd_rs == NULL) { 140 icmp6stat.icp6s_tooshort++; 141 return; 142 } 143 #endif 144 145 icmp6len -= sizeof(*nd_rs); 146 nd6_option_init(nd_rs + 1, icmp6len, &ndopts); 147 if (nd6_options(&ndopts) < 0) { 148 log(LOG_INFO, "nd6_rs_input: invalid ND option, ignored\n"); 149 goto freeit; 150 } 151 152 if (ndopts.nd_opts_src_lladdr) { 153 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1); 154 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3; 155 } 156 157 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 158 log(LOG_INFO, 159 "nd6_rs_input: lladdrlen mismatch for %s " 160 "(if %d, RS packet %d)\n", 161 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2); 162 } 163 164 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0); 165 166 freeit: 167 m_freem(m); 168 } 169 170 /* 171 * Receive Router Advertisement Message. 172 * 173 * Based on RFC 2461 174 * TODO: on-link bit on prefix information 175 * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing 176 */ 177 void 178 nd6_ra_input(m, off, icmp6len) 179 struct mbuf *m; 180 int off, icmp6len; 181 { 182 struct ifnet *ifp = m->m_pkthdr.rcvif; 183 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index]; 184 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 185 struct nd_router_advert *nd_ra; 186 struct in6_addr saddr6 = ip6->ip6_src; 187 #if 0 188 struct in6_addr daddr6 = ip6->ip6_dst; 189 int flags; /* = nd_ra->nd_ra_flags_reserved; */ 190 int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0); 191 int is_other = ((flags & ND_RA_FLAG_OTHER) != 0); 192 #endif 193 union nd_opts ndopts; 194 struct nd_defrouter *dr; 195 196 if (ip6_accept_rtadv == 0) 197 goto freeit; 198 199 if (ip6->ip6_hlim != 255) { 200 log(LOG_ERR, 201 "nd6_ra_input: invalid hlim %d\n", ip6->ip6_hlim); 202 goto freeit; 203 } 204 205 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) { 206 log(LOG_ERR, 207 "nd6_ra_input: src %s is not link-local\n", 208 ip6_sprintf(&saddr6)); 209 goto freeit; 210 } 211 212 #ifndef PULLDOWN_TEST 213 IP6_EXTHDR_CHECK(m, off, icmp6len,); 214 nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off); 215 #else 216 IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len); 217 if (nd_ra == NULL) { 218 icmp6stat.icp6s_tooshort++; 219 return; 220 } 221 #endif 222 223 icmp6len -= sizeof(*nd_ra); 224 nd6_option_init(nd_ra + 1, icmp6len, &ndopts); 225 if (nd6_options(&ndopts) < 0) { 226 log(LOG_INFO, "nd6_ra_input: invalid ND option, ignored\n"); 227 goto freeit; 228 } 229 230 { 231 struct nd_defrouter dr0; 232 u_int32_t advreachable = nd_ra->nd_ra_reachable; 233 long time_second = time.tv_sec; 234 235 dr0.rtaddr = saddr6; 236 dr0.flags = nd_ra->nd_ra_flags_reserved; 237 dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime); 238 dr0.expire = time_second + dr0.rtlifetime; 239 dr0.ifp = ifp; 240 /* unspecified or not? (RFC 2461 6.3.4) */ 241 if (advreachable) { 242 NTOHL(advreachable); 243 if (advreachable <= MAX_REACHABLE_TIME && 244 ndi->basereachable != advreachable) { 245 ndi->basereachable = advreachable; 246 ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable); 247 ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */ 248 } 249 } 250 if (nd_ra->nd_ra_retransmit) 251 ndi->retrans = ntohl(nd_ra->nd_ra_retransmit); 252 if (nd_ra->nd_ra_curhoplimit) 253 ndi->chlim = nd_ra->nd_ra_curhoplimit; 254 dr = defrtrlist_update(&dr0); 255 } 256 257 /* 258 * prefix 259 */ 260 if (ndopts.nd_opts_pi) { 261 struct nd_opt_hdr *pt; 262 struct nd_opt_prefix_info *pi; 263 struct nd_prefix pr; 264 265 for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi; 266 pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end; 267 pt = (struct nd_opt_hdr *)((caddr_t)pt + 268 (pt->nd_opt_len << 3))) { 269 if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION) 270 continue; 271 pi = (struct nd_opt_prefix_info *)pt; 272 273 if (pi->nd_opt_pi_len != 4) { 274 log(LOG_INFO, "nd6_ra_input: invalid option " 275 "len %d for prefix information option, " 276 "ignored\n", pi->nd_opt_pi_len); 277 continue; 278 } 279 280 if (128 < pi->nd_opt_pi_prefix_len) { 281 log(LOG_INFO, "nd6_ra_input: invalid prefix " 282 "len %d for prefix information option, " 283 "ignored\n", pi->nd_opt_pi_prefix_len); 284 continue; 285 } 286 287 if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix) 288 || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) { 289 log(LOG_INFO, "nd6_ra_input: invalid prefix " 290 "%s, ignored\n", 291 ip6_sprintf(&pi->nd_opt_pi_prefix)); 292 continue; 293 } 294 295 /* aggregatable unicast address, rfc2374 */ 296 if ((pi->nd_opt_pi_prefix.s6_addr8[0] & 0xe0) == 0x20 297 && pi->nd_opt_pi_prefix_len != 64) { 298 log(LOG_INFO, "nd6_ra_input: invalid prefixlen " 299 "%d for rfc2374 prefix %s, ignored\n", 300 pi->nd_opt_pi_prefix_len, 301 ip6_sprintf(&pi->nd_opt_pi_prefix)); 302 continue; 303 } 304 305 bzero(&pr, sizeof(pr)); 306 pr.ndpr_prefix.sin6_family = AF_INET6; 307 pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix); 308 pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix; 309 pr.ndpr_ifp = (struct ifnet *)m->m_pkthdr.rcvif; 310 311 pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved & 312 ND_OPT_PI_FLAG_ONLINK) ? 1 : 0; 313 pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved & 314 ND_OPT_PI_FLAG_AUTO) ? 1 : 0; 315 pr.ndpr_plen = pi->nd_opt_pi_prefix_len; 316 pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time); 317 pr.ndpr_pltime = 318 ntohl(pi->nd_opt_pi_preferred_time); 319 320 if (in6_init_prefix_ltimes(&pr)) 321 continue; /* prefix lifetime init failed */ 322 323 (void)prelist_update(&pr, dr, m); 324 } 325 } 326 327 /* 328 * MTU 329 */ 330 if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) { 331 u_int32_t mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu); 332 333 /* lower bound */ 334 if (mtu < IPV6_MMTU) { 335 log(LOG_INFO, "nd6_ra_input: bogus mtu option " 336 "mtu=%d sent from %s, ignoring\n", 337 mtu, ip6_sprintf(&ip6->ip6_src)); 338 goto skip; 339 } 340 341 /* upper bound */ 342 if (ndi->maxmtu) { 343 if (mtu <= ndi->maxmtu) { 344 int change = (ndi->linkmtu != mtu); 345 346 ndi->linkmtu = mtu; 347 if (change) /* in6_maxmtu may change */ 348 in6_setmaxmtu(); 349 } else { 350 log(LOG_INFO, "nd6_ra_input: bogus mtu " 351 "mtu=%d sent from %s; " 352 "exceeds maxmtu %d, ignoring\n", 353 mtu, ip6_sprintf(&ip6->ip6_src), 354 ndi->maxmtu); 355 } 356 } else { 357 log(LOG_INFO, "nd6_ra_input: mtu option " 358 "mtu=%d sent from %s; maxmtu unknown, " 359 "ignoring\n", 360 mtu, ip6_sprintf(&ip6->ip6_src)); 361 } 362 } 363 364 skip: 365 366 /* 367 * Src linkaddress 368 */ 369 { 370 char *lladdr = NULL; 371 int lladdrlen = 0; 372 373 if (ndopts.nd_opts_src_lladdr) { 374 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1); 375 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3; 376 } 377 378 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 379 log(LOG_INFO, 380 "nd6_ra_input: lladdrlen mismatch for %s " 381 "(if %d, RA packet %d)\n", 382 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2); 383 } 384 385 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0); 386 387 /* 388 * Installing a link-layer address might change the state of the 389 * router's neighbor cache, which might also affect our on-link 390 * detection of adveritsed prefixes. 391 */ 392 pfxlist_onlink_check(); 393 } 394 395 freeit: 396 m_freem(m); 397 } 398 399 /* 400 * default router list proccessing sub routines 401 */ 402 void 403 defrouter_addreq(new) 404 struct nd_defrouter *new; 405 { 406 struct sockaddr_in6 def, mask, gate; 407 int s; 408 409 Bzero(&def, sizeof(def)); 410 Bzero(&mask, sizeof(mask)); 411 Bzero(&gate, sizeof(gate)); 412 413 def.sin6_len = mask.sin6_len = gate.sin6_len 414 = sizeof(struct sockaddr_in6); 415 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6; 416 gate.sin6_addr = new->rtaddr; 417 418 s = splsoftnet(); 419 (void)rtrequest(RTM_ADD, (struct sockaddr *)&def, 420 (struct sockaddr *)&gate, (struct sockaddr *)&mask, 421 RTF_GATEWAY, NULL); 422 splx(s); 423 return; 424 } 425 426 /* Add a route to a given interface as default */ 427 static void 428 defrouter_addifreq(ifp) 429 struct ifnet *ifp; 430 { 431 struct sockaddr_in6 def, mask; 432 struct ifaddr *ifa; 433 int error, flags; 434 435 bzero(&def, sizeof(def)); 436 bzero(&mask, sizeof(mask)); 437 438 def.sin6_len = mask.sin6_len = sizeof(struct sockaddr_in6); 439 def.sin6_family = mask.sin6_family = AF_INET6; 440 441 /* 442 * Search for an ifaddr beloging to the specified interface. 443 * XXX: An IPv6 address are required to be assigned on the interface. 444 */ 445 if ((ifa = ifaof_ifpforaddr((struct sockaddr *)&def, ifp)) == NULL) { 446 log(LOG_ERR, /* better error? */ 447 "defrouter_addifreq: failed to find an ifaddr " 448 "to install a route to interface %s\n", 449 if_name(ifp)); 450 return; 451 } 452 453 flags = ifa->ifa_flags; 454 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) 455 flags &= ~RTF_CLONING; 456 if ((error = rtrequest(RTM_ADD, (struct sockaddr *)&def, 457 ifa->ifa_addr, (struct sockaddr *)&mask, 458 flags, NULL)) != 0) { 459 log(LOG_ERR, 460 "defrouter_addifreq: failed to install a route to " 461 "interface %s (errno = %d)\n", 462 if_name(ifp), error); 463 } 464 } 465 466 struct nd_defrouter * 467 defrouter_lookup(addr, ifp) 468 struct in6_addr *addr; 469 struct ifnet *ifp; 470 { 471 struct nd_defrouter *dr; 472 473 for (dr = TAILQ_FIRST(&nd_defrouter); dr; 474 dr = TAILQ_NEXT(dr, dr_entry)) { 475 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) 476 return(dr); 477 } 478 479 return(NULL); /* search failed */ 480 } 481 482 void 483 defrouter_delreq(dr, dofree) 484 struct nd_defrouter *dr; 485 int dofree; 486 { 487 struct sockaddr_in6 def, mask, gate; 488 489 Bzero(&def, sizeof(def)); 490 Bzero(&mask, sizeof(mask)); 491 Bzero(&gate, sizeof(gate)); 492 493 def.sin6_len = mask.sin6_len = gate.sin6_len 494 = sizeof(struct sockaddr_in6); 495 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6; 496 gate.sin6_addr = dr->rtaddr; 497 498 rtrequest(RTM_DELETE, (struct sockaddr *)&def, 499 (struct sockaddr *)&gate, 500 (struct sockaddr *)&mask, 501 RTF_GATEWAY, (struct rtentry **)0); 502 503 if (dofree) /* XXX: necessary? */ 504 free(dr, M_IP6NDP); 505 } 506 507 void 508 defrtrlist_del(dr) 509 struct nd_defrouter *dr; 510 { 511 struct nd_defrouter *deldr = NULL; 512 struct nd_prefix *pr; 513 514 /* 515 * Flush all the routing table entries that use the router 516 * as a next hop. 517 */ 518 if (!ip6_forwarding && ip6_accept_rtadv) { 519 /* above is a good condition? */ 520 rt6_flush(&dr->rtaddr, dr->ifp); 521 } 522 523 if (dr == TAILQ_FIRST(&nd_defrouter)) 524 deldr = dr; /* The router is primary. */ 525 526 TAILQ_REMOVE(&nd_defrouter, dr, dr_entry); 527 528 /* 529 * Also delete all the pointers to the router in each prefix lists. 530 */ 531 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { 532 struct nd_pfxrouter *pfxrtr; 533 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL) 534 pfxrtr_del(pfxrtr); 535 } 536 pfxlist_onlink_check(); 537 538 /* 539 * If the router is the primary one, choose a new one. 540 * Note that defrouter_select() will remove the current gateway 541 * from the routing table. 542 */ 543 if (deldr) 544 defrouter_select(); 545 546 free(dr, M_IP6NDP); 547 } 548 549 /* 550 * Default Router Selection according to Section 6.3.6 of RFC 2461: 551 * 1) Routers that are reachable or probably reachable should be 552 * preferred. 553 * 2) When no routers on the list are known to be reachable or 554 * probably reachable, routers SHOULD be selected in a round-robin 555 * fashion. 556 * 3) If the Default Router List is empty, assume that all 557 * destinations are on-link. 558 */ 559 void 560 defrouter_select() 561 { 562 int s = splsoftnet(); 563 struct nd_defrouter *dr, anydr; 564 struct rtentry *rt = NULL; 565 struct llinfo_nd6 *ln = NULL; 566 567 /* 568 * Search for a (probably) reachable router from the list. 569 */ 570 for (dr = TAILQ_FIRST(&nd_defrouter); dr; 571 dr = TAILQ_NEXT(dr, dr_entry)) { 572 if ((rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) && 573 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && 574 ND6_IS_LLINFO_PROBREACH(ln)) { 575 /* Got it, and move it to the head */ 576 TAILQ_REMOVE(&nd_defrouter, dr, dr_entry); 577 TAILQ_INSERT_HEAD(&nd_defrouter, dr, dr_entry); 578 break; 579 } 580 } 581 582 if ((dr = TAILQ_FIRST(&nd_defrouter))) { 583 /* 584 * De-install the previous default gateway and install 585 * a new one. 586 * Note that if there is no reachable router in the list, 587 * the head entry will be used anyway. 588 * XXX: do we have to check the current routing table entry? 589 */ 590 bzero(&anydr, sizeof(anydr)); 591 defrouter_delreq(&anydr, 0); 592 defrouter_addreq(dr); 593 } 594 else { 595 /* 596 * The Default Router List is empty, so install the default 597 * route to an inteface. 598 * XXX: The specification does not say this mechanism should 599 * be restricted to hosts, but this would be not useful 600 * (even harmful) for routers. 601 */ 602 if (!ip6_forwarding) { 603 /* 604 * De-install the current default route 605 * in advance. 606 */ 607 bzero(&anydr, sizeof(anydr)); 608 defrouter_delreq(&anydr, 0); 609 if (nd6_defifp) { 610 /* 611 * Install a route to the default interface 612 * as default route. 613 */ 614 defrouter_addifreq(nd6_defifp); 615 } 616 #ifdef ND6_DEBUG 617 else /* noisy log? */ 618 log(LOG_INFO, "defrouter_select: " 619 "there's no default router and no default" 620 " interface\n"); 621 #endif 622 } 623 } 624 625 splx(s); 626 return; 627 } 628 629 static struct nd_defrouter * 630 defrtrlist_update(new) 631 struct nd_defrouter *new; 632 { 633 struct nd_defrouter *dr, *n; 634 int s = splsoftnet(); 635 636 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) { 637 /* entry exists */ 638 if (new->rtlifetime == 0) { 639 defrtrlist_del(dr); 640 dr = NULL; 641 } else { 642 /* override */ 643 dr->flags = new->flags; /* xxx flag check */ 644 dr->rtlifetime = new->rtlifetime; 645 dr->expire = new->expire; 646 } 647 splx(s); 648 return(dr); 649 } 650 651 /* entry does not exist */ 652 if (new->rtlifetime == 0) { 653 splx(s); 654 return(NULL); 655 } 656 657 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT); 658 if (n == NULL) { 659 splx(s); 660 return(NULL); 661 } 662 bzero(n, sizeof(*n)); 663 *n = *new; 664 665 /* 666 * Insert the new router at the end of the Default Router List. 667 * If there is no other router, install it anyway. Otherwise, 668 * just continue to use the current default router. 669 */ 670 TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry); 671 if (TAILQ_FIRST(&nd_defrouter) == n) 672 defrouter_select(); 673 splx(s); 674 675 return(n); 676 } 677 678 static struct nd_pfxrouter * 679 pfxrtr_lookup(pr, dr) 680 struct nd_prefix *pr; 681 struct nd_defrouter *dr; 682 { 683 struct nd_pfxrouter *search; 684 685 for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) { 686 if (search->router == dr) 687 break; 688 } 689 690 return(search); 691 } 692 693 static void 694 pfxrtr_add(pr, dr) 695 struct nd_prefix *pr; 696 struct nd_defrouter *dr; 697 { 698 struct nd_pfxrouter *new; 699 700 new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT); 701 if (new == NULL) 702 return; 703 bzero(new, sizeof(*new)); 704 new->router = dr; 705 706 LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry); 707 708 pfxlist_onlink_check(); 709 } 710 711 static void 712 pfxrtr_del(pfr) 713 struct nd_pfxrouter *pfr; 714 { 715 LIST_REMOVE(pfr, pfr_entry); 716 free(pfr, M_IP6NDP); 717 } 718 719 static struct nd_prefix * 720 prefix_lookup(pr) 721 struct nd_prefix *pr; 722 { 723 struct nd_prefix *search; 724 725 for (search = nd_prefix.lh_first; search; search = search->ndpr_next) { 726 if (pr->ndpr_ifp == search->ndpr_ifp && 727 pr->ndpr_plen == search->ndpr_plen && 728 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr, 729 &search->ndpr_prefix.sin6_addr, 730 pr->ndpr_plen) 731 ) { 732 break; 733 } 734 } 735 736 return(search); 737 } 738 739 static int 740 prelist_add(pr, dr) 741 struct nd_prefix *pr; 742 struct nd_defrouter *dr; 743 { 744 struct nd_prefix *new; 745 int i, s; 746 747 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT); 748 if (new == NULL) 749 return ENOMEM; 750 bzero(new, sizeof(*new)); 751 *new = *pr; 752 753 /* initilization */ 754 new->ndpr_statef_onlink = pr->ndpr_statef_onlink; 755 LIST_INIT(&new->ndpr_advrtrs); 756 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen); 757 /* make prefix in the canonical form */ 758 for (i = 0; i < 4; i++) 759 new->ndpr_prefix.sin6_addr.s6_addr32[i] &= 760 new->ndpr_mask.s6_addr32[i]; 761 762 /* xxx ND_OPT_PI_FLAG_ONLINK processing */ 763 764 s = splsoftnet(); 765 /* link ndpr_entry to nd_prefix list */ 766 LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry); 767 splx(s); 768 769 if (dr) 770 pfxrtr_add(new, dr); 771 772 return 0; 773 } 774 775 void 776 prelist_remove(pr) 777 struct nd_prefix *pr; 778 { 779 struct nd_pfxrouter *pfr, *next; 780 int s; 781 782 s = splsoftnet(); 783 /* unlink ndpr_entry from nd_prefix list */ 784 LIST_REMOVE(pr, ndpr_entry); 785 splx(s); 786 787 /* free list of routers that adversed the prefix */ 788 for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) { 789 next = pfr->pfr_next; 790 791 free(pfr, M_IP6NDP); 792 } 793 free(pr, M_IP6NDP); 794 795 pfxlist_onlink_check(); 796 } 797 798 /* 799 * NOTE: We set address lifetime to keep 800 * address lifetime <= prefix lifetime 801 * invariant. This is to simplify on-link determination code. 802 * If onlink determination is udated, this routine may have to be updated too. 803 */ 804 int 805 prelist_update(new, dr, m) 806 struct nd_prefix *new; 807 struct nd_defrouter *dr; /* may be NULL */ 808 struct mbuf *m; 809 { 810 struct in6_ifaddr *ia6 = NULL; 811 struct nd_prefix *pr; 812 int s = splsoftnet(); 813 int error = 0; 814 int auth; 815 struct in6_addrlifetime *lt6; 816 817 auth = 0; 818 if (m) { 819 /* 820 * Authenticity for NA consists authentication for 821 * both IP header and IP datagrams, doesn't it ? 822 */ 823 #if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM) 824 auth = (m->m_flags & M_AUTHIPHDR 825 && m->m_flags & M_AUTHIPDGM) ? 1 : 0; 826 #endif 827 } 828 829 if ((pr = prefix_lookup(new)) != NULL) { 830 if (pr->ndpr_ifp != new->ndpr_ifp) { 831 error = EADDRNOTAVAIL; 832 goto end; 833 } 834 /* update prefix information */ 835 pr->ndpr_flags = new->ndpr_flags; 836 pr->ndpr_vltime = new->ndpr_vltime; 837 pr->ndpr_pltime = new->ndpr_pltime; 838 pr->ndpr_preferred = new->ndpr_preferred; 839 pr->ndpr_expire = new->ndpr_expire; 840 841 /* 842 * RFC 2462 5.5.3 (d) or (e) 843 * We got a prefix which we have seen in the past. 844 */ 845 if (!new->ndpr_raf_auto) 846 goto noautoconf1; 847 848 if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr)) 849 ia6 = NULL; 850 else 851 ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr); 852 853 if (ia6 == NULL) { 854 /* 855 * Special case: 856 * (1) We have seen the prefix advertised before, but 857 * we have never performed autoconfig for this prefix. 858 * This is because Autonomous bit was 0 previously, or 859 * autoconfig failed due to some other reasons. 860 * (2) We have seen the prefix advertised before and 861 * we have performed autoconfig in the past, but 862 * we seem to have no interface address right now. 863 * This is because the interface address have expired. 864 * 865 * This prefix is fresh, with respect to autoconfig 866 * process. 867 * 868 * Add an address based on RFC 2462 5.5.3 (d). 869 */ 870 ia6 = in6_ifadd(pr->ndpr_ifp, 871 &pr->ndpr_prefix.sin6_addr, &pr->ndpr_addr, 872 new->ndpr_plen); 873 if (!ia6) { 874 error = EADDRNOTAVAIL; 875 log(LOG_ERR, "prelist_update: failed to add a " 876 "new address\n"); 877 goto noautoconf1; 878 } 879 880 lt6 = &ia6->ia6_lifetime; 881 882 /* address lifetime <= prefix lifetime */ 883 lt6->ia6t_vltime = new->ndpr_vltime; 884 lt6->ia6t_pltime = new->ndpr_pltime; 885 in6_init_address_ltimes(new, lt6, 1); 886 } else { 887 #define TWOHOUR (120*60) 888 /* 889 * We have seen the prefix before, and we have added 890 * interface address in the past. We still have 891 * the interface address assigned. 892 * 893 * update address lifetime based on RFC 2462 894 * 5.5.3 (e). 895 */ 896 int update = 0; 897 898 lt6 = &ia6->ia6_lifetime; 899 900 #if 0 /* RFC 2462 5.5.3 (e) */ 901 lt6->ia6t_pltime = new->ndpr_pltime; 902 if (TWOHOUR < new->ndpr_vltime 903 || lt6pr->nd < new->ndpr_vltime) { 904 lt6->ia6t_vltime = new->ndpr_vltime; 905 update++; 906 } else if (auth 907 && lt6->ia6t_vltime <= TWOHOUR0 908 && new->ndpr_vltime <= lt6->ia6t_vltime) { 909 lt6->ia6t_vltime = new->ndpr_vltime; 910 update++; 911 } else { 912 lt6->ia6t_vltime = TWOHOUR; 913 update++; 914 } 915 916 /* 2 hour rule is not imposed for pref lifetime */ 917 new->ndpr_apltime = new->ndpr_pltime; 918 lt6->ia6t_pltime = new->ndpr_pltime; 919 #else /* update from Jim Bound, (ipng 6712) */ 920 if (TWOHOUR < new->ndpr_vltime 921 || lt6->ia6t_vltime < new->ndpr_vltime) { 922 lt6->ia6t_vltime = new->ndpr_vltime; 923 update++; 924 } else if (auth) { 925 lt6->ia6t_vltime = new->ndpr_vltime; 926 update++; 927 } 928 929 /* jim bound rule is not imposed for pref lifetime */ 930 lt6->ia6t_pltime = new->ndpr_pltime; 931 #endif 932 in6_init_address_ltimes(new, lt6, update); 933 } 934 935 noautoconf1: 936 937 #if 0 938 /* address lifetime expire processing, RFC 2462 5.5.4. */ 939 if (pr->ndpr_preferred && pr->ndpr_preferred < time_second) { 940 struct in6_ifaddr *ia6; 941 942 ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr); 943 if (ia6) 944 ia6->ia6_flags &= ~IN6_IFF_DEPRECATED; 945 } 946 #endif 947 948 if (dr && pfxrtr_lookup(pr, dr) == NULL) 949 pfxrtr_add(pr, dr); 950 } else { 951 int error_tmp; 952 953 if (new->ndpr_vltime == 0) goto end; 954 955 bzero(&new->ndpr_addr, sizeof(struct in6_addr)); 956 957 /* 958 * RFC 2462 5.5.3 (d) 959 * We got a fresh prefix. Perform some sanity checks 960 * and add an interface address by appending interface ID 961 * to the advertised prefix. 962 */ 963 if (!new->ndpr_raf_auto) 964 goto noautoconf2; 965 966 ia6 = in6_ifadd(new->ndpr_ifp, &new->ndpr_prefix.sin6_addr, 967 &new->ndpr_addr, new->ndpr_plen); 968 if (!ia6) { 969 error = EADDRNOTAVAIL; 970 log(LOG_ERR, "prelist_update: " 971 "failed to add a new address\n"); 972 goto noautoconf2; 973 } 974 /* set onlink bit if an interface route is configured */ 975 new->ndpr_statef_onlink = (ia6->ia_flags & IFA_ROUTE) ? 1 : 0; 976 977 lt6 = &ia6->ia6_lifetime; 978 979 /* address lifetime <= prefix lifetime */ 980 lt6->ia6t_vltime = new->ndpr_vltime; 981 lt6->ia6t_pltime = new->ndpr_pltime; 982 in6_init_address_ltimes(new, lt6, 1); 983 984 noautoconf2: 985 error_tmp = prelist_add(new, dr); 986 error = error_tmp ? error_tmp : error; 987 } 988 989 end: 990 splx(s); 991 return error; 992 } 993 994 /* 995 * A supplement function used in the on-link detection below; 996 * detect if a given prefix has a (probably) reachable advertising router. 997 * XXX: lengthy function name... 998 */ 999 static struct nd_pfxrouter * 1000 find_pfxlist_reachable_router(pr) 1001 struct nd_prefix *pr; 1002 { 1003 struct nd_pfxrouter *pfxrtr; 1004 struct rtentry *rt; 1005 struct llinfo_nd6 *ln; 1006 1007 for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr; 1008 pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) { 1009 if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0, 1010 pfxrtr->router->ifp)) && 1011 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && 1012 ND6_IS_LLINFO_PROBREACH(ln)) 1013 break; /* found */ 1014 } 1015 1016 return(pfxrtr); 1017 1018 } 1019 1020 /* 1021 * Check if each prefix in the prefix list has at least one available router 1022 * that advertised the prefix (A router is "available" if its neighbor cache 1023 * entry has reachable or probably reachable). 1024 * If the check fails, the prefix may be off-link, because, for example, 1025 * we have moved from the network but the lifetime of the prefix has not 1026 * been expired yet. So we should not use the prefix if there is another 1027 * prefix that has an available router. 1028 * But if there is no prefix that has an available router, we still regards 1029 * all the prefixes as on-link. This is because we can't tell if all the 1030 * routers are simply dead or if we really moved from the network and there 1031 * is no router around us. 1032 */ 1033 void 1034 pfxlist_onlink_check() 1035 { 1036 struct nd_prefix *pr; 1037 1038 /* 1039 * Check if there is a prefix that has a reachable advertising 1040 * router. 1041 */ 1042 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { 1043 if (find_pfxlist_reachable_router(pr)) 1044 break; 1045 } 1046 1047 if (pr) { 1048 /* 1049 * There is at least one prefix that has a reachable router. 1050 * First, detach prefixes which has no reachable advertising 1051 * router and then attach other prefixes. 1052 * The order is important since an attached prefix and a 1053 * detached prefix may have a same interface route. 1054 */ 1055 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { 1056 if (find_pfxlist_reachable_router(pr) == NULL && 1057 pr->ndpr_statef_onlink) { 1058 pr->ndpr_statef_onlink = 0; 1059 nd6_detach_prefix(pr); 1060 } 1061 } 1062 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) { 1063 if (find_pfxlist_reachable_router(pr) && 1064 pr->ndpr_statef_onlink == 0) 1065 nd6_attach_prefix(pr); 1066 } 1067 } 1068 else { 1069 /* there is no prefix that has a reachable router */ 1070 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) 1071 if (pr->ndpr_statef_onlink == 0) 1072 nd6_attach_prefix(pr); 1073 } 1074 } 1075 1076 static void 1077 nd6_detach_prefix(pr) 1078 struct nd_prefix *pr; 1079 { 1080 struct in6_ifaddr *ia6; 1081 struct sockaddr_in6 sa6, mask6; 1082 1083 /* 1084 * Delete the interface route associated with the prefix. 1085 */ 1086 bzero(&sa6, sizeof(sa6)); 1087 sa6.sin6_family = AF_INET6; 1088 sa6.sin6_len = sizeof(sa6); 1089 bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr, 1090 sizeof(struct in6_addr)); 1091 bzero(&mask6, sizeof(mask6)); 1092 mask6.sin6_family = AF_INET6; 1093 mask6.sin6_len = sizeof(sa6); 1094 bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr)); 1095 { 1096 int e; 1097 1098 e = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL, 1099 (struct sockaddr *)&mask6, 0, NULL); 1100 if (e) { 1101 log(LOG_ERR, 1102 "nd6_detach_prefix: failed to delete route: " 1103 "%s/%d (errno = %d)\n", 1104 ip6_sprintf(&sa6.sin6_addr), 1105 pr->ndpr_plen, 1106 e); 1107 } 1108 } 1109 1110 /* 1111 * Mark the address derived from the prefix detached so that 1112 * it won't be used as a source address for a new connection. 1113 */ 1114 if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr)) 1115 ia6 = NULL; 1116 else 1117 ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr); 1118 if (ia6) 1119 ia6->ia6_flags |= IN6_IFF_DETACHED; 1120 } 1121 1122 static void 1123 nd6_attach_prefix(pr) 1124 struct nd_prefix *pr; 1125 { 1126 struct ifaddr *ifa; 1127 struct in6_ifaddr *ia6; 1128 1129 /* 1130 * Add the interface route associated with the prefix(if necessary) 1131 * Should we consider if the L bit is set in pr->ndpr_flags? 1132 */ 1133 ifa = ifaof_ifpforaddr((struct sockaddr *)&pr->ndpr_prefix, 1134 pr->ndpr_ifp); 1135 if (ifa == NULL) { 1136 log(LOG_ERR, 1137 "nd6_attach_prefix: failed to find any ifaddr" 1138 " to add route for a prefix(%s/%d)\n", 1139 ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen); 1140 } 1141 else { 1142 int e; 1143 struct sockaddr_in6 mask6; 1144 1145 bzero(&mask6, sizeof(mask6)); 1146 mask6.sin6_family = AF_INET6; 1147 mask6.sin6_len = sizeof(mask6); 1148 mask6.sin6_addr = pr->ndpr_mask; 1149 e = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix, 1150 ifa->ifa_addr, (struct sockaddr *)&mask6, 1151 ifa->ifa_flags, NULL); 1152 if (e == 0) 1153 pr->ndpr_statef_onlink = 1; 1154 else { 1155 log(LOG_ERR, 1156 "nd6_attach_prefix: failed to add route for" 1157 " a prefix(%s/%d), errno = %d\n", 1158 ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen, e); 1159 } 1160 } 1161 1162 /* 1163 * Now the address derived from the prefix can be used as a source 1164 * for a new connection, so clear the detached flag. 1165 */ 1166 if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr)) 1167 ia6 = NULL; 1168 else 1169 ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr); 1170 if (ia6) { 1171 ia6->ia6_flags &= ~IN6_IFF_DETACHED; 1172 if (pr->ndpr_statef_onlink) 1173 ia6->ia_flags |= IFA_ROUTE; 1174 } 1175 } 1176 1177 static struct in6_ifaddr * 1178 in6_ifadd(ifp, in6, addr, prefixlen) 1179 struct ifnet *ifp; 1180 struct in6_addr *in6; 1181 struct in6_addr *addr; 1182 int prefixlen; /* prefix len of the new prefix in "in6" */ 1183 { 1184 struct ifaddr *ifa; 1185 struct in6_ifaddr *ia, *ib, *oia; 1186 int s, error; 1187 struct in6_addr mask; 1188 1189 in6_len2mask(&mask, prefixlen); 1190 1191 /* find link-local address (will be interface ID) */ 1192 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);/* 0 is OK? */ 1193 if (ifa) 1194 ib = (struct in6_ifaddr *)ifa; 1195 else 1196 return NULL; 1197 1198 #if 0 /* don't care link local addr state, and always do DAD */ 1199 /* if link-local address is not eligible, do not autoconfigure. */ 1200 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) { 1201 printf("in6_ifadd: link-local address not ready\n"); 1202 return NULL; 1203 } 1204 #endif 1205 1206 /* prefixlen + ifidlen must be equal to 128 */ 1207 if (prefixlen != in6_mask2len(&ib->ia_prefixmask.sin6_addr)) { 1208 log(LOG_ERR, "in6_ifadd: wrong prefixlen for %s" 1209 "(prefix=%d ifid=%d)\n", if_name(ifp), 1210 prefixlen, 1211 128 - in6_mask2len(&ib->ia_prefixmask.sin6_addr)); 1212 return NULL; 1213 } 1214 1215 /* make ifaddr */ 1216 ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_DONTWAIT); 1217 if (ia == NULL) { 1218 printf("ENOBUFS in in6_ifadd %d\n", __LINE__); 1219 return NULL; 1220 } 1221 1222 bzero((caddr_t)ia, sizeof(*ia)); 1223 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 1224 if (ifp->if_flags & IFF_POINTOPOINT) 1225 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; 1226 else 1227 ia->ia_ifa.ifa_dstaddr = NULL; 1228 ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; 1229 ia->ia_ifp = ifp; 1230 1231 /* link to in6_ifaddr */ 1232 if ((oia = in6_ifaddr) != NULL) { 1233 for( ; oia->ia_next; oia = oia->ia_next) 1234 continue; 1235 oia->ia_next = ia; 1236 } else { 1237 /* 1238 * This should be impossible, since we have at least one 1239 * link-local address (see the beginning of this function). 1240 * XXX: should we rather panic here? 1241 */ 1242 printf("in6_ifadd: in6_ifaddr is NULL (impossible!)\n"); 1243 in6_ifaddr = ia; 1244 } 1245 /* gain a refcnt for the link from in6_ifaddr */ 1246 IFAREF((struct ifaddr *)ia); 1247 1248 /* link to if_addrlist */ 1249 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 1250 /* gain another refcnt for the link from if_addrlist */ 1251 IFAREF((struct ifaddr *)ia); 1252 1253 /* new address */ 1254 ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6); 1255 ia->ia_addr.sin6_family = AF_INET6; 1256 /* prefix */ 1257 bcopy(in6, &ia->ia_addr.sin6_addr, sizeof(ia->ia_addr.sin6_addr)); 1258 ia->ia_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0]; 1259 ia->ia_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1]; 1260 ia->ia_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2]; 1261 ia->ia_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3]; 1262 /* interface ID */ 1263 ia->ia_addr.sin6_addr.s6_addr32[0] 1264 |= (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]); 1265 ia->ia_addr.sin6_addr.s6_addr32[1] 1266 |= (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]); 1267 ia->ia_addr.sin6_addr.s6_addr32[2] 1268 |= (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]); 1269 ia->ia_addr.sin6_addr.s6_addr32[3] 1270 |= (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]); 1271 1272 /* new prefix */ 1273 ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 1274 ia->ia_prefixmask.sin6_family = AF_INET6; 1275 bcopy(&mask, &ia->ia_prefixmask.sin6_addr, 1276 sizeof(ia->ia_prefixmask.sin6_addr)); 1277 1278 /* same routine */ 1279 ia->ia_ifa.ifa_rtrequest = 1280 (ifp->if_type == IFT_PPP) ? nd6_p2p_rtrequest : nd6_rtrequest; 1281 ia->ia_ifa.ifa_flags |= RTF_CLONING; 1282 ia->ia_ifa.ifa_metric = ifp->if_metric; 1283 1284 /* add interface route */ 1285 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP|RTF_CLONING))) { 1286 log(LOG_NOTICE, "in6_ifadd: failed to add an interface route " 1287 "for %s/%d on %s, errno = %d\n", 1288 ip6_sprintf(&ia->ia_addr.sin6_addr), prefixlen, 1289 if_name(ifp), error); 1290 } 1291 else 1292 ia->ia_flags |= IFA_ROUTE; 1293 1294 *addr = ia->ia_addr.sin6_addr; 1295 1296 if (ifp->if_flags & IFF_MULTICAST) { 1297 int error; /* not used */ 1298 struct in6_addr sol6; 1299 1300 /* Restore saved multicast addresses(if any). */ 1301 in6_restoremkludge(ia, ifp); 1302 1303 /* join solicited node multicast address */ 1304 bzero(&sol6, sizeof(sol6)); 1305 sol6.s6_addr16[0] = htons(0xff02); 1306 sol6.s6_addr16[1] = htons(ifp->if_index); 1307 sol6.s6_addr32[1] = 0; 1308 sol6.s6_addr32[2] = htonl(1); 1309 sol6.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3]; 1310 sol6.s6_addr8[12] = 0xff; 1311 (void)in6_addmulti(&sol6, ifp, &error); 1312 } 1313 1314 ia->ia6_flags |= IN6_IFF_TENTATIVE; 1315 1316 /* 1317 * To make the interface up. Only AF_INET6 in ia is used... 1318 */ 1319 s = splimp(); 1320 if (ifp->if_ioctl && (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) { 1321 splx(s); 1322 return NULL; 1323 } 1324 splx(s); 1325 1326 /* Perform DAD, if needed. */ 1327 nd6_dad_start((struct ifaddr *)ia, NULL); 1328 1329 return ia; 1330 } 1331 1332 int 1333 in6_ifdel(ifp, in6) 1334 struct ifnet *ifp; 1335 struct in6_addr *in6; 1336 { 1337 struct in6_ifaddr *ia = (struct in6_ifaddr *)NULL; 1338 struct in6_ifaddr *oia = (struct in6_ifaddr *)NULL; 1339 1340 if (!ifp) 1341 return -1; 1342 1343 ia = in6ifa_ifpwithaddr(ifp, in6); 1344 if (!ia) 1345 return -1; 1346 1347 if (ifp->if_flags & IFF_MULTICAST) { 1348 /* 1349 * delete solicited multicast addr for deleting host id 1350 */ 1351 struct in6_multi *in6m; 1352 struct in6_addr llsol; 1353 bzero(&llsol, sizeof(struct in6_addr)); 1354 llsol.s6_addr16[0] = htons(0xff02); 1355 llsol.s6_addr16[1] = htons(ifp->if_index); 1356 llsol.s6_addr32[1] = 0; 1357 llsol.s6_addr32[2] = htonl(1); 1358 llsol.s6_addr32[3] = 1359 ia->ia_addr.sin6_addr.s6_addr32[3]; 1360 llsol.s6_addr8[12] = 0xff; 1361 1362 IN6_LOOKUP_MULTI(llsol, ifp, in6m); 1363 if (in6m) 1364 in6_delmulti(in6m); 1365 } 1366 1367 if (ia->ia_flags & IFA_ROUTE) { 1368 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 1369 ia->ia_flags &= ~IFA_ROUTE; 1370 } 1371 1372 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 1373 IFAFREE(&ia->ia_ifa); 1374 1375 /* lladdr is never deleted */ 1376 oia = ia; 1377 if (oia == (ia = in6_ifaddr)) 1378 in6_ifaddr = ia->ia_next; 1379 else { 1380 while (ia->ia_next && (ia->ia_next != oia)) 1381 ia = ia->ia_next; 1382 if (ia->ia_next) 1383 ia->ia_next = oia->ia_next; 1384 else 1385 return -1; 1386 } 1387 1388 in6_savemkludge(oia); 1389 IFAFREE((&oia->ia_ifa)); 1390 /* xxx 1391 rtrequest(RTM_DELETE, 1392 (struct sockaddr *)&ia->ia_addr, 1393 (struct sockaddr *)0 1394 (struct sockaddr *)&ia->ia_prefixmask, 1395 RTF_UP|RTF_CLONING, 1396 (struct rtentry **)0); 1397 */ 1398 return 0; 1399 } 1400 1401 int 1402 in6_init_prefix_ltimes(struct nd_prefix *ndpr) 1403 { 1404 long time_second = time.tv_sec; 1405 1406 /* check if preferred lifetime > valid lifetime */ 1407 if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) { 1408 log(LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime" 1409 "(%d) is greater than valid lifetime(%d)\n", 1410 (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime); 1411 return (EINVAL); 1412 } 1413 if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME) 1414 ndpr->ndpr_preferred = 0; 1415 else 1416 ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime; 1417 if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME) 1418 ndpr->ndpr_expire = 0; 1419 else 1420 ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime; 1421 1422 return 0; 1423 } 1424 1425 static void 1426 in6_init_address_ltimes(struct nd_prefix *new, 1427 struct in6_addrlifetime *lt6, 1428 int update_vltime) 1429 { 1430 long time_second = time.tv_sec; 1431 1432 /* Valid lifetime must not be updated unless explicitly specified. */ 1433 if (update_vltime) { 1434 /* init ia6t_expire */ 1435 if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME) 1436 lt6->ia6t_expire = 0; 1437 else { 1438 lt6->ia6t_expire = time_second; 1439 lt6->ia6t_expire += lt6->ia6t_vltime; 1440 } 1441 /* Ensure addr lifetime <= prefix lifetime. */ 1442 if (new->ndpr_expire && lt6->ia6t_expire && 1443 new->ndpr_expire < lt6->ia6t_expire) 1444 lt6->ia6t_expire = new->ndpr_expire; 1445 } 1446 1447 /* init ia6t_preferred */ 1448 if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME) 1449 lt6->ia6t_preferred = 0; 1450 else { 1451 lt6->ia6t_preferred = time_second; 1452 lt6->ia6t_preferred += lt6->ia6t_pltime; 1453 } 1454 /* Ensure addr lifetime <= prefix lifetime. */ 1455 if (new->ndpr_preferred && lt6->ia6t_preferred 1456 && new->ndpr_preferred < lt6->ia6t_preferred) 1457 lt6->ia6t_preferred = new->ndpr_preferred; 1458 } 1459 1460 /* 1461 * Delete all the routing table entries that use the specified gateway. 1462 * XXX: this function causes search through all entries of routing table, so 1463 * it shouldn't be called when acting as a router. 1464 */ 1465 void 1466 rt6_flush(gateway, ifp) 1467 struct in6_addr *gateway; 1468 struct ifnet *ifp; 1469 { 1470 struct radix_node_head *rnh = rt_tables[AF_INET6]; 1471 int s = splsoftnet(); 1472 1473 /* We'll care only link-local addresses */ 1474 if (!IN6_IS_ADDR_LINKLOCAL(gateway)) { 1475 splx(s); 1476 return; 1477 } 1478 /* XXX: hack for KAME's link-local address kludge */ 1479 gateway->s6_addr16[1] = htons(ifp->if_index); 1480 1481 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway); 1482 splx(s); 1483 } 1484 1485 static int 1486 rt6_deleteroute(rn, arg) 1487 struct radix_node *rn; 1488 void *arg; 1489 { 1490 #define SIN6(s) ((struct sockaddr_in6 *)s) 1491 struct rtentry *rt = (struct rtentry *)rn; 1492 struct in6_addr *gate = (struct in6_addr *)arg; 1493 1494 if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6) 1495 return(0); 1496 1497 if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr)) 1498 return(0); 1499 1500 /* 1501 * We delete only host route. This means, in particular, we don't 1502 * delete default route. 1503 */ 1504 if ((rt->rt_flags & RTF_HOST) == 0) 1505 return(0); 1506 1507 return(rtrequest(RTM_DELETE, rt_key(rt), 1508 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0)); 1509 #undef SIN6 1510 } 1511 1512 int 1513 nd6_setdefaultiface(ifindex) 1514 int ifindex; 1515 { 1516 int error = 0; 1517 1518 if (ifindex < 0 || if_index < ifindex) 1519 return(EINVAL); 1520 1521 if (nd6_defifindex != ifindex) { 1522 nd6_defifindex = ifindex; 1523 if (nd6_defifindex > 0) 1524 nd6_defifp = ifindex2ifnet[nd6_defifindex]; 1525 else 1526 nd6_defifp = NULL; 1527 1528 /* 1529 * If the Default Router List is empty, install a route 1530 * to the specified interface as default or remove the default 1531 * route when the default interface becomes canceled. 1532 * The check for the queue is actually redundant, but 1533 * we do this here to avoid re-install the default route 1534 * if the list is NOT empty. 1535 */ 1536 if (TAILQ_FIRST(&nd_defrouter) == NULL) 1537 defrouter_select(); 1538 } 1539 1540 return(error); 1541 } 1542