nd6_rtr.c revision 64541
1/*	$FreeBSD: head/sys/netinet6/nd6_rtr.c 64541 2000-08-11 12:29:04Z itojun $	*/
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
64static struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *));
65static int prelist_add __P((struct nd_prefix *, struct nd_defrouter *));
66static struct nd_prefix *prefix_lookup __P((struct nd_prefix *));
67static struct in6_ifaddr *in6_ifadd __P((struct ifnet *, struct in6_addr *,
68			  struct in6_addr *, int));
69static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
70    struct nd_defrouter *));
71static void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *));
72static void pfxrtr_del __P((struct nd_pfxrouter *));
73static struct nd_pfxrouter *find_pfxlist_reachable_router
74    __P((struct nd_prefix *));
75static void nd6_detach_prefix __P((struct nd_prefix *));
76static void nd6_attach_prefix __P((struct nd_prefix *));
77static void defrouter_addifreq __P((struct ifnet *));
78#ifdef ND6_USE_RTSOCK
79static void defrouter_msg __P((int, struct rtentry *));
80#endif
81
82static void in6_init_address_ltimes __P((struct nd_prefix *ndpr,
83					 struct in6_addrlifetime *lt6,
84					 int update_vltime));
85
86static int rt6_deleteroute __P((struct radix_node *, void *));
87
88extern int nd6_recalc_reachtm_interval;
89
90struct ifnet *nd6_defifp;
91int 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 */
100void
101nd6_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 */
183void
184nd6_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
403freeit:
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. */
413static void
414defrouter_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
429void
430defrouter_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 */
461void
462defrouter_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
511struct nd_defrouter *
512defrouter_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
527void
528defrouter_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
566void
567defrtrlist_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 */
618void
619defrouter_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
688static struct nd_defrouter *
689defrtrlist_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
737static struct nd_pfxrouter *
738pfxrtr_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
752static void
753pfxrtr_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
770static void
771pfxrtr_del(pfr)
772	struct nd_pfxrouter *pfr;
773{
774	LIST_REMOVE(pfr, pfr_entry);
775	free(pfr, M_IP6NDP);
776}
777
778static struct nd_prefix *
779prefix_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
798static int
799prelist_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
835void
836prelist_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 */
864int
865prelist_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 */
1064struct nd_pfxrouter *
1065find_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 */
1098void
1099pfxlist_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
1141static void
1142nd6_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
1187static void
1188nd6_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
1242static struct in6_ifaddr *
1243in6_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
1393int
1394in6_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
1461int
1462in6_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
1484static void
1485in6_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 */
1523void
1524rt6_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
1543static int
1544rt6_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
1570int
1571nd6_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