nd6_nbr.c revision 53626
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/netinet6/nd6_nbr.c 53626 1999-11-23 05:42:36Z shin $
30 */
31
32#include "opt_inet.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/malloc.h>
37#include <sys/mbuf.h>
38#include <sys/socket.h>
39#include <sys/sockio.h>
40#include <sys/time.h>
41#include <sys/kernel.h>
42#include <sys/errno.h>
43#include <sys/syslog.h>
44#include <sys/queue.h>
45
46#include <net/if.h>
47#include <net/if_types.h>
48#include <net/if_dl.h>
49#include <net/route.h>
50
51#include <netinet/in.h>
52#include <netinet/in_var.h>
53#include <netinet6/in6_var.h>
54#include <netinet6/ip6.h>
55#include <netinet6/ip6_var.h>
56#include <netinet6/nd6.h>
57#include <netinet6/icmp6.h>
58
59#include <net/net_osdep.h>
60
61#define	SDL(s) ((struct sockaddr_dl *)s)
62
63struct	dadq;
64static struct	dadq *nd6_dad_find __P((struct ifaddr *));
65static void	nd6_dad_timer __P((struct ifaddr *));
66static void	nd6_dad_ns_input __P((struct ifaddr *));
67static void	nd6_dad_na_input __P((struct ifaddr *));
68
69/* ignore NS in DAD - specwise incorrect, */
70int	dad_ignore_ns = 0;
71
72/*
73 * Input an Neighbor Solicitation Message.
74 *
75 * Based on RFC 2461
76 * Based on RFC 2462 (duplicated address detection)
77 *
78 * XXX proxy advertisement
79 */
80void
81nd6_ns_input(m, off, icmp6len)
82	struct mbuf *m;
83	int off, icmp6len;
84{
85	struct ifnet *ifp = m->m_pkthdr.rcvif;
86	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
87	struct nd_neighbor_solicit *nd_ns
88		= (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
89	struct in6_addr saddr6 = ip6->ip6_src;
90	struct in6_addr daddr6 = ip6->ip6_dst;
91	struct in6_addr taddr6 = nd_ns->nd_ns_target;
92	struct in6_addr myaddr6;
93	char *lladdr = NULL;
94	struct ifaddr *ifa;
95	int lladdrlen = 0;
96	int anycast = 0, proxy = 0, tentative = 0;
97	int tlladdr;
98	union nd_opts ndopts;
99
100	if (ip6->ip6_hlim != 255) {
101		log(LOG_ERR,
102		    "nd6_ns_input: invalid hlim %d\n", ip6->ip6_hlim);
103		return;
104	}
105
106	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
107		/* dst has to be solicited node multicast address. */
108		if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL
109		    /*don't check ifindex portion*/
110		    && daddr6.s6_addr32[1] == 0
111		    && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE
112		    && daddr6.s6_addr8[12] == 0xff) {
113			; /*good*/
114		} else {
115			log(LOG_INFO, "nd6_ns_input: bad DAD packet "
116				"(wrong ip6 dst)\n");
117			goto bad;
118		}
119	}
120
121	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
122		log(LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n");
123		goto bad;
124	}
125
126	if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
127		taddr6.s6_addr16[1] = htons(ifp->if_index);
128
129	icmp6len -= sizeof(*nd_ns);
130	nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
131	if (nd6_options(&ndopts) < 0) {
132		log(LOG_INFO, "nd6_ns_input: invalid ND option, ignored\n");
133		goto bad;
134	}
135
136	if (ndopts.nd_opts_src_lladdr) {
137		lladdr = (char *)(ndopts.nd_opts_src_lladdr +1);
138		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
139	}
140
141	if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
142		log(LOG_INFO, "nd6_ns_input: bad DAD packet "
143			"(link-layer address option)\n");
144		goto bad;
145	}
146
147	/*
148	 * Attaching target link-layer address to the NA?
149	 * (RFC 2461 7.2.4)
150	 *
151	 * NS IP dst is unicast/anycast			MUST NOT add
152	 * NS IP dst is solicited-node multicast	MUST add
153	 *
154	 * In implementation, we add target link-layer address by default.
155	 * We do not add one in MUST NOT cases.
156	 */
157	if (!IN6_IS_ADDR_MULTICAST(&daddr6))
158		tlladdr = 0;
159	else
160		tlladdr = 1;
161
162	/*
163	 * Target address (taddr6) must be either:
164	 * (1) Valid unicast/anycast address for my receiving interface,
165	 * (2) Unicast address for which I'm offering proxy service, or
166	 * (3) "tentative" address on which DAD is being performed.
167	 */
168	/* (1) and (3) check. */
169	ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
170
171	/* (2) check. */
172	if (!ifa && nd6_proxyall) {
173		struct rtentry *rt;
174		struct sockaddr_in6 tsin6;
175
176		bzero(&tsin6, sizeof tsin6);
177		tsin6.sin6_len = sizeof(struct sockaddr_in6);
178		tsin6.sin6_family = AF_INET6;
179		tsin6.sin6_addr = taddr6;
180
181		rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0);
182		if (rt && rt->rt_ifp != ifp) {
183			/*
184			 * search link local addr for ifp, and use it for
185			 * proxy NA.
186			 */
187			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp);
188			if (ifa)
189				proxy = 1;
190		}
191		rtfree(rt);
192	}
193	if (!ifa) {
194		/*
195		 * We've got a NS packet, and we don't have that adddress
196		 * assigned for us.  We MUST silently ignore it.
197		 * See RFC2461 7.2.3.
198		 */
199		return;
200	}
201	myaddr6 = *IFA_IN6(ifa);
202	anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
203	tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
204	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
205		return;
206
207	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
208		log(LOG_INFO,
209		    "nd6_ns_input: lladdrlen mismatch for %s "
210		    "(if %d, NS packet %d)\n",
211			ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2);
212	}
213
214	if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
215		log(LOG_INFO,
216		    "nd6_ns_input: duplicate IP6 address %s\n",
217		    ip6_sprintf(&saddr6));
218		return;
219	}
220
221	/*
222	 * We have neighbor solicitation packet, with target address equals to
223	 * one of my tentative address.
224	 *
225	 * src addr	how to process?
226	 * ---		---
227	 * multicast	of course, invalid (rejected in ip6_input)
228	 * unicast	somebody is doing address resolution -> ignore
229	 * unspec	dup address detection
230	 *
231	 * The processing is defined in RFC 2462.
232	 */
233	if (tentative) {
234		/*
235		 * If source address is unspecified address, it is for
236		 * duplicated address detection.
237		 *
238		 * If not, the packet is for addess resolution;
239		 * silently ignore it.
240		 */
241		if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
242			nd6_dad_ns_input(ifa);
243
244		return;
245	}
246
247	/*
248	 * If the source address is unspecified address, entries must not
249	 * be created or updated.
250	 * It looks that sender is performing DAD.  Output NA toward
251	 * all-node multicast address, to tell the sender that I'm using
252	 * the address.
253	 * S bit ("solicited") must be zero.
254	 */
255	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
256		saddr6 = in6addr_linklocal_allnodes;
257		saddr6.s6_addr16[1] = htons(ifp->if_index);
258		nd6_na_output(ifp, &saddr6, &taddr6,
259			      ((anycast || proxy || !tlladdr)
260				      ? 0 : ND_NA_FLAG_OVERRIDE)
261			      	| (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
262			      tlladdr);
263		return;
264	}
265
266	nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0);
267
268	nd6_na_output(ifp, &saddr6, &taddr6,
269		      ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE)
270			| (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0)
271			| ND_NA_FLAG_SOLICITED,
272		      tlladdr);
273	return;
274
275 bad:
276	log(LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6));
277	log(LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6));
278	log(LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6));
279	return;
280}
281
282/*
283 * Output an Neighbor Solicitation Message. Caller specifies:
284 *	- ICMP6 header source IP6 address
285 *	- ND6 header target IP6 address
286 *	- ND6 header source datalink address
287 *
288 * Based on RFC 2461
289 * Based on RFC 2462 (duplicated address detection)
290 */
291void
292nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
293	struct ifnet *ifp;
294	struct in6_addr *daddr6, *taddr6;
295	struct llinfo_nd6 *ln;	/* for source address determination */
296	int dad;	/* duplicated address detection */
297{
298	struct mbuf *m;
299	struct ip6_hdr *ip6;
300	struct nd_neighbor_solicit *nd_ns;
301	struct in6_ifaddr *ia = NULL;
302	struct ip6_moptions im6o;
303	int icmp6len;
304	caddr_t mac;
305	struct ifnet *outif = NULL;
306
307	if (IN6_IS_ADDR_MULTICAST(taddr6))
308		return;
309
310	if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
311		return;
312
313	if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
314		m->m_flags |= M_MCAST;
315		im6o.im6o_multicast_ifp = ifp;
316		im6o.im6o_multicast_hlim = 255;
317		im6o.im6o_multicast_loop = 0;
318	}
319
320	icmp6len = sizeof(*nd_ns);
321	m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
322	MH_ALIGN(m, m->m_len + 16); /* 1+1+6 is enought. but just in case */
323
324	/* fill neighbor solicitation packet */
325	ip6 = mtod(m, struct ip6_hdr *);
326	ip6->ip6_flow = 0;
327	ip6->ip6_vfc = IPV6_VERSION;
328	/* ip6->ip6_plen will be set later */
329	ip6->ip6_nxt = IPPROTO_ICMPV6;
330	ip6->ip6_hlim = 255;
331	if (daddr6)
332		ip6->ip6_dst = *daddr6;
333	else {
334		ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
335		ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
336		ip6->ip6_dst.s6_addr32[1] = 0;
337		ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
338		ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
339		ip6->ip6_dst.s6_addr8[12] = 0xff;
340	}
341	if (!dad) {
342	/* spec-wise correct, scope match */
343		/*
344		 * RFC2461 7.2.2:
345		 * "If the source address of the packet prompting the
346		 * solicitation is the same as one of the addresses assigned
347		 * to the outgoing interface, that address SHOULD be placed
348		 * in the IP Source Address of the outgoing solicitation.
349		 * Otherwise, any one of the addresses assigned to the
350		 * interface should be used."
351		 *
352		 * We use the source address for the prompting packet
353		 * (saddr6), if:
354		 * - saddr6 is given from the caller (by giving "ln"), and
355		 * - saddr6 belongs to the outgoing interface.
356		 * Otherwise, we perform a scope-wise match.
357		 */
358		struct ip6_hdr *hip6;		/*hold ip6*/
359		struct in6_addr *saddr6;
360
361		if (ln && ln->ln_hold) {
362			hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
363			/* XXX pullup? */
364			if (sizeof(*hip6) < ln->ln_hold->m_len)
365				saddr6 = &hip6->ip6_src;
366			else
367				saddr6 = NULL;
368		} else
369			saddr6 = NULL;
370		if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6))
371			bcopy(saddr6, &ip6->ip6_src, sizeof(*saddr6));
372		else {
373			ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
374			if (ia == NULL) {
375				m_freem(m);	/*XXX*/
376				return;
377			}
378			ip6->ip6_src = ia->ia_addr.sin6_addr;
379		}
380	} else {
381		/*
382		 * Source address for DAD packet must always be IPv6
383		 * unspecified address. (0::0)
384		 */
385		bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
386	}
387	nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
388	nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
389	nd_ns->nd_ns_code = 0;
390	nd_ns->nd_ns_reserved = 0;
391	nd_ns->nd_ns_target = *taddr6;
392
393	if (IN6_IS_SCOPE_LINKLOCAL(&nd_ns->nd_ns_target))
394		nd_ns->nd_ns_target.s6_addr16[1] = 0;
395
396	/*
397	 * Add source link-layer address option.
398	 *
399	 *				spec		implementation
400	 *				---		---
401	 * DAD packet			MUST NOT	do not add the option
402	 * there's no link layer address:
403	 *				impossible	do not add the option
404	 * there's link layer address:
405	 *	Multicast NS		MUST add one	add the option
406	 *	Unicast NS		SHOULD add one	add the option
407	 */
408	if (!dad && (mac = nd6_ifptomac(ifp))) {
409		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
410		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
411		/* 8 byte alignments... */
412		optlen = (optlen + 7) & ~7;
413
414		m->m_pkthdr.len += optlen;
415		m->m_len += optlen;
416		icmp6len += optlen;
417		bzero((caddr_t)nd_opt, optlen);
418		nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
419		nd_opt->nd_opt_len = optlen >> 3;
420		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
421	}
422
423	ip6->ip6_plen = htons((u_short)icmp6len);
424	nd_ns->nd_ns_cksum = 0;
425	nd_ns->nd_ns_cksum
426		= in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
427
428#ifdef IPSEC
429	m->m_pkthdr.rcvif = NULL;
430#endif /*IPSEC*/
431	ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif);
432	if (outif) {
433		icmp6_ifstat_inc(outif, ifs6_out_msg);
434		icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit);
435	}
436	icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
437}
438
439/*
440 * Neighbor advertisement input handling.
441 *
442 * Based on RFC 2461
443 * Based on RFC 2462 (duplicated address detection)
444 */
445void
446nd6_na_input(m, off, icmp6len)
447	struct mbuf *m;
448	int off, icmp6len;
449{
450	struct ifnet *ifp = m->m_pkthdr.rcvif;
451	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
452	struct nd_neighbor_advert *nd_na
453		= (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
454	struct in6_addr daddr6 = ip6->ip6_dst;
455	struct in6_addr taddr6 = nd_na->nd_na_target;
456	int flags = nd_na->nd_na_flags_reserved;
457	int is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
458	int is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
459	int is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
460	char *lladdr = NULL;
461	int lladdrlen = 0;
462	struct ifaddr *ifa;
463	struct llinfo_nd6 *ln;
464	struct rtentry *rt;
465	struct sockaddr_dl *sdl;
466	union nd_opts ndopts;
467
468	if (ip6->ip6_hlim != 255) {
469		log(LOG_ERR,
470		    "nd6_na_input: invalid hlim %d\n", ip6->ip6_hlim);
471		return;
472	}
473
474	if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
475		taddr6.s6_addr16[1] = htons(ifp->if_index);
476
477	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
478		log(LOG_ERR,
479		    "nd6_na_input: invalid target address %s\n",
480		    ip6_sprintf(&taddr6));
481		return;
482	}
483	if (IN6_IS_ADDR_MULTICAST(&daddr6))
484		if (is_solicited) {
485			log(LOG_ERR,
486			    "nd6_na_input: a solicited adv is multicasted\n");
487			return;
488		}
489
490	icmp6len -= sizeof(*nd_na);
491	nd6_option_init(nd_na + 1, icmp6len, &ndopts);
492	if (nd6_options(&ndopts) < 0) {
493		log(LOG_INFO, "nd6_na_input: invalid ND option, ignored\n");
494		return;
495	}
496
497	if (ndopts.nd_opts_tgt_lladdr) {
498		lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
499		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
500	}
501
502	ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
503
504	/*
505	 * Target address matches one of my interface address.
506	 *
507	 * If my address is tentative, this means that there's somebody
508	 * already using the same address as mine.  This indicates DAD failure.
509	 * This is defined in RFC 2462.
510	 *
511	 * Otherwise, process as defined in RFC 2461.
512	 */
513	if (ifa
514	 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
515		nd6_dad_na_input(ifa);
516		return;
517	}
518
519	/* Just for safety, maybe unnecessery. */
520	if (ifa) {
521		log(LOG_ERR,
522		    "nd6_na_input: duplicate IP6 address %s\n",
523		    ip6_sprintf(&taddr6));
524		return;
525	}
526
527	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
528		log(LOG_INFO,
529		    "nd6_na_input: lladdrlen mismatch for %s "
530		    "(if %d, NA packet %d)\n",
531			ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2);
532	}
533
534	/*
535	 * If no neighbor cache entry is found, NA SHOULD silently be discarded.
536	 */
537	rt = nd6_lookup(&taddr6, 0, ifp);
538	if ((rt == NULL) ||
539	   ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
540	   ((sdl = SDL(rt->rt_gateway)) == NULL))
541		return;
542
543	if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
544		/*
545		 * If the link-layer has address, and no lladdr option came,
546		 * discard the packet.
547		 */
548		if (ifp->if_addrlen && !lladdr)
549			return;
550
551		/*
552		 * Record link-layer address, and update the state.
553		 */
554		sdl->sdl_alen = ifp->if_addrlen;
555		bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
556		if (is_solicited) {
557			ln->ln_state = ND6_LLINFO_REACHABLE;
558			if (ln->ln_expire)
559				ln->ln_expire = time_second +
560					nd_ifinfo[rt->rt_ifp->if_index].reachable;
561		} else
562			ln->ln_state = ND6_LLINFO_STALE;
563		ln->ln_router = is_router;
564	} else {
565		int llchange;
566
567		/*
568		 * Check if the link-layer address has changed or not.
569		 */
570		if (!lladdr)
571			llchange = 0;
572		else {
573			if (sdl->sdl_alen) {
574				if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
575					llchange = 1;
576				else
577					llchange = 0;
578			} else
579				llchange = 1;
580		}
581
582		/*
583		 * This is VERY complex.  Look at it with care.
584		 *
585		 * override solicit lladdr llchange	action
586		 *					(L: record lladdr)
587		 *
588		 *	0	0	n	--	(2c)
589		 *	0	0	y	n	(2b) L
590		 *	0	0	y	y	(1)    REACHABLE->STALE
591		 *	0	1	n	--	(2c)   *->REACHABLE
592		 *	0	1	y	n	(2b) L *->REACHABLE
593		 *	0	1	y	y	(1)    REACHABLE->STALE
594		 *	1	0	n	--	(2a)
595		 *	1	0	y	n	(2a) L
596		 *	1	0	y	y	(2a) L *->STALE
597		 *	1	1	n	--	(2a)   *->REACHABLE
598		 *	1	1	y	n	(2a) L *->REACHABLE
599		 *	1	1	y	y	(2a) L *->REACHABLE
600		 */
601		if (!is_override && (lladdr && llchange)) {	   /* (1) */
602			/*
603			 * If state is REACHABLE, make it STALE.
604			 * no other updates should be done.
605			 */
606			if (ln->ln_state == ND6_LLINFO_REACHABLE)
607				ln->ln_state = ND6_LLINFO_STALE;
608			return;
609		} else if (is_override				   /* (2a) */
610			|| (!is_override && (lladdr && !llchange)) /* (2b) */
611			|| !lladdr) {				   /* (2c) */
612			/*
613			 * Update link-local address, if any.
614			 */
615			if (lladdr) {
616				sdl->sdl_alen = ifp->if_addrlen;
617				bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
618			}
619
620			/*
621			 * If solicited, make the state REACHABLE.
622			 * If not solicited and the link-layer address was
623			 * changed, make it STALE.
624			 */
625			if (is_solicited) {
626				ln->ln_state = ND6_LLINFO_REACHABLE;
627				if (ln->ln_expire) {
628					ln->ln_expire = time_second +
629						nd_ifinfo[ifp->if_index].reachable;
630				}
631			} else {
632				if (lladdr && llchange)
633					ln->ln_state = ND6_LLINFO_STALE;
634			}
635		}
636
637		if (ln->ln_router && !is_router) {
638			/*
639			 * The peer dropped the router flag.
640			 * Remove the sender from the Default Router List and
641			 * update the Destination Cache entries.
642			 */
643			struct nd_defrouter *dr;
644			struct in6_addr *in6;
645			int s;
646
647			in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
648			s = splnet();
649			dr = defrouter_lookup(in6, rt->rt_ifp);
650			if (dr)
651				defrtrlist_del(dr);
652			else if (!ip6_forwarding && ip6_accept_rtadv) {
653				/*
654				 * Even if the neighbor is not in the default
655				 * router list, the neighbor may be used
656				 * as a next hop for some destinations
657				 * (e.g. redirect case). So we must
658				 * call rt6_flush explicitly.
659				 */
660				rt6_flush(&ip6->ip6_src, rt->rt_ifp);
661			}
662			splx(s);
663		}
664		ln->ln_router = is_router;
665	}
666	rt->rt_flags &= ~RTF_REJECT;
667	ln->ln_asked = 0;
668	if (ln->ln_hold) {
669		nd6_output(ifp, ln->ln_hold,
670			   (struct sockaddr_in6 *)rt_key(rt), rt);
671		ln->ln_hold = 0;
672	}
673}
674
675/*
676 * Neighbor advertisement output handling.
677 *
678 * Based on RFC 2461
679 *
680 * XXX NA delay for anycast address is not implemented yet
681 *      (RFC 2461 7.2.7)
682 * XXX proxy advertisement?
683 */
684void
685nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr)
686	struct ifnet *ifp;
687	struct in6_addr *daddr6, *taddr6;
688	u_long flags;
689	int tlladdr;	/* 1 if include target link-layer address */
690{
691	struct mbuf *m;
692	struct ip6_hdr *ip6;
693	struct nd_neighbor_advert *nd_na;
694	struct in6_ifaddr *ia = NULL;
695	struct ip6_moptions im6o;
696	int icmp6len;
697	caddr_t mac;
698	struct ifnet *outif;
699
700	if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
701		return;
702
703	if (IN6_IS_ADDR_MULTICAST(daddr6)) {
704		m->m_flags |= M_MCAST;
705		im6o.im6o_multicast_ifp = ifp;
706		im6o.im6o_multicast_hlim = 255;
707		im6o.im6o_multicast_loop = 0;
708	}
709
710	icmp6len = sizeof(*nd_na);
711	m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
712	MH_ALIGN(m, m->m_len + 16); /* 1+1+6 is enough. but just in case */
713
714	/* fill neighbor advertisement packet */
715	ip6 = mtod(m, struct ip6_hdr *);
716	ip6->ip6_flow = 0;
717	ip6->ip6_vfc = IPV6_VERSION;
718	ip6->ip6_nxt = IPPROTO_ICMPV6;
719	ip6->ip6_hlim = 255;
720	if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
721		/* reply to DAD */
722		ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
723		ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
724		ip6->ip6_dst.s6_addr32[1] = 0;
725		ip6->ip6_dst.s6_addr32[2] = 0;
726		ip6->ip6_dst.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
727		flags &= ~ND_NA_FLAG_SOLICITED;
728	} else
729		ip6->ip6_dst = *daddr6;
730
731	/*
732	 * Select a source whose scope is the same as that of the dest.
733	 */
734	ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
735	if (ia == NULL) {
736		m_freem(m);
737		return;
738	}
739	ip6->ip6_src = ia->ia_addr.sin6_addr;
740	nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
741	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
742	nd_na->nd_na_code = 0;
743	nd_na->nd_na_target = *taddr6;
744	if (IN6_IS_SCOPE_LINKLOCAL(&nd_na->nd_na_target))
745		nd_na->nd_na_target.s6_addr16[1] = 0;
746
747	/*
748	 * "tlladdr" indicates NS's condition for adding tlladdr or not.
749	 * see nd6_ns_input() for details.
750	 * Basically, if NS packet is sent to unicast/anycast addr,
751	 * target lladdr option SHOULD NOT be included.
752	 */
753	if (tlladdr && (mac = nd6_ifptomac(ifp))) {
754		int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
755		struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
756
757		/* roundup to 8 bytes alignment! */
758		optlen = (optlen + 7) & ~7;
759
760		m->m_pkthdr.len += optlen;
761		m->m_len += optlen;
762		icmp6len += optlen;
763		bzero((caddr_t)nd_opt, optlen);
764		nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
765		nd_opt->nd_opt_len = optlen >> 3;
766		bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
767	} else
768		flags &= ~ND_NA_FLAG_OVERRIDE;
769
770	ip6->ip6_plen = htons((u_short)icmp6len);
771	nd_na->nd_na_flags_reserved = flags;
772	nd_na->nd_na_cksum = 0;
773	nd_na->nd_na_cksum =
774		in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
775
776#ifdef IPSEC
777	m->m_pkthdr.rcvif = NULL;
778#endif /*IPSEC*/
779	ip6_output(m, NULL, NULL, 0, &im6o, &outif);
780	if (outif) {
781		icmp6_ifstat_inc(outif, ifs6_out_msg);
782		icmp6_ifstat_inc(outif, ifs6_out_neighboradvert);
783	}
784	icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
785}
786
787caddr_t
788nd6_ifptomac(ifp)
789	struct ifnet *ifp;
790{
791	switch (ifp->if_type) {
792	case IFT_ARCNET:
793	case IFT_ETHER:
794	case IFT_FDDI:
795		return ((caddr_t)(ifp + 1));
796		break;
797	default:
798		return NULL;
799	}
800}
801
802TAILQ_HEAD(dadq_head, dadq);
803struct dadq {
804	TAILQ_ENTRY(dadq) dad_list;
805	struct ifaddr *dad_ifa;
806	int dad_count;		/* max NS to send */
807	int dad_ns_ocount;	/* NS sent so far */
808	int dad_ns_icount;
809	int dad_na_icount;
810	struct callout_handle dad_timer;
811};
812
813static struct dadq_head dadq;
814
815static struct dadq *
816nd6_dad_find(ifa)
817	struct ifaddr *ifa;
818{
819	struct dadq *dp;
820
821	for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
822		if (dp->dad_ifa == ifa)
823			return dp;
824	}
825	return NULL;
826}
827
828/*
829 * Start Duplicated Address Detection (DAD) for specified interface address.
830 */
831void
832nd6_dad_start(ifa, tick)
833	struct ifaddr *ifa;
834	int *tick;	/* minimum delay ticks for IFF_UP event */
835{
836	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
837	struct dadq *dp;
838	static int dad_init = 0;
839
840	if (!dad_init) {
841		TAILQ_INIT(&dadq);
842		dad_init++;
843	}
844
845	/*
846	 * If we don't need DAD, don't do it.
847	 * There are several cases:
848	 * - DAD is disabled (ip6_dad_count == 0)
849	 * - the interface address is anycast
850	 */
851	if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
852		printf("nd6_dad_start: called with non-tentative address "
853			"%s(%s)\n",
854			ip6_sprintf(&ia->ia_addr.sin6_addr),
855			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
856		return;
857	}
858	if (ia->ia6_flags & IN6_IFF_ANYCAST) {
859		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
860		return;
861	}
862	if (!ip6_dad_count) {
863		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
864		return;
865	}
866	if (!ifa->ifa_ifp)
867		panic("nd6_dad_start: ifa->ifa_ifp == NULL");
868	if (!(ifa->ifa_ifp->if_flags & IFF_UP))
869		return;
870	if (nd6_dad_find(ifa) != NULL) {
871		/* DAD already in progress */
872		return;
873	}
874
875	dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT);
876	if (dp == NULL) {
877		printf("nd6_dad_start: memory allocation failed for "
878			"%s(%s)\n",
879			ip6_sprintf(&ia->ia_addr.sin6_addr),
880			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
881		return;
882	}
883	bzero(dp, sizeof(*dp));
884	TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
885
886	/* XXXJRT This is probably a purely debugging message. */
887	printf("%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
888	    ip6_sprintf(&ia->ia_addr.sin6_addr));
889
890	/*
891	 * Send NS packet for DAD, ip6_dad_count times.
892	 * Note that we must delay the first transmission, if this is the
893	 * first packet to be sent from the interface after interface
894	 * (re)initialization.
895	 */
896	dp->dad_ifa = ifa;
897	ifa->ifa_refcnt++;	/*just for safety*/
898	dp->dad_count = ip6_dad_count;
899	dp->dad_ns_icount = dp->dad_na_icount = 0;
900	dp->dad_ns_ocount = 0;
901	if (!tick) {
902		dp->dad_ns_ocount++;
903		nd6_ns_output(ifa->ifa_ifp, NULL, &ia->ia_addr.sin6_addr,
904			NULL, 1);
905		dp->dad_timer =
906		timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
907			nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
908	} else {
909		int ntick;
910
911		if (*tick == 0)
912			ntick = random() % (MAX_RTR_SOLICITATION_DELAY * hz);
913		else
914			ntick = *tick + random() % (hz / 2);
915		*tick = ntick;
916		dp->dad_timer =
917		timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
918			ntick);
919	}
920}
921
922static void
923nd6_dad_timer(ifa)
924	struct ifaddr *ifa;
925{
926	int s;
927	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
928	struct dadq *dp;
929
930	s = splnet();		/*XXX*/
931
932	/* Sanity check */
933	if (ia == NULL) {
934		printf("nd6_dad_timer: called with null parameter\n");
935		goto done;
936	}
937	dp = nd6_dad_find(ifa);
938	if (dp == NULL) {
939		printf("nd6_dad_timer: DAD structure not found\n");
940		goto done;
941	}
942	if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
943		printf("nd6_dad_timer: called with duplicated address "
944			"%s(%s)\n",
945			ip6_sprintf(&ia->ia_addr.sin6_addr),
946			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
947		goto done;
948	}
949	if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
950		printf("nd6_dad_timer: called with non-tentative address "
951			"%s(%s)\n",
952			ip6_sprintf(&ia->ia_addr.sin6_addr),
953			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
954		goto done;
955	}
956
957	/* Need more checks? */
958	if (dp->dad_ns_ocount < dp->dad_count) {
959		/*
960		 * We have more NS to go.  Send NS packet for DAD.
961		 */
962		dp->dad_ns_ocount++;
963		nd6_ns_output(ifa->ifa_ifp, NULL, &ia->ia_addr.sin6_addr,
964			NULL, 1);
965		dp->dad_timer =
966		timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
967			nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
968	} else {
969		/*
970		 * We have transmitted sufficient number of DAD packets.
971		 * See what we've got.
972		 */
973		int duplicate;
974
975		duplicate = 0;
976
977		if (dp->dad_na_icount) {
978			/*
979			 * the check is in nd6_dad_na_input(),
980			 * but just in case
981			 */
982			duplicate++;
983		}
984
985		if (dp->dad_ns_icount) {
986			/* We've seen NS, means DAD has failed. */
987			duplicate++;
988		}
989
990		if (duplicate) {
991			/* (*dp) will be freed in nd6_dad_duplicated() */
992			dp = NULL;
993			nd6_dad_duplicated(ifa);
994		} else {
995			/*
996			 * We are done with DAD.  No NA came, no NS came.
997			 * duplicated address found.
998			 */
999			ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1000
1001			/* XXXJRT This is probably a purely debugging message */
1002			printf("%s: DAD complete for %s - no duplicates "
1003			    "found\n", if_name(ifa->ifa_ifp),
1004			    ip6_sprintf(&ia->ia_addr.sin6_addr));
1005
1006			TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1007			free(dp, M_IP6NDP);
1008			dp = NULL;
1009			ifa->ifa_refcnt--;
1010		}
1011	}
1012
1013done:
1014	splx(s);
1015}
1016
1017void
1018nd6_dad_duplicated(ifa)
1019	struct ifaddr *ifa;
1020{
1021	struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1022	struct dadq *dp;
1023
1024	dp = nd6_dad_find(ifa);
1025	if (dp == NULL) {
1026		printf("nd6_dad_duplicated: DAD structure not found\n");
1027		return;
1028	}
1029
1030	log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: %d NS, "
1031	    "%d NA\n", if_name(ifa->ifa_ifp),
1032	    ip6_sprintf(&ia->ia_addr.sin6_addr),
1033	    dp->dad_ns_icount, dp->dad_na_icount);
1034
1035	ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1036	ia->ia6_flags |= IN6_IFF_DUPLICATED;
1037
1038	/* We are done with DAD, with duplicated address found. (failure) */
1039	untimeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa
1040		, dp->dad_timer);
1041
1042	printf("%s: DAD complete for %s - duplicate found\n",
1043	    if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
1044	printf("%s: manual intervention required\n", if_name(ifa->ifa_ifp));
1045
1046	TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1047	free(dp, M_IP6NDP);
1048	dp = NULL;
1049	ifa->ifa_refcnt--;
1050}
1051
1052void
1053nd6_dad_ns_input(ifa)
1054	struct ifaddr *ifa;
1055{
1056	struct in6_ifaddr *ia;
1057	struct ifnet *ifp;
1058	struct in6_addr *taddr6;
1059	struct dadq *dp;
1060	int duplicate;
1061
1062	if (!ifa)
1063		panic("ifa == NULL in nd6_dad_ns_input");
1064
1065	ia = (struct in6_ifaddr *)ifa;
1066	ifp = ifa->ifa_ifp;
1067	taddr6 = &ia->ia_addr.sin6_addr;
1068	duplicate = 0;
1069	dp = nd6_dad_find(ifa);
1070
1071	/*
1072	 * If it is from myself, ignore this.
1073	 */
1074	if (ifp && (ifp->if_flags & IFF_LOOPBACK))
1075		return;
1076
1077	/* Quickhack - completely ignore DAD NS packets */
1078	if (dad_ignore_ns) {
1079		log(LOG_INFO, "nd6_dad_ns_input: ignoring DAD NS packet for "
1080		    "address %s(%s)\n", ip6_sprintf(taddr6),
1081		    if_name(ifa->ifa_ifp));
1082		return;
1083	}
1084
1085	/*
1086	 * if I'm yet to start DAD, someone else started using this address
1087	 * first.  I have a duplicate and you win.
1088	 */
1089	if (!dp || dp->dad_ns_ocount == 0)
1090		duplicate++;
1091
1092	/* XXX more checks for loopback situation - see nd6_dad_timer too */
1093
1094	if (duplicate) {
1095		dp = NULL;	/* will be freed in nd6_dad_duplicated() */
1096		nd6_dad_duplicated(ifa);
1097	} else {
1098		/*
1099		 * not sure if I got a duplicate.
1100		 * increment ns count and see what happens.
1101		 */
1102		if (dp)
1103			dp->dad_ns_icount++;
1104	}
1105}
1106
1107void
1108nd6_dad_na_input(ifa)
1109	struct ifaddr *ifa;
1110{
1111	struct dadq *dp;
1112
1113	if (!ifa)
1114		panic("ifa == NULL in nd6_dad_na_input");
1115
1116	dp = nd6_dad_find(ifa);
1117	if (dp)
1118		dp->dad_na_icount++;
1119
1120	/* remove the address. */
1121	nd6_dad_duplicated(ifa);
1122}
1123