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: releng/10.3/sys/netinet6/nd6_nbr.c 290348 2015-11-04 01:00:42Z hrs $");
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);
626148385Sume	return;
62753541Sshin}
62853541Sshin
629282622Shiren#ifndef BURN_BRIDGES
630282622Shirenvoid
631282622Shirennd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
632282622Shiren    const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce)
633282622Shiren{
634282622Shiren
635282622Shiren	nd6_ns_output_fib(ifp, daddr6, taddr6, ln, nonce, RT_DEFAULT_FIB);
636282622Shiren}
637282622Shiren#endif
63853541Sshin/*
63953541Sshin * Neighbor advertisement input handling.
64053541Sshin *
64153541Sshin * Based on RFC 2461
642148987Sume * Based on RFC 2462 (duplicate address detection)
64362587Sitojun *
64462587Sitojun * the following items are not implemented yet:
64562587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
64662587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
64753541Sshin */
64853541Sshinvoid
649171259Sdelphijnd6_na_input(struct mbuf *m, int off, int icmp6len)
65053541Sshin{
65153541Sshin	struct ifnet *ifp = m->m_pkthdr.rcvif;
65253541Sshin	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
65362587Sitojun	struct nd_neighbor_advert *nd_na;
65453541Sshin	struct in6_addr daddr6 = ip6->ip6_dst;
65562587Sitojun	struct in6_addr taddr6;
65662587Sitojun	int flags;
65762587Sitojun	int is_router;
65862587Sitojun	int is_solicited;
65962587Sitojun	int is_override;
66053541Sshin	char *lladdr = NULL;
66153541Sshin	int lladdrlen = 0;
662186468Skmacy	int checklink = 0;
66353541Sshin	struct ifaddr *ifa;
664186119Sqingli	struct llentry *ln = NULL;
66553541Sshin	union nd_opts ndopts;
666186119Sqingli	struct mbuf *chain = NULL;
667186119Sqingli	struct sockaddr_in6 sin6;
668165118Sbz	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
66953541Sshin
67053541Sshin	if (ip6->ip6_hlim != 255) {
67178064Sume		nd6log((LOG_ERR,
67278064Sume		    "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
673165118Sbz		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
674165118Sbz		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
67578064Sume		goto bad;
67662587Sitojun	}
67762587Sitojun
67862587Sitojun#ifndef PULLDOWN_TEST
67962587Sitojun	IP6_EXTHDR_CHECK(m, off, icmp6len,);
68062587Sitojun	nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
68162587Sitojun#else
68262587Sitojun	IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
68362587Sitojun	if (nd_na == NULL) {
684190964Srwatson		ICMP6STAT_INC(icp6s_tooshort);
68553541Sshin		return;
68653541Sshin	}
68762587Sitojun#endif
688148385Sume
68962587Sitojun	flags = nd_na->nd_na_flags_reserved;
69062587Sitojun	is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
69162587Sitojun	is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
69262587Sitojun	is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
693282622Shiren	memset(&sin6, 0, sizeof(sin6));
69453541Sshin
695148385Sume	taddr6 = nd_na->nd_na_target;
696148385Sume	if (in6_setscope(&taddr6, ifp, NULL))
697150202Ssuz		goto bad;	/* XXX: impossible */
69853541Sshin
69953541Sshin	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
70078064Sume		nd6log((LOG_ERR,
70153541Sshin		    "nd6_na_input: invalid target address %s\n",
702165118Sbz		    ip6_sprintf(ip6bufs, &taddr6)));
70378064Sume		goto bad;
70453541Sshin	}
70553541Sshin	if (IN6_IS_ADDR_MULTICAST(&daddr6))
70653541Sshin		if (is_solicited) {
70778064Sume			nd6log((LOG_ERR,
70878064Sume			    "nd6_na_input: a solicited adv is multicasted\n"));
70978064Sume			goto bad;
71053541Sshin		}
71153541Sshin
71253541Sshin	icmp6len -= sizeof(*nd_na);
71353541Sshin	nd6_option_init(nd_na + 1, icmp6len, &ndopts);
71453541Sshin	if (nd6_options(&ndopts) < 0) {
71578064Sume		nd6log((LOG_INFO,
71678064Sume		    "nd6_na_input: invalid ND option, ignored\n"));
71778064Sume		/* nd6_options have incremented stats */
71862587Sitojun		goto freeit;
71953541Sshin	}
72053541Sshin
72153541Sshin	if (ndopts.nd_opts_tgt_lladdr) {
72253541Sshin		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
72353541Sshin		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
72453541Sshin	}
72553541Sshin
726228571Sglebius	/*
727228571Sglebius	 * This effectively disables the DAD check on a non-master CARP
728228571Sglebius	 * address.
729228571Sglebius	 */
730228571Sglebius	if (ifp->if_carp)
731228571Sglebius		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
732228571Sglebius	else
733228571Sglebius		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
73453541Sshin
73553541Sshin	/*
73653541Sshin	 * Target address matches one of my interface address.
73753541Sshin	 *
73853541Sshin	 * If my address is tentative, this means that there's somebody
73953541Sshin	 * already using the same address as mine.  This indicates DAD failure.
74053541Sshin	 * This is defined in RFC 2462.
74153541Sshin	 *
74253541Sshin	 * Otherwise, process as defined in RFC 2461.
74353541Sshin	 */
74453541Sshin	if (ifa
74553541Sshin	 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
746280705Sae		nd6_dad_na_input(ifa);
747194760Srwatson		ifa_free(ifa);
74862587Sitojun		goto freeit;
74953541Sshin	}
75053541Sshin
75195023Ssuz	/* Just for safety, maybe unnecessary. */
75253541Sshin	if (ifa) {
753194760Srwatson		ifa_free(ifa);
75453541Sshin		log(LOG_ERR,
75553541Sshin		    "nd6_na_input: duplicate IP6 address %s\n",
756165118Sbz		    ip6_sprintf(ip6bufs, &taddr6));
75762587Sitojun		goto freeit;
75853541Sshin	}
75953541Sshin
76053541Sshin	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
761120941Sume		nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
762165118Sbz		    "(if %d, NA packet %d)\n", ip6_sprintf(ip6bufs, &taddr6),
763120941Sume		    ifp->if_addrlen, lladdrlen - 2));
76478064Sume		goto bad;
76553541Sshin	}
76653541Sshin
76753541Sshin	/*
768120941Sume	 * If no neighbor cache entry is found, NA SHOULD silently be
769120941Sume	 * discarded.
77053541Sshin	 */
771260504Sae	IF_AFDATA_RLOCK(ifp);
772186119Sqingli	ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
773260504Sae	IF_AFDATA_RUNLOCK(ifp);
774186119Sqingli	if (ln == NULL) {
77562587Sitojun		goto freeit;
776186119Sqingli	}
77753541Sshin
77853541Sshin	if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
77953541Sshin		/*
78053541Sshin		 * If the link-layer has address, and no lladdr option came,
78153541Sshin		 * discard the packet.
78253541Sshin		 */
783186119Sqingli		if (ifp->if_addrlen && lladdr == NULL) {
78462587Sitojun			goto freeit;
785186119Sqingli		}
78653541Sshin
78753541Sshin		/*
78853541Sshin		 * Record link-layer address, and update the state.
78953541Sshin		 */
790186119Sqingli		bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
791186119Sqingli		ln->la_flags |= LLE_VALID;
792245925Snp		EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
79353541Sshin		if (is_solicited) {
79453541Sshin			ln->ln_state = ND6_LLINFO_REACHABLE;
79562587Sitojun			ln->ln_byhint = 0;
796151539Ssuz			if (!ND6_LLINFO_PERMANENT(ln)) {
797186119Sqingli				nd6_llinfo_settimer_locked(ln,
798186119Sqingli				    (long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
799120941Sume			}
80078064Sume		} else {
80153541Sshin			ln->ln_state = ND6_LLINFO_STALE;
802186119Sqingli			nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
80378064Sume		}
80478064Sume		if ((ln->ln_router = is_router) != 0) {
80578064Sume			/*
80678064Sume			 * This means a router's state has changed from
80778064Sume			 * non-reachable to probably reachable, and might
80878064Sume			 * affect the status of associated prefixes..
80978064Sume			 */
810186468Skmacy			checklink = 1;
81178064Sume		}
81253541Sshin	} else {
81353541Sshin		int llchange;
81453541Sshin
81553541Sshin		/*
81653541Sshin		 * Check if the link-layer address has changed or not.
81753541Sshin		 */
818151465Ssuz		if (lladdr == NULL)
81953541Sshin			llchange = 0;
82053541Sshin		else {
821186119Sqingli			if (ln->la_flags & LLE_VALID) {
822186119Sqingli				if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
82353541Sshin					llchange = 1;
82453541Sshin				else
82553541Sshin					llchange = 0;
82653541Sshin			} else
82753541Sshin				llchange = 1;
82853541Sshin		}
82953541Sshin
83053541Sshin		/*
83153541Sshin		 * This is VERY complex.  Look at it with care.
83253541Sshin		 *
83353541Sshin		 * override solicit lladdr llchange	action
83453541Sshin		 *					(L: record lladdr)
83553541Sshin		 *
83653541Sshin		 *	0	0	n	--	(2c)
83753541Sshin		 *	0	0	y	n	(2b) L
83853541Sshin		 *	0	0	y	y	(1)    REACHABLE->STALE
83953541Sshin		 *	0	1	n	--	(2c)   *->REACHABLE
84053541Sshin		 *	0	1	y	n	(2b) L *->REACHABLE
84153541Sshin		 *	0	1	y	y	(1)    REACHABLE->STALE
84253541Sshin		 *	1	0	n	--	(2a)
84353541Sshin		 *	1	0	y	n	(2a) L
84453541Sshin		 *	1	0	y	y	(2a) L *->STALE
84553541Sshin		 *	1	1	n	--	(2a)   *->REACHABLE
84653541Sshin		 *	1	1	y	n	(2a) L *->REACHABLE
84753541Sshin		 *	1	1	y	y	(2a) L *->REACHABLE
84853541Sshin		 */
849151539Ssuz		if (!is_override && (lladdr != NULL && llchange)) {  /* (1) */
85053541Sshin			/*
85153541Sshin			 * If state is REACHABLE, make it STALE.
85253541Sshin			 * no other updates should be done.
85353541Sshin			 */
85478064Sume			if (ln->ln_state == ND6_LLINFO_REACHABLE) {
85553541Sshin				ln->ln_state = ND6_LLINFO_STALE;
856186119Sqingli				nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
85778064Sume			}
85862587Sitojun			goto freeit;
85953541Sshin		} else if (is_override				   /* (2a) */
860151465Ssuz			|| (!is_override && (lladdr != NULL && !llchange)) /* (2b) */
861151465Ssuz			|| lladdr == NULL) {			   /* (2c) */
86253541Sshin			/*
86353541Sshin			 * Update link-local address, if any.
86453541Sshin			 */
865151465Ssuz			if (lladdr != NULL) {
866186119Sqingli				bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
867186119Sqingli				ln->la_flags |= LLE_VALID;
868245925Snp				EVENTHANDLER_INVOKE(lle_event, ln,
869245925Snp				    LLENTRY_RESOLVED);
87053541Sshin			}
87153541Sshin
87253541Sshin			/*
87353541Sshin			 * If solicited, make the state REACHABLE.
87453541Sshin			 * If not solicited and the link-layer address was
87553541Sshin			 * changed, make it STALE.
87653541Sshin			 */
87753541Sshin			if (is_solicited) {
87853541Sshin				ln->ln_state = ND6_LLINFO_REACHABLE;
87962587Sitojun				ln->ln_byhint = 0;
880151539Ssuz				if (!ND6_LLINFO_PERMANENT(ln)) {
881186119Sqingli					nd6_llinfo_settimer_locked(ln,
882151539Ssuz					    (long)ND_IFINFO(ifp)->reachable * hz);
88353541Sshin				}
88453541Sshin			} else {
885151465Ssuz				if (lladdr != NULL && llchange) {
88653541Sshin					ln->ln_state = ND6_LLINFO_STALE;
887186119Sqingli					nd6_llinfo_settimer_locked(ln,
888181803Sbz					    (long)V_nd6_gctimer * hz);
88978064Sume				}
89053541Sshin			}
89153541Sshin		}
89253541Sshin
89353541Sshin		if (ln->ln_router && !is_router) {
89453541Sshin			/*
89553541Sshin			 * The peer dropped the router flag.
89653541Sshin			 * Remove the sender from the Default Router List and
89753541Sshin			 * update the Destination Cache entries.
89853541Sshin			 */
89953541Sshin			struct nd_defrouter *dr;
90053541Sshin			struct in6_addr *in6;
90153541Sshin
902186119Sqingli			in6 = &L3_ADDR_SIN6(ln)->sin6_addr;
90395023Ssuz
90495023Ssuz			/*
90595023Ssuz			 * Lock to protect the default router list.
90695023Ssuz			 * XXX: this might be unnecessary, since this function
90795023Ssuz			 * is only called under the network software interrupt
908120941Sume			 * context.  However, we keep it just for safety.
90995023Ssuz			 */
910186119Sqingli			dr = defrouter_lookup(in6, ln->lle_tbl->llt_ifp);
91153541Sshin			if (dr)
91253541Sshin				defrtrlist_del(dr);
913222728Shrs			else if (ND_IFINFO(ln->lle_tbl->llt_ifp)->flags &
914222728Shrs			    ND6_IFF_ACCEPT_RTADV) {
91553541Sshin				/*
91653541Sshin				 * Even if the neighbor is not in the default
91753541Sshin				 * router list, the neighbor may be used
91853541Sshin				 * as a next hop for some destinations
91953541Sshin				 * (e.g. redirect case). So we must
92053541Sshin				 * call rt6_flush explicitly.
92153541Sshin				 */
922128422Sluigi				rt6_flush(&ip6->ip6_src, ifp);
92353541Sshin			}
92453541Sshin		}
92553541Sshin		ln->ln_router = is_router;
92653541Sshin	}
927186119Sqingli        /* XXX - QL
928186119Sqingli	 *  Does this matter?
929186119Sqingli	 *  rt->rt_flags &= ~RTF_REJECT;
930186119Sqingli	 */
931186119Sqingli	ln->la_asked = 0;
932282622Shiren	if (ln->la_hold != NULL)
933282622Shiren		nd6_grab_holdchain(ln, &chain, &sin6);
934186119Sqingli freeit:
935282622Shiren	if (ln != NULL)
936186119Sqingli		LLE_WUNLOCK(ln);
93762587Sitojun
938282622Shiren	if (chain != NULL)
939282622Shiren		nd6_flush_holdchain(ifp, ifp, chain, &sin6);
940282622Shiren
941186468Skmacy	if (checklink)
942186468Skmacy		pfxlist_onlink_check();
943186468Skmacy
94462587Sitojun	m_freem(m);
94578064Sume	return;
94678064Sume
94778064Sume bad:
948186160Skmacy	if (ln != NULL)
949186119Sqingli		LLE_WUNLOCK(ln);
950186119Sqingli
951190964Srwatson	ICMP6STAT_INC(icp6s_badna);
95278064Sume	m_freem(m);
95353541Sshin}
95453541Sshin
95553541Sshin/*
95653541Sshin * Neighbor advertisement output handling.
95753541Sshin *
95853541Sshin * Based on RFC 2461
95953541Sshin *
96062587Sitojun * the following items are not implemented yet:
96162587Sitojun * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
96262587Sitojun * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
963171259Sdelphij *
964171259Sdelphij * tlladdr - 1 if include target link-layer address
965171259Sdelphij * sdl0 - sockaddr_dl (= proxy NA) or NULL
96653541Sshin */
967231852Sbzstatic void
968231852Sbznd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
969171259Sdelphij    const struct in6_addr *taddr6, u_long flags, int tlladdr,
970231852Sbz    struct sockaddr *sdl0, u_int fibnum)
97153541Sshin{
97253541Sshin	struct mbuf *m;
973211501Sanchie	struct m_tag *mtag;
974231852Sbz	struct ifnet *oifp;
97553541Sshin	struct ip6_hdr *ip6;
97653541Sshin	struct nd_neighbor_advert *nd_na;
97753541Sshin	struct ip6_moptions im6o;
978194777Sbz	struct in6_addr src, daddr6;
979148385Sume	struct sockaddr_in6 dst_sa;
980148385Sume	int icmp6len, maxlen, error;
98192733Speter	caddr_t mac = NULL;
982148385Sume	struct route_in6 ro;
98362587Sitojun
984148385Sume	bzero(&ro, sizeof(ro));
985148385Sume
986148385Sume	daddr6 = *daddr6_0;	/* make a local copy for modification */
987148385Sume
98862587Sitojun	/* estimate the size of message */
98962587Sitojun	maxlen = sizeof(*ip6) + sizeof(*nd_na);
99062587Sitojun	maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
991281866Sae	KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
992281866Sae	    "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
993281866Sae	    __func__, max_linkhdr, maxlen, MCLBYTES));
99453541Sshin
995248328Sglebius	if (max_linkhdr + maxlen > MHLEN)
996248328Sglebius		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
997248328Sglebius	else
998248328Sglebius		m = m_gethdr(M_NOWAIT, MT_DATA);
99962587Sitojun	if (m == NULL)
100062587Sitojun		return;
1001231852Sbz	M_SETFIB(m, fibnum);
100262587Sitojun
1003148385Sume	if (IN6_IS_ADDR_MULTICAST(&daddr6)) {
100453541Sshin		m->m_flags |= M_MCAST;
100553541Sshin		im6o.im6o_multicast_ifp = ifp;
100653541Sshin		im6o.im6o_multicast_hlim = 255;
100753541Sshin		im6o.im6o_multicast_loop = 0;
100853541Sshin	}
100953541Sshin
101053541Sshin	icmp6len = sizeof(*nd_na);
101153541Sshin	m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
101295023Ssuz	m->m_data += max_linkhdr;	/* or MH_ALIGN() equivalent? */
101353541Sshin
101453541Sshin	/* fill neighbor advertisement packet */
101553541Sshin	ip6 = mtod(m, struct ip6_hdr *);
101653541Sshin	ip6->ip6_flow = 0;
101762587Sitojun	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
101862587Sitojun	ip6->ip6_vfc |= IPV6_VERSION;
101953541Sshin	ip6->ip6_nxt = IPPROTO_ICMPV6;
102053541Sshin	ip6->ip6_hlim = 255;
1021148385Sume	if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
102253541Sshin		/* reply to DAD */
1023153227Sume		daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
1024153227Sume		daddr6.s6_addr16[1] = 0;
1025153227Sume		daddr6.s6_addr32[1] = 0;
1026153227Sume		daddr6.s6_addr32[2] = 0;
1027153227Sume		daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
1028148385Sume		if (in6_setscope(&daddr6, ifp, NULL))
1029148385Sume			goto bad;
1030148385Sume
103153541Sshin		flags &= ~ND_NA_FLAG_SOLICITED;
1032148385Sume	}
1033148385Sume	ip6->ip6_dst = daddr6;
1034148385Sume	bzero(&dst_sa, sizeof(struct sockaddr_in6));
1035148385Sume	dst_sa.sin6_family = AF_INET6;
1036148385Sume	dst_sa.sin6_len = sizeof(struct sockaddr_in6);
1037148385Sume	dst_sa.sin6_addr = daddr6;
103853541Sshin
103953541Sshin	/*
104053541Sshin	 * Select a source whose scope is the same as that of the dest.
104153541Sshin	 */
1042148385Sume	bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
1043231852Sbz	oifp = ifp;
1044231852Sbz	error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src);
1045194777Sbz	if (error) {
1046165118Sbz		char ip6buf[INET6_ADDRSTRLEN];
1047148385Sume		nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
1048148385Sume		    "determined: dst=%s, error=%d\n",
1049165118Sbz		    ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error));
1050148385Sume		goto bad;
105153541Sshin	}
1052194777Sbz	ip6->ip6_src = src;
105353541Sshin	nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
105453541Sshin	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
105553541Sshin	nd_na->nd_na_code = 0;
105653541Sshin	nd_na->nd_na_target = *taddr6;
1057121315Sume	in6_clearscope(&nd_na->nd_na_target); /* XXX */
105853541Sshin
105953541Sshin	/*
106053541Sshin	 * "tlladdr" indicates NS's condition for adding tlladdr or not.
106153541Sshin	 * see nd6_ns_input() for details.
106253541Sshin	 * Basically, if NS packet is sent to unicast/anycast addr,
106353541Sshin	 * target lladdr option SHOULD NOT be included.
106453541Sshin	 */
106562587Sitojun	if (tlladdr) {
106662587Sitojun		/*
106762587Sitojun		 * sdl0 != NULL indicates proxy NA.  If we do proxy, use
106862587Sitojun		 * lladdr in sdl0.  If we are not proxying (sending NA for
106962587Sitojun		 * my address) use lladdr configured for the interface.
107062587Sitojun		 */
1071142215Sglebius		if (sdl0 == NULL) {
1072142215Sglebius			if (ifp->if_carp)
1073211157Swill				mac = (*carp_macmatch6_p)(ifp, m, taddr6);
1074142215Sglebius			if (mac == NULL)
1075142215Sglebius				mac = nd6_ifptomac(ifp);
1076142215Sglebius		} else if (sdl0->sa_family == AF_LINK) {
107762587Sitojun			struct sockaddr_dl *sdl;
107862587Sitojun			sdl = (struct sockaddr_dl *)sdl0;
107962587Sitojun			if (sdl->sdl_alen == ifp->if_addrlen)
108062587Sitojun				mac = LLADDR(sdl);
108162587Sitojun		}
108262587Sitojun	}
108362587Sitojun	if (tlladdr && mac) {
108453541Sshin		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
108553541Sshin		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
1086120941Sume
108753541Sshin		/* roundup to 8 bytes alignment! */
108853541Sshin		optlen = (optlen + 7) & ~7;
108953541Sshin
109053541Sshin		m->m_pkthdr.len += optlen;
109153541Sshin		m->m_len += optlen;
109253541Sshin		icmp6len += optlen;
109353541Sshin		bzero((caddr_t)nd_opt, optlen);
109453541Sshin		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
109553541Sshin		nd_opt->nd_opt_len = optlen >> 3;
109653541Sshin		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
109753541Sshin	} else
109853541Sshin		flags &= ~ND_NA_FLAG_OVERRIDE;
109953541Sshin
110053541Sshin	ip6->ip6_plen = htons((u_short)icmp6len);
110153541Sshin	nd_na->nd_na_flags_reserved = flags;
110253541Sshin	nd_na->nd_na_cksum = 0;
110353541Sshin	nd_na->nd_na_cksum =
1104120941Sume	    in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
110553541Sshin
1106211501Sanchie	if (send_sendso_input_hook != NULL) {
1107211501Sanchie		mtag = m_tag_get(PACKET_TAG_ND_OUTGOING,
1108211501Sanchie		    sizeof(unsigned short), M_NOWAIT);
1109211501Sanchie		if (mtag == NULL)
1110211501Sanchie			goto bad;
1111211501Sanchie		*(unsigned short *)(mtag + 1) = nd_na->nd_na_type;
1112211501Sanchie		m_tag_prepend(m, mtag);
1113211501Sanchie	}
1114211501Sanchie
1115148385Sume	ip6_output(m, NULL, &ro, 0, &im6o, NULL, NULL);
1116148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_msg);
1117148385Sume	icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
1118190964Srwatson	ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);
1119148385Sume
1120238092Sglebius	/* We don't cache this route. */
1121238092Sglebius	RO_RTFREE(&ro);
1122238092Sglebius
1123148385Sume	return;
1124148385Sume
1125148385Sume  bad:
1126148385Sume	if (ro.ro_rt) {
1127148385Sume		RTFREE(ro.ro_rt);
1128148385Sume	}
1129148385Sume	m_freem(m);
1130148385Sume	return;
113153541Sshin}
113253541Sshin
1133231852Sbz#ifndef BURN_BRIDGES
1134231852Sbzvoid
1135231852Sbznd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
1136231852Sbz    const struct in6_addr *taddr6, u_long flags, int tlladdr,
1137231852Sbz    struct sockaddr *sdl0)
1138231852Sbz{
1139231852Sbz
1140231852Sbz	nd6_na_output_fib(ifp, daddr6_0, taddr6, flags, tlladdr, sdl0,
1141231852Sbz	    RT_DEFAULT_FIB);
1142231852Sbz}
1143231852Sbz#endif
1144231852Sbz
114553541Sshincaddr_t
1146171259Sdelphijnd6_ifptomac(struct ifnet *ifp)
114753541Sshin{
114853541Sshin	switch (ifp->if_type) {
114953541Sshin	case IFT_ARCNET:
115053541Sshin	case IFT_ETHER:
115153541Sshin	case IFT_FDDI:
115278064Sume	case IFT_IEEE1394:
115378468Ssumikawa#ifdef IFT_L2VLAN
115478468Ssumikawa	case IFT_L2VLAN:
115578468Ssumikawa#endif
115678064Sume#ifdef IFT_IEEE80211
115778064Sume	case IFT_IEEE80211:
115878064Sume#endif
1159219819Sjeff	case IFT_INFINIBAND:
1160149829Sthompsa	case IFT_BRIDGE:
1161120049Smdodd	case IFT_ISO88025:
1162147306Sbrooks		return IF_LLADDR(ifp);
116353541Sshin	default:
116453541Sshin		return NULL;
116553541Sshin	}
116653541Sshin}
116753541Sshin
116853541Sshinstruct dadq {
116960938Sjake	TAILQ_ENTRY(dadq) dad_list;
117053541Sshin	struct ifaddr *dad_ifa;
117153541Sshin	int dad_count;		/* max NS to send */
117262587Sitojun	int dad_ns_tcount;	/* # of trials to send NS */
117353541Sshin	int dad_ns_ocount;	/* NS sent so far */
117453541Sshin	int dad_ns_icount;
117553541Sshin	int dad_na_icount;
1176282622Shiren	int dad_ns_lcount;	/* looped back NS */
1177282622Shiren	int dad_loopbackprobe;	/* probing state for loopback detection */
117878064Sume	struct callout dad_timer_ch;
1179191816Szec	struct vnet *dad_vnet;
1180282622Shiren	u_int dad_refcnt;
1181282622Shiren#define	ND_OPT_NONCE_LEN32 \
1182282622Shiren		((ND_OPT_NONCE_LEN + sizeof(uint32_t) - 1)/sizeof(uint32_t))
1183282622Shiren	uint32_t dad_nonce[ND_OPT_NONCE_LEN32];
118453541Sshin};
118553541Sshin
1186215701Sdimstatic VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
1187272847Shrsstatic VNET_DEFINE(struct rwlock, dad_rwlock);
1188272847Shrs#define	V_dadq			VNET(dadq)
1189272847Shrs#define	V_dad_rwlock		VNET(dad_rwlock)
1190195699Srwatson
1191272847Shrs#define	DADQ_RLOCK()		rw_rlock(&V_dad_rwlock)
1192272847Shrs#define	DADQ_RUNLOCK()		rw_runlock(&V_dad_rwlock)
1193272847Shrs#define	DADQ_WLOCK()		rw_wlock(&V_dad_rwlock)
1194272847Shrs#define	DADQ_WUNLOCK()		rw_wunlock(&V_dad_rwlock)
1195272847Shrs
1196282622Shirenstatic void
1197282622Shirennd6_dad_add(struct dadq *dp)
1198282622Shiren{
1199282622Shiren
1200282622Shiren	DADQ_WLOCK();
1201282622Shiren	TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list);
1202282622Shiren	DADQ_WUNLOCK();
1203282622Shiren}
1204282622Shiren
1205282622Shirenstatic void
1206282622Shirennd6_dad_del(struct dadq *dp)
1207282622Shiren{
1208282622Shiren
1209282622Shiren	DADQ_WLOCK();
1210282622Shiren	TAILQ_REMOVE(&V_dadq, dp, dad_list);
1211282622Shiren	DADQ_WUNLOCK();
1212282622Shiren	nd6_dad_rele(dp);
1213282622Shiren}
1214282622Shiren
121553541Sshinstatic struct dadq *
1216282622Shirennd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n)
121753541Sshin{
121853541Sshin	struct dadq *dp;
121953541Sshin
1220272847Shrs	DADQ_RLOCK();
1221282622Shiren	TAILQ_FOREACH(dp, &V_dadq, dad_list) {
1222282622Shiren		if (dp->dad_ifa != ifa)
1223282622Shiren			continue;
1224282622Shiren		/*
1225282622Shiren		 * Skip if the nonce matches the received one.
1226282622Shiren		 * +2 in the length is required because of type and
1227282622Shiren		 * length fields are included in a header.
1228282622Shiren		 */
1229282622Shiren		if (n != NULL &&
1230282622Shiren		    n->nd_opt_nonce_len == (ND_OPT_NONCE_LEN + 2) / 8 &&
1231282622Shiren		    memcmp(&n->nd_opt_nonce[0], &dp->dad_nonce[0],
1232282622Shiren		        ND_OPT_NONCE_LEN) == 0) {
1233282622Shiren			dp->dad_ns_lcount++;
1234282622Shiren			continue;
1235282622Shiren		}
1236282622Shiren		refcount_acquire(&dp->dad_refcnt);
1237282622Shiren		break;
1238282622Shiren	}
1239272847Shrs	DADQ_RUNLOCK();
1240226340Sglebius
1241272847Shrs	return (dp);
124253541Sshin}
124353541Sshin
124478064Sumestatic void
1245290348Shrsnd6_dad_starttimer(struct dadq *dp, int ticks, int send_ns)
124678064Sume{
124778064Sume
1248290348Shrs	if (send_ns != 0)
1249290348Shrs		nd6_dad_ns_output(dp);
125078064Sume	callout_reset(&dp->dad_timer_ch, ticks,
1251191816Szec	    (void (*)(void *))nd6_dad_timer, (void *)dp);
125278064Sume}
125378064Sume
125478064Sumestatic void
1255171259Sdelphijnd6_dad_stoptimer(struct dadq *dp)
125678064Sume{
125778064Sume
1258282622Shiren	callout_drain(&dp->dad_timer_ch);
125978064Sume}
126078064Sume
1261282622Shirenstatic void
1262282622Shirennd6_dad_rele(struct dadq *dp)
1263282622Shiren{
1264282622Shiren
1265282622Shiren	if (refcount_release(&dp->dad_refcnt)) {
1266282622Shiren		ifa_free(dp->dad_ifa);
1267282622Shiren		free(dp, M_IP6NDP);
1268282622Shiren	}
1269282622Shiren}
1270282622Shiren
1271282622Shirenvoid
1272282622Shirennd6_dad_init(void)
1273282622Shiren{
1274282622Shiren
1275282622Shiren	rw_init(&V_dad_rwlock, "nd6 DAD queue");
1276282622Shiren	TAILQ_INIT(&V_dadq);
1277282622Shiren}
1278282622Shiren
127953541Sshin/*
1280148987Sume * Start Duplicate Address Detection (DAD) for specified interface address.
128153541Sshin */
128253541Sshinvoid
1283171259Sdelphijnd6_dad_start(struct ifaddr *ifa, int delay)
128453541Sshin{
128553541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
128653541Sshin	struct dadq *dp;
1287165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
1288290348Shrs	int send_ns;
128953541Sshin
129053541Sshin	/*
129153541Sshin	 * If we don't need DAD, don't do it.
129253541Sshin	 * There are several cases:
129353541Sshin	 * - DAD is disabled (ip6_dad_count == 0)
129453541Sshin	 * - the interface address is anycast
129553541Sshin	 */
129653541Sshin	if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
129762587Sitojun		log(LOG_DEBUG,
129862587Sitojun			"nd6_dad_start: called with non-tentative address "
129953541Sshin			"%s(%s)\n",
1300165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
130153541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
130253541Sshin		return;
130353541Sshin	}
130453541Sshin	if (ia->ia6_flags & IN6_IFF_ANYCAST) {
130553541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
130653541Sshin		return;
130753541Sshin	}
1308181803Sbz	if (!V_ip6_dad_count) {
130953541Sshin		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
131053541Sshin		return;
131153541Sshin	}
1312151465Ssuz	if (ifa->ifa_ifp == NULL)
131353541Sshin		panic("nd6_dad_start: ifa->ifa_ifp == NULL");
1314287734Shrs	if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) {
1315287734Shrs		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
131653541Sshin		return;
1317120941Sume	}
1318287734Shrs	if (!(ifa->ifa_ifp->if_flags & IFF_UP) ||
1319287734Shrs	    !(ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) ||
1320287734Shrs	    (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)) {
1321287734Shrs		ia->ia6_flags |= IN6_IFF_TENTATIVE;
1322197138Shrs		return;
1323287734Shrs	}
1324282622Shiren	if ((dp = nd6_dad_find(ifa, NULL)) != NULL) {
1325290348Shrs		/*
1326290348Shrs		 * DAD already in progress.  Let the existing entry
1327290348Shrs		 * to finish it.
1328290348Shrs		 */
132953541Sshin		return;
133053541Sshin	}
133153541Sshin
1332282622Shiren	dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO);
133353541Sshin	if (dp == NULL) {
133462587Sitojun		log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
133553541Sshin			"%s(%s)\n",
1336165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
133753541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
133853541Sshin		return;
133953541Sshin	}
134078064Sume	callout_init(&dp->dad_timer_ch, 0);
1341191816Szec#ifdef VIMAGE
1342191816Szec	dp->dad_vnet = curvnet;
1343191816Szec#endif
134478064Sume	nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1345165118Sbz	    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
134653541Sshin
134753541Sshin	/*
134853541Sshin	 * Send NS packet for DAD, ip6_dad_count times.
134953541Sshin	 * Note that we must delay the first transmission, if this is the
135053541Sshin	 * first packet to be sent from the interface after interface
135153541Sshin	 * (re)initialization.
135253541Sshin	 */
135353541Sshin	dp->dad_ifa = ifa;
1354282622Shiren	ifa_ref(dp->dad_ifa);
1355181803Sbz	dp->dad_count = V_ip6_dad_count;
135653541Sshin	dp->dad_ns_icount = dp->dad_na_icount = 0;
135762587Sitojun	dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1358282622Shiren	dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
1359282622Shiren	refcount_init(&dp->dad_refcnt, 1);
1360282622Shiren	nd6_dad_add(dp);
1361290348Shrs	send_ns = 0;
1362151539Ssuz	if (delay == 0) {
1363290348Shrs		send_ns = 1;
1364290348Shrs		delay = (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000;
136553541Sshin	}
1366290348Shrs	nd6_dad_starttimer(dp, delay, send_ns);
136753541Sshin}
136853541Sshin
136978064Sume/*
137078064Sume * terminate DAD unconditionally.  used for address removals.
137178064Sume */
137278064Sumevoid
1373171259Sdelphijnd6_dad_stop(struct ifaddr *ifa)
137478064Sume{
137578064Sume	struct dadq *dp;
137678064Sume
1377282622Shiren	dp = nd6_dad_find(ifa, NULL);
137878064Sume	if (!dp) {
137978064Sume		/* DAD wasn't started yet */
138078064Sume		return;
138178064Sume	}
138278064Sume
138378064Sume	nd6_dad_stoptimer(dp);
138478064Sume
1385282622Shiren	/*
1386282622Shiren	 * The DAD queue entry may have been removed by nd6_dad_timer() while
1387282622Shiren	 * we were waiting for it to stop, so re-do the lookup.
1388282622Shiren	 */
1389282622Shiren	nd6_dad_rele(dp);
1390282622Shiren	if (nd6_dad_find(ifa, NULL) == NULL)
1391282622Shiren		return;
1392282622Shiren
1393282622Shiren	nd6_dad_del(dp);
1394282622Shiren	nd6_dad_rele(dp);
139578064Sume}
139678064Sume
139753541Sshinstatic void
1398191816Szecnd6_dad_timer(struct dadq *dp)
139953541Sshin{
1400183550Szec	CURVNET_SET(dp->dad_vnet);
1401191816Szec	struct ifaddr *ifa = dp->dad_ifa;
1402272857Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
140353541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1404165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
140553541Sshin
140653541Sshin	/* Sanity check */
140753541Sshin	if (ia == NULL) {
140862587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1409282622Shiren		goto err;
141053541Sshin	}
1411272857Shrs	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) {
1412272857Shrs		/* Do not need DAD for ifdisabled interface. */
1413272857Shrs		log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of "
1414272857Shrs		    "ND6_IFF_IFDISABLED.\n", ifp->if_xname);
1415282622Shiren		goto err;
1416272857Shrs	}
141753541Sshin	if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
141862587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
141953541Sshin			"%s(%s)\n",
1420165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
142153541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1422282622Shiren		goto err;
142353541Sshin	}
142453541Sshin	if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
142562587Sitojun		log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
142653541Sshin			"%s(%s)\n",
1427165118Sbz			ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
142853541Sshin			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1429282622Shiren		goto err;
143053541Sshin	}
143153541Sshin
1432282622Shiren	/* Stop DAD if the interface is down even after dad_maxtry attempts. */
1433282622Shiren	if ((dp->dad_ns_tcount > V_dad_maxtry) &&
1434282622Shiren	    (((ifp->if_flags & IFF_UP) == 0) ||
1435282622Shiren	     ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) {
1436290348Shrs		nd6log((LOG_INFO, "%s: could not run DAD "
1437290348Shrs		    "because the interface was down or not running.\n",
1438120941Sume		    if_name(ifa->ifa_ifp)));
1439282622Shiren		goto err;
144062587Sitojun	}
144162587Sitojun
144253541Sshin	/* Need more checks? */
144353541Sshin	if (dp->dad_ns_ocount < dp->dad_count) {
144453541Sshin		/*
144553541Sshin		 * We have more NS to go.  Send NS packet for DAD.
144653541Sshin		 */
1447120941Sume		nd6_dad_starttimer(dp,
1448290348Shrs		    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1);
1449282622Shiren		goto done;
145053541Sshin	} else {
145153541Sshin		/*
145253541Sshin		 * We have transmitted sufficient number of DAD packets.
145353541Sshin		 * See what we've got.
145453541Sshin		 */
1455282622Shiren		if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0)
1456282622Shiren			/* We've seen NS or NA, means DAD has failed. */
1457282622Shiren			nd6_dad_duplicated(ifa, dp);
1458282622Shiren		else if (V_dad_enhanced != 0 &&
1459282622Shiren		    dp->dad_ns_lcount > 0 &&
1460282622Shiren		    dp->dad_ns_lcount > dp->dad_loopbackprobe) {
146153541Sshin			/*
1462285825Shrs			 * Sec. 4.1 in RFC 7527 requires transmission of
1463285825Shrs			 * additional probes until the loopback condition
1464285825Shrs			 * becomes clear when a looped back probe is detected.
146553541Sshin			 */
1466282622Shiren			log(LOG_ERR, "%s: a looped back NS message is "
1467282622Shiren			    "detected during DAD for %s.  "
1468282622Shiren			    "Another DAD probes are being sent.\n",
1469282622Shiren			    if_name(ifa->ifa_ifp),
1470282622Shiren			    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
1471282622Shiren			dp->dad_loopbackprobe = dp->dad_ns_lcount;
1472282622Shiren			/*
1473282622Shiren			 * Send an NS immediately and increase dad_count by
1474282622Shiren			 * V_nd6_mmaxtries - 1.
1475282622Shiren			 */
1476282622Shiren			dp->dad_count =
1477282622Shiren			    dp->dad_ns_ocount + V_nd6_mmaxtries - 1;
1478282622Shiren			nd6_dad_starttimer(dp,
1479290348Shrs			    (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000,
1480290348Shrs			    1);
1481282622Shiren			goto done;
148253541Sshin		} else {
148353541Sshin			/*
148453541Sshin			 * We are done with DAD.  No NA came, no NS came.
1485272857Shrs			 * No duplicate address found.  Check IFDISABLED flag
1486272857Shrs			 * again in case that it is changed between the
1487272857Shrs			 * beginning of this function and here.
148853541Sshin			 */
1489272857Shrs			if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0)
1490272857Shrs				ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
149153541Sshin
149278064Sume			nd6log((LOG_DEBUG,
149362587Sitojun			    "%s: DAD complete for %s - no duplicates found\n",
149462587Sitojun			    if_name(ifa->ifa_ifp),
1495165118Sbz			    ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)));
1496282622Shiren			if (dp->dad_ns_lcount > 0)
1497282622Shiren				log(LOG_ERR, "%s: DAD completed while "
1498282622Shiren				    "a looped back NS message is detected "
1499282622Shiren				    "during DAD for %s.\n",
1500282622Shiren				    if_name(ifa->ifa_ifp),
1501282622Shiren				    ip6_sprintf(ip6buf, IFA_IN6(ifa)));
150253541Sshin		}
150353541Sshin	}
1504282622Shirenerr:
1505282622Shiren	nd6_dad_del(dp);
150653541Sshindone:
1507183550Szec	CURVNET_RESTORE();
150853541Sshin}
150953541Sshin
1510282622Shirenstatic void
1511282622Shirennd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
151253541Sshin{
151353541Sshin	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1514151477Ssuz	struct ifnet *ifp;
1515165118Sbz	char ip6buf[INET6_ADDRSTRLEN];
151653541Sshin
151778064Sume	log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
1518282622Shiren	    "NS in/out/loopback=%d/%d/%d, NA in=%d\n",
1519165118Sbz	    if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
1520282622Shiren	    dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount,
1521282622Shiren	    dp->dad_na_icount);
152253541Sshin
152353541Sshin	ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
152453541Sshin	ia->ia6_flags |= IN6_IFF_DUPLICATED;
152553541Sshin
1526151477Ssuz	ifp = ifa->ifa_ifp;
152762587Sitojun	log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
1528165118Sbz	    if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr));
152962587Sitojun	log(LOG_ERR, "%s: manual intervention required\n",
1530151477Ssuz	    if_name(ifp));
153153541Sshin
1532151477Ssuz	/*
1533151477Ssuz	 * If the address is a link-local address formed from an interface
1534151477Ssuz	 * identifier based on the hardware address which is supposed to be
1535151477Ssuz	 * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
1536151477Ssuz	 * operation on the interface SHOULD be disabled.
1537197138Shrs	 * [RFC 4862, Section 5.4.5]
1538151477Ssuz	 */
1539151477Ssuz	if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
1540151477Ssuz		struct in6_addr in6;
1541151477Ssuz
1542151477Ssuz		/*
1543151477Ssuz		 * To avoid over-reaction, we only apply this logic when we are
1544151477Ssuz		 * very sure that hardware addresses are supposed to be unique.
1545151477Ssuz		 */
1546151477Ssuz		switch (ifp->if_type) {
1547151477Ssuz		case IFT_ETHER:
1548151477Ssuz		case IFT_FDDI:
1549151477Ssuz		case IFT_ATM:
1550151477Ssuz		case IFT_IEEE1394:
1551151477Ssuz#ifdef IFT_IEEE80211
1552151477Ssuz		case IFT_IEEE80211:
1553151477Ssuz#endif
1554219819Sjeff		case IFT_INFINIBAND:
1555151477Ssuz			in6 = ia->ia_addr.sin6_addr;
1556151477Ssuz			if (in6_get_hw_ifid(ifp, &in6) == 0 &&
1557151477Ssuz			    IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
1558151477Ssuz				ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1559151477Ssuz				log(LOG_ERR, "%s: possible hardware address "
1560151477Ssuz				    "duplication detected, disable IPv6\n",
1561151477Ssuz				    if_name(ifp));
1562151477Ssuz			}
1563151477Ssuz			break;
1564151477Ssuz		}
1565151477Ssuz	}
156653541Sshin}
156753541Sshin
156862587Sitojunstatic void
1569290348Shrsnd6_dad_ns_output(struct dadq *dp)
157062587Sitojun{
1571290348Shrs	struct in6_ifaddr *ia = (struct in6_ifaddr *)dp->dad_ifa;
1572290348Shrs	struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
1573282622Shiren	int i;
157462587Sitojun
157562587Sitojun	dp->dad_ns_tcount++;
157662587Sitojun	if ((ifp->if_flags & IFF_UP) == 0) {
157762587Sitojun		return;
157862587Sitojun	}
1579148887Srwatson	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
158062587Sitojun		return;
158162587Sitojun	}
158262587Sitojun
158362587Sitojun	dp->dad_ns_ocount++;
1584282622Shiren	if (V_dad_enhanced != 0) {
1585282622Shiren		for (i = 0; i < ND_OPT_NONCE_LEN32; i++)
1586282622Shiren			dp->dad_nonce[i] = arc4random();
1587282622Shiren		/*
1588282622Shiren		 * XXXHRS: Note that in the case that
1589282622Shiren		 * DupAddrDetectTransmits > 1, multiple NS messages with
1590282622Shiren		 * different nonces can be looped back in an unexpected
1591282622Shiren		 * order.  The current implementation recognizes only
1592282622Shiren		 * the latest nonce on the sender side.  Practically it
1593282622Shiren		 * should work well in almost all cases.
1594282622Shiren		 */
1595282622Shiren	}
1596282622Shiren	nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL,
1597282622Shiren	    (uint8_t *)&dp->dad_nonce[0]);
159862587Sitojun}
159962587Sitojun
160062587Sitojunstatic void
1601282622Shirennd6_dad_ns_input(struct ifaddr *ifa, struct nd_opt_nonce *ndopt_nonce)
160253541Sshin{
160353541Sshin	struct in6_ifaddr *ia;
160453541Sshin	struct ifnet *ifp;
160578064Sume	const struct in6_addr *taddr6;
160653541Sshin	struct dadq *dp;
160753541Sshin
1608151465Ssuz	if (ifa == NULL)
160953541Sshin		panic("ifa == NULL in nd6_dad_ns_input");
161053541Sshin
161153541Sshin	ia = (struct in6_ifaddr *)ifa;
161253541Sshin	ifp = ifa->ifa_ifp;
161353541Sshin	taddr6 = &ia->ia_addr.sin6_addr;
1614282622Shiren	/* Ignore Nonce option when Enhanced DAD is disabled. */
1615282622Shiren	if (V_dad_enhanced == 0)
1616282622Shiren		ndopt_nonce = NULL;
1617282622Shiren	dp = nd6_dad_find(ifa, ndopt_nonce);
1618282622Shiren	if (dp == NULL)
161953541Sshin		return;
162053541Sshin
1621282622Shiren	dp->dad_ns_icount++;
1622282622Shiren	nd6_dad_rele(dp);
162353541Sshin}
162453541Sshin
162562587Sitojunstatic void
1626171259Sdelphijnd6_dad_na_input(struct ifaddr *ifa)
162753541Sshin{
162853541Sshin	struct dadq *dp;
162953541Sshin
1630151465Ssuz	if (ifa == NULL)
163153541Sshin		panic("ifa == NULL in nd6_dad_na_input");
163253541Sshin
1633282622Shiren	dp = nd6_dad_find(ifa, NULL);
1634282622Shiren	if (dp != NULL) {
163553541Sshin		dp->dad_na_icount++;
1636282622Shiren		nd6_dad_rele(dp);
1637282622Shiren	}
163853541Sshin}
1639