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