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$");
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>
43282622Shiren#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>
52282622Shiren#include <sys/sysctl.h>
5353541Sshin#include <sys/syslog.h>
5453541Sshin#include <sys/queue.h>
5578064Sume#include <sys/callout.h>
56282622Shiren#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
66282622Shiren#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;
85282622Shirenstatic struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *);
86282622Shirenstatic void nd6_dad_add(struct dadq *dp);
87282622Shirenstatic void nd6_dad_del(struct dadq *dp);
88282622Shirenstatic void nd6_dad_rele(struct dadq *);
89290348Shrsstatic void nd6_dad_starttimer(struct dadq *, int, int);
90175162Sobrienstatic void nd6_dad_stoptimer(struct dadq *);
91191816Szecstatic void nd6_dad_timer(struct dadq *);
92282622Shirenstatic void nd6_dad_duplicated(struct ifaddr *, struct dadq *);
93290348Shrsstatic void nd6_dad_ns_output(struct dadq *);
94282622Shirenstatic 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);
98282622Shirenstatic void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *,
99282622Shiren    const struct in6_addr *, struct llentry *, uint8_t *, u_int);
10053541Sshin
101282622Shirenstatic VNET_DEFINE(int, dad_enhanced) = 1;
102282622Shiren#define	V_dad_enhanced			VNET(dad_enhanced)
103282622Shiren
104282622ShirenSYSCTL_DECL(_net_inet6_ip6);
105282622ShirenSYSCTL_INT(_net_inet6_ip6, OID_AUTO, dad_enhanced, CTLFLAG_VNET | CTLFLAG_RW,
106282622Shiren    &VNET_NAME(dad_enhanced), 0,
107282622Shiren    "Enable Enhanced DAD, which adds a random nonce to NS messages for DAD.");
108282622Shiren
109272847Shrsstatic VNET_DEFINE(int, dad_maxtry) = 15;	/* max # of *tries* to
110272847Shrs						   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) {
252270923Sae		struct route_in6 ro;
253121765Ssam		int need_proxy;
25453541Sshin
255270923Sae		bzero(&ro, sizeof(ro));
256270923Sae		ro.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
257270923Sae		ro.ro_dst.sin6_family = AF_INET6;
258270923Sae		ro.ro_dst.sin6_addr = taddr6;
25953541Sshin
260231852Sbz		/* Always use the default FIB. */
261178167Sqingli#ifdef RADIX_MPATH
262231852Sbz		rtalloc_mpath_fib((struct route *)&ro, RTF_ANNOUNCE,
263231852Sbz		    RT_DEFAULT_FIB);
264178167Sqingli#else
265270923Sae		in6_rtalloc(&ro, RT_DEFAULT_FIB);
266178167Sqingli#endif
267270923Sae		need_proxy = (ro.ro_rt &&
268270923Sae		    (ro.ro_rt->rt_flags & RTF_ANNOUNCE) != 0 &&
269270923Sae		    ro.ro_rt->rt_gateway->sa_family == AF_LINK);
270270923Sae		if (ro.ro_rt != NULL) {
271219562Sbz			if (need_proxy)
272270923Sae				proxydl = *SDL(ro.ro_rt->rt_gateway);
273270923Sae			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))
334282622Shiren			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 *
395282622Shiren *    ln - for source address determination
396282622Shiren * nonce - If non-NULL, NS is used for duplicate address detection and
397282622Shiren *         the value (length is ND_OPT_NONCE_LEN) is used as a random nonce.
39853541Sshin */
399282622Shirenstatic void
400282622Shirennd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6,
401282622Shiren    const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce,
402282622Shiren    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;
420281866Sae	KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
421281866Sae	    "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
422281866Sae	    __func__, max_linkhdr, maxlen, MCLBYTES));
42353541Sshin
424282622Shiren
425248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
426248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
427248328Sglebius	else
428248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
42962587Sitojun	if (m == NULL)
43062587Sitojun		return;
431282622Shiren	M_SETFIB(m, fibnum);
43262587Sitojun
433215559Sbz	bzero(&ro, sizeof(ro));
434215559Sbz
43553541Sshin	if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
43653541Sshin		m->m_flags |= M_MCAST;
43753541Sshin		im6o.im6o_multicast_ifp = ifp;
43853541Sshin		im6o.im6o_multicast_hlim = 255;
43953541Sshin		im6o.im6o_multicast_loop = 0;
44053541Sshin	}
44153541Sshin
44253541Sshin	icmp6len = sizeof(*nd_ns);
44353541Sshin	m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
44495023Ssuz	m->m_data += max_linkhdr;	/* or MH_ALIGN() equivalent? */
44553541Sshin
44653541Sshin	/* fill neighbor solicitation packet */
44753541Sshin	ip6 = mtod(m, struct ip6_hdr *);
44853541Sshin	ip6->ip6_flow = 0;
44962587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
45062587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
45153541Sshin	/* ip6->ip6_plen will be set later */
45253541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
45353541Sshin	ip6->ip6_hlim = 255;
45453541Sshin	if (daddr6)
45553541Sshin		ip6->ip6_dst = *daddr6;
45653541Sshin	else {
45753541Sshin		ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
458148385Sume		ip6->ip6_dst.s6_addr16[1] = 0;
45953541Sshin		ip6->ip6_dst.s6_addr32[1] = 0;
46053541Sshin		ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
46153541Sshin		ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
46253541Sshin		ip6->ip6_dst.s6_addr8[12] = 0xff;
463148385Sume		if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
464148385Sume			goto bad;
46553541Sshin	}
466282622Shiren	if (nonce == NULL) {
467194760Srwatson		struct ifaddr *ifa;
468194760Srwatson
46953541Sshin		/*
47053541Sshin		 * RFC2461 7.2.2:
47153541Sshin		 * "If the source address of the packet prompting the
47253541Sshin		 * solicitation is the same as one of the addresses assigned
47353541Sshin		 * to the outgoing interface, that address SHOULD be placed
47453541Sshin		 * in the IP Source Address of the outgoing solicitation.
47553541Sshin		 * Otherwise, any one of the addresses assigned to the
47653541Sshin		 * interface should be used."
47753541Sshin		 *
47853541Sshin		 * We use the source address for the prompting packet
47953541Sshin		 * (saddr6), if:
48053541Sshin		 * - saddr6 is given from the caller (by giving "ln"), and
48153541Sshin		 * - saddr6 belongs to the outgoing interface.
482148385Sume		 * Otherwise, we perform the source address selection as usual.
48353541Sshin		 */
484216022Sbz		struct in6_addr *hsrc;
48553541Sshin
486216022Sbz		hsrc = NULL;
487216022Sbz		if (ln != NULL) {
488216022Sbz			LLE_RLOCK(ln);
489216022Sbz			if (ln->la_hold != NULL) {
490216022Sbz				struct ip6_hdr *hip6;		/* hold ip6 */
491216022Sbz
492216022Sbz				/*
493216022Sbz				 * assuming every packet in la_hold has the same IP
494216022Sbz				 * header
495216022Sbz				 */
496216022Sbz				hip6 = mtod(ln->la_hold, struct ip6_hdr *);
497216022Sbz				/* XXX pullup? */
498216022Sbz				if (sizeof(*hip6) < ln->la_hold->m_len) {
499216022Sbz					ip6->ip6_src = hip6->ip6_src;
500216022Sbz					hsrc = &hip6->ip6_src;
501216022Sbz				}
502216022Sbz			}
503216022Sbz			LLE_RUNLOCK(ln);
504148385Sume		}
505194760Srwatson		if (hsrc && (ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp,
506194760Srwatson		    hsrc)) != NULL) {
507216022Sbz			/* ip6_src set already. */
508194760Srwatson			ifa_free(ifa);
509194760Srwatson		} else {
510148385Sume			int error;
511148385Sume			struct sockaddr_in6 dst_sa;
512216022Sbz			struct in6_addr src_in;
513231852Sbz			struct ifnet *oifp;
514148385Sume
515148385Sume			bzero(&dst_sa, sizeof(dst_sa));
516148385Sume			dst_sa.sin6_family = AF_INET6;
517148385Sume			dst_sa.sin6_len = sizeof(dst_sa);
518148385Sume			dst_sa.sin6_addr = ip6->ip6_dst;
519148385Sume
520231852Sbz			oifp = ifp;
521194777Sbz			error = in6_selectsrc(&dst_sa, NULL,
522231852Sbz			    NULL, &ro, NULL, &oifp, &src_in);
523194777Sbz			if (error) {
524165118Sbz				char ip6buf[INET6_ADDRSTRLEN];
525282622Shiren				nd6log((LOG_DEBUG, "%s: source can't be "
526282622Shiren				    "determined: dst=%s, error=%d\n", __func__,
527165118Sbz				    ip6_sprintf(ip6buf, &dst_sa.sin6_addr),
528165118Sbz				    error));
529148385Sume				goto bad;
53053541Sshin			}
531216022Sbz			ip6->ip6_src = src_in;
53253541Sshin		}
53353541Sshin	} else {
53453541Sshin		/*
53553541Sshin		 * Source address for DAD packet must always be IPv6
53653541Sshin		 * unspecified address. (0::0)
537148385Sume		 * We actually don't have to 0-clear the address (we did it
538148385Sume		 * above), but we do so here explicitly to make the intention
539148385Sume		 * clearer.
54053541Sshin		 */
541216022Sbz		bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
54253541Sshin	}
54353541Sshin	nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
54453541Sshin	nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
54553541Sshin	nd_ns->nd_ns_code = 0;
54653541Sshin	nd_ns->nd_ns_reserved = 0;
54753541Sshin	nd_ns->nd_ns_target = *taddr6;
548121315Sume	in6_clearscope(&nd_ns->nd_ns_target); /* XXX */
54953541Sshin
55053541Sshin	/*
55153541Sshin	 * Add source link-layer address option.
55253541Sshin	 *
55353541Sshin	 *				spec		implementation
55453541Sshin	 *				---		---
55553541Sshin	 * DAD packet			MUST NOT	do not add the option
55653541Sshin	 * there's no link layer address:
55753541Sshin	 *				impossible	do not add the option
55853541Sshin	 * there's link layer address:
55953541Sshin	 *	Multicast NS		MUST add one	add the option
56053541Sshin	 *	Unicast NS		SHOULD add one	add the option
56153541Sshin	 */
562282622Shiren	if (nonce == NULL && (mac = nd6_ifptomac(ifp))) {
56353541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
56453541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
56553541Sshin		/* 8 byte alignments... */
56653541Sshin		optlen = (optlen + 7) & ~7;
567120941Sume
56853541Sshin		m->m_pkthdr.len += optlen;
56953541Sshin		m->m_len += optlen;
57053541Sshin		icmp6len += optlen;
57153541Sshin		bzero((caddr_t)nd_opt, optlen);
57253541Sshin		nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
57353541Sshin		nd_opt->nd_opt_len = optlen >> 3;
57453541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
57553541Sshin	}
576282622Shiren	/*
577282622Shiren	 * Add a Nonce option (RFC 3971) to detect looped back NS messages.
578282622Shiren	 * This behavior is documented as Enhanced Duplicate Address
579287734Shrs	 * Detection in RFC 7527.
580282622Shiren	 * net.inet6.ip6.dad_enhanced=0 disables this.
581282622Shiren	 */
582282622Shiren	if (V_dad_enhanced != 0 && nonce != NULL) {
583282622Shiren		int optlen = sizeof(struct nd_opt_hdr) + ND_OPT_NONCE_LEN;
584282622Shiren		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
585282622Shiren		/* 8-byte alignment is required. */
586282622Shiren		optlen = (optlen + 7) & ~7;
58753541Sshin
588282622Shiren		m->m_pkthdr.len += optlen;
589282622Shiren		m->m_len += optlen;
590282622Shiren		icmp6len += optlen;
591282622Shiren		bzero((caddr_t)nd_opt, optlen);
592282622Shiren		nd_opt->nd_opt_type = ND_OPT_NONCE;
593282622Shiren		nd_opt->nd_opt_len = optlen >> 3;
594282622Shiren		bcopy(nonce, (caddr_t)(nd_opt + 1), ND_OPT_NONCE_LEN);
595282622Shiren	}
59653541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
59753541Sshin	nd_ns->nd_ns_cksum = 0;
598120941Sume	nd_ns->nd_ns_cksum =
599120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
60053541Sshin
601211501Sanchie	if (send_sendso_input_hook != NULL) {
602211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
603211501Sanchie			sizeof(unsigned short), M_NOWAIT);
604211501Sanchie		if (mtag == NULL)
605211501Sanchie			goto bad;
606211501Sanchie		*(unsigned short *)(mtag + 1) = nd_ns->nd_ns_type;
607211501Sanchie		m_tag_prepend(m, mtag);
608211501Sanchie	}
609211501Sanchie
610282622Shiren	ip6_output(m, NULL, &ro, (nonce != NULL) ? IPV6_UNSPECSRC : 0,
611282622Shiren	    &im6o, NULL, NULL);
612148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
613148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
614190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
615148385Sume
616238092Sglebius	/* We don't cache this route. */
617238092Sglebius	RO_RTFREE(&ro);
618238092Sglebius
619148385Sume	return;
620148385Sume
621148385Sume  bad:
622148385Sume	if (ro.ro_rt) {
623148385Sume		RTFREE(ro.ro_rt);
624148385Sume	}
625148385Sume	m_freem(m);
62653541Sshin}
62753541Sshin
628282622Shiren#ifndef BURN_BRIDGES
629282622Shirenvoid
630282622Shirennd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
631282622Shiren    const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce)
632282622Shiren{
633282622Shiren
634282622Shiren	nd6_ns_output_fib(ifp, daddr6, taddr6, ln, nonce, RT_DEFAULT_FIB);
635282622Shiren}
636282622Shiren#endif
63753541Sshin/*
63853541Sshin * Neighbor advertisement input handling.
63953541Sshin *
64053541Sshin * Based on RFC 2461
641148987Sume * Based on RFC 2462 (duplicate address detection)
64262587Sitojun *
64362587Sitojun * the following items are not implemented yet:
64462587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
64562587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
64653541Sshin */
64753541Sshinvoid
648171259Sdelphijnd6_na_input(struct mbuf *m, int off, int icmp6len)
64953541Sshin{
65053541Sshin	struct ifnet *ifp = m->m_pkthdr.rcvif;
65153541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
65262587Sitojun	struct nd_neighbor_advert *nd_na;
65353541Sshin	struct in6_addr daddr6 = ip6->ip6_dst;
65462587Sitojun	struct in6_addr taddr6;
65562587Sitojun	int flags;
65662587Sitojun	int is_router;
65762587Sitojun	int is_solicited;
65862587Sitojun	int is_override;
65953541Sshin	char *lladdr = NULL;
66053541Sshin	int lladdrlen = 0;
661186468Skmacy	int checklink = 0;
66253541Sshin	struct ifaddr *ifa;
663186119Sqingli	struct llentry *ln = NULL;
66453541Sshin	union nd_opts ndopts;
665186119Sqingli	struct mbuf *chain = NULL;
666186119Sqingli	struct sockaddr_in6 sin6;
667165118Sbz	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
66853541Sshin
66953541Sshin	if (ip6->ip6_hlim != 255) {
67078064Sume		nd6log((LOG_ERR,
67178064Sume		    "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
672165118Sbz		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
673165118Sbz		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
67478064Sume		goto bad;
67562587Sitojun	}
67662587Sitojun
67762587Sitojun#ifndef PULLDOWN_TEST
67862587Sitojun	IP6_EXTHDR_CHECK(m, off, icmp6len,);
67962587Sitojun	nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
68062587Sitojun#else
68162587Sitojun	IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
68262587Sitojun	if (nd_na == NULL) {
683190964Srwatson		ICMP6STAT_INC(icp6s_tooshort);
68453541Sshin		return;
68553541Sshin	}
68662587Sitojun#endif
687148385Sume
68862587Sitojun	flags = nd_na->nd_na_flags_reserved;
68962587Sitojun	is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
69062587Sitojun	is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
69162587Sitojun	is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
692282622Shiren	memset(&sin6, 0, sizeof(sin6));
69353541Sshin
694148385Sume	taddr6 = nd_na->nd_na_target;
695148385Sume	if (in6_setscope(&taddr6, ifp, NULL))
696150202Ssuz		goto bad;	/* XXX: impossible */
69753541Sshin
69853541Sshin	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
69978064Sume		nd6log((LOG_ERR,
70053541Sshin		    "nd6_na_input: invalid target address %s\n",
701165118Sbz		    ip6_sprintf(ip6bufs, &taddr6)));
70278064Sume		goto bad;
70353541Sshin	}
70453541Sshin	if (IN6_IS_ADDR_MULTICAST(&daddr6))
70553541Sshin		if (is_solicited) {
70678064Sume			nd6log((LOG_ERR,
70778064Sume			    "nd6_na_input: a solicited adv is multicasted\n"));
70878064Sume			goto bad;
70953541Sshin		}
71053541Sshin
71153541Sshin	icmp6len -= sizeof(*nd_na);
71253541Sshin	nd6_option_init(nd_na + 1, icmp6len, &ndopts);
71353541Sshin	if (nd6_options(&ndopts) < 0) {
71478064Sume		nd6log((LOG_INFO,
71578064Sume		    "nd6_na_input: invalid ND option, ignored\n"));
71678064Sume		/* nd6_options have incremented stats */
71762587Sitojun		goto freeit;
71853541Sshin	}
71953541Sshin
72053541Sshin	if (ndopts.nd_opts_tgt_lladdr) {
72153541Sshin		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
72253541Sshin		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
72353541Sshin	}
72453541Sshin
725228571Sglebius	/*
726228571Sglebius	 * This effectively disables the DAD check on a non-master CARP
727228571Sglebius	 * address.
728228571Sglebius	 */
729228571Sglebius	if (ifp->if_carp)
730228571Sglebius		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
731228571Sglebius	else
732228571Sglebius		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
73353541Sshin
73453541Sshin	/*
73553541Sshin	 * Target address matches one of my interface address.
73653541Sshin	 *
73753541Sshin	 * If my address is tentative, this means that there's somebody
73853541Sshin	 * already using the same address as mine.  This indicates DAD failure.
73953541Sshin	 * This is defined in RFC 2462.
74053541Sshin	 *
74153541Sshin	 * Otherwise, process as defined in RFC 2461.
74253541Sshin	 */
74353541Sshin	if (ifa
74453541Sshin	 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
745280705Sae		nd6_dad_na_input(ifa);
746194760Srwatson		ifa_free(ifa);
74762587Sitojun		goto freeit;
74853541Sshin	}
74953541Sshin
75095023Ssuz	/* Just for safety, maybe unnecessary. */
75153541Sshin	if (ifa) {
752194760Srwatson		ifa_free(ifa);
75353541Sshin		log(LOG_ERR,
75453541Sshin		    "nd6_na_input: duplicate IP6 address %s\n",
755165118Sbz		    ip6_sprintf(ip6bufs, &taddr6));
75662587Sitojun		goto freeit;
75753541Sshin	}
75853541Sshin
75953541Sshin	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
760120941Sume		nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
761165118Sbz		    "(if %d, NA packet %d)\n", ip6_sprintf(ip6bufs, &taddr6),
762120941Sume		    ifp->if_addrlen, lladdrlen - 2));
76378064Sume		goto bad;
76453541Sshin	}
76553541Sshin
76653541Sshin	/*
767120941Sume	 * If no neighbor cache entry is found, NA SHOULD silently be
768120941Sume	 * discarded.
76953541Sshin	 */
770260504Sae	IF_AFDATA_RLOCK(ifp);
771186119Sqingli	ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
772260504Sae	IF_AFDATA_RUNLOCK(ifp);
773186119Sqingli	if (ln == NULL) {
77462587Sitojun		goto freeit;
775186119Sqingli	}
77653541Sshin
77753541Sshin	if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
77853541Sshin		/*
77953541Sshin		 * If the link-layer has address, and no lladdr option came,
78053541Sshin		 * discard the packet.
78153541Sshin		 */
782186119Sqingli		if (ifp->if_addrlen && lladdr == NULL) {
78362587Sitojun			goto freeit;
784186119Sqingli		}
78553541Sshin
78653541Sshin		/*
78753541Sshin		 * Record link-layer address, and update the state.
78853541Sshin		 */
789186119Sqingli		bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
790186119Sqingli		ln->la_flags |= LLE_VALID;
791245925Snp		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
79253541Sshin		if (is_solicited) {
79353541Sshin			ln->ln_state = ND6_LLINFO_REACHABLE;
79462587Sitojun			ln->ln_byhint = 0;
795151539Ssuz			if (!ND6_LLINFO_PERMANENT(ln)) {
796186119Sqingli				nd6_llinfo_settimer_locked(ln,
797186119Sqingli				    (long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
798120941Sume			}
79978064Sume		} else {
80053541Sshin			ln->ln_state = ND6_LLINFO_STALE;
801186119Sqingli			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
80278064Sume		}
80378064Sume		if ((ln->ln_router = is_router) != 0) {
80478064Sume			/*
80578064Sume			 * This means a router's state has changed from
80678064Sume			 * non-reachable to probably reachable, and might
80778064Sume			 * affect the status of associated prefixes..
80878064Sume			 */
809186468Skmacy			checklink = 1;
81078064Sume		}
81153541Sshin	} else {
81253541Sshin		int llchange;
81353541Sshin
81453541Sshin		/*
81553541Sshin		 * Check if the link-layer address has changed or not.
81653541Sshin		 */
817151465Ssuz		if (lladdr == NULL)
81853541Sshin			llchange = 0;
81953541Sshin		else {
820186119Sqingli			if (ln->la_flags & LLE_VALID) {
821186119Sqingli				if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
82253541Sshin					llchange = 1;
82353541Sshin				else
82453541Sshin					llchange = 0;
82553541Sshin			} else
82653541Sshin				llchange = 1;
82753541Sshin		}
82853541Sshin
82953541Sshin		/*
83053541Sshin		 * This is VERY complex.  Look at it with care.
83153541Sshin		 *
83253541Sshin		 * override solicit lladdr llchange	action
83353541Sshin		 *					(L: record lladdr)
83453541Sshin		 *
83553541Sshin		 *	0	0	n	--	(2c)
83653541Sshin		 *	0	0	y	n	(2b) L
83753541Sshin		 *	0	0	y	y	(1)    REACHABLE->STALE
83853541Sshin		 *	0	1	n	--	(2c)   *->REACHABLE
83953541Sshin		 *	0	1	y	n	(2b) L *->REACHABLE
84053541Sshin		 *	0	1	y	y	(1)    REACHABLE->STALE
84153541Sshin		 *	1	0	n	--	(2a)
84253541Sshin		 *	1	0	y	n	(2a) L
84353541Sshin		 *	1	0	y	y	(2a) L *->STALE
84453541Sshin		 *	1	1	n	--	(2a)   *->REACHABLE
84553541Sshin		 *	1	1	y	n	(2a) L *->REACHABLE
84653541Sshin		 *	1	1	y	y	(2a) L *->REACHABLE
84753541Sshin		 */
848151539Ssuz		if (!is_override && (lladdr != NULL && llchange)) {  /* (1) */
84953541Sshin			/*
85053541Sshin			 * If state is REACHABLE, make it STALE.
85153541Sshin			 * no other updates should be done.
85253541Sshin			 */
85378064Sume			if (ln->ln_state == ND6_LLINFO_REACHABLE) {
85453541Sshin				ln->ln_state = ND6_LLINFO_STALE;
855186119Sqingli				nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
85678064Sume			}
85762587Sitojun			goto freeit;
85853541Sshin		} else if (is_override				   /* (2a) */
859151465Ssuz			|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */
860151465Ssuz			|| lladdr == NULL) {			   /* (2c) */
86153541Sshin			/*
86253541Sshin			 * Update link-local address, if any.
86353541Sshin			 */
864151465Ssuz			if (lladdr != NULL) {
865186119Sqingli				bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
866186119Sqingli				ln->la_flags |= LLE_VALID;
867245925Snp				EVENTHANDLER_INVOKE(lle_event, ln,
868245925Snp				    LLENTRY_RESOLVED);
86953541Sshin			}
87053541Sshin
87153541Sshin			/*
87253541Sshin			 * If solicited, make the state REACHABLE.
87353541Sshin			 * If not solicited and the link-layer address was
87453541Sshin			 * changed, make it STALE.
87553541Sshin			 */
87653541Sshin			if (is_solicited) {
87753541Sshin				ln->ln_state = ND6_LLINFO_REACHABLE;
87862587Sitojun				ln->ln_byhint = 0;
879151539Ssuz				if (!ND6_LLINFO_PERMANENT(ln)) {
880186119Sqingli					nd6_llinfo_settimer_locked(ln,
881151539Ssuz					    (long)ND_IFINFO(ifp)->reachable * hz);
88253541Sshin				}
88353541Sshin			} else {
884151465Ssuz				if (lladdr != NULL && llchange) {
88553541Sshin					ln->ln_state = ND6_LLINFO_STALE;
886186119Sqingli					nd6_llinfo_settimer_locked(ln,
887181803Sbz					    (long)V_nd6_gctimer * hz);
88878064Sume				}
88953541Sshin			}
89053541Sshin		}
89153541Sshin
89253541Sshin		if (ln->ln_router && !is_router) {
89353541Sshin			/*
89453541Sshin			 * The peer dropped the router flag.
89553541Sshin			 * Remove the sender from the Default Router List and
89653541Sshin			 * update the Destination Cache entries.
89753541Sshin			 */
898303458Ssbruno			if (!defrouter_remove(&L3_ADDR_SIN6(ln)->sin6_addr,
899303458Ssbruno			    ln->lle_tbl->llt_ifp) &&
900303458Ssbruno			    (ND_IFINFO(ln->lle_tbl->llt_ifp)->flags &
901303458Ssbruno			     ND6_IFF_ACCEPT_RTADV) != 0)
90253541Sshin				/*
90353541Sshin				 * Even if the neighbor is not in the default
904303458Ssbruno				 * router list, the neighbor may be used as a
905303458Ssbruno				 * next hop for some destinations (e.g. redirect
906303458Ssbruno				 * case). So we must call rt6_flush explicitly.
90753541Sshin				 */
908128422Sluigi				rt6_flush(&ip6->ip6_src, ifp);
90953541Sshin		}
91053541Sshin		ln->ln_router = is_router;
91153541Sshin	}
912186119Sqingli        /* XXX - QL
913186119Sqingli	 *  Does this matter?
914186119Sqingli	 *  rt->rt_flags &= ~RTF_REJECT;
915186119Sqingli	 */
916186119Sqingli	ln->la_asked = 0;
917282622Shiren	if (ln->la_hold != NULL)
918282622Shiren		nd6_grab_holdchain(ln, &chain, &sin6);
919186119Sqingli freeit:
920282622Shiren	if (ln != NULL)
921186119Sqingli		LLE_WUNLOCK(ln);
92262587Sitojun
923282622Shiren	if (chain != NULL)
924282622Shiren		nd6_flush_holdchain(ifp, ifp, chain, &sin6);
925282622Shiren
926186468Skmacy	if (checklink)
927186468Skmacy		pfxlist_onlink_check();
928186468Skmacy
92962587Sitojun	m_freem(m);
93078064Sume	return;
93178064Sume
93278064Sume bad:
933186160Skmacy	if (ln != NULL)
934186119Sqingli		LLE_WUNLOCK(ln);
935186119Sqingli
936190964Srwatson	ICMP6STAT_INC(icp6s_badna);
93778064Sume	m_freem(m);
93853541Sshin}
93953541Sshin
94053541Sshin/*
94153541Sshin * Neighbor advertisement output handling.
94253541Sshin *
94353541Sshin * Based on RFC 2461
94453541Sshin *
94562587Sitojun * the following items are not implemented yet:
94662587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
94762587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
948171259Sdelphij *
949171259Sdelphij * tlladdr - 1 if include target link-layer address
950171259Sdelphij * sdl0 - sockaddr_dl (= proxy NA) or NULL
95153541Sshin */
952231852Sbzstatic void
953231852Sbznd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
954171259Sdelphij    const struct in6_addr *taddr6, u_long flags, int tlladdr,
955231852Sbz    struct sockaddr *sdl0, u_int fibnum)
95653541Sshin{
95753541Sshin	struct mbuf *m;
958211501Sanchie	struct m_tag *mtag;
959231852Sbz	struct ifnet *oifp;
96053541Sshin	struct ip6_hdr *ip6;
96153541Sshin	struct nd_neighbor_advert *nd_na;
96253541Sshin	struct ip6_moptions im6o;
963194777Sbz	struct in6_addr src, daddr6;
964148385Sume	struct sockaddr_in6 dst_sa;
965148385Sume	int icmp6len, maxlen, error;
96692733Speter	caddr_t mac = NULL;
967148385Sume	struct route_in6 ro;
96862587Sitojun
969148385Sume	bzero(&ro, sizeof(ro));
970148385Sume
971148385Sume	daddr6 = *daddr6_0;	/* make a local copy for modification */
972148385Sume
97362587Sitojun	/* estimate the size of message */
97462587Sitojun	maxlen = sizeof(*ip6) + sizeof(*nd_na);
97562587Sitojun	maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
976281866Sae	KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
977281866Sae	    "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
978281866Sae	    __func__, max_linkhdr, maxlen, MCLBYTES));
97953541Sshin
980248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
981248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
982248328Sglebius	else
983248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
98462587Sitojun	if (m == NULL)
98562587Sitojun		return;
986231852Sbz	M_SETFIB(m, fibnum);
98762587Sitojun
988148385Sume	if (IN6_IS_ADDR_MULTICAST(&daddr6)) {
98953541Sshin		m->m_flags |= M_MCAST;
99053541Sshin		im6o.im6o_multicast_ifp = ifp;
99153541Sshin		im6o.im6o_multicast_hlim = 255;
99253541Sshin		im6o.im6o_multicast_loop = 0;
99353541Sshin	}
99453541Sshin
99553541Sshin	icmp6len = sizeof(*nd_na);
99653541Sshin	m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
99795023Ssuz	m->m_data += max_linkhdr;	/* or MH_ALIGN() equivalent? */
99853541Sshin
99953541Sshin	/* fill neighbor advertisement packet */
100053541Sshin	ip6 = mtod(m, struct ip6_hdr *);
100153541Sshin	ip6->ip6_flow = 0;
100262587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
100362587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
100453541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
100553541Sshin	ip6->ip6_hlim = 255;
1006148385Sume	if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
100753541Sshin		/* reply to DAD */
1008153227Sume		daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
1009153227Sume		daddr6.s6_addr16[1] = 0;
1010153227Sume		daddr6.s6_addr32[1] = 0;
1011153227Sume		daddr6.s6_addr32[2] = 0;
1012153227Sume		daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
1013148385Sume		if (in6_setscope(&daddr6, ifp, NULL))
1014148385Sume			goto bad;
1015148385Sume
101653541Sshin		flags &= ~ND_NA_FLAG_SOLICITED;
1017148385Sume	}
1018148385Sume	ip6->ip6_dst = daddr6;
1019148385Sume	bzero(&dst_sa, sizeof(struct sockaddr_in6));
1020148385Sume	dst_sa.sin6_family = AF_INET6;
1021148385Sume	dst_sa.sin6_len = sizeof(struct sockaddr_in6);
1022148385Sume	dst_sa.sin6_addr = daddr6;
102353541Sshin
102453541Sshin	/*
102553541Sshin	 * Select a source whose scope is the same as that of the dest.
102653541Sshin	 */
1027148385Sume	bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
1028231852Sbz	oifp = ifp;
1029231852Sbz	error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src);
1030194777Sbz	if (error) {
1031165118Sbz		char ip6buf[INET6_ADDRSTRLEN];
1032148385Sume		nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
1033148385Sume		    "determined: dst=%s, error=%d\n",
1034165118Sbz		    ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error));
1035148385Sume		goto bad;
103653541Sshin	}
1037194777Sbz	ip6->ip6_src = src;
103853541Sshin	nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
103953541Sshin	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
104053541Sshin	nd_na->nd_na_code = 0;
104153541Sshin	nd_na->nd_na_target = *taddr6;
1042121315Sume	in6_clearscope(&nd_na->nd_na_target); /* XXX */
104353541Sshin
104453541Sshin	/*
104553541Sshin	 * "tlladdr" indicates NS's condition for adding tlladdr or not.
104653541Sshin	 * see nd6_ns_input() for details.
104753541Sshin	 * Basically, if NS packet is sent to unicast/anycast addr,
104853541Sshin	 * target lladdr option SHOULD NOT be included.
104953541Sshin	 */
105062587Sitojun	if (tlladdr) {
105162587Sitojun		/*
105262587Sitojun		 * sdl0 != NULL indicates proxy NA.  If we do proxy, use
105362587Sitojun		 * lladdr in sdl0.  If we are not proxying (sending NA for
105462587Sitojun		 * my address) use lladdr configured for the interface.
105562587Sitojun		 */
1056142215Sglebius		if (sdl0 == NULL) {
1057142215Sglebius			if (ifp->if_carp)
1058211157Swill				mac = (*carp_macmatch6_p)(ifp, m, taddr6);
1059142215Sglebius			if (mac == NULL)
1060142215Sglebius				mac = nd6_ifptomac(ifp);
1061142215Sglebius		} else if (sdl0->sa_family == AF_LINK) {
106262587Sitojun			struct sockaddr_dl *sdl;
106362587Sitojun			sdl = (struct sockaddr_dl *)sdl0;
106462587Sitojun			if (sdl->sdl_alen == ifp->if_addrlen)
106562587Sitojun				mac = LLADDR(sdl);
106662587Sitojun		}
106762587Sitojun	}
106862587Sitojun	if (tlladdr && mac) {
106953541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
107053541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
1071120941Sume
107253541Sshin		/* roundup to 8 bytes alignment! */
107353541Sshin		optlen = (optlen + 7) & ~7;
107453541Sshin
107553541Sshin		m->m_pkthdr.len += optlen;
107653541Sshin		m->m_len += optlen;
107753541Sshin		icmp6len += optlen;
107853541Sshin		bzero((caddr_t)nd_opt, optlen);
107953541Sshin		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
108053541Sshin		nd_opt->nd_opt_len = optlen >> 3;
108153541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
108253541Sshin	} else
108353541Sshin		flags &= ~ND_NA_FLAG_OVERRIDE;
108453541Sshin
108553541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
108653541Sshin	nd_na->nd_na_flags_reserved = flags;
108753541Sshin	nd_na->nd_na_cksum = 0;
108853541Sshin	nd_na->nd_na_cksum =
1089120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
109053541Sshin
1091211501Sanchie	if (send_sendso_input_hook != NULL) {
1092211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
1093211501Sanchie		    sizeof(unsigned short), M_NOWAIT);
1094211501Sanchie		if (mtag == NULL)
1095211501Sanchie			goto bad;
1096211501Sanchie		*(unsigned short *)(mtag + 1) = nd_na->nd_na_type;
1097211501Sanchie		m_tag_prepend(m, mtag);
1098211501Sanchie	}
1099211501Sanchie
1100148385Sume	ip6_output(m, NULL, &ro, 0, &im6o, NULL, NULL);
1101148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
1102148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
1103190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);
1104148385Sume
1105238092Sglebius	/* We don't cache this route. */
1106238092Sglebius	RO_RTFREE(&ro);
1107238092Sglebius
1108148385Sume	return;
1109148385Sume
1110148385Sume  bad:
1111148385Sume	if (ro.ro_rt) {
1112148385Sume		RTFREE(ro.ro_rt);
1113148385Sume	}
1114148385Sume	m_freem(m);
111553541Sshin}
111653541Sshin
1117231852Sbz#ifndef BURN_BRIDGES
1118231852Sbzvoid
1119231852Sbznd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
1120231852Sbz    const struct in6_addr *taddr6, u_long flags, int tlladdr,
1121231852Sbz    struct sockaddr *sdl0)
1122231852Sbz{
1123231852Sbz
1124231852Sbz	nd6_na_output_fib(ifp, daddr6_0, taddr6, flags, tlladdr, sdl0,
1125231852Sbz	    RT_DEFAULT_FIB);
1126231852Sbz}
1127231852Sbz#endif
1128231852Sbz
112953541Sshincaddr_t
1130171259Sdelphijnd6_ifptomac(struct ifnet *ifp)
113153541Sshin{
113253541Sshin	switch (ifp->if_type) {
113353541Sshin	case IFT_ARCNET:
113453541Sshin	case IFT_ETHER:
113553541Sshin	case IFT_FDDI:
113678064Sume	case IFT_IEEE1394:
113778468Ssumikawa#ifdef IFT_L2VLAN
113878468Ssumikawa	case IFT_L2VLAN:
113978468Ssumikawa#endif
114078064Sume#ifdef IFT_IEEE80211
114178064Sume	case IFT_IEEE80211:
114278064Sume#endif
1143219819Sjeff	case IFT_INFINIBAND:
1144149829Sthompsa	case IFT_BRIDGE:
1145120049Smdodd	case IFT_ISO88025:
1146147306Sbrooks		return IF_LLADDR(ifp);
114753541Sshin	default:
114853541Sshin		return NULL;
114953541Sshin	}
115053541Sshin}
115153541Sshin
115253541Sshinstruct dadq {
115360938Sjake	TAILQ_ENTRY(dadq) dad_list;
115453541Sshin	struct ifaddr *dad_ifa;
115553541Sshin	int dad_count;		/* max NS to send */
115662587Sitojun	int dad_ns_tcount;	/* # of trials to send NS */
115753541Sshin	int dad_ns_ocount;	/* NS sent so far */
115853541Sshin	int dad_ns_icount;
115953541Sshin	int dad_na_icount;
1160282622Shiren	int dad_ns_lcount;	/* looped back NS */
1161282622Shiren	int dad_loopbackprobe;	/* probing state for loopback detection */
116278064Sume	struct callout dad_timer_ch;
1163191816Szec	struct vnet *dad_vnet;
1164282622Shiren	u_int dad_refcnt;
1165282622Shiren#define	ND_OPT_NONCE_LEN32 \
1166282622Shiren		((ND_OPT_NONCE_LEN + sizeof(uint32_t) - 1)/sizeof(uint32_t))
1167282622Shiren	uint32_t dad_nonce[ND_OPT_NONCE_LEN32];
116853541Sshin};
116953541Sshin
1170215701Sdimstatic VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
1171272847Shrsstatic VNET_DEFINE(struct rwlock, dad_rwlock);
1172272847Shrs#define	V_dadq			VNET(dadq)
1173272847Shrs#define	V_dad_rwlock		VNET(dad_rwlock)
1174195699Srwatson
1175272847Shrs#define	DADQ_RLOCK()		rw_rlock(&V_dad_rwlock)
1176272847Shrs#define	DADQ_RUNLOCK()		rw_runlock(&V_dad_rwlock)
1177272847Shrs#define	DADQ_WLOCK()		rw_wlock(&V_dad_rwlock)
1178272847Shrs#define	DADQ_WUNLOCK()		rw_wunlock(&V_dad_rwlock)
1179272847Shrs
1180282622Shirenstatic void
1181282622Shirennd6_dad_add(struct dadq *dp)
1182282622Shiren{
1183282622Shiren
1184282622Shiren	DADQ_WLOCK();
1185282622Shiren	TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list);
1186282622Shiren	DADQ_WUNLOCK();
1187282622Shiren}
1188282622Shiren
1189282622Shirenstatic void
1190282622Shirennd6_dad_del(struct dadq *dp)
1191282622Shiren{
1192282622Shiren
1193282622Shiren	DADQ_WLOCK();
1194282622Shiren	TAILQ_REMOVE(&V_dadq, dp, dad_list);
1195282622Shiren	DADQ_WUNLOCK();
1196282622Shiren	nd6_dad_rele(dp);
1197282622Shiren}
1198282622Shiren
119953541Sshinstatic struct dadq *
1200282622Shirennd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n)
120153541Sshin{
120253541Sshin	struct dadq *dp;
120353541Sshin
1204272847Shrs	DADQ_RLOCK();
1205282622Shiren	TAILQ_FOREACH(dp, &V_dadq, dad_list) {
1206282622Shiren		if (dp->dad_ifa != ifa)
1207282622Shiren			continue;
1208282622Shiren		/*
1209282622Shiren		 * Skip if the nonce matches the received one.
1210282622Shiren		 * +2 in the length is required because of type and
1211282622Shiren		 * length fields are included in a header.
1212282622Shiren		 */
1213282622Shiren		if (n != NULL &&
1214282622Shiren		    n->nd_opt_nonce_len == (ND_OPT_NONCE_LEN + 2) / 8 &&
1215282622Shiren		    memcmp(&n->nd_opt_nonce[0], &dp->dad_nonce[0],
1216282622Shiren		        ND_OPT_NONCE_LEN) == 0) {
1217282622Shiren			dp->dad_ns_lcount++;
1218282622Shiren			continue;
1219282622Shiren		}
1220282622Shiren		refcount_acquire(&dp->dad_refcnt);
1221282622Shiren		break;
1222282622Shiren	}
1223272847Shrs	DADQ_RUNLOCK();
1224226340Sglebius
1225272847Shrs	return (dp);
122653541Sshin}
122753541Sshin
122878064Sumestatic void
1229290348Shrsnd6_dad_starttimer(struct dadq *dp, int ticks, int send_ns)
123078064Sume{
123178064Sume
1232290348Shrs	if (send_ns != 0)
1233290348Shrs		nd6_dad_ns_output(dp);
123478064Sume	callout_reset(&dp->dad_timer_ch, ticks,
1235191816Szec	    (void (*)(void *))nd6_dad_timer, (void *)dp);
123678064Sume}
123778064Sume
123878064Sumestatic void
1239171259Sdelphijnd6_dad_stoptimer(struct dadq *dp)
124078064Sume{
124178064Sume
1242282622Shiren	callout_drain(&dp->dad_timer_ch);
124378064Sume}
124478064Sume
1245282622Shirenstatic void
1246282622Shirennd6_dad_rele(struct dadq *dp)
1247282622Shiren{
1248282622Shiren
1249282622Shiren	if (refcount_release(&dp->dad_refcnt)) {
1250282622Shiren		ifa_free(dp->dad_ifa);
1251282622Shiren		free(dp, M_IP6NDP);
1252282622Shiren	}
1253282622Shiren}
1254282622Shiren
1255282622Shirenvoid
1256282622Shirennd6_dad_init(void)
1257282622Shiren{
1258282622Shiren
1259282622Shiren	rw_init(&V_dad_rwlock, "nd6 DAD queue");
1260282622Shiren	TAILQ_INIT(&V_dadq);
1261282622Shiren}
1262282622Shiren
126353541Sshin/*
1264148987Sume * Start Duplicate Address Detection (DAD) for specified interface address.
126553541Sshin */
126653541Sshinvoid
1267171259Sdelphijnd6_dad_start(struct ifaddr *ifa, int delay)
126853541Sshin{
126953541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
127053541Sshin	struct dadq *dp;
1271165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
1272290348Shrs	int send_ns;
127353541Sshin
127453541Sshin	/*
127553541Sshin	 * If we don't need DAD, don't do it.
127653541Sshin	 * There are several cases:
127753541Sshin	 * - DAD is disabled (ip6_dad_count == 0)
127853541Sshin	 * - the interface address is anycast
127953541Sshin	 */
128053541Sshin	if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
128162587Sitojun		log(LOG_DEBUG,
128262587Sitojun			"nd6_dad_start: called with non-tentative address "
128353541Sshin			"%s(%s)\n",
1284165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
128553541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
128653541Sshin		return;
128753541Sshin	}
128853541Sshin	if (ia->ia6_flags & IN6_IFF_ANYCAST) {
128953541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
129053541Sshin		return;
129153541Sshin	}
1292181803Sbz	if (!V_ip6_dad_count) {
129353541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
129453541Sshin		return;
129553541Sshin	}
1296151465Ssuz	if (ifa->ifa_ifp == NULL)
129753541Sshin		panic("nd6_dad_start: ifa->ifa_ifp == NULL");
1298287734Shrs	if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) {
1299287734Shrs		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
130053541Sshin		return;
1301120941Sume	}
1302287734Shrs	if (!(ifa->ifa_ifp->if_flags & IFF_UP) ||
1303287734Shrs	    !(ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) ||
1304287734Shrs	    (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)) {
1305287734Shrs		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1306197138Shrs		return;
1307287734Shrs	}
1308282622Shiren	if ((dp = nd6_dad_find(ifa, NULL)) != NULL) {
1309290348Shrs		/*
1310299145Smarkj		 * DAD is already in progress.  Let the existing entry
1311299145Smarkj		 * finish it.
1312290348Shrs		 */
1313299145Smarkj		nd6_dad_rele(dp);
131453541Sshin		return;
131553541Sshin	}
131653541Sshin
1317282622Shiren	dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
131853541Sshin	if (dp == NULL) {
131962587Sitojun		log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
132053541Sshin			"%s(%s)\n",
1321165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
132253541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
132353541Sshin		return;
132453541Sshin	}
132578064Sume	callout_init(&dp->dad_timer_ch, 0);
1326191816Szec#ifdef VIMAGE
1327191816Szec	dp->dad_vnet = curvnet;
1328191816Szec#endif
132978064Sume	nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1330165118Sbz	    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
133153541Sshin
133253541Sshin	/*
133353541Sshin	 * Send NS packet for DAD, ip6_dad_count times.
133453541Sshin	 * Note that we must delay the first transmission, if this is the
133553541Sshin	 * first packet to be sent from the interface after interface
133653541Sshin	 * (re)initialization.
133753541Sshin	 */
133853541Sshin	dp->dad_ifa = ifa;
1339282622Shiren	ifa_ref(dp->dad_ifa);
1340181803Sbz	dp->dad_count = V_ip6_dad_count;
134153541Sshin	dp->dad_ns_icount = dp->dad_na_icount = 0;
134262587Sitojun	dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1343282622Shiren	dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
1344282622Shiren	refcount_init(&dp->dad_refcnt, 1);
1345282622Shiren	nd6_dad_add(dp);
1346290348Shrs	send_ns = 0;
1347151539Ssuz	if (delay == 0) {
1348290348Shrs		send_ns = 1;
1349290348Shrs		delay = (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000;
135053541Sshin	}
1351290348Shrs	nd6_dad_starttimer(dp, delay, send_ns);
135253541Sshin}
135353541Sshin
135478064Sume/*
135578064Sume * terminate DAD unconditionally.  used for address removals.
135678064Sume */
135778064Sumevoid
1358171259Sdelphijnd6_dad_stop(struct ifaddr *ifa)
135978064Sume{
136078064Sume	struct dadq *dp;
136178064Sume
1362282622Shiren	dp = nd6_dad_find(ifa, NULL);
136378064Sume	if (!dp) {
136478064Sume		/* DAD wasn't started yet */
136578064Sume		return;
136678064Sume	}
136778064Sume
136878064Sume	nd6_dad_stoptimer(dp);
136978064Sume
1370282622Shiren	/*
1371282622Shiren	 * The DAD queue entry may have been removed by nd6_dad_timer() while
1372282622Shiren	 * we were waiting for it to stop, so re-do the lookup.
1373282622Shiren	 */
1374282622Shiren	nd6_dad_rele(dp);
1375282622Shiren	if (nd6_dad_find(ifa, NULL) == NULL)
1376282622Shiren		return;
1377282622Shiren
1378282622Shiren	nd6_dad_del(dp);
1379282622Shiren	nd6_dad_rele(dp);
138078064Sume}
138178064Sume
138253541Sshinstatic void
1383191816Szecnd6_dad_timer(struct dadq *dp)
138453541Sshin{
1385183550Szec	CURVNET_SET(dp->dad_vnet);
1386191816Szec	struct ifaddr *ifa = dp->dad_ifa;
1387272857Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
138853541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1389165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
139053541Sshin
139153541Sshin	/* Sanity check */
139253541Sshin	if (ia == NULL) {
139362587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1394282622Shiren		goto err;
139553541Sshin	}
1396272857Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
1397272857Shrs		/* Do not need DAD for ifdisabled interface. */
1398272857Shrs		log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of "
1399272857Shrs		    "ND6_IFF_IFDISABLED.\n", ifp->if_xname);
1400282622Shiren		goto err;
1401272857Shrs	}
140253541Sshin	if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
140362587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
140453541Sshin			"%s(%s)\n",
1405165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
140653541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1407282622Shiren		goto err;
140853541Sshin	}
140953541Sshin	if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
141062587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
141153541Sshin			"%s(%s)\n",
1412165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
141353541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1414282622Shiren		goto err;
141553541Sshin	}
141653541Sshin
1417282622Shiren	/* Stop DAD if the interface is down even after dad_maxtry attempts. */
1418282622Shiren	if ((dp->dad_ns_tcount > V_dad_maxtry) &&
1419282622Shiren	    (((ifp->if_flags & IFF_UP) == 0) ||
1420282622Shiren	     ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) {
1421290348Shrs		nd6log((LOG_INFO, "%s: could not run DAD "
1422290348Shrs		    "because the interface was down or not running.\n",
1423120941Sume		    if_name(ifa->ifa_ifp)));
1424282622Shiren		goto err;
142562587Sitojun	}
142662587Sitojun
142753541Sshin	/* Need more checks? */
142853541Sshin	if (dp->dad_ns_ocount < dp->dad_count) {
142953541Sshin		/*
143053541Sshin		 * We have more NS to go.  Send NS packet for DAD.
143153541Sshin		 */
1432120941Sume		nd6_dad_starttimer(dp,
1433290348Shrs		    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1);
1434282622Shiren		goto done;
143553541Sshin	} else {
143653541Sshin		/*
143753541Sshin		 * We have transmitted sufficient number of DAD packets.
143853541Sshin		 * See what we've got.
143953541Sshin		 */
1440282622Shiren		if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0)
1441282622Shiren			/* We've seen NS or NA, means DAD has failed. */
1442282622Shiren			nd6_dad_duplicated(ifa, dp);
1443282622Shiren		else if (V_dad_enhanced != 0 &&
1444282622Shiren		    dp->dad_ns_lcount > 0 &&
1445282622Shiren		    dp->dad_ns_lcount > dp->dad_loopbackprobe) {
144653541Sshin			/*
1447285825Shrs			 * Sec. 4.1 in RFC 7527 requires transmission of
1448285825Shrs			 * additional probes until the loopback condition
1449285825Shrs			 * becomes clear when a looped back probe is detected.
145053541Sshin			 */
1451282622Shiren			log(LOG_ERR, "%s: a looped back NS message is "
1452282622Shiren			    "detected during DAD for %s.  "
1453282622Shiren			    "Another DAD probes are being sent.\n",
1454282622Shiren			    if_name(ifa->ifa_ifp),
1455282622Shiren			    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
1456282622Shiren			dp->dad_loopbackprobe = dp->dad_ns_lcount;
1457282622Shiren			/*
1458282622Shiren			 * Send an NS immediately and increase dad_count by
1459282622Shiren			 * V_nd6_mmaxtries - 1.
1460282622Shiren			 */
1461282622Shiren			dp->dad_count =
1462282622Shiren			    dp->dad_ns_ocount + V_nd6_mmaxtries - 1;
1463282622Shiren			nd6_dad_starttimer(dp,
1464290348Shrs			    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000,
1465290348Shrs			    1);
1466282622Shiren			goto done;
146753541Sshin		} else {
146853541Sshin			/*
146953541Sshin			 * We are done with DAD.  No NA came, no NS came.
1470272857Shrs			 * No duplicate address found.  Check IFDISABLED flag
1471272857Shrs			 * again in case that it is changed between the
1472272857Shrs			 * beginning of this function and here.
147353541Sshin			 */
1474272857Shrs			if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0)
1475272857Shrs				ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
147653541Sshin
147778064Sume			nd6log((LOG_DEBUG,
147862587Sitojun			    "%s: DAD complete for %s - no duplicates found\n",
147962587Sitojun			    if_name(ifa->ifa_ifp),
1480165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
1481282622Shiren			if (dp->dad_ns_lcount > 0)
1482282622Shiren				log(LOG_ERR, "%s: DAD completed while "
1483282622Shiren				    "a looped back NS message is detected "
1484282622Shiren				    "during DAD for %s.\n",
1485282622Shiren				    if_name(ifa->ifa_ifp),
1486282622Shiren				    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
148753541Sshin		}
148853541Sshin	}
1489282622Shirenerr:
1490282622Shiren	nd6_dad_del(dp);
149153541Sshindone:
1492183550Szec	CURVNET_RESTORE();
149353541Sshin}
149453541Sshin
1495282622Shirenstatic void
1496282622Shirennd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
149753541Sshin{
149853541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1499151477Ssuz	struct ifnet *ifp;
1500165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
150153541Sshin
150278064Sume	log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
1503282622Shiren	    "NS in/out/loopback=%d/%d/%d, NA in=%d\n",
1504165118Sbz	    if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
1505282622Shiren	    dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount,
1506282622Shiren	    dp->dad_na_icount);
150753541Sshin
150853541Sshin	ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
150953541Sshin	ia->ia6_flags |= IN6_IFF_DUPLICATED;
151053541Sshin
1511151477Ssuz	ifp = ifa->ifa_ifp;
151262587Sitojun	log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
1513165118Sbz	    if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr));
151462587Sitojun	log(LOG_ERR, "%s: manual intervention required\n",
1515151477Ssuz	    if_name(ifp));
151653541Sshin
1517151477Ssuz	/*
1518151477Ssuz	 * If the address is a link-local address formed from an interface
1519151477Ssuz	 * identifier based on the hardware address which is supposed to be
1520151477Ssuz	 * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
1521151477Ssuz	 * operation on the interface SHOULD be disabled.
1522197138Shrs	 * [RFC 4862, Section 5.4.5]
1523151477Ssuz	 */
1524151477Ssuz	if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
1525151477Ssuz		struct in6_addr in6;
1526151477Ssuz
1527151477Ssuz		/*
1528151477Ssuz		 * To avoid over-reaction, we only apply this logic when we are
1529151477Ssuz		 * very sure that hardware addresses are supposed to be unique.
1530151477Ssuz		 */
1531151477Ssuz		switch (ifp->if_type) {
1532151477Ssuz		case IFT_ETHER:
1533151477Ssuz		case IFT_FDDI:
1534151477Ssuz		case IFT_ATM:
1535151477Ssuz		case IFT_IEEE1394:
1536151477Ssuz#ifdef IFT_IEEE80211
1537151477Ssuz		case IFT_IEEE80211:
1538151477Ssuz#endif
1539219819Sjeff		case IFT_INFINIBAND:
1540151477Ssuz			in6 = ia->ia_addr.sin6_addr;
1541151477Ssuz			if (in6_get_hw_ifid(ifp, &in6) == 0 &&
1542151477Ssuz			    IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
1543151477Ssuz				ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1544151477Ssuz				log(LOG_ERR, "%s: possible hardware address "
1545151477Ssuz				    "duplication detected, disable IPv6\n",
1546151477Ssuz				    if_name(ifp));
1547151477Ssuz			}
1548151477Ssuz			break;
1549151477Ssuz		}
1550151477Ssuz	}
155153541Sshin}
155253541Sshin
155362587Sitojunstatic void
1554290348Shrsnd6_dad_ns_output(struct dadq *dp)
155562587Sitojun{
1556290348Shrs	struct in6_ifaddr *ia = (struct in6_ifaddr *)dp->dad_ifa;
1557290348Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
1558282622Shiren	int i;
155962587Sitojun
156062587Sitojun	dp->dad_ns_tcount++;
156162587Sitojun	if ((ifp->if_flags & IFF_UP) == 0) {
156262587Sitojun		return;
156362587Sitojun	}
1564148887Srwatson	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
156562587Sitojun		return;
156662587Sitojun	}
156762587Sitojun
156862587Sitojun	dp->dad_ns_ocount++;
1569282622Shiren	if (V_dad_enhanced != 0) {
1570282622Shiren		for (i = 0; i < ND_OPT_NONCE_LEN32; i++)
1571282622Shiren			dp->dad_nonce[i] = arc4random();
1572282622Shiren		/*
1573282622Shiren		 * XXXHRS: Note that in the case that
1574282622Shiren		 * DupAddrDetectTransmits > 1, multiple NS messages with
1575282622Shiren		 * different nonces can be looped back in an unexpected
1576282622Shiren		 * order.  The current implementation recognizes only
1577282622Shiren		 * the latest nonce on the sender side.  Practically it
1578282622Shiren		 * should work well in almost all cases.
1579282622Shiren		 */
1580282622Shiren	}
1581282622Shiren	nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL,
1582282622Shiren	    (uint8_t *)&dp->dad_nonce[0]);
158362587Sitojun}
158462587Sitojun
158562587Sitojunstatic void
1586282622Shirennd6_dad_ns_input(struct ifaddr *ifa, struct nd_opt_nonce *ndopt_nonce)
158753541Sshin{
158853541Sshin	struct in6_ifaddr *ia;
158953541Sshin	struct ifnet *ifp;
159078064Sume	const struct in6_addr *taddr6;
159153541Sshin	struct dadq *dp;
159253541Sshin
1593151465Ssuz	if (ifa == NULL)
159453541Sshin		panic("ifa == NULL in nd6_dad_ns_input");
159553541Sshin
159653541Sshin	ia = (struct in6_ifaddr *)ifa;
159753541Sshin	ifp = ifa->ifa_ifp;
159853541Sshin	taddr6 = &ia->ia_addr.sin6_addr;
1599282622Shiren	/* Ignore Nonce option when Enhanced DAD is disabled. */
1600282622Shiren	if (V_dad_enhanced == 0)
1601282622Shiren		ndopt_nonce = NULL;
1602282622Shiren	dp = nd6_dad_find(ifa, ndopt_nonce);
1603282622Shiren	if (dp == NULL)
160453541Sshin		return;
160553541Sshin
1606282622Shiren	dp->dad_ns_icount++;
1607282622Shiren	nd6_dad_rele(dp);
160853541Sshin}
160953541Sshin
161062587Sitojunstatic void
1611171259Sdelphijnd6_dad_na_input(struct ifaddr *ifa)
161253541Sshin{
161353541Sshin	struct dadq *dp;
161453541Sshin
1615151465Ssuz	if (ifa == NULL)
161653541Sshin		panic("ifa == NULL in nd6_dad_na_input");
161753541Sshin
1618282622Shiren	dp = nd6_dad_find(ifa, NULL);
1619282622Shiren	if (dp != NULL) {
162053541Sshin		dp->dad_na_icount++;
1621282622Shiren		nd6_dad_rele(dp);
1622282622Shiren	}
162353541Sshin}
1624