xref: /freebsd/sys/netinet6/nd6.c (revision 11d8451df3d33c5bb876da719ac65e8fc64154f6)
1caf43b02SWarner Losh /*-
282cd038dSYoshinobu Inoue  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
382cd038dSYoshinobu Inoue  * All rights reserved.
482cd038dSYoshinobu Inoue  *
582cd038dSYoshinobu Inoue  * Redistribution and use in source and binary forms, with or without
682cd038dSYoshinobu Inoue  * modification, are permitted provided that the following conditions
782cd038dSYoshinobu Inoue  * are met:
882cd038dSYoshinobu Inoue  * 1. Redistributions of source code must retain the above copyright
982cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer.
1082cd038dSYoshinobu Inoue  * 2. Redistributions in binary form must reproduce the above copyright
1182cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer in the
1282cd038dSYoshinobu Inoue  *    documentation and/or other materials provided with the distribution.
1382cd038dSYoshinobu Inoue  * 3. Neither the name of the project nor the names of its contributors
1482cd038dSYoshinobu Inoue  *    may be used to endorse or promote products derived from this software
1582cd038dSYoshinobu Inoue  *    without specific prior written permission.
1682cd038dSYoshinobu Inoue  *
1782cd038dSYoshinobu Inoue  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1882cd038dSYoshinobu Inoue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1982cd038dSYoshinobu Inoue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2082cd038dSYoshinobu Inoue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2182cd038dSYoshinobu Inoue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2282cd038dSYoshinobu Inoue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2382cd038dSYoshinobu Inoue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2482cd038dSYoshinobu Inoue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2582cd038dSYoshinobu Inoue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2682cd038dSYoshinobu Inoue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2782cd038dSYoshinobu Inoue  * SUCH DAMAGE.
28b48287a3SDavid E. O'Brien  *
29b48287a3SDavid E. O'Brien  *	$KAME: nd6.c,v 1.144 2001/05/24 07:44:00 itojun Exp $
3082cd038dSYoshinobu Inoue  */
3182cd038dSYoshinobu Inoue 
32b48287a3SDavid E. O'Brien #include <sys/cdefs.h>
33b48287a3SDavid E. O'Brien __FBSDID("$FreeBSD$");
34b48287a3SDavid E. O'Brien 
35686cdd19SJun-ichiro itojun Hagino #include "opt_inet.h"
36686cdd19SJun-ichiro itojun Hagino #include "opt_inet6.h"
37686cdd19SJun-ichiro itojun Hagino 
3882cd038dSYoshinobu Inoue #include <sys/param.h>
3982cd038dSYoshinobu Inoue #include <sys/systm.h>
4033841545SHajimu UMEMOTO #include <sys/callout.h>
4182cd038dSYoshinobu Inoue #include <sys/malloc.h>
4282cd038dSYoshinobu Inoue #include <sys/mbuf.h>
4382cd038dSYoshinobu Inoue #include <sys/socket.h>
4482cd038dSYoshinobu Inoue #include <sys/sockio.h>
4582cd038dSYoshinobu Inoue #include <sys/time.h>
4682cd038dSYoshinobu Inoue #include <sys/kernel.h>
47686cdd19SJun-ichiro itojun Hagino #include <sys/protosw.h>
4882cd038dSYoshinobu Inoue #include <sys/errno.h>
4982cd038dSYoshinobu Inoue #include <sys/syslog.h>
506e6b3f7cSQing Li #include <sys/lock.h>
516e6b3f7cSQing Li #include <sys/rwlock.h>
5282cd038dSYoshinobu Inoue #include <sys/queue.h>
5357f60867SMark Johnston #include <sys/sdt.h>
5433841545SHajimu UMEMOTO #include <sys/sysctl.h>
5582cd038dSYoshinobu Inoue 
5682cd038dSYoshinobu Inoue #include <net/if.h>
5776039bc8SGleb Smirnoff #include <net/if_var.h>
5831b3783cSHajimu UMEMOTO #include <net/if_arc.h>
5982cd038dSYoshinobu Inoue #include <net/if_dl.h>
6082cd038dSYoshinobu Inoue #include <net/if_types.h>
612049fdeeSMatthew N. Dodd #include <net/iso88025.h>
628e5fd461SMatthew N. Dodd #include <net/fddi.h>
6382cd038dSYoshinobu Inoue #include <net/route.h>
644b79449eSBjoern A. Zeeb #include <net/vnet.h>
6582cd038dSYoshinobu Inoue 
6682cd038dSYoshinobu Inoue #include <netinet/in.h>
6757f60867SMark Johnston #include <netinet/in_kdtrace.h>
686e6b3f7cSQing Li #include <net/if_llatbl.h>
696e6b3f7cSQing Li #define	L3_ADDR_SIN6(le)	((struct sockaddr_in6 *) L3_ADDR(le))
7082cd038dSYoshinobu Inoue #include <netinet/if_ether.h>
7182cd038dSYoshinobu Inoue #include <netinet6/in6_var.h>
72686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h>
7382cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h>
74a1f7e5f8SHajimu UMEMOTO #include <netinet6/scope6_var.h>
7582cd038dSYoshinobu Inoue #include <netinet6/nd6.h>
76a283298cSHiroki Sato #include <netinet6/in6_ifattach.h>
77686cdd19SJun-ichiro itojun Hagino #include <netinet/icmp6.h>
781db8d1f8SAna Kukec #include <netinet6/send.h>
7982cd038dSYoshinobu Inoue 
80743eee66SSUZUKI Shinsuke #include <sys/limits.h>
81743eee66SSUZUKI Shinsuke 
82aed55708SRobert Watson #include <security/mac/mac_framework.h>
83aed55708SRobert Watson 
8482cd038dSYoshinobu Inoue #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */
8582cd038dSYoshinobu Inoue #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */
8682cd038dSYoshinobu Inoue 
8747e8d432SGleb Smirnoff #define SIN6(s) ((const struct sockaddr_in6 *)(s))
8882cd038dSYoshinobu Inoue 
8982cea7e6SBjoern A. Zeeb /* timer values */
9082cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_prune)	= 1;	/* walk list every 1 seconds */
9182cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_delay)	= 5;	/* delay first probe time 5 second */
9282cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_umaxtries)	= 3;	/* maximum unicast query */
9382cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_mmaxtries)	= 3;	/* maximum multicast query */
9482cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_useloopback) = 1;	/* use loopback interface for
9582cea7e6SBjoern A. Zeeb 					 * local traffic */
9682cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_gctimer)	= (60 * 60 * 24); /* 1 day: garbage
9782cea7e6SBjoern A. Zeeb 					 * collection timer */
98686cdd19SJun-ichiro itojun Hagino 
99686cdd19SJun-ichiro itojun Hagino /* preventing too many loops in ND option parsing */
1003e288e62SDimitry Andric static VNET_DEFINE(int, nd6_maxndopt) = 10; /* max # of ND options allowed */
10182cea7e6SBjoern A. Zeeb 
10282cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_maxnudhint) = 0;	/* max # of subsequent upper
10382cea7e6SBjoern A. Zeeb 					 * layer hints */
1043e288e62SDimitry Andric static VNET_DEFINE(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved
10582cea7e6SBjoern A. Zeeb 					 * ND entries */
1061e77c105SRobert Watson #define	V_nd6_maxndopt			VNET(nd6_maxndopt)
1071e77c105SRobert Watson #define	V_nd6_maxqueuelen		VNET(nd6_maxqueuelen)
108686cdd19SJun-ichiro itojun Hagino 
10982cea7e6SBjoern A. Zeeb #ifdef ND6_DEBUG
11082cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_debug) = 1;
11182cea7e6SBjoern A. Zeeb #else
11282cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_debug) = 0;
11382cea7e6SBjoern A. Zeeb #endif
11433841545SHajimu UMEMOTO 
11582cd038dSYoshinobu Inoue /* for debugging? */
1166e6b3f7cSQing Li #if 0
11782cd038dSYoshinobu Inoue static int nd6_inuse, nd6_allocated;
1186e6b3f7cSQing Li #endif
11982cd038dSYoshinobu Inoue 
120eddfbb76SRobert Watson VNET_DEFINE(struct nd_drhead, nd_defrouter);
121eddfbb76SRobert Watson VNET_DEFINE(struct nd_prhead, nd_prefix);
12282cd038dSYoshinobu Inoue 
12382cea7e6SBjoern A. Zeeb VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND6_RECALC_REACHTM_INTERVAL;
1241e77c105SRobert Watson #define	V_nd6_recalc_reachtm_interval	VNET(nd6_recalc_reachtm_interval)
12544e33a07SMarko Zec 
1261db8d1f8SAna Kukec int	(*send_sendso_input_hook)(struct mbuf *, struct ifnet *, int, int);
1271db8d1f8SAna Kukec 
1286f56329aSXin LI static int nd6_is_new_addr_neighbor(struct sockaddr_in6 *,
1296f56329aSXin LI 	struct ifnet *);
1309233d8f3SDavid E. O'Brien static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
1319233d8f3SDavid E. O'Brien static void nd6_slowtimo(void *);
1329233d8f3SDavid E. O'Brien static int regen_tmpaddr(struct in6_ifaddr *);
1336e6b3f7cSQing Li static struct llentry *nd6_free(struct llentry *, int);
1349233d8f3SDavid E. O'Brien static void nd6_llinfo_timer(void *);
1356e6b3f7cSQing Li static void clear_llinfo_pqueue(struct llentry *);
136f6b84910SAlexander V. Chernikov static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
137d7968c29SAlexander V. Chernikov static int nd6_output_lle(struct ifnet *, struct ifnet *, struct mbuf *,
138d7968c29SAlexander V. Chernikov 	struct sockaddr_in6 *);
139abc1be90SAlexander V. Chernikov static int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *,
140abc1be90SAlexander V. Chernikov     struct sockaddr_in6 *);
14133841545SHajimu UMEMOTO 
1423e288e62SDimitry Andric static VNET_DEFINE(struct callout, nd6_slowtimo_ch);
1431e77c105SRobert Watson #define	V_nd6_slowtimo_ch		VNET(nd6_slowtimo_ch)
144eddfbb76SRobert Watson 
145eddfbb76SRobert Watson VNET_DEFINE(struct callout, nd6_timer_ch);
146eddfbb76SRobert Watson 
14782cd038dSYoshinobu Inoue void
1481272577eSXin LI nd6_init(void)
14982cd038dSYoshinobu Inoue {
15082cd038dSYoshinobu Inoue 
15144e33a07SMarko Zec 	LIST_INIT(&V_nd_prefix);
15244e33a07SMarko Zec 
153686cdd19SJun-ichiro itojun Hagino 	/* initialization of the default router list */
154603724d3SBjoern A. Zeeb 	TAILQ_INIT(&V_nd_defrouter);
15582cea7e6SBjoern A. Zeeb 
15682cd038dSYoshinobu Inoue 	/* start timer */
157603724d3SBjoern A. Zeeb 	callout_init(&V_nd6_slowtimo_ch, 0);
158603724d3SBjoern A. Zeeb 	callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
159f6dfe47aSMarko Zec 	    nd6_slowtimo, curvnet);
160d6ad6a86SMark Johnston 
161d6ad6a86SMark Johnston 	nd6_dad_init();
16282cd038dSYoshinobu Inoue }
16382cd038dSYoshinobu Inoue 
164bc29160dSMarko Zec #ifdef VIMAGE
165bc29160dSMarko Zec void
166bc29160dSMarko Zec nd6_destroy()
167bc29160dSMarko Zec {
168bc29160dSMarko Zec 
169bc29160dSMarko Zec 	callout_drain(&V_nd6_slowtimo_ch);
170bc29160dSMarko Zec 	callout_drain(&V_nd6_timer_ch);
171bc29160dSMarko Zec }
172bc29160dSMarko Zec #endif
173bc29160dSMarko Zec 
17431b1bfe1SHajimu UMEMOTO struct nd_ifinfo *
1751272577eSXin LI nd6_ifattach(struct ifnet *ifp)
17682cd038dSYoshinobu Inoue {
17731b1bfe1SHajimu UMEMOTO 	struct nd_ifinfo *nd;
17882cd038dSYoshinobu Inoue 
17939e19560SBjoern A. Zeeb 	nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO);
18031b1bfe1SHajimu UMEMOTO 	nd->initialized = 1;
18182cd038dSYoshinobu Inoue 
18231b1bfe1SHajimu UMEMOTO 	nd->chlim = IPV6_DEFHLIM;
18331b1bfe1SHajimu UMEMOTO 	nd->basereachable = REACHABLE_TIME;
18431b1bfe1SHajimu UMEMOTO 	nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
18531b1bfe1SHajimu UMEMOTO 	nd->retrans = RETRANS_TIMER;
186a283298cSHiroki Sato 
187a283298cSHiroki Sato 	nd->flags = ND6_IFF_PERFORMNUD;
188a283298cSHiroki Sato 
189af805644SHiroki Sato 	/* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL.
190af805644SHiroki Sato 	 * XXXHRS: Clear ND6_IFF_AUTO_LINKLOCAL on an IFT_BRIDGE interface by
191af805644SHiroki Sato 	 * default regardless of the V_ip6_auto_linklocal configuration to
192af805644SHiroki Sato 	 * give a reasonable default behavior.
193af805644SHiroki Sato 	 */
194af805644SHiroki Sato 	if ((V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) ||
195af805644SHiroki Sato 	    (ifp->if_flags & IFF_LOOPBACK))
196a283298cSHiroki Sato 		nd->flags |= ND6_IFF_AUTO_LINKLOCAL;
197af805644SHiroki Sato 	/*
198af805644SHiroki Sato 	 * A loopback interface does not need to accept RTADV.
199af805644SHiroki Sato 	 * XXXHRS: Clear ND6_IFF_ACCEPT_RTADV on an IFT_BRIDGE interface by
200af805644SHiroki Sato 	 * default regardless of the V_ip6_accept_rtadv configuration to
201af805644SHiroki Sato 	 * prevent the interface from accepting RA messages arrived
202af805644SHiroki Sato 	 * on one of the member interfaces with ND6_IFF_ACCEPT_RTADV.
203af805644SHiroki Sato 	 */
204af805644SHiroki Sato 	if (V_ip6_accept_rtadv &&
205af805644SHiroki Sato 	    !(ifp->if_flags & IFF_LOOPBACK) &&
206af805644SHiroki Sato 	    (ifp->if_type != IFT_BRIDGE))
207a283298cSHiroki Sato 			nd->flags |= ND6_IFF_ACCEPT_RTADV;
208e7fa8d0aSHiroki Sato 	if (V_ip6_no_radr && !(ifp->if_flags & IFF_LOOPBACK))
209e7fa8d0aSHiroki Sato 		nd->flags |= ND6_IFF_NO_RADR;
21031b1bfe1SHajimu UMEMOTO 
21131b1bfe1SHajimu UMEMOTO 	/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
21231b1bfe1SHajimu UMEMOTO 	nd6_setmtu0(ifp, nd);
21331b1bfe1SHajimu UMEMOTO 
21431b1bfe1SHajimu UMEMOTO 	return nd;
21531b1bfe1SHajimu UMEMOTO }
21631b1bfe1SHajimu UMEMOTO 
21731b1bfe1SHajimu UMEMOTO void
2181272577eSXin LI nd6_ifdetach(struct nd_ifinfo *nd)
21931b1bfe1SHajimu UMEMOTO {
22031b1bfe1SHajimu UMEMOTO 
22131b1bfe1SHajimu UMEMOTO 	free(nd, M_IP6NDP);
22282cd038dSYoshinobu Inoue }
22382cd038dSYoshinobu Inoue 
22482cd038dSYoshinobu Inoue /*
22582cd038dSYoshinobu Inoue  * Reset ND level link MTU. This function is called when the physical MTU
22682cd038dSYoshinobu Inoue  * changes, which means we might have to adjust the ND level MTU.
22782cd038dSYoshinobu Inoue  */
22882cd038dSYoshinobu Inoue void
2291272577eSXin LI nd6_setmtu(struct ifnet *ifp)
23082cd038dSYoshinobu Inoue {
23131b1bfe1SHajimu UMEMOTO 
23231b1bfe1SHajimu UMEMOTO 	nd6_setmtu0(ifp, ND_IFINFO(ifp));
23331b1bfe1SHajimu UMEMOTO }
23431b1bfe1SHajimu UMEMOTO 
23531b1bfe1SHajimu UMEMOTO /* XXX todo: do not maintain copy of ifp->if_mtu in ndi->maxmtu */
23631b1bfe1SHajimu UMEMOTO void
2371272577eSXin LI nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi)
23831b1bfe1SHajimu UMEMOTO {
23931b3783cSHajimu UMEMOTO 	u_int32_t omaxmtu;
24031b1bfe1SHajimu UMEMOTO 
24131b3783cSHajimu UMEMOTO 	omaxmtu = ndi->maxmtu;
24282cd038dSYoshinobu Inoue 
24382cd038dSYoshinobu Inoue 	switch (ifp->if_type) {
24431b3783cSHajimu UMEMOTO 	case IFT_ARCNET:
24531b3783cSHajimu UMEMOTO 		ndi->maxmtu = MIN(ARC_PHDS_MAXMTU, ifp->if_mtu); /* RFC2497 */
24682cd038dSYoshinobu Inoue 		break;
24782cd038dSYoshinobu Inoue 	case IFT_FDDI:
24831b3783cSHajimu UMEMOTO 		ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu); /* RFC2467 */
24982cd038dSYoshinobu Inoue 		break;
2502049fdeeSMatthew N. Dodd 	case IFT_ISO88025:
2512049fdeeSMatthew N. Dodd 		 ndi->maxmtu = MIN(ISO88025_MAX_MTU, ifp->if_mtu);
2522049fdeeSMatthew N. Dodd 		 break;
25382cd038dSYoshinobu Inoue 	default:
25482cd038dSYoshinobu Inoue 		ndi->maxmtu = ifp->if_mtu;
25582cd038dSYoshinobu Inoue 		break;
25682cd038dSYoshinobu Inoue 	}
25782cd038dSYoshinobu Inoue 
25882cd038dSYoshinobu Inoue 	/*
25931b3783cSHajimu UMEMOTO 	 * Decreasing the interface MTU under IPV6 minimum MTU may cause
26031b3783cSHajimu UMEMOTO 	 * undesirable situation.  We thus notify the operator of the change
26131b3783cSHajimu UMEMOTO 	 * explicitly.  The check for omaxmtu is necessary to restrict the
26231b3783cSHajimu UMEMOTO 	 * log to the case of changing the MTU, not initializing it.
26382cd038dSYoshinobu Inoue 	 */
26431b3783cSHajimu UMEMOTO 	if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) {
26531b3783cSHajimu UMEMOTO 		log(LOG_NOTICE, "nd6_setmtu0: "
26631b3783cSHajimu UMEMOTO 		    "new link MTU on %s (%lu) is too small for IPv6\n",
26731b3783cSHajimu UMEMOTO 		    if_name(ifp), (unsigned long)ndi->maxmtu);
26882cd038dSYoshinobu Inoue 	}
26931b3783cSHajimu UMEMOTO 
270603724d3SBjoern A. Zeeb 	if (ndi->maxmtu > V_in6_maxmtu)
27131b3783cSHajimu UMEMOTO 		in6_setmaxmtu(); /* check all interfaces just in case */
27231b3783cSHajimu UMEMOTO 
27382cd038dSYoshinobu Inoue }
27482cd038dSYoshinobu Inoue 
27582cd038dSYoshinobu Inoue void
2761272577eSXin LI nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts)
27782cd038dSYoshinobu Inoue {
27807eb2995SHajimu UMEMOTO 
27982cd038dSYoshinobu Inoue 	bzero(ndopts, sizeof(*ndopts));
28082cd038dSYoshinobu Inoue 	ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
28182cd038dSYoshinobu Inoue 	ndopts->nd_opts_last
28282cd038dSYoshinobu Inoue 		= (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
28382cd038dSYoshinobu Inoue 
28482cd038dSYoshinobu Inoue 	if (icmp6len == 0) {
28582cd038dSYoshinobu Inoue 		ndopts->nd_opts_done = 1;
28682cd038dSYoshinobu Inoue 		ndopts->nd_opts_search = NULL;
28782cd038dSYoshinobu Inoue 	}
28882cd038dSYoshinobu Inoue }
28982cd038dSYoshinobu Inoue 
29082cd038dSYoshinobu Inoue /*
29182cd038dSYoshinobu Inoue  * Take one ND option.
29282cd038dSYoshinobu Inoue  */
29382cd038dSYoshinobu Inoue struct nd_opt_hdr *
2941272577eSXin LI nd6_option(union nd_opts *ndopts)
29582cd038dSYoshinobu Inoue {
29682cd038dSYoshinobu Inoue 	struct nd_opt_hdr *nd_opt;
29782cd038dSYoshinobu Inoue 	int olen;
29882cd038dSYoshinobu Inoue 
29939e19560SBjoern A. Zeeb 	KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
30039e19560SBjoern A. Zeeb 	KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
30139e19560SBjoern A. Zeeb 	    __func__));
3022ce62dceSSUZUKI Shinsuke 	if (ndopts->nd_opts_search == NULL)
30382cd038dSYoshinobu Inoue 		return NULL;
30482cd038dSYoshinobu Inoue 	if (ndopts->nd_opts_done)
30582cd038dSYoshinobu Inoue 		return NULL;
30682cd038dSYoshinobu Inoue 
30782cd038dSYoshinobu Inoue 	nd_opt = ndopts->nd_opts_search;
30882cd038dSYoshinobu Inoue 
30919391949SKris Kennaway 	/* make sure nd_opt_len is inside the buffer */
31019391949SKris Kennaway 	if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
31119391949SKris Kennaway 		bzero(ndopts, sizeof(*ndopts));
31219391949SKris Kennaway 		return NULL;
31319391949SKris Kennaway 	}
31419391949SKris Kennaway 
31582cd038dSYoshinobu Inoue 	olen = nd_opt->nd_opt_len << 3;
31682cd038dSYoshinobu Inoue 	if (olen == 0) {
31782cd038dSYoshinobu Inoue 		/*
31882cd038dSYoshinobu Inoue 		 * Message validation requires that all included
31982cd038dSYoshinobu Inoue 		 * options have a length that is greater than zero.
32082cd038dSYoshinobu Inoue 		 */
32182cd038dSYoshinobu Inoue 		bzero(ndopts, sizeof(*ndopts));
32282cd038dSYoshinobu Inoue 		return NULL;
32382cd038dSYoshinobu Inoue 	}
32482cd038dSYoshinobu Inoue 
32582cd038dSYoshinobu Inoue 	ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
32619391949SKris Kennaway 	if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
32719391949SKris Kennaway 		/* option overruns the end of buffer, invalid */
32819391949SKris Kennaway 		bzero(ndopts, sizeof(*ndopts));
32919391949SKris Kennaway 		return NULL;
33019391949SKris Kennaway 	} else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
33119391949SKris Kennaway 		/* reached the end of options chain */
33282cd038dSYoshinobu Inoue 		ndopts->nd_opts_done = 1;
33382cd038dSYoshinobu Inoue 		ndopts->nd_opts_search = NULL;
33482cd038dSYoshinobu Inoue 	}
33582cd038dSYoshinobu Inoue 	return nd_opt;
33682cd038dSYoshinobu Inoue }
33782cd038dSYoshinobu Inoue 
33882cd038dSYoshinobu Inoue /*
33982cd038dSYoshinobu Inoue  * Parse multiple ND options.
34082cd038dSYoshinobu Inoue  * This function is much easier to use, for ND routines that do not need
34182cd038dSYoshinobu Inoue  * multiple options of the same type.
34282cd038dSYoshinobu Inoue  */
34382cd038dSYoshinobu Inoue int
3441272577eSXin LI nd6_options(union nd_opts *ndopts)
34582cd038dSYoshinobu Inoue {
34682cd038dSYoshinobu Inoue 	struct nd_opt_hdr *nd_opt;
34782cd038dSYoshinobu Inoue 	int i = 0;
34882cd038dSYoshinobu Inoue 
34939e19560SBjoern A. Zeeb 	KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__));
35039e19560SBjoern A. Zeeb 	KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts",
35139e19560SBjoern A. Zeeb 	    __func__));
3522ce62dceSSUZUKI Shinsuke 	if (ndopts->nd_opts_search == NULL)
35382cd038dSYoshinobu Inoue 		return 0;
35482cd038dSYoshinobu Inoue 
35582cd038dSYoshinobu Inoue 	while (1) {
35682cd038dSYoshinobu Inoue 		nd_opt = nd6_option(ndopts);
3572ce62dceSSUZUKI Shinsuke 		if (nd_opt == NULL && ndopts->nd_opts_last == NULL) {
35882cd038dSYoshinobu Inoue 			/*
35982cd038dSYoshinobu Inoue 			 * Message validation requires that all included
36082cd038dSYoshinobu Inoue 			 * options have a length that is greater than zero.
36182cd038dSYoshinobu Inoue 			 */
362e27b0c87SRobert Watson 			ICMP6STAT_INC(icp6s_nd_badopt);
36382cd038dSYoshinobu Inoue 			bzero(ndopts, sizeof(*ndopts));
36482cd038dSYoshinobu Inoue 			return -1;
36582cd038dSYoshinobu Inoue 		}
36682cd038dSYoshinobu Inoue 
3672ce62dceSSUZUKI Shinsuke 		if (nd_opt == NULL)
36882cd038dSYoshinobu Inoue 			goto skip1;
36982cd038dSYoshinobu Inoue 
37082cd038dSYoshinobu Inoue 		switch (nd_opt->nd_opt_type) {
37182cd038dSYoshinobu Inoue 		case ND_OPT_SOURCE_LINKADDR:
37282cd038dSYoshinobu Inoue 		case ND_OPT_TARGET_LINKADDR:
37382cd038dSYoshinobu Inoue 		case ND_OPT_MTU:
37482cd038dSYoshinobu Inoue 		case ND_OPT_REDIRECTED_HEADER:
375*11d8451dSHiroki Sato 		case ND_OPT_NONCE:
37682cd038dSYoshinobu Inoue 			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
37733841545SHajimu UMEMOTO 				nd6log((LOG_INFO,
37833841545SHajimu UMEMOTO 				    "duplicated ND6 option found (type=%d)\n",
37933841545SHajimu UMEMOTO 				    nd_opt->nd_opt_type));
38082cd038dSYoshinobu Inoue 				/* XXX bark? */
38182cd038dSYoshinobu Inoue 			} else {
38282cd038dSYoshinobu Inoue 				ndopts->nd_opt_array[nd_opt->nd_opt_type]
38382cd038dSYoshinobu Inoue 					= nd_opt;
38482cd038dSYoshinobu Inoue 			}
38582cd038dSYoshinobu Inoue 			break;
38682cd038dSYoshinobu Inoue 		case ND_OPT_PREFIX_INFORMATION:
38782cd038dSYoshinobu Inoue 			if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
38882cd038dSYoshinobu Inoue 				ndopts->nd_opt_array[nd_opt->nd_opt_type]
38982cd038dSYoshinobu Inoue 					= nd_opt;
39082cd038dSYoshinobu Inoue 			}
39182cd038dSYoshinobu Inoue 			ndopts->nd_opts_pi_end =
39282cd038dSYoshinobu Inoue 				(struct nd_opt_prefix_info *)nd_opt;
39382cd038dSYoshinobu Inoue 			break;
394abbe8356SBjoern A. Zeeb 		/* What about ND_OPT_ROUTE_INFO? RFC 4191 */
395abbe8356SBjoern A. Zeeb 		case ND_OPT_RDNSS:	/* RFC 6106 */
396abbe8356SBjoern A. Zeeb 		case ND_OPT_DNSSL:	/* RFC 6106 */
397abbe8356SBjoern A. Zeeb 			/*
398abbe8356SBjoern A. Zeeb 			 * Silently ignore options we know and do not care about
399abbe8356SBjoern A. Zeeb 			 * in the kernel.
400abbe8356SBjoern A. Zeeb 			 */
401abbe8356SBjoern A. Zeeb 			break;
40282cd038dSYoshinobu Inoue 		default:
40382cd038dSYoshinobu Inoue 			/*
40482cd038dSYoshinobu Inoue 			 * Unknown options must be silently ignored,
40582cd038dSYoshinobu Inoue 			 * to accomodate future extension to the protocol.
40682cd038dSYoshinobu Inoue 			 */
40733841545SHajimu UMEMOTO 			nd6log((LOG_DEBUG,
40882cd038dSYoshinobu Inoue 			    "nd6_options: unsupported option %d - "
40933841545SHajimu UMEMOTO 			    "option ignored\n", nd_opt->nd_opt_type));
41082cd038dSYoshinobu Inoue 		}
41182cd038dSYoshinobu Inoue 
41282cd038dSYoshinobu Inoue skip1:
41382cd038dSYoshinobu Inoue 		i++;
414603724d3SBjoern A. Zeeb 		if (i > V_nd6_maxndopt) {
415e27b0c87SRobert Watson 			ICMP6STAT_INC(icp6s_nd_toomanyopt);
41633841545SHajimu UMEMOTO 			nd6log((LOG_INFO, "too many loop in nd opt\n"));
41782cd038dSYoshinobu Inoue 			break;
41882cd038dSYoshinobu Inoue 		}
41982cd038dSYoshinobu Inoue 
42082cd038dSYoshinobu Inoue 		if (ndopts->nd_opts_done)
42182cd038dSYoshinobu Inoue 			break;
42282cd038dSYoshinobu Inoue 	}
42382cd038dSYoshinobu Inoue 
42482cd038dSYoshinobu Inoue 	return 0;
42582cd038dSYoshinobu Inoue }
42682cd038dSYoshinobu Inoue 
42782cd038dSYoshinobu Inoue /*
428743eee66SSUZUKI Shinsuke  * ND6 timer routine to handle ND6 entries
42982cd038dSYoshinobu Inoue  */
43082cd038dSYoshinobu Inoue void
4316e6b3f7cSQing Li nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
432743eee66SSUZUKI Shinsuke {
433ef8d671cSHajimu UMEMOTO 	int canceled;
434ef8d671cSHajimu UMEMOTO 
435e6950476SBjoern A. Zeeb 	LLE_WLOCK_ASSERT(ln);
436e6950476SBjoern A. Zeeb 
437743eee66SSUZUKI Shinsuke 	if (tick < 0) {
4386e6b3f7cSQing Li 		ln->la_expire = 0;
439743eee66SSUZUKI Shinsuke 		ln->ln_ntick = 0;
440ef8d671cSHajimu UMEMOTO 		canceled = callout_stop(&ln->ln_timer_ch);
441743eee66SSUZUKI Shinsuke 	} else {
4427d26db17SHiroki Sato 		ln->la_expire = time_uptime + tick / hz;
4436e6b3f7cSQing Li 		LLE_ADDREF(ln);
444743eee66SSUZUKI Shinsuke 		if (tick > INT_MAX) {
445743eee66SSUZUKI Shinsuke 			ln->ln_ntick = tick - INT_MAX;
446ef8d671cSHajimu UMEMOTO 			canceled = callout_reset(&ln->ln_timer_ch, INT_MAX,
447743eee66SSUZUKI Shinsuke 			    nd6_llinfo_timer, ln);
448743eee66SSUZUKI Shinsuke 		} else {
449743eee66SSUZUKI Shinsuke 			ln->ln_ntick = 0;
450ef8d671cSHajimu UMEMOTO 			canceled = callout_reset(&ln->ln_timer_ch, tick,
451743eee66SSUZUKI Shinsuke 			    nd6_llinfo_timer, ln);
452743eee66SSUZUKI Shinsuke 		}
453743eee66SSUZUKI Shinsuke 	}
454ef8d671cSHajimu UMEMOTO 	if (canceled)
455ef8d671cSHajimu UMEMOTO 		LLE_REMREF(ln);
456743eee66SSUZUKI Shinsuke }
45782cd038dSYoshinobu Inoue 
4586e6b3f7cSQing Li void
4596e6b3f7cSQing Li nd6_llinfo_settimer(struct llentry *ln, long tick)
4606e6b3f7cSQing Li {
4616e6b3f7cSQing Li 
4626e6b3f7cSQing Li 	LLE_WLOCK(ln);
4636e6b3f7cSQing Li 	nd6_llinfo_settimer_locked(ln, tick);
4646e6b3f7cSQing Li 	LLE_WUNLOCK(ln);
4656e6b3f7cSQing Li }
4666e6b3f7cSQing Li 
467743eee66SSUZUKI Shinsuke static void
4681272577eSXin LI nd6_llinfo_timer(void *arg)
469743eee66SSUZUKI Shinsuke {
4706e6b3f7cSQing Li 	struct llentry *ln;
471743eee66SSUZUKI Shinsuke 	struct in6_addr *dst;
472743eee66SSUZUKI Shinsuke 	struct ifnet *ifp;
473686cdd19SJun-ichiro itojun Hagino 	struct nd_ifinfo *ndi = NULL;
47482cd038dSYoshinobu Inoue 
47519291ab3SBjoern A. Zeeb 	KASSERT(arg != NULL, ("%s: arg NULL", __func__));
4766e6b3f7cSQing Li 	ln = (struct llentry *)arg;
4772575fbb8SRandall Stewart 	LLE_WLOCK(ln);
4782575fbb8SRandall Stewart 	if (callout_pending(&ln->la_timer)) {
4792575fbb8SRandall Stewart 		/*
4802575fbb8SRandall Stewart 		 * Here we are a bit odd here in the treatment of
4812575fbb8SRandall Stewart 		 * active/pending. If the pending bit is set, it got
4822575fbb8SRandall Stewart 		 * rescheduled before I ran. The active
4832575fbb8SRandall Stewart 		 * bit we ignore, since if it was stopped
4842575fbb8SRandall Stewart 		 * in ll_tablefree() and was currently running
4852575fbb8SRandall Stewart 		 * it would have return 0 so the code would
4862575fbb8SRandall Stewart 		 * not have deleted it since the callout could
4872575fbb8SRandall Stewart 		 * not be stopped so we want to go through
4882575fbb8SRandall Stewart 		 * with the delete here now. If the callout
4892575fbb8SRandall Stewart 		 * was restarted, the pending bit will be back on and
4902575fbb8SRandall Stewart 		 * we just want to bail since the callout_reset would
4912575fbb8SRandall Stewart 		 * return 1 and our reference would have been removed
4922575fbb8SRandall Stewart 		 * by nd6_llinfo_settimer_locked above since canceled
4932575fbb8SRandall Stewart 		 * would have been 1.
4942575fbb8SRandall Stewart 		 */
4952575fbb8SRandall Stewart 		LLE_WUNLOCK(ln);
4962575fbb8SRandall Stewart 		return;
4972575fbb8SRandall Stewart 	}
49819291ab3SBjoern A. Zeeb 	ifp = ln->lle_tbl->llt_ifp;
4996e6b3f7cSQing Li 	CURVNET_SET(ifp->if_vnet);
50082cd038dSYoshinobu Inoue 
501743eee66SSUZUKI Shinsuke 	if (ln->ln_ntick > 0) {
502743eee66SSUZUKI Shinsuke 		if (ln->ln_ntick > INT_MAX) {
503743eee66SSUZUKI Shinsuke 			ln->ln_ntick -= INT_MAX;
504e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, INT_MAX);
505743eee66SSUZUKI Shinsuke 		} else {
506743eee66SSUZUKI Shinsuke 			ln->ln_ntick = 0;
507e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, ln->ln_ntick);
50882cd038dSYoshinobu Inoue 		}
5096e6b3f7cSQing Li 		goto done;
510743eee66SSUZUKI Shinsuke 	}
511743eee66SSUZUKI Shinsuke 
512743eee66SSUZUKI Shinsuke 	ndi = ND_IFINFO(ifp);
5136e6b3f7cSQing Li 	dst = &L3_ADDR_SIN6(ln)->sin6_addr;
514287e3cb4SHajimu UMEMOTO 	if (ln->la_flags & LLE_STATIC) {
5156e6b3f7cSQing Li 		goto done;
5166e6b3f7cSQing Li 	}
51782cd038dSYoshinobu Inoue 
5186e6b3f7cSQing Li 	if (ln->la_flags & LLE_DELETED) {
5196e6b3f7cSQing Li 		(void)nd6_free(ln, 0);
5202eb10edcSHajimu UMEMOTO 		ln = NULL;
5216e6b3f7cSQing Li 		goto done;
5226e6b3f7cSQing Li 	}
52382cd038dSYoshinobu Inoue 
52482cd038dSYoshinobu Inoue 	switch (ln->ln_state) {
52582cd038dSYoshinobu Inoue 	case ND6_LLINFO_INCOMPLETE:
5266e6b3f7cSQing Li 		if (ln->la_asked < V_nd6_mmaxtries) {
5276e6b3f7cSQing Li 			ln->la_asked++;
528e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
529e6950476SBjoern A. Zeeb 			LLE_WUNLOCK(ln);
530*11d8451dSHiroki Sato 			nd6_ns_output(ifp, NULL, dst, ln, NULL);
531e6950476SBjoern A. Zeeb 			LLE_WLOCK(ln);
53282cd038dSYoshinobu Inoue 		} else {
5336e6b3f7cSQing Li 			struct mbuf *m = ln->la_hold;
53482cd038dSYoshinobu Inoue 			if (m) {
53531d4137bSSUZUKI Shinsuke 				struct mbuf *m0;
53631d4137bSSUZUKI Shinsuke 
53782cd038dSYoshinobu Inoue 				/*
5386e6b3f7cSQing Li 				 * assuming every packet in la_hold has the
539e6950476SBjoern A. Zeeb 				 * same IP header.  Send error after unlock.
54082cd038dSYoshinobu Inoue 				 */
54131d4137bSSUZUKI Shinsuke 				m0 = m->m_nextpkt;
54231d4137bSSUZUKI Shinsuke 				m->m_nextpkt = NULL;
5436e6b3f7cSQing Li 				ln->la_hold = m0;
54431d4137bSSUZUKI Shinsuke 				clear_llinfo_pqueue(ln);
54582cd038dSYoshinobu Inoue 			}
54663a97a40SNavdeep Parhar 			EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_TIMEDOUT);
5476e6b3f7cSQing Li 			(void)nd6_free(ln, 0);
548743eee66SSUZUKI Shinsuke 			ln = NULL;
549e6950476SBjoern A. Zeeb 			if (m != NULL)
550e6950476SBjoern A. Zeeb 				icmp6_error2(m, ICMP6_DST_UNREACH,
551e6950476SBjoern A. Zeeb 				    ICMP6_DST_UNREACH_ADDR, 0, ifp);
55282cd038dSYoshinobu Inoue 		}
55382cd038dSYoshinobu Inoue 		break;
55482cd038dSYoshinobu Inoue 	case ND6_LLINFO_REACHABLE:
555743eee66SSUZUKI Shinsuke 		if (!ND6_LLINFO_PERMANENT(ln)) {
55682cd038dSYoshinobu Inoue 			ln->ln_state = ND6_LLINFO_STALE;
557e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
55833841545SHajimu UMEMOTO 		}
55982cd038dSYoshinobu Inoue 		break;
56033841545SHajimu UMEMOTO 
56133841545SHajimu UMEMOTO 	case ND6_LLINFO_STALE:
56233841545SHajimu UMEMOTO 		/* Garbage Collection(RFC 2461 5.3) */
563743eee66SSUZUKI Shinsuke 		if (!ND6_LLINFO_PERMANENT(ln)) {
56463a97a40SNavdeep Parhar 			EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
5656e6b3f7cSQing Li 			(void)nd6_free(ln, 1);
566743eee66SSUZUKI Shinsuke 			ln = NULL;
567743eee66SSUZUKI Shinsuke 		}
56833841545SHajimu UMEMOTO 		break;
56933841545SHajimu UMEMOTO 
57082cd038dSYoshinobu Inoue 	case ND6_LLINFO_DELAY:
571686cdd19SJun-ichiro itojun Hagino 		if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
572686cdd19SJun-ichiro itojun Hagino 			/* We need NUD */
5736e6b3f7cSQing Li 			ln->la_asked = 1;
57482cd038dSYoshinobu Inoue 			ln->ln_state = ND6_LLINFO_PROBE;
575e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
576e6950476SBjoern A. Zeeb 			LLE_WUNLOCK(ln);
577*11d8451dSHiroki Sato 			nd6_ns_output(ifp, dst, dst, ln, NULL);
578e6950476SBjoern A. Zeeb 			LLE_WLOCK(ln);
57933841545SHajimu UMEMOTO 		} else {
580686cdd19SJun-ichiro itojun Hagino 			ln->ln_state = ND6_LLINFO_STALE; /* XXX */
581e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
58233841545SHajimu UMEMOTO 		}
58382cd038dSYoshinobu Inoue 		break;
58482cd038dSYoshinobu Inoue 	case ND6_LLINFO_PROBE:
5856e6b3f7cSQing Li 		if (ln->la_asked < V_nd6_umaxtries) {
5866e6b3f7cSQing Li 			ln->la_asked++;
587e6950476SBjoern A. Zeeb 			nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
588e6950476SBjoern A. Zeeb 			LLE_WUNLOCK(ln);
589*11d8451dSHiroki Sato 			nd6_ns_output(ifp, dst, dst, ln, NULL);
590e6950476SBjoern A. Zeeb 			LLE_WLOCK(ln);
59182cd038dSYoshinobu Inoue 		} else {
59263a97a40SNavdeep Parhar 			EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
5936e6b3f7cSQing Li 			(void)nd6_free(ln, 0);
594743eee66SSUZUKI Shinsuke 			ln = NULL;
59582cd038dSYoshinobu Inoue 		}
59682cd038dSYoshinobu Inoue 		break;
597e6950476SBjoern A. Zeeb 	default:
598e6950476SBjoern A. Zeeb 		panic("%s: paths in a dark night can be confusing: %d",
599e6950476SBjoern A. Zeeb 		    __func__, ln->ln_state);
60082cd038dSYoshinobu Inoue 	}
6016e6b3f7cSQing Li done:
6026e6b3f7cSQing Li 	if (ln != NULL)
603e6950476SBjoern A. Zeeb 		LLE_FREE_LOCKED(ln);
604f0c0b143SHajimu UMEMOTO 	CURVNET_RESTORE();
60582cd038dSYoshinobu Inoue }
60682cd038dSYoshinobu Inoue 
607743eee66SSUZUKI Shinsuke 
608743eee66SSUZUKI Shinsuke /*
609743eee66SSUZUKI Shinsuke  * ND6 timer routine to expire default route list and prefix list
610743eee66SSUZUKI Shinsuke  */
611743eee66SSUZUKI Shinsuke void
6128b615593SMarko Zec nd6_timer(void *arg)
613743eee66SSUZUKI Shinsuke {
61421ca7b57SMarko Zec 	CURVNET_SET((struct vnet *) arg);
6153b0b2840SJohn Baldwin 	struct nd_defrouter *dr, *ndr;
6163b0b2840SJohn Baldwin 	struct nd_prefix *pr, *npr;
617743eee66SSUZUKI Shinsuke 	struct in6_ifaddr *ia6, *nia6;
618743eee66SSUZUKI Shinsuke 
619603724d3SBjoern A. Zeeb 	callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz,
620f6dfe47aSMarko Zec 	    nd6_timer, curvnet);
621743eee66SSUZUKI Shinsuke 
62233841545SHajimu UMEMOTO 	/* expire default router list */
6233b0b2840SJohn Baldwin 	TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
6247d26db17SHiroki Sato 		if (dr->expire && dr->expire < time_uptime)
62582cd038dSYoshinobu Inoue 			defrtrlist_del(dr);
626686cdd19SJun-ichiro itojun Hagino 	}
62782cd038dSYoshinobu Inoue 
62833841545SHajimu UMEMOTO 	/*
62933841545SHajimu UMEMOTO 	 * expire interface addresses.
63033841545SHajimu UMEMOTO 	 * in the past the loop was inside prefix expiry processing.
63133841545SHajimu UMEMOTO 	 * However, from a stricter speci-confrmance standpoint, we should
63233841545SHajimu UMEMOTO 	 * rather separate address lifetimes and prefix lifetimes.
633d1da0a06SRobert Watson 	 *
634d1da0a06SRobert Watson 	 * XXXRW: in6_ifaddrhead locking.
63533841545SHajimu UMEMOTO 	 */
63633841545SHajimu UMEMOTO   addrloop:
63780af0152SRobert Watson 	TAILQ_FOREACH_SAFE(ia6, &V_in6_ifaddrhead, ia_link, nia6) {
63882cd038dSYoshinobu Inoue 		/* check address lifetime */
63933841545SHajimu UMEMOTO 		if (IFA6_IS_INVALID(ia6)) {
64033841545SHajimu UMEMOTO 			int regen = 0;
64133841545SHajimu UMEMOTO 
64233841545SHajimu UMEMOTO 			/*
64333841545SHajimu UMEMOTO 			 * If the expiring address is temporary, try
64433841545SHajimu UMEMOTO 			 * regenerating a new one.  This would be useful when
64588ff5695SSUZUKI Shinsuke 			 * we suspended a laptop PC, then turned it on after a
64633841545SHajimu UMEMOTO 			 * period that could invalidate all temporary
64733841545SHajimu UMEMOTO 			 * addresses.  Although we may have to restart the
64833841545SHajimu UMEMOTO 			 * loop (see below), it must be after purging the
64933841545SHajimu UMEMOTO 			 * address.  Otherwise, we'd see an infinite loop of
65033841545SHajimu UMEMOTO 			 * regeneration.
65133841545SHajimu UMEMOTO 			 */
652603724d3SBjoern A. Zeeb 			if (V_ip6_use_tempaddr &&
65333841545SHajimu UMEMOTO 			    (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
65433841545SHajimu UMEMOTO 				if (regen_tmpaddr(ia6) == 0)
65533841545SHajimu UMEMOTO 					regen = 1;
65633841545SHajimu UMEMOTO 			}
65733841545SHajimu UMEMOTO 
65833841545SHajimu UMEMOTO 			in6_purgeaddr(&ia6->ia_ifa);
65933841545SHajimu UMEMOTO 
66033841545SHajimu UMEMOTO 			if (regen)
66133841545SHajimu UMEMOTO 				goto addrloop; /* XXX: see below */
66243068328SHajimu UMEMOTO 		} else if (IFA6_IS_DEPRECATED(ia6)) {
66333841545SHajimu UMEMOTO 			int oldflags = ia6->ia6_flags;
66433841545SHajimu UMEMOTO 
66582cd038dSYoshinobu Inoue 			ia6->ia6_flags |= IN6_IFF_DEPRECATED;
66633841545SHajimu UMEMOTO 
66733841545SHajimu UMEMOTO 			/*
66833841545SHajimu UMEMOTO 			 * If a temporary address has just become deprecated,
66933841545SHajimu UMEMOTO 			 * regenerate a new one if possible.
67033841545SHajimu UMEMOTO 			 */
671603724d3SBjoern A. Zeeb 			if (V_ip6_use_tempaddr &&
67233841545SHajimu UMEMOTO 			    (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
67333841545SHajimu UMEMOTO 			    (oldflags & IN6_IFF_DEPRECATED) == 0) {
67433841545SHajimu UMEMOTO 
67533841545SHajimu UMEMOTO 				if (regen_tmpaddr(ia6) == 0) {
67633841545SHajimu UMEMOTO 					/*
67733841545SHajimu UMEMOTO 					 * A new temporary address is
67833841545SHajimu UMEMOTO 					 * generated.
67933841545SHajimu UMEMOTO 					 * XXX: this means the address chain
68033841545SHajimu UMEMOTO 					 * has changed while we are still in
68133841545SHajimu UMEMOTO 					 * the loop.  Although the change
68233841545SHajimu UMEMOTO 					 * would not cause disaster (because
68388ff5695SSUZUKI Shinsuke 					 * it's not a deletion, but an
68488ff5695SSUZUKI Shinsuke 					 * addition,) we'd rather restart the
68533841545SHajimu UMEMOTO 					 * loop just for safety.  Or does this
68633841545SHajimu UMEMOTO 					 * significantly reduce performance??
68733841545SHajimu UMEMOTO 					 */
68833841545SHajimu UMEMOTO 					goto addrloop;
68933841545SHajimu UMEMOTO 				}
69033841545SHajimu UMEMOTO 			}
69183649f07SHajimu UMEMOTO 		} else {
69233841545SHajimu UMEMOTO 			/*
69333841545SHajimu UMEMOTO 			 * A new RA might have made a deprecated address
69433841545SHajimu UMEMOTO 			 * preferred.
69533841545SHajimu UMEMOTO 			 */
69633841545SHajimu UMEMOTO 			ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
69782cd038dSYoshinobu Inoue 		}
69882cd038dSYoshinobu Inoue 	}
69982cd038dSYoshinobu Inoue 
70033841545SHajimu UMEMOTO 	/* expire prefix list */
7013b0b2840SJohn Baldwin 	LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
70282cd038dSYoshinobu Inoue 		/*
70382cd038dSYoshinobu Inoue 		 * check prefix lifetime.
70482cd038dSYoshinobu Inoue 		 * since pltime is just for autoconf, pltime processing for
70582cd038dSYoshinobu Inoue 		 * prefix is not necessary.
70682cd038dSYoshinobu Inoue 		 */
707743eee66SSUZUKI Shinsuke 		if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
7087d26db17SHiroki Sato 		    time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) {
70982cd038dSYoshinobu Inoue 
71082cd038dSYoshinobu Inoue 			/*
71182cd038dSYoshinobu Inoue 			 * address expiration and prefix expiration are
71233841545SHajimu UMEMOTO 			 * separate.  NEVER perform in6_purgeaddr here.
71382cd038dSYoshinobu Inoue 			 */
71482cd038dSYoshinobu Inoue 			prelist_remove(pr);
7153b0b2840SJohn Baldwin 		}
71682cd038dSYoshinobu Inoue 	}
7178b615593SMarko Zec 	CURVNET_RESTORE();
71882cd038dSYoshinobu Inoue }
71982cd038dSYoshinobu Inoue 
7201272577eSXin LI /*
7211272577eSXin LI  * ia6 - deprecated/invalidated temporary address
7221272577eSXin LI  */
72333841545SHajimu UMEMOTO static int
7241272577eSXin LI regen_tmpaddr(struct in6_ifaddr *ia6)
72533841545SHajimu UMEMOTO {
72633841545SHajimu UMEMOTO 	struct ifaddr *ifa;
72733841545SHajimu UMEMOTO 	struct ifnet *ifp;
72833841545SHajimu UMEMOTO 	struct in6_ifaddr *public_ifa6 = NULL;
72933841545SHajimu UMEMOTO 
73033841545SHajimu UMEMOTO 	ifp = ia6->ia_ifa.ifa_ifp;
731137f91e8SJohn Baldwin 	IF_ADDR_RLOCK(ifp);
732c4dd3fe1SRobert Watson 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
73333841545SHajimu UMEMOTO 		struct in6_ifaddr *it6;
73433841545SHajimu UMEMOTO 
73533841545SHajimu UMEMOTO 		if (ifa->ifa_addr->sa_family != AF_INET6)
73633841545SHajimu UMEMOTO 			continue;
73733841545SHajimu UMEMOTO 
73833841545SHajimu UMEMOTO 		it6 = (struct in6_ifaddr *)ifa;
73933841545SHajimu UMEMOTO 
74033841545SHajimu UMEMOTO 		/* ignore no autoconf addresses. */
74133841545SHajimu UMEMOTO 		if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
74233841545SHajimu UMEMOTO 			continue;
74333841545SHajimu UMEMOTO 
74433841545SHajimu UMEMOTO 		/* ignore autoconf addresses with different prefixes. */
74533841545SHajimu UMEMOTO 		if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr)
74633841545SHajimu UMEMOTO 			continue;
74733841545SHajimu UMEMOTO 
74833841545SHajimu UMEMOTO 		/*
74933841545SHajimu UMEMOTO 		 * Now we are looking at an autoconf address with the same
75033841545SHajimu UMEMOTO 		 * prefix as ours.  If the address is temporary and is still
75133841545SHajimu UMEMOTO 		 * preferred, do not create another one.  It would be rare, but
75233841545SHajimu UMEMOTO 		 * could happen, for example, when we resume a laptop PC after
75333841545SHajimu UMEMOTO 		 * a long period.
75433841545SHajimu UMEMOTO 		 */
75533841545SHajimu UMEMOTO 		if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
75633841545SHajimu UMEMOTO 		    !IFA6_IS_DEPRECATED(it6)) {
75733841545SHajimu UMEMOTO 			public_ifa6 = NULL;
75833841545SHajimu UMEMOTO 			break;
75933841545SHajimu UMEMOTO 		}
76033841545SHajimu UMEMOTO 
76133841545SHajimu UMEMOTO 		/*
76233841545SHajimu UMEMOTO 		 * This is a public autoconf address that has the same prefix
76333841545SHajimu UMEMOTO 		 * as ours.  If it is preferred, keep it.  We can't break the
76433841545SHajimu UMEMOTO 		 * loop here, because there may be a still-preferred temporary
76533841545SHajimu UMEMOTO 		 * address with the prefix.
76633841545SHajimu UMEMOTO 		 */
76733841545SHajimu UMEMOTO 		if (!IFA6_IS_DEPRECATED(it6))
76833841545SHajimu UMEMOTO 		    public_ifa6 = it6;
769c1752bcdSQing Li 
770c1752bcdSQing Li 		if (public_ifa6 != NULL)
771c1752bcdSQing Li 			ifa_ref(&public_ifa6->ia_ifa);
77233841545SHajimu UMEMOTO 	}
773137f91e8SJohn Baldwin 	IF_ADDR_RUNLOCK(ifp);
77433841545SHajimu UMEMOTO 
77533841545SHajimu UMEMOTO 	if (public_ifa6 != NULL) {
77633841545SHajimu UMEMOTO 		int e;
77733841545SHajimu UMEMOTO 
778743eee66SSUZUKI Shinsuke 		if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
779c1752bcdSQing Li 			ifa_free(&public_ifa6->ia_ifa);
78033841545SHajimu UMEMOTO 			log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
78133841545SHajimu UMEMOTO 			    " tmp addr,errno=%d\n", e);
78233841545SHajimu UMEMOTO 			return (-1);
78333841545SHajimu UMEMOTO 		}
784c1752bcdSQing Li 		ifa_free(&public_ifa6->ia_ifa);
78533841545SHajimu UMEMOTO 		return (0);
78633841545SHajimu UMEMOTO 	}
78733841545SHajimu UMEMOTO 
78833841545SHajimu UMEMOTO 	return (-1);
78933841545SHajimu UMEMOTO }
79033841545SHajimu UMEMOTO 
791686cdd19SJun-ichiro itojun Hagino /*
792686cdd19SJun-ichiro itojun Hagino  * Nuke neighbor cache/prefix/default router management table, right before
793686cdd19SJun-ichiro itojun Hagino  * ifp goes away.
794686cdd19SJun-ichiro itojun Hagino  */
795686cdd19SJun-ichiro itojun Hagino void
7961272577eSXin LI nd6_purge(struct ifnet *ifp)
797686cdd19SJun-ichiro itojun Hagino {
798743eee66SSUZUKI Shinsuke 	struct nd_defrouter *dr, *ndr;
799686cdd19SJun-ichiro itojun Hagino 	struct nd_prefix *pr, *npr;
800686cdd19SJun-ichiro itojun Hagino 
801686cdd19SJun-ichiro itojun Hagino 	/*
802743eee66SSUZUKI Shinsuke 	 * Nuke default router list entries toward ifp.
803743eee66SSUZUKI Shinsuke 	 * We defer removal of default router list entries that is installed
804743eee66SSUZUKI Shinsuke 	 * in the routing table, in order to keep additional side effects as
805743eee66SSUZUKI Shinsuke 	 * small as possible.
806686cdd19SJun-ichiro itojun Hagino 	 */
8073b0b2840SJohn Baldwin 	TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
808743eee66SSUZUKI Shinsuke 		if (dr->installed)
809743eee66SSUZUKI Shinsuke 			continue;
810743eee66SSUZUKI Shinsuke 
811686cdd19SJun-ichiro itojun Hagino 		if (dr->ifp == ifp)
812686cdd19SJun-ichiro itojun Hagino 			defrtrlist_del(dr);
813686cdd19SJun-ichiro itojun Hagino 	}
814743eee66SSUZUKI Shinsuke 
8153b0b2840SJohn Baldwin 	TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) {
816743eee66SSUZUKI Shinsuke 		if (!dr->installed)
817743eee66SSUZUKI Shinsuke 			continue;
818743eee66SSUZUKI Shinsuke 
819686cdd19SJun-ichiro itojun Hagino 		if (dr->ifp == ifp)
820686cdd19SJun-ichiro itojun Hagino 			defrtrlist_del(dr);
821686cdd19SJun-ichiro itojun Hagino 	}
822686cdd19SJun-ichiro itojun Hagino 
823686cdd19SJun-ichiro itojun Hagino 	/* Nuke prefix list entries toward ifp */
8243b0b2840SJohn Baldwin 	LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) {
825686cdd19SJun-ichiro itojun Hagino 		if (pr->ndpr_ifp == ifp) {
82633841545SHajimu UMEMOTO 			/*
827743eee66SSUZUKI Shinsuke 			 * Because if_detach() does *not* release prefixes
828743eee66SSUZUKI Shinsuke 			 * while purging addresses the reference count will
829743eee66SSUZUKI Shinsuke 			 * still be above zero. We therefore reset it to
830743eee66SSUZUKI Shinsuke 			 * make sure that the prefix really gets purged.
831743eee66SSUZUKI Shinsuke 			 */
832743eee66SSUZUKI Shinsuke 			pr->ndpr_refcnt = 0;
833743eee66SSUZUKI Shinsuke 
834743eee66SSUZUKI Shinsuke 			/*
83533841545SHajimu UMEMOTO 			 * Previously, pr->ndpr_addr is removed as well,
83633841545SHajimu UMEMOTO 			 * but I strongly believe we don't have to do it.
83733841545SHajimu UMEMOTO 			 * nd6_purge() is only called from in6_ifdetach(),
83833841545SHajimu UMEMOTO 			 * which removes all the associated interface addresses
83933841545SHajimu UMEMOTO 			 * by itself.
84033841545SHajimu UMEMOTO 			 * (jinmei@kame.net 20010129)
84133841545SHajimu UMEMOTO 			 */
842686cdd19SJun-ichiro itojun Hagino 			prelist_remove(pr);
843686cdd19SJun-ichiro itojun Hagino 		}
844686cdd19SJun-ichiro itojun Hagino 	}
845686cdd19SJun-ichiro itojun Hagino 
846686cdd19SJun-ichiro itojun Hagino 	/* cancel default outgoing interface setting */
847603724d3SBjoern A. Zeeb 	if (V_nd6_defifindex == ifp->if_index)
848686cdd19SJun-ichiro itojun Hagino 		nd6_setdefaultiface(0);
849686cdd19SJun-ichiro itojun Hagino 
850e7fa8d0aSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
851a283298cSHiroki Sato 		/* Refresh default router list. */
852686cdd19SJun-ichiro itojun Hagino 		defrouter_select();
8536e6b3f7cSQing Li 	}
8546e6b3f7cSQing Li 
8556e6b3f7cSQing Li 	/* XXXXX
8566e6b3f7cSQing Li 	 * We do not nuke the neighbor cache entries here any more
8576e6b3f7cSQing Li 	 * because the neighbor cache is kept in if_afdata[AF_INET6].
8586e6b3f7cSQing Li 	 * nd6_purge() is invoked by in6_ifdetach() which is called
8596e6b3f7cSQing Li 	 * from if_detach() where everything gets purged. So let
8606e6b3f7cSQing Li 	 * in6_domifdetach() do the actual L2 table purging work.
8616e6b3f7cSQing Li 	 */
8621026ccc4SHajimu UMEMOTO }
863686cdd19SJun-ichiro itojun Hagino 
864686cdd19SJun-ichiro itojun Hagino /*
8656e6b3f7cSQing Li  * the caller acquires and releases the lock on the lltbls
8666e6b3f7cSQing Li  * Returns the llentry locked
867686cdd19SJun-ichiro itojun Hagino  */
8686e6b3f7cSQing Li struct llentry *
8696e6b3f7cSQing Li nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
87082cd038dSYoshinobu Inoue {
87182cd038dSYoshinobu Inoue 	struct sockaddr_in6 sin6;
8726e6b3f7cSQing Li 	struct llentry *ln;
87368352503SBjoern A. Zeeb 	int llflags;
87482cd038dSYoshinobu Inoue 
87582cd038dSYoshinobu Inoue 	bzero(&sin6, sizeof(sin6));
87682cd038dSYoshinobu Inoue 	sin6.sin6_len = sizeof(struct sockaddr_in6);
87782cd038dSYoshinobu Inoue 	sin6.sin6_family = AF_INET6;
87882cd038dSYoshinobu Inoue 	sin6.sin6_addr = *addr6;
879686cdd19SJun-ichiro itojun Hagino 
8806e6b3f7cSQing Li 	IF_AFDATA_LOCK_ASSERT(ifp);
88182cd038dSYoshinobu Inoue 
88268352503SBjoern A. Zeeb 	llflags = 0;
8836e6b3f7cSQing Li 	if (flags & ND6_CREATE)
8846e6b3f7cSQing Li 	    llflags |= LLE_CREATE;
8856e6b3f7cSQing Li 	if (flags & ND6_EXCLUSIVE)
8866e6b3f7cSQing Li 	    llflags |= LLE_EXCLUSIVE;
8876e6b3f7cSQing Li 
8886e6b3f7cSQing Li 	ln = lla_lookup(LLTABLE6(ifp), llflags, (struct sockaddr *)&sin6);
88968352503SBjoern A. Zeeb 	if ((ln != NULL) && (llflags & LLE_CREATE))
89082cd038dSYoshinobu Inoue 		ln->ln_state = ND6_LLINFO_NOSTATE;
8916e6b3f7cSQing Li 
8926e6b3f7cSQing Li 	return (ln);
89382cd038dSYoshinobu Inoue }
89482cd038dSYoshinobu Inoue 
89582cd038dSYoshinobu Inoue /*
89677b691e0SBrian Feldman  * Test whether a given IPv6 address is a neighbor or not, ignoring
89777b691e0SBrian Feldman  * the actual neighbor cache.  The neighbor cache is ignored in order
89877b691e0SBrian Feldman  * to not reenter the routing code from within itself.
89982cd038dSYoshinobu Inoue  */
90077b691e0SBrian Feldman static int
9011272577eSXin LI nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
90282cd038dSYoshinobu Inoue {
9034208ea14SHajimu UMEMOTO 	struct nd_prefix *pr;
904743eee66SSUZUKI Shinsuke 	struct ifaddr *dstaddr;
90582cd038dSYoshinobu Inoue 
906686cdd19SJun-ichiro itojun Hagino 	/*
907686cdd19SJun-ichiro itojun Hagino 	 * A link-local address is always a neighbor.
9084208ea14SHajimu UMEMOTO 	 * XXX: a link does not necessarily specify a single interface.
909686cdd19SJun-ichiro itojun Hagino 	 */
910a1f7e5f8SHajimu UMEMOTO 	if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
911a1f7e5f8SHajimu UMEMOTO 		struct sockaddr_in6 sin6_copy;
912a1f7e5f8SHajimu UMEMOTO 		u_int32_t zone;
913a1f7e5f8SHajimu UMEMOTO 
914a1f7e5f8SHajimu UMEMOTO 		/*
915a1f7e5f8SHajimu UMEMOTO 		 * We need sin6_copy since sa6_recoverscope() may modify the
916a1f7e5f8SHajimu UMEMOTO 		 * content (XXX).
917a1f7e5f8SHajimu UMEMOTO 		 */
918a1f7e5f8SHajimu UMEMOTO 		sin6_copy = *addr;
919a1f7e5f8SHajimu UMEMOTO 		if (sa6_recoverscope(&sin6_copy))
920a1f7e5f8SHajimu UMEMOTO 			return (0); /* XXX: should be impossible */
921a1f7e5f8SHajimu UMEMOTO 		if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone))
922a1f7e5f8SHajimu UMEMOTO 			return (0);
923a1f7e5f8SHajimu UMEMOTO 		if (sin6_copy.sin6_scope_id == zone)
92482cd038dSYoshinobu Inoue 			return (1);
925a1f7e5f8SHajimu UMEMOTO 		else
926a1f7e5f8SHajimu UMEMOTO 			return (0);
927a1f7e5f8SHajimu UMEMOTO 	}
92882cd038dSYoshinobu Inoue 
92982cd038dSYoshinobu Inoue 	/*
93082cd038dSYoshinobu Inoue 	 * If the address matches one of our addresses,
93182cd038dSYoshinobu Inoue 	 * it should be a neighbor.
9324208ea14SHajimu UMEMOTO 	 * If the address matches one of our on-link prefixes, it should be a
9334208ea14SHajimu UMEMOTO 	 * neighbor.
93482cd038dSYoshinobu Inoue 	 */
9353b0b2840SJohn Baldwin 	LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
9364208ea14SHajimu UMEMOTO 		if (pr->ndpr_ifp != ifp)
9374208ea14SHajimu UMEMOTO 			continue;
93882cd038dSYoshinobu Inoue 
939baf7c373SQing Li 		if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) {
940baf7c373SQing Li 			struct rtentry *rt;
94181d5d46bSBjoern A. Zeeb 
94281d5d46bSBjoern A. Zeeb 			/* Always use the default FIB here. */
94381d5d46bSBjoern A. Zeeb 			rt = in6_rtalloc1((struct sockaddr *)&pr->ndpr_prefix,
94481d5d46bSBjoern A. Zeeb 			    0, 0, RT_DEFAULT_FIB);
945baf7c373SQing Li 			if (rt == NULL)
9464208ea14SHajimu UMEMOTO 				continue;
947baf7c373SQing Li 			/*
948baf7c373SQing Li 			 * This is the case where multiple interfaces
949baf7c373SQing Li 			 * have the same prefix, but only one is installed
950baf7c373SQing Li 			 * into the routing table and that prefix entry
951baf7c373SQing Li 			 * is not the one being examined here. In the case
952baf7c373SQing Li 			 * where RADIX_MPATH is enabled, multiple route
953baf7c373SQing Li 			 * entries (of the same rt_key value) will be
954baf7c373SQing Li 			 * installed because the interface addresses all
955baf7c373SQing Li 			 * differ.
956baf7c373SQing Li 			 */
957baf7c373SQing Li 			if (!IN6_ARE_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
958baf7c373SQing Li 			       &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr)) {
959baf7c373SQing Li 				RTFREE_LOCKED(rt);
960baf7c373SQing Li 				continue;
961baf7c373SQing Li 			}
962baf7c373SQing Li 			RTFREE_LOCKED(rt);
963baf7c373SQing Li 		}
9644208ea14SHajimu UMEMOTO 
9654208ea14SHajimu UMEMOTO 		if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
9664208ea14SHajimu UMEMOTO 		    &addr->sin6_addr, &pr->ndpr_mask))
9674208ea14SHajimu UMEMOTO 			return (1);
96882cd038dSYoshinobu Inoue 	}
9694208ea14SHajimu UMEMOTO 
9704208ea14SHajimu UMEMOTO 	/*
971743eee66SSUZUKI Shinsuke 	 * If the address is assigned on the node of the other side of
972743eee66SSUZUKI Shinsuke 	 * a p2p interface, the address should be a neighbor.
973743eee66SSUZUKI Shinsuke 	 */
9744f8585e0SAlan Somers 	dstaddr = ifa_ifwithdstaddr((struct sockaddr *)addr, RT_ALL_FIBS);
9758c0fec80SRobert Watson 	if (dstaddr != NULL) {
9768c0fec80SRobert Watson 		if (dstaddr->ifa_ifp == ifp) {
9778c0fec80SRobert Watson 			ifa_free(dstaddr);
978743eee66SSUZUKI Shinsuke 			return (1);
9798c0fec80SRobert Watson 		}
9808c0fec80SRobert Watson 		ifa_free(dstaddr);
9818c0fec80SRobert Watson 	}
982743eee66SSUZUKI Shinsuke 
983743eee66SSUZUKI Shinsuke 	/*
9844208ea14SHajimu UMEMOTO 	 * If the default router list is empty, all addresses are regarded
9854208ea14SHajimu UMEMOTO 	 * as on-link, and thus, as a neighbor.
9864208ea14SHajimu UMEMOTO 	 */
987e7fa8d0aSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV &&
9883b0b2840SJohn Baldwin 	    TAILQ_EMPTY(&V_nd_defrouter) &&
989603724d3SBjoern A. Zeeb 	    V_nd6_defifindex == ifp->if_index) {
99082cd038dSYoshinobu Inoue 		return (1);
99182cd038dSYoshinobu Inoue 	}
99282cd038dSYoshinobu Inoue 
99377b691e0SBrian Feldman 	return (0);
99477b691e0SBrian Feldman }
99577b691e0SBrian Feldman 
99677b691e0SBrian Feldman 
99777b691e0SBrian Feldman /*
99877b691e0SBrian Feldman  * Detect if a given IPv6 address identifies a neighbor on a given link.
99977b691e0SBrian Feldman  * XXX: should take care of the destination of a p2p link?
100077b691e0SBrian Feldman  */
100177b691e0SBrian Feldman int
10021272577eSXin LI nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
100377b691e0SBrian Feldman {
10046e6b3f7cSQing Li 	struct llentry *lle;
10056e6b3f7cSQing Li 	int rc = 0;
100677b691e0SBrian Feldman 
10076e6b3f7cSQing Li 	IF_AFDATA_UNLOCK_ASSERT(ifp);
100877b691e0SBrian Feldman 	if (nd6_is_new_addr_neighbor(addr, ifp))
100977b691e0SBrian Feldman 		return (1);
101077b691e0SBrian Feldman 
101182cd038dSYoshinobu Inoue 	/*
101282cd038dSYoshinobu Inoue 	 * Even if the address matches none of our addresses, it might be
101382cd038dSYoshinobu Inoue 	 * in the neighbor cache.
101482cd038dSYoshinobu Inoue 	 */
101573cb2f38SAndrey V. Elsukov 	IF_AFDATA_RLOCK(ifp);
10166e6b3f7cSQing Li 	if ((lle = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) {
10176e6b3f7cSQing Li 		LLE_RUNLOCK(lle);
10186e6b3f7cSQing Li 		rc = 1;
10196e6b3f7cSQing Li 	}
102073cb2f38SAndrey V. Elsukov 	IF_AFDATA_RUNLOCK(ifp);
10216e6b3f7cSQing Li 	return (rc);
102282cd038dSYoshinobu Inoue }
102382cd038dSYoshinobu Inoue 
102482cd038dSYoshinobu Inoue /*
102582cd038dSYoshinobu Inoue  * Free an nd6 llinfo entry.
1026743eee66SSUZUKI Shinsuke  * Since the function would cause significant changes in the kernel, DO NOT
1027743eee66SSUZUKI Shinsuke  * make it global, unless you have a strong reason for the change, and are sure
1028743eee66SSUZUKI Shinsuke  * that the change is safe.
102982cd038dSYoshinobu Inoue  */
10306e6b3f7cSQing Li static struct llentry *
10316e6b3f7cSQing Li nd6_free(struct llentry *ln, int gc)
103282cd038dSYoshinobu Inoue {
10336e6b3f7cSQing Li         struct llentry *next;
103482cd038dSYoshinobu Inoue 	struct nd_defrouter *dr;
1035e6950476SBjoern A. Zeeb 	struct ifnet *ifp;
1036e6950476SBjoern A. Zeeb 
1037e6950476SBjoern A. Zeeb 	LLE_WLOCK_ASSERT(ln);
103882cd038dSYoshinobu Inoue 
103982cd038dSYoshinobu Inoue 	/*
104033841545SHajimu UMEMOTO 	 * we used to have pfctlinput(PRC_HOSTDEAD) here.
104133841545SHajimu UMEMOTO 	 * even though it is not harmful, it was not really necessary.
104282cd038dSYoshinobu Inoue 	 */
1043686cdd19SJun-ichiro itojun Hagino 
1044743eee66SSUZUKI Shinsuke 	/* cancel timer */
1045e6950476SBjoern A. Zeeb 	nd6_llinfo_settimer_locked(ln, -1);
1046e6950476SBjoern A. Zeeb 
1047e6950476SBjoern A. Zeeb 	ifp = ln->lle_tbl->llt_ifp;
1048743eee66SSUZUKI Shinsuke 
1049e7fa8d0aSHiroki Sato 	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
1050e6950476SBjoern A. Zeeb 		dr = defrouter_lookup(&L3_ADDR_SIN6(ln)->sin6_addr, ifp);
105133841545SHajimu UMEMOTO 
1052743eee66SSUZUKI Shinsuke 		if (dr != NULL && dr->expire &&
1053743eee66SSUZUKI Shinsuke 		    ln->ln_state == ND6_LLINFO_STALE && gc) {
1054743eee66SSUZUKI Shinsuke 			/*
1055743eee66SSUZUKI Shinsuke 			 * If the reason for the deletion is just garbage
1056743eee66SSUZUKI Shinsuke 			 * collection, and the neighbor is an active default
1057743eee66SSUZUKI Shinsuke 			 * router, do not delete it.  Instead, reset the GC
1058743eee66SSUZUKI Shinsuke 			 * timer using the router's lifetime.
1059743eee66SSUZUKI Shinsuke 			 * Simply deleting the entry would affect default
1060743eee66SSUZUKI Shinsuke 			 * router selection, which is not necessarily a good
1061743eee66SSUZUKI Shinsuke 			 * thing, especially when we're using router preference
1062743eee66SSUZUKI Shinsuke 			 * values.
1063743eee66SSUZUKI Shinsuke 			 * XXX: the check for ln_state would be redundant,
1064743eee66SSUZUKI Shinsuke 			 *      but we intentionally keep it just in case.
1065743eee66SSUZUKI Shinsuke 			 */
10667d26db17SHiroki Sato 			if (dr->expire > time_uptime)
1067e6950476SBjoern A. Zeeb 				nd6_llinfo_settimer_locked(ln,
10687d26db17SHiroki Sato 				    (dr->expire - time_uptime) * hz);
1069743eee66SSUZUKI Shinsuke 			else
1070e6950476SBjoern A. Zeeb 				nd6_llinfo_settimer_locked(ln,
1071e6950476SBjoern A. Zeeb 				    (long)V_nd6_gctimer * hz);
1072e6950476SBjoern A. Zeeb 
1073e6950476SBjoern A. Zeeb 			next = LIST_NEXT(ln, lle_next);
1074ef8d671cSHajimu UMEMOTO 			LLE_REMREF(ln);
1075ef8d671cSHajimu UMEMOTO 			LLE_WUNLOCK(ln);
1076e6950476SBjoern A. Zeeb 			return (next);
1077743eee66SSUZUKI Shinsuke 		}
1078743eee66SSUZUKI Shinsuke 
1079686cdd19SJun-ichiro itojun Hagino 		if (dr) {
1080686cdd19SJun-ichiro itojun Hagino 			/*
1081686cdd19SJun-ichiro itojun Hagino 			 * Unreachablity of a router might affect the default
1082686cdd19SJun-ichiro itojun Hagino 			 * router selection and on-link detection of advertised
1083686cdd19SJun-ichiro itojun Hagino 			 * prefixes.
1084686cdd19SJun-ichiro itojun Hagino 			 */
1085686cdd19SJun-ichiro itojun Hagino 
1086686cdd19SJun-ichiro itojun Hagino 			/*
1087686cdd19SJun-ichiro itojun Hagino 			 * Temporarily fake the state to choose a new default
1088686cdd19SJun-ichiro itojun Hagino 			 * router and to perform on-link determination of
108988ff5695SSUZUKI Shinsuke 			 * prefixes correctly.
1090686cdd19SJun-ichiro itojun Hagino 			 * Below the state will be set correctly,
1091686cdd19SJun-ichiro itojun Hagino 			 * or the entry itself will be deleted.
1092686cdd19SJun-ichiro itojun Hagino 			 */
1093686cdd19SJun-ichiro itojun Hagino 			ln->ln_state = ND6_LLINFO_INCOMPLETE;
10941d5089c2SBjoern A. Zeeb 		}
1095686cdd19SJun-ichiro itojun Hagino 
10961d5089c2SBjoern A. Zeeb 		if (ln->ln_router || dr) {
10971d5089c2SBjoern A. Zeeb 
10981d5089c2SBjoern A. Zeeb 			/*
10991d5089c2SBjoern A. Zeeb 			 * We need to unlock to avoid a LOR with rt6_flush() with the
11001d5089c2SBjoern A. Zeeb 			 * rnh and for the calls to pfxlist_onlink_check() and
11011d5089c2SBjoern A. Zeeb 			 * defrouter_select() in the block further down for calls
11021d5089c2SBjoern A. Zeeb 			 * into nd6_lookup().  We still hold a ref.
11031d5089c2SBjoern A. Zeeb 			 */
11041d5089c2SBjoern A. Zeeb 			LLE_WUNLOCK(ln);
11051d5089c2SBjoern A. Zeeb 
11061d5089c2SBjoern A. Zeeb 			/*
11071d5089c2SBjoern A. Zeeb 			 * rt6_flush must be called whether or not the neighbor
11081d5089c2SBjoern A. Zeeb 			 * is in the Default Router List.
11091d5089c2SBjoern A. Zeeb 			 * See a corresponding comment in nd6_na_input().
11101d5089c2SBjoern A. Zeeb 			 */
11111d5089c2SBjoern A. Zeeb 			rt6_flush(&L3_ADDR_SIN6(ln)->sin6_addr, ifp);
11121d5089c2SBjoern A. Zeeb 		}
11131d5089c2SBjoern A. Zeeb 
11141d5089c2SBjoern A. Zeeb 		if (dr) {
111533841545SHajimu UMEMOTO 			/*
111633841545SHajimu UMEMOTO 			 * Since defrouter_select() does not affect the
111733841545SHajimu UMEMOTO 			 * on-link determination and MIP6 needs the check
111833841545SHajimu UMEMOTO 			 * before the default router selection, we perform
111933841545SHajimu UMEMOTO 			 * the check now.
112033841545SHajimu UMEMOTO 			 */
112133841545SHajimu UMEMOTO 			pfxlist_onlink_check();
112233841545SHajimu UMEMOTO 
1123686cdd19SJun-ichiro itojun Hagino 			/*
11241d5089c2SBjoern A. Zeeb 			 * Refresh default router list.
1125686cdd19SJun-ichiro itojun Hagino 			 */
1126686cdd19SJun-ichiro itojun Hagino 			defrouter_select();
1127686cdd19SJun-ichiro itojun Hagino 		}
11281d5089c2SBjoern A. Zeeb 
11291d5089c2SBjoern A. Zeeb 		if (ln->ln_router || dr)
11301d5089c2SBjoern A. Zeeb 			LLE_WLOCK(ln);
113182cd038dSYoshinobu Inoue 	}
113282cd038dSYoshinobu Inoue 
113333841545SHajimu UMEMOTO 	/*
113433841545SHajimu UMEMOTO 	 * Before deleting the entry, remember the next entry as the
113533841545SHajimu UMEMOTO 	 * return value.  We need this because pfxlist_onlink_check() above
113633841545SHajimu UMEMOTO 	 * might have freed other entries (particularly the old next entry) as
113733841545SHajimu UMEMOTO 	 * a side effect (XXX).
113833841545SHajimu UMEMOTO 	 */
11396e6b3f7cSQing Li 	next = LIST_NEXT(ln, lle_next);
1140686cdd19SJun-ichiro itojun Hagino 
1141e6950476SBjoern A. Zeeb 	/*
1142e6950476SBjoern A. Zeeb 	 * Save to unlock. We still hold an extra reference and will not
1143e6950476SBjoern A. Zeeb 	 * free(9) in llentry_free() if someone else holds one as well.
1144e6950476SBjoern A. Zeeb 	 */
1145e6950476SBjoern A. Zeeb 	LLE_WUNLOCK(ln);
11466e6b3f7cSQing Li 	IF_AFDATA_LOCK(ifp);
11476e6b3f7cSQing Li 	LLE_WLOCK(ln);
1148b1ec2940SGleb Smirnoff 
1149b1ec2940SGleb Smirnoff 	/* Guard against race with other llentry_free(). */
1150b1ec2940SGleb Smirnoff 	if (ln->la_flags & LLE_LINKED) {
1151becba438SBjoern A. Zeeb 		LLE_REMREF(ln);
11526e6b3f7cSQing Li 		llentry_free(ln);
1153b1ec2940SGleb Smirnoff 	} else
1154b1ec2940SGleb Smirnoff 		LLE_FREE_LOCKED(ln);
1155b1ec2940SGleb Smirnoff 
11566e6b3f7cSQing Li 	IF_AFDATA_UNLOCK(ifp);
115733841545SHajimu UMEMOTO 
115833841545SHajimu UMEMOTO 	return (next);
115982cd038dSYoshinobu Inoue }
116082cd038dSYoshinobu Inoue 
116182cd038dSYoshinobu Inoue /*
116282cd038dSYoshinobu Inoue  * Upper-layer reachability hint for Neighbor Unreachability Detection.
116382cd038dSYoshinobu Inoue  *
1164cd0fdcf7SHajimu UMEMOTO  * XXX cost-effective methods?
116582cd038dSYoshinobu Inoue  */
116682cd038dSYoshinobu Inoue void
11671272577eSXin LI nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
116882cd038dSYoshinobu Inoue {
11696e6b3f7cSQing Li 	struct llentry *ln;
11706e6b3f7cSQing Li 	struct ifnet *ifp;
117182cd038dSYoshinobu Inoue 
11726e6b3f7cSQing Li 	if ((dst6 == NULL) || (rt == NULL))
117382cd038dSYoshinobu Inoue 		return;
117482cd038dSYoshinobu Inoue 
11756e6b3f7cSQing Li 	ifp = rt->rt_ifp;
1176ea0c3776SAndrey V. Elsukov 	IF_AFDATA_RLOCK(ifp);
11776e6b3f7cSQing Li 	ln = nd6_lookup(dst6, ND6_EXCLUSIVE, NULL);
1178ea0c3776SAndrey V. Elsukov 	IF_AFDATA_RUNLOCK(ifp);
11796e6b3f7cSQing Li 	if (ln == NULL)
118082cd038dSYoshinobu Inoue 		return;
118182cd038dSYoshinobu Inoue 
1182ad8d5711SMunechika SUMIKAWA 	if (ln->ln_state < ND6_LLINFO_REACHABLE)
11836e6b3f7cSQing Li 		goto done;
118482cd038dSYoshinobu Inoue 
1185686cdd19SJun-ichiro itojun Hagino 	/*
1186686cdd19SJun-ichiro itojun Hagino 	 * if we get upper-layer reachability confirmation many times,
1187686cdd19SJun-ichiro itojun Hagino 	 * it is possible we have false information.
1188686cdd19SJun-ichiro itojun Hagino 	 */
1189686cdd19SJun-ichiro itojun Hagino 	if (!force) {
1190686cdd19SJun-ichiro itojun Hagino 		ln->ln_byhint++;
11916e6b3f7cSQing Li 		if (ln->ln_byhint > V_nd6_maxnudhint) {
11926e6b3f7cSQing Li 			goto done;
11936e6b3f7cSQing Li 		}
1194686cdd19SJun-ichiro itojun Hagino 	}
1195686cdd19SJun-ichiro itojun Hagino 
119682cd038dSYoshinobu Inoue  	ln->ln_state = ND6_LLINFO_REACHABLE;
1197743eee66SSUZUKI Shinsuke 	if (!ND6_LLINFO_PERMANENT(ln)) {
1198d715e397SBjoern A. Zeeb 		nd6_llinfo_settimer_locked(ln,
1199743eee66SSUZUKI Shinsuke 		    (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
1200743eee66SSUZUKI Shinsuke 	}
12016e6b3f7cSQing Li done:
12026e6b3f7cSQing Li 	LLE_WUNLOCK(ln);
120382cd038dSYoshinobu Inoue }
120482cd038dSYoshinobu Inoue 
120582cd038dSYoshinobu Inoue 
12060f1aca65SQing Li /*
12070f1aca65SQing Li  * Rejuvenate this function for routing operations related
12080f1aca65SQing Li  * processing.
12090f1aca65SQing Li  */
12100f1aca65SQing Li void
12110f1aca65SQing Li nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
12120f1aca65SQing Li {
121339e19560SBjoern A. Zeeb 	struct sockaddr_in6 *gateway;
12140f1aca65SQing Li 	struct nd_defrouter *dr;
121539e19560SBjoern A. Zeeb 	struct ifnet *ifp;
12160f1aca65SQing Li 
121739e19560SBjoern A. Zeeb 	gateway = (struct sockaddr_in6 *)rt->rt_gateway;
121839e19560SBjoern A. Zeeb 	ifp = rt->rt_ifp;
12190f1aca65SQing Li 
12200f1aca65SQing Li 	switch (req) {
12210f1aca65SQing Li 	case RTM_ADD:
12220f1aca65SQing Li 		break;
12230f1aca65SQing Li 
12240f1aca65SQing Li 	case RTM_DELETE:
12250f1aca65SQing Li 		if (!ifp)
12260f1aca65SQing Li 			return;
12270f1aca65SQing Li 		/*
12280f1aca65SQing Li 		 * Only indirect routes are interesting.
12290f1aca65SQing Li 		 */
12300f1aca65SQing Li 		if ((rt->rt_flags & RTF_GATEWAY) == 0)
12310f1aca65SQing Li 			return;
12320f1aca65SQing Li 		/*
12330f1aca65SQing Li 		 * check for default route
12340f1aca65SQing Li 		 */
12350f1aca65SQing Li 		if (IN6_ARE_ADDR_EQUAL(&in6addr_any,
12360f1aca65SQing Li 				       &SIN6(rt_key(rt))->sin6_addr)) {
12370f1aca65SQing Li 
12380f1aca65SQing Li 			dr = defrouter_lookup(&gateway->sin6_addr, ifp);
12390f1aca65SQing Li 			if (dr != NULL)
12400f1aca65SQing Li 				dr->installed = 0;
12410f1aca65SQing Li 		}
12420f1aca65SQing Li 		break;
12430f1aca65SQing Li 	}
12440f1aca65SQing Li }
12450f1aca65SQing Li 
12460f1aca65SQing Li 
124782cd038dSYoshinobu Inoue int
12481272577eSXin LI nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
124982cd038dSYoshinobu Inoue {
125082cd038dSYoshinobu Inoue 	struct in6_drlist *drl = (struct in6_drlist *)data;
1251f95d4633SHajimu UMEMOTO 	struct in6_oprlist *oprl = (struct in6_oprlist *)data;
125282cd038dSYoshinobu Inoue 	struct in6_ndireq *ndi = (struct in6_ndireq *)data;
125382cd038dSYoshinobu Inoue 	struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
1254686cdd19SJun-ichiro itojun Hagino 	struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
1255743eee66SSUZUKI Shinsuke 	struct nd_defrouter *dr;
125682cd038dSYoshinobu Inoue 	struct nd_prefix *pr;
125782cd038dSYoshinobu Inoue 	int i = 0, error = 0;
125882cd038dSYoshinobu Inoue 
12590de0dd9bSHiroki Sato 	if (ifp->if_afdata[AF_INET6] == NULL)
12600de0dd9bSHiroki Sato 		return (EPFNOSUPPORT);
126182cd038dSYoshinobu Inoue 	switch (cmd) {
126282cd038dSYoshinobu Inoue 	case SIOCGDRLST_IN6:
126333841545SHajimu UMEMOTO 		/*
126433841545SHajimu UMEMOTO 		 * obsolete API, use sysctl under net.inet6.icmp6
126533841545SHajimu UMEMOTO 		 */
126682cd038dSYoshinobu Inoue 		bzero(drl, sizeof(*drl));
12673b0b2840SJohn Baldwin 		TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
12683b0b2840SJohn Baldwin 			if (i >= DRLSTSIZ)
12693b0b2840SJohn Baldwin 				break;
127082cd038dSYoshinobu Inoue 			drl->defrouter[i].rtaddr = dr->rtaddr;
1271f95d4633SHajimu UMEMOTO 			in6_clearscope(&drl->defrouter[i].rtaddr);
127282cd038dSYoshinobu Inoue 
127382cd038dSYoshinobu Inoue 			drl->defrouter[i].flags = dr->flags;
127482cd038dSYoshinobu Inoue 			drl->defrouter[i].rtlifetime = dr->rtlifetime;
1275ffa0165aSHiroki Sato 			drl->defrouter[i].expire = dr->expire +
1276ffa0165aSHiroki Sato 			    (time_second - time_uptime);
127782cd038dSYoshinobu Inoue 			drl->defrouter[i].if_index = dr->ifp->if_index;
127882cd038dSYoshinobu Inoue 			i++;
127982cd038dSYoshinobu Inoue 		}
128082cd038dSYoshinobu Inoue 		break;
128182cd038dSYoshinobu Inoue 	case SIOCGPRLST_IN6:
1282686cdd19SJun-ichiro itojun Hagino 		/*
128333841545SHajimu UMEMOTO 		 * obsolete API, use sysctl under net.inet6.icmp6
1284f95d4633SHajimu UMEMOTO 		 *
1285f95d4633SHajimu UMEMOTO 		 * XXX the structure in6_prlist was changed in backward-
1286f95d4633SHajimu UMEMOTO 		 * incompatible manner.  in6_oprlist is used for SIOCGPRLST_IN6,
1287f95d4633SHajimu UMEMOTO 		 * in6_prlist is used for nd6_sysctl() - fill_prlist().
128833841545SHajimu UMEMOTO 		 */
128933841545SHajimu UMEMOTO 		/*
1290686cdd19SJun-ichiro itojun Hagino 		 * XXX meaning of fields, especialy "raflags", is very
1291686cdd19SJun-ichiro itojun Hagino 		 * differnet between RA prefix list and RR/static prefix list.
1292686cdd19SJun-ichiro itojun Hagino 		 * how about separating ioctls into two?
1293686cdd19SJun-ichiro itojun Hagino 		 */
1294f95d4633SHajimu UMEMOTO 		bzero(oprl, sizeof(*oprl));
12953b0b2840SJohn Baldwin 		LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
129682cd038dSYoshinobu Inoue 			struct nd_pfxrouter *pfr;
129782cd038dSYoshinobu Inoue 			int j;
129882cd038dSYoshinobu Inoue 
12993b0b2840SJohn Baldwin 			if (i >= PRLSTSIZ)
13003b0b2840SJohn Baldwin 				break;
1301a1f7e5f8SHajimu UMEMOTO 			oprl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
1302f95d4633SHajimu UMEMOTO 			oprl->prefix[i].raflags = pr->ndpr_raf;
1303f95d4633SHajimu UMEMOTO 			oprl->prefix[i].prefixlen = pr->ndpr_plen;
1304f95d4633SHajimu UMEMOTO 			oprl->prefix[i].vltime = pr->ndpr_vltime;
1305f95d4633SHajimu UMEMOTO 			oprl->prefix[i].pltime = pr->ndpr_pltime;
1306f95d4633SHajimu UMEMOTO 			oprl->prefix[i].if_index = pr->ndpr_ifp->if_index;
1307743eee66SSUZUKI Shinsuke 			if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
1308743eee66SSUZUKI Shinsuke 				oprl->prefix[i].expire = 0;
1309743eee66SSUZUKI Shinsuke 			else {
1310743eee66SSUZUKI Shinsuke 				time_t maxexpire;
1311743eee66SSUZUKI Shinsuke 
1312743eee66SSUZUKI Shinsuke 				/* XXX: we assume time_t is signed. */
1313743eee66SSUZUKI Shinsuke 				maxexpire = (-1) &
131436dc24e6SSUZUKI Shinsuke 				    ~((time_t)1 <<
131536dc24e6SSUZUKI Shinsuke 				    ((sizeof(maxexpire) * 8) - 1));
1316743eee66SSUZUKI Shinsuke 				if (pr->ndpr_vltime <
1317743eee66SSUZUKI Shinsuke 				    maxexpire - pr->ndpr_lastupdate) {
1318743eee66SSUZUKI Shinsuke 					oprl->prefix[i].expire =
1319743eee66SSUZUKI Shinsuke 					    pr->ndpr_lastupdate +
1320ffa0165aSHiroki Sato 					    pr->ndpr_vltime +
1321ffa0165aSHiroki Sato 					    (time_second - time_uptime);
1322743eee66SSUZUKI Shinsuke 				} else
1323743eee66SSUZUKI Shinsuke 					oprl->prefix[i].expire = maxexpire;
1324743eee66SSUZUKI Shinsuke 			}
132582cd038dSYoshinobu Inoue 
132682cd038dSYoshinobu Inoue 			j = 0;
13273b0b2840SJohn Baldwin 			LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
132882cd038dSYoshinobu Inoue 				if (j < DRLSTSIZ) {
1329f95d4633SHajimu UMEMOTO #define RTRADDR oprl->prefix[i].advrtr[j]
133082cd038dSYoshinobu Inoue 					RTRADDR = pfr->router->rtaddr;
1331f95d4633SHajimu UMEMOTO 					in6_clearscope(&RTRADDR);
133282cd038dSYoshinobu Inoue #undef RTRADDR
133382cd038dSYoshinobu Inoue 				}
133482cd038dSYoshinobu Inoue 				j++;
133582cd038dSYoshinobu Inoue 			}
1336f95d4633SHajimu UMEMOTO 			oprl->prefix[i].advrtrs = j;
1337f95d4633SHajimu UMEMOTO 			oprl->prefix[i].origin = PR_ORIG_RA;
133882cd038dSYoshinobu Inoue 
133982cd038dSYoshinobu Inoue 			i++;
134082cd038dSYoshinobu Inoue 		}
134182cd038dSYoshinobu Inoue 
134282cd038dSYoshinobu Inoue 		break;
134333841545SHajimu UMEMOTO 	case OSIOCGIFINFO_IN6:
13442ce62dceSSUZUKI Shinsuke #define ND	ndi->ndi
134531b1bfe1SHajimu UMEMOTO 		/* XXX: old ndp(8) assumes a positive value for linkmtu. */
13462ce62dceSSUZUKI Shinsuke 		bzero(&ND, sizeof(ND));
13472ce62dceSSUZUKI Shinsuke 		ND.linkmtu = IN6_LINKMTU(ifp);
13482ce62dceSSUZUKI Shinsuke 		ND.maxmtu = ND_IFINFO(ifp)->maxmtu;
13492ce62dceSSUZUKI Shinsuke 		ND.basereachable = ND_IFINFO(ifp)->basereachable;
13502ce62dceSSUZUKI Shinsuke 		ND.reachable = ND_IFINFO(ifp)->reachable;
13512ce62dceSSUZUKI Shinsuke 		ND.retrans = ND_IFINFO(ifp)->retrans;
13522ce62dceSSUZUKI Shinsuke 		ND.flags = ND_IFINFO(ifp)->flags;
13532ce62dceSSUZUKI Shinsuke 		ND.recalctm = ND_IFINFO(ifp)->recalctm;
13542ce62dceSSUZUKI Shinsuke 		ND.chlim = ND_IFINFO(ifp)->chlim;
135533841545SHajimu UMEMOTO 		break;
135682cd038dSYoshinobu Inoue 	case SIOCGIFINFO_IN6:
13572ce62dceSSUZUKI Shinsuke 		ND = *ND_IFINFO(ifp);
135882cd038dSYoshinobu Inoue 		break;
1359b9204379SSUZUKI Shinsuke 	case SIOCSIFINFO_IN6:
1360b9204379SSUZUKI Shinsuke 		/*
1361b9204379SSUZUKI Shinsuke 		 * used to change host variables from userland.
1362b9204379SSUZUKI Shinsuke 		 * intented for a use on router to reflect RA configurations.
1363b9204379SSUZUKI Shinsuke 		 */
1364b9204379SSUZUKI Shinsuke 		/* 0 means 'unspecified' */
1365b9204379SSUZUKI Shinsuke 		if (ND.linkmtu != 0) {
1366b9204379SSUZUKI Shinsuke 			if (ND.linkmtu < IPV6_MMTU ||
1367b9204379SSUZUKI Shinsuke 			    ND.linkmtu > IN6_LINKMTU(ifp)) {
1368b9204379SSUZUKI Shinsuke 				error = EINVAL;
1369b9204379SSUZUKI Shinsuke 				break;
1370b9204379SSUZUKI Shinsuke 			}
1371b9204379SSUZUKI Shinsuke 			ND_IFINFO(ifp)->linkmtu = ND.linkmtu;
1372b9204379SSUZUKI Shinsuke 		}
1373b9204379SSUZUKI Shinsuke 
1374b9204379SSUZUKI Shinsuke 		if (ND.basereachable != 0) {
1375b9204379SSUZUKI Shinsuke 			int obasereachable = ND_IFINFO(ifp)->basereachable;
1376b9204379SSUZUKI Shinsuke 
1377b9204379SSUZUKI Shinsuke 			ND_IFINFO(ifp)->basereachable = ND.basereachable;
1378b9204379SSUZUKI Shinsuke 			if (ND.basereachable != obasereachable)
1379b9204379SSUZUKI Shinsuke 				ND_IFINFO(ifp)->reachable =
1380b9204379SSUZUKI Shinsuke 				    ND_COMPUTE_RTIME(ND.basereachable);
1381b9204379SSUZUKI Shinsuke 		}
1382b9204379SSUZUKI Shinsuke 		if (ND.retrans != 0)
1383b9204379SSUZUKI Shinsuke 			ND_IFINFO(ifp)->retrans = ND.retrans;
1384b9204379SSUZUKI Shinsuke 		if (ND.chlim != 0)
1385b9204379SSUZUKI Shinsuke 			ND_IFINFO(ifp)->chlim = ND.chlim;
1386b9204379SSUZUKI Shinsuke 		/* FALLTHROUGH */
1387686cdd19SJun-ichiro itojun Hagino 	case SIOCSIFINFO_FLAGS:
1388a283298cSHiroki Sato 	{
1389a283298cSHiroki Sato 		struct ifaddr *ifa;
1390a283298cSHiroki Sato 		struct in6_ifaddr *ia;
1391a283298cSHiroki Sato 
1392a283298cSHiroki Sato 		if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
1393a283298cSHiroki Sato 		    !(ND.flags & ND6_IFF_IFDISABLED)) {
1394a283298cSHiroki Sato 			/* ifdisabled 1->0 transision */
1395a283298cSHiroki Sato 
1396a283298cSHiroki Sato 			/*
1397a283298cSHiroki Sato 			 * If the interface is marked as ND6_IFF_IFDISABLED and
1398a283298cSHiroki Sato 			 * has an link-local address with IN6_IFF_DUPLICATED,
1399a283298cSHiroki Sato 			 * do not clear ND6_IFF_IFDISABLED.
1400a283298cSHiroki Sato 			 * See RFC 4862, Section 5.4.5.
1401a283298cSHiroki Sato 			 */
1402a283298cSHiroki Sato 			int duplicated_linklocal = 0;
1403a283298cSHiroki Sato 
1404137f91e8SJohn Baldwin 			IF_ADDR_RLOCK(ifp);
1405a283298cSHiroki Sato 			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1406a283298cSHiroki Sato 				if (ifa->ifa_addr->sa_family != AF_INET6)
1407a283298cSHiroki Sato 					continue;
1408a283298cSHiroki Sato 				ia = (struct in6_ifaddr *)ifa;
1409a283298cSHiroki Sato 				if ((ia->ia6_flags & IN6_IFF_DUPLICATED) &&
1410e7fa8d0aSHiroki Sato 				    IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) {
1411a283298cSHiroki Sato 					duplicated_linklocal = 1;
1412a283298cSHiroki Sato 					break;
1413a283298cSHiroki Sato 				}
1414a283298cSHiroki Sato 			}
1415137f91e8SJohn Baldwin 			IF_ADDR_RUNLOCK(ifp);
1416a283298cSHiroki Sato 
1417a283298cSHiroki Sato 			if (duplicated_linklocal) {
1418a283298cSHiroki Sato 				ND.flags |= ND6_IFF_IFDISABLED;
1419a283298cSHiroki Sato 				log(LOG_ERR, "Cannot enable an interface"
1420a283298cSHiroki Sato 				    " with a link-local address marked"
1421a283298cSHiroki Sato 				    " duplicate.\n");
1422a283298cSHiroki Sato 			} else {
1423a283298cSHiroki Sato 				ND_IFINFO(ifp)->flags &= ~ND6_IFF_IFDISABLED;
1424154d5f73SHiroki Sato 				if (ifp->if_flags & IFF_UP)
1425a283298cSHiroki Sato 					in6_if_up(ifp);
1426a283298cSHiroki Sato 			}
1427a283298cSHiroki Sato 		} else if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
1428a283298cSHiroki Sato 			    (ND.flags & ND6_IFF_IFDISABLED)) {
1429a283298cSHiroki Sato 			/* ifdisabled 0->1 transision */
1430a283298cSHiroki Sato 			/* Mark all IPv6 address as tentative. */
1431a283298cSHiroki Sato 
1432a283298cSHiroki Sato 			ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1433137f91e8SJohn Baldwin 			IF_ADDR_RLOCK(ifp);
1434a283298cSHiroki Sato 			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1435a283298cSHiroki Sato 				if (ifa->ifa_addr->sa_family != AF_INET6)
1436a283298cSHiroki Sato 					continue;
1437a283298cSHiroki Sato 				ia = (struct in6_ifaddr *)ifa;
1438a283298cSHiroki Sato 				ia->ia6_flags |= IN6_IFF_TENTATIVE;
1439a283298cSHiroki Sato 			}
1440137f91e8SJohn Baldwin 			IF_ADDR_RUNLOCK(ifp);
1441a283298cSHiroki Sato 		}
1442a283298cSHiroki Sato 
1443154d5f73SHiroki Sato 		if (ND.flags & ND6_IFF_AUTO_LINKLOCAL) {
1444154d5f73SHiroki Sato 			if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)) {
1445a283298cSHiroki Sato 				/* auto_linklocal 0->1 transision */
1446a283298cSHiroki Sato 
1447a283298cSHiroki Sato 				/* If no link-local address on ifp, configure */
1448a283298cSHiroki Sato 				ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL;
1449a283298cSHiroki Sato 				in6_ifattach(ifp, NULL);
1450154d5f73SHiroki Sato 			} else if (!(ND.flags & ND6_IFF_IFDISABLED) &&
1451154d5f73SHiroki Sato 			    ifp->if_flags & IFF_UP) {
145277bc4985SHiroki Sato 				/*
145377bc4985SHiroki Sato 				 * When the IF already has
1454154d5f73SHiroki Sato 				 * ND6_IFF_AUTO_LINKLOCAL, no link-local
1455154d5f73SHiroki Sato 				 * address is assigned, and IFF_UP, try to
1456154d5f73SHiroki Sato 				 * assign one.
145777bc4985SHiroki Sato 				 */
145877bc4985SHiroki Sato 				int haslinklocal = 0;
145977bc4985SHiroki Sato 
1460137f91e8SJohn Baldwin 				IF_ADDR_RLOCK(ifp);
146177bc4985SHiroki Sato 				TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
146277bc4985SHiroki Sato 					if (ifa->ifa_addr->sa_family != AF_INET6)
146377bc4985SHiroki Sato 						continue;
146477bc4985SHiroki Sato 					ia = (struct in6_ifaddr *)ifa;
146577bc4985SHiroki Sato 					if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) {
146677bc4985SHiroki Sato 						haslinklocal = 1;
146777bc4985SHiroki Sato 						break;
146877bc4985SHiroki Sato 					}
146977bc4985SHiroki Sato 				}
1470137f91e8SJohn Baldwin 				IF_ADDR_RUNLOCK(ifp);
147177bc4985SHiroki Sato 				if (!haslinklocal)
147277bc4985SHiroki Sato 					in6_ifattach(ifp, NULL);
1473a283298cSHiroki Sato 			}
1474a283298cSHiroki Sato 		}
1475154d5f73SHiroki Sato 	}
14762ce62dceSSUZUKI Shinsuke 		ND_IFINFO(ifp)->flags = ND.flags;
1477686cdd19SJun-ichiro itojun Hagino 		break;
14782ce62dceSSUZUKI Shinsuke #undef ND
1479686cdd19SJun-ichiro itojun Hagino 	case SIOCSNDFLUSH_IN6:	/* XXX: the ioctl name is confusing... */
1480743eee66SSUZUKI Shinsuke 		/* sync kernel routing table with the default router list */
1481743eee66SSUZUKI Shinsuke 		defrouter_reset();
1482686cdd19SJun-ichiro itojun Hagino 		defrouter_select();
148382cd038dSYoshinobu Inoue 		break;
148482cd038dSYoshinobu Inoue 	case SIOCSPFXFLUSH_IN6:
148582cd038dSYoshinobu Inoue 	{
148682cd038dSYoshinobu Inoue 		/* flush all the prefix advertised by routers */
148782cd038dSYoshinobu Inoue 		struct nd_prefix *pr, *next;
148882cd038dSYoshinobu Inoue 
14893b0b2840SJohn Baldwin 		LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, next) {
149033841545SHajimu UMEMOTO 			struct in6_ifaddr *ia, *ia_next;
149133841545SHajimu UMEMOTO 
149233841545SHajimu UMEMOTO 			if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
149333841545SHajimu UMEMOTO 				continue; /* XXX */
149433841545SHajimu UMEMOTO 
149533841545SHajimu UMEMOTO 			/* do we really have to remove addresses as well? */
1496d1da0a06SRobert Watson 			/* XXXRW: in6_ifaddrhead locking. */
149780af0152SRobert Watson 			TAILQ_FOREACH_SAFE(ia, &V_in6_ifaddrhead, ia_link,
149880af0152SRobert Watson 			    ia_next) {
149933841545SHajimu UMEMOTO 				if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
150033841545SHajimu UMEMOTO 					continue;
150133841545SHajimu UMEMOTO 
150233841545SHajimu UMEMOTO 				if (ia->ia6_ndpr == pr)
150333841545SHajimu UMEMOTO 					in6_purgeaddr(&ia->ia_ifa);
150433841545SHajimu UMEMOTO 			}
150582cd038dSYoshinobu Inoue 			prelist_remove(pr);
150682cd038dSYoshinobu Inoue 		}
150782cd038dSYoshinobu Inoue 		break;
150882cd038dSYoshinobu Inoue 	}
150982cd038dSYoshinobu Inoue 	case SIOCSRTRFLUSH_IN6:
151082cd038dSYoshinobu Inoue 	{
151182cd038dSYoshinobu Inoue 		/* flush all the default routers */
151282cd038dSYoshinobu Inoue 		struct nd_defrouter *dr, *next;
151382cd038dSYoshinobu Inoue 
1514743eee66SSUZUKI Shinsuke 		defrouter_reset();
15153b0b2840SJohn Baldwin 		TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, next) {
151682cd038dSYoshinobu Inoue 			defrtrlist_del(dr);
151782cd038dSYoshinobu Inoue 		}
1518743eee66SSUZUKI Shinsuke 		defrouter_select();
151982cd038dSYoshinobu Inoue 		break;
152082cd038dSYoshinobu Inoue 	}
152182cd038dSYoshinobu Inoue 	case SIOCGNBRINFO_IN6:
152282cd038dSYoshinobu Inoue 	{
15236e6b3f7cSQing Li 		struct llentry *ln;
152482cd038dSYoshinobu Inoue 		struct in6_addr nb_addr = nbi->addr; /* make local for safety */
152582cd038dSYoshinobu Inoue 
1526a1f7e5f8SHajimu UMEMOTO 		if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
1527a1f7e5f8SHajimu UMEMOTO 			return (error);
152882cd038dSYoshinobu Inoue 
152973cb2f38SAndrey V. Elsukov 		IF_AFDATA_RLOCK(ifp);
15306e6b3f7cSQing Li 		ln = nd6_lookup(&nb_addr, 0, ifp);
153173cb2f38SAndrey V. Elsukov 		IF_AFDATA_RUNLOCK(ifp);
15326e6b3f7cSQing Li 
15336e6b3f7cSQing Li 		if (ln == NULL) {
153482cd038dSYoshinobu Inoue 			error = EINVAL;
153582cd038dSYoshinobu Inoue 			break;
153682cd038dSYoshinobu Inoue 		}
153782cd038dSYoshinobu Inoue 		nbi->state = ln->ln_state;
15386e6b3f7cSQing Li 		nbi->asked = ln->la_asked;
153982cd038dSYoshinobu Inoue 		nbi->isrouter = ln->ln_router;
15405a041915SHiroki Sato 		if (ln->la_expire == 0)
15415a041915SHiroki Sato 			nbi->expire = 0;
15425a041915SHiroki Sato 		else
15435a041915SHiroki Sato 			nbi->expire = ln->la_expire +
15445a041915SHiroki Sato 			    (time_second - time_uptime);
15456e6b3f7cSQing Li 		LLE_RUNLOCK(ln);
154682cd038dSYoshinobu Inoue 		break;
154782cd038dSYoshinobu Inoue 	}
1548686cdd19SJun-ichiro itojun Hagino 	case SIOCGDEFIFACE_IN6:	/* XXX: should be implemented as a sysctl? */
1549603724d3SBjoern A. Zeeb 		ndif->ifindex = V_nd6_defifindex;
1550686cdd19SJun-ichiro itojun Hagino 		break;
1551686cdd19SJun-ichiro itojun Hagino 	case SIOCSDEFIFACE_IN6:	/* XXX: should be implemented as a sysctl? */
1552686cdd19SJun-ichiro itojun Hagino 		return (nd6_setdefaultiface(ndif->ifindex));
155382cd038dSYoshinobu Inoue 	}
155482cd038dSYoshinobu Inoue 	return (error);
155582cd038dSYoshinobu Inoue }
155682cd038dSYoshinobu Inoue 
155782cd038dSYoshinobu Inoue /*
155882cd038dSYoshinobu Inoue  * Create neighbor cache entry and cache link-layer address,
155982cd038dSYoshinobu Inoue  * on reception of inbound ND6 packets.  (RS/RA/NS/redirect)
15601272577eSXin LI  *
15611272577eSXin LI  * type - ICMP6 type
15621272577eSXin LI  * code - type dependent information
15636e6b3f7cSQing Li  *
15646e6b3f7cSQing Li  * XXXXX
15656e6b3f7cSQing Li  *  The caller of this function already acquired the ndp
15666e6b3f7cSQing Li  *  cache table lock because the cache entry is returned.
156782cd038dSYoshinobu Inoue  */
15686e6b3f7cSQing Li struct llentry *
15691272577eSXin LI nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
15701272577eSXin LI     int lladdrlen, int type, int code)
157182cd038dSYoshinobu Inoue {
15726e6b3f7cSQing Li 	struct llentry *ln = NULL;
157382cd038dSYoshinobu Inoue 	int is_newentry;
157482cd038dSYoshinobu Inoue 	int do_update;
157582cd038dSYoshinobu Inoue 	int olladdr;
157682cd038dSYoshinobu Inoue 	int llchange;
157768352503SBjoern A. Zeeb 	int flags;
157882cd038dSYoshinobu Inoue 	int newstate = 0;
15793d3728e9SQing Li 	uint16_t router = 0;
15806e6b3f7cSQing Li 	struct sockaddr_in6 sin6;
1581fd14c50bSKip Macy 	struct mbuf *chain = NULL;
15823d3728e9SQing Li 	int static_route = 0;
15836e6b3f7cSQing Li 
15846e6b3f7cSQing Li 	IF_AFDATA_UNLOCK_ASSERT(ifp);
158582cd038dSYoshinobu Inoue 
158639e19560SBjoern A. Zeeb 	KASSERT(ifp != NULL, ("%s: ifp == NULL", __func__));
158739e19560SBjoern A. Zeeb 	KASSERT(from != NULL, ("%s: from == NULL", __func__));
158882cd038dSYoshinobu Inoue 
158982cd038dSYoshinobu Inoue 	/* nothing must be updated for unspecified address */
159082cd038dSYoshinobu Inoue 	if (IN6_IS_ADDR_UNSPECIFIED(from))
159182cd038dSYoshinobu Inoue 		return NULL;
159282cd038dSYoshinobu Inoue 
159382cd038dSYoshinobu Inoue 	/*
159482cd038dSYoshinobu Inoue 	 * Validation about ifp->if_addrlen and lladdrlen must be done in
159582cd038dSYoshinobu Inoue 	 * the caller.
159682cd038dSYoshinobu Inoue 	 *
159782cd038dSYoshinobu Inoue 	 * XXX If the link does not have link-layer adderss, what should
159882cd038dSYoshinobu Inoue 	 * we do? (ifp->if_addrlen == 0)
159982cd038dSYoshinobu Inoue 	 * Spec says nothing in sections for RA, RS and NA.  There's small
160082cd038dSYoshinobu Inoue 	 * description on it in NS section (RFC 2461 7.2.3).
160182cd038dSYoshinobu Inoue 	 */
160268352503SBjoern A. Zeeb 	flags = lladdr ? ND6_EXCLUSIVE : 0;
1603ea0c3776SAndrey V. Elsukov 	IF_AFDATA_RLOCK(ifp);
16046e6b3f7cSQing Li 	ln = nd6_lookup(from, flags, ifp);
1605ea0c3776SAndrey V. Elsukov 	IF_AFDATA_RUNLOCK(ifp);
16066e6b3f7cSQing Li 	if (ln == NULL) {
160768352503SBjoern A. Zeeb 		flags |= ND6_EXCLUSIVE;
1608ea0c3776SAndrey V. Elsukov 		IF_AFDATA_LOCK(ifp);
16096e6b3f7cSQing Li 		ln = nd6_lookup(from, flags | ND6_CREATE, ifp);
16106e6b3f7cSQing Li 		IF_AFDATA_UNLOCK(ifp);
161182cd038dSYoshinobu Inoue 		is_newentry = 1;
161233841545SHajimu UMEMOTO 	} else {
161333841545SHajimu UMEMOTO 		/* do nothing if static ndp is set */
16143d3728e9SQing Li 		if (ln->la_flags & LLE_STATIC) {
16153d3728e9SQing Li 			static_route = 1;
16166e6b3f7cSQing Li 			goto done;
16173d3728e9SQing Li 		}
161882cd038dSYoshinobu Inoue 		is_newentry = 0;
161933841545SHajimu UMEMOTO 	}
16202ce62dceSSUZUKI Shinsuke 	if (ln == NULL)
16216e6b3f7cSQing Li 		return (NULL);
162282cd038dSYoshinobu Inoue 
16236e6b3f7cSQing Li 	olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
162482cd038dSYoshinobu Inoue 	if (olladdr && lladdr) {
16256e6b3f7cSQing Li 		llchange = bcmp(lladdr, &ln->ll_addr,
16266e6b3f7cSQing Li 		    ifp->if_addrlen);
162782cd038dSYoshinobu Inoue 	} else
162882cd038dSYoshinobu Inoue 		llchange = 0;
162982cd038dSYoshinobu Inoue 
163082cd038dSYoshinobu Inoue 	/*
163182cd038dSYoshinobu Inoue 	 * newentry olladdr  lladdr  llchange	(*=record)
163282cd038dSYoshinobu Inoue 	 *	0	n	n	--	(1)
163382cd038dSYoshinobu Inoue 	 *	0	y	n	--	(2)
163482cd038dSYoshinobu Inoue 	 *	0	n	y	--	(3) * STALE
163582cd038dSYoshinobu Inoue 	 *	0	y	y	n	(4) *
163682cd038dSYoshinobu Inoue 	 *	0	y	y	y	(5) * STALE
163782cd038dSYoshinobu Inoue 	 *	1	--	n	--	(6)   NOSTATE(= PASSIVE)
163882cd038dSYoshinobu Inoue 	 *	1	--	y	--	(7) * STALE
163982cd038dSYoshinobu Inoue 	 */
164082cd038dSYoshinobu Inoue 
164182cd038dSYoshinobu Inoue 	if (lladdr) {		/* (3-5) and (7) */
164282cd038dSYoshinobu Inoue 		/*
164382cd038dSYoshinobu Inoue 		 * Record source link-layer address
164482cd038dSYoshinobu Inoue 		 * XXX is it dependent to ifp->if_type?
164582cd038dSYoshinobu Inoue 		 */
16466e6b3f7cSQing Li 		bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
16476e6b3f7cSQing Li 		ln->la_flags |= LLE_VALID;
164863a97a40SNavdeep Parhar 		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
164982cd038dSYoshinobu Inoue 	}
165082cd038dSYoshinobu Inoue 
165182cd038dSYoshinobu Inoue 	if (!is_newentry) {
16522ce62dceSSUZUKI Shinsuke 		if ((!olladdr && lladdr != NULL) ||	/* (3) */
16532ce62dceSSUZUKI Shinsuke 		    (olladdr && lladdr != NULL && llchange)) {	/* (5) */
165482cd038dSYoshinobu Inoue 			do_update = 1;
165582cd038dSYoshinobu Inoue 			newstate = ND6_LLINFO_STALE;
165682cd038dSYoshinobu Inoue 		} else					/* (1-2,4) */
165782cd038dSYoshinobu Inoue 			do_update = 0;
165882cd038dSYoshinobu Inoue 	} else {
165982cd038dSYoshinobu Inoue 		do_update = 1;
16602ce62dceSSUZUKI Shinsuke 		if (lladdr == NULL)			/* (6) */
166182cd038dSYoshinobu Inoue 			newstate = ND6_LLINFO_NOSTATE;
166282cd038dSYoshinobu Inoue 		else					/* (7) */
166382cd038dSYoshinobu Inoue 			newstate = ND6_LLINFO_STALE;
166482cd038dSYoshinobu Inoue 	}
166582cd038dSYoshinobu Inoue 
166682cd038dSYoshinobu Inoue 	if (do_update) {
166782cd038dSYoshinobu Inoue 		/*
166882cd038dSYoshinobu Inoue 		 * Update the state of the neighbor cache.
166982cd038dSYoshinobu Inoue 		 */
167082cd038dSYoshinobu Inoue 		ln->ln_state = newstate;
167182cd038dSYoshinobu Inoue 
167282cd038dSYoshinobu Inoue 		if (ln->ln_state == ND6_LLINFO_STALE) {
1673d7968c29SAlexander V. Chernikov 			if (ln->la_hold != NULL)
1674d7968c29SAlexander V. Chernikov 				nd6_grab_holdchain(ln, &chain, &sin6);
167582cd038dSYoshinobu Inoue 		} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
167682cd038dSYoshinobu Inoue 			/* probe right away */
16776e6b3f7cSQing Li 			nd6_llinfo_settimer_locked((void *)ln, 0);
167882cd038dSYoshinobu Inoue 		}
167982cd038dSYoshinobu Inoue 	}
168082cd038dSYoshinobu Inoue 
168182cd038dSYoshinobu Inoue 	/*
168282cd038dSYoshinobu Inoue 	 * ICMP6 type dependent behavior.
168382cd038dSYoshinobu Inoue 	 *
168482cd038dSYoshinobu Inoue 	 * NS: clear IsRouter if new entry
168582cd038dSYoshinobu Inoue 	 * RS: clear IsRouter
168682cd038dSYoshinobu Inoue 	 * RA: set IsRouter if there's lladdr
168782cd038dSYoshinobu Inoue 	 * redir: clear IsRouter if new entry
168882cd038dSYoshinobu Inoue 	 *
168982cd038dSYoshinobu Inoue 	 * RA case, (1):
169082cd038dSYoshinobu Inoue 	 * The spec says that we must set IsRouter in the following cases:
169182cd038dSYoshinobu Inoue 	 * - If lladdr exist, set IsRouter.  This means (1-5).
169282cd038dSYoshinobu Inoue 	 * - If it is old entry (!newentry), set IsRouter.  This means (7).
169382cd038dSYoshinobu Inoue 	 * So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
169482cd038dSYoshinobu Inoue 	 * A quetion arises for (1) case.  (1) case has no lladdr in the
169582cd038dSYoshinobu Inoue 	 * neighbor cache, this is similar to (6).
169682cd038dSYoshinobu Inoue 	 * This case is rare but we figured that we MUST NOT set IsRouter.
169782cd038dSYoshinobu Inoue 	 *
169882cd038dSYoshinobu Inoue 	 * newentry olladdr  lladdr  llchange	    NS  RS  RA	redir
169982cd038dSYoshinobu Inoue 	 *							D R
170082cd038dSYoshinobu Inoue 	 *	0	n	n	--	(1)	c   ?     s
170182cd038dSYoshinobu Inoue 	 *	0	y	n	--	(2)	c   s     s
170282cd038dSYoshinobu Inoue 	 *	0	n	y	--	(3)	c   s     s
170382cd038dSYoshinobu Inoue 	 *	0	y	y	n	(4)	c   s     s
170482cd038dSYoshinobu Inoue 	 *	0	y	y	y	(5)	c   s     s
170582cd038dSYoshinobu Inoue 	 *	1	--	n	--	(6) c	c	c s
170682cd038dSYoshinobu Inoue 	 *	1	--	y	--	(7) c	c   s	c s
170782cd038dSYoshinobu Inoue 	 *
170882cd038dSYoshinobu Inoue 	 *					(c=clear s=set)
170982cd038dSYoshinobu Inoue 	 */
171082cd038dSYoshinobu Inoue 	switch (type & 0xff) {
171182cd038dSYoshinobu Inoue 	case ND_NEIGHBOR_SOLICIT:
171282cd038dSYoshinobu Inoue 		/*
171382cd038dSYoshinobu Inoue 		 * New entry must have is_router flag cleared.
171482cd038dSYoshinobu Inoue 		 */
171582cd038dSYoshinobu Inoue 		if (is_newentry)	/* (6-7) */
171682cd038dSYoshinobu Inoue 			ln->ln_router = 0;
171782cd038dSYoshinobu Inoue 		break;
171882cd038dSYoshinobu Inoue 	case ND_REDIRECT:
171982cd038dSYoshinobu Inoue 		/*
172082cd038dSYoshinobu Inoue 		 * If the icmp is a redirect to a better router, always set the
172182cd038dSYoshinobu Inoue 		 * is_router flag.  Otherwise, if the entry is newly created,
172282cd038dSYoshinobu Inoue 		 * clear the flag.  [RFC 2461, sec 8.3]
172382cd038dSYoshinobu Inoue 		 */
172482cd038dSYoshinobu Inoue 		if (code == ND_REDIRECT_ROUTER)
172582cd038dSYoshinobu Inoue 			ln->ln_router = 1;
172682cd038dSYoshinobu Inoue 		else if (is_newentry) /* (6-7) */
172782cd038dSYoshinobu Inoue 			ln->ln_router = 0;
172882cd038dSYoshinobu Inoue 		break;
172982cd038dSYoshinobu Inoue 	case ND_ROUTER_SOLICIT:
173082cd038dSYoshinobu Inoue 		/*
173182cd038dSYoshinobu Inoue 		 * is_router flag must always be cleared.
173282cd038dSYoshinobu Inoue 		 */
173382cd038dSYoshinobu Inoue 		ln->ln_router = 0;
173482cd038dSYoshinobu Inoue 		break;
173582cd038dSYoshinobu Inoue 	case ND_ROUTER_ADVERT:
173682cd038dSYoshinobu Inoue 		/*
173782cd038dSYoshinobu Inoue 		 * Mark an entry with lladdr as a router.
173882cd038dSYoshinobu Inoue 		 */
173907eb2995SHajimu UMEMOTO 		if ((!is_newentry && (olladdr || lladdr)) ||	/* (2-5) */
174007eb2995SHajimu UMEMOTO 		    (is_newentry && lladdr)) {			/* (7) */
174182cd038dSYoshinobu Inoue 			ln->ln_router = 1;
174282cd038dSYoshinobu Inoue 		}
174382cd038dSYoshinobu Inoue 		break;
174482cd038dSYoshinobu Inoue 	}
174582cd038dSYoshinobu Inoue 
174623ee1bfaSKip Macy 	if (ln != NULL) {
17473d3728e9SQing Li 		static_route = (ln->la_flags & LLE_STATIC);
1748c2b3a02bSKip Macy 		router = ln->ln_router;
1749c2b3a02bSKip Macy 
17506e6b3f7cSQing Li 		if (flags & ND6_EXCLUSIVE)
17516e6b3f7cSQing Li 			LLE_WUNLOCK(ln);
17526e6b3f7cSQing Li 		else
17536e6b3f7cSQing Li 			LLE_RUNLOCK(ln);
1754c2b3a02bSKip Macy 		if (static_route)
17556e6b3f7cSQing Li 			ln = NULL;
17566e6b3f7cSQing Li 	}
1757d7968c29SAlexander V. Chernikov 	if (chain != NULL)
1758d7968c29SAlexander V. Chernikov 		nd6_flush_holdchain(ifp, ifp, chain, &sin6);
17596e6b3f7cSQing Li 
1760554bf4aaSHajimu UMEMOTO 	/*
1761554bf4aaSHajimu UMEMOTO 	 * When the link-layer address of a router changes, select the
1762554bf4aaSHajimu UMEMOTO 	 * best router again.  In particular, when the neighbor entry is newly
1763554bf4aaSHajimu UMEMOTO 	 * created, it might affect the selection policy.
1764554bf4aaSHajimu UMEMOTO 	 * Question: can we restrict the first condition to the "is_newentry"
1765554bf4aaSHajimu UMEMOTO 	 * case?
1766554bf4aaSHajimu UMEMOTO 	 * XXX: when we hear an RA from a new router with the link-layer
1767554bf4aaSHajimu UMEMOTO 	 * address option, defrouter_select() is called twice, since
1768554bf4aaSHajimu UMEMOTO 	 * defrtrlist_update called the function as well.  However, I believe
1769554bf4aaSHajimu UMEMOTO 	 * we can compromise the overhead, since it only happens the first
1770554bf4aaSHajimu UMEMOTO 	 * time.
1771554bf4aaSHajimu UMEMOTO 	 * XXX: although defrouter_select() should not have a bad effect
1772554bf4aaSHajimu UMEMOTO 	 * for those are not autoconfigured hosts, we explicitly avoid such
1773554bf4aaSHajimu UMEMOTO 	 * cases for safety.
1774554bf4aaSHajimu UMEMOTO 	 */
1775e7fa8d0aSHiroki Sato 	if (do_update && router &&
1776a283298cSHiroki Sato 	    ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
17776e6b3f7cSQing Li 		/*
17786e6b3f7cSQing Li 		 * guaranteed recursion
17796e6b3f7cSQing Li 		 */
1780554bf4aaSHajimu UMEMOTO 		defrouter_select();
17816e6b3f7cSQing Li 	}
1782554bf4aaSHajimu UMEMOTO 
17836e6b3f7cSQing Li 	return (ln);
17846e6b3f7cSQing Li done:
1785aba53ef0SKip Macy 	if (ln != NULL) {
17866e6b3f7cSQing Li 		if (flags & ND6_EXCLUSIVE)
17876e6b3f7cSQing Li 			LLE_WUNLOCK(ln);
17886e6b3f7cSQing Li 		else
17896e6b3f7cSQing Li 			LLE_RUNLOCK(ln);
17903d3728e9SQing Li 		if (static_route)
17916e6b3f7cSQing Li 			ln = NULL;
17926e6b3f7cSQing Li 	}
17936e6b3f7cSQing Li 	return (ln);
179482cd038dSYoshinobu Inoue }
179582cd038dSYoshinobu Inoue 
179682cd038dSYoshinobu Inoue static void
17978b615593SMarko Zec nd6_slowtimo(void *arg)
179882cd038dSYoshinobu Inoue {
17998b615593SMarko Zec 	CURVNET_SET((struct vnet *) arg);
180033841545SHajimu UMEMOTO 	struct nd_ifinfo *nd6if;
180131b1bfe1SHajimu UMEMOTO 	struct ifnet *ifp;
180282cd038dSYoshinobu Inoue 
1803603724d3SBjoern A. Zeeb 	callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
1804f6dfe47aSMarko Zec 	    nd6_slowtimo, curvnet);
180577dfcdc4SRobert Watson 	IFNET_RLOCK_NOSLEEP();
1806e6abaf91SGleb Smirnoff 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
18070de0dd9bSHiroki Sato 		if (ifp->if_afdata[AF_INET6] == NULL)
18080de0dd9bSHiroki Sato 			continue;
180931b1bfe1SHajimu UMEMOTO 		nd6if = ND_IFINFO(ifp);
181082cd038dSYoshinobu Inoue 		if (nd6if->basereachable && /* already initialized */
181182cd038dSYoshinobu Inoue 		    (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
181282cd038dSYoshinobu Inoue 			/*
181382cd038dSYoshinobu Inoue 			 * Since reachable time rarely changes by router
181482cd038dSYoshinobu Inoue 			 * advertisements, we SHOULD insure that a new random
181582cd038dSYoshinobu Inoue 			 * value gets recomputed at least once every few hours.
181682cd038dSYoshinobu Inoue 			 * (RFC 2461, 6.3.4)
181782cd038dSYoshinobu Inoue 			 */
1818603724d3SBjoern A. Zeeb 			nd6if->recalctm = V_nd6_recalc_reachtm_interval;
181982cd038dSYoshinobu Inoue 			nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
182082cd038dSYoshinobu Inoue 		}
182182cd038dSYoshinobu Inoue 	}
182277dfcdc4SRobert Watson 	IFNET_RUNLOCK_NOSLEEP();
18238b615593SMarko Zec 	CURVNET_RESTORE();
182482cd038dSYoshinobu Inoue }
182582cd038dSYoshinobu Inoue 
1826d7968c29SAlexander V. Chernikov void
1827d7968c29SAlexander V. Chernikov nd6_grab_holdchain(struct llentry *ln, struct mbuf **chain,
1828d7968c29SAlexander V. Chernikov     struct sockaddr_in6 *sin6)
1829d7968c29SAlexander V. Chernikov {
1830d7968c29SAlexander V. Chernikov 
1831d7968c29SAlexander V. Chernikov 	LLE_WLOCK_ASSERT(ln);
1832d7968c29SAlexander V. Chernikov 
1833d7968c29SAlexander V. Chernikov 	*chain = ln->la_hold;
1834d7968c29SAlexander V. Chernikov 	ln->la_hold = NULL;
1835d7968c29SAlexander V. Chernikov 	memcpy(sin6, L3_ADDR_SIN6(ln), sizeof(*sin6));
1836d7968c29SAlexander V. Chernikov 
1837d7968c29SAlexander V. Chernikov 	if (ln->ln_state == ND6_LLINFO_STALE) {
1838d7968c29SAlexander V. Chernikov 
1839d7968c29SAlexander V. Chernikov 		/*
1840d7968c29SAlexander V. Chernikov 		 * The first time we send a packet to a
1841d7968c29SAlexander V. Chernikov 		 * neighbor whose entry is STALE, we have
1842d7968c29SAlexander V. Chernikov 		 * to change the state to DELAY and a sets
1843d7968c29SAlexander V. Chernikov 		 * a timer to expire in DELAY_FIRST_PROBE_TIME
1844d7968c29SAlexander V. Chernikov 		 * seconds to ensure do neighbor unreachability
1845d7968c29SAlexander V. Chernikov 		 * detection on expiration.
1846d7968c29SAlexander V. Chernikov 		 * (RFC 2461 7.3.3)
1847d7968c29SAlexander V. Chernikov 		 */
1848d7968c29SAlexander V. Chernikov 		ln->la_asked = 0;
1849d7968c29SAlexander V. Chernikov 		ln->ln_state = ND6_LLINFO_DELAY;
1850d7968c29SAlexander V. Chernikov 		nd6_llinfo_settimer_locked(ln, (long)V_nd6_delay * hz);
1851d7968c29SAlexander V. Chernikov 	}
1852d7968c29SAlexander V. Chernikov }
1853d7968c29SAlexander V. Chernikov 
1854d7968c29SAlexander V. Chernikov static int
1855d7968c29SAlexander V. Chernikov nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
1856d7968c29SAlexander V. Chernikov     struct sockaddr_in6 *dst)
1857d7968c29SAlexander V. Chernikov {
1858d7968c29SAlexander V. Chernikov 	int error;
1859d7968c29SAlexander V. Chernikov 	int ip6len;
1860d7968c29SAlexander V. Chernikov 	struct ip6_hdr *ip6;
1861d7968c29SAlexander V. Chernikov 	struct m_tag *mtag;
1862d7968c29SAlexander V. Chernikov 
1863d7968c29SAlexander V. Chernikov #ifdef MAC
1864d7968c29SAlexander V. Chernikov 	mac_netinet6_nd6_send(ifp, m);
1865d7968c29SAlexander V. Chernikov #endif
1866d7968c29SAlexander V. Chernikov 
1867d7968c29SAlexander V. Chernikov 	/*
1868d7968c29SAlexander V. Chernikov 	 * If called from nd6_ns_output() (NS), nd6_na_output() (NA),
1869d7968c29SAlexander V. Chernikov 	 * icmp6_redirect_output() (REDIRECT) or from rip6_output() (RS, RA
1870d7968c29SAlexander V. Chernikov 	 * as handled by rtsol and rtadvd), mbufs will be tagged for SeND
1871d7968c29SAlexander V. Chernikov 	 * to be diverted to user space.  When re-injected into the kernel,
1872d7968c29SAlexander V. Chernikov 	 * send_output() will directly dispatch them to the outgoing interface.
1873d7968c29SAlexander V. Chernikov 	 */
1874d7968c29SAlexander V. Chernikov 	if (send_sendso_input_hook != NULL) {
1875d7968c29SAlexander V. Chernikov 		mtag = m_tag_find(m, PACKET_TAG_ND_OUTGOING, NULL);
1876d7968c29SAlexander V. Chernikov 		if (mtag != NULL) {
1877d7968c29SAlexander V. Chernikov 			ip6 = mtod(m, struct ip6_hdr *);
1878d7968c29SAlexander V. Chernikov 			ip6len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
1879d7968c29SAlexander V. Chernikov 			/* Use the SEND socket */
1880d7968c29SAlexander V. Chernikov 			error = send_sendso_input_hook(m, ifp, SND_OUT,
1881d7968c29SAlexander V. Chernikov 			    ip6len);
1882d7968c29SAlexander V. Chernikov 			/* -1 == no app on SEND socket */
1883d7968c29SAlexander V. Chernikov 			if (error == 0 || error != -1)
1884d7968c29SAlexander V. Chernikov 			    return (error);
1885d7968c29SAlexander V. Chernikov 		}
1886d7968c29SAlexander V. Chernikov 	}
1887d7968c29SAlexander V. Chernikov 
1888d7968c29SAlexander V. Chernikov 	m_clrprotoflags(m);	/* Avoid confusing lower layers. */
1889d7968c29SAlexander V. Chernikov 	IP_PROBE(send, NULL, NULL, mtod(m, struct ip6_hdr *), ifp, NULL,
1890d7968c29SAlexander V. Chernikov 	    mtod(m, struct ip6_hdr *));
1891d7968c29SAlexander V. Chernikov 
1892d7968c29SAlexander V. Chernikov 	if ((ifp->if_flags & IFF_LOOPBACK) == 0)
1893d7968c29SAlexander V. Chernikov 		origifp = ifp;
1894d7968c29SAlexander V. Chernikov 
1895d7968c29SAlexander V. Chernikov 	error = (*ifp->if_output)(origifp, m, (struct sockaddr *)dst, NULL);
1896d7968c29SAlexander V. Chernikov 	return (error);
1897d7968c29SAlexander V. Chernikov }
1898d7968c29SAlexander V. Chernikov 
1899f6990c4eSAlexander V. Chernikov /*
1900f6990c4eSAlexander V. Chernikov  * IPv6 packet output - light version.
1901f6990c4eSAlexander V. Chernikov  * Checks if destination LLE exists and is in proper state
1902f6990c4eSAlexander V. Chernikov  * (e.g no modification required). If not true, fall back to
1903f6990c4eSAlexander V. Chernikov  * "heavy" version.
1904f6990c4eSAlexander V. Chernikov  */
190582cd038dSYoshinobu Inoue int
1906f6990c4eSAlexander V. Chernikov nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
19071272577eSXin LI     struct sockaddr_in6 *dst, struct rtentry *rt0)
190882cd038dSYoshinobu Inoue {
1909f6990c4eSAlexander V. Chernikov 	struct llentry *ln = NULL;
19106e6b3f7cSQing Li 
1911f6990c4eSAlexander V. Chernikov 	/* discard the packet if IPv6 operation is disabled on the interface */
1912f6990c4eSAlexander V. Chernikov 	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
1913f6990c4eSAlexander V. Chernikov 		m_freem(m);
1914f6990c4eSAlexander V. Chernikov 		return (ENETDOWN); /* better error? */
1915f6990c4eSAlexander V. Chernikov 	}
1916f6990c4eSAlexander V. Chernikov 
1917f6990c4eSAlexander V. Chernikov 	if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
1918f6990c4eSAlexander V. Chernikov 		goto sendpkt;
1919f6990c4eSAlexander V. Chernikov 
1920f6990c4eSAlexander V. Chernikov 	if (nd6_need_cache(ifp) == 0)
1921f6990c4eSAlexander V. Chernikov 		goto sendpkt;
1922f6990c4eSAlexander V. Chernikov 
1923f6990c4eSAlexander V. Chernikov 	IF_AFDATA_RLOCK(ifp);
1924f6990c4eSAlexander V. Chernikov 	ln = nd6_lookup(&dst->sin6_addr, 0, ifp);
1925f6990c4eSAlexander V. Chernikov 	IF_AFDATA_RUNLOCK(ifp);
1926f6990c4eSAlexander V. Chernikov 
1927f6990c4eSAlexander V. Chernikov 	/*
1928f6990c4eSAlexander V. Chernikov 	 * Perform fast path for the following cases:
1929f6990c4eSAlexander V. Chernikov 	 * 1) lle state is REACHABLE
1930f6990c4eSAlexander V. Chernikov 	 * 2) lle state is DELAY (NS message sentNS message sent)
1931f6990c4eSAlexander V. Chernikov 	 *
1932f6990c4eSAlexander V. Chernikov 	 * Every other case involves lle modification, so we handle
1933f6990c4eSAlexander V. Chernikov 	 * them separately.
1934f6990c4eSAlexander V. Chernikov 	 */
1935f6990c4eSAlexander V. Chernikov 	if (ln == NULL || (ln->ln_state != ND6_LLINFO_REACHABLE &&
1936f6990c4eSAlexander V. Chernikov 	    ln->ln_state != ND6_LLINFO_DELAY)) {
1937f6990c4eSAlexander V. Chernikov 		/* Fall back to slow processing path */
1938f6990c4eSAlexander V. Chernikov 		if (ln != NULL)
1939f6990c4eSAlexander V. Chernikov 			LLE_RUNLOCK(ln);
1940d7968c29SAlexander V. Chernikov 		return (nd6_output_lle(ifp, origifp, m, dst));
1941f6990c4eSAlexander V. Chernikov 	}
1942f6990c4eSAlexander V. Chernikov 
1943f6990c4eSAlexander V. Chernikov sendpkt:
1944f6990c4eSAlexander V. Chernikov 	if (ln != NULL)
1945f6990c4eSAlexander V. Chernikov 		LLE_RUNLOCK(ln);
1946f6990c4eSAlexander V. Chernikov 
1947d7968c29SAlexander V. Chernikov 	return (nd6_output_ifp(ifp, origifp, m, dst));
19486e6b3f7cSQing Li }
19496e6b3f7cSQing Li 
19506e6b3f7cSQing Li 
19516e6b3f7cSQing Li /*
1952f6990c4eSAlexander V. Chernikov  * Output IPv6 packet - heavy version.
1953f6990c4eSAlexander V. Chernikov  * Function assume that either
1954f6990c4eSAlexander V. Chernikov  * 1) destination LLE does not exist, is invalid or stale, so
1955f6990c4eSAlexander V. Chernikov  *   ND6_EXCLUSIVE lock needs to be acquired
1956f6990c4eSAlexander V. Chernikov  * 2) destination lle is provided (with ND6_EXCLUSIVE lock),
1957f6990c4eSAlexander V. Chernikov  *   in that case packets are queued in &chain.
19586e6b3f7cSQing Li  *
19596e6b3f7cSQing Li  */
1960d7968c29SAlexander V. Chernikov static int
1961f6990c4eSAlexander V. Chernikov nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
1962d7968c29SAlexander V. Chernikov     struct sockaddr_in6 *dst)
19636e6b3f7cSQing Li {
1964d7968c29SAlexander V. Chernikov 	struct llentry *lle = NULL;
19656e6b3f7cSQing Li 	int flags = 0;
196682cd038dSYoshinobu Inoue 
19679dffa6a3SAlexander V. Chernikov 	KASSERT(m != NULL, ("NULL mbuf, nothing to send"));
19689dffa6a3SAlexander V. Chernikov 	/* discard the packet if IPv6 operation is disabled on the interface */
19699dffa6a3SAlexander V. Chernikov 	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
19709dffa6a3SAlexander V. Chernikov 		m_freem(m);
19719dffa6a3SAlexander V. Chernikov 		return (ENETDOWN); /* better error? */
19729dffa6a3SAlexander V. Chernikov 	}
19739dffa6a3SAlexander V. Chernikov 
197482cd038dSYoshinobu Inoue 	if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
197582cd038dSYoshinobu Inoue 		goto sendpkt;
197682cd038dSYoshinobu Inoue 
197733841545SHajimu UMEMOTO 	if (nd6_need_cache(ifp) == 0)
197882cd038dSYoshinobu Inoue 		goto sendpkt;
197982cd038dSYoshinobu Inoue 
198082cd038dSYoshinobu Inoue 	/*
198182cd038dSYoshinobu Inoue 	 * Address resolution or Neighbor Unreachability Detection
198282cd038dSYoshinobu Inoue 	 * for the next hop.
198382cd038dSYoshinobu Inoue 	 * At this point, the destination of the packet must be a unicast
198482cd038dSYoshinobu Inoue 	 * or an anycast address(i.e. not a multicast).
198582cd038dSYoshinobu Inoue 	 */
1986f6990c4eSAlexander V. Chernikov 	if (lle == NULL) {
1987c445d252SAdrian Chadd 		IF_AFDATA_RLOCK(ifp);
1988f6990c4eSAlexander V. Chernikov 		lle = nd6_lookup(&dst->sin6_addr, ND6_EXCLUSIVE, ifp);
1989c445d252SAdrian Chadd 		IF_AFDATA_RUNLOCK(ifp);
1990f6990c4eSAlexander V. Chernikov 		if ((lle == NULL) && nd6_is_addr_neighbor(dst, ifp))  {
1991686cdd19SJun-ichiro itojun Hagino 			/*
1992686cdd19SJun-ichiro itojun Hagino 			 * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
1993686cdd19SJun-ichiro itojun Hagino 			 * the condition below is not very efficient.  But we believe
1994686cdd19SJun-ichiro itojun Hagino 			 * it is tolerable, because this should be a rare case.
1995686cdd19SJun-ichiro itojun Hagino 			 */
19969dffa6a3SAlexander V. Chernikov 			flags = ND6_CREATE | ND6_EXCLUSIVE;
1997bbd8aebaSQing Li 			IF_AFDATA_LOCK(ifp);
1998f6990c4eSAlexander V. Chernikov 			lle = nd6_lookup(&dst->sin6_addr, flags, ifp);
1999bbd8aebaSQing Li 			IF_AFDATA_UNLOCK(ifp);
200082cd038dSYoshinobu Inoue 		}
20016e6b3f7cSQing Li 	}
2002f6990c4eSAlexander V. Chernikov 	if (lle == NULL) {
2003686cdd19SJun-ichiro itojun Hagino 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
200431b1bfe1SHajimu UMEMOTO 		    !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
20051d54aa3bSBjoern A. Zeeb 			char ip6buf[INET6_ADDRSTRLEN];
2006686cdd19SJun-ichiro itojun Hagino 			log(LOG_DEBUG,
2007686cdd19SJun-ichiro itojun Hagino 			    "nd6_output: can't allocate llinfo for %s "
2008bbd8aebaSQing Li 			    "(ln=%p)\n",
2009f6990c4eSAlexander V. Chernikov 			    ip6_sprintf(ip6buf, &dst->sin6_addr), lle);
20109dffa6a3SAlexander V. Chernikov 			m_freem(m);
20119dffa6a3SAlexander V. Chernikov 			return (ENOBUFS);
201282cd038dSYoshinobu Inoue 		}
2013686cdd19SJun-ichiro itojun Hagino 		goto sendpkt;	/* send anyway */
2014686cdd19SJun-ichiro itojun Hagino 	}
2015686cdd19SJun-ichiro itojun Hagino 
2016f6990c4eSAlexander V. Chernikov 	LLE_WLOCK_ASSERT(lle);
2017f6990c4eSAlexander V. Chernikov 
2018686cdd19SJun-ichiro itojun Hagino 	/* We don't have to do link-layer address resolution on a p2p link. */
2019686cdd19SJun-ichiro itojun Hagino 	if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
2020f6990c4eSAlexander V. Chernikov 	    lle->ln_state < ND6_LLINFO_REACHABLE) {
2021f6990c4eSAlexander V. Chernikov 		lle->ln_state = ND6_LLINFO_STALE;
2022f6990c4eSAlexander V. Chernikov 		nd6_llinfo_settimer_locked(lle, (long)V_nd6_gctimer * hz);
202333841545SHajimu UMEMOTO 	}
202482cd038dSYoshinobu Inoue 
202582cd038dSYoshinobu Inoue 	/*
202682cd038dSYoshinobu Inoue 	 * The first time we send a packet to a neighbor whose entry is
202782cd038dSYoshinobu Inoue 	 * STALE, we have to change the state to DELAY and a sets a timer to
202882cd038dSYoshinobu Inoue 	 * expire in DELAY_FIRST_PROBE_TIME seconds to ensure do
202982cd038dSYoshinobu Inoue 	 * neighbor unreachability detection on expiration.
203082cd038dSYoshinobu Inoue 	 * (RFC 2461 7.3.3)
203182cd038dSYoshinobu Inoue 	 */
2032f6990c4eSAlexander V. Chernikov 	if (lle->ln_state == ND6_LLINFO_STALE) {
2033f6990c4eSAlexander V. Chernikov 		lle->la_asked = 0;
2034f6990c4eSAlexander V. Chernikov 		lle->ln_state = ND6_LLINFO_DELAY;
2035f6990c4eSAlexander V. Chernikov 		nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
203682cd038dSYoshinobu Inoue 	}
203782cd038dSYoshinobu Inoue 
203882cd038dSYoshinobu Inoue 	/*
203982cd038dSYoshinobu Inoue 	 * If the neighbor cache entry has a state other than INCOMPLETE
204088ff5695SSUZUKI Shinsuke 	 * (i.e. its link-layer address is already resolved), just
204182cd038dSYoshinobu Inoue 	 * send the packet.
204282cd038dSYoshinobu Inoue 	 */
2043f6990c4eSAlexander V. Chernikov 	if (lle->ln_state > ND6_LLINFO_INCOMPLETE)
204482cd038dSYoshinobu Inoue 		goto sendpkt;
204582cd038dSYoshinobu Inoue 
204682cd038dSYoshinobu Inoue 	/*
204782cd038dSYoshinobu Inoue 	 * There is a neighbor cache entry, but no ethernet address
2048743eee66SSUZUKI Shinsuke 	 * response yet.  Append this latest packet to the end of the
2049743eee66SSUZUKI Shinsuke 	 * packet queue in the mbuf, unless the number of the packet
2050743eee66SSUZUKI Shinsuke 	 * does not exceed nd6_maxqueuelen.  When it exceeds nd6_maxqueuelen,
2051743eee66SSUZUKI Shinsuke 	 * the oldest packet in the queue will be removed.
205282cd038dSYoshinobu Inoue 	 */
2053f6990c4eSAlexander V. Chernikov 	if (lle->ln_state == ND6_LLINFO_NOSTATE)
2054f6990c4eSAlexander V. Chernikov 		lle->ln_state = ND6_LLINFO_INCOMPLETE;
20556e6b3f7cSQing Li 
2056f6990c4eSAlexander V. Chernikov 	if (lle->la_hold != NULL) {
2057743eee66SSUZUKI Shinsuke 		struct mbuf *m_hold;
2058743eee66SSUZUKI Shinsuke 		int i;
2059743eee66SSUZUKI Shinsuke 
2060743eee66SSUZUKI Shinsuke 		i = 0;
2061f6990c4eSAlexander V. Chernikov 		for (m_hold = lle->la_hold; m_hold; m_hold = m_hold->m_nextpkt){
2062743eee66SSUZUKI Shinsuke 			i++;
2063743eee66SSUZUKI Shinsuke 			if (m_hold->m_nextpkt == NULL) {
2064743eee66SSUZUKI Shinsuke 				m_hold->m_nextpkt = m;
2065743eee66SSUZUKI Shinsuke 				break;
206682cd038dSYoshinobu Inoue 			}
206782cd038dSYoshinobu Inoue 		}
2068603724d3SBjoern A. Zeeb 		while (i >= V_nd6_maxqueuelen) {
2069f6990c4eSAlexander V. Chernikov 			m_hold = lle->la_hold;
2070f6990c4eSAlexander V. Chernikov 			lle->la_hold = lle->la_hold->m_nextpkt;
207131d4137bSSUZUKI Shinsuke 			m_freem(m_hold);
2072743eee66SSUZUKI Shinsuke 			i--;
2073743eee66SSUZUKI Shinsuke 		}
2074743eee66SSUZUKI Shinsuke 	} else {
2075f6990c4eSAlexander V. Chernikov 		lle->la_hold = m;
20766e6b3f7cSQing Li 	}
2077743eee66SSUZUKI Shinsuke 
2078743eee66SSUZUKI Shinsuke 	/*
2079743eee66SSUZUKI Shinsuke 	 * If there has been no NS for the neighbor after entering the
2080743eee66SSUZUKI Shinsuke 	 * INCOMPLETE state, send the first solicitation.
2081743eee66SSUZUKI Shinsuke 	 */
2082f6990c4eSAlexander V. Chernikov 	if (!ND6_LLINFO_PERMANENT(lle) && lle->la_asked == 0) {
2083f6990c4eSAlexander V. Chernikov 		lle->la_asked++;
20846e6b3f7cSQing Li 
2085f6990c4eSAlexander V. Chernikov 		nd6_llinfo_settimer_locked(lle,
2086743eee66SSUZUKI Shinsuke 		    (long)ND_IFINFO(ifp)->retrans * hz / 1000);
2087f6990c4eSAlexander V. Chernikov 		LLE_WUNLOCK(lle);
2088*11d8451dSHiroki Sato 		nd6_ns_output(ifp, NULL, &dst->sin6_addr, lle, NULL);
2089d7968c29SAlexander V. Chernikov 	} else {
2090d7968c29SAlexander V. Chernikov 		/* We did the lookup so we need to do the unlock here. */
2091f6990c4eSAlexander V. Chernikov 		LLE_WUNLOCK(lle);
2092743eee66SSUZUKI Shinsuke 	}
2093e6950476SBjoern A. Zeeb 
209482cd038dSYoshinobu Inoue 	return (0);
209582cd038dSYoshinobu Inoue 
209682cd038dSYoshinobu Inoue   sendpkt:
2097d7968c29SAlexander V. Chernikov 	if (lle != NULL)
2098f6990c4eSAlexander V. Chernikov 		LLE_WUNLOCK(lle);
20995b27b045SSUZUKI Shinsuke 
2100d7968c29SAlexander V. Chernikov 	return (nd6_output_ifp(ifp, origifp, m, dst));
210182cd038dSYoshinobu Inoue }
210282cd038dSYoshinobu Inoue 
21036e6b3f7cSQing Li 
21046e6b3f7cSQing Li int
2105d7968c29SAlexander V. Chernikov nd6_flush_holdchain(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain,
21069c9bde01SAlexander V. Chernikov     struct sockaddr_in6 *dst)
21076e6b3f7cSQing Li {
21086e6b3f7cSQing Li 	struct mbuf *m, *m_head;
21096e6b3f7cSQing Li 	struct ifnet *outifp;
21106e6b3f7cSQing Li 	int error = 0;
21116e6b3f7cSQing Li 
21126e6b3f7cSQing Li 	m_head = chain;
21136e6b3f7cSQing Li 	if ((ifp->if_flags & IFF_LOOPBACK) != 0)
21146e6b3f7cSQing Li 		outifp = origifp;
21156e6b3f7cSQing Li 	else
21166e6b3f7cSQing Li 		outifp = ifp;
21176e6b3f7cSQing Li 
21186e6b3f7cSQing Li 	while (m_head) {
21196e6b3f7cSQing Li 		m = m_head;
21206e6b3f7cSQing Li 		m_head = m_head->m_nextpkt;
2121d7968c29SAlexander V. Chernikov 		error = nd6_output_ifp(ifp, origifp, m, dst);
21226e6b3f7cSQing Li 	}
21236e6b3f7cSQing Li 
21246e6b3f7cSQing Li 	/*
21256e6b3f7cSQing Li 	 * XXX
21266e6b3f7cSQing Li 	 * note that intermediate errors are blindly ignored - but this is
21276e6b3f7cSQing Li 	 * the same convention as used with nd6_output when called by
21286e6b3f7cSQing Li 	 * nd6_cache_lladdr
21296e6b3f7cSQing Li 	 */
21306e6b3f7cSQing Li 	return (error);
21316e6b3f7cSQing Li }
21326e6b3f7cSQing Li 
21336e6b3f7cSQing Li 
213482cd038dSYoshinobu Inoue int
21351272577eSXin LI nd6_need_cache(struct ifnet *ifp)
213633841545SHajimu UMEMOTO {
213733841545SHajimu UMEMOTO 	/*
213833841545SHajimu UMEMOTO 	 * XXX: we currently do not make neighbor cache on any interface
213933841545SHajimu UMEMOTO 	 * other than ARCnet, Ethernet, FDDI and GIF.
214033841545SHajimu UMEMOTO 	 *
214133841545SHajimu UMEMOTO 	 * RFC2893 says:
214233841545SHajimu UMEMOTO 	 * - unidirectional tunnels needs no ND
214333841545SHajimu UMEMOTO 	 */
214433841545SHajimu UMEMOTO 	switch (ifp->if_type) {
214533841545SHajimu UMEMOTO 	case IFT_ARCNET:
214633841545SHajimu UMEMOTO 	case IFT_ETHER:
214733841545SHajimu UMEMOTO 	case IFT_FDDI:
214833841545SHajimu UMEMOTO 	case IFT_IEEE1394:
214905b6760dSMunechika SUMIKAWA #ifdef IFT_L2VLAN
215005b6760dSMunechika SUMIKAWA 	case IFT_L2VLAN:
215105b6760dSMunechika SUMIKAWA #endif
215233841545SHajimu UMEMOTO #ifdef IFT_IEEE80211
215333841545SHajimu UMEMOTO 	case IFT_IEEE80211:
215433841545SHajimu UMEMOTO #endif
2155e4cd31ddSJeff Roberson 	case IFT_INFINIBAND:
215659280079SAndrew Thompson 	case IFT_BRIDGE:
2157c57086ceSHajimu UMEMOTO 	case IFT_PROPVIRTUAL:
215833841545SHajimu UMEMOTO 		return (1);
215933841545SHajimu UMEMOTO 	default:
216033841545SHajimu UMEMOTO 		return (0);
216133841545SHajimu UMEMOTO 	}
216233841545SHajimu UMEMOTO }
216333841545SHajimu UMEMOTO 
21646e6b3f7cSQing Li /*
2165f6b84910SAlexander V. Chernikov  * Add pernament ND6 link-layer record for given
2166f6b84910SAlexander V. Chernikov  * interface address.
2167f6b84910SAlexander V. Chernikov  *
2168f6b84910SAlexander V. Chernikov  * Very similar to IPv4 arp_ifinit(), but:
2169f6b84910SAlexander V. Chernikov  * 1) IPv6 DAD is performed in different place
2170f6b84910SAlexander V. Chernikov  * 2) It is called by IPv6 protocol stack in contrast to
2171f6b84910SAlexander V. Chernikov  * arp_ifinit() which is typically called in SIOCSIFADDR
2172f6b84910SAlexander V. Chernikov  * driver ioctl handler.
2173f6b84910SAlexander V. Chernikov  *
2174f6b84910SAlexander V. Chernikov  */
2175f6b84910SAlexander V. Chernikov int
2176f6b84910SAlexander V. Chernikov nd6_add_ifa_lle(struct in6_ifaddr *ia)
2177f6b84910SAlexander V. Chernikov {
2178f6b84910SAlexander V. Chernikov 	struct ifnet *ifp;
2179f6b84910SAlexander V. Chernikov 	struct llentry *ln;
2180f6b84910SAlexander V. Chernikov 
2181f6b84910SAlexander V. Chernikov 	ifp = ia->ia_ifa.ifa_ifp;
2182af6209a1SAndrey V. Elsukov 	if (nd6_need_cache(ifp) == 0)
2183af6209a1SAndrey V. Elsukov 		return (0);
2184f6b84910SAlexander V. Chernikov 	IF_AFDATA_LOCK(ifp);
2185f6b84910SAlexander V. Chernikov 	ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
2186f6b84910SAlexander V. Chernikov 	ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR |
2187f6b84910SAlexander V. Chernikov 	    LLE_EXCLUSIVE), (struct sockaddr *)&ia->ia_addr);
2188f6b84910SAlexander V. Chernikov 	IF_AFDATA_UNLOCK(ifp);
2189f6b84910SAlexander V. Chernikov 	if (ln != NULL) {
2190f6b84910SAlexander V. Chernikov 		ln->la_expire = 0;  /* for IPv6 this means permanent */
2191f6b84910SAlexander V. Chernikov 		ln->ln_state = ND6_LLINFO_REACHABLE;
2192f6b84910SAlexander V. Chernikov 		LLE_WUNLOCK(ln);
2193f6b84910SAlexander V. Chernikov 		in6_newaddrmsg(ia, RTM_ADD);
2194f6b84910SAlexander V. Chernikov 		return (0);
2195f6b84910SAlexander V. Chernikov 	}
2196f6b84910SAlexander V. Chernikov 
2197f6b84910SAlexander V. Chernikov 	return (ENOBUFS);
2198f6b84910SAlexander V. Chernikov }
2199f6b84910SAlexander V. Chernikov 
2200f6b84910SAlexander V. Chernikov /*
2201f6b84910SAlexander V. Chernikov  * Removes ALL lle records for interface address prefix.
2202f6b84910SAlexander V. Chernikov  * XXXME: That's probably not we really want to do, we need
2203f6b84910SAlexander V. Chernikov  * to remove address record only and keep other records
2204f6b84910SAlexander V. Chernikov  * until we determine if given prefix is really going
2205f6b84910SAlexander V. Chernikov  * to be removed.
2206f6b84910SAlexander V. Chernikov  */
2207f6b84910SAlexander V. Chernikov void
2208f6b84910SAlexander V. Chernikov nd6_rem_ifa_lle(struct in6_ifaddr *ia)
2209f6b84910SAlexander V. Chernikov {
2210f6b84910SAlexander V. Chernikov 	struct sockaddr_in6 mask, addr;
2211f6b84910SAlexander V. Chernikov 	struct ifnet *ifp;
2212f6b84910SAlexander V. Chernikov 
2213f6b84910SAlexander V. Chernikov 	in6_newaddrmsg(ia, RTM_DELETE);
2214f6b84910SAlexander V. Chernikov 
2215f6b84910SAlexander V. Chernikov 	ifp = ia->ia_ifa.ifa_ifp;
2216f6b84910SAlexander V. Chernikov 	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
2217f6b84910SAlexander V. Chernikov 	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
2218f6b84910SAlexander V. Chernikov 	lltable_prefix_free(AF_INET6, (struct sockaddr *)&addr,
2219f6b84910SAlexander V. Chernikov 	            (struct sockaddr *)&mask, LLE_STATIC);
2220f6b84910SAlexander V. Chernikov }
2221f6b84910SAlexander V. Chernikov 
2222f6b84910SAlexander V. Chernikov /*
22236e6b3f7cSQing Li  * the callers of this function need to be re-worked to drop
22246e6b3f7cSQing Li  * the lle lock, drop here for now
22256e6b3f7cSQing Li  */
222633841545SHajimu UMEMOTO int
2227bbd8aebaSQing Li nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
222874860d4fSAlexander V. Chernikov     const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
222982cd038dSYoshinobu Inoue {
22306e6b3f7cSQing Li 	struct llentry *ln;
223182cd038dSYoshinobu Inoue 
223274860d4fSAlexander V. Chernikov 	if (pflags != NULL)
223374860d4fSAlexander V. Chernikov 		*pflags = 0;
22346e6b3f7cSQing Li 	IF_AFDATA_UNLOCK_ASSERT(ifp);
2235f31b83e1SNavdeep Parhar 	if (m != NULL && m->m_flags & M_MCAST) {
223682cd038dSYoshinobu Inoue 		switch (ifp->if_type) {
223782cd038dSYoshinobu Inoue 		case IFT_ETHER:
223882cd038dSYoshinobu Inoue 		case IFT_FDDI:
223905b6760dSMunechika SUMIKAWA #ifdef IFT_L2VLAN
224005b6760dSMunechika SUMIKAWA 		case IFT_L2VLAN:
224105b6760dSMunechika SUMIKAWA #endif
224233841545SHajimu UMEMOTO #ifdef IFT_IEEE80211
224333841545SHajimu UMEMOTO 		case IFT_IEEE80211:
224433841545SHajimu UMEMOTO #endif
224559280079SAndrew Thompson 		case IFT_BRIDGE:
22462049fdeeSMatthew N. Dodd 		case IFT_ISO88025:
224782cd038dSYoshinobu Inoue 			ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
224882cd038dSYoshinobu Inoue 						 desten);
2249354c3d34SLuigi Rizzo 			return (0);
225082cd038dSYoshinobu Inoue 		default:
2251fef5fd23SBosko Milekic 			m_freem(m);
2252354c3d34SLuigi Rizzo 			return (EAFNOSUPPORT);
225382cd038dSYoshinobu Inoue 		}
225482cd038dSYoshinobu Inoue 	}
225582cd038dSYoshinobu Inoue 
22566e6b3f7cSQing Li 
22576e6b3f7cSQing Li 	/*
22586e6b3f7cSQing Li 	 * the entry should have been created in nd6_store_lladdr
22596e6b3f7cSQing Li 	 */
226073cb2f38SAndrey V. Elsukov 	IF_AFDATA_RLOCK(ifp);
22616e6b3f7cSQing Li 	ln = lla_lookup(LLTABLE6(ifp), 0, dst);
226273cb2f38SAndrey V. Elsukov 	IF_AFDATA_RUNLOCK(ifp);
22636e6b3f7cSQing Li 	if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
226415209fb6SKip Macy 		if (ln != NULL)
22656e6b3f7cSQing Li 			LLE_RUNLOCK(ln);
2266530f95fcSGleb Smirnoff 		/* this could happen, if we could not allocate memory */
2267530f95fcSGleb Smirnoff 		m_freem(m);
22686e6b3f7cSQing Li 		return (1);
2269530f95fcSGleb Smirnoff 	}
2270530f95fcSGleb Smirnoff 
22716e6b3f7cSQing Li 	bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
227274860d4fSAlexander V. Chernikov 	if (pflags != NULL)
227374860d4fSAlexander V. Chernikov 		*pflags = ln->la_flags;
22746e6b3f7cSQing Li 	LLE_RUNLOCK(ln);
22756e6b3f7cSQing Li 	/*
22766e6b3f7cSQing Li 	 * A *small* use after free race exists here
22776e6b3f7cSQing Li 	 */
2278cd46a114SLuigi Rizzo 	return (0);
227982cd038dSYoshinobu Inoue }
228033841545SHajimu UMEMOTO 
228131d4137bSSUZUKI Shinsuke static void
22826e6b3f7cSQing Li clear_llinfo_pqueue(struct llentry *ln)
228331d4137bSSUZUKI Shinsuke {
228431d4137bSSUZUKI Shinsuke 	struct mbuf *m_hold, *m_hold_next;
228531d4137bSSUZUKI Shinsuke 
22866e6b3f7cSQing Li 	for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) {
228731d4137bSSUZUKI Shinsuke 		m_hold_next = m_hold->m_nextpkt;
228831d4137bSSUZUKI Shinsuke 		m_freem(m_hold);
228931d4137bSSUZUKI Shinsuke 	}
229031d4137bSSUZUKI Shinsuke 
22916e6b3f7cSQing Li 	ln->la_hold = NULL;
229231d4137bSSUZUKI Shinsuke 	return;
229331d4137bSSUZUKI Shinsuke }
229431d4137bSSUZUKI Shinsuke 
229533841545SHajimu UMEMOTO static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS);
229633841545SHajimu UMEMOTO static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS);
229733841545SHajimu UMEMOTO #ifdef SYSCTL_DECL
229833841545SHajimu UMEMOTO SYSCTL_DECL(_net_inet6_icmp6);
229933841545SHajimu UMEMOTO #endif
230033841545SHajimu UMEMOTO SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_DRLIST, nd6_drlist,
230133841545SHajimu UMEMOTO 	CTLFLAG_RD, nd6_sysctl_drlist, "");
230233841545SHajimu UMEMOTO SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist,
230333841545SHajimu UMEMOTO 	CTLFLAG_RD, nd6_sysctl_prlist, "");
23046df8a710SGleb Smirnoff SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen,
23056df8a710SGleb Smirnoff 	CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, "");
23066df8a710SGleb Smirnoff SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_gctimer,
23076df8a710SGleb Smirnoff 	CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), "");
230833841545SHajimu UMEMOTO 
230933841545SHajimu UMEMOTO static int
231033841545SHajimu UMEMOTO nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
231133841545SHajimu UMEMOTO {
23127195094cSMarius Strobl 	struct in6_defrouter d;
231333841545SHajimu UMEMOTO 	struct nd_defrouter *dr;
23147195094cSMarius Strobl 	int error;
231533841545SHajimu UMEMOTO 
231633841545SHajimu UMEMOTO 	if (req->newptr)
23177195094cSMarius Strobl 		return (EPERM);
231833841545SHajimu UMEMOTO 
23197195094cSMarius Strobl 	bzero(&d, sizeof(d));
23207195094cSMarius Strobl 	d.rtaddr.sin6_family = AF_INET6;
23217195094cSMarius Strobl 	d.rtaddr.sin6_len = sizeof(d.rtaddr);
23227195094cSMarius Strobl 
23237195094cSMarius Strobl 	/*
23247195094cSMarius Strobl 	 * XXX locking
23257195094cSMarius Strobl 	 */
23263b0b2840SJohn Baldwin 	TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) {
23277195094cSMarius Strobl 		d.rtaddr.sin6_addr = dr->rtaddr;
23287195094cSMarius Strobl 		error = sa6_recoverscope(&d.rtaddr);
2329edbb8b46SPeter Wemm 		if (error != 0)
2330b2630c29SGeorge V. Neville-Neil 			return (error);
23317195094cSMarius Strobl 		d.flags = dr->flags;
23327195094cSMarius Strobl 		d.rtlifetime = dr->rtlifetime;
2333ffa0165aSHiroki Sato 		d.expire = dr->expire + (time_second - time_uptime);
23347195094cSMarius Strobl 		d.if_index = dr->ifp->if_index;
23357195094cSMarius Strobl 		error = SYSCTL_OUT(req, &d, sizeof(d));
23367195094cSMarius Strobl 		if (error != 0)
233707eb2995SHajimu UMEMOTO 			return (error);
233833841545SHajimu UMEMOTO 	}
23397195094cSMarius Strobl 	return (0);
23407195094cSMarius Strobl }
234133841545SHajimu UMEMOTO 
234233841545SHajimu UMEMOTO static int
234333841545SHajimu UMEMOTO nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
234433841545SHajimu UMEMOTO {
23457195094cSMarius Strobl 	struct in6_prefix p;
23467195094cSMarius Strobl 	struct sockaddr_in6 s6;
234733841545SHajimu UMEMOTO 	struct nd_prefix *pr;
23487195094cSMarius Strobl 	struct nd_pfxrouter *pfr;
23497195094cSMarius Strobl 	time_t maxexpire;
23507195094cSMarius Strobl 	int error;
23511d54aa3bSBjoern A. Zeeb 	char ip6buf[INET6_ADDRSTRLEN];
235233841545SHajimu UMEMOTO 
235333841545SHajimu UMEMOTO 	if (req->newptr)
23547195094cSMarius Strobl 		return (EPERM);
235533841545SHajimu UMEMOTO 
23567195094cSMarius Strobl 	bzero(&p, sizeof(p));
23577195094cSMarius Strobl 	p.origin = PR_ORIG_RA;
23587195094cSMarius Strobl 	bzero(&s6, sizeof(s6));
23597195094cSMarius Strobl 	s6.sin6_family = AF_INET6;
23607195094cSMarius Strobl 	s6.sin6_len = sizeof(s6);
23617195094cSMarius Strobl 
23627195094cSMarius Strobl 	/*
23637195094cSMarius Strobl 	 * XXX locking
23647195094cSMarius Strobl 	 */
23653b0b2840SJohn Baldwin 	LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) {
23667195094cSMarius Strobl 		p.prefix = pr->ndpr_prefix;
23677195094cSMarius Strobl 		if (sa6_recoverscope(&p.prefix)) {
23687195094cSMarius Strobl 			log(LOG_ERR, "scope error in prefix list (%s)\n",
23697195094cSMarius Strobl 			    ip6_sprintf(ip6buf, &p.prefix.sin6_addr));
2370a1f7e5f8SHajimu UMEMOTO 			/* XXX: press on... */
2371a1f7e5f8SHajimu UMEMOTO 		}
23727195094cSMarius Strobl 		p.raflags = pr->ndpr_raf;
23737195094cSMarius Strobl 		p.prefixlen = pr->ndpr_plen;
23747195094cSMarius Strobl 		p.vltime = pr->ndpr_vltime;
23757195094cSMarius Strobl 		p.pltime = pr->ndpr_pltime;
23767195094cSMarius Strobl 		p.if_index = pr->ndpr_ifp->if_index;
2377743eee66SSUZUKI Shinsuke 		if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
23787195094cSMarius Strobl 			p.expire = 0;
2379743eee66SSUZUKI Shinsuke 		else {
2380743eee66SSUZUKI Shinsuke 			/* XXX: we assume time_t is signed. */
2381743eee66SSUZUKI Shinsuke 			maxexpire = (-1) &
23827195094cSMarius Strobl 			    ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1));
23837195094cSMarius Strobl 			if (pr->ndpr_vltime < maxexpire - pr->ndpr_lastupdate)
23847195094cSMarius Strobl 				p.expire = pr->ndpr_lastupdate +
2385ffa0165aSHiroki Sato 				    pr->ndpr_vltime +
2386ffa0165aSHiroki Sato 				    (time_second - time_uptime);
23877195094cSMarius Strobl 			else
23887195094cSMarius Strobl 				p.expire = maxexpire;
2389743eee66SSUZUKI Shinsuke 		}
23907195094cSMarius Strobl 		p.refcnt = pr->ndpr_refcnt;
23917195094cSMarius Strobl 		p.flags = pr->ndpr_stateflags;
23927195094cSMarius Strobl 		p.advrtrs = 0;
23937195094cSMarius Strobl 		LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
23947195094cSMarius Strobl 			p.advrtrs++;
23957195094cSMarius Strobl 		error = SYSCTL_OUT(req, &p, sizeof(p));
23967195094cSMarius Strobl 		if (error != 0)
239707eb2995SHajimu UMEMOTO 			return (error);
23987195094cSMarius Strobl 		LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
23997195094cSMarius Strobl 			s6.sin6_addr = pfr->router->rtaddr;
24007195094cSMarius Strobl 			if (sa6_recoverscope(&s6))
24017195094cSMarius Strobl 				log(LOG_ERR,
24027195094cSMarius Strobl 				    "scope error in prefix list (%s)\n",
24037195094cSMarius Strobl 				    ip6_sprintf(ip6buf, &pfr->router->rtaddr));
24047195094cSMarius Strobl 			error = SYSCTL_OUT(req, &s6, sizeof(s6));
24057195094cSMarius Strobl 			if (error != 0)
24067195094cSMarius Strobl 				return (error);
24077195094cSMarius Strobl 		}
24087195094cSMarius Strobl 	}
24097195094cSMarius Strobl 	return (0);
241033841545SHajimu UMEMOTO }
2411