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