xref: /freebsd/sys/netinet6/nd6_rtr.c (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
1 /*	$FreeBSD$	*/
2 /*	$KAME: nd6_rtr.c,v 1.43 2000/07/02 23:19:59 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 "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 			oldrt->rt_refcnt++; /* XXX */
554 		rtfree(oldrt);
555 	}
556 
557 	if (dofree)		/* XXX: necessary? */
558 		free(dr, M_IP6NDP);
559 }
560 
561 void
562 defrtrlist_del(dr)
563 	struct nd_defrouter *dr;
564 {
565 	struct nd_defrouter *deldr = NULL;
566 	struct nd_prefix *pr;
567 
568 	/*
569 	 * Flush all the routing table entries that use the router
570 	 * as a next hop.
571 	 */
572 	if (!ip6_forwarding && ip6_accept_rtadv) {
573 		/* above is a good condition? */
574 		rt6_flush(&dr->rtaddr, dr->ifp);
575 	}
576 
577 	if (dr == TAILQ_FIRST(&nd_defrouter))
578 		deldr = dr;	/* The router is primary. */
579 
580 	TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
581 
582 	/*
583 	 * Also delete all the pointers to the router in each prefix lists.
584 	 */
585 	for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
586 		struct nd_pfxrouter *pfxrtr;
587 		if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
588 			pfxrtr_del(pfxrtr);
589 	}
590 	pfxlist_onlink_check();
591 
592 	/*
593 	 * If the router is the primary one, choose a new one.
594 	 * Note that defrouter_select() will remove the current gateway
595 	 * from the routing table.
596 	 */
597 	if (deldr)
598 		defrouter_select();
599 
600 	free(dr, M_IP6NDP);
601 }
602 
603 /*
604  * Default Router Selection according to Section 6.3.6 of RFC 2461:
605  * 1) Routers that are reachable or probably reachable should be
606  *    preferred.
607  * 2) When no routers on the list are known to be reachable or
608  *    probably reachable, routers SHOULD be selected in a round-robin
609  *    fashion.
610  * 3) If the Default Router List is empty, assume that all
611  *    destinations are on-link.
612  */
613 void
614 defrouter_select()
615 {
616 	int s = splnet();
617 	struct nd_defrouter *dr, anydr;
618 	struct rtentry *rt = NULL;
619 	struct llinfo_nd6 *ln = NULL;
620 
621 	/*
622 	 * Search for a (probably) reachable router from the list.
623 	 */
624 	for (dr = TAILQ_FIRST(&nd_defrouter); dr;
625 	     dr = TAILQ_NEXT(dr, dr_entry)) {
626 		if ((rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
627 		    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
628 		    ND6_IS_LLINFO_PROBREACH(ln)) {
629 			/* Got it, and move it to the head */
630 			TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
631 			TAILQ_INSERT_HEAD(&nd_defrouter, dr, dr_entry);
632 			break;
633 		}
634 	}
635 
636 	if ((dr = TAILQ_FIRST(&nd_defrouter))) {
637 		/*
638 		 * De-install the previous default gateway and install
639 		 * a new one.
640 		 * Note that if there is no reachable router in the list,
641 		 * the head entry will be used anyway.
642 		 * XXX: do we have to check the current routing table entry?
643 		 */
644 		bzero(&anydr, sizeof(anydr));
645 		defrouter_delreq(&anydr, 0);
646 		defrouter_addreq(dr);
647 	}
648 	else {
649 		/*
650 		 * The Default Router List is empty, so install the default
651 		 * route to an inteface.
652 		 * XXX: The specification does not say this mechanism should
653 		 * be restricted to hosts, but this would be not useful
654 		 * (even harmful) for routers.
655 		 */
656 		if (!ip6_forwarding) {
657 			/*
658 			 * De-install the current default route
659 			 * in advance.
660 			 */
661 			bzero(&anydr, sizeof(anydr));
662 			defrouter_delreq(&anydr, 0);
663 			if (nd6_defifp) {
664 				/*
665 				 * Install a route to the default interface
666 				 * as default route.
667 				 */
668 				defrouter_addifreq(nd6_defifp);
669 			}
670 #ifdef ND6_DEBUG
671 			else	/* noisy log? */
672 				log(LOG_INFO, "defrouter_select: "
673 				    "there's no default router and no default"
674 				    " interface\n");
675 #endif
676 		}
677 	}
678 
679 	splx(s);
680 	return;
681 }
682 
683 static struct nd_defrouter *
684 defrtrlist_update(new)
685 	struct nd_defrouter *new;
686 {
687 	struct nd_defrouter *dr, *n;
688 	int s = splnet();
689 
690 	if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
691 		/* entry exists */
692 		if (new->rtlifetime == 0) {
693 			defrtrlist_del(dr);
694 			dr = NULL;
695 		} else {
696 			/* override */
697 			dr->flags = new->flags; /* xxx flag check */
698 			dr->rtlifetime = new->rtlifetime;
699 			dr->expire = new->expire;
700 		}
701 		splx(s);
702 		return(dr);
703 	}
704 
705 	/* entry does not exist */
706 	if (new->rtlifetime == 0) {
707 		splx(s);
708 		return(NULL);
709 	}
710 
711 	n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
712 	if (n == NULL) {
713 		splx(s);
714 		return(NULL);
715 	}
716 	bzero(n, sizeof(*n));
717 	*n = *new;
718 
719 	/*
720 	 * Insert the new router at the end of the Default Router List.
721 	 * If there is no other router, install it anyway. Otherwise,
722 	 * just continue to use the current default router.
723 	 */
724 	TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
725 	if (TAILQ_FIRST(&nd_defrouter) == n)
726 		defrouter_select();
727 	splx(s);
728 
729 	return(n);
730 }
731 
732 static struct nd_pfxrouter *
733 pfxrtr_lookup(pr, dr)
734 	struct nd_prefix *pr;
735 	struct nd_defrouter *dr;
736 {
737 	struct nd_pfxrouter *search;
738 
739 	for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
740 		if (search->router == dr)
741 			break;
742 	}
743 
744 	return(search);
745 }
746 
747 static void
748 pfxrtr_add(pr, dr)
749 	struct nd_prefix *pr;
750 	struct nd_defrouter *dr;
751 {
752 	struct nd_pfxrouter *new;
753 
754 	new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
755 	if (new == NULL)
756 		return;
757 	bzero(new, sizeof(*new));
758 	new->router = dr;
759 
760 	LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
761 
762 	pfxlist_onlink_check();
763 }
764 
765 static void
766 pfxrtr_del(pfr)
767 	struct nd_pfxrouter *pfr;
768 {
769 	LIST_REMOVE(pfr, pfr_entry);
770 	free(pfr, M_IP6NDP);
771 }
772 
773 static struct nd_prefix *
774 prefix_lookup(pr)
775 	struct nd_prefix *pr;
776 {
777 	struct nd_prefix *search;
778 
779 	for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
780 		if (pr->ndpr_ifp == search->ndpr_ifp &&
781 		    pr->ndpr_plen == search->ndpr_plen &&
782 		    in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
783 					 &search->ndpr_prefix.sin6_addr,
784 					 pr->ndpr_plen)
785 		    ) {
786 			break;
787 		}
788 	}
789 
790 	return(search);
791 }
792 
793 static int
794 prelist_add(pr, dr)
795 	struct nd_prefix *pr;
796 	struct nd_defrouter *dr;
797 {
798 	struct nd_prefix *new;
799 	int i, s;
800 
801 	new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
802 	if (new == NULL)
803 		return ENOMEM;
804 	bzero(new, sizeof(*new));
805 	*new = *pr;
806 
807 	/* initilization */
808 	new->ndpr_statef_onlink = pr->ndpr_statef_onlink;
809 	LIST_INIT(&new->ndpr_advrtrs);
810 	in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
811 	/* make prefix in the canonical form */
812 	for (i = 0; i < 4; i++)
813 		new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
814 			new->ndpr_mask.s6_addr32[i];
815 
816 	/* xxx ND_OPT_PI_FLAG_ONLINK processing */
817 
818 	s = splnet();
819 	/* link ndpr_entry to nd_prefix list */
820 	LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
821 	splx(s);
822 
823 	if (dr) {
824 		pfxrtr_add(new, dr);
825 	}
826 
827 	return 0;
828 }
829 
830 void
831 prelist_remove(pr)
832 	struct nd_prefix *pr;
833 {
834 	struct nd_pfxrouter *pfr, *next;
835 	int s;
836 
837 	s = splnet();
838 	/* unlink ndpr_entry from nd_prefix list */
839 	LIST_REMOVE(pr, ndpr_entry);
840 	splx(s);
841 
842 	/* free list of routers that adversed the prefix */
843 	for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
844 		next = pfr->pfr_next;
845 
846 		free(pfr, M_IP6NDP);
847 	}
848 	free(pr, M_IP6NDP);
849 
850 	pfxlist_onlink_check();
851 }
852 
853 /*
854  * NOTE: We set address lifetime to keep
855  *	address lifetime <= prefix lifetime
856  * invariant.  This is to simplify on-link determination code.
857  * If onlink determination is udated, this routine may have to be updated too.
858  */
859 int
860 prelist_update(new, dr, m)
861 	struct nd_prefix *new;
862 	struct nd_defrouter *dr; /* may be NULL */
863 	struct mbuf *m;
864 {
865 	struct in6_ifaddr *ia6 = NULL;
866 	struct nd_prefix *pr;
867 	int s = splnet();
868 	int error = 0;
869 	int auth;
870 	struct in6_addrlifetime *lt6;
871 	u_char onlink;	/* Mobile IPv6 */
872 
873 	auth = 0;
874 	if (m) {
875 		/*
876 		 * Authenticity for NA consists authentication for
877 		 * both IP header and IP datagrams, doesn't it ?
878 		 */
879 #if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
880 		auth = (m->m_flags & M_AUTHIPHDR
881 		     && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
882 #endif
883 	}
884 
885 	if ((pr = prefix_lookup(new)) != NULL) {
886 		if (pr->ndpr_ifp != new->ndpr_ifp) {
887 			error = EADDRNOTAVAIL;
888 			goto end;
889 		}
890 
891 		/* update prefix information */
892 		pr->ndpr_flags = new->ndpr_flags;
893 		pr->ndpr_vltime = new->ndpr_vltime;
894 		pr->ndpr_pltime = new->ndpr_pltime;
895 		pr->ndpr_preferred = new->ndpr_preferred;
896 		pr->ndpr_expire = new->ndpr_expire;
897 
898 		/*
899 		 * RFC 2462 5.5.3 (d) or (e)
900 		 * We got a prefix which we have seen in the past.
901 		 */
902 		if (!new->ndpr_raf_auto)
903 			goto noautoconf1;
904 
905 		if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
906 			ia6 = NULL;
907 		else
908 			ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
909 
910 		if (ia6 == NULL) {
911 			/*
912 			 * Special case:
913 			 * (1) We have seen the prefix advertised before, but
914 			 * we have never performed autoconfig for this prefix.
915 			 * This is because Autonomous bit was 0 previously, or
916 			 * autoconfig failed due to some other reasons.
917 			 * (2) We have seen the prefix advertised before and
918 			 * we have performed autoconfig in the past, but
919 			 * we seem to have no interface address right now.
920 			 * This is because the interface address have expired.
921 			 *
922 			 * This prefix is fresh, with respect to autoconfig
923 			 * process.
924 			 *
925 			 * Add an address based on RFC 2462 5.5.3 (d).
926 			 */
927 			ia6 = in6_ifadd(pr->ndpr_ifp,
928 				&pr->ndpr_prefix.sin6_addr, &pr->ndpr_addr,
929 				new->ndpr_plen);
930 			if (!ia6) {
931 				error = EADDRNOTAVAIL;
932 				log(LOG_ERR, "prelist_update: failed to add a "
933 				    "new address\n");
934 				goto noautoconf1;
935 			}
936 
937 			lt6 = &ia6->ia6_lifetime;
938 
939 			/* address lifetime <= prefix lifetime */
940 			lt6->ia6t_vltime = new->ndpr_vltime;
941 			lt6->ia6t_pltime = new->ndpr_pltime;
942 			in6_init_address_ltimes(new, lt6, 1);
943 		} else {
944 #define TWOHOUR		(120*60)
945 			/*
946 			 * We have seen the prefix before, and we have added
947 			 * interface address in the past.  We still have
948 			 * the interface address assigned.
949 			 *
950 			 * update address lifetime based on RFC 2462
951 			 * 5.5.3 (e).
952 			 */
953 			int update = 0;
954 
955 			lt6 = &ia6->ia6_lifetime;
956 
957 #if 0	/* RFC 2462 5.5.3 (e) */
958 			lt6->ia6t_pltime = new->ndpr_pltime;
959 			if (TWOHOUR < new->ndpr_vltime
960 			 || lt6pr->nd < new->ndpr_vltime) {
961 				lt6->ia6t_vltime = new->ndpr_vltime;
962 				update++;
963 			} else if (auth
964 				&& lt6->ia6t_vltime <= TWOHOUR0
965 				&& new->ndpr_vltime <= lt6->ia6t_vltime) {
966 				lt6->ia6t_vltime = new->ndpr_vltime;
967 				update++;
968 			} else {
969 				lt6->ia6t_vltime = TWOHOUR;
970 				update++;
971 			}
972 
973 			/* 2 hour rule is not imposed for pref lifetime */
974 			new->ndpr_apltime = new->ndpr_pltime;
975 			lt6->ia6t_pltime = new->ndpr_pltime;
976 #else	/* update from Jim Bound, (ipng 6712) */
977 			if (TWOHOUR < new->ndpr_vltime
978 			 || lt6->ia6t_vltime < new->ndpr_vltime) {
979 				lt6->ia6t_vltime = new->ndpr_vltime;
980 				update++;
981 			} else if (auth) {
982 				lt6->ia6t_vltime = new->ndpr_vltime;
983 				update++;
984 			}
985 
986 			/* jim bound rule is not imposed for pref lifetime */
987 			lt6->ia6t_pltime = new->ndpr_pltime;
988 #endif
989 			in6_init_address_ltimes(new, lt6, update);
990 		}
991 
992  noautoconf1:
993 
994 #if 0
995 		/* address lifetime expire processing, RFC 2462 5.5.4. */
996 		if (pr->ndpr_preferred && pr->ndpr_preferred < time_second) {
997 			struct in6_ifaddr *ia6;
998 
999 			ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1000 			if (ia6)
1001 				ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
1002 		}
1003 #endif
1004 
1005 		onlink = pr->ndpr_statef_onlink;     /* Mobile IPv6 */
1006 
1007 		if (dr && pfxrtr_lookup(pr, dr) == NULL)
1008 			pfxrtr_add(pr, dr);
1009 
1010 	} else {
1011 		int error_tmp;
1012 
1013 		if (new->ndpr_vltime == 0) goto end;
1014 
1015 		bzero(&new->ndpr_addr, sizeof(struct in6_addr));
1016 
1017 		/*
1018 		 * RFC 2462 5.5.3 (d)
1019 		 * We got a fresh prefix.  Perform some sanity checks
1020 		 * and add an interface address by appending interface ID
1021 		 * to the advertised prefix.
1022 		 */
1023 		if (!new->ndpr_raf_auto)
1024 			goto noautoconf2;
1025 
1026 		ia6 = in6_ifadd(new->ndpr_ifp, &new->ndpr_prefix.sin6_addr,
1027 			  &new->ndpr_addr, new->ndpr_plen);
1028 		if (!ia6) {
1029 			error = EADDRNOTAVAIL;
1030 			log(LOG_ERR, "prelist_update: "
1031 				"failed to add a new address\n");
1032 			goto noautoconf2;
1033 		}
1034 		/* set onlink bit if an interface route is configured */
1035 		new->ndpr_statef_onlink = (ia6->ia_flags & IFA_ROUTE) ? 1 : 0;
1036 
1037 		lt6 = &ia6->ia6_lifetime;
1038 
1039 		/* address lifetime <= prefix lifetime */
1040 		lt6->ia6t_vltime = new->ndpr_vltime;
1041 		lt6->ia6t_pltime = new->ndpr_pltime;
1042 		in6_init_address_ltimes(new, lt6, 1);
1043 
1044  noautoconf2:
1045 		error_tmp = prelist_add(new, dr);
1046 		error = error_tmp ? error_tmp : error;
1047 	}
1048 
1049  end:
1050 	splx(s);
1051 	return error;
1052 }
1053 
1054 /*
1055  * A supplement function used in the on-link detection below;
1056  * detect if a given prefix has a (probably) reachable advertising router.
1057  * XXX: lengthy function name...
1058  */
1059 struct nd_pfxrouter *
1060 find_pfxlist_reachable_router(pr)
1061 	struct nd_prefix *pr;
1062 {
1063 	struct nd_pfxrouter *pfxrtr;
1064 	struct rtentry *rt;
1065 	struct llinfo_nd6 *ln;
1066 
1067 	for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1068 	     pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1069 		if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
1070 				     pfxrtr->router->ifp)) &&
1071 		    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
1072 		    ND6_IS_LLINFO_PROBREACH(ln))
1073 			break;	/* found */
1074 	}
1075 
1076 	return(pfxrtr);
1077 
1078 }
1079 
1080 /*
1081  * Check if each prefix in the prefix list has at least one available router
1082  * that advertised the prefix (A router is "available" if its neighbor cache
1083  * entry has reachable or probably reachable).
1084  * If the check fails, the prefix may be off-link, because, for example,
1085  * we have moved from the network but the lifetime of the prefix has not
1086  * been expired yet. So we should not use the prefix if there is another
1087  * prefix that has an available router.
1088  * But if there is no prefix that has an available router, we still regards
1089  * all the prefixes as on-link. This is because we can't tell if all the
1090  * routers are simply dead or if we really moved from the network and there
1091  * is no router around us.
1092  */
1093 void
1094 pfxlist_onlink_check()
1095 {
1096 	struct nd_prefix *pr;
1097 
1098 	/*
1099 	 * Check if there is a prefix that has a reachable advertising
1100 	 * router.
1101 	 */
1102 	for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1103 		if (find_pfxlist_reachable_router(pr))
1104 			break;
1105 	}
1106 
1107 	if (pr) {
1108 		/*
1109 		 * There is at least one prefix that has a reachable router.
1110 		 * First, detach prefixes which has no reachable advertising
1111 		 * router and then attach other prefixes.
1112 		 * The order is important since an attached prefix and a
1113 		 * detached prefix may have a same interface route.
1114 		 */
1115 		for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1116 			if (find_pfxlist_reachable_router(pr) == NULL &&
1117 			    pr->ndpr_statef_onlink) {
1118 				pr->ndpr_statef_onlink = 0;
1119 				nd6_detach_prefix(pr);
1120 			}
1121 		}
1122 		for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1123 			if (find_pfxlist_reachable_router(pr) &&
1124 			    pr->ndpr_statef_onlink == 0)
1125 				nd6_attach_prefix(pr);
1126 		}
1127 	}
1128 	else {
1129 		/* there is no prefix that has a reachable router */
1130 		for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next)
1131 			if (pr->ndpr_statef_onlink == 0)
1132 				nd6_attach_prefix(pr);
1133 	}
1134 }
1135 
1136 static void
1137 nd6_detach_prefix(pr)
1138 	struct nd_prefix *pr;
1139 {
1140 	struct in6_ifaddr *ia6;
1141 	struct sockaddr_in6 sa6, mask6;
1142 
1143 	/*
1144 	 * Delete the interface route associated with the prefix.
1145 	 */
1146 	bzero(&sa6, sizeof(sa6));
1147 	sa6.sin6_family = AF_INET6;
1148 	sa6.sin6_len = sizeof(sa6);
1149 	bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
1150 	      sizeof(struct in6_addr));
1151 	bzero(&mask6, sizeof(mask6));
1152 	mask6.sin6_family = AF_INET6;
1153 	mask6.sin6_len = sizeof(sa6);
1154 	bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
1155 	{
1156 		int e;
1157 
1158 		e = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
1159 			      (struct sockaddr *)&mask6, 0, NULL);
1160 		if (e) {
1161 			log(LOG_ERR,
1162 			    "nd6_detach_prefix: failed to delete route: "
1163 			    "%s/%d (errno = %d)\n",
1164 			    ip6_sprintf(&sa6.sin6_addr),
1165 			    pr->ndpr_plen,
1166 			    e);
1167 		}
1168 	}
1169 
1170 	/*
1171 	 * Mark the address derived from the prefix detached so that
1172 	 * it won't be used as a source address for a new connection.
1173 	 */
1174 	if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
1175 		ia6 = NULL;
1176 	else
1177 		ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1178 	if (ia6)
1179 		ia6->ia6_flags |= IN6_IFF_DETACHED;
1180 }
1181 
1182 static void
1183 nd6_attach_prefix(pr)
1184 	struct nd_prefix *pr;
1185 {
1186 	struct ifaddr *ifa;
1187 	struct in6_ifaddr *ia6;
1188 
1189 	/*
1190 	 * Add the interface route associated with the prefix(if necessary)
1191 	 * Should we consider if the L bit is set in pr->ndpr_flags?
1192 	 */
1193 	ifa = ifaof_ifpforaddr((struct sockaddr *)&pr->ndpr_prefix,
1194 			       pr->ndpr_ifp);
1195 	if (ifa == NULL) {
1196 		log(LOG_ERR,
1197 		    "nd6_attach_prefix: failed to find any ifaddr"
1198 		    " to add route for a prefix(%s/%d)\n",
1199 		    ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen);
1200 	}
1201 	else {
1202 		int e;
1203 		struct sockaddr_in6 mask6;
1204 
1205 		bzero(&mask6, sizeof(mask6));
1206 		mask6.sin6_family = AF_INET6;
1207 		mask6.sin6_len = sizeof(mask6);
1208 		mask6.sin6_addr = pr->ndpr_mask;
1209 		e = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1210 			      ifa->ifa_addr, (struct sockaddr *)&mask6,
1211 			      ifa->ifa_flags, NULL);
1212 		if (e == 0)
1213 			pr->ndpr_statef_onlink = 1;
1214 		else {
1215 			log(LOG_ERR,
1216 			    "nd6_attach_prefix: failed to add route for"
1217 			    " a prefix(%s/%d), errno = %d\n",
1218 			    ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen, e);
1219 		}
1220 	}
1221 
1222 	/*
1223 	 * Now the address derived from the prefix can be used as a source
1224 	 * for a new connection, so clear the detached flag.
1225 	 */
1226 	if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
1227 		ia6 = NULL;
1228 	else
1229 		ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1230 	if (ia6) {
1231 		ia6->ia6_flags &= ~IN6_IFF_DETACHED;
1232 		if (pr->ndpr_statef_onlink)
1233 			ia6->ia_flags |= IFA_ROUTE;
1234 	}
1235 }
1236 
1237 static struct in6_ifaddr *
1238 in6_ifadd(ifp, in6, addr, prefixlen)
1239 	struct ifnet *ifp;
1240 	struct in6_addr *in6;
1241 	struct in6_addr *addr;
1242 	int prefixlen;	/* prefix len of the new prefix in "in6" */
1243 {
1244 	struct ifaddr *ifa;
1245 	struct in6_ifaddr *ia, *ib, *oia;
1246 	int s, error;
1247 	struct in6_addr mask;
1248 
1249 	in6_len2mask(&mask, prefixlen);
1250 
1251 	/* find link-local address (will be interface ID) */
1252 	ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);/* 0 is OK? */
1253 	if (ifa)
1254 		ib = (struct in6_ifaddr *)ifa;
1255 	else
1256 		return NULL;
1257 
1258 #if 0 /* don't care link local addr state, and always do DAD */
1259 	/* if link-local address is not eligible, do not autoconfigure. */
1260 	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
1261 		printf("in6_ifadd: link-local address not ready\n");
1262 		return NULL;
1263 	}
1264 #endif
1265 
1266 	/* prefixlen + ifidlen must be equal to 128 */
1267 	if (prefixlen != in6_mask2len(&ib->ia_prefixmask.sin6_addr)) {
1268 		log(LOG_ERR, "in6_ifadd: wrong prefixlen for %s"
1269 			"(prefix=%d ifid=%d)\n", if_name(ifp),
1270 			prefixlen,
1271 			128 - in6_mask2len(&ib->ia_prefixmask.sin6_addr));
1272 		return NULL;
1273 	}
1274 
1275 	/* make ifaddr */
1276 	ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_DONTWAIT);
1277 	if (ia == NULL) {
1278 		printf("ENOBUFS in in6_ifadd %d\n", __LINE__);
1279 		return NULL;
1280 	}
1281 
1282 	bzero((caddr_t)ia, sizeof(*ia));
1283 	ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1284 	if (ifp->if_flags & IFF_POINTOPOINT)
1285 		ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
1286 	else
1287 		ia->ia_ifa.ifa_dstaddr = NULL;
1288 	ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
1289 	ia->ia_ifp = ifp;
1290 
1291 	/* link to in6_ifaddr */
1292 	if ((oia = in6_ifaddr) != NULL) {
1293 		for( ; oia->ia_next; oia = oia->ia_next)
1294 			continue;
1295 		oia->ia_next = ia;
1296 	} else {
1297 		/*
1298 		 * This should be impossible, since we have at least one
1299 		 * link-local address (see the beginning of this function).
1300 		 * XXX: should we rather panic here?
1301 		 */
1302 		printf("in6_ifadd: in6_ifaddr is NULL (impossible!)\n");
1303 		in6_ifaddr = ia;
1304 	}
1305 	/* gain a refcnt for the link from in6_ifaddr */
1306 	ia->ia_ifa.ifa_refcnt++;
1307 
1308 	/* link to if_addrlist */
1309 	TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1310 	/* gain another refcnt for the link from if_addrlist */
1311 	ia->ia_ifa.ifa_refcnt++;
1312 
1313 	/* new address */
1314 	ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
1315 	ia->ia_addr.sin6_family = AF_INET6;
1316 	/* prefix */
1317 	bcopy(in6, &ia->ia_addr.sin6_addr, sizeof(ia->ia_addr.sin6_addr));
1318 	ia->ia_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1319 	ia->ia_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
1320 	ia->ia_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
1321 	ia->ia_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1322 	/* interface ID */
1323 	ia->ia_addr.sin6_addr.s6_addr32[0]
1324 		|= (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
1325 	ia->ia_addr.sin6_addr.s6_addr32[1]
1326 		|= (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
1327 	ia->ia_addr.sin6_addr.s6_addr32[2]
1328 		|= (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
1329 	ia->ia_addr.sin6_addr.s6_addr32[3]
1330 		|= (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
1331 
1332 	/* new prefix */
1333 	ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1334 	ia->ia_prefixmask.sin6_family = AF_INET6;
1335 	bcopy(&mask, &ia->ia_prefixmask.sin6_addr,
1336 		sizeof(ia->ia_prefixmask.sin6_addr));
1337 
1338 	/* same routine */
1339 	ia->ia_ifa.ifa_rtrequest =
1340 		(ifp->if_type == IFT_PPP) ? nd6_p2p_rtrequest : nd6_rtrequest;
1341 	ia->ia_ifa.ifa_flags |= RTF_CLONING;
1342 	ia->ia_ifa.ifa_metric = ifp->if_metric;
1343 
1344 	/* add interface route */
1345 	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP|RTF_CLONING))) {
1346 		log(LOG_NOTICE, "in6_ifadd: failed to add an interface route "
1347 		    "for %s/%d on %s, errno = %d\n",
1348 		    ip6_sprintf(&ia->ia_addr.sin6_addr), prefixlen,
1349 		    if_name(ifp), error);
1350 	} else
1351 		ia->ia_flags |= IFA_ROUTE;
1352 
1353 	*addr = ia->ia_addr.sin6_addr;
1354 
1355 	if (ifp->if_flags & IFF_MULTICAST) {
1356 		int error;	/* not used */
1357 		struct in6_addr sol6;
1358 
1359 		/* join solicited node multicast address */
1360 		bzero(&sol6, sizeof(sol6));
1361 		sol6.s6_addr16[0] = htons(0xff02);
1362 		sol6.s6_addr16[1] = htons(ifp->if_index);
1363 		sol6.s6_addr32[1] = 0;
1364 		sol6.s6_addr32[2] = htonl(1);
1365 		sol6.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];
1366 		sol6.s6_addr8[12] = 0xff;
1367 		(void)in6_addmulti(&sol6, ifp, &error);
1368 	}
1369 
1370 	ia->ia6_flags |= IN6_IFF_TENTATIVE;
1371 
1372 	/*
1373 	 * To make the interface up. Only AF_INET6 in ia is used...
1374 	 */
1375 	s = splimp();
1376 	if (ifp->if_ioctl && (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) {
1377 		splx(s);
1378 		return NULL;
1379 	}
1380 	splx(s);
1381 
1382 	/* Perform DAD, if needed. */
1383 	nd6_dad_start((struct ifaddr *)ia, NULL);
1384 
1385 	return ia;
1386 }
1387 
1388 int
1389 in6_ifdel(ifp, in6)
1390 	struct ifnet *ifp;
1391 	struct in6_addr *in6;
1392 {
1393 	struct in6_ifaddr *ia = (struct in6_ifaddr *)NULL;
1394 	struct in6_ifaddr *oia = (struct in6_ifaddr *)NULL;
1395 
1396 	if (!ifp)
1397 		return -1;
1398 
1399 	ia = in6ifa_ifpwithaddr(ifp, in6);
1400 	if (!ia)
1401 		return -1;
1402 
1403 	if (ifp->if_flags & IFF_MULTICAST) {
1404 		/*
1405 		 * delete solicited multicast addr for deleting host id
1406 		 */
1407 		struct in6_multi *in6m;
1408 		struct in6_addr llsol;
1409 		bzero(&llsol, sizeof(struct in6_addr));
1410 		llsol.s6_addr16[0] = htons(0xff02);
1411 		llsol.s6_addr16[1] = htons(ifp->if_index);
1412 		llsol.s6_addr32[1] = 0;
1413 		llsol.s6_addr32[2] = htonl(1);
1414 		llsol.s6_addr32[3] =
1415 				ia->ia_addr.sin6_addr.s6_addr32[3];
1416 		llsol.s6_addr8[12] = 0xff;
1417 
1418 		IN6_LOOKUP_MULTI(llsol, ifp, in6m);
1419 		if (in6m)
1420 			in6_delmulti(in6m);
1421 	}
1422 
1423 	if (ia->ia_flags & IFA_ROUTE) {
1424 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1425 		ia->ia_flags &= ~IFA_ROUTE;
1426 	}
1427 
1428 	TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1429 	IFAFREE(&ia->ia_ifa);
1430 
1431 	/* lladdr is never deleted */
1432 	oia = ia;
1433 	if (oia == (ia = in6_ifaddr))
1434 		in6_ifaddr = ia->ia_next;
1435 	else {
1436 		while (ia->ia_next && (ia->ia_next != oia))
1437 			ia = ia->ia_next;
1438 		if (ia->ia_next)
1439 			ia->ia_next = oia->ia_next;
1440 		else
1441 			return -1;
1442 	}
1443 
1444 	IFAFREE((&oia->ia_ifa));
1445 /* xxx
1446 	rtrequest(RTM_DELETE,
1447 		  (struct sockaddr *)&ia->ia_addr,
1448 		  (struct sockaddr *)0
1449 		  (struct sockaddr *)&ia->ia_prefixmask,
1450 		  RTF_UP|RTF_CLONING,
1451 		  (struct rtentry **)0);
1452 */
1453 	return 0;
1454 }
1455 
1456 int
1457 in6_init_prefix_ltimes(struct nd_prefix *ndpr)
1458 {
1459 
1460 	/* check if preferred lifetime > valid lifetime */
1461 	if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
1462 		log(LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime"
1463 		    "(%d) is greater than valid lifetime(%d)\n",
1464 		    (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime);
1465 		return (EINVAL);
1466 	}
1467 	if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
1468 		ndpr->ndpr_preferred = 0;
1469 	else
1470 		ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime;
1471 	if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
1472 		ndpr->ndpr_expire = 0;
1473 	else
1474 		ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
1475 
1476 	return 0;
1477 }
1478 
1479 static void
1480 in6_init_address_ltimes(struct nd_prefix *new,
1481 			struct in6_addrlifetime *lt6,
1482 			int update_vltime)
1483 {
1484 
1485 	/* Valid lifetime must not be updated unless explicitly specified. */
1486 	if (update_vltime) {
1487 		/* init ia6t_expire */
1488 		if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
1489 			lt6->ia6t_expire = 0;
1490 		else {
1491 			lt6->ia6t_expire = time_second;
1492 			lt6->ia6t_expire += lt6->ia6t_vltime;
1493 		}
1494 		/* Ensure addr lifetime <= prefix lifetime. */
1495 		if (new->ndpr_expire && lt6->ia6t_expire &&
1496 		    new->ndpr_expire < lt6->ia6t_expire)
1497 			lt6->ia6t_expire = new->ndpr_expire;
1498 	}
1499 
1500 	/* init ia6t_preferred */
1501 	if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1502 		lt6->ia6t_preferred = 0;
1503 	else {
1504 		lt6->ia6t_preferred = time_second;
1505 		lt6->ia6t_preferred += lt6->ia6t_pltime;
1506 	}
1507 	 /* Ensure addr lifetime <= prefix lifetime. */
1508 	if (new->ndpr_preferred && lt6->ia6t_preferred
1509 	    && new->ndpr_preferred < lt6->ia6t_preferred)
1510 		lt6->ia6t_preferred = new->ndpr_preferred;
1511 }
1512 
1513 /*
1514  * Delete all the routing table entries that use the specified gateway.
1515  * XXX: this function causes search through all entries of routing table, so
1516  * it shouldn't be called when acting as a router.
1517  */
1518 void
1519 rt6_flush(gateway, ifp)
1520     struct in6_addr *gateway;
1521     struct ifnet *ifp;
1522 {
1523 	struct radix_node_head *rnh = rt_tables[AF_INET6];
1524 	int s = splnet();
1525 
1526 	/* We'll care only link-local addresses */
1527 	if (!IN6_IS_ADDR_LINKLOCAL(gateway)) {
1528 		splx(s);
1529 		return;
1530 	}
1531 	/* XXX: hack for KAME's link-local address kludge */
1532 	gateway->s6_addr16[1] = htons(ifp->if_index);
1533 
1534 	rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
1535 	splx(s);
1536 }
1537 
1538 static int
1539 rt6_deleteroute(rn, arg)
1540 	struct radix_node *rn;
1541 	void *arg;
1542 {
1543 #define SIN6(s)	((struct sockaddr_in6 *)s)
1544 	struct rtentry *rt = (struct rtentry *)rn;
1545 	struct in6_addr *gate = (struct in6_addr *)arg;
1546 
1547 	if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
1548 		return(0);
1549 
1550 	if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr))
1551 		return(0);
1552 
1553 	/*
1554 	 * We delete only host route. This means, in particular, we don't
1555 	 * delete default route.
1556 	 */
1557 	if ((rt->rt_flags & RTF_HOST) == 0)
1558 		return(0);
1559 
1560 	return(rtrequest(RTM_DELETE, rt_key(rt),
1561 			 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0));
1562 #undef SIN6
1563 }
1564 
1565 int
1566 nd6_setdefaultiface(ifindex)
1567 	int ifindex;
1568 {
1569 	int error = 0;
1570 
1571 	if (ifindex < 0 || if_index < ifindex)
1572 		return(EINVAL);
1573 
1574 	if (nd6_defifindex != ifindex) {
1575 		nd6_defifindex = ifindex;
1576 		if (nd6_defifindex > 0)
1577 			nd6_defifp = ifindex2ifnet[nd6_defifindex];
1578 		else
1579 			nd6_defifp = NULL;
1580 
1581 		/*
1582 		 * If the Default Router List is empty, install a route
1583 		 * to the specified interface as default or remove the default
1584 		 * route when the default interface becomes canceled.
1585 		 * The check for the queue is actually redundant, but
1586 		 * we do this here to avoid re-install the default route
1587 		 * if the list is NOT empty.
1588 		 */
1589 		if (TAILQ_FIRST(&nd_defrouter) == NULL)
1590 			defrouter_select();
1591 
1592 		/*
1593 		 * Our current implementation assumes one-to-one maping between
1594 		 * interfaces and links, so it would be natural to use the
1595 		 * default interface as the default link.
1596 		 */
1597 		scope6_setdefault(nd6_defifp);
1598 	}
1599 
1600 	return(error);
1601 }
1602