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: stable/11/sys/netinet6/nd6_nbr.c 359803 2020-04-11 09:36:41Z 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>
7153541Sshin#include <netinet6/in6_var.h>
72151477Ssuz#include <netinet6/in6_ifattach.h>
7362587Sitojun#include <netinet/ip6.h>
7453541Sshin#include <netinet6/ip6_var.h>
75148385Sume#include <netinet6/scope6_var.h>
7653541Sshin#include <netinet6/nd6.h>
7762587Sitojun#include <netinet/icmp6.h>
78211193Swill#include <netinet/ip_carp.h>
79211501Sanchie#include <netinet6/send.h>
8053541Sshin
8162587Sitojun#define SDL(s) ((struct sockaddr_dl *)s)
8253541Sshin
8362587Sitojunstruct dadq;
84279531Shrsstatic struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *);
85274347Smelifarostatic void nd6_dad_add(struct dadq *dp);
86274347Smelifarostatic void nd6_dad_del(struct dadq *dp);
87275593Smarkjstatic void nd6_dad_rele(struct dadq *);
88288600Shrsstatic void nd6_dad_starttimer(struct dadq *, int, int);
89175162Sobrienstatic void nd6_dad_stoptimer(struct dadq *);
90191816Szecstatic void nd6_dad_timer(struct dadq *);
91274347Smelifarostatic void nd6_dad_duplicated(struct ifaddr *, struct dadq *);
92288600Shrsstatic void nd6_dad_ns_output(struct dadq *);
93279531Shrsstatic void nd6_dad_ns_input(struct ifaddr *, struct nd_opt_nonce *);
94175162Sobrienstatic void nd6_dad_na_input(struct ifaddr *);
95231852Sbzstatic void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
96231852Sbz    const struct in6_addr *, u_long, int, struct sockaddr *, u_int);
97279564Saestatic void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *,
98287484Smelifaro    const struct in6_addr *, const struct in6_addr *, uint8_t *, u_int);
9953541Sshin
100279531Shrsstatic VNET_DEFINE(int, dad_enhanced) = 1;
101279531Shrs#define	V_dad_enhanced			VNET(dad_enhanced)
102279531Shrs
103279531ShrsSYSCTL_DECL(_net_inet6_ip6);
104279531ShrsSYSCTL_INT(_net_inet6_ip6, OID_AUTO, dad_enhanced, CTLFLAG_VNET | CTLFLAG_RW,
105279531Shrs    &VNET_NAME(dad_enhanced), 0,
106279531Shrs    "Enable Enhanced DAD, which adds a random nonce to NS messages for DAD.");
107279531Shrs
108266857Shrsstatic VNET_DEFINE(int, dad_maxtry) = 15;	/* max # of *tries* to
109266857Shrs						   transmit DAD packet */
110195727Srwatson#define	V_dad_maxtry			VNET(dad_maxtry)
111195699Srwatson
11253541Sshin/*
113108470Sschweikh * Input a Neighbor Solicitation Message.
11453541Sshin *
11553541Sshin * Based on RFC 2461
116148987Sume * Based on RFC 2462 (duplicate address detection)
11753541Sshin */
11853541Sshinvoid
119171259Sdelphijnd6_ns_input(struct mbuf *m, int off, int icmp6len)
12053541Sshin{
12153541Sshin	struct ifnet *ifp = m->m_pkthdr.rcvif;
12253541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
12362587Sitojun	struct nd_neighbor_solicit *nd_ns;
12453541Sshin	struct in6_addr saddr6 = ip6->ip6_src;
12553541Sshin	struct in6_addr daddr6 = ip6->ip6_dst;
12662587Sitojun	struct in6_addr taddr6;
127292402Ssmh	struct in6_addr myaddr6;
12853541Sshin	char *lladdr = NULL;
129142215Sglebius	struct ifaddr *ifa = NULL;
13053541Sshin	int lladdrlen = 0;
131292402Ssmh	int anycast = 0, proxy = 0, tentative = 0;
13253541Sshin	int tlladdr;
133292402Ssmh	int rflag;
13453541Sshin	union nd_opts ndopts;
135219562Sbz	struct sockaddr_dl proxydl;
136165118Sbz	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
13753541Sshin
138327337Sae	/* RFC 6980: Nodes MUST silently ignore fragments */
139327337Sae	if(m->m_flags & M_FRAGMENTED)
140327337Sae		goto freeit;
141327337Sae
142292402Ssmh	rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0;
143292402Ssmh	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif)
144292402Ssmh		rflag = 0;
14578064Sume#ifndef PULLDOWN_TEST
14678064Sume	IP6_EXTHDR_CHECK(m, off, icmp6len,);
14778064Sume	nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
14878064Sume#else
14978064Sume	IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
15078064Sume	if (nd_ns == NULL) {
151190964Srwatson		ICMP6STAT_INC(icp6s_tooshort);
15278064Sume		return;
15378064Sume	}
15478064Sume#endif
15578064Sume	ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
15678064Sume	taddr6 = nd_ns->nd_ns_target;
157148385Sume	if (in6_setscope(&taddr6, ifp, NULL) != 0)
158148385Sume		goto bad;
15978064Sume
16053541Sshin	if (ip6->ip6_hlim != 255) {
16178064Sume		nd6log((LOG_ERR,
16278064Sume		    "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
163165118Sbz		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
164165118Sbz		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
16578064Sume		goto bad;
16653541Sshin	}
16753541Sshin
16853541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
169148987Sume		/* dst has to be a solicited node multicast address. */
170120941Sume		if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
17195023Ssuz		    /* don't check ifindex portion */
172120941Sume		    daddr6.s6_addr32[1] == 0 &&
173120941Sume		    daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
174120941Sume		    daddr6.s6_addr8[12] == 0xff) {
17595023Ssuz			; /* good */
17653541Sshin		} else {
17778064Sume			nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
178120941Sume			    "(wrong ip6 dst)\n"));
17953541Sshin			goto bad;
18053541Sshin		}
181185348Szec	} else if (!V_nd6_onlink_ns_rfc4861) {
182183529Scperciva		struct sockaddr_in6 src_sa6;
183183529Scperciva
184183529Scperciva		/*
185183529Scperciva		 * According to recent IETF discussions, it is not a good idea
186183529Scperciva		 * to accept a NS from an address which would not be deemed
187183529Scperciva		 * to be a neighbor otherwise.  This point is expected to be
188183529Scperciva		 * clarified in future revisions of the specification.
189183529Scperciva		 */
190183529Scperciva		bzero(&src_sa6, sizeof(src_sa6));
191183529Scperciva		src_sa6.sin6_family = AF_INET6;
192183529Scperciva		src_sa6.sin6_len = sizeof(src_sa6);
193183529Scperciva		src_sa6.sin6_addr = saddr6;
194186119Sqingli		if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) {
195183529Scperciva			nd6log((LOG_INFO, "nd6_ns_input: "
196183529Scperciva				"NS packet from non-neighbor\n"));
197183529Scperciva			goto bad;
198183529Scperciva		}
19953541Sshin	}
20053541Sshin
20153541Sshin	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
20278064Sume		nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
20353541Sshin		goto bad;
20453541Sshin	}
20553541Sshin
20653541Sshin	icmp6len -= sizeof(*nd_ns);
20753541Sshin	nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
20853541Sshin	if (nd6_options(&ndopts) < 0) {
20978064Sume		nd6log((LOG_INFO,
21078064Sume		    "nd6_ns_input: invalid ND option, ignored\n"));
21178064Sume		/* nd6_options have incremented stats */
21278064Sume		goto freeit;
21353541Sshin	}
21453541Sshin
21553541Sshin	if (ndopts.nd_opts_src_lladdr) {
21695023Ssuz		lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
21753541Sshin		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
21853541Sshin	}
219120941Sume
22053541Sshin	if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
22178064Sume		nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
22278064Sume		    "(link-layer address option)\n"));
22353541Sshin		goto bad;
22453541Sshin	}
22553541Sshin
22653541Sshin	/*
22753541Sshin	 * Attaching target link-layer address to the NA?
22853541Sshin	 * (RFC 2461 7.2.4)
22953541Sshin	 *
23053541Sshin	 * NS IP dst is unicast/anycast			MUST NOT add
23153541Sshin	 * NS IP dst is solicited-node multicast	MUST add
23253541Sshin	 *
23353541Sshin	 * In implementation, we add target link-layer address by default.
23453541Sshin	 * We do not add one in MUST NOT cases.
23553541Sshin	 */
236292402Ssmh	if (!IN6_IS_ADDR_MULTICAST(&daddr6))
237292402Ssmh		tlladdr = 0;
238292402Ssmh	else
239292402Ssmh		tlladdr = 1;
24053541Sshin
24153541Sshin	/*
24253541Sshin	 * Target address (taddr6) must be either:
24353541Sshin	 * (1) Valid unicast/anycast address for my receiving interface,
24453541Sshin	 * (2) Unicast address for which I'm offering proxy service, or
24553541Sshin	 * (3) "tentative" address on which DAD is being performed.
24653541Sshin	 */
24753541Sshin	/* (1) and (3) check. */
248142215Sglebius	if (ifp->if_carp)
249211157Swill		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
250228571Sglebius	else
251142215Sglebius		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
25253541Sshin
25353541Sshin	/* (2) check. */
254151465Ssuz	if (ifa == NULL) {
255293159Smelifaro		struct sockaddr_dl rt_gateway;
256293159Smelifaro		struct rt_addrinfo info;
257293159Smelifaro		struct sockaddr_in6 dst6;
25853541Sshin
259293159Smelifaro		bzero(&dst6, sizeof(dst6));
260293159Smelifaro		dst6.sin6_len = sizeof(struct sockaddr_in6);
261293159Smelifaro		dst6.sin6_family = AF_INET6;
262293159Smelifaro		dst6.sin6_addr = taddr6;
26353541Sshin
264293159Smelifaro		bzero(&rt_gateway, sizeof(rt_gateway));
265293159Smelifaro		rt_gateway.sdl_len = sizeof(rt_gateway);
266293159Smelifaro		bzero(&info, sizeof(info));
267293159Smelifaro		info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
268293159Smelifaro
269317067Sasomers		if (rib_lookup_info(ifp->if_fib, (struct sockaddr *)&dst6,
270293159Smelifaro		    0, 0, &info) == 0) {
271293159Smelifaro			if ((info.rti_flags & RTF_ANNOUNCE) != 0 &&
272293159Smelifaro			    rt_gateway.sdl_family == AF_LINK) {
273293159Smelifaro
274293159Smelifaro				/*
275293159Smelifaro				 * proxy NDP for single entry
276293159Smelifaro				 */
277293159Smelifaro				proxydl = *SDL(&rt_gateway);
278293159Smelifaro				ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(
279293159Smelifaro				    ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
280293159Smelifaro				if (ifa)
281293159Smelifaro					proxy = 1;
282293159Smelifaro			}
283219562Sbz		}
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	}
293292402Ssmh	myaddr6 = *IFA_IN6(ifa);
294292402Ssmh	anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
295292402Ssmh	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
307292402Ssmh	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	 */
325292402Ssmh	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;
353292402Ssmh		nd6_na_output_fib(ifp, &in6_all, &taddr6,
354292402Ssmh		    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
355292402Ssmh		    rflag, tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL,
356292402Ssmh		    M_GETFIB(m));
35762587Sitojun		goto freeit;
35853541Sshin	}
35953541Sshin
360120941Sume	nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
361120941Sume	    ND_NEIGHBOR_SOLICIT, 0);
36253541Sshin
363292402Ssmh	nd6_na_output_fib(ifp, &saddr6, &taddr6,
364292402Ssmh	    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
365292402Ssmh	    rflag | ND_NA_FLAG_SOLICITED, tlladdr,
366292402Ssmh	    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
400287484Smelifarond6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6,
401287484Smelifaro    const struct in6_addr *daddr6, const struct in6_addr *taddr6,
402287484Smelifaro    uint8_t *nonce, 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;
412120941Sume
41353541Sshin	if (IN6_IS_ADDR_MULTICAST(taddr6))
41453541Sshin		return;
41553541Sshin
41662587Sitojun	/* estimate the size of message */
41762587Sitojun	maxlen = sizeof(*ip6) + sizeof(*nd_ns);
41862587Sitojun	maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
419281309Sae	KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
420281309Sae	    "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
421281309Sae	    __func__, max_linkhdr, maxlen, MCLBYTES));
42253541Sshin
423248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
424248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
425248328Sglebius	else
426248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
42762587Sitojun	if (m == NULL)
42862587Sitojun		return;
429279564Sae	M_SETFIB(m, fibnum);
43062587Sitojun
43153541Sshin	if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
43253541Sshin		m->m_flags |= M_MCAST;
43353541Sshin		im6o.im6o_multicast_ifp = ifp;
43453541Sshin		im6o.im6o_multicast_hlim = 255;
43553541Sshin		im6o.im6o_multicast_loop = 0;
43653541Sshin	}
43753541Sshin
43853541Sshin	icmp6len = sizeof(*nd_ns);
43953541Sshin	m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
440276692Srwatson	m->m_data += max_linkhdr;	/* or M_ALIGN() equivalent? */
44153541Sshin
44253541Sshin	/* fill neighbor solicitation packet */
44353541Sshin	ip6 = mtod(m, struct ip6_hdr *);
44453541Sshin	ip6->ip6_flow = 0;
44562587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
44662587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
44753541Sshin	/* ip6->ip6_plen will be set later */
44853541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
44953541Sshin	ip6->ip6_hlim = 255;
45053541Sshin	if (daddr6)
45153541Sshin		ip6->ip6_dst = *daddr6;
45253541Sshin	else {
45353541Sshin		ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
454148385Sume		ip6->ip6_dst.s6_addr16[1] = 0;
45553541Sshin		ip6->ip6_dst.s6_addr32[1] = 0;
45653541Sshin		ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
45753541Sshin		ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
45853541Sshin		ip6->ip6_dst.s6_addr8[12] = 0xff;
459148385Sume		if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
460148385Sume			goto bad;
46153541Sshin	}
462279531Shrs	if (nonce == NULL) {
463287484Smelifaro		struct ifaddr *ifa = NULL;
464194760Srwatson
46553541Sshin		/*
46653541Sshin		 * RFC2461 7.2.2:
46753541Sshin		 * "If the source address of the packet prompting the
46853541Sshin		 * solicitation is the same as one of the addresses assigned
46953541Sshin		 * to the outgoing interface, that address SHOULD be placed
47053541Sshin		 * in the IP Source Address of the outgoing solicitation.
47153541Sshin		 * Otherwise, any one of the addresses assigned to the
47253541Sshin		 * interface should be used."
47353541Sshin		 *
47453541Sshin		 * We use the source address for the prompting packet
475287484Smelifaro		 * (saddr6), if saddr6 belongs to the outgoing interface.
476148385Sume		 * Otherwise, we perform the source address selection as usual.
47753541Sshin		 */
47853541Sshin
479287484Smelifaro		if (saddr6 != NULL)
480287484Smelifaro			ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, saddr6);
481287484Smelifaro		if (ifa != NULL) {
482216022Sbz			/* ip6_src set already. */
483287484Smelifaro			ip6->ip6_src = *saddr6;
484194760Srwatson			ifa_free(ifa);
485194760Srwatson		} else {
486148385Sume			int error;
487293633Smelifaro			struct in6_addr dst6, src6;
488293633Smelifaro			uint32_t scopeid;
489148385Sume
490293633Smelifaro			in6_splitscope(&ip6->ip6_dst, &dst6, &scopeid);
491317067Sasomers			error = in6_selectsrc_addr(fibnum, &dst6,
492293633Smelifaro			    scopeid, ifp, &src6, NULL);
493194777Sbz			if (error) {
494165118Sbz				char ip6buf[INET6_ADDRSTRLEN];
495279564Sae				nd6log((LOG_DEBUG, "%s: source can't be "
496279564Sae				    "determined: dst=%s, error=%d\n", __func__,
497293633Smelifaro				    ip6_sprintf(ip6buf, &dst6),
498165118Sbz				    error));
499148385Sume				goto bad;
50053541Sshin			}
501293633Smelifaro			ip6->ip6_src = src6;
50253541Sshin		}
50353541Sshin	} else {
50453541Sshin		/*
50553541Sshin		 * Source address for DAD packet must always be IPv6
50653541Sshin		 * unspecified address. (0::0)
507148385Sume		 * We actually don't have to 0-clear the address (we did it
508148385Sume		 * above), but we do so here explicitly to make the intention
509148385Sume		 * clearer.
51053541Sshin		 */
511216022Sbz		bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
51253541Sshin	}
51353541Sshin	nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
51453541Sshin	nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
51553541Sshin	nd_ns->nd_ns_code = 0;
51653541Sshin	nd_ns->nd_ns_reserved = 0;
51753541Sshin	nd_ns->nd_ns_target = *taddr6;
518121315Sume	in6_clearscope(&nd_ns->nd_ns_target); /* XXX */
51953541Sshin
52053541Sshin	/*
52153541Sshin	 * Add source link-layer address option.
52253541Sshin	 *
52353541Sshin	 *				spec		implementation
52453541Sshin	 *				---		---
52553541Sshin	 * DAD packet			MUST NOT	do not add the option
52653541Sshin	 * there's no link layer address:
52753541Sshin	 *				impossible	do not add the option
52853541Sshin	 * there's link layer address:
52953541Sshin	 *	Multicast NS		MUST add one	add the option
53053541Sshin	 *	Unicast NS		SHOULD add one	add the option
53153541Sshin	 */
532279531Shrs	if (nonce == NULL && (mac = nd6_ifptomac(ifp))) {
53353541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
53453541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
53553541Sshin		/* 8 byte alignments... */
53653541Sshin		optlen = (optlen + 7) & ~7;
537120941Sume
53853541Sshin		m->m_pkthdr.len += optlen;
53953541Sshin		m->m_len += optlen;
54053541Sshin		icmp6len += optlen;
54153541Sshin		bzero((caddr_t)nd_opt, optlen);
54253541Sshin		nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
54353541Sshin		nd_opt->nd_opt_len = optlen >> 3;
54453541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
54553541Sshin	}
546279531Shrs	/*
547279531Shrs	 * Add a Nonce option (RFC 3971) to detect looped back NS messages.
548279531Shrs	 * This behavior is documented as Enhanced Duplicate Address
549287094Shrs	 * Detection in RFC 7527.
550279531Shrs	 * net.inet6.ip6.dad_enhanced=0 disables this.
551279531Shrs	 */
552279531Shrs	if (V_dad_enhanced != 0 && nonce != NULL) {
553279531Shrs		int optlen = sizeof(struct nd_opt_hdr) + ND_OPT_NONCE_LEN;
554279531Shrs		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
555279531Shrs		/* 8-byte alignment is required. */
556279531Shrs		optlen = (optlen + 7) & ~7;
55753541Sshin
558279531Shrs		m->m_pkthdr.len += optlen;
559279531Shrs		m->m_len += optlen;
560279531Shrs		icmp6len += optlen;
561279531Shrs		bzero((caddr_t)nd_opt, optlen);
562279531Shrs		nd_opt->nd_opt_type = ND_OPT_NONCE;
563279531Shrs		nd_opt->nd_opt_len = optlen >> 3;
564279531Shrs		bcopy(nonce, (caddr_t)(nd_opt + 1), ND_OPT_NONCE_LEN);
565279531Shrs	}
56653541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
56753541Sshin	nd_ns->nd_ns_cksum = 0;
568120941Sume	nd_ns->nd_ns_cksum =
569120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
57053541Sshin
571211501Sanchie	if (send_sendso_input_hook != NULL) {
572211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
573211501Sanchie			sizeof(unsigned short), M_NOWAIT);
574211501Sanchie		if (mtag == NULL)
575211501Sanchie			goto bad;
576211501Sanchie		*(unsigned short *)(mtag + 1) = nd_ns->nd_ns_type;
577211501Sanchie		m_tag_prepend(m, mtag);
578211501Sanchie	}
579211501Sanchie
580293101Smelifaro	ip6_output(m, NULL, NULL, (nonce != NULL) ? IPV6_UNSPECSRC : 0,
581279531Shrs	    &im6o, NULL, NULL);
582148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
583148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
584190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
585148385Sume
586148385Sume	return;
587148385Sume
588148385Sume  bad:
589148385Sume	m_freem(m);
59053541Sshin}
59153541Sshin
592279564Sae#ifndef BURN_BRIDGES
593279564Saevoid
594287484Smelifarond6_ns_output(struct ifnet *ifp, const struct in6_addr *saddr6,
595287484Smelifaro    const struct in6_addr *daddr6, const struct in6_addr *taddr6,uint8_t *nonce)
596279564Sae{
597279564Sae
598287484Smelifaro	nd6_ns_output_fib(ifp, saddr6, daddr6, taddr6, nonce, RT_DEFAULT_FIB);
599279564Sae}
600279564Sae#endif
60153541Sshin/*
60253541Sshin * Neighbor advertisement input handling.
60353541Sshin *
60453541Sshin * Based on RFC 2461
605148987Sume * Based on RFC 2462 (duplicate address detection)
60662587Sitojun *
60762587Sitojun * the following items are not implemented yet:
60862587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
60962587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
61053541Sshin */
61153541Sshinvoid
612171259Sdelphijnd6_na_input(struct mbuf *m, int off, int icmp6len)
61353541Sshin{
61453541Sshin	struct ifnet *ifp = m->m_pkthdr.rcvif;
61553541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
61662587Sitojun	struct nd_neighbor_advert *nd_na;
61753541Sshin	struct in6_addr daddr6 = ip6->ip6_dst;
61862587Sitojun	struct in6_addr taddr6;
61962587Sitojun	int flags;
62062587Sitojun	int is_router;
62162587Sitojun	int is_solicited;
62262587Sitojun	int is_override;
62353541Sshin	char *lladdr = NULL;
62453541Sshin	int lladdrlen = 0;
625186468Skmacy	int checklink = 0;
62653541Sshin	struct ifaddr *ifa;
627186119Sqingli	struct llentry *ln = NULL;
62853541Sshin	union nd_opts ndopts;
629186119Sqingli	struct mbuf *chain = NULL;
630186119Sqingli	struct sockaddr_in6 sin6;
631292978Smelifaro	u_char linkhdr[LLE_MAX_LINKHDR];
632292978Smelifaro	size_t linkhdrsize;
633292978Smelifaro	int lladdr_off;
634165118Sbz	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
63553541Sshin
636327337Sae	/* RFC 6980: Nodes MUST silently ignore fragments */
637327337Sae	if(m->m_flags & M_FRAGMENTED)
638327337Sae		goto freeit;
639327337Sae
64053541Sshin	if (ip6->ip6_hlim != 255) {
64178064Sume		nd6log((LOG_ERR,
64278064Sume		    "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
643165118Sbz		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
644165118Sbz		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
64578064Sume		goto bad;
64662587Sitojun	}
64762587Sitojun
64862587Sitojun#ifndef PULLDOWN_TEST
64962587Sitojun	IP6_EXTHDR_CHECK(m, off, icmp6len,);
65062587Sitojun	nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
65162587Sitojun#else
65262587Sitojun	IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
65362587Sitojun	if (nd_na == NULL) {
654190964Srwatson		ICMP6STAT_INC(icp6s_tooshort);
65553541Sshin		return;
65653541Sshin	}
65762587Sitojun#endif
658148385Sume
65962587Sitojun	flags = nd_na->nd_na_flags_reserved;
66062587Sitojun	is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
66162587Sitojun	is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
66262587Sitojun	is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
663276844Smelifaro	memset(&sin6, 0, sizeof(sin6));
66453541Sshin
665148385Sume	taddr6 = nd_na->nd_na_target;
666148385Sume	if (in6_setscope(&taddr6, ifp, NULL))
667150202Ssuz		goto bad;	/* XXX: impossible */
66853541Sshin
66953541Sshin	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
67078064Sume		nd6log((LOG_ERR,
67153541Sshin		    "nd6_na_input: invalid target address %s\n",
672165118Sbz		    ip6_sprintf(ip6bufs, &taddr6)));
67378064Sume		goto bad;
67453541Sshin	}
67553541Sshin	if (IN6_IS_ADDR_MULTICAST(&daddr6))
67653541Sshin		if (is_solicited) {
67778064Sume			nd6log((LOG_ERR,
67878064Sume			    "nd6_na_input: a solicited adv is multicasted\n"));
67978064Sume			goto bad;
68053541Sshin		}
68153541Sshin
68253541Sshin	icmp6len -= sizeof(*nd_na);
68353541Sshin	nd6_option_init(nd_na + 1, icmp6len, &ndopts);
68453541Sshin	if (nd6_options(&ndopts) < 0) {
68578064Sume		nd6log((LOG_INFO,
68678064Sume		    "nd6_na_input: invalid ND option, ignored\n"));
68778064Sume		/* nd6_options have incremented stats */
68862587Sitojun		goto freeit;
68953541Sshin	}
69053541Sshin
69153541Sshin	if (ndopts.nd_opts_tgt_lladdr) {
69253541Sshin		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
69353541Sshin		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
69453541Sshin	}
69553541Sshin
696228571Sglebius	/*
697228571Sglebius	 * This effectively disables the DAD check on a non-master CARP
698228571Sglebius	 * address.
699228571Sglebius	 */
700228571Sglebius	if (ifp->if_carp)
701228571Sglebius		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
702228571Sglebius	else
703228571Sglebius		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
70453541Sshin
70553541Sshin	/*
70653541Sshin	 * Target address matches one of my interface address.
70753541Sshin	 *
70853541Sshin	 * If my address is tentative, this means that there's somebody
70953541Sshin	 * already using the same address as mine.  This indicates DAD failure.
71053541Sshin	 * This is defined in RFC 2462.
71153541Sshin	 *
71253541Sshin	 * Otherwise, process as defined in RFC 2461.
71353541Sshin	 */
71453541Sshin	if (ifa
71553541Sshin	 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
716280236Sae		nd6_dad_na_input(ifa);
717194760Srwatson		ifa_free(ifa);
71862587Sitojun		goto freeit;
71953541Sshin	}
72053541Sshin
72195023Ssuz	/* Just for safety, maybe unnecessary. */
72253541Sshin	if (ifa) {
723194760Srwatson		ifa_free(ifa);
72453541Sshin		log(LOG_ERR,
72553541Sshin		    "nd6_na_input: duplicate IP6 address %s\n",
726165118Sbz		    ip6_sprintf(ip6bufs, &taddr6));
72762587Sitojun		goto freeit;
72853541Sshin	}
72953541Sshin
73053541Sshin	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
731120941Sume		nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
732165118Sbz		    "(if %d, NA packet %d)\n", ip6_sprintf(ip6bufs, &taddr6),
733120941Sume		    ifp->if_addrlen, lladdrlen - 2));
73478064Sume		goto bad;
73553541Sshin	}
73653541Sshin
73753541Sshin	/*
738120941Sume	 * If no neighbor cache entry is found, NA SHOULD silently be
739120941Sume	 * discarded.
74053541Sshin	 */
741260187Sae	IF_AFDATA_RLOCK(ifp);
742186119Sqingli	ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
743260187Sae	IF_AFDATA_RUNLOCK(ifp);
744186119Sqingli	if (ln == NULL) {
74562587Sitojun		goto freeit;
746186119Sqingli	}
74753541Sshin
748359803Sae	/*
749359803Sae	 * Do not try to override static entry.
750359803Sae	 */
751359803Sae	if (ln->la_flags & LLE_STATIC)
752359803Sae		goto freeit;
753359803Sae
75453541Sshin	if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
75553541Sshin		/*
75653541Sshin		 * If the link-layer has address, and no lladdr option came,
75753541Sshin		 * discard the packet.
75853541Sshin		 */
759186119Sqingli		if (ifp->if_addrlen && lladdr == NULL) {
76062587Sitojun			goto freeit;
761186119Sqingli		}
76253541Sshin
76353541Sshin		/*
76453541Sshin		 * Record link-layer address, and update the state.
76553541Sshin		 */
766292978Smelifaro		linkhdrsize = sizeof(linkhdr);
767292978Smelifaro		if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
768292978Smelifaro		    linkhdr, &linkhdrsize, &lladdr_off) != 0)
769292978Smelifaro			return;
770292978Smelifaro
771292978Smelifaro		if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
772292978Smelifaro		    lladdr_off) == 0) {
773292155Smelifaro			ln = NULL;
774292155Smelifaro			goto freeit;
775292155Smelifaro		}
776245925Snp		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
777288301Smelifaro		if (is_solicited)
778288062Smelifaro			nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
779288301Smelifaro		else
780288062Smelifaro			nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
78178064Sume		if ((ln->ln_router = is_router) != 0) {
78278064Sume			/*
78378064Sume			 * This means a router's state has changed from
78478064Sume			 * non-reachable to probably reachable, and might
78578064Sume			 * affect the status of associated prefixes..
78678064Sume			 */
787186468Skmacy			checklink = 1;
78878064Sume		}
78953541Sshin	} else {
79053541Sshin		int llchange;
79153541Sshin
79253541Sshin		/*
79353541Sshin		 * Check if the link-layer address has changed or not.
79453541Sshin		 */
795151465Ssuz		if (lladdr == NULL)
79653541Sshin			llchange = 0;
79753541Sshin		else {
798186119Sqingli			if (ln->la_flags & LLE_VALID) {
799292978Smelifaro				if (bcmp(lladdr, ln->ll_addr, ifp->if_addrlen))
80053541Sshin					llchange = 1;
80153541Sshin				else
80253541Sshin					llchange = 0;
80353541Sshin			} else
80453541Sshin				llchange = 1;
80553541Sshin		}
80653541Sshin
80753541Sshin		/*
80853541Sshin		 * This is VERY complex.  Look at it with care.
80953541Sshin		 *
81053541Sshin		 * override solicit lladdr llchange	action
81153541Sshin		 *					(L: record lladdr)
81253541Sshin		 *
81353541Sshin		 *	0	0	n	--	(2c)
81453541Sshin		 *	0	0	y	n	(2b) L
81553541Sshin		 *	0	0	y	y	(1)    REACHABLE->STALE
81653541Sshin		 *	0	1	n	--	(2c)   *->REACHABLE
81753541Sshin		 *	0	1	y	n	(2b) L *->REACHABLE
81853541Sshin		 *	0	1	y	y	(1)    REACHABLE->STALE
81953541Sshin		 *	1	0	n	--	(2a)
82053541Sshin		 *	1	0	y	n	(2a) L
82153541Sshin		 *	1	0	y	y	(2a) L *->STALE
82253541Sshin		 *	1	1	n	--	(2a)   *->REACHABLE
82353541Sshin		 *	1	1	y	n	(2a) L *->REACHABLE
82453541Sshin		 *	1	1	y	y	(2a) L *->REACHABLE
82553541Sshin		 */
826151539Ssuz		if (!is_override && (lladdr != NULL && llchange)) {  /* (1) */
82753541Sshin			/*
82853541Sshin			 * If state is REACHABLE, make it STALE.
82953541Sshin			 * no other updates should be done.
83053541Sshin			 */
831288062Smelifaro			if (ln->ln_state == ND6_LLINFO_REACHABLE)
832288062Smelifaro				nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
83362587Sitojun			goto freeit;
83453541Sshin		} else if (is_override				   /* (2a) */
835151465Ssuz			|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */
836151465Ssuz			|| lladdr == NULL) {			   /* (2c) */
83753541Sshin			/*
83853541Sshin			 * Update link-local address, if any.
83953541Sshin			 */
840151465Ssuz			if (lladdr != NULL) {
841292978Smelifaro				linkhdrsize = sizeof(linkhdr);
842292978Smelifaro				if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
843292978Smelifaro				    linkhdr, &linkhdrsize, &lladdr_off) != 0)
844292978Smelifaro					goto freeit;
845292978Smelifaro				if (lltable_try_set_entry_addr(ifp, ln, linkhdr,
846292978Smelifaro				    linkhdrsize, lladdr_off) == 0) {
847292155Smelifaro					ln = NULL;
848292155Smelifaro					goto freeit;
849292155Smelifaro				}
850245925Snp				EVENTHANDLER_INVOKE(lle_event, ln,
851245925Snp				    LLENTRY_RESOLVED);
85253541Sshin			}
85353541Sshin
85453541Sshin			/*
85553541Sshin			 * If solicited, make the state REACHABLE.
85653541Sshin			 * If not solicited and the link-layer address was
85753541Sshin			 * changed, make it STALE.
85853541Sshin			 */
859288301Smelifaro			if (is_solicited)
860288062Smelifaro				nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE);
861288301Smelifaro			else {
862288062Smelifaro				if (lladdr != NULL && llchange)
863288062Smelifaro					nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
86453541Sshin			}
86553541Sshin		}
86653541Sshin
86753541Sshin		if (ln->ln_router && !is_router) {
86853541Sshin			/*
86953541Sshin			 * The peer dropped the router flag.
87053541Sshin			 * Remove the sender from the Default Router List and
87153541Sshin			 * update the Destination Cache entries.
87253541Sshin			 */
873293038Smelifaro			struct ifnet *nd6_ifp;
87453541Sshin
875293038Smelifaro			nd6_ifp = lltable_get_ifp(ln->lle_tbl);
876296991Smarkj			if (!defrouter_remove(&ln->r_l3addr.addr6, nd6_ifp) &&
877296991Smarkj			    (ND_IFINFO(nd6_ifp)->flags &
878296991Smarkj			     ND6_IFF_ACCEPT_RTADV) != 0)
879296991Smarkj				/*
880296991Smarkj				 * Even if the neighbor is not in the default
881296991Smarkj				 * router list, the neighbor may be used as a
882296991Smarkj				 * next hop for some destinations (e.g. redirect
883296991Smarkj				 * case). So we must call rt6_flush explicitly.
884296991Smarkj				 */
885296991Smarkj				rt6_flush(&ip6->ip6_src, ifp);
88653541Sshin		}
88753541Sshin		ln->ln_router = is_router;
88853541Sshin	}
889186119Sqingli        /* XXX - QL
890186119Sqingli	 *  Does this matter?
891186119Sqingli	 *  rt->rt_flags &= ~RTF_REJECT;
892186119Sqingli	 */
893186119Sqingli	ln->la_asked = 0;
894276844Smelifaro	if (ln->la_hold != NULL)
895276844Smelifaro		nd6_grab_holdchain(ln, &chain, &sin6);
896186119Sqingli freeit:
897276844Smelifaro	if (ln != NULL)
898186119Sqingli		LLE_WUNLOCK(ln);
89962587Sitojun
900276844Smelifaro	if (chain != NULL)
901276844Smelifaro		nd6_flush_holdchain(ifp, ifp, chain, &sin6);
902276844Smelifaro
903186468Skmacy	if (checklink)
904186468Skmacy		pfxlist_onlink_check();
905186468Skmacy
90662587Sitojun	m_freem(m);
90778064Sume	return;
90878064Sume
90978064Sume bad:
910186160Skmacy	if (ln != NULL)
911186119Sqingli		LLE_WUNLOCK(ln);
912186119Sqingli
913190964Srwatson	ICMP6STAT_INC(icp6s_badna);
91478064Sume	m_freem(m);
91553541Sshin}
91653541Sshin
91753541Sshin/*
91853541Sshin * Neighbor advertisement output handling.
91953541Sshin *
92053541Sshin * Based on RFC 2461
92153541Sshin *
92262587Sitojun * the following items are not implemented yet:
92362587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
92462587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
925171259Sdelphij *
926171259Sdelphij * tlladdr - 1 if include target link-layer address
927171259Sdelphij * sdl0 - sockaddr_dl (= proxy NA) or NULL
92853541Sshin */
929231852Sbzstatic void
930231852Sbznd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
931171259Sdelphij    const struct in6_addr *taddr6, u_long flags, int tlladdr,
932231852Sbz    struct sockaddr *sdl0, u_int fibnum)
93353541Sshin{
93453541Sshin	struct mbuf *m;
935211501Sanchie	struct m_tag *mtag;
93653541Sshin	struct ip6_hdr *ip6;
93753541Sshin	struct nd_neighbor_advert *nd_na;
93853541Sshin	struct ip6_moptions im6o;
939293633Smelifaro	struct in6_addr daddr6, dst6, src6;
940293633Smelifaro	uint32_t scopeid;
941293633Smelifaro
942148385Sume	int icmp6len, maxlen, error;
94392733Speter	caddr_t mac = NULL;
94462587Sitojun
945148385Sume	daddr6 = *daddr6_0;	/* make a local copy for modification */
946148385Sume
94762587Sitojun	/* estimate the size of message */
94862587Sitojun	maxlen = sizeof(*ip6) + sizeof(*nd_na);
94962587Sitojun	maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
950281309Sae	KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
951281309Sae	    "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
952281309Sae	    __func__, max_linkhdr, maxlen, MCLBYTES));
95353541Sshin
954248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
955248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
956248328Sglebius	else
957248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
95862587Sitojun	if (m == NULL)
95962587Sitojun		return;
960231852Sbz	M_SETFIB(m, fibnum);
96162587Sitojun
962148385Sume	if (IN6_IS_ADDR_MULTICAST(&daddr6)) {
96353541Sshin		m->m_flags |= M_MCAST;
96453541Sshin		im6o.im6o_multicast_ifp = ifp;
96553541Sshin		im6o.im6o_multicast_hlim = 255;
96653541Sshin		im6o.im6o_multicast_loop = 0;
96753541Sshin	}
96853541Sshin
96953541Sshin	icmp6len = sizeof(*nd_na);
97053541Sshin	m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
971276692Srwatson	m->m_data += max_linkhdr;	/* or M_ALIGN() equivalent? */
97253541Sshin
97353541Sshin	/* fill neighbor advertisement packet */
97453541Sshin	ip6 = mtod(m, struct ip6_hdr *);
97553541Sshin	ip6->ip6_flow = 0;
97662587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
97762587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
97853541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
97953541Sshin	ip6->ip6_hlim = 255;
980148385Sume	if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
98153541Sshin		/* reply to DAD */
982153227Sume		daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
983153227Sume		daddr6.s6_addr16[1] = 0;
984153227Sume		daddr6.s6_addr32[1] = 0;
985153227Sume		daddr6.s6_addr32[2] = 0;
986153227Sume		daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
987148385Sume		if (in6_setscope(&daddr6, ifp, NULL))
988148385Sume			goto bad;
989148385Sume
99053541Sshin		flags &= ~ND_NA_FLAG_SOLICITED;
991148385Sume	}
992148385Sume	ip6->ip6_dst = daddr6;
99353541Sshin
99453541Sshin	/*
99553541Sshin	 * Select a source whose scope is the same as that of the dest.
99653541Sshin	 */
997293633Smelifaro	in6_splitscope(&daddr6, &dst6, &scopeid);
998317067Sasomers	error = in6_selectsrc_addr(fibnum, &dst6,
999293633Smelifaro	    scopeid, ifp, &src6, NULL);
1000194777Sbz	if (error) {
1001165118Sbz		char ip6buf[INET6_ADDRSTRLEN];
1002148385Sume		nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
1003148385Sume		    "determined: dst=%s, error=%d\n",
1004293633Smelifaro		    ip6_sprintf(ip6buf, &daddr6), error));
1005148385Sume		goto bad;
100653541Sshin	}
1007293633Smelifaro	ip6->ip6_src = src6;
100853541Sshin	nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
100953541Sshin	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
101053541Sshin	nd_na->nd_na_code = 0;
101153541Sshin	nd_na->nd_na_target = *taddr6;
1012121315Sume	in6_clearscope(&nd_na->nd_na_target); /* XXX */
101353541Sshin
101453541Sshin	/*
101553541Sshin	 * "tlladdr" indicates NS's condition for adding tlladdr or not.
101653541Sshin	 * see nd6_ns_input() for details.
101753541Sshin	 * Basically, if NS packet is sent to unicast/anycast addr,
101853541Sshin	 * target lladdr option SHOULD NOT be included.
101953541Sshin	 */
102062587Sitojun	if (tlladdr) {
102162587Sitojun		/*
102262587Sitojun		 * sdl0 != NULL indicates proxy NA.  If we do proxy, use
102362587Sitojun		 * lladdr in sdl0.  If we are not proxying (sending NA for
102462587Sitojun		 * my address) use lladdr configured for the interface.
102562587Sitojun		 */
1026142215Sglebius		if (sdl0 == NULL) {
1027142215Sglebius			if (ifp->if_carp)
1028211157Swill				mac = (*carp_macmatch6_p)(ifp, m, taddr6);
1029142215Sglebius			if (mac == NULL)
1030142215Sglebius				mac = nd6_ifptomac(ifp);
1031142215Sglebius		} else if (sdl0->sa_family == AF_LINK) {
103262587Sitojun			struct sockaddr_dl *sdl;
103362587Sitojun			sdl = (struct sockaddr_dl *)sdl0;
103462587Sitojun			if (sdl->sdl_alen == ifp->if_addrlen)
103562587Sitojun				mac = LLADDR(sdl);
103662587Sitojun		}
103762587Sitojun	}
103862587Sitojun	if (tlladdr && mac) {
103953541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
104053541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
1041120941Sume
104253541Sshin		/* roundup to 8 bytes alignment! */
104353541Sshin		optlen = (optlen + 7) & ~7;
104453541Sshin
104553541Sshin		m->m_pkthdr.len += optlen;
104653541Sshin		m->m_len += optlen;
104753541Sshin		icmp6len += optlen;
104853541Sshin		bzero((caddr_t)nd_opt, optlen);
104953541Sshin		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
105053541Sshin		nd_opt->nd_opt_len = optlen >> 3;
105153541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
105253541Sshin	} else
105353541Sshin		flags &= ~ND_NA_FLAG_OVERRIDE;
105453541Sshin
105553541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
105653541Sshin	nd_na->nd_na_flags_reserved = flags;
105753541Sshin	nd_na->nd_na_cksum = 0;
105853541Sshin	nd_na->nd_na_cksum =
1059120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
106053541Sshin
1061211501Sanchie	if (send_sendso_input_hook != NULL) {
1062211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
1063211501Sanchie		    sizeof(unsigned short), M_NOWAIT);
1064211501Sanchie		if (mtag == NULL)
1065211501Sanchie			goto bad;
1066211501Sanchie		*(unsigned short *)(mtag + 1) = nd_na->nd_na_type;
1067211501Sanchie		m_tag_prepend(m, mtag);
1068211501Sanchie	}
1069211501Sanchie
1070293101Smelifaro	ip6_output(m, NULL, NULL, 0, &im6o, NULL, NULL);
1071148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
1072148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
1073190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);
1074148385Sume
1075148385Sume	return;
1076148385Sume
1077148385Sume  bad:
1078148385Sume	m_freem(m);
107953541Sshin}
108053541Sshin
1081231852Sbz#ifndef BURN_BRIDGES
1082231852Sbzvoid
1083231852Sbznd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
1084231852Sbz    const struct in6_addr *taddr6, u_long flags, int tlladdr,
1085231852Sbz    struct sockaddr *sdl0)
1086231852Sbz{
1087231852Sbz
1088231852Sbz	nd6_na_output_fib(ifp, daddr6_0, taddr6, flags, tlladdr, sdl0,
1089231852Sbz	    RT_DEFAULT_FIB);
1090231852Sbz}
1091231852Sbz#endif
1092231852Sbz
109353541Sshincaddr_t
1094171259Sdelphijnd6_ifptomac(struct ifnet *ifp)
109553541Sshin{
109653541Sshin	switch (ifp->if_type) {
109753541Sshin	case IFT_ARCNET:
109853541Sshin	case IFT_ETHER:
109953541Sshin	case IFT_FDDI:
110078064Sume	case IFT_IEEE1394:
110178468Ssumikawa	case IFT_L2VLAN:
110278064Sume	case IFT_IEEE80211:
1103219819Sjeff	case IFT_INFINIBAND:
1104149829Sthompsa	case IFT_BRIDGE:
1105120049Smdodd	case IFT_ISO88025:
1106147306Sbrooks		return IF_LLADDR(ifp);
110753541Sshin	default:
110853541Sshin		return NULL;
110953541Sshin	}
111053541Sshin}
111153541Sshin
111253541Sshinstruct dadq {
111360938Sjake	TAILQ_ENTRY(dadq) dad_list;
111453541Sshin	struct ifaddr *dad_ifa;
111553541Sshin	int dad_count;		/* max NS to send */
111662587Sitojun	int dad_ns_tcount;	/* # of trials to send NS */
111753541Sshin	int dad_ns_ocount;	/* NS sent so far */
111853541Sshin	int dad_ns_icount;
111953541Sshin	int dad_na_icount;
1120279531Shrs	int dad_ns_lcount;	/* looped back NS */
1121279676Shrs	int dad_loopbackprobe;	/* probing state for loopback detection */
112278064Sume	struct callout dad_timer_ch;
1123191816Szec	struct vnet *dad_vnet;
1124275593Smarkj	u_int dad_refcnt;
1125279531Shrs#define	ND_OPT_NONCE_LEN32 \
1126279531Shrs		((ND_OPT_NONCE_LEN + sizeof(uint32_t) - 1)/sizeof(uint32_t))
1127279531Shrs	uint32_t dad_nonce[ND_OPT_NONCE_LEN32];
1128332819Sjtl	bool dad_ondadq;	/* on dadq? Protected by DADQ_WLOCK. */
112953541Sshin};
113053541Sshin
1131215701Sdimstatic VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
1132266857Shrsstatic VNET_DEFINE(struct rwlock, dad_rwlock);
1133266857Shrs#define	V_dadq			VNET(dadq)
1134266857Shrs#define	V_dad_rwlock		VNET(dad_rwlock)
1135195699Srwatson
1136266857Shrs#define	DADQ_RLOCK()		rw_rlock(&V_dad_rwlock)
1137266857Shrs#define	DADQ_RUNLOCK()		rw_runlock(&V_dad_rwlock)
1138266857Shrs#define	DADQ_WLOCK()		rw_wlock(&V_dad_rwlock)
1139266857Shrs#define	DADQ_WUNLOCK()		rw_wunlock(&V_dad_rwlock)
1140266857Shrs
1141274347Smelifarostatic void
1142274347Smelifarond6_dad_add(struct dadq *dp)
1143274347Smelifaro{
1144274347Smelifaro
1145274347Smelifaro	DADQ_WLOCK();
1146275593Smarkj	TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list);
1147332819Sjtl	dp->dad_ondadq = true;
1148274347Smelifaro	DADQ_WUNLOCK();
1149274347Smelifaro}
1150274347Smelifaro
1151274347Smelifarostatic void
1152274347Smelifarond6_dad_del(struct dadq *dp)
1153274347Smelifaro{
1154274347Smelifaro
1155274347Smelifaro	DADQ_WLOCK();
1156332819Sjtl	if (dp->dad_ondadq) {
1157332819Sjtl		/*
1158332819Sjtl		 * Remove dp from the dadq and release the dadq's
1159332819Sjtl		 * reference.
1160332819Sjtl		 */
1161332819Sjtl		TAILQ_REMOVE(&V_dadq, dp, dad_list);
1162332819Sjtl		dp->dad_ondadq = false;
1163332819Sjtl		DADQ_WUNLOCK();
1164332819Sjtl		nd6_dad_rele(dp);
1165332819Sjtl	} else
1166332819Sjtl		DADQ_WUNLOCK();
1167274347Smelifaro}
1168274347Smelifaro
116953541Sshinstatic struct dadq *
1170279531Shrsnd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n)
117153541Sshin{
117253541Sshin	struct dadq *dp;
117353541Sshin
1174266857Shrs	DADQ_RLOCK();
1175279531Shrs	TAILQ_FOREACH(dp, &V_dadq, dad_list) {
1176279531Shrs		if (dp->dad_ifa != ifa)
1177279531Shrs			continue;
1178279531Shrs		/*
1179279531Shrs		 * Skip if the nonce matches the received one.
1180279531Shrs		 * +2 in the length is required because of type and
1181279531Shrs		 * length fields are included in a header.
1182279531Shrs		 */
1183279531Shrs		if (n != NULL &&
1184279531Shrs		    n->nd_opt_nonce_len == (ND_OPT_NONCE_LEN + 2) / 8 &&
1185279531Shrs		    memcmp(&n->nd_opt_nonce[0], &dp->dad_nonce[0],
1186279531Shrs		        ND_OPT_NONCE_LEN) == 0) {
1187279531Shrs			dp->dad_ns_lcount++;
1188279531Shrs			continue;
1189275593Smarkj		}
1190279531Shrs		refcount_acquire(&dp->dad_refcnt);
1191279531Shrs		break;
1192279531Shrs	}
1193266857Shrs	DADQ_RUNLOCK();
1194226340Sglebius
1195275700Smarkj	return (dp);
119653541Sshin}
119753541Sshin
119878064Sumestatic void
1199288600Shrsnd6_dad_starttimer(struct dadq *dp, int ticks, int send_ns)
120078064Sume{
120178064Sume
1202288600Shrs	if (send_ns != 0)
1203288600Shrs		nd6_dad_ns_output(dp);
120478064Sume	callout_reset(&dp->dad_timer_ch, ticks,
1205191816Szec	    (void (*)(void *))nd6_dad_timer, (void *)dp);
120678064Sume}
120778064Sume
120878064Sumestatic void
1209171259Sdelphijnd6_dad_stoptimer(struct dadq *dp)
121078064Sume{
121178064Sume
1212275593Smarkj	callout_drain(&dp->dad_timer_ch);
121378064Sume}
121478064Sume
1215275593Smarkjstatic void
1216275593Smarkjnd6_dad_rele(struct dadq *dp)
1217275593Smarkj{
1218275593Smarkj
1219275593Smarkj	if (refcount_release(&dp->dad_refcnt)) {
1220275593Smarkj		ifa_free(dp->dad_ifa);
1221275593Smarkj		free(dp, M_IP6NDP);
1222275593Smarkj	}
1223275593Smarkj}
1224275593Smarkj
1225275593Smarkjvoid
1226275593Smarkjnd6_dad_init(void)
1227275593Smarkj{
1228275593Smarkj
1229275593Smarkj	rw_init(&V_dad_rwlock, "nd6 DAD queue");
1230275593Smarkj	TAILQ_INIT(&V_dadq);
1231275593Smarkj}
1232275593Smarkj
123353541Sshin/*
1234148987Sume * Start Duplicate Address Detection (DAD) for specified interface address.
123553541Sshin */
123653541Sshinvoid
1237171259Sdelphijnd6_dad_start(struct ifaddr *ifa, int delay)
123853541Sshin{
123953541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
124053541Sshin	struct dadq *dp;
1241165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
124253541Sshin
124353541Sshin	/*
124453541Sshin	 * If we don't need DAD, don't do it.
124553541Sshin	 * There are several cases:
124653541Sshin	 * - DAD is disabled (ip6_dad_count == 0)
124753541Sshin	 * - the interface address is anycast
124853541Sshin	 */
124953541Sshin	if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
125062587Sitojun		log(LOG_DEBUG,
125162587Sitojun			"nd6_dad_start: called with non-tentative address "
125253541Sshin			"%s(%s)\n",
1253165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
125453541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
125553541Sshin		return;
125653541Sshin	}
125753541Sshin	if (ia->ia6_flags & IN6_IFF_ANYCAST) {
125853541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
125953541Sshin		return;
126053541Sshin	}
1261181803Sbz	if (!V_ip6_dad_count) {
126253541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
126353541Sshin		return;
126453541Sshin	}
1265151465Ssuz	if (ifa->ifa_ifp == NULL)
126653541Sshin		panic("nd6_dad_start: ifa->ifa_ifp == NULL");
1267287094Shrs	if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) {
1268287094Shrs		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
126953541Sshin		return;
1270120941Sume	}
1271287094Shrs	if (!(ifa->ifa_ifp->if_flags & IFF_UP) ||
1272287094Shrs	    !(ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) ||
1273287094Shrs	    (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)) {
1274287094Shrs		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1275197138Shrs		return;
1276287094Shrs	}
1277279531Shrs	if ((dp = nd6_dad_find(ifa, NULL)) != NULL) {
1278288600Shrs		/*
1279295732Smarkj		 * DAD is already in progress.  Let the existing entry
1280295732Smarkj		 * finish it.
1281288600Shrs		 */
1282295732Smarkj		nd6_dad_rele(dp);
128353541Sshin		return;
128453541Sshin	}
128553541Sshin
1286275593Smarkj	dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
128753541Sshin	if (dp == NULL) {
128862587Sitojun		log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
128953541Sshin			"%s(%s)\n",
1290165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
129153541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
129253541Sshin		return;
129353541Sshin	}
129478064Sume	callout_init(&dp->dad_timer_ch, 0);
1295191816Szec#ifdef VIMAGE
1296191816Szec	dp->dad_vnet = curvnet;
1297191816Szec#endif
129878064Sume	nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1299165118Sbz	    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
130053541Sshin
130153541Sshin	/*
130253541Sshin	 * Send NS packet for DAD, ip6_dad_count times.
130353541Sshin	 * Note that we must delay the first transmission, if this is the
130453541Sshin	 * first packet to be sent from the interface after interface
130553541Sshin	 * (re)initialization.
130653541Sshin	 */
130753541Sshin	dp->dad_ifa = ifa;
1308275593Smarkj	ifa_ref(dp->dad_ifa);
1309181803Sbz	dp->dad_count = V_ip6_dad_count;
131053541Sshin	dp->dad_ns_icount = dp->dad_na_icount = 0;
131162587Sitojun	dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1312279676Shrs	dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
1313332819Sjtl
1314332819Sjtl	/* Add this to the dadq and add a reference for the dadq. */
1315275593Smarkj	refcount_init(&dp->dad_refcnt, 1);
1316274347Smelifaro	nd6_dad_add(dp);
1317301213Smarkj	nd6_dad_starttimer(dp, delay, 0);
131853541Sshin}
131953541Sshin
132078064Sume/*
132178064Sume * terminate DAD unconditionally.  used for address removals.
132278064Sume */
132378064Sumevoid
1324171259Sdelphijnd6_dad_stop(struct ifaddr *ifa)
132578064Sume{
132678064Sume	struct dadq *dp;
132778064Sume
1328279531Shrs	dp = nd6_dad_find(ifa, NULL);
132978064Sume	if (!dp) {
133078064Sume		/* DAD wasn't started yet */
133178064Sume		return;
133278064Sume	}
133378064Sume
133478064Sume	nd6_dad_stoptimer(dp);
1335332819Sjtl	nd6_dad_del(dp);
133678064Sume
1337332819Sjtl	/* Release this function's reference, acquired by nd6_dad_find(). */
1338275593Smarkj	nd6_dad_rele(dp);
133978064Sume}
134078064Sume
134153541Sshinstatic void
1342191816Szecnd6_dad_timer(struct dadq *dp)
134353541Sshin{
1344183550Szec	CURVNET_SET(dp->dad_vnet);
1345191816Szec	struct ifaddr *ifa = dp->dad_ifa;
1346266248Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
134753541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1348165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
134953541Sshin
135053541Sshin	/* Sanity check */
135153541Sshin	if (ia == NULL) {
135262587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1353275593Smarkj		goto err;
135453541Sshin	}
1355266248Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
1356266248Shrs		/* Do not need DAD for ifdisabled interface. */
1357266248Shrs		log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of "
1358266248Shrs		    "ND6_IFF_IFDISABLED.\n", ifp->if_xname);
1359275593Smarkj		goto err;
1360266248Shrs	}
136153541Sshin	if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
136262587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
136353541Sshin			"%s(%s)\n",
1364165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
136553541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1366275593Smarkj		goto err;
136753541Sshin	}
136853541Sshin	if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
136962587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
137053541Sshin			"%s(%s)\n",
1371165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
137253541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1373275593Smarkj		goto err;
137453541Sshin	}
137553541Sshin
1376279676Shrs	/* Stop DAD if the interface is down even after dad_maxtry attempts. */
1377279676Shrs	if ((dp->dad_ns_tcount > V_dad_maxtry) &&
1378279676Shrs	    (((ifp->if_flags & IFF_UP) == 0) ||
1379279676Shrs	     ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) {
1380288600Shrs		nd6log((LOG_INFO, "%s: could not run DAD "
1381288600Shrs		    "because the interface was down or not running.\n",
1382120941Sume		    if_name(ifa->ifa_ifp)));
1383275593Smarkj		goto err;
138462587Sitojun	}
138562587Sitojun
138653541Sshin	/* Need more checks? */
138753541Sshin	if (dp->dad_ns_ocount < dp->dad_count) {
138853541Sshin		/*
138953541Sshin		 * We have more NS to go.  Send NS packet for DAD.
139053541Sshin		 */
1391120941Sume		nd6_dad_starttimer(dp,
1392288600Shrs		    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1);
1393275593Smarkj		goto done;
139453541Sshin	} else {
139553541Sshin		/*
139653541Sshin		 * We have transmitted sufficient number of DAD packets.
139753541Sshin		 * See what we've got.
139853541Sshin		 */
1399275593Smarkj		if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0)
1400275593Smarkj			/* We've seen NS or NA, means DAD has failed. */
1401274347Smelifaro			nd6_dad_duplicated(ifa, dp);
1402279676Shrs		else if (V_dad_enhanced != 0 &&
1403279676Shrs		    dp->dad_ns_lcount > 0 &&
1404279676Shrs		    dp->dad_ns_lcount > dp->dad_loopbackprobe) {
140553541Sshin			/*
1406282805Shrs			 * Sec. 4.1 in RFC 7527 requires transmission of
1407282805Shrs			 * additional probes until the loopback condition
1408282805Shrs			 * becomes clear when a looped back probe is detected.
1409279676Shrs			 */
1410279676Shrs			log(LOG_ERR, "%s: a looped back NS message is "
1411279676Shrs			    "detected during DAD for %s.  "
1412279676Shrs			    "Another DAD probes are being sent.\n",
1413279676Shrs			    if_name(ifa->ifa_ifp),
1414279676Shrs			    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
1415279676Shrs			dp->dad_loopbackprobe = dp->dad_ns_lcount;
1416279676Shrs			/*
1417279676Shrs			 * Send an NS immediately and increase dad_count by
1418279676Shrs			 * V_nd6_mmaxtries - 1.
1419279676Shrs			 */
1420279676Shrs			dp->dad_count =
1421279676Shrs			    dp->dad_ns_ocount + V_nd6_mmaxtries - 1;
1422279676Shrs			nd6_dad_starttimer(dp,
1423288600Shrs			    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000,
1424288600Shrs			    1);
1425279676Shrs			goto done;
1426279676Shrs		} else {
1427279676Shrs			/*
142853541Sshin			 * We are done with DAD.  No NA came, no NS came.
1429266248Shrs			 * No duplicate address found.  Check IFDISABLED flag
1430266248Shrs			 * again in case that it is changed between the
1431266248Shrs			 * beginning of this function and here.
143253541Sshin			 */
1433266248Shrs			if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0)
1434266248Shrs				ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
143553541Sshin
143678064Sume			nd6log((LOG_DEBUG,
143762587Sitojun			    "%s: DAD complete for %s - no duplicates found\n",
143862587Sitojun			    if_name(ifa->ifa_ifp),
1439165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
1440279676Shrs			if (dp->dad_ns_lcount > 0)
1441279676Shrs				log(LOG_ERR, "%s: DAD completed while "
1442279676Shrs				    "a looped back NS message is detected "
1443279676Shrs				    "during DAD for %s.\n",
1444279676Shrs				    if_name(ifa->ifa_ifp),
1445279676Shrs				    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
144653541Sshin		}
144753541Sshin	}
1448275593Smarkjerr:
1449275593Smarkj	nd6_dad_del(dp);
145053541Sshindone:
1451183550Szec	CURVNET_RESTORE();
145253541Sshin}
145353541Sshin
1454275593Smarkjstatic void
1455274347Smelifarond6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
145653541Sshin{
145753541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1458151477Ssuz	struct ifnet *ifp;
1459165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
146053541Sshin
146178064Sume	log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
1462279531Shrs	    "NS in/out/loopback=%d/%d/%d, NA in=%d\n",
1463165118Sbz	    if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
1464279531Shrs	    dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount,
1465279531Shrs	    dp->dad_na_icount);
146653541Sshin
146753541Sshin	ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
146853541Sshin	ia->ia6_flags |= IN6_IFF_DUPLICATED;
146953541Sshin
1470151477Ssuz	ifp = ifa->ifa_ifp;
147162587Sitojun	log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
1472165118Sbz	    if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr));
147362587Sitojun	log(LOG_ERR, "%s: manual intervention required\n",
1474151477Ssuz	    if_name(ifp));
147553541Sshin
1476151477Ssuz	/*
1477151477Ssuz	 * If the address is a link-local address formed from an interface
1478151477Ssuz	 * identifier based on the hardware address which is supposed to be
1479151477Ssuz	 * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
1480151477Ssuz	 * operation on the interface SHOULD be disabled.
1481197138Shrs	 * [RFC 4862, Section 5.4.5]
1482151477Ssuz	 */
1483151477Ssuz	if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
1484151477Ssuz		struct in6_addr in6;
1485151477Ssuz
1486151477Ssuz		/*
1487151477Ssuz		 * To avoid over-reaction, we only apply this logic when we are
1488151477Ssuz		 * very sure that hardware addresses are supposed to be unique.
1489151477Ssuz		 */
1490151477Ssuz		switch (ifp->if_type) {
1491151477Ssuz		case IFT_ETHER:
1492151477Ssuz		case IFT_FDDI:
1493151477Ssuz		case IFT_ATM:
1494151477Ssuz		case IFT_IEEE1394:
1495151477Ssuz		case IFT_IEEE80211:
1496219819Sjeff		case IFT_INFINIBAND:
1497151477Ssuz			in6 = ia->ia_addr.sin6_addr;
1498151477Ssuz			if (in6_get_hw_ifid(ifp, &in6) == 0 &&
1499151477Ssuz			    IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
1500151477Ssuz				ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1501151477Ssuz				log(LOG_ERR, "%s: possible hardware address "
1502151477Ssuz				    "duplication detected, disable IPv6\n",
1503151477Ssuz				    if_name(ifp));
1504151477Ssuz			}
1505151477Ssuz			break;
1506151477Ssuz		}
1507151477Ssuz	}
150853541Sshin}
150953541Sshin
151062587Sitojunstatic void
1511288600Shrsnd6_dad_ns_output(struct dadq *dp)
151262587Sitojun{
1513288600Shrs	struct in6_ifaddr *ia = (struct in6_ifaddr *)dp->dad_ifa;
1514288600Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
1515279531Shrs	int i;
151662587Sitojun
151762587Sitojun	dp->dad_ns_tcount++;
151862587Sitojun	if ((ifp->if_flags & IFF_UP) == 0) {
151962587Sitojun		return;
152062587Sitojun	}
1521148887Srwatson	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
152262587Sitojun		return;
152362587Sitojun	}
152462587Sitojun
152562587Sitojun	dp->dad_ns_ocount++;
1526279531Shrs	if (V_dad_enhanced != 0) {
1527279531Shrs		for (i = 0; i < ND_OPT_NONCE_LEN32; i++)
1528279531Shrs			dp->dad_nonce[i] = arc4random();
1529279531Shrs		/*
1530279531Shrs		 * XXXHRS: Note that in the case that
1531279531Shrs		 * DupAddrDetectTransmits > 1, multiple NS messages with
1532279531Shrs		 * different nonces can be looped back in an unexpected
1533279531Shrs		 * order.  The current implementation recognizes only
1534279531Shrs		 * the latest nonce on the sender side.  Practically it
1535279531Shrs		 * should work well in almost all cases.
1536279531Shrs		 */
1537279559Shrs	}
1538287484Smelifaro	nd6_ns_output(ifp, NULL, NULL, &ia->ia_addr.sin6_addr,
1539279559Shrs	    (uint8_t *)&dp->dad_nonce[0]);
154062587Sitojun}
154162587Sitojun
154262587Sitojunstatic void
1543279531Shrsnd6_dad_ns_input(struct ifaddr *ifa, struct nd_opt_nonce *ndopt_nonce)
154453541Sshin{
154553541Sshin	struct in6_ifaddr *ia;
154653541Sshin	struct ifnet *ifp;
154778064Sume	const struct in6_addr *taddr6;
154853541Sshin	struct dadq *dp;
154953541Sshin
1550151465Ssuz	if (ifa == NULL)
155153541Sshin		panic("ifa == NULL in nd6_dad_ns_input");
155253541Sshin
155353541Sshin	ia = (struct in6_ifaddr *)ifa;
155453541Sshin	ifp = ifa->ifa_ifp;
155553541Sshin	taddr6 = &ia->ia_addr.sin6_addr;
1556279531Shrs	/* Ignore Nonce option when Enhanced DAD is disabled. */
1557279531Shrs	if (V_dad_enhanced == 0)
1558279531Shrs		ndopt_nonce = NULL;
1559279531Shrs	dp = nd6_dad_find(ifa, ndopt_nonce);
1560275593Smarkj	if (dp == NULL)
1561275593Smarkj		return;
156253541Sshin
1563275593Smarkj	dp->dad_ns_icount++;
1564275593Smarkj	nd6_dad_rele(dp);
156553541Sshin}
156653541Sshin
156762587Sitojunstatic void
1568171259Sdelphijnd6_dad_na_input(struct ifaddr *ifa)
156953541Sshin{
157053541Sshin	struct dadq *dp;
157153541Sshin
1572151465Ssuz	if (ifa == NULL)
157353541Sshin		panic("ifa == NULL in nd6_dad_na_input");
157453541Sshin
1575279531Shrs	dp = nd6_dad_find(ifa, NULL);
1576275593Smarkj	if (dp != NULL) {
157753541Sshin		dp->dad_na_icount++;
1578275593Smarkj		nd6_dad_rele(dp);
1579275593Smarkj	}
158053541Sshin}
1581