]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/nd6_nbr.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / netinet6 / nd6_nbr.c
CommitLineData
b0d623f7 1/*
39236c6e 2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
b0d623f7
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
1c79356b
A
28
29/*
30 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the project nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
1c79356b
A
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/malloc.h>
61#include <sys/mbuf.h>
62#include <sys/socket.h>
63#include <sys/sockio.h>
64#include <sys/time.h>
65#include <sys/kernel.h>
66#include <sys/errno.h>
1c79356b 67#include <sys/syslog.h>
6d2010ae
A
68#include <sys/sysctl.h>
69#include <sys/mcache.h>
70#include <sys/protosw.h>
1c79356b
A
71#include <kern/queue.h>
72
6d2010ae
A
73#include <kern/locks.h>
74#include <kern/zalloc.h>
75
1c79356b 76#include <net/if.h>
6d2010ae 77#include <net/if_var.h>
1c79356b
A
78#include <net/if_types.h>
79#include <net/if_dl.h>
6d2010ae 80#include <net/if_llreach.h>
1c79356b
A
81#include <net/route.h>
82
83#include <netinet/in.h>
84#include <netinet/in_var.h>
85#include <netinet6/in6_var.h>
39236c6e 86#include <netinet6/in6_ifattach.h>
1c79356b
A
87#include <netinet/ip6.h>
88#include <netinet6/ip6_var.h>
89#include <netinet6/nd6.h>
6d2010ae 90#include <netinet6/scope6_var.h>
1c79356b
A
91#include <netinet/icmp6.h>
92
1c79356b
A
93#if IPSEC
94#include <netinet6/ipsec.h>
9bccf70c
A
95#if INET6
96#include <netinet6/ipsec6.h>
97#endif
1c79356b
A
98#endif
99
1c79356b 100struct dadq;
91447636 101static struct dadq *nd6_dad_find(struct ifaddr *);
91447636 102void nd6_dad_stoptimer(struct ifaddr *);
91447636
A
103static void nd6_dad_timer(struct ifaddr *);
104static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
fe8ab488 105static void nd6_dad_ns_input(struct mbuf *, struct ifaddr *, char *, int);
39236c6e
A
106static struct mbuf *nd6_dad_na_input(struct mbuf *, struct ifnet *,
107 struct in6_addr *, caddr_t, int);
6d2010ae
A
108static void dad_addref(struct dadq *, int);
109static void dad_remref(struct dadq *);
110static struct dadq *nd6_dad_attach(struct dadq *, struct ifaddr *);
111static void nd6_dad_detach(struct dadq *, struct ifaddr *);
1c79356b 112
1c79356b
A
113static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
114
6d2010ae
A
115static unsigned int dad_size; /* size of zone element */
116static struct zone *dad_zone; /* zone for dadq */
117
118#define DAD_ZONE_MAX 64 /* maximum elements in zone */
119#define DAD_ZONE_NAME "nd6_dad" /* zone name */
120
121#define DAD_LOCK_ASSERT_HELD(_dp) \
122 lck_mtx_assert(&(_dp)->dad_lock, LCK_MTX_ASSERT_OWNED)
123
124#define DAD_LOCK_ASSERT_NOTHELD(_dp) \
125 lck_mtx_assert(&(_dp)->dad_lock, LCK_MTX_ASSERT_NOTOWNED)
126
127#define DAD_LOCK(_dp) \
128 lck_mtx_lock(&(_dp)->dad_lock)
129
130#define DAD_LOCK_SPIN(_dp) \
131 lck_mtx_lock_spin(&(_dp)->dad_lock)
132
133#define DAD_CONVERT_LOCK(_dp) do { \
134 DAD_LOCK_ASSERT_HELD(_dp); \
135 lck_mtx_convert_spin(&(_dp)->dad_lock); \
136} while (0)
137
138#define DAD_UNLOCK(_dp) \
139 lck_mtx_unlock(&(_dp)->dad_lock)
140
141#define DAD_ADDREF(_dp) \
142 dad_addref(_dp, 0)
143
144#define DAD_ADDREF_LOCKED(_dp) \
145 dad_addref(_dp, 1)
146
147#define DAD_REMREF(_dp) \
148 dad_remref(_dp)
149
91447636
A
150extern lck_mtx_t *dad6_mutex;
151extern lck_mtx_t *nd6_mutex;
6d2010ae
A
152
153static int nd6_llreach_base = (LL_BASE_REACHABLE / 1000); /* seconds */
154
316670eb
A
155static struct sockaddr_in6 hostrtmask;
156
6d2010ae
A
157SYSCTL_DECL(_net_inet6_icmp6);
158
159SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_llreach_base,
160 CTLFLAG_RW | CTLFLAG_LOCKED, &nd6_llreach_base, LL_BASE_REACHABLE,
161 "default ND6 link-layer reachability max lifetime (in seconds)");
162
1c79356b 163/*
6d2010ae
A
164 * Obtain a link-layer source cache entry for the sender.
165 *
166 * NOTE: This is currently only for ND6/Ethernet.
167 */
168void
169nd6_llreach_alloc(struct rtentry *rt, struct ifnet *ifp, void *addr,
170 unsigned int alen, boolean_t solicited)
171{
172 struct llinfo_nd6 *ln = rt->rt_llinfo;
173
174 if (nd6_llreach_base != 0 &&
db609669 175 (ln->ln_expire != 0 || (ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0) &&
39236c6e 176 !(rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
6d2010ae
A
177 ifp->if_addrlen == IF_LLREACH_MAXLEN && /* Ethernet */
178 alen == ifp->if_addrlen) {
179 struct if_llreach *lr;
180 const char *why = NULL, *type = "";
181
182 /* Become a regular mutex, just in case */
183 RT_CONVERT_LOCK(rt);
184
185 if ((lr = ln->ln_llreach) != NULL) {
186 type = (solicited ? "ND6 advertisement" :
187 "ND6 unsolicited announcement");
188 /*
189 * If target has changed, create a new record;
190 * otherwise keep existing record.
191 */
192 IFLR_LOCK(lr);
193 if (bcmp(addr, lr->lr_key.addr, alen) != 0) {
194 IFLR_UNLOCK(lr);
195 /* Purge any link-layer info caching */
196 VERIFY(rt->rt_llinfo_purge != NULL);
197 rt->rt_llinfo_purge(rt);
198 lr = NULL;
199 why = " for different target HW address; "
200 "using new llreach record";
201 } else {
202 lr->lr_probes = 0; /* reset probe count */
203 IFLR_UNLOCK(lr);
204 if (solicited) {
205 why = " for same target HW address; "
206 "keeping existing llreach record";
207 }
208 }
209 }
210
211 if (lr == NULL) {
212 lr = ln->ln_llreach = ifnet_llreach_alloc(ifp,
213 ETHERTYPE_IPV6, addr, alen, nd6_llreach_base);
214 if (lr != NULL) {
215 lr->lr_probes = 0; /* reset probe count */
216 if (why == NULL)
217 why = "creating new llreach record";
218 }
219 }
220
221 if (nd6_debug && lr != NULL && why != NULL) {
222 char tmp[MAX_IPv6_STR_LEN];
223
39236c6e
A
224 nd6log((LOG_DEBUG, "%s: %s%s for %s\n", if_name(ifp),
225 type, why, inet_ntop(AF_INET6,
6d2010ae
A
226 &SIN6(rt_key(rt))->sin6_addr, tmp, sizeof (tmp))));
227 }
228 }
229}
230
231void
232nd6_llreach_use(struct llinfo_nd6 *ln)
233{
234 if (ln->ln_llreach != NULL)
235 ln->ln_lastused = net_uptime();
236}
237
238/*
239 * Input a Neighbor Solicitation Message.
1c79356b 240 *
39236c6e
A
241 * Based on RFC 4861
242 * Based on RFC 4862 (duplicate address detection)
1c79356b
A
243 */
244void
91447636
A
245nd6_ns_input(
246 struct mbuf *m,
247 int off,
248 int icmp6len)
1c79356b
A
249{
250 struct ifnet *ifp = m->m_pkthdr.rcvif;
251 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
252 struct nd_neighbor_solicit *nd_ns;
253 struct in6_addr saddr6 = ip6->ip6_src;
254 struct in6_addr daddr6 = ip6->ip6_dst;
255 struct in6_addr taddr6;
256 struct in6_addr myaddr6;
257 char *lladdr = NULL;
b0d623f7 258 struct ifaddr *ifa = NULL;
1c79356b 259 int lladdrlen = 0;
316670eb 260 int anycast = 0, proxy = 0, dadprogress = 0;
1c79356b
A
261 int tlladdr;
262 union nd_opts ndopts;
b0d623f7 263 struct sockaddr_dl proxydl;
316670eb 264 boolean_t advrouter;
39236c6e 265 boolean_t is_dad_probe;
316670eb 266
db609669
A
267 if ((ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0) {
268 nd6log((LOG_INFO, "nd6_ns_input: on ND6ALT interface!\n"));
269 return;
270 }
271
316670eb
A
272 /* Expect 32-bit aligned data pointer on strict-align platforms */
273 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
1c79356b 274
91447636 275 IP6_EXTHDR_CHECK(m, off, icmp6len, return);
9bccf70c 276 nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
39236c6e
A
277 m->m_pkthdr.pkt_flags |= PKTF_INET6_RESOLVE;
278
9bccf70c
A
279 ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
280 taddr6 = nd_ns->nd_ns_target;
6d2010ae
A
281 if (in6_setscope(&taddr6, ifp, NULL) != 0)
282 goto bad;
9bccf70c 283
316670eb 284 if (ip6->ip6_hlim != IPV6_MAXHLIM) {
9bccf70c
A
285 nd6log((LOG_ERR,
286 "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
287 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
288 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
289 goto bad;
1c79356b
A
290 }
291
39236c6e
A
292 is_dad_probe = IN6_IS_ADDR_UNSPECIFIED(&saddr6);
293 if (is_dad_probe) {
6d2010ae
A
294 /* dst has to be a solicited node multicast address. */
295 if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
55e303ae 296 /* don't check ifindex portion */
6d2010ae
A
297 daddr6.s6_addr32[1] == 0 &&
298 daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
299 daddr6.s6_addr8[12] == 0xff) {
55e303ae 300 ; /* good */
1c79356b 301 } else {
9bccf70c
A
302 nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
303 "(wrong ip6 dst)\n"));
1c79356b
A
304 goto bad;
305 }
6d2010ae
A
306 } else if (!nd6_onlink_ns_rfc4861) {
307 struct sockaddr_in6 src_sa6;
308
309 /*
310 * According to recent IETF discussions, it is not a good idea
311 * to accept a NS from an address which would not be deemed
312 * to be a neighbor otherwise. This point is expected to be
313 * clarified in future revisions of the specification.
314 */
315 bzero(&src_sa6, sizeof(src_sa6));
316 src_sa6.sin6_family = AF_INET6;
317 src_sa6.sin6_len = sizeof(src_sa6);
318 src_sa6.sin6_addr = saddr6;
319 if (!nd6_is_addr_neighbor(&src_sa6, ifp, 0)) {
320 nd6log((LOG_INFO, "nd6_ns_input: "
321 "NS packet from non-neighbor\n"));
322 goto bad;
323 }
1c79356b
A
324 }
325
1c79356b 326 if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
9bccf70c 327 nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
1c79356b
A
328 goto bad;
329 }
330
1c79356b
A
331 icmp6len -= sizeof(*nd_ns);
332 nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
333 if (nd6_options(&ndopts) < 0) {
9bccf70c
A
334 nd6log((LOG_INFO,
335 "nd6_ns_input: invalid ND option, ignored\n"));
336 /* nd6_options have incremented stats */
337 goto freeit;
1c79356b
A
338 }
339
340 if (ndopts.nd_opts_src_lladdr) {
55e303ae 341 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
1c79356b
A
342 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
343 }
6d2010ae 344
39236c6e 345 if (is_dad_probe && lladdr) {
9bccf70c
A
346 nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
347 "(link-layer address option)\n"));
1c79356b
A
348 goto bad;
349 }
350
351 /*
352 * Attaching target link-layer address to the NA?
353 * (RFC 2461 7.2.4)
354 *
355 * NS IP dst is unicast/anycast MUST NOT add
356 * NS IP dst is solicited-node multicast MUST add
357 *
358 * In implementation, we add target link-layer address by default.
359 * We do not add one in MUST NOT cases.
360 */
1c79356b
A
361 if (!IN6_IS_ADDR_MULTICAST(&daddr6))
362 tlladdr = 0;
363 else
364 tlladdr = 1;
365
366 /*
367 * Target address (taddr6) must be either:
368 * (1) Valid unicast/anycast address for my receiving interface,
369 * (2) Unicast address for which I'm offering proxy service, or
316670eb 370 * (3) "tentative" or "optimistic" address [DAD is in progress].
1c79356b
A
371 */
372 /* (1) and (3) check. */
373 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
374
375 /* (2) check. */
6d2010ae 376 if (ifa == NULL) {
1c79356b
A
377 struct rtentry *rt;
378 struct sockaddr_in6 tsin6;
379
6d2010ae 380 bzero(&tsin6, sizeof tsin6);
1c79356b
A
381 tsin6.sin6_len = sizeof(struct sockaddr_in6);
382 tsin6.sin6_family = AF_INET6;
383 tsin6.sin6_addr = taddr6;
384
6d2010ae
A
385 rt = rtalloc1_scoped((struct sockaddr *)&tsin6, 0, 0,
386 ifp->if_index);
387
b0d623f7
A
388 if (rt != NULL) {
389 RT_LOCK(rt);
390 if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
391 rt->rt_gateway->sa_family == AF_LINK) {
392 /*
393 * proxy NDP for single entry
394 */
395 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(
396 ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
397 if (ifa) {
398 proxy = 1;
399 proxydl = *SDL(rt->rt_gateway);
400 }
1c79356b 401 }
b0d623f7 402 RT_UNLOCK(rt);
1c79356b 403 rtfree(rt);
b0d623f7 404 }
1c79356b 405 }
316670eb
A
406 if (ifa == NULL && ip6_forwarding && nd6_prproxy) {
407 /*
408 * Is the target address part of the prefix that is being
409 * proxied and installed on another interface?
410 */
411 ifa = (struct ifaddr *)in6ifa_prproxyaddr(&taddr6);
412 }
6d2010ae 413 if (ifa == NULL) {
1c79356b 414 /*
316670eb
A
415 * We've got an NS packet, and we don't have that address
416 * assigned for us. We MUST silently ignore it on this
417 * interface, c.f. RFC 4861 7.2.3.
418 *
419 * Forwarding associated with NDPRF_PRPROXY may apply.
1c79356b 420 */
316670eb
A
421 if (ip6_forwarding && nd6_prproxy)
422 nd6_prproxy_ns_input(ifp, &saddr6, lladdr,
423 lladdrlen, &daddr6, &taddr6);
1c79356b
A
424 goto freeit;
425 }
6d2010ae 426 IFA_LOCK(ifa);
1c79356b
A
427 myaddr6 = *IFA_IN6(ifa);
428 anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
316670eb
A
429 dadprogress =
430 ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DADPROGRESS;
6d2010ae
A
431 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED) {
432 IFA_UNLOCK(ifa);
1c79356b 433 goto freeit;
6d2010ae
A
434 }
435 IFA_UNLOCK(ifa);
1c79356b
A
436
437 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
9bccf70c 438 nd6log((LOG_INFO,
1c79356b
A
439 "nd6_ns_input: lladdrlen mismatch for %s "
440 "(if %d, NS packet %d)\n",
9bccf70c
A
441 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
442 goto bad;
1c79356b
A
443 }
444
445 if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
55e303ae
A
446 nd6log((LOG_INFO,
447 "nd6_ns_input: duplicate IP6 address %s\n",
448 ip6_sprintf(&saddr6)));
1c79356b
A
449 goto freeit;
450 }
451
452 /*
453 * We have neighbor solicitation packet, with target address equals to
316670eb 454 * one of my DAD in-progress addresses.
1c79356b
A
455 *
456 * src addr how to process?
457 * --- ---
458 * multicast of course, invalid (rejected in ip6_input)
459 * unicast somebody is doing address resolution -> ignore
460 * unspec dup address detection
461 *
39236c6e
A
462 * The processing is defined in the "draft standard" RFC 4862 (and by
463 * RFC 4429, which is a "proposed standard" update to its obsolete
464 * predecessor, RFC 2462) The reason optimistic DAD is not included
465 * in RFC 4862 is entirely due to IETF procedural considerations.
1c79356b 466 */
316670eb 467 if (dadprogress) {
1c79356b
A
468 /*
469 * If source address is unspecified address, it is for
6d2010ae 470 * duplicate address detection.
1c79356b
A
471 *
472 * If not, the packet is for addess resolution;
473 * silently ignore it.
474 */
39236c6e 475 if (is_dad_probe)
fe8ab488 476 nd6_dad_ns_input(m, ifa, lladdr, lladdrlen);
1c79356b
A
477
478 goto freeit;
479 }
480
316670eb
A
481 /* Are we an advertising router on this interface? */
482 advrouter = (ifp->if_eflags & IFEF_IPV6_ROUTER);
483
1c79356b
A
484 /*
485 * If the source address is unspecified address, entries must not
486 * be created or updated.
316670eb
A
487 * It looks that sender is performing DAD. If I'm using the address,
488 * and it's a "preferred" address, i.e. not optimistic, then output NA
489 * toward all-node multicast address, to tell the sender that I'm using
1c79356b
A
490 * the address.
491 * S bit ("solicited") must be zero.
492 */
39236c6e 493 if (is_dad_probe) {
1c79356b 494 saddr6 = in6addr_linklocal_allnodes;
6d2010ae
A
495 if (in6_setscope(&saddr6, ifp, NULL) != 0)
496 goto bad;
316670eb
A
497 if ((dadprogress & IN6_IFF_OPTIMISTIC) == 0)
498 nd6_na_output(ifp, &saddr6, &taddr6,
499 ((anycast || proxy || !tlladdr) ? 0 :
500 ND_NA_FLAG_OVERRIDE) | (advrouter ?
501 ND_NA_FLAG_ROUTER : 0), tlladdr, proxy ?
502 (struct sockaddr *)&proxydl : NULL);
1c79356b
A
503 goto freeit;
504 }
505
316670eb
A
506 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
507 ND_NEIGHBOR_SOLICIT, 0);
1c79356b
A
508
509 nd6_na_output(ifp, &saddr6, &taddr6,
316670eb
A
510 ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
511 (advrouter ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
512 tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL);
1c79356b
A
513 freeit:
514 m_freem(m);
b0d623f7 515 if (ifa != NULL)
6d2010ae 516 IFA_REMREF(ifa);
1c79356b
A
517 return;
518
519 bad:
9bccf70c
A
520 nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)));
521 nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)));
522 nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)));
523 icmp6stat.icp6s_badns++;
1c79356b 524 m_freem(m);
b0d623f7 525 if (ifa != NULL)
6d2010ae 526 IFA_REMREF(ifa);
1c79356b
A
527}
528
529/*
6d2010ae 530 * Output a Neighbor Solicitation Message. Caller specifies:
1c79356b
A
531 * - ICMP6 header source IP6 address
532 * - ND6 header target IP6 address
533 * - ND6 header source datalink address
534 *
39236c6e
A
535 * Based on RFC 4861
536 * Based on RFC 4862 (duplicate address detection)
537 * Based on RFC 4429 (optimistic duplicate address detection)
b0d623f7
A
538 *
539 * Caller must bump up ln->ln_rt refcnt to make sure 'ln' doesn't go
540 * away if there is a llinfo_nd6 passed in.
1c79356b
A
541 */
542void
91447636
A
543nd6_ns_output(
544 struct ifnet *ifp,
545 const struct in6_addr *daddr6,
546 const struct in6_addr *taddr6,
547 struct llinfo_nd6 *ln, /* for source address determination */
6d2010ae 548 int dad) /* duplicated address detection */
1c79356b
A
549{
550 struct mbuf *m;
551 struct ip6_hdr *ip6;
552 struct nd_neighbor_solicit *nd_ns;
553 struct in6_ifaddr *ia = NULL;
6d2010ae
A
554 struct in6_addr *src, src_in, src_storage;
555 struct ip6_moptions *im6o = NULL;
556 struct ifnet *outif = NULL;
1c79356b
A
557 int icmp6len;
558 int maxlen;
6d2010ae 559 int flags;
1c79356b 560 caddr_t mac;
6d2010ae 561 struct route_in6 ro;
39236c6e
A
562 struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 },
563 IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR, 0 };
316670eb 564 u_int32_t rtflags = 0;
6d2010ae 565
316670eb 566 if ((ifp->if_eflags & IFEF_IPV6_ND6ALT) || IN6_IS_ADDR_MULTICAST(taddr6))
1c79356b
A
567 return;
568
316670eb
A
569 bzero(&ro, sizeof(ro));
570
6d2010ae 571 ip6oa.ip6oa_boundif = ifp->if_index;
316670eb 572 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
6d2010ae 573
1c79356b
A
574 /* estimate the size of message */
575 maxlen = sizeof(*ip6) + sizeof(*nd_ns);
576 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
577 if (max_linkhdr + maxlen >= MCLBYTES) {
9bccf70c 578#if DIAGNOSTIC
1c79356b
A
579 printf("nd6_ns_output: max_linkhdr + maxlen >= MCLBYTES "
580 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
581#endif
582 return;
583 }
584
2d21ac55 585 MGETHDR(m, M_DONTWAIT, MT_DATA); /* XXXMAC: mac_create_mbuf_linklayer() probably */
1c79356b
A
586 if (m && max_linkhdr + maxlen >= MHLEN) {
587 MCLGET(m, M_DONTWAIT);
588 if ((m->m_flags & M_EXT) == 0) {
589 m_free(m);
590 m = NULL;
591 }
592 }
593 if (m == NULL)
594 return;
9bccf70c 595 m->m_pkthdr.rcvif = NULL;
1c79356b
A
596
597 if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
598 m->m_flags |= M_MCAST;
6d2010ae
A
599
600 im6o = ip6_allocmoptions(M_DONTWAIT);
601 if (im6o == NULL) {
602 m_freem(m);
603 return;
604 }
605
606 im6o->im6o_multicast_ifp = ifp;
316670eb 607 im6o->im6o_multicast_hlim = IPV6_MAXHLIM;
6d2010ae 608 im6o->im6o_multicast_loop = 0;
1c79356b
A
609 }
610
611 icmp6len = sizeof(*nd_ns);
612 m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
55e303ae 613 m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */
1c79356b
A
614
615 /* fill neighbor solicitation packet */
616 ip6 = mtod(m, struct ip6_hdr *);
617 ip6->ip6_flow = 0;
618 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
619 ip6->ip6_vfc |= IPV6_VERSION;
620 /* ip6->ip6_plen will be set later */
621 ip6->ip6_nxt = IPPROTO_ICMPV6;
316670eb 622 ip6->ip6_hlim = IPV6_MAXHLIM;
1c79356b
A
623 if (daddr6)
624 ip6->ip6_dst = *daddr6;
625 else {
626 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
6d2010ae 627 ip6->ip6_dst.s6_addr16[1] = 0;
1c79356b
A
628 ip6->ip6_dst.s6_addr32[1] = 0;
629 ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
630 ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
631 ip6->ip6_dst.s6_addr8[12] = 0xff;
6d2010ae
A
632 if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0)
633 goto bad;
1c79356b
A
634 }
635 if (!dad) {
1c79356b
A
636 /*
637 * RFC2461 7.2.2:
638 * "If the source address of the packet prompting the
639 * solicitation is the same as one of the addresses assigned
640 * to the outgoing interface, that address SHOULD be placed
641 * in the IP Source Address of the outgoing solicitation.
642 * Otherwise, any one of the addresses assigned to the
643 * interface should be used."
644 *
645 * We use the source address for the prompting packet
646 * (saddr6), if:
647 * - saddr6 is given from the caller (by giving "ln"), and
648 * - saddr6 belongs to the outgoing interface.
6d2010ae 649 * Otherwise, we perform the source address selection as usual.
1c79356b 650 */
6d2010ae
A
651 struct ip6_hdr *hip6; /* hold ip6 */
652 struct in6_addr *hsrc = NULL;
b0d623f7
A
653
654 /* Caller holds ref on this route */
655 if (ln != NULL) {
656 RT_LOCK(ln->ln_rt);
6d2010ae
A
657 /*
658 * assuming every packet in ln_hold has the same IP
659 * header
660 */
b0d623f7
A
661 if (ln->ln_hold != NULL) {
662 hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
663 /* XXX pullup? */
664 if (sizeof (*hip6) < ln->ln_hold->m_len)
6d2010ae 665 hsrc = &hip6->ip6_src;
b0d623f7 666 else
6d2010ae
A
667 hsrc = NULL;
668 }
669 /* Update probe count, if applicable */
670 if (ln->ln_llreach != NULL) {
671 IFLR_LOCK_SPIN(ln->ln_llreach);
672 ln->ln_llreach->lr_probes++;
673 IFLR_UNLOCK(ln->ln_llreach);
b0d623f7 674 }
316670eb 675 rtflags = ln->ln_rt->rt_flags;
b0d623f7 676 RT_UNLOCK(ln->ln_rt);
1c79356b 677 }
316670eb
A
678 if (hsrc != NULL && (ia = in6ifa_ifpwithaddr(ifp, hsrc)) &&
679 (ia->ia6_flags & IN6_IFF_OPTIMISTIC) == 0) {
6d2010ae 680 src = hsrc;
6d2010ae
A
681 } else {
682 int error;
683 struct sockaddr_in6 dst_sa;
684
685 bzero(&dst_sa, sizeof(dst_sa));
686 dst_sa.sin6_family = AF_INET6;
687 dst_sa.sin6_len = sizeof(dst_sa);
688 dst_sa.sin6_addr = ip6->ip6_dst;
689
690 src = in6_selectsrc(&dst_sa, NULL,
691 NULL, &ro, NULL, &src_storage, ip6oa.ip6oa_boundif,
692 &error);
693 if (src == NULL) {
694 nd6log((LOG_DEBUG,
695 "nd6_ns_output: source can't be "
696 "determined: dst=%s, error=%d\n",
697 ip6_sprintf(&dst_sa.sin6_addr),
698 error));
699 goto bad;
700 }
316670eb 701
39236c6e
A
702 if (ia != NULL) {
703 IFA_REMREF(&ia->ia_ifa);
704 ia = NULL;
705 }
fe8ab488
A
706 /*
707 * RFC 4429 section 3.2:
708 * When a node has a unicast packet to send
709 * from an Optimistic Address to a neighbor,
710 * but does not know the neighbor's link-layer
711 * address, it MUST NOT perform Address
712 * Resolution.
713 */
316670eb
A
714 ia = in6ifa_ifpwithaddr(ifp, src);
715 if (!ia || (ia->ia6_flags & IN6_IFF_OPTIMISTIC)) {
716 nd6log((LOG_DEBUG,
717 "nd6_ns_output: no preferred source "
718 "available: dst=%s\n",
719 ip6_sprintf(&dst_sa.sin6_addr)));
720 goto bad;
721 }
6d2010ae 722 }
1c79356b
A
723 } else {
724 /*
725 * Source address for DAD packet must always be IPv6
726 * unspecified address. (0::0)
6d2010ae
A
727 * We actually don't have to 0-clear the address (we did it
728 * above), but we do so here explicitly to make the intention
729 * clearer.
1c79356b 730 */
6d2010ae
A
731 bzero(&src_in, sizeof(src_in));
732 src = &src_in;
316670eb 733 ip6oa.ip6oa_flags &= ~IP6OAF_BOUND_SRCADDR;
1c79356b 734 }
6d2010ae 735 ip6->ip6_src = *src;
1c79356b
A
736 nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
737 nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
738 nd_ns->nd_ns_code = 0;
739 nd_ns->nd_ns_reserved = 0;
740 nd_ns->nd_ns_target = *taddr6;
6d2010ae 741 in6_clearscope(&nd_ns->nd_ns_target); /* XXX */
1c79356b
A
742
743 /*
744 * Add source link-layer address option.
745 *
746 * spec implementation
747 * --- ---
748 * DAD packet MUST NOT do not add the option
749 * there's no link layer address:
750 * impossible do not add the option
751 * there's link layer address:
752 * Multicast NS MUST add one add the option
753 * Unicast NS SHOULD add one add the option
754 */
755 if (!dad && (mac = nd6_ifptomac(ifp))) {
756 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
757 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
758 /* 8 byte alignments... */
759 optlen = (optlen + 7) & ~7;
316670eb 760
1c79356b
A
761 m->m_pkthdr.len += optlen;
762 m->m_len += optlen;
763 icmp6len += optlen;
764 bzero((caddr_t)nd_opt, optlen);
765 nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
766 nd_opt->nd_opt_len = optlen >> 3;
767 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
768 }
769
770 ip6->ip6_plen = htons((u_short)icmp6len);
771 nd_ns->nd_ns_cksum = 0;
772 nd_ns->nd_ns_cksum
773 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
774
6d2010ae
A
775 flags = dad ? IPV6_UNSPECSRC : 0;
776 flags |= IPV6_OUTARGS;
777
39236c6e
A
778 /*
779 * PKTF_{INET,INET6}_RESOLVE_RTR are mutually exclusive, so make
780 * sure only one of them is set (just in case.)
781 */
782 m->m_pkthdr.pkt_flags &= ~(PKTF_INET_RESOLVE | PKTF_RESOLVE_RTR);
783 m->m_pkthdr.pkt_flags |= PKTF_INET6_RESOLVE;
316670eb
A
784 /*
785 * If this is a NS for resolving the (default) router, mark
786 * the packet accordingly so that the driver can find out,
787 * in case it needs to perform driver-specific action(s).
788 */
39236c6e
A
789 if (rtflags & RTF_ROUTER)
790 m->m_pkthdr.pkt_flags |= PKTF_RESOLVE_RTR;
316670eb
A
791
792 if (ifp->if_eflags & IFEF_TXSTART) {
39236c6e
A
793 /*
794 * Use control service class if the interface
316670eb
A
795 * supports transmit-start model
796 */
797 (void) m_set_service_class(m, MBUF_SC_CTL);
798 }
799
6d2010ae 800 ip6_output(m, NULL, NULL, flags, im6o, &outif, &ip6oa);
1c79356b
A
801 if (outif) {
802 icmp6_ifstat_inc(outif, ifs6_out_msg);
803 icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit);
6d2010ae 804 ifnet_release(outif);
1c79356b
A
805 }
806 icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
6d2010ae 807
39236c6e 808exit:
6d2010ae
A
809 if (im6o != NULL)
810 IM6O_REMREF(im6o);
39236c6e
A
811
812 ROUTE_RELEASE(&ro); /* we don't cache this route. */
813
6d2010ae
A
814 if (ia != NULL)
815 IFA_REMREF(&ia->ia_ifa);
816 return;
817
818bad:
6d2010ae 819 m_freem(m);
39236c6e 820 goto exit;
1c79356b
A
821}
822
823/*
824 * Neighbor advertisement input handling.
825 *
39236c6e
A
826 * Based on RFC 4861
827 * Based on RFC 4862 (duplicate address detection)
1c79356b
A
828 *
829 * the following items are not implemented yet:
39236c6e
A
830 * - anycast advertisement delay rule (RFC 4861 7.2.7, SHOULD)
831 * - proxy advertisement delay rule (RFC 4861 7.2.8, last paragraph, "should")
1c79356b
A
832 */
833void
39236c6e 834nd6_na_input(struct mbuf *m, int off, int icmp6len)
1c79356b
A
835{
836 struct ifnet *ifp = m->m_pkthdr.rcvif;
837 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
838 struct nd_neighbor_advert *nd_na;
316670eb 839 struct in6_addr saddr6 = ip6->ip6_src;
1c79356b
A
840 struct in6_addr daddr6 = ip6->ip6_dst;
841 struct in6_addr taddr6;
842 int flags;
843 int is_router;
844 int is_solicited;
845 int is_override;
846 char *lladdr = NULL;
847 int lladdrlen = 0;
1c79356b
A
848 struct llinfo_nd6 *ln;
849 struct rtentry *rt;
850 struct sockaddr_dl *sdl;
851 union nd_opts ndopts;
39236c6e 852 uint64_t timenow;
1c79356b 853
db609669
A
854 if ((ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0) {
855 nd6log((LOG_INFO, "nd6_na_input: on ND6ALT interface!\n"));
856 return;
857 }
858
316670eb
A
859 /* Expect 32-bit aligned data pointer on strict-align platforms */
860 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
861
862 if (ip6->ip6_hlim != IPV6_MAXHLIM) {
9bccf70c
A
863 nd6log((LOG_ERR,
864 "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
865 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
866 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
867 goto bad;
1c79356b
A
868 }
869
91447636 870 IP6_EXTHDR_CHECK(m, off, icmp6len, return);
1c79356b 871 nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
39236c6e 872 m->m_pkthdr.pkt_flags |= PKTF_INET6_RESOLVE;
6d2010ae 873
1c79356b
A
874 flags = nd_na->nd_na_flags_reserved;
875 is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
876 is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
877 is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
878
6d2010ae
A
879 taddr6 = nd_na->nd_na_target;
880 if (in6_setscope(&taddr6, ifp, NULL))
881 goto bad; /* XXX: impossible */
1c79356b
A
882
883 if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
9bccf70c 884 nd6log((LOG_ERR,
1c79356b 885 "nd6_na_input: invalid target address %s\n",
9bccf70c
A
886 ip6_sprintf(&taddr6)));
887 goto bad;
1c79356b
A
888 }
889 if (IN6_IS_ADDR_MULTICAST(&daddr6))
890 if (is_solicited) {
9bccf70c
A
891 nd6log((LOG_ERR,
892 "nd6_na_input: a solicited adv is multicasted\n"));
893 goto bad;
1c79356b
A
894 }
895
896 icmp6len -= sizeof(*nd_na);
897 nd6_option_init(nd_na + 1, icmp6len, &ndopts);
898 if (nd6_options(&ndopts) < 0) {
9bccf70c
A
899 nd6log((LOG_INFO,
900 "nd6_na_input: invalid ND option, ignored\n"));
901 /* nd6_options have incremented stats */
1c79356b
A
902 goto freeit;
903 }
904
905 if (ndopts.nd_opts_tgt_lladdr) {
906 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
907 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
1c79356b 908
39236c6e
A
909 if (((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
910 nd6log((LOG_INFO,
911 "nd6_na_input: lladdrlen mismatch for %s "
912 "(if %d, NA packet %d)\n",
913 ip6_sprintf(&taddr6), ifp->if_addrlen,
914 lladdrlen - 2));
915 goto bad;
6d2010ae 916 }
1c79356b
A
917 }
918
39236c6e
A
919 m = nd6_dad_na_input(m, ifp, &taddr6, lladdr, lladdrlen);
920 if (m == NULL)
921 return;
1c79356b 922
316670eb
A
923 /* Forwarding associated with NDPRF_PRPROXY may apply. */
924 if (ip6_forwarding && nd6_prproxy)
925 nd6_prproxy_na_input(ifp, &saddr6, &daddr6, &taddr6, flags);
926
1c79356b 927 /*
6d2010ae 928 * If no neighbor cache entry is found, NA SHOULD silently be
316670eb
A
929 * discarded. If we are forwarding (and Scoped Routing is in
930 * effect), try to see if there is a neighbor cache entry on
931 * another interface (in case we are doing prefix proxying.)
1c79356b 932 */
316670eb
A
933 if ((rt = nd6_lookup(&taddr6, 0, ifp, 0)) == NULL) {
934 if (!ip6_forwarding || !ip6_doscopedroute || !nd6_prproxy)
935 goto freeit;
936
937 if ((rt = nd6_lookup(&taddr6, 0, NULL, 0)) == NULL)
938 goto freeit;
939
940 RT_LOCK_ASSERT_HELD(rt);
941 if (rt->rt_ifp != ifp) {
942 /*
943 * Purge any link-layer info caching.
944 */
945 if (rt->rt_llinfo_purge != NULL)
946 rt->rt_llinfo_purge(rt);
947
948 /* Adjust route ref count for the interfaces */
949 if (rt->rt_if_ref_fn != NULL) {
950 rt->rt_if_ref_fn(ifp, 1);
951 rt->rt_if_ref_fn(rt->rt_ifp, -1);
952 }
953
954 /* Change the interface when the existing route is on */
955 rt->rt_ifp = ifp;
39236c6e
A
956
957 /*
958 * If rmx_mtu is not locked, update it
959 * to the MTU used by the new interface.
960 */
961 if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
962 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
316670eb
A
963 }
964 }
b0d623f7
A
965
966 RT_LOCK_ASSERT_HELD(rt);
967 if ((ln = rt->rt_llinfo) == NULL ||
968 (sdl = SDL(rt->rt_gateway)) == NULL) {
969 RT_REMREF_LOCKED(rt);
970 RT_UNLOCK(rt);
1c79356b 971 goto freeit;
b0d623f7 972 }
1c79356b 973
39236c6e
A
974 timenow = net_uptime();
975
1c79356b
A
976 if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
977 /*
978 * If the link-layer has address, and no lladdr option came,
979 * discard the packet.
980 */
b0d623f7
A
981 if (ifp->if_addrlen && !lladdr) {
982 RT_REMREF_LOCKED(rt);
983 RT_UNLOCK(rt);
1c79356b 984 goto freeit;
b0d623f7 985 }
1c79356b
A
986
987 /*
988 * Record link-layer address, and update the state.
989 */
990 sdl->sdl_alen = ifp->if_addrlen;
991 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
992 if (is_solicited) {
993 ln->ln_state = ND6_LLINFO_REACHABLE;
39236c6e 994 if (ln->ln_expire != 0) {
316670eb
A
995 struct nd_ifinfo *ndi;
996
b0d623f7 997 lck_rw_lock_shared(nd_if_rwlock);
316670eb
A
998 ndi = ND_IFINFO(rt->rt_ifp);
999 VERIFY(ndi != NULL && ndi->initialized);
1000 lck_mtx_lock(&ndi->lock);
39236c6e 1001 ln_setexpire(ln, timenow + ndi->reachable);
316670eb 1002 lck_mtx_unlock(&ndi->lock);
b0d623f7 1003 lck_rw_done(nd_if_rwlock);
39236c6e
A
1004 RT_UNLOCK(rt);
1005 lck_mtx_lock(rnh_lock);
1006 nd6_sched_timeout(NULL, NULL);
1007 lck_mtx_unlock(rnh_lock);
1008 RT_LOCK(rt);
b0d623f7 1009 }
9bccf70c 1010 } else {
1c79356b 1011 ln->ln_state = ND6_LLINFO_STALE;
39236c6e 1012 ln_setexpire(ln, timenow + nd6_gctimer);
9bccf70c
A
1013 }
1014 if ((ln->ln_router = is_router) != 0) {
1015 /*
1016 * This means a router's state has changed from
1017 * non-reachable to probably reachable, and might
1018 * affect the status of associated prefixes..
1019 */
b0d623f7 1020 RT_UNLOCK(rt);
6d2010ae
A
1021 lck_mtx_lock(nd6_mutex);
1022 pfxlist_onlink_check();
1023 lck_mtx_unlock(nd6_mutex);
b0d623f7 1024 RT_LOCK(rt);
9bccf70c 1025 }
1c79356b
A
1026 } else {
1027 int llchange;
1028
1029 /*
1030 * Check if the link-layer address has changed or not.
1031 */
1032 if (!lladdr)
1033 llchange = 0;
1034 else {
1035 if (sdl->sdl_alen) {
1036 if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
1037 llchange = 1;
1038 else
1039 llchange = 0;
1040 } else
1041 llchange = 1;
1042 }
1043
1044 /*
1045 * This is VERY complex. Look at it with care.
1046 *
1047 * override solicit lladdr llchange action
1048 * (L: record lladdr)
1049 *
1050 * 0 0 n -- (2c)
1051 * 0 0 y n (2b) L
1052 * 0 0 y y (1) REACHABLE->STALE
1053 * 0 1 n -- (2c) *->REACHABLE
1054 * 0 1 y n (2b) L *->REACHABLE
1055 * 0 1 y y (1) REACHABLE->STALE
1056 * 1 0 n -- (2a)
1057 * 1 0 y n (2a) L
1058 * 1 0 y y (2a) L *->STALE
1059 * 1 1 n -- (2a) *->REACHABLE
1060 * 1 1 y n (2a) L *->REACHABLE
1061 * 1 1 y y (2a) L *->REACHABLE
1062 */
6d2010ae 1063 if (!is_override && (lladdr != NULL && llchange)) { /* (1) */
1c79356b
A
1064 /*
1065 * If state is REACHABLE, make it STALE.
1066 * no other updates should be done.
1067 */
9bccf70c 1068 if (ln->ln_state == ND6_LLINFO_REACHABLE) {
1c79356b 1069 ln->ln_state = ND6_LLINFO_STALE;
39236c6e 1070 ln_setexpire(ln, timenow + nd6_gctimer);
9bccf70c 1071 }
b0d623f7
A
1072 RT_REMREF_LOCKED(rt);
1073 RT_UNLOCK(rt);
1c79356b
A
1074 goto freeit;
1075 } else if (is_override /* (2a) */
1076 || (!is_override && (lladdr && !llchange)) /* (2b) */
1077 || !lladdr) { /* (2c) */
1078 /*
1079 * Update link-local address, if any.
1080 */
1081 if (lladdr) {
1082 sdl->sdl_alen = ifp->if_addrlen;
1083 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
1084 }
1085
1086 /*
1087 * If solicited, make the state REACHABLE.
1088 * If not solicited and the link-layer address was
1089 * changed, make it STALE.
1090 */
1091 if (is_solicited) {
1092 ln->ln_state = ND6_LLINFO_REACHABLE;
39236c6e 1093 if (ln->ln_expire != 0) {
316670eb
A
1094 struct nd_ifinfo *ndi;
1095
b0d623f7 1096 lck_rw_lock_shared(nd_if_rwlock);
316670eb
A
1097 ndi = ND_IFINFO(ifp);
1098 VERIFY(ndi != NULL && ndi->initialized);
1099 lck_mtx_lock(&ndi->lock);
39236c6e
A
1100 ln_setexpire(ln,
1101 timenow + ndi->reachable);
316670eb 1102 lck_mtx_unlock(&ndi->lock);
b0d623f7 1103 lck_rw_done(nd_if_rwlock);
39236c6e
A
1104 RT_UNLOCK(rt);
1105 lck_mtx_lock(rnh_lock);
1106 nd6_sched_timeout(NULL, NULL);
1107 lck_mtx_unlock(rnh_lock);
1108 RT_LOCK(rt);
1c79356b
A
1109 }
1110 } else {
9bccf70c 1111 if (lladdr && llchange) {
1c79356b 1112 ln->ln_state = ND6_LLINFO_STALE;
39236c6e 1113 ln_setexpire(ln, timenow + nd6_gctimer);
9bccf70c 1114 }
1c79356b
A
1115 }
1116 }
1117
1118 if (ln->ln_router && !is_router) {
1119 /*
1120 * The peer dropped the router flag.
1121 * Remove the sender from the Default Router List and
1122 * update the Destination Cache entries.
1123 */
1124 struct nd_defrouter *dr;
1125 struct in6_addr *in6;
b0d623f7 1126 struct ifnet *rt_ifp = rt->rt_ifp;
1c79356b 1127
316670eb
A
1128 in6 = &((struct sockaddr_in6 *)
1129 (void *)rt_key(rt))->sin6_addr;
55e303ae 1130
b0d623f7 1131 RT_UNLOCK(rt);
91447636 1132 lck_mtx_lock(nd6_mutex);
b0d623f7 1133 dr = defrouter_lookup(in6, rt_ifp);
91447636 1134 if (dr) {
6d2010ae
A
1135 defrtrlist_del(dr);
1136 NDDR_REMREF(dr);
91447636 1137 lck_mtx_unlock(nd6_mutex);
316670eb 1138 } else {
91447636 1139 lck_mtx_unlock(nd6_mutex);
316670eb 1140 if (ip6_doscopedroute || !ip6_forwarding) {
91447636 1141 /*
316670eb
A
1142 * Even if the neighbor is not in the
1143 * default router list, the neighbor
1144 * may be used as a next hop for some
1145 * destinations (e.g. redirect case).
1146 * So we must call rt6_flush explicitly.
91447636 1147 */
b0d623f7 1148 rt6_flush(&ip6->ip6_src, rt_ifp);
91447636 1149 }
1c79356b 1150 }
b0d623f7 1151 RT_LOCK(rt);
1c79356b
A
1152 }
1153 ln->ln_router = is_router;
1154 }
b0d623f7 1155 RT_LOCK_ASSERT_HELD(rt);
1c79356b 1156 rt->rt_flags &= ~RTF_REJECT;
6d2010ae
A
1157
1158 /* cache the gateway (sender HW) address */
1159 nd6_llreach_alloc(rt, ifp, LLADDR(sdl), sdl->sdl_alen, TRUE);
1160
1161 /* update the llinfo, send a queued packet if there is one */
1c79356b 1162 ln->ln_asked = 0;
b0d623f7 1163 if (ln->ln_hold != NULL) {
6d2010ae
A
1164 struct mbuf *m_hold, *m_hold_next;
1165 struct sockaddr_in6 sin6;
1166
1167 rtkey_to_sa6(rt, &sin6);
9bccf70c 1168 /*
6d2010ae
A
1169 * reset the ln_hold in advance, to explicitly
1170 * prevent a ln_hold lookup in nd6_output()
1171 * (wouldn't happen, though...)
9bccf70c 1172 */
6d2010ae
A
1173 for (m_hold = ln->ln_hold;
1174 m_hold; m_hold = m_hold_next) {
1175 m_hold_next = m_hold->m_nextpkt;
1176 m_hold->m_nextpkt = NULL;
1177 /*
1178 * we assume ifp is not a loopback here, so just set
1179 * the 2nd argument as the 1st one.
1180 */
1181 RT_UNLOCK(rt);
316670eb 1182 nd6_output(ifp, ifp, m_hold, &sin6, rt, NULL);
6d2010ae
A
1183 RT_LOCK_SPIN(rt);
1184 }
1185 ln->ln_hold = NULL;
1186
1c79356b 1187 }
b0d623f7
A
1188 RT_REMREF_LOCKED(rt);
1189 RT_UNLOCK(rt);
1c79356b 1190
6d2010ae 1191bad:
9bccf70c 1192 icmp6stat.icp6s_badna++;
39236c6e
A
1193 /* fall through */
1194
1195freeit:
9bccf70c 1196 m_freem(m);
1c79356b
A
1197}
1198
1199/*
1200 * Neighbor advertisement output handling.
1201 *
1202 * Based on RFC 2461
1203 *
1204 * the following items are not implemented yet:
1205 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
1206 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
6d2010ae
A
1207 *
1208 * tlladdr - 1 if include target link-layer address
1209 * sdl0 - sockaddr_dl (= proxy NA) or NULL
1c79356b
A
1210 */
1211void
91447636
A
1212nd6_na_output(
1213 struct ifnet *ifp,
6d2010ae 1214 const struct in6_addr *daddr6_0,
91447636 1215 const struct in6_addr *taddr6,
b0d623f7 1216 uint32_t flags,
91447636
A
1217 int tlladdr, /* 1 if include target link-layer address */
1218 struct sockaddr *sdl0) /* sockaddr_dl (= proxy NA) or NULL */
1c79356b
A
1219{
1220 struct mbuf *m;
1221 struct ip6_hdr *ip6;
1222 struct nd_neighbor_advert *nd_na;
6d2010ae 1223 struct ip6_moptions *im6o = NULL;
55e303ae 1224 caddr_t mac = NULL;
6d2010ae
A
1225 struct route_in6 ro;
1226 struct in6_addr *src, src_storage, daddr6;
316670eb 1227 struct in6_ifaddr *ia;
6d2010ae
A
1228 struct sockaddr_in6 dst_sa;
1229 int icmp6len, maxlen, error;
1230 struct ifnet *outif = NULL;
39236c6e
A
1231 struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 },
1232 IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR, 0 };
6d2010ae
A
1233
1234 bzero(&ro, sizeof(ro));
1235
1236 daddr6 = *daddr6_0; /* make a local copy for modification */
1237
1238 ip6oa.ip6oa_boundif = ifp->if_index;
316670eb 1239 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
1c79356b
A
1240
1241 /* estimate the size of message */
1242 maxlen = sizeof(*ip6) + sizeof(*nd_na);
1243 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
1244 if (max_linkhdr + maxlen >= MCLBYTES) {
9bccf70c 1245#if DIAGNOSTIC
1c79356b
A
1246 printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES "
1247 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
1248#endif
1249 return;
1250 }
1251
2d21ac55 1252 MGETHDR(m, M_DONTWAIT, MT_DATA); /* XXXMAC: mac_create_mbuf_linklayer() probably */
1c79356b
A
1253 if (m && max_linkhdr + maxlen >= MHLEN) {
1254 MCLGET(m, M_DONTWAIT);
1255 if ((m->m_flags & M_EXT) == 0) {
1256 m_free(m);
1257 m = NULL;
1258 }
1259 }
1260 if (m == NULL)
1261 return;
9bccf70c 1262 m->m_pkthdr.rcvif = NULL;
1c79356b 1263
6d2010ae 1264 if (IN6_IS_ADDR_MULTICAST(&daddr6)) {
1c79356b 1265 m->m_flags |= M_MCAST;
6d2010ae
A
1266
1267 im6o = ip6_allocmoptions(M_DONTWAIT);
1268 if (im6o == NULL) {
1269 m_freem(m);
1270 return;
1271 }
1272
1273 im6o->im6o_multicast_ifp = ifp;
316670eb 1274 im6o->im6o_multicast_hlim = IPV6_MAXHLIM;
6d2010ae 1275 im6o->im6o_multicast_loop = 0;
1c79356b
A
1276 }
1277
1278 icmp6len = sizeof(*nd_na);
1279 m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
55e303ae 1280 m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */
1c79356b
A
1281
1282 /* fill neighbor advertisement packet */
1283 ip6 = mtod(m, struct ip6_hdr *);
1284 ip6->ip6_flow = 0;
1285 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1286 ip6->ip6_vfc |= IPV6_VERSION;
1287 ip6->ip6_nxt = IPPROTO_ICMPV6;
316670eb 1288 ip6->ip6_hlim = IPV6_MAXHLIM;
6d2010ae 1289 if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
1c79356b 1290 /* reply to DAD */
6d2010ae
A
1291 daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
1292 daddr6.s6_addr16[1] = 0;
1293 daddr6.s6_addr32[1] = 0;
1294 daddr6.s6_addr32[2] = 0;
1295 daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
1296 if (in6_setscope(&daddr6, ifp, NULL))
1297 goto bad;
1298
1c79356b
A
1299 flags &= ~ND_NA_FLAG_SOLICITED;
1300 } else
6d2010ae
A
1301 ip6->ip6_dst = daddr6;
1302
1303 bzero(&dst_sa, sizeof(struct sockaddr_in6));
1304 dst_sa.sin6_family = AF_INET6;
1305 dst_sa.sin6_len = sizeof(struct sockaddr_in6);
1306 dst_sa.sin6_addr = daddr6;
1c79356b
A
1307
1308 /*
1309 * Select a source whose scope is the same as that of the dest.
1310 */
6d2010ae
A
1311 bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
1312 src = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &src_storage,
1313 ip6oa.ip6oa_boundif, &error);
1314 if (src == NULL) {
1315 nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
1316 "determined: dst=%s, error=%d\n",
1317 ip6_sprintf(&dst_sa.sin6_addr), error));
1318 goto bad;
1c79356b 1319 }
6d2010ae 1320 ip6->ip6_src = *src;
b0d623f7 1321
316670eb
A
1322 /*
1323 * RFC 4429 requires not setting "override" flag on NA packets sent
1324 * from optimistic addresses.
1325 */
1326 ia = in6ifa_ifpwithaddr(ifp, src);
1327 if (ia != NULL) {
1328 if (ia->ia6_flags & IN6_IFF_OPTIMISTIC)
1329 flags &= ~ND_NA_FLAG_OVERRIDE;
1330 IFA_REMREF(&ia->ia_ifa);
1331 }
1332
1c79356b
A
1333 nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
1334 nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
1335 nd_na->nd_na_code = 0;
1336 nd_na->nd_na_target = *taddr6;
6d2010ae 1337 in6_clearscope(&nd_na->nd_na_target); /* XXX */
1c79356b
A
1338
1339 /*
1340 * "tlladdr" indicates NS's condition for adding tlladdr or not.
1341 * see nd6_ns_input() for details.
1342 * Basically, if NS packet is sent to unicast/anycast addr,
1343 * target lladdr option SHOULD NOT be included.
1344 */
1345 if (tlladdr) {
1c79356b
A
1346 /*
1347 * sdl0 != NULL indicates proxy NA. If we do proxy, use
1348 * lladdr in sdl0. If we are not proxying (sending NA for
1349 * my address) use lladdr configured for the interface.
1350 */
1351 if (sdl0 == NULL)
1352 mac = nd6_ifptomac(ifp);
1353 else if (sdl0->sa_family == AF_LINK) {
1354 struct sockaddr_dl *sdl;
316670eb 1355 sdl = (struct sockaddr_dl *)(void *)sdl0;
1c79356b
A
1356 if (sdl->sdl_alen == ifp->if_addrlen)
1357 mac = LLADDR(sdl);
1358 }
1359 }
1360 if (tlladdr && mac) {
1361 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
1362 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
6d2010ae 1363
1c79356b
A
1364 /* roundup to 8 bytes alignment! */
1365 optlen = (optlen + 7) & ~7;
1366
1367 m->m_pkthdr.len += optlen;
1368 m->m_len += optlen;
1369 icmp6len += optlen;
1370 bzero((caddr_t)nd_opt, optlen);
1371 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
1372 nd_opt->nd_opt_len = optlen >> 3;
1373 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
1374 } else
1375 flags &= ~ND_NA_FLAG_OVERRIDE;
1376
1377 ip6->ip6_plen = htons((u_short)icmp6len);
1378 nd_na->nd_na_flags_reserved = flags;
1379 nd_na->nd_na_cksum = 0;
1380 nd_na->nd_na_cksum =
1381 in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
1382
39236c6e 1383 m->m_pkthdr.pkt_flags |= PKTF_INET6_RESOLVE;
316670eb
A
1384
1385 if (ifp->if_eflags & IFEF_TXSTART) {
1386 /* Use control service class if the interface supports
1387 * transmit-start model.
1388 */
1389 (void) m_set_service_class(m, MBUF_SC_CTL);
1390 }
1391
6d2010ae 1392 ip6_output(m, NULL, NULL, IPV6_OUTARGS, im6o, &outif, &ip6oa);
1c79356b
A
1393 if (outif) {
1394 icmp6_ifstat_inc(outif, ifs6_out_msg);
1395 icmp6_ifstat_inc(outif, ifs6_out_neighboradvert);
6d2010ae 1396 ifnet_release(outif);
1c79356b
A
1397 }
1398 icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
6d2010ae 1399
39236c6e 1400exit:
6d2010ae
A
1401 if (im6o != NULL)
1402 IM6O_REMREF(im6o);
39236c6e
A
1403
1404 ROUTE_RELEASE(&ro);
6d2010ae
A
1405 return;
1406
1407bad:
6d2010ae 1408 m_freem(m);
39236c6e 1409 goto exit;
1c79356b
A
1410}
1411
1412caddr_t
91447636
A
1413nd6_ifptomac(
1414 struct ifnet *ifp)
1c79356b 1415{
6d2010ae
A
1416 switch (ifp->if_type) {
1417 case IFT_ARCNET:
1418 case IFT_ETHER:
1419 case IFT_IEEE8023ADLAG:
1420 case IFT_FDDI:
1421 case IFT_IEEE1394:
1422#ifdef IFT_L2VLAN
1423 case IFT_L2VLAN:
1424#endif
1425#ifdef IFT_IEEE80211
1426 case IFT_IEEE80211:
1427#endif
1428#ifdef IFT_CARP
1429 case IFT_CARP:
1430#endif
1431 case IFT_BRIDGE:
1432 case IFT_ISO88025:
39236c6e 1433 return ((caddr_t)IF_LLADDR(ifp));
6d2010ae
A
1434 default:
1435 return NULL;
1436 }
1c79356b
A
1437}
1438
1439TAILQ_HEAD(dadq_head, dadq);
1440struct dadq {
6d2010ae
A
1441 decl_lck_mtx_data(, dad_lock);
1442 u_int32_t dad_refcount; /* reference count */
1443 int dad_attached;
1c79356b
A
1444 TAILQ_ENTRY(dadq) dad_list;
1445 struct ifaddr *dad_ifa;
1446 int dad_count; /* max NS to send */
1447 int dad_ns_tcount; /* # of trials to send NS */
1448 int dad_ns_ocount; /* NS sent so far */
1449 int dad_ns_icount;
1450 int dad_na_icount;
39236c6e 1451 int dad_nd_ixcount; /* Count of IFDISABLED eligible ND rx'd */
fe8ab488 1452 uint8_t dad_ehsrc[ETHER_ADDR_LEN];
1c79356b
A
1453};
1454
1455static struct dadq_head dadq;
6d2010ae
A
1456
1457void
1458nd6_nbr_init(void)
1459{
316670eb
A
1460 int i;
1461
6d2010ae
A
1462 TAILQ_INIT(&dadq);
1463
1464 dad_size = sizeof (struct dadq);
1465 dad_zone = zinit(dad_size, DAD_ZONE_MAX * dad_size, 0, DAD_ZONE_NAME);
1466 if (dad_zone == NULL) {
1467 panic("%s: failed allocating %s", __func__, DAD_ZONE_NAME);
1468 /* NOTREACHED */
1469 }
1470 zone_change(dad_zone, Z_EXPAND, TRUE);
1471 zone_change(dad_zone, Z_CALLERACCT, FALSE);
316670eb
A
1472
1473 bzero(&hostrtmask, sizeof hostrtmask);
1474 hostrtmask.sin6_family = AF_INET6;
1475 hostrtmask.sin6_len = sizeof hostrtmask;
1476 for (i = 0; i < sizeof hostrtmask.sin6_addr; ++i)
1477 hostrtmask.sin6_addr.s6_addr[i] = 0xff;
6d2010ae 1478}
1c79356b
A
1479
1480static struct dadq *
6d2010ae 1481nd6_dad_find(struct ifaddr *ifa)
1c79356b
A
1482{
1483 struct dadq *dp;
6d2010ae 1484
91447636 1485 lck_mtx_lock(dad6_mutex);
1c79356b 1486 for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
6d2010ae 1487 DAD_LOCK_SPIN(dp);
91447636 1488 if (dp->dad_ifa == ifa) {
6d2010ae
A
1489 DAD_ADDREF_LOCKED(dp);
1490 DAD_UNLOCK(dp);
91447636 1491 lck_mtx_unlock(dad6_mutex);
6d2010ae 1492 return (dp);
91447636 1493 }
6d2010ae 1494 DAD_UNLOCK(dp);
1c79356b 1495 }
91447636 1496 lck_mtx_unlock(dad6_mutex);
6d2010ae 1497 return (NULL);
1c79356b
A
1498}
1499
9bccf70c 1500void
91447636
A
1501nd6_dad_stoptimer(
1502 struct ifaddr *ifa)
9bccf70c
A
1503{
1504
91447636 1505 untimeout((void (*)(void *))nd6_dad_timer, (void *)ifa);
9bccf70c 1506}
9bccf70c 1507
1c79356b 1508/*
6d2010ae 1509 * Start Duplicate Address Detection (DAD) for specified interface address.
1c79356b
A
1510 */
1511void
91447636
A
1512nd6_dad_start(
1513 struct ifaddr *ifa,
2d21ac55 1514 int *tick_delay) /* minimum delay ticks for IFF_UP event */
1c79356b
A
1515{
1516 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1517 struct dadq *dp;
1c79356b 1518
fe8ab488
A
1519 nd6log2((LOG_DEBUG, "%s - %s ifp %s ia6_flags 0x%x\n",
1520 __func__,
1521 ip6_sprintf(&ia->ia_addr.sin6_addr),
1522 if_name(ia->ia_ifp),
1523 ia->ia6_flags));
1524
1c79356b
A
1525 /*
1526 * If we don't need DAD, don't do it.
1527 * There are several cases:
1528 * - DAD is disabled (ip6_dad_count == 0)
1529 * - the interface address is anycast
1530 */
6d2010ae 1531 IFA_LOCK(&ia->ia_ifa);
316670eb 1532 if (!(ia->ia6_flags & IN6_IFF_DADPROGRESS)) {
1c79356b 1533 log(LOG_DEBUG,
316670eb 1534 "nd6_dad_start: not a tentative or optimistic address "
1c79356b
A
1535 "%s(%s)\n",
1536 ip6_sprintf(&ia->ia_addr.sin6_addr),
1537 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
6d2010ae 1538 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
1539 return;
1540 }
316670eb
A
1541 if (!ip6_dad_count || (ia->ia6_flags & IN6_IFF_ANYCAST) != 0) {
1542 ia->ia6_flags &= ~IN6_IFF_DADPROGRESS;
6d2010ae 1543 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
1544 return;
1545 }
6d2010ae
A
1546 IFA_UNLOCK(&ia->ia_ifa);
1547 if (ifa->ifa_ifp == NULL)
1c79356b 1548 panic("nd6_dad_start: ifa->ifa_ifp == NULL");
316670eb
A
1549 if (!(ifa->ifa_ifp->if_flags & IFF_UP) ||
1550 (ifa->ifa_ifp->if_eflags & IFEF_IPV6_ND6ALT)) {
1c79356b 1551 return;
6d2010ae
A
1552 }
1553 if ((dp = nd6_dad_find(ifa)) != NULL) {
1554 DAD_REMREF(dp);
1c79356b
A
1555 /* DAD already in progress */
1556 return;
1557 }
1558
6d2010ae 1559 dp = zalloc(dad_zone);
1c79356b
A
1560 if (dp == NULL) {
1561 log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
1562 "%s(%s)\n",
1563 ip6_sprintf(&ia->ia_addr.sin6_addr),
1564 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1565 return;
1566 }
6d2010ae
A
1567 bzero(dp, dad_size);
1568 lck_mtx_init(&dp->dad_lock, ifa_mtx_grp, ifa_mtx_attr);
1569
1570 /* Callee adds one reference for us */
1571 dp = nd6_dad_attach(dp, ifa);
1c79356b 1572
316670eb
A
1573 nd6log((LOG_DEBUG, "%s: starting %sDAD for %s\n",
1574 if_name(ifa->ifa_ifp),
fe8ab488 1575 (ia->ia6_flags & IN6_IFF_OPTIMISTIC) ? "optimistic " : "",
9bccf70c 1576 ip6_sprintf(&ia->ia_addr.sin6_addr)));
1c79356b
A
1577
1578 /*
1579 * Send NS packet for DAD, ip6_dad_count times.
1580 * Note that we must delay the first transmission, if this is the
1581 * first packet to be sent from the interface after interface
1582 * (re)initialization.
1583 */
2d21ac55 1584 if (tick_delay == NULL) {
b0d623f7 1585 u_int32_t retrans;
316670eb
A
1586 struct nd_ifinfo *ndi;
1587
1c79356b 1588 nd6_dad_ns_output(dp, ifa);
b0d623f7 1589 lck_rw_lock_shared(nd_if_rwlock);
316670eb
A
1590 ndi = ND_IFINFO(ifa->ifa_ifp);
1591 VERIFY(ndi != NULL && ndi->initialized);
1592 lck_mtx_lock(&ndi->lock);
1593 retrans = ndi->retrans * hz / 1000;
1594 lck_mtx_unlock(&ndi->lock);
b0d623f7
A
1595 lck_rw_done(nd_if_rwlock);
1596 timeout((void (*)(void *))nd6_dad_timer, (void *)ifa, retrans);
1c79356b
A
1597 } else {
1598 int ntick;
1599
2d21ac55 1600 if (*tick_delay == 0)
1c79356b
A
1601 ntick = random() % (MAX_RTR_SOLICITATION_DELAY * hz);
1602 else
2d21ac55
A
1603 ntick = *tick_delay + random() % (hz / 2);
1604 *tick_delay = ntick;
91447636 1605 timeout((void (*)(void *))nd6_dad_timer, (void *)ifa,
1c79356b
A
1606 ntick);
1607 }
6d2010ae
A
1608
1609 DAD_REMREF(dp); /* drop our reference */
1610}
1611
1612static struct dadq *
1613nd6_dad_attach(struct dadq *dp, struct ifaddr *ifa)
1614{
1615 lck_mtx_lock(dad6_mutex);
1616 DAD_LOCK(dp);
1617 dp->dad_ifa = ifa;
1618 IFA_ADDREF(ifa); /* for dad_ifa */
1619 dp->dad_count = ip6_dad_count;
1620 dp->dad_ns_icount = dp->dad_na_icount = 0;
1621 dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
39236c6e 1622 dp->dad_nd_ixcount = 0;
6d2010ae
A
1623 VERIFY(!dp->dad_attached);
1624 dp->dad_attached = 1;
1625 DAD_ADDREF_LOCKED(dp); /* for caller */
1626 DAD_ADDREF_LOCKED(dp); /* for dadq_head list */
1627 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
1628 DAD_UNLOCK(dp);
1629 lck_mtx_unlock(dad6_mutex);
1630
1631 return (dp);
1632}
1633
1634static void
1635nd6_dad_detach(struct dadq *dp, struct ifaddr *ifa)
1636{
1637 int detached;
1638
1639 lck_mtx_lock(dad6_mutex);
1640 DAD_LOCK(dp);
1641 if ((detached = dp->dad_attached)) {
1642 VERIFY(dp->dad_ifa == ifa);
1643 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1644 dp->dad_list.tqe_next = NULL;
1645 dp->dad_list.tqe_prev = NULL;
1646 dp->dad_attached = 0;
1647 }
1648 DAD_UNLOCK(dp);
1649 lck_mtx_unlock(dad6_mutex);
1650 if (detached) {
1651 DAD_REMREF(dp); /* drop dadq_head reference */
1652 }
1c79356b
A
1653}
1654
9bccf70c
A
1655/*
1656 * terminate DAD unconditionally. used for address removals.
1657 */
1658void
6d2010ae 1659nd6_dad_stop(struct ifaddr *ifa)
9bccf70c
A
1660{
1661 struct dadq *dp;
1662
9bccf70c
A
1663 dp = nd6_dad_find(ifa);
1664 if (!dp) {
1665 /* DAD wasn't started yet */
1666 return;
1667 }
1668
91447636 1669 untimeout((void (*)(void *))nd6_dad_timer, (void *)ifa);
9bccf70c 1670
6d2010ae
A
1671 nd6_dad_detach(dp, ifa);
1672 DAD_REMREF(dp); /* drop our reference */
9bccf70c
A
1673}
1674
1c79356b 1675static void
6d2010ae 1676nd6_unsol_na_output(struct ifaddr *ifa)
1c79356b 1677{
1c79356b 1678 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
6d2010ae
A
1679 struct ifnet *ifp = ifa->ifa_ifp;
1680 struct in6_addr saddr6, taddr6;
1681
1682 if ((ifp->if_flags & IFF_UP) == 0 ||
316670eb
A
1683 (ifp->if_flags & IFF_RUNNING) == 0 ||
1684 (ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0)
6d2010ae
A
1685 return;
1686
1687 IFA_LOCK_SPIN(&ia->ia_ifa);
1688 taddr6 = ia->ia_addr.sin6_addr;
1689 IFA_UNLOCK(&ia->ia_ifa);
1690 if (in6_setscope(&taddr6, ifp, NULL) != 0)
1691 return;
1692 saddr6 = in6addr_linklocal_allnodes;
1693 if (in6_setscope(&saddr6, ifp, NULL) != 0)
1694 return;
1695
1696 nd6log((LOG_INFO, "%s: sending unsolicited NA\n",
1697 if_name(ifa->ifa_ifp)));
1698
1699 nd6_na_output(ifp, &saddr6, &taddr6, ND_NA_FLAG_OVERRIDE, 1, NULL);
1700}
1701
1702static void
1703nd6_dad_timer(struct ifaddr *ifa)
1704{
1705 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1706 struct dadq *dp = NULL;
fe8ab488 1707 struct nd_ifinfo *ndi;
1c79356b 1708
1c79356b
A
1709 /* Sanity check */
1710 if (ia == NULL) {
1711 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1712 goto done;
1713 }
fe8ab488
A
1714
1715 nd6log2((LOG_DEBUG, "%s - %s ifp %s ia6_flags 0x%x\n",
1716 __func__,
1717 ip6_sprintf(&ia->ia_addr.sin6_addr),
1718 if_name(ia->ia_ifp),
1719 ia->ia6_flags));
1720
1c79356b
A
1721 dp = nd6_dad_find(ifa);
1722 if (dp == NULL) {
1723 log(LOG_ERR, "nd6_dad_timer: DAD structure not found\n");
1724 goto done;
1725 }
6d2010ae 1726 IFA_LOCK(&ia->ia_ifa);
1c79356b
A
1727 if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
1728 log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
1729 "%s(%s)\n",
1730 ip6_sprintf(&ia->ia_addr.sin6_addr),
1731 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
6d2010ae 1732 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
1733 goto done;
1734 }
316670eb
A
1735 if ((ia->ia6_flags & IN6_IFF_DADPROGRESS) == 0) {
1736 log(LOG_ERR, "nd6_dad_timer: not a tentative or optimistic "
1737 "address %s(%s)\n",
1c79356b
A
1738 ip6_sprintf(&ia->ia_addr.sin6_addr),
1739 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
6d2010ae 1740 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
1741 goto done;
1742 }
6d2010ae 1743 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
1744
1745 /* timeouted with IFF_{RUNNING,UP} check */
6d2010ae 1746 DAD_LOCK(dp);
1c79356b 1747 if (dp->dad_ns_tcount > dad_maxtry) {
6d2010ae 1748 DAD_UNLOCK(dp);
9bccf70c
A
1749 nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
1750 if_name(ifa->ifa_ifp)));
1c79356b 1751
6d2010ae 1752 nd6_dad_detach(dp, ifa);
1c79356b
A
1753 goto done;
1754 }
1755
1756 /* Need more checks? */
1757 if (dp->dad_ns_ocount < dp->dad_count) {
b0d623f7 1758 u_int32_t retrans;
316670eb 1759
6d2010ae 1760 DAD_UNLOCK(dp);
1c79356b
A
1761 /*
1762 * We have more NS to go. Send NS packet for DAD.
1763 */
1764 nd6_dad_ns_output(dp, ifa);
b0d623f7 1765 lck_rw_lock_shared(nd_if_rwlock);
316670eb
A
1766 ndi = ND_IFINFO(ifa->ifa_ifp);
1767 VERIFY(ndi != NULL && ndi->initialized);
1768 lck_mtx_lock(&ndi->lock);
1769 retrans = ndi->retrans * hz / 1000;
1770 lck_mtx_unlock(&ndi->lock);
b0d623f7
A
1771 lck_rw_done(nd_if_rwlock);
1772 timeout((void (*)(void *))nd6_dad_timer, (void *)ifa, retrans);
1c79356b
A
1773 } else {
1774 /*
1775 * We have transmitted sufficient number of DAD packets.
1776 * See what we've got.
1777 */
1778 int duplicate;
39236c6e 1779 boolean_t candisable;
1c79356b
A
1780
1781 duplicate = 0;
39236c6e 1782 candisable = dp->dad_nd_ixcount > 0;
1c79356b
A
1783
1784 if (dp->dad_na_icount) {
1785 /*
1786 * the check is in nd6_dad_na_input(),
1787 * but just in case
1788 */
1789 duplicate++;
1790 }
1791
1792 if (dp->dad_ns_icount) {
1c79356b
A
1793 /* We've seen NS, means DAD has failed. */
1794 duplicate++;
1c79356b 1795 }
6d2010ae 1796 DAD_UNLOCK(dp);
1c79356b
A
1797
1798 if (duplicate) {
39236c6e
A
1799 nd6log((LOG_INFO,
1800 "%s: duplicate IPv6 address %s [timer]\n",
1801 __func__, ip6_sprintf(&ia->ia_addr.sin6_addr),
1802 if_name(ia->ia_ifp)));
1803 nd6_dad_duplicated(ifa);
1c79356b 1804 /* (*dp) will be freed in nd6_dad_duplicated() */
1c79356b 1805 } else {
fe8ab488
A
1806 boolean_t txunsolna;
1807
1c79356b
A
1808 /*
1809 * We are done with DAD. No NA came, no NS came.
6d2010ae 1810 * No duplicate address found.
1c79356b 1811 */
6d2010ae 1812 IFA_LOCK_SPIN(&ia->ia_ifa);
316670eb 1813 ia->ia6_flags &= ~IN6_IFF_DADPROGRESS;
6d2010ae 1814 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 1815
fe8ab488
A
1816 lck_rw_lock_shared(nd_if_rwlock);
1817 ndi = ND_IFINFO(ifa->ifa_ifp);
1818 VERIFY(ndi != NULL && ndi->initialized);
1819 lck_mtx_lock(&ndi->lock);
1820 txunsolna = (ndi->flags & ND6_IFF_REPLICATED) != 0;
1821 lck_mtx_unlock(&ndi->lock);
1822 lck_rw_done(nd_if_rwlock);
1823
1824 if (txunsolna) {
1825 nd6_unsol_na_output(ifa);
1826 }
1827
9bccf70c 1828 nd6log((LOG_DEBUG,
fe8ab488 1829 "%s: DAD complete for %s - no duplicates found%s\n",
1c79356b 1830 if_name(ifa->ifa_ifp),
fe8ab488
A
1831 ip6_sprintf(&ia->ia_addr.sin6_addr),
1832 txunsolna ? ", tx unsolicited NA with O=1" : "."));
1833 in6_post_msg(ia->ia_ifp, KEV_INET6_NEW_USER_ADDR, ia,
1834 dp->dad_ehsrc);
6d2010ae 1835 nd6_dad_detach(dp, ifa);
1c79356b
A
1836 }
1837 }
1838
1839done:
6d2010ae
A
1840 if (dp != NULL)
1841 DAD_REMREF(dp); /* drop our reference */
1c79356b
A
1842}
1843
1844void
39236c6e 1845nd6_dad_duplicated(struct ifaddr *ifa)
1c79356b
A
1846{
1847 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1848 struct dadq *dp;
6d2010ae 1849 struct ifnet *ifp = ifa->ifa_ifp;
39236c6e 1850 boolean_t disable;
1c79356b
A
1851
1852 dp = nd6_dad_find(ifa);
1853 if (dp == NULL) {
39236c6e 1854 log(LOG_ERR, "%s: DAD structure not found.\n", __func__);
1c79356b
A
1855 return;
1856 }
6d2010ae
A
1857 IFA_LOCK(&ia->ia_ifa);
1858 DAD_LOCK(dp);
39236c6e
A
1859 nd6log((LOG_ERR, "%s: NS in/out=%d/%d, NA in=%d, ND x=%d\n",
1860 __func__, dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount,
1861 dp->dad_nd_ixcount));
1862 disable = dp->dad_nd_ixcount > 0;
6d2010ae 1863 DAD_UNLOCK(dp);
316670eb 1864 ia->ia6_flags &= ~IN6_IFF_DADPROGRESS;
1c79356b 1865 ia->ia6_flags |= IN6_IFF_DUPLICATED;
6d2010ae 1866 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 1867
39236c6e
A
1868 /* increment DAD collision counter */
1869 ++ip6stat.ip6s_dad_collide;
1870
1c79356b 1871 /* We are done with DAD, with duplicated address found. (failure) */
91447636 1872 untimeout((void (*)(void *))nd6_dad_timer, (void *)ifa);
9bccf70c 1873
6d2010ae 1874 IFA_LOCK(&ia->ia_ifa);
39236c6e 1875 log(LOG_ERR, "%s: DAD complete for %s - duplicate found.\n",
6d2010ae 1876 if_name(ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
6d2010ae 1877 IFA_UNLOCK(&ia->ia_ifa);
39236c6e
A
1878
1879 if (disable) {
6d2010ae 1880 log(LOG_ERR, "%s: possible hardware address duplication "
39236c6e
A
1881 "detected, disabling IPv6 for interface.\n", if_name(ifp));
1882
6d2010ae 1883 lck_rw_lock_shared(nd_if_rwlock);
39236c6e 1884 nd_ifinfo[ifp->if_index].flags |= ND6_IFF_IFDISABLED;
6d2010ae 1885 lck_rw_done(nd_if_rwlock);
39236c6e
A
1886 /* Make sure to set IFEF_IPV6_DISABLED too */
1887 nd6_if_disable(ifp, TRUE);
6d2010ae 1888 }
316670eb 1889
39236c6e
A
1890 log(LOG_ERR, "%s: manual intervention required!\n", if_name(ifp));
1891
6d2010ae
A
1892 /* Send an event to the configuration agent so that the
1893 * duplicate address will be notified to the user and will
1894 * be removed.
1895 */
fe8ab488 1896 in6_post_msg(ifp, KEV_INET6_NEW_USER_ADDR, ia, dp->dad_ehsrc);
6d2010ae
A
1897 nd6_dad_detach(dp, ifa);
1898 DAD_REMREF(dp); /* drop our reference */
1c79356b
A
1899}
1900
1901static void
6d2010ae 1902nd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa)
1c79356b
A
1903{
1904 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1905 struct ifnet *ifp = ifa->ifa_ifp;
6d2010ae 1906 struct in6_addr taddr6;
1c79356b 1907
6d2010ae 1908 DAD_LOCK(dp);
1c79356b
A
1909 dp->dad_ns_tcount++;
1910 if ((ifp->if_flags & IFF_UP) == 0) {
6d2010ae 1911 DAD_UNLOCK(dp);
1c79356b
A
1912 return;
1913 }
1914 if ((ifp->if_flags & IFF_RUNNING) == 0) {
6d2010ae 1915 DAD_UNLOCK(dp);
1c79356b
A
1916 return;
1917 }
1918
1919 dp->dad_ns_ocount++;
6d2010ae
A
1920 DAD_UNLOCK(dp);
1921 IFA_LOCK_SPIN(&ia->ia_ifa);
1922 taddr6 = ia->ia_addr.sin6_addr;
1923 IFA_UNLOCK(&ia->ia_ifa);
1924 nd6_ns_output(ifp, NULL, &taddr6, NULL, 1);
1c79356b
A
1925}
1926
1927static void
fe8ab488
A
1928nd6_dad_ns_input(struct mbuf *m, struct ifaddr *ifa, char *lladdr,
1929 int lladdrlen)
1c79356b 1930{
1c79356b 1931 struct dadq *dp;
39236c6e
A
1932 struct in6_ifaddr *ia;
1933 boolean_t candisable, dadstarted;
fe8ab488 1934 struct ip6aux *ip6a;
1c79356b 1935
39236c6e
A
1936 VERIFY(ifa != NULL);
1937 candisable = FALSE;
1938 IFA_LOCK(ifa);
1939 ia = (struct in6_ifaddr *) ifa;
1940 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
39236c6e 1941 ip6a = ip6_findaux(m);
fe8ab488 1942 candisable = TRUE;
39236c6e
A
1943 if (ip6a && (ip6a->ip6a_flags & IP6A_HASEEN) != 0) {
1944 struct in6_addr in6 = ia->ia_addr.sin6_addr;
1945
1946 nd6log((LOG_INFO,
1947 "%s: eh_src=%02x:%02x:%02x:%02x:%02x:%02x -> %s\n",
1948 __func__,
1949 ip6a->ip6a_ehsrc[0], ip6a->ip6a_ehsrc[1],
1950 ip6a->ip6a_ehsrc[2], ip6a->ip6a_ehsrc[3],
1951 ip6a->ip6a_ehsrc[4], ip6a->ip6a_ehsrc[5],
1952 if_name(ifa->ifa_ifp)));
1953
1954 in6.s6_addr8[8] = ip6a->ip6a_ehsrc[0] ^ ND6_EUI64_UBIT;
1955 in6.s6_addr8[9] = ip6a->ip6a_ehsrc[1];
1956 in6.s6_addr8[10] = ip6a->ip6a_ehsrc[2];
1957 in6.s6_addr8[11] = 0xff;
1958 in6.s6_addr8[12] = 0xfe;
1959 in6.s6_addr8[13] = ip6a->ip6a_ehsrc[3];
1960 in6.s6_addr8[14] = ip6a->ip6a_ehsrc[4];
1961 in6.s6_addr8[15] = ip6a->ip6a_ehsrc[5];
1962
1963 if (!IN6_ARE_ADDR_EQUAL(&in6, &ia->ia_addr.sin6_addr)) {
1964 nd6log((LOG_ERR, "%s: DAD NS for %s on %s "
1965 "is from another MAC address.\n", __func__,
1966 ip6_sprintf(&ia->ia_addr.sin6_addr),
1967 if_name(ifa->ifa_ifp)));
1968 candisable = FALSE;
1969 }
1970 } else {
1971 nd6log((LOG_INFO,
1972 "%s: no eh_src for DAD NS %s at %s.\n", __func__,
1973 ip6_sprintf(&ia->ia_addr.sin6_addr),
1974 if_name(ifa->ifa_ifp)));
1975 }
1c79356b 1976 }
39236c6e 1977 IFA_UNLOCK(ifa);
1c79356b 1978
39236c6e
A
1979 /* If DAD has not yet started, then this DAD NS probe is proof that
1980 * another node has started first. Otherwise, it could be a multicast
1981 * loopback, in which case it should be counted and handled later in
1982 * the DAD timer callback.
1c79356b 1983 */
39236c6e
A
1984 dadstarted = FALSE;
1985 dp = nd6_dad_find(ifa);
1986 if (dp != NULL) {
6d2010ae 1987 DAD_LOCK(dp);
39236c6e
A
1988 ++dp->dad_ns_icount;
1989 if (candisable)
1990 ++dp->dad_nd_ixcount;
1991 if (dp->dad_ns_ocount > 0)
1992 dadstarted = TRUE;
fe8ab488
A
1993 if (lladdr && lladdrlen >= ETHER_ADDR_LEN)
1994 memcpy(dp->dad_ehsrc, lladdr, ETHER_ADDR_LEN);
6d2010ae
A
1995 DAD_UNLOCK(dp);
1996 DAD_REMREF(dp);
39236c6e
A
1997 dp = NULL;
1998 }
1999
2000 nd6log((LOG_INFO, "%s: dadstarted=%d candisable=%d\n",
2001 __func__, dadstarted, candisable));
2002
2003 if (!dadstarted) {
2004 nd6log((LOG_INFO,
2005 "%s: duplicate IPv6 address %s [processing NS on %s]\n",
2006 __func__, ip6_sprintf(&ia->ia_addr.sin6_addr),
2007 if_name(ifa->ifa_ifp)));
2008 nd6_dad_duplicated(ifa);
1c79356b
A
2009 }
2010}
2011
39236c6e
A
2012static struct mbuf *
2013nd6_dad_na_input(struct mbuf *m, struct ifnet *ifp, struct in6_addr *taddr,
2014 caddr_t lladdr, int lladdrlen)
1c79356b 2015{
39236c6e
A
2016 struct ifaddr *ifa;
2017 struct in6_ifaddr *ia;
1c79356b 2018 struct dadq *dp;
39236c6e 2019 struct nd_ifinfo *ndi;
fe8ab488 2020 boolean_t candisable, replicated;
1c79356b 2021
39236c6e 2022 ifa = (struct ifaddr *) in6ifa_ifpwithaddr(ifp, taddr);
6d2010ae 2023 if (ifa == NULL)
39236c6e 2024 return m;
1c79356b 2025
39236c6e 2026 candisable = FALSE;
fe8ab488 2027 replicated = FALSE;
39236c6e 2028
fe8ab488 2029 /* Get the ND6_IFF_REPLICATED flag. */
39236c6e
A
2030 lck_rw_lock_shared(nd_if_rwlock);
2031 ndi = ND_IFINFO(ifp);
2032 if (ndi != NULL && ndi->initialized) {
2033 lck_mtx_lock(&ndi->lock);
fe8ab488 2034 replicated = !!(ndi->flags & ND6_IFF_REPLICATED);
39236c6e 2035 lck_mtx_unlock(&ndi->lock);
6d2010ae 2036 }
39236c6e 2037 lck_rw_done(nd_if_rwlock);
fe8ab488 2038 if (replicated) {
39236c6e 2039 nd6log((LOG_INFO, "%s: ignoring duplicate NA on "
fe8ab488 2040 "replicated interface %s\n", __func__, if_name(ifp)));
39236c6e
A
2041 goto done;
2042 }
2043
2044 /* Lock the interface address until done (see label below). */
2045 IFA_LOCK(ifa);
2046 ia = (struct in6_ifaddr *) ifa;
2047
6d2010ae
A
2048 /*
2049 * If the address is a link-local address formed from an interface
2050 * identifier based on the hardware address which is supposed to be
2051 * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
2052 * operation on the interface SHOULD be disabled according to RFC 4862,
2053 * section 5.4.5, but here we decide not to disable if the target
2054 * hardware address is not also ours, which is a transitory possibility
2055 * in the presence of network-resident sleep proxies on the local link.
2056 */
39236c6e 2057 if (!(ia->ia6_flags & IN6_IFF_DADPROGRESS)) {
6d2010ae 2058 IFA_UNLOCK(ifa);
39236c6e
A
2059 nd6log((LOG_INFO, "%s: ignoring duplicate NA on "
2060 "%s [DAD not in progress]\n", __func__,
2061 if_name(ifp)));
2062 goto done;
2063 }
2064
2065 /* Some sleep proxies improperly send the client's Ethernet address in
2066 * the target link-layer address option, so detect this by comparing
2067 * the L2-header source address, if we have seen it, with the target
2068 * address, and ignoring the NA if they don't match.
2069 */
fe8ab488 2070 if (lladdr != NULL && lladdrlen >= ETHER_ADDR_LEN) {
39236c6e
A
2071 struct ip6aux *ip6a = ip6_findaux(m);
2072 if (ip6a && (ip6a->ip6a_flags & IP6A_HASEEN) != 0 &&
2073 bcmp(ip6a->ip6a_ehsrc, lladdr, ETHER_ADDR_LEN) != 0) {
2074 IFA_UNLOCK(ifa);
2075 nd6log((LOG_ERR, "%s: ignoring duplicate NA on %s "
2076 "[eh_src != tgtlladdr]\n", __func__, if_name(ifp)));
2077 goto done;
2078 }
2079 }
2080
2081 IFA_UNLOCK(ifa);
2082
2083 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr) &&
2084 !(ia->ia6_flags & IN6_IFF_SECURED)) {
2085 struct in6_addr in6;
2086
6d2010ae
A
2087 /*
2088 * To avoid over-reaction, we only apply this logic when we are
2089 * very sure that hardware addresses are supposed to be unique.
2090 */
2091 switch (ifp->if_type) {
2092 case IFT_BRIDGE:
2093 case IFT_ETHER:
2094 case IFT_FDDI:
2095 case IFT_ATM:
2096 case IFT_IEEE1394:
2097#ifdef IFT_IEEE80211
2098 case IFT_IEEE80211:
2099#endif
2100 /* Check if our hardware address matches the target */
2101 if (lladdr != NULL && lladdrlen > 0) {
2102 struct ifaddr *llifa;
2103 struct sockaddr_dl *sdl;
39236c6e 2104
6d2010ae
A
2105 llifa = ifp->if_lladdr;
2106 IFA_LOCK(llifa);
316670eb
A
2107 sdl = (struct sockaddr_dl *)(void *)
2108 llifa->ifa_addr;
39236c6e 2109 if (lladdrlen == sdl->sdl_alen &&
6d2010ae 2110 bcmp(lladdr, LLADDR(sdl), lladdrlen) == 0)
39236c6e 2111 candisable = TRUE;
6d2010ae
A
2112 IFA_UNLOCK(llifa);
2113 }
2114 in6 = ia->ia_addr.sin6_addr;
39236c6e 2115 if (in6_iid_from_hw(ifp, &in6) != 0)
6d2010ae 2116 break;
39236c6e
A
2117
2118 /* Refine decision about whether IPv6 can be disabled */
6d2010ae 2119 IFA_LOCK(ifa);
39236c6e 2120 if (candisable &&
6d2010ae 2121 !IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
39236c6e
A
2122 /*
2123 * Apply this logic only to the embedded MAC
2124 * address form of link-local IPv6 address.
2125 */
2126 candisable = FALSE;
6d2010ae
A
2127 } else if (lladdr == NULL &&
2128 IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
2129 /*
2130 * We received a NA with no target link-layer
2131 * address option. This means that someone else
2132 * has our address. Mark it as a hardware
2133 * duplicate so we disable IPv6 later on.
2134 */
39236c6e 2135 candisable = TRUE;
6d2010ae
A
2136 }
2137 IFA_UNLOCK(ifa);
2138 break;
2139 default:
2140 break;
2141 }
6d2010ae 2142 }
39236c6e
A
2143
2144 dp = nd6_dad_find(ifa);
2145 if (dp == NULL) {
2146 nd6log((LOG_INFO, "%s: no DAD structure for %s on %s.\n",
2147 __func__, ip6_sprintf(taddr), if_name(ifp)));
2148 goto done;
2149 }
2150
6d2010ae 2151 DAD_LOCK_SPIN(dp);
fe8ab488
A
2152 if (lladdr != NULL && lladdrlen >= ETHER_ADDR_LEN)
2153 memcpy(dp->dad_ehsrc, lladdr, ETHER_ADDR_LEN);
6d2010ae 2154 dp->dad_na_icount++;
39236c6e
A
2155 if (candisable)
2156 dp->dad_nd_ixcount++;
6d2010ae
A
2157 DAD_UNLOCK(dp);
2158 DAD_REMREF(dp);
39236c6e 2159
1c79356b 2160 /* remove the address. */
39236c6e
A
2161 nd6log((LOG_INFO,
2162 "%s: duplicate IPv6 address %s [processing NA on %s]\n", __func__,
2163 ip6_sprintf(taddr), if_name(ifp)));
2164 nd6_dad_duplicated(ifa);
2165
2166done:
2167 IFA_LOCK_ASSERT_NOTHELD(ifa);
2168 IFA_REMREF(ifa);
2169 m_freem(m);
2170 return NULL;
6d2010ae
A
2171}
2172
2173static void
2174dad_addref(struct dadq *dp, int locked)
2175{
2176 if (!locked)
2177 DAD_LOCK_SPIN(dp);
2178 else
2179 DAD_LOCK_ASSERT_HELD(dp);
2180
2181 if (++dp->dad_refcount == 0) {
2182 panic("%s: dad %p wraparound refcnt\n", __func__, dp);
2183 /* NOTREACHED */
2184 }
2185 if (!locked)
2186 DAD_UNLOCK(dp);
2187}
2188
2189static void
2190dad_remref(struct dadq *dp)
2191{
2192 struct ifaddr *ifa;
2193
2194 DAD_LOCK_SPIN(dp);
2195 if (dp->dad_refcount == 0)
2196 panic("%s: dad %p negative refcnt\n", __func__, dp);
2197 --dp->dad_refcount;
2198 if (dp->dad_refcount > 0) {
2199 DAD_UNLOCK(dp);
2200 return;
2201 }
2202 DAD_UNLOCK(dp);
2203
2204 if (dp->dad_attached ||
2205 dp->dad_list.tqe_next != NULL || dp->dad_list.tqe_prev != NULL) {
2206 panic("%s: attached dad=%p is being freed", __func__, dp);
2207 /* NOTREACHED */
2208 }
2209
2210 if ((ifa = dp->dad_ifa) != NULL) {
2211 IFA_REMREF(ifa); /* drop dad_ifa reference */
2212 dp->dad_ifa = NULL;
2213 }
2214
2215 lck_mtx_destroy(&dp->dad_lock, ifa_mtx_grp);
2216 zfree(dad_zone, dp);
2217}
2218
2219void
2220nd6_llreach_set_reachable(struct ifnet *ifp, void *addr, unsigned int alen)
2221{
2222 /* Nothing more to do if it's disabled */
2223 if (nd6_llreach_base == 0)
2224 return;
2225
2226 ifnet_llreach_set_reachable(ifp, ETHERTYPE_IPV6, addr, alen);
1c79356b 2227}
316670eb
A
2228
2229void
2230nd6_alt_node_addr_decompose(struct ifnet *ifp, struct sockaddr *sa,
2231 struct sockaddr_dl* sdl, struct sockaddr_in6 *sin6)
2232{
2233 static const size_t EUI64_LENGTH = 8;
39236c6e 2234
316670eb
A
2235 VERIFY(nd6_need_cache(ifp));
2236 VERIFY(sa);
2237 VERIFY(sdl && (void *)sa != (void *)sdl);
2238 VERIFY(sin6 && (void *)sa != (void *)sin6);
39236c6e 2239
316670eb
A
2240 bzero(sin6, sizeof *sin6);
2241 sin6->sin6_len = sizeof *sin6;
2242 sin6->sin6_family = AF_INET6;
39236c6e 2243
316670eb
A
2244 bzero(sdl, sizeof *sdl);
2245 sdl->sdl_len = sizeof *sdl;
2246 sdl->sdl_family = AF_LINK;
2247 sdl->sdl_type = ifp->if_type;
2248 sdl->sdl_index = ifp->if_index;
39236c6e 2249
316670eb
A
2250 switch (sa->sa_family) {
2251 case AF_INET6: {
2252 struct sockaddr_in6 *sin6a = (struct sockaddr_in6 *)(void *)sa;
2253 struct in6_addr *in6 = &sin6a->sin6_addr;
39236c6e 2254
316670eb 2255 VERIFY(sa->sa_len == sizeof *sin6);
39236c6e 2256
316670eb
A
2257 sdl->sdl_nlen = strlen(ifp->if_name);
2258 bcopy(ifp->if_name, sdl->sdl_data, sdl->sdl_nlen);
2259 if (in6->s6_addr[11] == 0xff && in6->s6_addr[12] == 0xfe) {
2260 sdl->sdl_alen = ETHER_ADDR_LEN;
2261 LLADDR(sdl)[0] = (in6->s6_addr[8] ^ ND6_EUI64_UBIT);
2262 LLADDR(sdl)[1] = in6->s6_addr[9];
2263 LLADDR(sdl)[2] = in6->s6_addr[10];
2264 LLADDR(sdl)[3] = in6->s6_addr[13];
2265 LLADDR(sdl)[4] = in6->s6_addr[14];
2266 LLADDR(sdl)[5] = in6->s6_addr[15];
39236c6e 2267 } else {
316670eb
A
2268 sdl->sdl_alen = EUI64_LENGTH;
2269 bcopy(&in6->s6_addr[8], LLADDR(sdl), EUI64_LENGTH);
2270 }
39236c6e 2271
316670eb
A
2272 sdl->sdl_slen = 0;
2273 break;
2274 }
2275 case AF_LINK: {
2276 struct sockaddr_dl *sdla = (struct sockaddr_dl *)(void *)sa;
2277 struct in6_addr *in6 = &sin6->sin6_addr;
2278 caddr_t lla = LLADDR(sdla);
39236c6e 2279
316670eb
A
2280 VERIFY(sa->sa_len <= sizeof *sdl);
2281 bcopy(sa, sdl, sa->sa_len);
39236c6e 2282
316670eb
A
2283 sin6->sin6_scope_id = sdla->sdl_index;
2284 if (sin6->sin6_scope_id == 0)
2285 sin6->sin6_scope_id = ifp->if_index;
2286 in6->s6_addr[0] = 0xfe;
2287 in6->s6_addr[1] = 0x80;
2288 if (sdla->sdl_alen == EUI64_LENGTH)
2289 bcopy(lla, &in6->s6_addr[8], EUI64_LENGTH);
2290 else {
2291 VERIFY(sdla->sdl_alen == ETHER_ADDR_LEN);
39236c6e 2292
316670eb
A
2293 in6->s6_addr[8] = ((uint8_t) lla[0] ^ ND6_EUI64_UBIT);
2294 in6->s6_addr[9] = (uint8_t) lla[1];
2295 in6->s6_addr[10] = (uint8_t) lla[2];
2296 in6->s6_addr[11] = 0xff;
2297 in6->s6_addr[12] = 0xfe;
2298 in6->s6_addr[13] = (uint8_t) lla[3];
2299 in6->s6_addr[14] = (uint8_t) lla[4];
2300 in6->s6_addr[15] = (uint8_t) lla[5];
2301 }
39236c6e 2302
316670eb
A
2303 break;
2304 }
2305 default:
2306 VERIFY(false);
2307 break;
2308 }
2309}
2310
2311void
2312nd6_alt_node_present(struct ifnet *ifp, struct sockaddr_in6 *sin6,
2313 struct sockaddr_dl *sdl, int32_t rssi, int lqm, int npm)
2314{
2315 struct rtentry *rt;
2316 struct llinfo_nd6 *ln;
2317 struct if_llreach *lr;
2318
39236c6e
A
2319 nd6_cache_lladdr(ifp, &sin6->sin6_addr, LLADDR(sdl), sdl->sdl_alen,
2320 ND_NEIGHBOR_ADVERT, 0);
316670eb
A
2321
2322 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_NOTOWNED);
2323 lck_mtx_lock(rnh_lock);
2324
2325 rt = rtalloc1_scoped_locked((struct sockaddr *)sin6, 1, 0,
2326 ifp->if_index);
2327 if (rt != NULL) {
2328 RT_LOCK(rt);
2329 VERIFY(rt->rt_flags & RTF_LLINFO);
2330 VERIFY(rt->rt_llinfo);
2331
2332 ln = rt->rt_llinfo;
2333 ln->ln_state = ND6_LLINFO_REACHABLE;
39236c6e 2334 ln_setexpire(ln, 0);
316670eb
A
2335
2336 lr = ln->ln_llreach;
2337 if (lr) {
2338 IFLR_LOCK(lr);
2339 lr->lr_rssi = rssi;
2340 lr->lr_lqm = (int32_t) lqm;
2341 lr->lr_npm = (int32_t) npm;
2342 IFLR_UNLOCK(lr);
2343 }
2344
2345 RT_UNLOCK(rt);
2346 RT_REMREF(rt);
2347 }
2348
2349 lck_mtx_unlock(rnh_lock);
2350
2351 if (rt == NULL) {
2352 log(LOG_ERR, "%s: failed to add/update host route to %s.\n",
2353 __func__, ip6_sprintf(&sin6->sin6_addr));
39236c6e
A
2354 } else {
2355 nd6log((LOG_DEBUG, "%s: host route to %s [lr=0x%llx]\n",
2356 __func__, ip6_sprintf(&sin6->sin6_addr),
2357 (uint64_t)VM_KERNEL_ADDRPERM(lr)));
db609669 2358 }
316670eb
A
2359}
2360
2361void
2362nd6_alt_node_absent(struct ifnet *ifp, struct sockaddr_in6 *sin6)
2363{
2364 struct rtentry *rt;
2365
db609669
A
2366 nd6log((LOG_DEBUG, "%s: host route to %s\n", __func__,
2367 ip6_sprintf(&sin6->sin6_addr)));
2368
316670eb
A
2369 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_NOTOWNED);
2370 lck_mtx_lock(rnh_lock);
2371
2372 rt = rtalloc1_scoped_locked((struct sockaddr *)sin6, 0, 0,
2373 ifp->if_index);
2374 if (rt != NULL) {
2375 RT_LOCK(rt);
2376
39236c6e 2377 if (!(rt->rt_flags & (RTF_CLONING|RTF_PRCLONING)) &&
316670eb
A
2378 (rt->rt_flags & (RTF_HOST|RTF_LLINFO|RTF_WASCLONED)) ==
2379 (RTF_HOST|RTF_LLINFO|RTF_WASCLONED)) {
2380 rt->rt_flags |= RTF_CONDEMNED;
2381 RT_UNLOCK(rt);
2382
2383 (void) rtrequest_locked(RTM_DELETE, rt_key(rt),
2384 (struct sockaddr *)NULL, rt_mask(rt), 0,
2385 (struct rtentry **)NULL);
2386
2387 rtfree_locked(rt);
39236c6e 2388 } else {
316670eb
A
2389 RT_REMREF_LOCKED(rt);
2390 RT_UNLOCK(rt);
2391 }
2392 }
2393
2394 lck_mtx_unlock(rnh_lock);
2395}