nd6_nbr.c revision 279564
1139826Simp/*-
253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
353541Sshin * All rights reserved.
453541Sshin *
553541Sshin * Redistribution and use in source and binary forms, with or without
653541Sshin * modification, are permitted provided that the following conditions
753541Sshin * are met:
853541Sshin * 1. Redistributions of source code must retain the above copyright
953541Sshin *    notice, this list of conditions and the following disclaimer.
1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1153541Sshin *    notice, this list of conditions and the following disclaimer in the
1253541Sshin *    documentation and/or other materials provided with the distribution.
1353541Sshin * 3. Neither the name of the project nor the names of its contributors
1453541Sshin *    may be used to endorse or promote products derived from this software
1553541Sshin *    without specific prior written permission.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
28174510Sobrien *
29174510Sobrien *	$KAME: nd6_nbr.c,v 1.86 2002/01/21 02:33:04 jinmei Exp $
3053541Sshin */
3153541Sshin
32174510Sobrien#include <sys/cdefs.h>
33174510Sobrien__FBSDID("$FreeBSD: head/sys/netinet6/nd6_nbr.c 279564 2015-03-03 10:50:03Z ae $");
34174510Sobrien
3562587Sitojun#include "opt_inet.h"
3662587Sitojun#include "opt_inet6.h"
37142215Sglebius#include "opt_ipsec.h"
38178167Sqingli#include "opt_mpath.h"
3955009Sshin
4053541Sshin#include <sys/param.h>
4153541Sshin#include <sys/systm.h>
4253541Sshin#include <sys/malloc.h>
43279531Shrs#include <sys/libkern.h>
44186119Sqingli#include <sys/lock.h>
45186119Sqingli#include <sys/rwlock.h>
4653541Sshin#include <sys/mbuf.h>
4753541Sshin#include <sys/socket.h>
4853541Sshin#include <sys/sockio.h>
4953541Sshin#include <sys/time.h>
5053541Sshin#include <sys/kernel.h>
5153541Sshin#include <sys/errno.h>
52279531Shrs#include <sys/sysctl.h>
5353541Sshin#include <sys/syslog.h>
5453541Sshin#include <sys/queue.h>
5578064Sume#include <sys/callout.h>
56275593Smarkj#include <sys/refcount.h>
5753541Sshin
5853541Sshin#include <net/if.h>
5953541Sshin#include <net/if_types.h>
6053541Sshin#include <net/if_dl.h>
61147306Sbrooks#include <net/if_var.h>
6253541Sshin#include <net/route.h>
63178167Sqingli#ifdef RADIX_MPATH
64178167Sqingli#include <net/radix_mpath.h>
65178167Sqingli#endif
66279531Shrs#include <net/vnet.h>
6753541Sshin
6853541Sshin#include <netinet/in.h>
6953541Sshin#include <netinet/in_var.h>
70186119Sqingli#include <net/if_llatbl.h>
71186119Sqingli#define	L3_ADDR_SIN6(le)	((struct sockaddr_in6 *) L3_ADDR(le))
7253541Sshin#include <netinet6/in6_var.h>
73151477Ssuz#include <netinet6/in6_ifattach.h>
7462587Sitojun#include <netinet/ip6.h>
7553541Sshin#include <netinet6/ip6_var.h>
76148385Sume#include <netinet6/scope6_var.h>
7753541Sshin#include <netinet6/nd6.h>
7862587Sitojun#include <netinet/icmp6.h>
79211193Swill#include <netinet/ip_carp.h>
80211501Sanchie#include <netinet6/send.h>
8153541Sshin
8262587Sitojun#define SDL(s) ((struct sockaddr_dl *)s)
8353541Sshin
8462587Sitojunstruct dadq;
85279531Shrsstatic struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *);
86274347Smelifarostatic void nd6_dad_add(struct dadq *dp);
87274347Smelifarostatic void nd6_dad_del(struct dadq *dp);
88275593Smarkjstatic void nd6_dad_rele(struct dadq *);
89175162Sobrienstatic void nd6_dad_starttimer(struct dadq *, int);
90175162Sobrienstatic void nd6_dad_stoptimer(struct dadq *);
91191816Szecstatic void nd6_dad_timer(struct dadq *);
92274347Smelifarostatic void nd6_dad_duplicated(struct ifaddr *, struct dadq *);
93175162Sobrienstatic void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
94279531Shrsstatic void nd6_dad_ns_input(struct ifaddr *, struct nd_opt_nonce *);
95175162Sobrienstatic void nd6_dad_na_input(struct ifaddr *);
96231852Sbzstatic void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
97231852Sbz    const struct in6_addr *, u_long, int, struct sockaddr *, u_int);
98279564Saestatic void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *,
99279564Sae    const struct in6_addr *, struct llentry *, uint8_t *, u_int);
10053541Sshin
101279531Shrsstatic VNET_DEFINE(int, dad_enhanced) = 1;
102279531Shrs#define	V_dad_enhanced			VNET(dad_enhanced)
103279531Shrs
104279531ShrsSYSCTL_DECL(_net_inet6_ip6);
105279531ShrsSYSCTL_INT(_net_inet6_ip6, OID_AUTO, dad_enhanced, CTLFLAG_VNET | CTLFLAG_RW,
106279531Shrs    &VNET_NAME(dad_enhanced), 0,
107279531Shrs    "Enable Enhanced DAD, which adds a random nonce to NS messages for DAD.");
108279531Shrs
109266857Shrsstatic VNET_DEFINE(int, dad_maxtry) = 15;	/* max # of *tries* to
110266857Shrs						   transmit DAD packet */
111195727Srwatson#define	V_dad_maxtry			VNET(dad_maxtry)
112195699Srwatson
11353541Sshin/*
114108470Sschweikh * Input a Neighbor Solicitation Message.
11553541Sshin *
11653541Sshin * Based on RFC 2461
117148987Sume * Based on RFC 2462 (duplicate address detection)
11853541Sshin */
11953541Sshinvoid
120171259Sdelphijnd6_ns_input(struct mbuf *m, int off, int icmp6len)
12153541Sshin{
12253541Sshin	struct ifnet *ifp = m->m_pkthdr.rcvif;
12353541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
12462587Sitojun	struct nd_neighbor_solicit *nd_ns;
12553541Sshin	struct in6_addr saddr6 = ip6->ip6_src;
12653541Sshin	struct in6_addr daddr6 = ip6->ip6_dst;
12762587Sitojun	struct in6_addr taddr6;
12853541Sshin	struct in6_addr myaddr6;
12953541Sshin	char *lladdr = NULL;
130142215Sglebius	struct ifaddr *ifa = NULL;
13153541Sshin	int lladdrlen = 0;
13253541Sshin	int anycast = 0, proxy = 0, tentative = 0;
13353541Sshin	int tlladdr;
134222728Shrs	int rflag;
13553541Sshin	union nd_opts ndopts;
136219562Sbz	struct sockaddr_dl proxydl;
137165118Sbz	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
13853541Sshin
139222728Shrs	rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0;
140222728Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif)
141222728Shrs		rflag = 0;
14278064Sume#ifndef PULLDOWN_TEST
14378064Sume	IP6_EXTHDR_CHECK(m, off, icmp6len,);
14478064Sume	nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
14578064Sume#else
14678064Sume	IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
14778064Sume	if (nd_ns == NULL) {
148190964Srwatson		ICMP6STAT_INC(icp6s_tooshort);
14978064Sume		return;
15078064Sume	}
15178064Sume#endif
15278064Sume	ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
15378064Sume	taddr6 = nd_ns->nd_ns_target;
154148385Sume	if (in6_setscope(&taddr6, ifp, NULL) != 0)
155148385Sume		goto bad;
15678064Sume
15753541Sshin	if (ip6->ip6_hlim != 255) {
15878064Sume		nd6log((LOG_ERR,
15978064Sume		    "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
160165118Sbz		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
161165118Sbz		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
16278064Sume		goto bad;
16353541Sshin	}
16453541Sshin
16553541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
166148987Sume		/* dst has to be a solicited node multicast address. */
167120941Sume		if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
16895023Ssuz		    /* don't check ifindex portion */
169120941Sume		    daddr6.s6_addr32[1] == 0 &&
170120941Sume		    daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
171120941Sume		    daddr6.s6_addr8[12] == 0xff) {
17295023Ssuz			; /* good */
17353541Sshin		} else {
17478064Sume			nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
175120941Sume			    "(wrong ip6 dst)\n"));
17653541Sshin			goto bad;
17753541Sshin		}
178185348Szec	} else if (!V_nd6_onlink_ns_rfc4861) {
179183529Scperciva		struct sockaddr_in6 src_sa6;
180183529Scperciva
181183529Scperciva		/*
182183529Scperciva		 * According to recent IETF discussions, it is not a good idea
183183529Scperciva		 * to accept a NS from an address which would not be deemed
184183529Scperciva		 * to be a neighbor otherwise.  This point is expected to be
185183529Scperciva		 * clarified in future revisions of the specification.
186183529Scperciva		 */
187183529Scperciva		bzero(&src_sa6, sizeof(src_sa6));
188183529Scperciva		src_sa6.sin6_family = AF_INET6;
189183529Scperciva		src_sa6.sin6_len = sizeof(src_sa6);
190183529Scperciva		src_sa6.sin6_addr = saddr6;
191186119Sqingli		if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) {
192183529Scperciva			nd6log((LOG_INFO, "nd6_ns_input: "
193183529Scperciva				"NS packet from non-neighbor\n"));
194183529Scperciva			goto bad;
195183529Scperciva		}
19653541Sshin	}
19753541Sshin
19853541Sshin	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
19978064Sume		nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
20053541Sshin		goto bad;
20153541Sshin	}
20253541Sshin
20353541Sshin	icmp6len -= sizeof(*nd_ns);
20453541Sshin	nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
20553541Sshin	if (nd6_options(&ndopts) < 0) {
20678064Sume		nd6log((LOG_INFO,
20778064Sume		    "nd6_ns_input: invalid ND option, ignored\n"));
20878064Sume		/* nd6_options have incremented stats */
20978064Sume		goto freeit;
21053541Sshin	}
21153541Sshin
21253541Sshin	if (ndopts.nd_opts_src_lladdr) {
21395023Ssuz		lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
21453541Sshin		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
21553541Sshin	}
216120941Sume
21753541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
21878064Sume		nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
21978064Sume		    "(link-layer address option)\n"));
22053541Sshin		goto bad;
22153541Sshin	}
22253541Sshin
22353541Sshin	/*
22453541Sshin	 * Attaching target link-layer address to the NA?
22553541Sshin	 * (RFC 2461 7.2.4)
22653541Sshin	 *
22753541Sshin	 * NS IP dst is unicast/anycast			MUST NOT add
22853541Sshin	 * NS IP dst is solicited-node multicast	MUST add
22953541Sshin	 *
23053541Sshin	 * In implementation, we add target link-layer address by default.
23153541Sshin	 * We do not add one in MUST NOT cases.
23253541Sshin	 */
23353541Sshin	if (!IN6_IS_ADDR_MULTICAST(&daddr6))
23453541Sshin		tlladdr = 0;
23553541Sshin	else
23653541Sshin		tlladdr = 1;
23753541Sshin
23853541Sshin	/*
23953541Sshin	 * Target address (taddr6) must be either:
24053541Sshin	 * (1) Valid unicast/anycast address for my receiving interface,
24153541Sshin	 * (2) Unicast address for which I'm offering proxy service, or
24253541Sshin	 * (3) "tentative" address on which DAD is being performed.
24353541Sshin	 */
24453541Sshin	/* (1) and (3) check. */
245142215Sglebius	if (ifp->if_carp)
246211157Swill		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
247228571Sglebius	else
248142215Sglebius		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
24953541Sshin
25053541Sshin	/* (2) check. */
251151465Ssuz	if (ifa == NULL) {
252257985Sae		struct route_in6 ro;
253121765Ssam		int need_proxy;
25453541Sshin
255257985Sae		bzero(&ro, sizeof(ro));
256257985Sae		ro.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
257257985Sae		ro.ro_dst.sin6_family = AF_INET6;
258257985Sae		ro.ro_dst.sin6_addr = taddr6;
25953541Sshin
260231852Sbz		/* Always use the default FIB. */
261178167Sqingli#ifdef RADIX_MPATH
262264976Smelifaro		rtalloc_mpath_fib((struct route *)&ro, ntohl(taddr6.s6_addr32[3]),
263231852Sbz		    RT_DEFAULT_FIB);
264178167Sqingli#else
265257985Sae		in6_rtalloc(&ro, RT_DEFAULT_FIB);
266178167Sqingli#endif
267257985Sae		need_proxy = (ro.ro_rt &&
268257985Sae		    (ro.ro_rt->rt_flags & RTF_ANNOUNCE) != 0 &&
269257985Sae		    ro.ro_rt->rt_gateway->sa_family == AF_LINK);
270257985Sae		if (ro.ro_rt != NULL) {
271219562Sbz			if (need_proxy)
272257985Sae				proxydl = *SDL(ro.ro_rt->rt_gateway);
273257985Sae			RTFREE(ro.ro_rt);
274219562Sbz		}
275121765Ssam		if (need_proxy) {
27653541Sshin			/*
27762587Sitojun			 * proxy NDP for single entry
27853541Sshin			 */
27962587Sitojun			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
28062587Sitojun				IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
281219562Sbz			if (ifa)
28253541Sshin				proxy = 1;
28353541Sshin		}
28453541Sshin	}
285151479Ssuz	if (ifa == NULL) {
28653541Sshin		/*
28778064Sume		 * We've got an NS packet, and we don't have that adddress
28853541Sshin		 * assigned for us.  We MUST silently ignore it.
28953541Sshin		 * See RFC2461 7.2.3.
29053541Sshin		 */
29162587Sitojun		goto freeit;
29253541Sshin	}
29353541Sshin	myaddr6 = *IFA_IN6(ifa);
29453541Sshin	anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
29553541Sshin	tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
29653541Sshin	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
29762587Sitojun		goto freeit;
29853541Sshin
29953541Sshin	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
300120941Sume		nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
30153541Sshin		    "(if %d, NS packet %d)\n",
302165118Sbz		    ip6_sprintf(ip6bufs, &taddr6),
303120941Sume		    ifp->if_addrlen, lladdrlen - 2));
30478064Sume		goto bad;
30553541Sshin	}
30653541Sshin
30753541Sshin	if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
308120941Sume		nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
309165118Sbz		    ip6_sprintf(ip6bufs, &saddr6)));
31062587Sitojun		goto freeit;
31153541Sshin	}
31253541Sshin
31353541Sshin	/*
31453541Sshin	 * We have neighbor solicitation packet, with target address equals to
31553541Sshin	 * one of my tentative address.
31653541Sshin	 *
31753541Sshin	 * src addr	how to process?
31853541Sshin	 * ---		---
31953541Sshin	 * multicast	of course, invalid (rejected in ip6_input)
32053541Sshin	 * unicast	somebody is doing address resolution -> ignore
32153541Sshin	 * unspec	dup address detection
32253541Sshin	 *
32353541Sshin	 * The processing is defined in RFC 2462.
32453541Sshin	 */
32553541Sshin	if (tentative) {
32653541Sshin		/*
32753541Sshin		 * If source address is unspecified address, it is for
328148987Sume		 * duplicate address detection.
32953541Sshin		 *
33053541Sshin		 * If not, the packet is for addess resolution;
33153541Sshin		 * silently ignore it.
33253541Sshin		 */
33353541Sshin		if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
334279531Shrs			nd6_dad_ns_input(ifa, ndopts.nd_opts_nonce);
33553541Sshin
33662587Sitojun		goto freeit;
33753541Sshin	}
33853541Sshin
33953541Sshin	/*
34053541Sshin	 * If the source address is unspecified address, entries must not
34153541Sshin	 * be created or updated.
34253541Sshin	 * It looks that sender is performing DAD.  Output NA toward
34353541Sshin	 * all-node multicast address, to tell the sender that I'm using
34453541Sshin	 * the address.
34553541Sshin	 * S bit ("solicited") must be zero.
34653541Sshin	 */
34753541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
348148385Sume		struct in6_addr in6_all;
349148385Sume
350148385Sume		in6_all = in6addr_linklocal_allnodes;
351148385Sume		if (in6_setscope(&in6_all, ifp, NULL) != 0)
352148385Sume			goto bad;
353231852Sbz		nd6_na_output_fib(ifp, &in6_all, &taddr6,
354120941Sume		    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
355231852Sbz		    rflag, tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL,
356231852Sbz		    M_GETFIB(m));
35762587Sitojun		goto freeit;
35853541Sshin	}
35953541Sshin
360120941Sume	nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
361120941Sume	    ND_NEIGHBOR_SOLICIT, 0);
36253541Sshin
363231852Sbz	nd6_na_output_fib(ifp, &saddr6, &taddr6,
364120941Sume	    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
365222728Shrs	    rflag | ND_NA_FLAG_SOLICITED, tlladdr,
366231852Sbz	    proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
36762587Sitojun freeit:
368194760Srwatson	if (ifa != NULL)
369194760Srwatson		ifa_free(ifa);
37062587Sitojun	m_freem(m);
37153541Sshin	return;
37253541Sshin
37353541Sshin bad:
374165118Sbz	nd6log((LOG_ERR, "nd6_ns_input: src=%s\n",
375165118Sbz		ip6_sprintf(ip6bufs, &saddr6)));
376165118Sbz	nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n",
377165118Sbz		ip6_sprintf(ip6bufs, &daddr6)));
378165118Sbz	nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n",
379165118Sbz		ip6_sprintf(ip6bufs, &taddr6)));
380190964Srwatson	ICMP6STAT_INC(icp6s_badns);
381194760Srwatson	if (ifa != NULL)
382194760Srwatson		ifa_free(ifa);
38362587Sitojun	m_freem(m);
38453541Sshin}
38553541Sshin
38653541Sshin/*
387108470Sschweikh * Output a Neighbor Solicitation Message. Caller specifies:
38853541Sshin *	- ICMP6 header source IP6 address
38953541Sshin *	- ND6 header target IP6 address
39053541Sshin *	- ND6 header source datalink address
39153541Sshin *
39253541Sshin * Based on RFC 2461
393148987Sume * Based on RFC 2462 (duplicate address detection)
394171259Sdelphij *
395279531Shrs *    ln - for source address determination
396279531Shrs * nonce - If non-NULL, NS is used for duplicate address detection and
397279531Shrs *         the value (length is ND_OPT_NONCE_LEN) is used as a random nonce.
39853541Sshin */
399279564Saestatic void
400279564Saend6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6,
401279564Sae    const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce,
402279564Sae    u_int fibnum)
40353541Sshin{
40453541Sshin	struct mbuf *m;
405211501Sanchie	struct m_tag *mtag;
40653541Sshin	struct ip6_hdr *ip6;
40753541Sshin	struct nd_neighbor_solicit *nd_ns;
40853541Sshin	struct ip6_moptions im6o;
40953541Sshin	int icmp6len;
41062587Sitojun	int maxlen;
41153541Sshin	caddr_t mac;
412148385Sume	struct route_in6 ro;
413120941Sume
41453541Sshin	if (IN6_IS_ADDR_MULTICAST(taddr6))
41553541Sshin		return;
41653541Sshin
41762587Sitojun	/* estimate the size of message */
41862587Sitojun	maxlen = sizeof(*ip6) + sizeof(*nd_ns);
41962587Sitojun	maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
42062587Sitojun	if (max_linkhdr + maxlen >= MCLBYTES) {
42162587Sitojun#ifdef DIAGNOSTIC
422279564Sae		printf("%s: max_linkhdr + maxlen >= MCLBYTES "
423279564Sae		    "(%d + %d > %d)\n", __func__, max_linkhdr, maxlen,
424279564Sae		    MCLBYTES);
42562587Sitojun#endif
42653541Sshin		return;
42762587Sitojun	}
42853541Sshin
429248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
430248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
431248328Sglebius	else
432248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
43362587Sitojun	if (m == NULL)
43462587Sitojun		return;
435279564Sae	M_SETFIB(m, fibnum);
43662587Sitojun
437215559Sbz	bzero(&ro, sizeof(ro));
438215559Sbz
43953541Sshin	if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
44053541Sshin		m->m_flags |= M_MCAST;
44153541Sshin		im6o.im6o_multicast_ifp = ifp;
44253541Sshin		im6o.im6o_multicast_hlim = 255;
44353541Sshin		im6o.im6o_multicast_loop = 0;
44453541Sshin	}
44553541Sshin
44653541Sshin	icmp6len = sizeof(*nd_ns);
44753541Sshin	m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
448276692Srwatson	m->m_data += max_linkhdr;	/* or M_ALIGN() equivalent? */
44953541Sshin
45053541Sshin	/* fill neighbor solicitation packet */
45153541Sshin	ip6 = mtod(m, struct ip6_hdr *);
45253541Sshin	ip6->ip6_flow = 0;
45362587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
45462587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
45553541Sshin	/* ip6->ip6_plen will be set later */
45653541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
45753541Sshin	ip6->ip6_hlim = 255;
45853541Sshin	if (daddr6)
45953541Sshin		ip6->ip6_dst = *daddr6;
46053541Sshin	else {
46153541Sshin		ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
462148385Sume		ip6->ip6_dst.s6_addr16[1] = 0;
46353541Sshin		ip6->ip6_dst.s6_addr32[1] = 0;
46453541Sshin		ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
46553541Sshin		ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
46653541Sshin		ip6->ip6_dst.s6_addr8[12] = 0xff;
467148385Sume		if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
468148385Sume			goto bad;
46953541Sshin	}
470279531Shrs	if (nonce == NULL) {
471194760Srwatson		struct ifaddr *ifa;
472194760Srwatson
47353541Sshin		/*
47453541Sshin		 * RFC2461 7.2.2:
47553541Sshin		 * "If the source address of the packet prompting the
47653541Sshin		 * solicitation is the same as one of the addresses assigned
47753541Sshin		 * to the outgoing interface, that address SHOULD be placed
47853541Sshin		 * in the IP Source Address of the outgoing solicitation.
47953541Sshin		 * Otherwise, any one of the addresses assigned to the
48053541Sshin		 * interface should be used."
48153541Sshin		 *
48253541Sshin		 * We use the source address for the prompting packet
48353541Sshin		 * (saddr6), if:
48453541Sshin		 * - saddr6 is given from the caller (by giving "ln"), and
48553541Sshin		 * - saddr6 belongs to the outgoing interface.
486148385Sume		 * Otherwise, we perform the source address selection as usual.
48753541Sshin		 */
488216022Sbz		struct in6_addr *hsrc;
48953541Sshin
490216022Sbz		hsrc = NULL;
491216022Sbz		if (ln != NULL) {
492216022Sbz			LLE_RLOCK(ln);
493216022Sbz			if (ln->la_hold != NULL) {
494216022Sbz				struct ip6_hdr *hip6;		/* hold ip6 */
495216022Sbz
496216022Sbz				/*
497216022Sbz				 * assuming every packet in la_hold has the same IP
498216022Sbz				 * header
499216022Sbz				 */
500216022Sbz				hip6 = mtod(ln->la_hold, struct ip6_hdr *);
501216022Sbz				/* XXX pullup? */
502216022Sbz				if (sizeof(*hip6) < ln->la_hold->m_len) {
503216022Sbz					ip6->ip6_src = hip6->ip6_src;
504216022Sbz					hsrc = &hip6->ip6_src;
505216022Sbz				}
506216022Sbz			}
507216022Sbz			LLE_RUNLOCK(ln);
508148385Sume		}
509194760Srwatson		if (hsrc && (ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp,
510194760Srwatson		    hsrc)) != NULL) {
511216022Sbz			/* ip6_src set already. */
512194760Srwatson			ifa_free(ifa);
513194760Srwatson		} else {
514148385Sume			int error;
515148385Sume			struct sockaddr_in6 dst_sa;
516216022Sbz			struct in6_addr src_in;
517231852Sbz			struct ifnet *oifp;
518148385Sume
519148385Sume			bzero(&dst_sa, sizeof(dst_sa));
520148385Sume			dst_sa.sin6_family = AF_INET6;
521148385Sume			dst_sa.sin6_len = sizeof(dst_sa);
522148385Sume			dst_sa.sin6_addr = ip6->ip6_dst;
523148385Sume
524231852Sbz			oifp = ifp;
525194777Sbz			error = in6_selectsrc(&dst_sa, NULL,
526231852Sbz			    NULL, &ro, NULL, &oifp, &src_in);
527194777Sbz			if (error) {
528165118Sbz				char ip6buf[INET6_ADDRSTRLEN];
529279564Sae				nd6log((LOG_DEBUG, "%s: source can't be "
530279564Sae				    "determined: dst=%s, error=%d\n", __func__,
531165118Sbz				    ip6_sprintf(ip6buf, &dst_sa.sin6_addr),
532165118Sbz				    error));
533148385Sume				goto bad;
53453541Sshin			}
535216022Sbz			ip6->ip6_src = src_in;
53653541Sshin		}
53753541Sshin	} else {
53853541Sshin		/*
53953541Sshin		 * Source address for DAD packet must always be IPv6
54053541Sshin		 * unspecified address. (0::0)
541148385Sume		 * We actually don't have to 0-clear the address (we did it
542148385Sume		 * above), but we do so here explicitly to make the intention
543148385Sume		 * clearer.
54453541Sshin		 */
545216022Sbz		bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
54653541Sshin	}
54753541Sshin	nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
54853541Sshin	nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
54953541Sshin	nd_ns->nd_ns_code = 0;
55053541Sshin	nd_ns->nd_ns_reserved = 0;
55153541Sshin	nd_ns->nd_ns_target = *taddr6;
552121315Sume	in6_clearscope(&nd_ns->nd_ns_target); /* XXX */
55353541Sshin
55453541Sshin	/*
55553541Sshin	 * Add source link-layer address option.
55653541Sshin	 *
55753541Sshin	 *				spec		implementation
55853541Sshin	 *				---		---
55953541Sshin	 * DAD packet			MUST NOT	do not add the option
56053541Sshin	 * there's no link layer address:
56153541Sshin	 *				impossible	do not add the option
56253541Sshin	 * there's link layer address:
56353541Sshin	 *	Multicast NS		MUST add one	add the option
56453541Sshin	 *	Unicast NS		SHOULD add one	add the option
56553541Sshin	 */
566279531Shrs	if (nonce == NULL && (mac = nd6_ifptomac(ifp))) {
56753541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
56853541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
56953541Sshin		/* 8 byte alignments... */
57053541Sshin		optlen = (optlen + 7) & ~7;
571120941Sume
57253541Sshin		m->m_pkthdr.len += optlen;
57353541Sshin		m->m_len += optlen;
57453541Sshin		icmp6len += optlen;
57553541Sshin		bzero((caddr_t)nd_opt, optlen);
57653541Sshin		nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
57753541Sshin		nd_opt->nd_opt_len = optlen >> 3;
57853541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
57953541Sshin	}
580279531Shrs	/*
581279531Shrs	 * Add a Nonce option (RFC 3971) to detect looped back NS messages.
582279531Shrs	 * This behavior is documented as Enhanced Duplicate Address
583279531Shrs	 * Detection in draft-ietf-6man-enhanced-dad-13.
584279531Shrs	 * net.inet6.ip6.dad_enhanced=0 disables this.
585279531Shrs	 */
586279531Shrs	if (V_dad_enhanced != 0 && nonce != NULL) {
587279531Shrs		int optlen = sizeof(struct nd_opt_hdr) + ND_OPT_NONCE_LEN;
588279531Shrs		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
589279531Shrs		/* 8-byte alignment is required. */
590279531Shrs		optlen = (optlen + 7) & ~7;
59153541Sshin
592279531Shrs		m->m_pkthdr.len += optlen;
593279531Shrs		m->m_len += optlen;
594279531Shrs		icmp6len += optlen;
595279531Shrs		bzero((caddr_t)nd_opt, optlen);
596279531Shrs		nd_opt->nd_opt_type = ND_OPT_NONCE;
597279531Shrs		nd_opt->nd_opt_len = optlen >> 3;
598279531Shrs		bcopy(nonce, (caddr_t)(nd_opt + 1), ND_OPT_NONCE_LEN);
599279531Shrs	}
60053541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
60153541Sshin	nd_ns->nd_ns_cksum = 0;
602120941Sume	nd_ns->nd_ns_cksum =
603120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
60453541Sshin
605211501Sanchie	if (send_sendso_input_hook != NULL) {
606211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
607211501Sanchie			sizeof(unsigned short), M_NOWAIT);
608211501Sanchie		if (mtag == NULL)
609211501Sanchie			goto bad;
610211501Sanchie		*(unsigned short *)(mtag + 1) = nd_ns->nd_ns_type;
611211501Sanchie		m_tag_prepend(m, mtag);
612211501Sanchie	}
613211501Sanchie
614279531Shrs	ip6_output(m, NULL, &ro, (nonce != NULL) ? IPV6_UNSPECSRC : 0,
615279531Shrs	    &im6o, NULL, NULL);
616148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
617148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
618190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
619148385Sume
620238092Sglebius	/* We don't cache this route. */
621238092Sglebius	RO_RTFREE(&ro);
622238092Sglebius
623148385Sume	return;
624148385Sume
625148385Sume  bad:
626148385Sume	if (ro.ro_rt) {
627148385Sume		RTFREE(ro.ro_rt);
628148385Sume	}
629148385Sume	m_freem(m);
630148385Sume	return;
63153541Sshin}
63253541Sshin
633279564Sae#ifndef BURN_BRIDGES
634279564Saevoid
635279564Saend6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
636279564Sae    const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce)
637279564Sae{
638279564Sae
639279564Sae	nd6_ns_output_fib(ifp, daddr6, taddr6, ln, nonce, RT_DEFAULT_FIB);
640279564Sae}
641279564Sae#endif
64253541Sshin/*
64353541Sshin * Neighbor advertisement input handling.
64453541Sshin *
64553541Sshin * Based on RFC 2461
646148987Sume * Based on RFC 2462 (duplicate address detection)
64762587Sitojun *
64862587Sitojun * the following items are not implemented yet:
64962587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
65062587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
65153541Sshin */
65253541Sshinvoid
653171259Sdelphijnd6_na_input(struct mbuf *m, int off, int icmp6len)
65453541Sshin{
65553541Sshin	struct ifnet *ifp = m->m_pkthdr.rcvif;
65653541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
65762587Sitojun	struct nd_neighbor_advert *nd_na;
65853541Sshin	struct in6_addr daddr6 = ip6->ip6_dst;
65962587Sitojun	struct in6_addr taddr6;
66062587Sitojun	int flags;
66162587Sitojun	int is_router;
66262587Sitojun	int is_solicited;
66362587Sitojun	int is_override;
66453541Sshin	char *lladdr = NULL;
66553541Sshin	int lladdrlen = 0;
666186468Skmacy	int checklink = 0;
66753541Sshin	struct ifaddr *ifa;
668186119Sqingli	struct llentry *ln = NULL;
66953541Sshin	union nd_opts ndopts;
670186119Sqingli	struct mbuf *chain = NULL;
671186119Sqingli	struct sockaddr_in6 sin6;
672165118Sbz	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
67353541Sshin
67453541Sshin	if (ip6->ip6_hlim != 255) {
67578064Sume		nd6log((LOG_ERR,
67678064Sume		    "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
677165118Sbz		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
678165118Sbz		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
67978064Sume		goto bad;
68062587Sitojun	}
68162587Sitojun
68262587Sitojun#ifndef PULLDOWN_TEST
68362587Sitojun	IP6_EXTHDR_CHECK(m, off, icmp6len,);
68462587Sitojun	nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
68562587Sitojun#else
68662587Sitojun	IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
68762587Sitojun	if (nd_na == NULL) {
688190964Srwatson		ICMP6STAT_INC(icp6s_tooshort);
68953541Sshin		return;
69053541Sshin	}
69162587Sitojun#endif
692148385Sume
69362587Sitojun	flags = nd_na->nd_na_flags_reserved;
69462587Sitojun	is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
69562587Sitojun	is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
69662587Sitojun	is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
697276844Smelifaro	memset(&sin6, 0, sizeof(sin6));
69853541Sshin
699148385Sume	taddr6 = nd_na->nd_na_target;
700148385Sume	if (in6_setscope(&taddr6, ifp, NULL))
701150202Ssuz		goto bad;	/* XXX: impossible */
70253541Sshin
70353541Sshin	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
70478064Sume		nd6log((LOG_ERR,
70553541Sshin		    "nd6_na_input: invalid target address %s\n",
706165118Sbz		    ip6_sprintf(ip6bufs, &taddr6)));
70778064Sume		goto bad;
70853541Sshin	}
70953541Sshin	if (IN6_IS_ADDR_MULTICAST(&daddr6))
71053541Sshin		if (is_solicited) {
71178064Sume			nd6log((LOG_ERR,
71278064Sume			    "nd6_na_input: a solicited adv is multicasted\n"));
71378064Sume			goto bad;
71453541Sshin		}
71553541Sshin
71653541Sshin	icmp6len -= sizeof(*nd_na);
71753541Sshin	nd6_option_init(nd_na + 1, icmp6len, &ndopts);
71853541Sshin	if (nd6_options(&ndopts) < 0) {
71978064Sume		nd6log((LOG_INFO,
72078064Sume		    "nd6_na_input: invalid ND option, ignored\n"));
72178064Sume		/* nd6_options have incremented stats */
72262587Sitojun		goto freeit;
72353541Sshin	}
72453541Sshin
72553541Sshin	if (ndopts.nd_opts_tgt_lladdr) {
72653541Sshin		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
72753541Sshin		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
72853541Sshin	}
72953541Sshin
730228571Sglebius	/*
731228571Sglebius	 * This effectively disables the DAD check on a non-master CARP
732228571Sglebius	 * address.
733228571Sglebius	 */
734228571Sglebius	if (ifp->if_carp)
735228571Sglebius		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
736228571Sglebius	else
737228571Sglebius		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
73853541Sshin
73953541Sshin	/*
74053541Sshin	 * Target address matches one of my interface address.
74153541Sshin	 *
74253541Sshin	 * If my address is tentative, this means that there's somebody
74353541Sshin	 * already using the same address as mine.  This indicates DAD failure.
74453541Sshin	 * This is defined in RFC 2462.
74553541Sshin	 *
74653541Sshin	 * Otherwise, process as defined in RFC 2461.
74753541Sshin	 */
74853541Sshin	if (ifa
74953541Sshin	 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
750194760Srwatson		ifa_free(ifa);
75153541Sshin		nd6_dad_na_input(ifa);
75262587Sitojun		goto freeit;
75353541Sshin	}
75453541Sshin
75595023Ssuz	/* Just for safety, maybe unnecessary. */
75653541Sshin	if (ifa) {
757194760Srwatson		ifa_free(ifa);
75853541Sshin		log(LOG_ERR,
75953541Sshin		    "nd6_na_input: duplicate IP6 address %s\n",
760165118Sbz		    ip6_sprintf(ip6bufs, &taddr6));
76162587Sitojun		goto freeit;
76253541Sshin	}
76353541Sshin
76453541Sshin	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
765120941Sume		nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
766165118Sbz		    "(if %d, NA packet %d)\n", ip6_sprintf(ip6bufs, &taddr6),
767120941Sume		    ifp->if_addrlen, lladdrlen - 2));
76878064Sume		goto bad;
76953541Sshin	}
77053541Sshin
77153541Sshin	/*
772120941Sume	 * If no neighbor cache entry is found, NA SHOULD silently be
773120941Sume	 * discarded.
77453541Sshin	 */
775260187Sae	IF_AFDATA_RLOCK(ifp);
776186119Sqingli	ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
777260187Sae	IF_AFDATA_RUNLOCK(ifp);
778186119Sqingli	if (ln == NULL) {
77962587Sitojun		goto freeit;
780186119Sqingli	}
78153541Sshin
78253541Sshin	if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
78353541Sshin		/*
78453541Sshin		 * If the link-layer has address, and no lladdr option came,
78553541Sshin		 * discard the packet.
78653541Sshin		 */
787186119Sqingli		if (ifp->if_addrlen && lladdr == NULL) {
78862587Sitojun			goto freeit;
789186119Sqingli		}
79053541Sshin
79153541Sshin		/*
79253541Sshin		 * Record link-layer address, and update the state.
79353541Sshin		 */
794186119Sqingli		bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
795186119Sqingli		ln->la_flags |= LLE_VALID;
796245925Snp		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
79753541Sshin		if (is_solicited) {
79853541Sshin			ln->ln_state = ND6_LLINFO_REACHABLE;
79962587Sitojun			ln->ln_byhint = 0;
800151539Ssuz			if (!ND6_LLINFO_PERMANENT(ln)) {
801186119Sqingli				nd6_llinfo_settimer_locked(ln,
802186119Sqingli				    (long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
803120941Sume			}
80478064Sume		} else {
80553541Sshin			ln->ln_state = ND6_LLINFO_STALE;
806186119Sqingli			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
80778064Sume		}
80878064Sume		if ((ln->ln_router = is_router) != 0) {
80978064Sume			/*
81078064Sume			 * This means a router's state has changed from
81178064Sume			 * non-reachable to probably reachable, and might
81278064Sume			 * affect the status of associated prefixes..
81378064Sume			 */
814186468Skmacy			checklink = 1;
81578064Sume		}
81653541Sshin	} else {
81753541Sshin		int llchange;
81853541Sshin
81953541Sshin		/*
82053541Sshin		 * Check if the link-layer address has changed or not.
82153541Sshin		 */
822151465Ssuz		if (lladdr == NULL)
82353541Sshin			llchange = 0;
82453541Sshin		else {
825186119Sqingli			if (ln->la_flags & LLE_VALID) {
826186119Sqingli				if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
82753541Sshin					llchange = 1;
82853541Sshin				else
82953541Sshin					llchange = 0;
83053541Sshin			} else
83153541Sshin				llchange = 1;
83253541Sshin		}
83353541Sshin
83453541Sshin		/*
83553541Sshin		 * This is VERY complex.  Look at it with care.
83653541Sshin		 *
83753541Sshin		 * override solicit lladdr llchange	action
83853541Sshin		 *					(L: record lladdr)
83953541Sshin		 *
84053541Sshin		 *	0	0	n	--	(2c)
84153541Sshin		 *	0	0	y	n	(2b) L
84253541Sshin		 *	0	0	y	y	(1)    REACHABLE->STALE
84353541Sshin		 *	0	1	n	--	(2c)   *->REACHABLE
84453541Sshin		 *	0	1	y	n	(2b) L *->REACHABLE
84553541Sshin		 *	0	1	y	y	(1)    REACHABLE->STALE
84653541Sshin		 *	1	0	n	--	(2a)
84753541Sshin		 *	1	0	y	n	(2a) L
84853541Sshin		 *	1	0	y	y	(2a) L *->STALE
84953541Sshin		 *	1	1	n	--	(2a)   *->REACHABLE
85053541Sshin		 *	1	1	y	n	(2a) L *->REACHABLE
85153541Sshin		 *	1	1	y	y	(2a) L *->REACHABLE
85253541Sshin		 */
853151539Ssuz		if (!is_override && (lladdr != NULL && llchange)) {  /* (1) */
85453541Sshin			/*
85553541Sshin			 * If state is REACHABLE, make it STALE.
85653541Sshin			 * no other updates should be done.
85753541Sshin			 */
85878064Sume			if (ln->ln_state == ND6_LLINFO_REACHABLE) {
85953541Sshin				ln->ln_state = ND6_LLINFO_STALE;
860186119Sqingli				nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
86178064Sume			}
86262587Sitojun			goto freeit;
86353541Sshin		} else if (is_override				   /* (2a) */
864151465Ssuz			|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */
865151465Ssuz			|| lladdr == NULL) {			   /* (2c) */
86653541Sshin			/*
86753541Sshin			 * Update link-local address, if any.
86853541Sshin			 */
869151465Ssuz			if (lladdr != NULL) {
870186119Sqingli				bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
871186119Sqingli				ln->la_flags |= LLE_VALID;
872245925Snp				EVENTHANDLER_INVOKE(lle_event, ln,
873245925Snp				    LLENTRY_RESOLVED);
87453541Sshin			}
87553541Sshin
87653541Sshin			/*
87753541Sshin			 * If solicited, make the state REACHABLE.
87853541Sshin			 * If not solicited and the link-layer address was
87953541Sshin			 * changed, make it STALE.
88053541Sshin			 */
88153541Sshin			if (is_solicited) {
88253541Sshin				ln->ln_state = ND6_LLINFO_REACHABLE;
88362587Sitojun				ln->ln_byhint = 0;
884151539Ssuz				if (!ND6_LLINFO_PERMANENT(ln)) {
885186119Sqingli					nd6_llinfo_settimer_locked(ln,
886151539Ssuz					    (long)ND_IFINFO(ifp)->reachable * hz);
88753541Sshin				}
88853541Sshin			} else {
889151465Ssuz				if (lladdr != NULL && llchange) {
89053541Sshin					ln->ln_state = ND6_LLINFO_STALE;
891186119Sqingli					nd6_llinfo_settimer_locked(ln,
892181803Sbz					    (long)V_nd6_gctimer * hz);
89378064Sume				}
89453541Sshin			}
89553541Sshin		}
89653541Sshin
89753541Sshin		if (ln->ln_router && !is_router) {
89853541Sshin			/*
89953541Sshin			 * The peer dropped the router flag.
90053541Sshin			 * Remove the sender from the Default Router List and
90153541Sshin			 * update the Destination Cache entries.
90253541Sshin			 */
90353541Sshin			struct nd_defrouter *dr;
90453541Sshin			struct in6_addr *in6;
90553541Sshin
906186119Sqingli			in6 = &L3_ADDR_SIN6(ln)->sin6_addr;
90795023Ssuz
90895023Ssuz			/*
90995023Ssuz			 * Lock to protect the default router list.
91095023Ssuz			 * XXX: this might be unnecessary, since this function
91195023Ssuz			 * is only called under the network software interrupt
912120941Sume			 * context.  However, we keep it just for safety.
91395023Ssuz			 */
914186119Sqingli			dr = defrouter_lookup(in6, ln->lle_tbl->llt_ifp);
91553541Sshin			if (dr)
91653541Sshin				defrtrlist_del(dr);
917222728Shrs			else if (ND_IFINFO(ln->lle_tbl->llt_ifp)->flags &
918222728Shrs			    ND6_IFF_ACCEPT_RTADV) {
91953541Sshin				/*
92053541Sshin				 * Even if the neighbor is not in the default
92153541Sshin				 * router list, the neighbor may be used
92253541Sshin				 * as a next hop for some destinations
92353541Sshin				 * (e.g. redirect case). So we must
92453541Sshin				 * call rt6_flush explicitly.
92553541Sshin				 */
926128422Sluigi				rt6_flush(&ip6->ip6_src, ifp);
92753541Sshin			}
92853541Sshin		}
92953541Sshin		ln->ln_router = is_router;
93053541Sshin	}
931186119Sqingli        /* XXX - QL
932186119Sqingli	 *  Does this matter?
933186119Sqingli	 *  rt->rt_flags &= ~RTF_REJECT;
934186119Sqingli	 */
935186119Sqingli	ln->la_asked = 0;
936276844Smelifaro	if (ln->la_hold != NULL)
937276844Smelifaro		nd6_grab_holdchain(ln, &chain, &sin6);
938186119Sqingli freeit:
939276844Smelifaro	if (ln != NULL)
940186119Sqingli		LLE_WUNLOCK(ln);
94162587Sitojun
942276844Smelifaro	if (chain != NULL)
943276844Smelifaro		nd6_flush_holdchain(ifp, ifp, chain, &sin6);
944276844Smelifaro
945186468Skmacy	if (checklink)
946186468Skmacy		pfxlist_onlink_check();
947186468Skmacy
94862587Sitojun	m_freem(m);
94978064Sume	return;
95078064Sume
95178064Sume bad:
952186160Skmacy	if (ln != NULL)
953186119Sqingli		LLE_WUNLOCK(ln);
954186119Sqingli
955190964Srwatson	ICMP6STAT_INC(icp6s_badna);
95678064Sume	m_freem(m);
95753541Sshin}
95853541Sshin
95953541Sshin/*
96053541Sshin * Neighbor advertisement output handling.
96153541Sshin *
96253541Sshin * Based on RFC 2461
96353541Sshin *
96462587Sitojun * the following items are not implemented yet:
96562587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
96662587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
967171259Sdelphij *
968171259Sdelphij * tlladdr - 1 if include target link-layer address
969171259Sdelphij * sdl0 - sockaddr_dl (= proxy NA) or NULL
97053541Sshin */
971231852Sbzstatic void
972231852Sbznd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
973171259Sdelphij    const struct in6_addr *taddr6, u_long flags, int tlladdr,
974231852Sbz    struct sockaddr *sdl0, u_int fibnum)
97553541Sshin{
97653541Sshin	struct mbuf *m;
977211501Sanchie	struct m_tag *mtag;
978231852Sbz	struct ifnet *oifp;
97953541Sshin	struct ip6_hdr *ip6;
98053541Sshin	struct nd_neighbor_advert *nd_na;
98153541Sshin	struct ip6_moptions im6o;
982194777Sbz	struct in6_addr src, daddr6;
983148385Sume	struct sockaddr_in6 dst_sa;
984148385Sume	int icmp6len, maxlen, error;
98592733Speter	caddr_t mac = NULL;
986148385Sume	struct route_in6 ro;
98762587Sitojun
988148385Sume	bzero(&ro, sizeof(ro));
989148385Sume
990148385Sume	daddr6 = *daddr6_0;	/* make a local copy for modification */
991148385Sume
99262587Sitojun	/* estimate the size of message */
99362587Sitojun	maxlen = sizeof(*ip6) + sizeof(*nd_na);
99462587Sitojun	maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
99562587Sitojun	if (max_linkhdr + maxlen >= MCLBYTES) {
99662587Sitojun#ifdef DIAGNOSTIC
99762587Sitojun		printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES "
99862587Sitojun		    "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
99962587Sitojun#endif
100053541Sshin		return;
100162587Sitojun	}
100253541Sshin
1003248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
1004248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1005248328Sglebius	else
1006248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
100762587Sitojun	if (m == NULL)
100862587Sitojun		return;
1009231852Sbz	M_SETFIB(m, fibnum);
101062587Sitojun
1011148385Sume	if (IN6_IS_ADDR_MULTICAST(&daddr6)) {
101253541Sshin		m->m_flags |= M_MCAST;
101353541Sshin		im6o.im6o_multicast_ifp = ifp;
101453541Sshin		im6o.im6o_multicast_hlim = 255;
101553541Sshin		im6o.im6o_multicast_loop = 0;
101653541Sshin	}
101753541Sshin
101853541Sshin	icmp6len = sizeof(*nd_na);
101953541Sshin	m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
1020276692Srwatson	m->m_data += max_linkhdr;	/* or M_ALIGN() equivalent? */
102153541Sshin
102253541Sshin	/* fill neighbor advertisement packet */
102353541Sshin	ip6 = mtod(m, struct ip6_hdr *);
102453541Sshin	ip6->ip6_flow = 0;
102562587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
102662587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
102753541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
102853541Sshin	ip6->ip6_hlim = 255;
1029148385Sume	if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
103053541Sshin		/* reply to DAD */
1031153227Sume		daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
1032153227Sume		daddr6.s6_addr16[1] = 0;
1033153227Sume		daddr6.s6_addr32[1] = 0;
1034153227Sume		daddr6.s6_addr32[2] = 0;
1035153227Sume		daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
1036148385Sume		if (in6_setscope(&daddr6, ifp, NULL))
1037148385Sume			goto bad;
1038148385Sume
103953541Sshin		flags &= ~ND_NA_FLAG_SOLICITED;
1040148385Sume	}
1041148385Sume	ip6->ip6_dst = daddr6;
1042148385Sume	bzero(&dst_sa, sizeof(struct sockaddr_in6));
1043148385Sume	dst_sa.sin6_family = AF_INET6;
1044148385Sume	dst_sa.sin6_len = sizeof(struct sockaddr_in6);
1045148385Sume	dst_sa.sin6_addr = daddr6;
104653541Sshin
104753541Sshin	/*
104853541Sshin	 * Select a source whose scope is the same as that of the dest.
104953541Sshin	 */
1050148385Sume	bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
1051231852Sbz	oifp = ifp;
1052231852Sbz	error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src);
1053194777Sbz	if (error) {
1054165118Sbz		char ip6buf[INET6_ADDRSTRLEN];
1055148385Sume		nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
1056148385Sume		    "determined: dst=%s, error=%d\n",
1057165118Sbz		    ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error));
1058148385Sume		goto bad;
105953541Sshin	}
1060194777Sbz	ip6->ip6_src = src;
106153541Sshin	nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
106253541Sshin	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
106353541Sshin	nd_na->nd_na_code = 0;
106453541Sshin	nd_na->nd_na_target = *taddr6;
1065121315Sume	in6_clearscope(&nd_na->nd_na_target); /* XXX */
106653541Sshin
106753541Sshin	/*
106853541Sshin	 * "tlladdr" indicates NS's condition for adding tlladdr or not.
106953541Sshin	 * see nd6_ns_input() for details.
107053541Sshin	 * Basically, if NS packet is sent to unicast/anycast addr,
107153541Sshin	 * target lladdr option SHOULD NOT be included.
107253541Sshin	 */
107362587Sitojun	if (tlladdr) {
107462587Sitojun		/*
107562587Sitojun		 * sdl0 != NULL indicates proxy NA.  If we do proxy, use
107662587Sitojun		 * lladdr in sdl0.  If we are not proxying (sending NA for
107762587Sitojun		 * my address) use lladdr configured for the interface.
107862587Sitojun		 */
1079142215Sglebius		if (sdl0 == NULL) {
1080142215Sglebius			if (ifp->if_carp)
1081211157Swill				mac = (*carp_macmatch6_p)(ifp, m, taddr6);
1082142215Sglebius			if (mac == NULL)
1083142215Sglebius				mac = nd6_ifptomac(ifp);
1084142215Sglebius		} else if (sdl0->sa_family == AF_LINK) {
108562587Sitojun			struct sockaddr_dl *sdl;
108662587Sitojun			sdl = (struct sockaddr_dl *)sdl0;
108762587Sitojun			if (sdl->sdl_alen == ifp->if_addrlen)
108862587Sitojun				mac = LLADDR(sdl);
108962587Sitojun		}
109062587Sitojun	}
109162587Sitojun	if (tlladdr && mac) {
109253541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
109353541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
1094120941Sume
109553541Sshin		/* roundup to 8 bytes alignment! */
109653541Sshin		optlen = (optlen + 7) & ~7;
109753541Sshin
109853541Sshin		m->m_pkthdr.len += optlen;
109953541Sshin		m->m_len += optlen;
110053541Sshin		icmp6len += optlen;
110153541Sshin		bzero((caddr_t)nd_opt, optlen);
110253541Sshin		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
110353541Sshin		nd_opt->nd_opt_len = optlen >> 3;
110453541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
110553541Sshin	} else
110653541Sshin		flags &= ~ND_NA_FLAG_OVERRIDE;
110753541Sshin
110853541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
110953541Sshin	nd_na->nd_na_flags_reserved = flags;
111053541Sshin	nd_na->nd_na_cksum = 0;
111153541Sshin	nd_na->nd_na_cksum =
1112120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
111353541Sshin
1114211501Sanchie	if (send_sendso_input_hook != NULL) {
1115211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
1116211501Sanchie		    sizeof(unsigned short), M_NOWAIT);
1117211501Sanchie		if (mtag == NULL)
1118211501Sanchie			goto bad;
1119211501Sanchie		*(unsigned short *)(mtag + 1) = nd_na->nd_na_type;
1120211501Sanchie		m_tag_prepend(m, mtag);
1121211501Sanchie	}
1122211501Sanchie
1123148385Sume	ip6_output(m, NULL, &ro, 0, &im6o, NULL, NULL);
1124148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
1125148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
1126190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);
1127148385Sume
1128238092Sglebius	/* We don't cache this route. */
1129238092Sglebius	RO_RTFREE(&ro);
1130238092Sglebius
1131148385Sume	return;
1132148385Sume
1133148385Sume  bad:
1134148385Sume	if (ro.ro_rt) {
1135148385Sume		RTFREE(ro.ro_rt);
1136148385Sume	}
1137148385Sume	m_freem(m);
1138148385Sume	return;
113953541Sshin}
114053541Sshin
1141231852Sbz#ifndef BURN_BRIDGES
1142231852Sbzvoid
1143231852Sbznd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
1144231852Sbz    const struct in6_addr *taddr6, u_long flags, int tlladdr,
1145231852Sbz    struct sockaddr *sdl0)
1146231852Sbz{
1147231852Sbz
1148231852Sbz	nd6_na_output_fib(ifp, daddr6_0, taddr6, flags, tlladdr, sdl0,
1149231852Sbz	    RT_DEFAULT_FIB);
1150231852Sbz}
1151231852Sbz#endif
1152231852Sbz
115353541Sshincaddr_t
1154171259Sdelphijnd6_ifptomac(struct ifnet *ifp)
115553541Sshin{
115653541Sshin	switch (ifp->if_type) {
115753541Sshin	case IFT_ARCNET:
115853541Sshin	case IFT_ETHER:
115953541Sshin	case IFT_FDDI:
116078064Sume	case IFT_IEEE1394:
116178468Ssumikawa#ifdef IFT_L2VLAN
116278468Ssumikawa	case IFT_L2VLAN:
116378468Ssumikawa#endif
116478064Sume#ifdef IFT_IEEE80211
116578064Sume	case IFT_IEEE80211:
116678064Sume#endif
1167219819Sjeff	case IFT_INFINIBAND:
1168149829Sthompsa	case IFT_BRIDGE:
1169120049Smdodd	case IFT_ISO88025:
1170147306Sbrooks		return IF_LLADDR(ifp);
117153541Sshin	default:
117253541Sshin		return NULL;
117353541Sshin	}
117453541Sshin}
117553541Sshin
117653541Sshinstruct dadq {
117760938Sjake	TAILQ_ENTRY(dadq) dad_list;
117853541Sshin	struct ifaddr *dad_ifa;
117953541Sshin	int dad_count;		/* max NS to send */
118062587Sitojun	int dad_ns_tcount;	/* # of trials to send NS */
118153541Sshin	int dad_ns_ocount;	/* NS sent so far */
118253541Sshin	int dad_ns_icount;
118353541Sshin	int dad_na_icount;
1184279531Shrs	int dad_ns_lcount;	/* looped back NS */
118578064Sume	struct callout dad_timer_ch;
1186191816Szec	struct vnet *dad_vnet;
1187275593Smarkj	u_int dad_refcnt;
1188279531Shrs#define	ND_OPT_NONCE_LEN32 \
1189279531Shrs		((ND_OPT_NONCE_LEN + sizeof(uint32_t) - 1)/sizeof(uint32_t))
1190279531Shrs	uint32_t dad_nonce[ND_OPT_NONCE_LEN32];
119153541Sshin};
119253541Sshin
1193215701Sdimstatic VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
1194266857Shrsstatic VNET_DEFINE(struct rwlock, dad_rwlock);
1195266857Shrs#define	V_dadq			VNET(dadq)
1196266857Shrs#define	V_dad_rwlock		VNET(dad_rwlock)
1197195699Srwatson
1198266857Shrs#define	DADQ_RLOCK()		rw_rlock(&V_dad_rwlock)
1199266857Shrs#define	DADQ_RUNLOCK()		rw_runlock(&V_dad_rwlock)
1200266857Shrs#define	DADQ_WLOCK()		rw_wlock(&V_dad_rwlock)
1201266857Shrs#define	DADQ_WUNLOCK()		rw_wunlock(&V_dad_rwlock)
1202266857Shrs
1203274347Smelifarostatic void
1204274347Smelifarond6_dad_add(struct dadq *dp)
1205274347Smelifaro{
1206274347Smelifaro
1207274347Smelifaro	DADQ_WLOCK();
1208275593Smarkj	TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list);
1209274347Smelifaro	DADQ_WUNLOCK();
1210274347Smelifaro}
1211274347Smelifaro
1212274347Smelifarostatic void
1213274347Smelifarond6_dad_del(struct dadq *dp)
1214274347Smelifaro{
1215274347Smelifaro
1216274347Smelifaro	DADQ_WLOCK();
1217275593Smarkj	TAILQ_REMOVE(&V_dadq, dp, dad_list);
1218274347Smelifaro	DADQ_WUNLOCK();
1219275593Smarkj	nd6_dad_rele(dp);
1220274347Smelifaro}
1221274347Smelifaro
122253541Sshinstatic struct dadq *
1223279531Shrsnd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n)
122453541Sshin{
122553541Sshin	struct dadq *dp;
1226279531Shrs	char ip6buf[INET6_ADDRSTRLEN];
122753541Sshin
1228266857Shrs	DADQ_RLOCK();
1229279531Shrs	TAILQ_FOREACH(dp, &V_dadq, dad_list) {
1230279531Shrs		if (dp->dad_ifa != ifa)
1231279531Shrs			continue;
1232279531Shrs		/*
1233279531Shrs		 * Skip if the nonce matches the received one.
1234279531Shrs		 * +2 in the length is required because of type and
1235279531Shrs		 * length fields are included in a header.
1236279531Shrs		 */
1237279531Shrs		if (n != NULL &&
1238279531Shrs		    n->nd_opt_nonce_len == (ND_OPT_NONCE_LEN + 2) / 8 &&
1239279531Shrs		    memcmp(&n->nd_opt_nonce[0], &dp->dad_nonce[0],
1240279531Shrs		        ND_OPT_NONCE_LEN) == 0) {
1241279531Shrs			log(LOG_ERR, "%s: a looped back NS message is "
1242279531Shrs			    "detected during DAD for %s.\n",
1243279531Shrs			    if_name(ifa->ifa_ifp),
1244279531Shrs			    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
1245279531Shrs			dp->dad_ns_lcount++;
1246279531Shrs			continue;
1247275593Smarkj		}
1248279531Shrs		refcount_acquire(&dp->dad_refcnt);
1249279531Shrs		break;
1250279531Shrs	}
1251266857Shrs	DADQ_RUNLOCK();
1252226340Sglebius
1253275700Smarkj	return (dp);
125453541Sshin}
125553541Sshin
125678064Sumestatic void
1257171259Sdelphijnd6_dad_starttimer(struct dadq *dp, int ticks)
125878064Sume{
125978064Sume
126078064Sume	callout_reset(&dp->dad_timer_ch, ticks,
1261191816Szec	    (void (*)(void *))nd6_dad_timer, (void *)dp);
126278064Sume}
126378064Sume
126478064Sumestatic void
1265171259Sdelphijnd6_dad_stoptimer(struct dadq *dp)
126678064Sume{
126778064Sume
1268275593Smarkj	callout_drain(&dp->dad_timer_ch);
126978064Sume}
127078064Sume
1271275593Smarkjstatic void
1272275593Smarkjnd6_dad_rele(struct dadq *dp)
1273275593Smarkj{
1274275593Smarkj
1275275593Smarkj	if (refcount_release(&dp->dad_refcnt)) {
1276275593Smarkj		ifa_free(dp->dad_ifa);
1277275593Smarkj		free(dp, M_IP6NDP);
1278275593Smarkj	}
1279275593Smarkj}
1280275593Smarkj
1281275593Smarkjvoid
1282275593Smarkjnd6_dad_init(void)
1283275593Smarkj{
1284275593Smarkj
1285275593Smarkj	rw_init(&V_dad_rwlock, "nd6 DAD queue");
1286275593Smarkj	TAILQ_INIT(&V_dadq);
1287275593Smarkj}
1288275593Smarkj
128953541Sshin/*
1290148987Sume * Start Duplicate Address Detection (DAD) for specified interface address.
129153541Sshin */
129253541Sshinvoid
1293171259Sdelphijnd6_dad_start(struct ifaddr *ifa, int delay)
129453541Sshin{
129553541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
129653541Sshin	struct dadq *dp;
1297165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
129853541Sshin
129953541Sshin	/*
130053541Sshin	 * If we don't need DAD, don't do it.
130153541Sshin	 * There are several cases:
130253541Sshin	 * - DAD is disabled (ip6_dad_count == 0)
130353541Sshin	 * - the interface address is anycast
130453541Sshin	 */
130553541Sshin	if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
130662587Sitojun		log(LOG_DEBUG,
130762587Sitojun			"nd6_dad_start: called with non-tentative address "
130853541Sshin			"%s(%s)\n",
1309165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
131053541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
131153541Sshin		return;
131253541Sshin	}
131353541Sshin	if (ia->ia6_flags & IN6_IFF_ANYCAST) {
131453541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
131553541Sshin		return;
131653541Sshin	}
1317181803Sbz	if (!V_ip6_dad_count) {
131853541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
131953541Sshin		return;
132053541Sshin	}
1321151465Ssuz	if (ifa->ifa_ifp == NULL)
132253541Sshin		panic("nd6_dad_start: ifa->ifa_ifp == NULL");
1323120941Sume	if (!(ifa->ifa_ifp->if_flags & IFF_UP)) {
132453541Sshin		return;
1325120941Sume	}
1326197138Shrs	if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)
1327197138Shrs		return;
1328279531Shrs	if ((dp = nd6_dad_find(ifa, NULL)) != NULL) {
132953541Sshin		/* DAD already in progress */
1330275593Smarkj		nd6_dad_rele(dp);
133153541Sshin		return;
133253541Sshin	}
133353541Sshin
1334275593Smarkj	dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
133553541Sshin	if (dp == NULL) {
133662587Sitojun		log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
133753541Sshin			"%s(%s)\n",
1338165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
133953541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
134053541Sshin		return;
134153541Sshin	}
134278064Sume	callout_init(&dp->dad_timer_ch, 0);
1343191816Szec#ifdef VIMAGE
1344191816Szec	dp->dad_vnet = curvnet;
1345191816Szec#endif
134678064Sume	nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1347165118Sbz	    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
134853541Sshin
134953541Sshin	/*
135053541Sshin	 * Send NS packet for DAD, ip6_dad_count times.
135153541Sshin	 * Note that we must delay the first transmission, if this is the
135253541Sshin	 * first packet to be sent from the interface after interface
135353541Sshin	 * (re)initialization.
135453541Sshin	 */
135553541Sshin	dp->dad_ifa = ifa;
1356275593Smarkj	ifa_ref(dp->dad_ifa);
1357181803Sbz	dp->dad_count = V_ip6_dad_count;
135853541Sshin	dp->dad_ns_icount = dp->dad_na_icount = 0;
135962587Sitojun	dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1360279531Shrs	dp->dad_ns_lcount = 0;
1361275593Smarkj	refcount_init(&dp->dad_refcnt, 1);
1362274347Smelifaro	nd6_dad_add(dp);
1363151539Ssuz	if (delay == 0) {
136462587Sitojun		nd6_dad_ns_output(dp, ifa);
1365121161Sume		nd6_dad_starttimer(dp,
1366151539Ssuz		    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
136753541Sshin	} else {
1368151539Ssuz		nd6_dad_starttimer(dp, delay);
136953541Sshin	}
137053541Sshin}
137153541Sshin
137278064Sume/*
137378064Sume * terminate DAD unconditionally.  used for address removals.
137478064Sume */
137578064Sumevoid
1376171259Sdelphijnd6_dad_stop(struct ifaddr *ifa)
137778064Sume{
137878064Sume	struct dadq *dp;
137978064Sume
1380279531Shrs	dp = nd6_dad_find(ifa, NULL);
138178064Sume	if (!dp) {
138278064Sume		/* DAD wasn't started yet */
138378064Sume		return;
138478064Sume	}
138578064Sume
138678064Sume	nd6_dad_stoptimer(dp);
138778064Sume
1388275593Smarkj	/*
1389275593Smarkj	 * The DAD queue entry may have been removed by nd6_dad_timer() while
1390275593Smarkj	 * we were waiting for it to stop, so re-do the lookup.
1391275593Smarkj	 */
1392275593Smarkj	nd6_dad_rele(dp);
1393279531Shrs	if (nd6_dad_find(ifa, NULL) == NULL)
1394275593Smarkj		return;
1395275593Smarkj
1396274347Smelifaro	nd6_dad_del(dp);
1397275593Smarkj	nd6_dad_rele(dp);
139878064Sume}
139978064Sume
140053541Sshinstatic void
1401191816Szecnd6_dad_timer(struct dadq *dp)
140253541Sshin{
1403183550Szec	CURVNET_SET(dp->dad_vnet);
1404191816Szec	struct ifaddr *ifa = dp->dad_ifa;
1405266248Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
140653541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1407165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
140853541Sshin
140953541Sshin	/* Sanity check */
141053541Sshin	if (ia == NULL) {
141162587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1412275593Smarkj		goto err;
141353541Sshin	}
1414266248Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
1415266248Shrs		/* Do not need DAD for ifdisabled interface. */
1416266248Shrs		log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of "
1417266248Shrs		    "ND6_IFF_IFDISABLED.\n", ifp->if_xname);
1418275593Smarkj		goto err;
1419266248Shrs	}
142053541Sshin	if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
142162587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
142253541Sshin			"%s(%s)\n",
1423165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
142453541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1425275593Smarkj		goto err;
142653541Sshin	}
142753541Sshin	if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
142862587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
142953541Sshin			"%s(%s)\n",
1430165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
143153541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1432275593Smarkj		goto err;
143353541Sshin	}
143453541Sshin
143562587Sitojun	/* timeouted with IFF_{RUNNING,UP} check */
1436181803Sbz	if (dp->dad_ns_tcount > V_dad_maxtry) {
143778064Sume		nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
1438120941Sume		    if_name(ifa->ifa_ifp)));
1439275593Smarkj		goto err;
144062587Sitojun	}
144162587Sitojun
144253541Sshin	/* Need more checks? */
144353541Sshin	if (dp->dad_ns_ocount < dp->dad_count) {
144453541Sshin		/*
144553541Sshin		 * We have more NS to go.  Send NS packet for DAD.
144653541Sshin		 */
144762587Sitojun		nd6_dad_ns_output(dp, ifa);
1448120941Sume		nd6_dad_starttimer(dp,
1449151539Ssuz		    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
1450275593Smarkj		goto done;
145153541Sshin	} else {
145253541Sshin		/*
145353541Sshin		 * We have transmitted sufficient number of DAD packets.
145453541Sshin		 * See what we've got.
145553541Sshin		 */
1456275593Smarkj		if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0)
1457275593Smarkj			/* We've seen NS or NA, means DAD has failed. */
1458274347Smelifaro			nd6_dad_duplicated(ifa, dp);
1459275593Smarkj		else {
146053541Sshin			/*
146153541Sshin			 * We are done with DAD.  No NA came, no NS came.
1462266248Shrs			 * No duplicate address found.  Check IFDISABLED flag
1463266248Shrs			 * again in case that it is changed between the
1464266248Shrs			 * beginning of this function and here.
146553541Sshin			 */
1466266248Shrs			if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0)
1467266248Shrs				ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
146853541Sshin
146978064Sume			nd6log((LOG_DEBUG,
147062587Sitojun			    "%s: DAD complete for %s - no duplicates found\n",
147162587Sitojun			    if_name(ifa->ifa_ifp),
1472165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
147353541Sshin		}
147453541Sshin	}
1475275593Smarkjerr:
1476275593Smarkj	nd6_dad_del(dp);
147753541Sshindone:
1478183550Szec	CURVNET_RESTORE();
147953541Sshin}
148053541Sshin
1481275593Smarkjstatic void
1482274347Smelifarond6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
148353541Sshin{
148453541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1485151477Ssuz	struct ifnet *ifp;
1486165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
148753541Sshin
148878064Sume	log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
1489279531Shrs	    "NS in/out/loopback=%d/%d/%d, NA in=%d\n",
1490165118Sbz	    if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
1491279531Shrs	    dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount,
1492279531Shrs	    dp->dad_na_icount);
149353541Sshin
149453541Sshin	ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
149553541Sshin	ia->ia6_flags |= IN6_IFF_DUPLICATED;
149653541Sshin
1497151477Ssuz	ifp = ifa->ifa_ifp;
149862587Sitojun	log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
1499165118Sbz	    if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr));
150062587Sitojun	log(LOG_ERR, "%s: manual intervention required\n",
1501151477Ssuz	    if_name(ifp));
150253541Sshin
1503151477Ssuz	/*
1504151477Ssuz	 * If the address is a link-local address formed from an interface
1505151477Ssuz	 * identifier based on the hardware address which is supposed to be
1506151477Ssuz	 * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
1507151477Ssuz	 * operation on the interface SHOULD be disabled.
1508197138Shrs	 * [RFC 4862, Section 5.4.5]
1509151477Ssuz	 */
1510151477Ssuz	if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
1511151477Ssuz		struct in6_addr in6;
1512151477Ssuz
1513151477Ssuz		/*
1514151477Ssuz		 * To avoid over-reaction, we only apply this logic when we are
1515151477Ssuz		 * very sure that hardware addresses are supposed to be unique.
1516151477Ssuz		 */
1517151477Ssuz		switch (ifp->if_type) {
1518151477Ssuz		case IFT_ETHER:
1519151477Ssuz		case IFT_FDDI:
1520151477Ssuz		case IFT_ATM:
1521151477Ssuz		case IFT_IEEE1394:
1522151477Ssuz#ifdef IFT_IEEE80211
1523151477Ssuz		case IFT_IEEE80211:
1524151477Ssuz#endif
1525219819Sjeff		case IFT_INFINIBAND:
1526151477Ssuz			in6 = ia->ia_addr.sin6_addr;
1527151477Ssuz			if (in6_get_hw_ifid(ifp, &in6) == 0 &&
1528151477Ssuz			    IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
1529151477Ssuz				ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1530151477Ssuz				log(LOG_ERR, "%s: possible hardware address "
1531151477Ssuz				    "duplication detected, disable IPv6\n",
1532151477Ssuz				    if_name(ifp));
1533151477Ssuz			}
1534151477Ssuz			break;
1535151477Ssuz		}
1536151477Ssuz	}
153753541Sshin}
153853541Sshin
153962587Sitojunstatic void
1540171259Sdelphijnd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa)
154162587Sitojun{
154262587Sitojun	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
154362587Sitojun	struct ifnet *ifp = ifa->ifa_ifp;
1544279531Shrs	int i;
154562587Sitojun
154662587Sitojun	dp->dad_ns_tcount++;
154762587Sitojun	if ((ifp->if_flags & IFF_UP) == 0) {
154862587Sitojun		return;
154962587Sitojun	}
1550148887Srwatson	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
155162587Sitojun		return;
155262587Sitojun	}
155362587Sitojun
155462587Sitojun	dp->dad_ns_ocount++;
1555279531Shrs	if (V_dad_enhanced != 0) {
1556279531Shrs		for (i = 0; i < ND_OPT_NONCE_LEN32; i++)
1557279531Shrs			dp->dad_nonce[i] = arc4random();
1558279531Shrs		/*
1559279531Shrs		 * XXXHRS: Note that in the case that
1560279531Shrs		 * DupAddrDetectTransmits > 1, multiple NS messages with
1561279531Shrs		 * different nonces can be looped back in an unexpected
1562279531Shrs		 * order.  The current implementation recognizes only
1563279531Shrs		 * the latest nonce on the sender side.  Practically it
1564279531Shrs		 * should work well in almost all cases.
1565279531Shrs		 */
1566279559Shrs	}
1567279559Shrs	nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL,
1568279559Shrs	    (uint8_t *)&dp->dad_nonce[0]);
156962587Sitojun}
157062587Sitojun
157162587Sitojunstatic void
1572279531Shrsnd6_dad_ns_input(struct ifaddr *ifa, struct nd_opt_nonce *ndopt_nonce)
157353541Sshin{
157453541Sshin	struct in6_ifaddr *ia;
157553541Sshin	struct ifnet *ifp;
157678064Sume	const struct in6_addr *taddr6;
157753541Sshin	struct dadq *dp;
157853541Sshin
1579151465Ssuz	if (ifa == NULL)
158053541Sshin		panic("ifa == NULL in nd6_dad_ns_input");
158153541Sshin
158253541Sshin	ia = (struct in6_ifaddr *)ifa;
158353541Sshin	ifp = ifa->ifa_ifp;
158453541Sshin	taddr6 = &ia->ia_addr.sin6_addr;
1585279531Shrs	/* Ignore Nonce option when Enhanced DAD is disabled. */
1586279531Shrs	if (V_dad_enhanced == 0)
1587279531Shrs		ndopt_nonce = NULL;
1588279531Shrs	dp = nd6_dad_find(ifa, ndopt_nonce);
1589275593Smarkj	if (dp == NULL)
1590275593Smarkj		return;
159153541Sshin
1592275593Smarkj	dp->dad_ns_icount++;
1593275593Smarkj	nd6_dad_rele(dp);
159453541Sshin}
159553541Sshin
159662587Sitojunstatic void
1597171259Sdelphijnd6_dad_na_input(struct ifaddr *ifa)
159853541Sshin{
159953541Sshin	struct dadq *dp;
160053541Sshin
1601151465Ssuz	if (ifa == NULL)
160253541Sshin		panic("ifa == NULL in nd6_dad_na_input");
160353541Sshin
1604279531Shrs	dp = nd6_dad_find(ifa, NULL);
1605275593Smarkj	if (dp != NULL) {
160653541Sshin		dp->dad_na_icount++;
1607275593Smarkj		nd6_dad_rele(dp);
1608275593Smarkj	}
160953541Sshin}
1610