nd6_rtr.c revision 64540
15766SN/A/*	$FreeBSD: head/sys/netinet6/nd6_rtr.c 64540 2000-08-11 12:27:07Z itojun $	*/
211166Sdarcy/*	$KAME: nd6_rtr.c,v 1.47 2000/08/08 08:58:42 jinmei Exp $	*/
35766SN/A
45766SN/A/*
55766SN/A * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
65766SN/A * All rights reserved.
75766SN/A *
85766SN/A * Redistribution and use in source and binary forms, with or without
95766SN/A * modification, are permitted provided that the following conditions
105766SN/A * are met:
115766SN/A * 1. Redistributions of source code must retain the above copyright
125766SN/A *    notice, this list of conditions and the following disclaimer.
135766SN/A * 2. Redistributions in binary form must reproduce the above copyright
145766SN/A *    notice, this list of conditions and the following disclaimer in the
155766SN/A *    documentation and/or other materials provided with the distribution.
165766SN/A * 3. Neither the name of the project nor the names of its contributors
175766SN/A *    may be used to endorse or promote products derived from this software
185766SN/A *    without specific prior written permission.
195766SN/A *
205766SN/A * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
215766SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
225766SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
235766SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
245766SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
255766SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
265766SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
275766SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
285766SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
295766SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
305766SN/A * SUCH DAMAGE.
315766SN/A */
325766SN/A
335766SN/A#include "opt_inet.h"
3411166Sdarcy#include "opt_inet6.h"
355766SN/A
365766SN/A#include <sys/param.h>
375766SN/A#include <sys/systm.h>
385766SN/A#include <sys/malloc.h>
395766SN/A#include <sys/mbuf.h>
405766SN/A#include <sys/socket.h>
415766SN/A#include <sys/sockio.h>
425766SN/A#include <sys/time.h>
435766SN/A#include <sys/errno.h>
445766SN/A#include <sys/syslog.h>
455766SN/A
465766SN/A#include <net/if.h>
475766SN/A#include <net/if_types.h>
485766SN/A#include <net/if_dl.h>
495766SN/A#include <net/route.h>
505766SN/A#include <net/radix.h>
515766SN/A
525766SN/A#include <netinet/in.h>
535766SN/A#include <netinet6/in6_var.h>
545766SN/A#include <netinet/ip6.h>
555766SN/A#include <netinet6/ip6_var.h>
565766SN/A#include <netinet6/nd6.h>
575766SN/A#include <netinet/icmp6.h>
585766SN/A#include <netinet6/scope6_var.h>
595766SN/A
605766SN/A#include <net/net_osdep.h>
615766SN/A
625766SN/A#define SDL(s)	((struct sockaddr_dl *)s)
635766SN/A
645766SN/Astatic struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *));
655766SN/Astatic int prelist_add __P((struct nd_prefix *, struct nd_defrouter *));
6611166Sdarcystatic struct nd_prefix *prefix_lookup __P((struct nd_prefix *));
675766SN/Astatic struct in6_ifaddr *in6_ifadd __P((struct ifnet *, struct in6_addr *,
685766SN/A			  struct in6_addr *, int));
695766SN/Astatic struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
705766SN/A    struct nd_defrouter *));
715766SN/Astatic void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *));
725766SN/Astatic void pfxrtr_del __P((struct nd_pfxrouter *));
735766SN/Astatic struct nd_pfxrouter *find_pfxlist_reachable_router
745766SN/A    __P((struct nd_prefix *));
755766SN/Astatic void nd6_detach_prefix __P((struct nd_prefix *));
765766SN/Astatic void nd6_attach_prefix __P((struct nd_prefix *));
775766SN/Astatic void defrouter_addifreq __P((struct ifnet *));
785766SN/A#ifdef ND6_USE_RTSOCK
795766SN/Astatic void defrouter_msg __P((int, struct rtentry *));
805766SN/A#endif
815766SN/A
825766SN/Astatic void in6_init_address_ltimes __P((struct nd_prefix *ndpr,
835766SN/A					 struct in6_addrlifetime *lt6,
845766SN/A					 int update_vltime));
855766SN/A
865766SN/Astatic int rt6_deleteroute __P((struct radix_node *, void *));
875766SN/A
885766SN/Aextern int nd6_recalc_reachtm_interval;
895766SN/A
905766SN/Astruct ifnet *nd6_defifp;
915766SN/Aint nd6_defifindex;
925766SN/A
935766SN/A/*
945766SN/A * Receive Router Solicitation Message - just for routers.
955766SN/A * Router solicitation/advertisement is mostly managed by userland program
965766SN/A * (rtadvd) so here we have no function like nd6_ra_output().
975766SN/A *
9811166Sdarcy * Based on RFC 2461
995766SN/A */
1005766SN/Avoid
1015766SN/And6_rs_input(m, off, icmp6len)
1025766SN/A	struct	mbuf *m;
1035766SN/A	int off, icmp6len;
1045766SN/A{
1055766SN/A	struct ifnet *ifp = m->m_pkthdr.rcvif;
1065766SN/A	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1075766SN/A	struct nd_router_solicit *nd_rs;
1085766SN/A	struct in6_addr saddr6 = ip6->ip6_src;
1095766SN/A#if 0
1105766SN/A	struct in6_addr daddr6 = ip6->ip6_dst;
1115766SN/A#endif
1125766SN/A	char *lladdr = NULL;
1135766SN/A	int lladdrlen = 0;
1145766SN/A#if 0
1155766SN/A	struct sockaddr_dl *sdl = (struct sockaddr_dl *)NULL;
1165766SN/A	struct llinfo_nd6 *ln = (struct llinfo_nd6 *)NULL;
1175766SN/A	struct rtentry *rt = NULL;
1185766SN/A	int is_newentry;
1195766SN/A#endif
1205766SN/A	union nd_opts ndopts;
1215766SN/A
1225766SN/A	/* If I'm not a router, ignore it. */
1235766SN/A	if (ip6_accept_rtadv != 0 || ip6_forwarding != 1)
1245766SN/A		goto freeit;
1255766SN/A
1265766SN/A	/* Sanity checks */
1275766SN/A	if (ip6->ip6_hlim != 255) {
1285766SN/A		log(LOG_ERR,
1295766SN/A		    "nd6_rs_input: invalid hlim %d\n", ip6->ip6_hlim);
13011166Sdarcy		goto freeit;
1315766SN/A	}
1325766SN/A
1335766SN/A	/*
1345766SN/A	 * Don't update the neighbor cache, if src = ::.
1355766SN/A	 * This indicates that the src has no IP address assigned yet.
1365766SN/A	 */
1375766SN/A	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
1385766SN/A		goto freeit;
1395766SN/A
1405766SN/A#ifndef PULLDOWN_TEST
1415766SN/A	IP6_EXTHDR_CHECK(m, off, icmp6len,);
1425766SN/A	nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
1435766SN/A#else
1445766SN/A	IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
1455766SN/A	if (nd_rs == NULL) {
1465766SN/A		icmp6stat.icp6s_tooshort++;
1475766SN/A		return;
1485766SN/A	}
1495766SN/A#endif
1505766SN/A
1515766SN/A	icmp6len -= sizeof(*nd_rs);
1525766SN/A	nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
1535766SN/A	if (nd6_options(&ndopts) < 0) {
1545766SN/A		log(LOG_INFO, "nd6_rs_input: invalid ND option, ignored\n");
1555766SN/A		goto freeit;
1565766SN/A	}
1575766SN/A
1585766SN/A	if (ndopts.nd_opts_src_lladdr) {
1595766SN/A		lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
1605766SN/A		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
1615766SN/A	}
1625766SN/A
1635766SN/A	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
1645766SN/A		log(LOG_INFO,
1655766SN/A		    "nd6_rs_input: lladdrlen mismatch for %s "
1665766SN/A		    "(if %d, RS packet %d)\n",
1675766SN/A			ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
1685766SN/A	}
1695766SN/A
1705766SN/A	nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
1715766SN/A
1725766SN/A freeit:
1735766SN/A	m_freem(m);
1745766SN/A}
1755766SN/A
1765766SN/A/*
1775766SN/A * Receive Router Advertisement Message.
1785766SN/A *
1795766SN/A * Based on RFC 2461
1805766SN/A * TODO: on-link bit on prefix information
1815766SN/A * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
1825766SN/A */
1835766SN/Avoid
1845766SN/And6_ra_input(m, off, icmp6len)
1855766SN/A	struct	mbuf *m;
1865766SN/A	int off, icmp6len;
1875766SN/A{
1885766SN/A	struct ifnet *ifp = m->m_pkthdr.rcvif;
1895766SN/A	struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
1905766SN/A	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1915766SN/A	struct nd_router_advert *nd_ra;
1925766SN/A	struct in6_addr saddr6 = ip6->ip6_src;
1935766SN/A#if 0
1945766SN/A	struct in6_addr daddr6 = ip6->ip6_dst;
1955766SN/A	int flags; /* = nd_ra->nd_ra_flags_reserved; */
1965766SN/A	int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0);
1975766SN/A	int is_other = ((flags & ND_RA_FLAG_OTHER) != 0);
1985766SN/A#endif
1995766SN/A	union nd_opts ndopts;
2005766SN/A	struct nd_defrouter *dr;
2015766SN/A
2025766SN/A	if (ip6_accept_rtadv == 0)
2035766SN/A		goto freeit;
2045766SN/A
2055766SN/A	if (ip6->ip6_hlim != 255) {
2065766SN/A		log(LOG_ERR,
2075766SN/A		    "nd6_ra_input: invalid hlim %d\n", ip6->ip6_hlim);
2085766SN/A		goto freeit;
2095766SN/A	}
2105766SN/A
2115766SN/A	if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
2125766SN/A		log(LOG_ERR,
2135766SN/A		    "nd6_ra_input: src %s is not link-local\n",
2145766SN/A		    ip6_sprintf(&saddr6));
2155766SN/A		goto freeit;
2165766SN/A	}
2175766SN/A
2185766SN/A#ifndef PULLDOWN_TEST
2195766SN/A	IP6_EXTHDR_CHECK(m, off, icmp6len,);
2205766SN/A	nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
2215766SN/A#else
2225766SN/A	IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
2235766SN/A	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		defrouter_msg(RTM_DELETE, oldrt);
550		if (oldrt->rt_refcnt <= 0) {
551			/*
552			 * XXX: borrowed from the RTM_DELETE case of
553			 * rtrequest().
554			 */
555			oldrt->rt_refcnt++;
556			rtfree(oldrt);
557		}
558	}
559
560	if (dofree)		/* XXX: necessary? */
561		free(dr, M_IP6NDP);
562}
563
564void
565defrtrlist_del(dr)
566	struct nd_defrouter *dr;
567{
568	struct nd_defrouter *deldr = NULL;
569	struct nd_prefix *pr;
570
571	/*
572	 * Flush all the routing table entries that use the router
573	 * as a next hop.
574	 */
575	if (!ip6_forwarding && ip6_accept_rtadv) {
576		/* above is a good condition? */
577		rt6_flush(&dr->rtaddr, dr->ifp);
578	}
579
580	if (dr == TAILQ_FIRST(&nd_defrouter))
581		deldr = dr;	/* The router is primary. */
582
583	TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
584
585	/*
586	 * Also delete all the pointers to the router in each prefix lists.
587	 */
588	for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
589		struct nd_pfxrouter *pfxrtr;
590		if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
591			pfxrtr_del(pfxrtr);
592	}
593	pfxlist_onlink_check();
594
595	/*
596	 * If the router is the primary one, choose a new one.
597	 * Note that defrouter_select() will remove the current gateway
598	 * from the routing table.
599	 */
600	if (deldr)
601		defrouter_select();
602
603	free(dr, M_IP6NDP);
604}
605
606/*
607 * Default Router Selection according to Section 6.3.6 of RFC 2461:
608 * 1) Routers that are reachable or probably reachable should be
609 *    preferred.
610 * 2) When no routers on the list are known to be reachable or
611 *    probably reachable, routers SHOULD be selected in a round-robin
612 *    fashion.
613 * 3) If the Default Router List is empty, assume that all
614 *    destinations are on-link.
615 */
616void
617defrouter_select()
618{
619	int s = splnet();
620	struct nd_defrouter *dr, anydr;
621	struct rtentry *rt = NULL;
622	struct llinfo_nd6 *ln = NULL;
623
624	/*
625	 * Search for a (probably) reachable router from the list.
626	 */
627	for (dr = TAILQ_FIRST(&nd_defrouter); dr;
628	     dr = TAILQ_NEXT(dr, dr_entry)) {
629		if ((rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
630		    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
631		    ND6_IS_LLINFO_PROBREACH(ln)) {
632			/* Got it, and move it to the head */
633			TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
634			TAILQ_INSERT_HEAD(&nd_defrouter, dr, dr_entry);
635			break;
636		}
637	}
638
639	if ((dr = TAILQ_FIRST(&nd_defrouter))) {
640		/*
641		 * De-install the previous default gateway and install
642		 * a new one.
643		 * Note that if there is no reachable router in the list,
644		 * the head entry will be used anyway.
645		 * XXX: do we have to check the current routing table entry?
646		 */
647		bzero(&anydr, sizeof(anydr));
648		defrouter_delreq(&anydr, 0);
649		defrouter_addreq(dr);
650	}
651	else {
652		/*
653		 * The Default Router List is empty, so install the default
654		 * route to an inteface.
655		 * XXX: The specification does not say this mechanism should
656		 * be restricted to hosts, but this would be not useful
657		 * (even harmful) for routers.
658		 */
659		if (!ip6_forwarding) {
660			/*
661			 * De-install the current default route
662			 * in advance.
663			 */
664			bzero(&anydr, sizeof(anydr));
665			defrouter_delreq(&anydr, 0);
666			if (nd6_defifp) {
667				/*
668				 * Install a route to the default interface
669				 * as default route.
670				 */
671				defrouter_addifreq(nd6_defifp);
672			}
673#ifdef ND6_DEBUG
674			else	/* noisy log? */
675				log(LOG_INFO, "defrouter_select: "
676				    "there's no default router and no default"
677				    " interface\n");
678#endif
679		}
680	}
681
682	splx(s);
683	return;
684}
685
686static struct nd_defrouter *
687defrtrlist_update(new)
688	struct nd_defrouter *new;
689{
690	struct nd_defrouter *dr, *n;
691	int s = splnet();
692
693	if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
694		/* entry exists */
695		if (new->rtlifetime == 0) {
696			defrtrlist_del(dr);
697			dr = NULL;
698		} else {
699			/* override */
700			dr->flags = new->flags; /* xxx flag check */
701			dr->rtlifetime = new->rtlifetime;
702			dr->expire = new->expire;
703		}
704		splx(s);
705		return(dr);
706	}
707
708	/* entry does not exist */
709	if (new->rtlifetime == 0) {
710		splx(s);
711		return(NULL);
712	}
713
714	n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
715	if (n == NULL) {
716		splx(s);
717		return(NULL);
718	}
719	bzero(n, sizeof(*n));
720	*n = *new;
721
722	/*
723	 * Insert the new router at the end of the Default Router List.
724	 * If there is no other router, install it anyway. Otherwise,
725	 * just continue to use the current default router.
726	 */
727	TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
728	if (TAILQ_FIRST(&nd_defrouter) == n)
729		defrouter_select();
730	splx(s);
731
732	return(n);
733}
734
735static struct nd_pfxrouter *
736pfxrtr_lookup(pr, dr)
737	struct nd_prefix *pr;
738	struct nd_defrouter *dr;
739{
740	struct nd_pfxrouter *search;
741
742	for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
743		if (search->router == dr)
744			break;
745	}
746
747	return(search);
748}
749
750static void
751pfxrtr_add(pr, dr)
752	struct nd_prefix *pr;
753	struct nd_defrouter *dr;
754{
755	struct nd_pfxrouter *new;
756
757	new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
758	if (new == NULL)
759		return;
760	bzero(new, sizeof(*new));
761	new->router = dr;
762
763	LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
764
765	pfxlist_onlink_check();
766}
767
768static void
769pfxrtr_del(pfr)
770	struct nd_pfxrouter *pfr;
771{
772	LIST_REMOVE(pfr, pfr_entry);
773	free(pfr, M_IP6NDP);
774}
775
776static struct nd_prefix *
777prefix_lookup(pr)
778	struct nd_prefix *pr;
779{
780	struct nd_prefix *search;
781
782	for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
783		if (pr->ndpr_ifp == search->ndpr_ifp &&
784		    pr->ndpr_plen == search->ndpr_plen &&
785		    in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
786					 &search->ndpr_prefix.sin6_addr,
787					 pr->ndpr_plen)
788		    ) {
789			break;
790		}
791	}
792
793	return(search);
794}
795
796static int
797prelist_add(pr, dr)
798	struct nd_prefix *pr;
799	struct nd_defrouter *dr;
800{
801	struct nd_prefix *new;
802	int i, s;
803
804	new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
805	if (new == NULL)
806		return ENOMEM;
807	bzero(new, sizeof(*new));
808	*new = *pr;
809
810	/* initilization */
811	new->ndpr_statef_onlink = pr->ndpr_statef_onlink;
812	LIST_INIT(&new->ndpr_advrtrs);
813	in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
814	/* make prefix in the canonical form */
815	for (i = 0; i < 4; i++)
816		new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
817			new->ndpr_mask.s6_addr32[i];
818
819	/* xxx ND_OPT_PI_FLAG_ONLINK processing */
820
821	s = splnet();
822	/* link ndpr_entry to nd_prefix list */
823	LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
824	splx(s);
825
826	if (dr) {
827		pfxrtr_add(new, dr);
828	}
829
830	return 0;
831}
832
833void
834prelist_remove(pr)
835	struct nd_prefix *pr;
836{
837	struct nd_pfxrouter *pfr, *next;
838	int s;
839
840	s = splnet();
841	/* unlink ndpr_entry from nd_prefix list */
842	LIST_REMOVE(pr, ndpr_entry);
843	splx(s);
844
845	/* free list of routers that adversed the prefix */
846	for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
847		next = pfr->pfr_next;
848
849		free(pfr, M_IP6NDP);
850	}
851	free(pr, M_IP6NDP);
852
853	pfxlist_onlink_check();
854}
855
856/*
857 * NOTE: We set address lifetime to keep
858 *	address lifetime <= prefix lifetime
859 * invariant.  This is to simplify on-link determination code.
860 * If onlink determination is udated, this routine may have to be updated too.
861 */
862int
863prelist_update(new, dr, m)
864	struct nd_prefix *new;
865	struct nd_defrouter *dr; /* may be NULL */
866	struct mbuf *m;
867{
868	struct in6_ifaddr *ia6 = NULL;
869	struct nd_prefix *pr;
870	int s = splnet();
871	int error = 0;
872	int auth;
873	struct in6_addrlifetime *lt6;
874	u_char onlink;	/* Mobile IPv6 */
875
876	auth = 0;
877	if (m) {
878		/*
879		 * Authenticity for NA consists authentication for
880		 * both IP header and IP datagrams, doesn't it ?
881		 */
882#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
883		auth = (m->m_flags & M_AUTHIPHDR
884		     && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
885#endif
886	}
887
888	if ((pr = prefix_lookup(new)) != NULL) {
889		if (pr->ndpr_ifp != new->ndpr_ifp) {
890			error = EADDRNOTAVAIL;
891			goto end;
892		}
893
894		/* update prefix information */
895		pr->ndpr_flags = new->ndpr_flags;
896		pr->ndpr_vltime = new->ndpr_vltime;
897		pr->ndpr_pltime = new->ndpr_pltime;
898		pr->ndpr_preferred = new->ndpr_preferred;
899		pr->ndpr_expire = new->ndpr_expire;
900
901		/*
902		 * RFC 2462 5.5.3 (d) or (e)
903		 * We got a prefix which we have seen in the past.
904		 */
905		if (!new->ndpr_raf_auto)
906			goto noautoconf1;
907
908		if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
909			ia6 = NULL;
910		else
911			ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
912
913		if (ia6 == NULL) {
914			/*
915			 * Special case:
916			 * (1) We have seen the prefix advertised before, but
917			 * we have never performed autoconfig for this prefix.
918			 * This is because Autonomous bit was 0 previously, or
919			 * autoconfig failed due to some other reasons.
920			 * (2) We have seen the prefix advertised before and
921			 * we have performed autoconfig in the past, but
922			 * we seem to have no interface address right now.
923			 * This is because the interface address have expired.
924			 *
925			 * This prefix is fresh, with respect to autoconfig
926			 * process.
927			 *
928			 * Add an address based on RFC 2462 5.5.3 (d).
929			 */
930			ia6 = in6_ifadd(pr->ndpr_ifp,
931				&pr->ndpr_prefix.sin6_addr, &pr->ndpr_addr,
932				new->ndpr_plen);
933			if (!ia6) {
934				error = EADDRNOTAVAIL;
935				log(LOG_ERR, "prelist_update: failed to add a "
936				    "new address\n");
937				goto noautoconf1;
938			}
939
940			lt6 = &ia6->ia6_lifetime;
941
942			/* address lifetime <= prefix lifetime */
943			lt6->ia6t_vltime = new->ndpr_vltime;
944			lt6->ia6t_pltime = new->ndpr_pltime;
945			in6_init_address_ltimes(new, lt6, 1);
946		} else {
947#define TWOHOUR		(120*60)
948			/*
949			 * We have seen the prefix before, and we have added
950			 * interface address in the past.  We still have
951			 * the interface address assigned.
952			 *
953			 * update address lifetime based on RFC 2462
954			 * 5.5.3 (e).
955			 */
956			int update = 0;
957
958			lt6 = &ia6->ia6_lifetime;
959
960#if 0	/* RFC 2462 5.5.3 (e) */
961			lt6->ia6t_pltime = new->ndpr_pltime;
962			if (TWOHOUR < new->ndpr_vltime
963			 || lt6pr->nd < new->ndpr_vltime) {
964				lt6->ia6t_vltime = new->ndpr_vltime;
965				update++;
966			} else if (auth
967				&& lt6->ia6t_vltime <= TWOHOUR0
968				&& new->ndpr_vltime <= lt6->ia6t_vltime) {
969				lt6->ia6t_vltime = new->ndpr_vltime;
970				update++;
971			} else {
972				lt6->ia6t_vltime = TWOHOUR;
973				update++;
974			}
975
976			/* 2 hour rule is not imposed for pref lifetime */
977			new->ndpr_apltime = new->ndpr_pltime;
978			lt6->ia6t_pltime = new->ndpr_pltime;
979#else	/* update from Jim Bound, (ipng 6712) */
980			if (TWOHOUR < new->ndpr_vltime
981			 || lt6->ia6t_vltime < new->ndpr_vltime) {
982				lt6->ia6t_vltime = new->ndpr_vltime;
983				update++;
984			} else if (auth) {
985				lt6->ia6t_vltime = new->ndpr_vltime;
986				update++;
987			}
988
989			/* jim bound rule is not imposed for pref lifetime */
990			lt6->ia6t_pltime = new->ndpr_pltime;
991#endif
992			in6_init_address_ltimes(new, lt6, update);
993		}
994
995 noautoconf1:
996
997#if 0
998		/* address lifetime expire processing, RFC 2462 5.5.4. */
999		if (pr->ndpr_preferred && pr->ndpr_preferred < time_second) {
1000			struct in6_ifaddr *ia6;
1001
1002			ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1003			if (ia6)
1004				ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
1005		}
1006#endif
1007
1008		onlink = pr->ndpr_statef_onlink;     /* Mobile IPv6 */
1009
1010		if (dr && pfxrtr_lookup(pr, dr) == NULL)
1011			pfxrtr_add(pr, dr);
1012
1013	} else {
1014		int error_tmp;
1015
1016		if (new->ndpr_vltime == 0) goto end;
1017
1018		bzero(&new->ndpr_addr, sizeof(struct in6_addr));
1019
1020		/*
1021		 * RFC 2462 5.5.3 (d)
1022		 * We got a fresh prefix.  Perform some sanity checks
1023		 * and add an interface address by appending interface ID
1024		 * to the advertised prefix.
1025		 */
1026		if (!new->ndpr_raf_auto)
1027			goto noautoconf2;
1028
1029		ia6 = in6_ifadd(new->ndpr_ifp, &new->ndpr_prefix.sin6_addr,
1030			  &new->ndpr_addr, new->ndpr_plen);
1031		if (!ia6) {
1032			error = EADDRNOTAVAIL;
1033			log(LOG_ERR, "prelist_update: "
1034				"failed to add a new address\n");
1035			goto noautoconf2;
1036		}
1037		/* set onlink bit if an interface route is configured */
1038		new->ndpr_statef_onlink = (ia6->ia_flags & IFA_ROUTE) ? 1 : 0;
1039
1040		lt6 = &ia6->ia6_lifetime;
1041
1042		/* address lifetime <= prefix lifetime */
1043		lt6->ia6t_vltime = new->ndpr_vltime;
1044		lt6->ia6t_pltime = new->ndpr_pltime;
1045		in6_init_address_ltimes(new, lt6, 1);
1046
1047 noautoconf2:
1048		error_tmp = prelist_add(new, dr);
1049		error = error_tmp ? error_tmp : error;
1050	}
1051
1052 end:
1053	splx(s);
1054	return error;
1055}
1056
1057/*
1058 * A supplement function used in the on-link detection below;
1059 * detect if a given prefix has a (probably) reachable advertising router.
1060 * XXX: lengthy function name...
1061 */
1062struct nd_pfxrouter *
1063find_pfxlist_reachable_router(pr)
1064	struct nd_prefix *pr;
1065{
1066	struct nd_pfxrouter *pfxrtr;
1067	struct rtentry *rt;
1068	struct llinfo_nd6 *ln;
1069
1070	for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1071	     pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1072		if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
1073				     pfxrtr->router->ifp)) &&
1074		    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
1075		    ND6_IS_LLINFO_PROBREACH(ln))
1076			break;	/* found */
1077	}
1078
1079	return(pfxrtr);
1080
1081}
1082
1083/*
1084 * Check if each prefix in the prefix list has at least one available router
1085 * that advertised the prefix (A router is "available" if its neighbor cache
1086 * entry has reachable or probably reachable).
1087 * If the check fails, the prefix may be off-link, because, for example,
1088 * we have moved from the network but the lifetime of the prefix has not
1089 * been expired yet. So we should not use the prefix if there is another
1090 * prefix that has an available router.
1091 * But if there is no prefix that has an available router, we still regards
1092 * all the prefixes as on-link. This is because we can't tell if all the
1093 * routers are simply dead or if we really moved from the network and there
1094 * is no router around us.
1095 */
1096void
1097pfxlist_onlink_check()
1098{
1099	struct nd_prefix *pr;
1100
1101	/*
1102	 * Check if there is a prefix that has a reachable advertising
1103	 * router.
1104	 */
1105	for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1106		if (find_pfxlist_reachable_router(pr))
1107			break;
1108	}
1109
1110	if (pr) {
1111		/*
1112		 * There is at least one prefix that has a reachable router.
1113		 * First, detach prefixes which has no reachable advertising
1114		 * router and then attach other prefixes.
1115		 * The order is important since an attached prefix and a
1116		 * detached prefix may have a same interface route.
1117		 */
1118		for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1119			if (find_pfxlist_reachable_router(pr) == NULL &&
1120			    pr->ndpr_statef_onlink) {
1121				pr->ndpr_statef_onlink = 0;
1122				nd6_detach_prefix(pr);
1123			}
1124		}
1125		for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1126			if (find_pfxlist_reachable_router(pr) &&
1127			    pr->ndpr_statef_onlink == 0)
1128				nd6_attach_prefix(pr);
1129		}
1130	}
1131	else {
1132		/* there is no prefix that has a reachable router */
1133		for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next)
1134			if (pr->ndpr_statef_onlink == 0)
1135				nd6_attach_prefix(pr);
1136	}
1137}
1138
1139static void
1140nd6_detach_prefix(pr)
1141	struct nd_prefix *pr;
1142{
1143	struct in6_ifaddr *ia6;
1144	struct sockaddr_in6 sa6, mask6;
1145
1146	/*
1147	 * Delete the interface route associated with the prefix.
1148	 */
1149	bzero(&sa6, sizeof(sa6));
1150	sa6.sin6_family = AF_INET6;
1151	sa6.sin6_len = sizeof(sa6);
1152	bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
1153	      sizeof(struct in6_addr));
1154	bzero(&mask6, sizeof(mask6));
1155	mask6.sin6_family = AF_INET6;
1156	mask6.sin6_len = sizeof(sa6);
1157	bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
1158	{
1159		int e;
1160
1161		e = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
1162			      (struct sockaddr *)&mask6, 0, NULL);
1163		if (e) {
1164			log(LOG_ERR,
1165			    "nd6_detach_prefix: failed to delete route: "
1166			    "%s/%d (errno = %d)\n",
1167			    ip6_sprintf(&sa6.sin6_addr),
1168			    pr->ndpr_plen,
1169			    e);
1170		}
1171	}
1172
1173	/*
1174	 * Mark the address derived from the prefix detached so that
1175	 * it won't be used as a source address for a new connection.
1176	 */
1177	if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
1178		ia6 = NULL;
1179	else
1180		ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1181	if (ia6)
1182		ia6->ia6_flags |= IN6_IFF_DETACHED;
1183}
1184
1185static void
1186nd6_attach_prefix(pr)
1187	struct nd_prefix *pr;
1188{
1189	struct ifaddr *ifa;
1190	struct in6_ifaddr *ia6;
1191
1192	/*
1193	 * Add the interface route associated with the prefix(if necessary)
1194	 * Should we consider if the L bit is set in pr->ndpr_flags?
1195	 */
1196	ifa = ifaof_ifpforaddr((struct sockaddr *)&pr->ndpr_prefix,
1197			       pr->ndpr_ifp);
1198	if (ifa == NULL) {
1199		log(LOG_ERR,
1200		    "nd6_attach_prefix: failed to find any ifaddr"
1201		    " to add route for a prefix(%s/%d)\n",
1202		    ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen);
1203	}
1204	else {
1205		int e;
1206		struct sockaddr_in6 mask6;
1207
1208		bzero(&mask6, sizeof(mask6));
1209		mask6.sin6_family = AF_INET6;
1210		mask6.sin6_len = sizeof(mask6);
1211		mask6.sin6_addr = pr->ndpr_mask;
1212		e = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1213			      ifa->ifa_addr, (struct sockaddr *)&mask6,
1214			      ifa->ifa_flags, NULL);
1215		if (e == 0)
1216			pr->ndpr_statef_onlink = 1;
1217		else {
1218			log(LOG_ERR,
1219			    "nd6_attach_prefix: failed to add route for"
1220			    " a prefix(%s/%d), errno = %d\n",
1221			    ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen, e);
1222		}
1223	}
1224
1225	/*
1226	 * Now the address derived from the prefix can be used as a source
1227	 * for a new connection, so clear the detached flag.
1228	 */
1229	if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
1230		ia6 = NULL;
1231	else
1232		ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1233	if (ia6) {
1234		ia6->ia6_flags &= ~IN6_IFF_DETACHED;
1235		if (pr->ndpr_statef_onlink)
1236			ia6->ia_flags |= IFA_ROUTE;
1237	}
1238}
1239
1240static struct in6_ifaddr *
1241in6_ifadd(ifp, in6, addr, prefixlen)
1242	struct ifnet *ifp;
1243	struct in6_addr *in6;
1244	struct in6_addr *addr;
1245	int prefixlen;	/* prefix len of the new prefix in "in6" */
1246{
1247	struct ifaddr *ifa;
1248	struct in6_ifaddr *ia, *ib, *oia;
1249	int s, error;
1250	struct in6_addr mask;
1251
1252	in6_len2mask(&mask, prefixlen);
1253
1254	/* find link-local address (will be interface ID) */
1255	ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);/* 0 is OK? */
1256	if (ifa)
1257		ib = (struct in6_ifaddr *)ifa;
1258	else
1259		return NULL;
1260
1261#if 0 /* don't care link local addr state, and always do DAD */
1262	/* if link-local address is not eligible, do not autoconfigure. */
1263	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
1264		printf("in6_ifadd: link-local address not ready\n");
1265		return NULL;
1266	}
1267#endif
1268
1269	/* prefixlen + ifidlen must be equal to 128 */
1270	if (prefixlen != in6_mask2len(&ib->ia_prefixmask.sin6_addr)) {
1271		log(LOG_ERR, "in6_ifadd: wrong prefixlen for %s"
1272			"(prefix=%d ifid=%d)\n", if_name(ifp),
1273			prefixlen,
1274			128 - in6_mask2len(&ib->ia_prefixmask.sin6_addr));
1275		return NULL;
1276	}
1277
1278	/* make ifaddr */
1279	ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_DONTWAIT);
1280	if (ia == NULL) {
1281		printf("ENOBUFS in in6_ifadd %d\n", __LINE__);
1282		return NULL;
1283	}
1284
1285	bzero((caddr_t)ia, sizeof(*ia));
1286	ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1287	if (ifp->if_flags & IFF_POINTOPOINT)
1288		ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
1289	else
1290		ia->ia_ifa.ifa_dstaddr = NULL;
1291	ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
1292	ia->ia_ifp = ifp;
1293
1294	/* link to in6_ifaddr */
1295	if ((oia = in6_ifaddr) != NULL) {
1296		for( ; oia->ia_next; oia = oia->ia_next)
1297			continue;
1298		oia->ia_next = ia;
1299	} else {
1300		/*
1301		 * This should be impossible, since we have at least one
1302		 * link-local address (see the beginning of this function).
1303		 * XXX: should we rather panic here?
1304		 */
1305		printf("in6_ifadd: in6_ifaddr is NULL (impossible!)\n");
1306		in6_ifaddr = ia;
1307	}
1308	/* gain a refcnt for the link from in6_ifaddr */
1309	ia->ia_ifa.ifa_refcnt++;
1310
1311	/* link to if_addrlist */
1312	TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1313	/* gain another refcnt for the link from if_addrlist */
1314	ia->ia_ifa.ifa_refcnt++;
1315
1316	/* new address */
1317	ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
1318	ia->ia_addr.sin6_family = AF_INET6;
1319	/* prefix */
1320	bcopy(in6, &ia->ia_addr.sin6_addr, sizeof(ia->ia_addr.sin6_addr));
1321	ia->ia_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1322	ia->ia_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
1323	ia->ia_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
1324	ia->ia_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1325	/* interface ID */
1326	ia->ia_addr.sin6_addr.s6_addr32[0]
1327		|= (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
1328	ia->ia_addr.sin6_addr.s6_addr32[1]
1329		|= (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
1330	ia->ia_addr.sin6_addr.s6_addr32[2]
1331		|= (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
1332	ia->ia_addr.sin6_addr.s6_addr32[3]
1333		|= (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
1334
1335	/* new prefix */
1336	ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1337	ia->ia_prefixmask.sin6_family = AF_INET6;
1338	bcopy(&mask, &ia->ia_prefixmask.sin6_addr,
1339		sizeof(ia->ia_prefixmask.sin6_addr));
1340
1341	/* same routine */
1342	ia->ia_ifa.ifa_rtrequest =
1343		(ifp->if_type == IFT_PPP) ? nd6_p2p_rtrequest : nd6_rtrequest;
1344	ia->ia_ifa.ifa_flags |= RTF_CLONING;
1345	ia->ia_ifa.ifa_metric = ifp->if_metric;
1346
1347	/* add interface route */
1348	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP|RTF_CLONING))) {
1349		log(LOG_NOTICE, "in6_ifadd: failed to add an interface route "
1350		    "for %s/%d on %s, errno = %d\n",
1351		    ip6_sprintf(&ia->ia_addr.sin6_addr), prefixlen,
1352		    if_name(ifp), error);
1353	} else
1354		ia->ia_flags |= IFA_ROUTE;
1355
1356	*addr = ia->ia_addr.sin6_addr;
1357
1358	if (ifp->if_flags & IFF_MULTICAST) {
1359		int error;	/* not used */
1360		struct in6_addr sol6;
1361
1362		/* join solicited node multicast address */
1363		bzero(&sol6, sizeof(sol6));
1364		sol6.s6_addr16[0] = htons(0xff02);
1365		sol6.s6_addr16[1] = htons(ifp->if_index);
1366		sol6.s6_addr32[1] = 0;
1367		sol6.s6_addr32[2] = htonl(1);
1368		sol6.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];
1369		sol6.s6_addr8[12] = 0xff;
1370		(void)in6_addmulti(&sol6, ifp, &error);
1371	}
1372
1373	ia->ia6_flags |= IN6_IFF_TENTATIVE;
1374
1375	/*
1376	 * To make the interface up. Only AF_INET6 in ia is used...
1377	 */
1378	s = splimp();
1379	if (ifp->if_ioctl && (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) {
1380		splx(s);
1381		return NULL;
1382	}
1383	splx(s);
1384
1385	/* Perform DAD, if needed. */
1386	nd6_dad_start((struct ifaddr *)ia, NULL);
1387
1388	return ia;
1389}
1390
1391int
1392in6_ifdel(ifp, in6)
1393	struct ifnet *ifp;
1394	struct in6_addr *in6;
1395{
1396	struct in6_ifaddr *ia = (struct in6_ifaddr *)NULL;
1397	struct in6_ifaddr *oia = (struct in6_ifaddr *)NULL;
1398
1399	if (!ifp)
1400		return -1;
1401
1402	ia = in6ifa_ifpwithaddr(ifp, in6);
1403	if (!ia)
1404		return -1;
1405
1406	if (ifp->if_flags & IFF_MULTICAST) {
1407		/*
1408		 * delete solicited multicast addr for deleting host id
1409		 */
1410		struct in6_multi *in6m;
1411		struct in6_addr llsol;
1412		bzero(&llsol, sizeof(struct in6_addr));
1413		llsol.s6_addr16[0] = htons(0xff02);
1414		llsol.s6_addr16[1] = htons(ifp->if_index);
1415		llsol.s6_addr32[1] = 0;
1416		llsol.s6_addr32[2] = htonl(1);
1417		llsol.s6_addr32[3] =
1418				ia->ia_addr.sin6_addr.s6_addr32[3];
1419		llsol.s6_addr8[12] = 0xff;
1420
1421		IN6_LOOKUP_MULTI(llsol, ifp, in6m);
1422		if (in6m)
1423			in6_delmulti(in6m);
1424	}
1425
1426	if (ia->ia_flags & IFA_ROUTE) {
1427		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1428		ia->ia_flags &= ~IFA_ROUTE;
1429	}
1430
1431	TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1432	IFAFREE(&ia->ia_ifa);
1433
1434	/* lladdr is never deleted */
1435	oia = ia;
1436	if (oia == (ia = in6_ifaddr))
1437		in6_ifaddr = ia->ia_next;
1438	else {
1439		while (ia->ia_next && (ia->ia_next != oia))
1440			ia = ia->ia_next;
1441		if (ia->ia_next)
1442			ia->ia_next = oia->ia_next;
1443		else
1444			return -1;
1445	}
1446
1447	IFAFREE((&oia->ia_ifa));
1448/* xxx
1449	rtrequest(RTM_DELETE,
1450		  (struct sockaddr *)&ia->ia_addr,
1451		  (struct sockaddr *)0
1452		  (struct sockaddr *)&ia->ia_prefixmask,
1453		  RTF_UP|RTF_CLONING,
1454		  (struct rtentry **)0);
1455*/
1456	return 0;
1457}
1458
1459int
1460in6_init_prefix_ltimes(struct nd_prefix *ndpr)
1461{
1462
1463	/* check if preferred lifetime > valid lifetime */
1464	if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
1465		log(LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime"
1466		    "(%d) is greater than valid lifetime(%d)\n",
1467		    (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime);
1468		return (EINVAL);
1469	}
1470	if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
1471		ndpr->ndpr_preferred = 0;
1472	else
1473		ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime;
1474	if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
1475		ndpr->ndpr_expire = 0;
1476	else
1477		ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
1478
1479	return 0;
1480}
1481
1482static void
1483in6_init_address_ltimes(struct nd_prefix *new,
1484			struct in6_addrlifetime *lt6,
1485			int update_vltime)
1486{
1487
1488	/* Valid lifetime must not be updated unless explicitly specified. */
1489	if (update_vltime) {
1490		/* init ia6t_expire */
1491		if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
1492			lt6->ia6t_expire = 0;
1493		else {
1494			lt6->ia6t_expire = time_second;
1495			lt6->ia6t_expire += lt6->ia6t_vltime;
1496		}
1497		/* Ensure addr lifetime <= prefix lifetime. */
1498		if (new->ndpr_expire && lt6->ia6t_expire &&
1499		    new->ndpr_expire < lt6->ia6t_expire)
1500			lt6->ia6t_expire = new->ndpr_expire;
1501	}
1502
1503	/* init ia6t_preferred */
1504	if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1505		lt6->ia6t_preferred = 0;
1506	else {
1507		lt6->ia6t_preferred = time_second;
1508		lt6->ia6t_preferred += lt6->ia6t_pltime;
1509	}
1510	 /* Ensure addr lifetime <= prefix lifetime. */
1511	if (new->ndpr_preferred && lt6->ia6t_preferred
1512	    && new->ndpr_preferred < lt6->ia6t_preferred)
1513		lt6->ia6t_preferred = new->ndpr_preferred;
1514}
1515
1516/*
1517 * Delete all the routing table entries that use the specified gateway.
1518 * XXX: this function causes search through all entries of routing table, so
1519 * it shouldn't be called when acting as a router.
1520 */
1521void
1522rt6_flush(gateway, ifp)
1523    struct in6_addr *gateway;
1524    struct ifnet *ifp;
1525{
1526	struct radix_node_head *rnh = rt_tables[AF_INET6];
1527	int s = splnet();
1528
1529	/* We'll care only link-local addresses */
1530	if (!IN6_IS_ADDR_LINKLOCAL(gateway)) {
1531		splx(s);
1532		return;
1533	}
1534	/* XXX: hack for KAME's link-local address kludge */
1535	gateway->s6_addr16[1] = htons(ifp->if_index);
1536
1537	rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
1538	splx(s);
1539}
1540
1541static int
1542rt6_deleteroute(rn, arg)
1543	struct radix_node *rn;
1544	void *arg;
1545{
1546#define SIN6(s)	((struct sockaddr_in6 *)s)
1547	struct rtentry *rt = (struct rtentry *)rn;
1548	struct in6_addr *gate = (struct in6_addr *)arg;
1549
1550	if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
1551		return(0);
1552
1553	if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr))
1554		return(0);
1555
1556	/*
1557	 * We delete only host route. This means, in particular, we don't
1558	 * delete default route.
1559	 */
1560	if ((rt->rt_flags & RTF_HOST) == 0)
1561		return(0);
1562
1563	return(rtrequest(RTM_DELETE, rt_key(rt),
1564			 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0));
1565#undef SIN6
1566}
1567
1568int
1569nd6_setdefaultiface(ifindex)
1570	int ifindex;
1571{
1572	int error = 0;
1573
1574	if (ifindex < 0 || if_index < ifindex)
1575		return(EINVAL);
1576
1577	if (nd6_defifindex != ifindex) {
1578		nd6_defifindex = ifindex;
1579		if (nd6_defifindex > 0)
1580			nd6_defifp = ifindex2ifnet[nd6_defifindex];
1581		else
1582			nd6_defifp = NULL;
1583
1584		/*
1585		 * If the Default Router List is empty, install a route
1586		 * to the specified interface as default or remove the default
1587		 * route when the default interface becomes canceled.
1588		 * The check for the queue is actually redundant, but
1589		 * we do this here to avoid re-install the default route
1590		 * if the list is NOT empty.
1591		 */
1592		if (TAILQ_FIRST(&nd_defrouter) == NULL)
1593			defrouter_select();
1594
1595		/*
1596		 * Our current implementation assumes one-to-one maping between
1597		 * interfaces and links, so it would be natural to use the
1598		 * default interface as the default link.
1599		 */
1600		scope6_setdefault(nd6_defifp);
1601	}
1602
1603	return(error);
1604}
1605