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