]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/nd6_nbr.c
xnu-1228.5.20.tar.gz
[apple/xnu.git] / bsd / netinet6 / nd6_nbr.c
1 /* $FreeBSD: src/sys/netinet6/nd6_nbr.c,v 1.4.2.4 2001/07/06 05:32:25 sumikawa Exp $ */
2 /* $KAME: nd6_nbr.c,v 1.64 2001/05/17 03:48:30 itojun Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/mbuf.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/time.h>
40 #include <sys/kernel.h>
41 #include <sys/errno.h>
42 #include <sys/syslog.h>
43 #include <kern/queue.h>
44
45 #include <net/if.h>
46 #include <net/if_types.h>
47 #include <net/if_dl.h>
48 #include <net/route.h>
49
50 #include <netinet/in.h>
51 #include <netinet/in_var.h>
52 #include <netinet6/in6_var.h>
53 #include <netinet/ip6.h>
54 #include <netinet6/ip6_var.h>
55 #include <netinet6/nd6.h>
56 #include <netinet/icmp6.h>
57
58 #if IPSEC
59 #include <netinet6/ipsec.h>
60 #if INET6
61 #include <netinet6/ipsec6.h>
62 #endif
63 extern int ipsec_bypass;
64 #endif
65
66 #include <net/net_osdep.h>
67
68 #define SDL(s) ((struct sockaddr_dl *)s)
69
70 struct dadq;
71 static struct dadq *nd6_dad_find(struct ifaddr *);
72 #ifndef __APPLE__
73 static void nd6_dad_starttimer(struct dadq *, int);
74 static void nd6_dad_stoptimer(struct dadq *);
75 #else
76 void nd6_dad_stoptimer(struct ifaddr *);
77 #endif
78 static void nd6_dad_timer(struct ifaddr *);
79 static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
80 static void nd6_dad_ns_input(struct ifaddr *);
81 static void nd6_dad_na_input(struct ifaddr *);
82
83 static int dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/
84 static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
85
86 extern lck_mtx_t *dad6_mutex;
87 extern lck_mtx_t *nd6_mutex;
88 /*
89 * Input an Neighbor Solicitation Message.
90 *
91 * Based on RFC 2461
92 * Based on RFC 2462 (duplicated address detection)
93 */
94 void
95 nd6_ns_input(
96 struct mbuf *m,
97 int off,
98 int icmp6len)
99 {
100 struct ifnet *ifp = m->m_pkthdr.rcvif;
101 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
102 struct nd_neighbor_solicit *nd_ns;
103 struct in6_addr saddr6 = ip6->ip6_src;
104 struct in6_addr daddr6 = ip6->ip6_dst;
105 struct in6_addr taddr6;
106 struct in6_addr myaddr6;
107 char *lladdr = NULL;
108 struct ifaddr *ifa;
109 int lladdrlen = 0;
110 int anycast = 0, proxy = 0, tentative = 0;
111 int tlladdr;
112 union nd_opts ndopts;
113 struct sockaddr_dl *proxydl = NULL;
114
115 #ifndef PULLDOWN_TEST
116 IP6_EXTHDR_CHECK(m, off, icmp6len, return);
117 nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
118 #else
119 IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
120 if (nd_ns == NULL) {
121 icmp6stat.icp6s_tooshort++;
122 return;
123 }
124 #endif
125 ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
126 taddr6 = nd_ns->nd_ns_target;
127
128 if (ip6->ip6_hlim != 255) {
129 nd6log((LOG_ERR,
130 "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
131 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
132 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
133 goto bad;
134 }
135
136 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
137 /* dst has to be solicited node multicast address. */
138 if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL
139 /* don't check ifindex portion */
140 && daddr6.s6_addr32[1] == 0
141 && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE
142 && daddr6.s6_addr8[12] == 0xff) {
143 ; /* good */
144 } else {
145 nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
146 "(wrong ip6 dst)\n"));
147 goto bad;
148 }
149 }
150
151 if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
152 nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
153 goto bad;
154 }
155
156 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
157 taddr6.s6_addr16[1] = htons(ifp->if_index);
158
159 icmp6len -= sizeof(*nd_ns);
160 nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
161 if (nd6_options(&ndopts) < 0) {
162 nd6log((LOG_INFO,
163 "nd6_ns_input: invalid ND option, ignored\n"));
164 /* nd6_options have incremented stats */
165 goto freeit;
166 }
167
168 if (ndopts.nd_opts_src_lladdr) {
169 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
170 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
171 }
172
173 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
174 nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
175 "(link-layer address option)\n"));
176 goto bad;
177 }
178
179 /*
180 * Attaching target link-layer address to the NA?
181 * (RFC 2461 7.2.4)
182 *
183 * NS IP dst is unicast/anycast MUST NOT add
184 * NS IP dst is solicited-node multicast MUST add
185 *
186 * In implementation, we add target link-layer address by default.
187 * We do not add one in MUST NOT cases.
188 */
189 #if 0 /* too much! */
190 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6);
191 if (ifa && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST))
192 tlladdr = 0;
193 else
194 #endif
195 if (!IN6_IS_ADDR_MULTICAST(&daddr6))
196 tlladdr = 0;
197 else
198 tlladdr = 1;
199
200 /*
201 * Target address (taddr6) must be either:
202 * (1) Valid unicast/anycast address for my receiving interface,
203 * (2) Unicast address for which I'm offering proxy service, or
204 * (3) "tentative" address on which DAD is being performed.
205 */
206 /* (1) and (3) check. */
207 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
208
209 /* (2) check. */
210 if (!ifa) {
211 struct rtentry *rt;
212 struct sockaddr_in6 tsin6;
213
214 bzero(&tsin6, sizeof tsin6);
215 tsin6.sin6_len = sizeof(struct sockaddr_in6);
216 tsin6.sin6_family = AF_INET6;
217 tsin6.sin6_addr = taddr6;
218
219 rt = rtalloc1((struct sockaddr *)&tsin6, 0, 0UL);
220 if (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
221 rt->rt_gateway->sa_family == AF_LINK) {
222 /*
223 * proxy NDP for single entry
224 */
225 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
226 IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
227 if (ifa) {
228 proxy = 1;
229 proxydl = SDL(rt->rt_gateway);
230 }
231 }
232 if (rt)
233 rtfree(rt);
234 }
235 if (!ifa) {
236 /*
237 * We've got an NS packet, and we don't have that adddress
238 * assigned for us. We MUST silently ignore it.
239 * See RFC2461 7.2.3.
240 */
241 goto freeit;
242 }
243 myaddr6 = *IFA_IN6(ifa);
244 anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
245 tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
246 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
247 goto freeit;
248
249 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
250 nd6log((LOG_INFO,
251 "nd6_ns_input: lladdrlen mismatch for %s "
252 "(if %d, NS packet %d)\n",
253 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
254 goto bad;
255 }
256
257 if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
258 nd6log((LOG_INFO,
259 "nd6_ns_input: duplicate IP6 address %s\n",
260 ip6_sprintf(&saddr6)));
261 goto freeit;
262 }
263
264 /*
265 * We have neighbor solicitation packet, with target address equals to
266 * one of my tentative address.
267 *
268 * src addr how to process?
269 * --- ---
270 * multicast of course, invalid (rejected in ip6_input)
271 * unicast somebody is doing address resolution -> ignore
272 * unspec dup address detection
273 *
274 * The processing is defined in RFC 2462.
275 */
276 if (tentative) {
277 /*
278 * If source address is unspecified address, it is for
279 * duplicated address detection.
280 *
281 * If not, the packet is for addess resolution;
282 * silently ignore it.
283 */
284 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
285 nd6_dad_ns_input(ifa);
286
287 goto freeit;
288 }
289
290 /*
291 * If the source address is unspecified address, entries must not
292 * be created or updated.
293 * It looks that sender is performing DAD. Output NA toward
294 * all-node multicast address, to tell the sender that I'm using
295 * the address.
296 * S bit ("solicited") must be zero.
297 */
298 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
299 saddr6 = in6addr_linklocal_allnodes;
300 saddr6.s6_addr16[1] = htons(ifp->if_index);
301 nd6_na_output(ifp, &saddr6, &taddr6,
302 ((anycast || proxy || !tlladdr)
303 ? 0 : ND_NA_FLAG_OVERRIDE)
304 | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
305 tlladdr, (struct sockaddr *)proxydl);
306 goto freeit;
307 }
308
309 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0);
310
311 nd6_na_output(ifp, &saddr6, &taddr6,
312 ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE)
313 | (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0)
314 | ND_NA_FLAG_SOLICITED,
315 tlladdr, (struct sockaddr *)proxydl);
316 freeit:
317 m_freem(m);
318 return;
319
320 bad:
321 nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)));
322 nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)));
323 nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)));
324 icmp6stat.icp6s_badns++;
325 m_freem(m);
326 }
327
328 /*
329 * Output an Neighbor Solicitation Message. Caller specifies:
330 * - ICMP6 header source IP6 address
331 * - ND6 header target IP6 address
332 * - ND6 header source datalink address
333 *
334 * Based on RFC 2461
335 * Based on RFC 2462 (duplicated address detection)
336 */
337 void
338 nd6_ns_output(
339 struct ifnet *ifp,
340 const struct in6_addr *daddr6,
341 const struct in6_addr *taddr6,
342 struct llinfo_nd6 *ln, /* for source address determination */
343 int dad, /* duplicated address detection */
344 int locked)
345 {
346 struct mbuf *m;
347 struct ip6_hdr *ip6;
348 struct nd_neighbor_solicit *nd_ns;
349 struct in6_ifaddr *ia = NULL;
350 struct ip6_moptions im6o;
351 int icmp6len;
352 int maxlen;
353 caddr_t mac;
354 struct ifnet *outif = NULL;
355
356 if (IN6_IS_ADDR_MULTICAST(taddr6))
357 return;
358
359 /* estimate the size of message */
360 maxlen = sizeof(*ip6) + sizeof(*nd_ns);
361 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
362 if (max_linkhdr + maxlen >= MCLBYTES) {
363 #if DIAGNOSTIC
364 printf("nd6_ns_output: max_linkhdr + maxlen >= MCLBYTES "
365 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
366 #endif
367 return;
368 }
369
370 MGETHDR(m, M_DONTWAIT, MT_DATA); /* XXXMAC: mac_create_mbuf_linklayer() probably */
371 if (m && max_linkhdr + maxlen >= MHLEN) {
372 MCLGET(m, M_DONTWAIT);
373 if ((m->m_flags & M_EXT) == 0) {
374 m_free(m);
375 m = NULL;
376 }
377 }
378 if (m == NULL)
379 return;
380 m->m_pkthdr.rcvif = NULL;
381
382 if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
383 m->m_flags |= M_MCAST;
384 im6o.im6o_multicast_ifp = ifp;
385 im6o.im6o_multicast_hlim = 255;
386 im6o.im6o_multicast_loop = 0;
387 }
388
389 icmp6len = sizeof(*nd_ns);
390 m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
391 m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */
392
393 /* fill neighbor solicitation packet */
394 ip6 = mtod(m, struct ip6_hdr *);
395 ip6->ip6_flow = 0;
396 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
397 ip6->ip6_vfc |= IPV6_VERSION;
398 /* ip6->ip6_plen will be set later */
399 ip6->ip6_nxt = IPPROTO_ICMPV6;
400 ip6->ip6_hlim = 255;
401 if (daddr6)
402 ip6->ip6_dst = *daddr6;
403 else {
404 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
405 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
406 ip6->ip6_dst.s6_addr32[1] = 0;
407 ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
408 ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
409 ip6->ip6_dst.s6_addr8[12] = 0xff;
410 }
411 if (!dad) {
412 #if 0 /* KAME way, exact address scope match */
413 /*
414 * Select a source whose scope is the same as that of the dest.
415 * Typically, the dest is link-local solicitation multicast
416 * (i.e. neighbor discovery) or link-local/global unicast
417 * (i.e. neighbor un-reachability detection).
418 */
419 ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
420 if (ia == NULL) {
421 m_freem(m);
422 return;
423 }
424 ip6->ip6_src = ia->ia_addr.sin6_addr;
425 #else /* spec-wise correct */
426 /*
427 * RFC2461 7.2.2:
428 * "If the source address of the packet prompting the
429 * solicitation is the same as one of the addresses assigned
430 * to the outgoing interface, that address SHOULD be placed
431 * in the IP Source Address of the outgoing solicitation.
432 * Otherwise, any one of the addresses assigned to the
433 * interface should be used."
434 *
435 * We use the source address for the prompting packet
436 * (saddr6), if:
437 * - saddr6 is given from the caller (by giving "ln"), and
438 * - saddr6 belongs to the outgoing interface.
439 * Otherwise, we perform a scope-wise match.
440 */
441 struct ip6_hdr *hip6; /* hold ip6 */
442 struct in6_addr *saddr6;
443
444 if (ln && ln->ln_hold) {
445 hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
446 /* XXX pullup? */
447 if (sizeof(*hip6) < ln->ln_hold->m_len)
448 saddr6 = &hip6->ip6_src;
449 else
450 saddr6 = NULL;
451 } else
452 saddr6 = NULL;
453 if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6))
454 bcopy(saddr6, &ip6->ip6_src, sizeof(*saddr6));
455 else {
456 ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
457 if (ia == NULL) {
458 if (ln && ln->ln_hold)
459 m_freem(ln->ln_hold);
460 ln->ln_hold = NULL;
461 m_freem(m);
462 return;
463 }
464 ip6->ip6_src = ia->ia_addr.sin6_addr;
465 }
466 #endif
467 } else {
468 /*
469 * Source address for DAD packet must always be IPv6
470 * unspecified address. (0::0)
471 */
472 bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
473 }
474 nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
475 nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
476 nd_ns->nd_ns_code = 0;
477 nd_ns->nd_ns_reserved = 0;
478 nd_ns->nd_ns_target = *taddr6;
479
480 if (IN6_IS_SCOPE_LINKLOCAL(&nd_ns->nd_ns_target))
481 nd_ns->nd_ns_target.s6_addr16[1] = 0;
482
483 /*
484 * Add source link-layer address option.
485 *
486 * spec implementation
487 * --- ---
488 * DAD packet MUST NOT do not add the option
489 * there's no link layer address:
490 * impossible do not add the option
491 * there's link layer address:
492 * Multicast NS MUST add one add the option
493 * Unicast NS SHOULD add one add the option
494 */
495 if (!dad && (mac = nd6_ifptomac(ifp))) {
496 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
497 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
498 /* 8 byte alignments... */
499 optlen = (optlen + 7) & ~7;
500
501 m->m_pkthdr.len += optlen;
502 m->m_len += optlen;
503 icmp6len += optlen;
504 bzero((caddr_t)nd_opt, optlen);
505 nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
506 nd_opt->nd_opt_len = optlen >> 3;
507 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
508 }
509
510 ip6->ip6_plen = htons((u_short)icmp6len);
511 nd_ns->nd_ns_cksum = 0;
512 nd_ns->nd_ns_cksum
513 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
514
515 #if IPSEC
516 /* Don't lookup socket */
517 if (ipsec_bypass == 0)
518 (void)ipsec_setsocket(m, NULL);
519 #endif
520 ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif, locked);
521 if (outif) {
522 icmp6_ifstat_inc(outif, ifs6_out_msg);
523 icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit);
524 }
525 icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
526 }
527
528 /*
529 * Neighbor advertisement input handling.
530 *
531 * Based on RFC 2461
532 * Based on RFC 2462 (duplicated address detection)
533 *
534 * the following items are not implemented yet:
535 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
536 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
537 */
538 void
539 nd6_na_input(
540 struct mbuf *m,
541 int off,
542 int icmp6len)
543 {
544 struct ifnet *ifp = m->m_pkthdr.rcvif;
545 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
546 struct nd_neighbor_advert *nd_na;
547 #if 0
548 struct in6_addr saddr6 = ip6->ip6_src;
549 #endif
550 struct in6_addr daddr6 = ip6->ip6_dst;
551 struct in6_addr taddr6;
552 int flags;
553 int is_router;
554 int is_solicited;
555 int is_override;
556 char *lladdr = NULL;
557 int lladdrlen = 0;
558 struct ifaddr *ifa;
559 struct llinfo_nd6 *ln;
560 struct rtentry *rt;
561 struct sockaddr_dl *sdl;
562 union nd_opts ndopts;
563 struct timeval timenow;
564
565 if (ip6->ip6_hlim != 255) {
566 nd6log((LOG_ERR,
567 "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n",
568 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
569 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
570 goto bad;
571 }
572
573 #ifndef PULLDOWN_TEST
574 IP6_EXTHDR_CHECK(m, off, icmp6len, return);
575 nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
576 #else
577 IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
578 if (nd_na == NULL) {
579 icmp6stat.icp6s_tooshort++;
580 return;
581 }
582 #endif
583 taddr6 = nd_na->nd_na_target;
584 flags = nd_na->nd_na_flags_reserved;
585 is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
586 is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
587 is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
588
589 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
590 taddr6.s6_addr16[1] = htons(ifp->if_index);
591
592 if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
593 nd6log((LOG_ERR,
594 "nd6_na_input: invalid target address %s\n",
595 ip6_sprintf(&taddr6)));
596 goto bad;
597 }
598 if (IN6_IS_ADDR_MULTICAST(&daddr6))
599 if (is_solicited) {
600 nd6log((LOG_ERR,
601 "nd6_na_input: a solicited adv is multicasted\n"));
602 goto bad;
603 }
604
605 icmp6len -= sizeof(*nd_na);
606 nd6_option_init(nd_na + 1, icmp6len, &ndopts);
607 if (nd6_options(&ndopts) < 0) {
608 nd6log((LOG_INFO,
609 "nd6_na_input: invalid ND option, ignored\n"));
610 /* nd6_options have incremented stats */
611 goto freeit;
612 }
613
614 if (ndopts.nd_opts_tgt_lladdr) {
615 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
616 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
617 }
618
619 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
620
621 /*
622 * Target address matches one of my interface address.
623 *
624 * If my address is tentative, this means that there's somebody
625 * already using the same address as mine. This indicates DAD failure.
626 * This is defined in RFC 2462.
627 *
628 * Otherwise, process as defined in RFC 2461.
629 */
630 if (ifa
631 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
632 nd6_dad_na_input(ifa);
633 goto freeit;
634 }
635
636 /* Just for safety, maybe unnecessary. */
637 if (ifa) {
638 log(LOG_ERR,
639 "nd6_na_input: duplicate IP6 address %s\n",
640 ip6_sprintf(&taddr6));
641 goto freeit;
642 }
643
644 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
645 nd6log((LOG_INFO,
646 "nd6_na_input: lladdrlen mismatch for %s "
647 "(if %d, NA packet %d)\n",
648 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
649 goto bad;
650 }
651
652 /*
653 * If no neighbor cache entry is found, NA SHOULD silently be discarded.
654 */
655 rt = nd6_lookup(&taddr6, 0, ifp, 0);
656 if ((rt == NULL) ||
657 ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
658 ((sdl = SDL(rt->rt_gateway)) == NULL))
659 goto freeit;
660
661 getmicrotime(&timenow);
662 if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
663 /*
664 * If the link-layer has address, and no lladdr option came,
665 * discard the packet.
666 */
667 if (ifp->if_addrlen && !lladdr)
668 goto freeit;
669
670 /*
671 * Record link-layer address, and update the state.
672 */
673 sdl->sdl_alen = ifp->if_addrlen;
674 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
675 if (is_solicited) {
676 ln->ln_state = ND6_LLINFO_REACHABLE;
677 ln->ln_byhint = 0;
678 if (ln->ln_expire)
679 ln->ln_expire = timenow.tv_sec +
680 nd_ifinfo[rt->rt_ifp->if_index].reachable;
681 } else {
682 ln->ln_state = ND6_LLINFO_STALE;
683 ln->ln_expire = timenow.tv_sec + nd6_gctimer;
684 }
685 if ((ln->ln_router = is_router) != 0) {
686 /*
687 * This means a router's state has changed from
688 * non-reachable to probably reachable, and might
689 * affect the status of associated prefixes..
690 */
691 pfxlist_onlink_check(0);
692 }
693 } else {
694 int llchange;
695
696 /*
697 * Check if the link-layer address has changed or not.
698 */
699 if (!lladdr)
700 llchange = 0;
701 else {
702 if (sdl->sdl_alen) {
703 if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
704 llchange = 1;
705 else
706 llchange = 0;
707 } else
708 llchange = 1;
709 }
710
711 /*
712 * This is VERY complex. Look at it with care.
713 *
714 * override solicit lladdr llchange action
715 * (L: record lladdr)
716 *
717 * 0 0 n -- (2c)
718 * 0 0 y n (2b) L
719 * 0 0 y y (1) REACHABLE->STALE
720 * 0 1 n -- (2c) *->REACHABLE
721 * 0 1 y n (2b) L *->REACHABLE
722 * 0 1 y y (1) REACHABLE->STALE
723 * 1 0 n -- (2a)
724 * 1 0 y n (2a) L
725 * 1 0 y y (2a) L *->STALE
726 * 1 1 n -- (2a) *->REACHABLE
727 * 1 1 y n (2a) L *->REACHABLE
728 * 1 1 y y (2a) L *->REACHABLE
729 */
730 if (!is_override && (lladdr && llchange)) { /* (1) */
731 /*
732 * If state is REACHABLE, make it STALE.
733 * no other updates should be done.
734 */
735 if (ln->ln_state == ND6_LLINFO_REACHABLE) {
736 ln->ln_state = ND6_LLINFO_STALE;
737 ln->ln_expire = timenow.tv_sec + nd6_gctimer;
738 }
739 goto freeit;
740 } else if (is_override /* (2a) */
741 || (!is_override && (lladdr && !llchange)) /* (2b) */
742 || !lladdr) { /* (2c) */
743 /*
744 * Update link-local address, if any.
745 */
746 if (lladdr) {
747 sdl->sdl_alen = ifp->if_addrlen;
748 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
749 }
750
751 /*
752 * If solicited, make the state REACHABLE.
753 * If not solicited and the link-layer address was
754 * changed, make it STALE.
755 */
756 if (is_solicited) {
757 ln->ln_state = ND6_LLINFO_REACHABLE;
758 ln->ln_byhint = 0;
759 if (ln->ln_expire) {
760 ln->ln_expire = timenow.tv_sec +
761 nd_ifinfo[ifp->if_index].reachable;
762 }
763 } else {
764 if (lladdr && llchange) {
765 ln->ln_state = ND6_LLINFO_STALE;
766 ln->ln_expire = timenow.tv_sec + nd6_gctimer;
767 }
768 }
769 }
770
771 if (ln->ln_router && !is_router) {
772 /*
773 * The peer dropped the router flag.
774 * Remove the sender from the Default Router List and
775 * update the Destination Cache entries.
776 */
777 struct nd_defrouter *dr;
778 struct in6_addr *in6;
779
780 in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
781
782 /*
783 * Lock to protect the default router list.
784 * XXX: this might be unnecessary, since this function
785 * is only called under the network software interrupt
786 * context. However, we keep it just for safety.
787 */
788 lck_mtx_lock(nd6_mutex);
789 dr = defrouter_lookup(in6, rt->rt_ifp);
790 if (dr) {
791 defrtrlist_del(dr, 1);
792 lck_mtx_unlock(nd6_mutex);
793 }
794 else {
795 lck_mtx_unlock(nd6_mutex);
796 if (!ip6_forwarding && (ip6_accept_rtadv || (rt->rt_ifp->if_eflags & IFEF_ACCEPT_RTADVD))) {
797 /*
798 * Even if the neighbor is not in the default
799 * router list, the neighbor may be used
800 * as a next hop for some destinations
801 * (e.g. redirect case). So we must
802 * call rt6_flush explicitly.
803 */
804 rt6_flush(&ip6->ip6_src, rt->rt_ifp);
805 }
806 }
807 }
808 ln->ln_router = is_router;
809 }
810 rt->rt_flags &= ~RTF_REJECT;
811 ln->ln_asked = 0;
812 if (ln->ln_hold) {
813 /*
814 * we assume ifp is not a loopback here, so just set the 2nd
815 * argument as the 1st one.
816 */
817 nd6_output(ifp, ifp, ln->ln_hold,
818 (struct sockaddr_in6 *)rt_key(rt), rt, 0);
819 ln->ln_hold = 0;
820 }
821
822 freeit:
823 m_freem(m);
824 return;
825
826 bad:
827 icmp6stat.icp6s_badna++;
828 m_freem(m);
829 }
830
831 /*
832 * Neighbor advertisement output handling.
833 *
834 * Based on RFC 2461
835 *
836 * the following items are not implemented yet:
837 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
838 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
839 */
840 void
841 nd6_na_output(
842 struct ifnet *ifp,
843 const struct in6_addr *daddr6,
844 const struct in6_addr *taddr6,
845 u_long flags,
846 int tlladdr, /* 1 if include target link-layer address */
847 struct sockaddr *sdl0) /* sockaddr_dl (= proxy NA) or NULL */
848 {
849 struct mbuf *m;
850 struct ip6_hdr *ip6;
851 struct nd_neighbor_advert *nd_na;
852 struct in6_ifaddr *ia = NULL;
853 struct ip6_moptions im6o;
854 int icmp6len;
855 int maxlen;
856 caddr_t mac = NULL;
857 struct ifnet *outif = NULL;
858
859 /* estimate the size of message */
860 maxlen = sizeof(*ip6) + sizeof(*nd_na);
861 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
862 if (max_linkhdr + maxlen >= MCLBYTES) {
863 #if DIAGNOSTIC
864 printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES "
865 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
866 #endif
867 return;
868 }
869
870 MGETHDR(m, M_DONTWAIT, MT_DATA); /* XXXMAC: mac_create_mbuf_linklayer() probably */
871 if (m && max_linkhdr + maxlen >= MHLEN) {
872 MCLGET(m, M_DONTWAIT);
873 if ((m->m_flags & M_EXT) == 0) {
874 m_free(m);
875 m = NULL;
876 }
877 }
878 if (m == NULL)
879 return;
880 m->m_pkthdr.rcvif = NULL;
881
882 if (IN6_IS_ADDR_MULTICAST(daddr6)) {
883 m->m_flags |= M_MCAST;
884 im6o.im6o_multicast_ifp = ifp;
885 im6o.im6o_multicast_hlim = 255;
886 im6o.im6o_multicast_loop = 0;
887 }
888
889 icmp6len = sizeof(*nd_na);
890 m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
891 m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */
892
893 /* fill neighbor advertisement packet */
894 ip6 = mtod(m, struct ip6_hdr *);
895 ip6->ip6_flow = 0;
896 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
897 ip6->ip6_vfc |= IPV6_VERSION;
898 ip6->ip6_nxt = IPPROTO_ICMPV6;
899 ip6->ip6_hlim = 255;
900 if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
901 /* reply to DAD */
902 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
903 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
904 ip6->ip6_dst.s6_addr32[1] = 0;
905 ip6->ip6_dst.s6_addr32[2] = 0;
906 ip6->ip6_dst.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
907 flags &= ~ND_NA_FLAG_SOLICITED;
908 } else
909 ip6->ip6_dst = *daddr6;
910
911 /*
912 * Select a source whose scope is the same as that of the dest.
913 */
914 ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
915 if (ia == NULL) {
916 m_freem(m);
917 return;
918 }
919 ip6->ip6_src = ia->ia_addr.sin6_addr;
920 nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
921 nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
922 nd_na->nd_na_code = 0;
923 nd_na->nd_na_target = *taddr6;
924 if (IN6_IS_SCOPE_LINKLOCAL(&nd_na->nd_na_target))
925 nd_na->nd_na_target.s6_addr16[1] = 0;
926
927 /*
928 * "tlladdr" indicates NS's condition for adding tlladdr or not.
929 * see nd6_ns_input() for details.
930 * Basically, if NS packet is sent to unicast/anycast addr,
931 * target lladdr option SHOULD NOT be included.
932 */
933 if (tlladdr) {
934 /*
935 * sdl0 != NULL indicates proxy NA. If we do proxy, use
936 * lladdr in sdl0. If we are not proxying (sending NA for
937 * my address) use lladdr configured for the interface.
938 */
939 if (sdl0 == NULL)
940 mac = nd6_ifptomac(ifp);
941 else if (sdl0->sa_family == AF_LINK) {
942 struct sockaddr_dl *sdl;
943 sdl = (struct sockaddr_dl *)sdl0;
944 if (sdl->sdl_alen == ifp->if_addrlen)
945 mac = LLADDR(sdl);
946 }
947 }
948 if (tlladdr && mac) {
949 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
950 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
951
952 /* roundup to 8 bytes alignment! */
953 optlen = (optlen + 7) & ~7;
954
955 m->m_pkthdr.len += optlen;
956 m->m_len += optlen;
957 icmp6len += optlen;
958 bzero((caddr_t)nd_opt, optlen);
959 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
960 nd_opt->nd_opt_len = optlen >> 3;
961 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
962 } else
963 flags &= ~ND_NA_FLAG_OVERRIDE;
964
965 ip6->ip6_plen = htons((u_short)icmp6len);
966 nd_na->nd_na_flags_reserved = flags;
967 nd_na->nd_na_cksum = 0;
968 nd_na->nd_na_cksum =
969 in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
970
971 #if IPSEC
972 /* Don't lookup socket */
973 if (ipsec_bypass == 0)
974 (void)ipsec_setsocket(m, NULL);
975 #endif
976 ip6_output(m, NULL, NULL, 0, &im6o, &outif, 0);
977 if (outif) {
978 icmp6_ifstat_inc(outif, ifs6_out_msg);
979 icmp6_ifstat_inc(outif, ifs6_out_neighboradvert);
980 }
981 icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
982 }
983
984 caddr_t
985 nd6_ifptomac(
986 struct ifnet *ifp)
987 {
988 return ((caddr_t)ifnet_lladdr(ifp));
989 }
990
991 TAILQ_HEAD(dadq_head, dadq);
992 struct dadq {
993 TAILQ_ENTRY(dadq) dad_list;
994 struct ifaddr *dad_ifa;
995 int dad_count; /* max NS to send */
996 int dad_ns_tcount; /* # of trials to send NS */
997 int dad_ns_ocount; /* NS sent so far */
998 int dad_ns_icount;
999 int dad_na_icount;
1000 };
1001
1002 static struct dadq_head dadq;
1003 static int dad_init = 0;
1004
1005 static struct dadq *
1006 nd6_dad_find(
1007 struct ifaddr *ifa)
1008 {
1009 struct dadq *dp;
1010 lck_mtx_lock(dad6_mutex);
1011 for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
1012 if (dp->dad_ifa == ifa) {
1013 lck_mtx_unlock(dad6_mutex);
1014 return dp;
1015 }
1016 }
1017 lck_mtx_unlock(dad6_mutex);
1018 return NULL;
1019 }
1020
1021 #ifdef __APPLE__
1022 void
1023 nd6_dad_stoptimer(
1024 struct ifaddr *ifa)
1025 {
1026
1027 untimeout((void (*)(void *))nd6_dad_timer, (void *)ifa);
1028 }
1029 #else
1030 static void
1031 nd6_dad_starttimer(
1032 struct dadq *dp,
1033 int ticks)
1034 {
1035
1036 callout_reset(&dp->dad_timer_ch, ticks,
1037 (void (*)(void *))nd6_dad_timer, (void *)dp->dad_ifa);
1038 }
1039
1040 static void
1041 nd6_dad_stoptimer(
1042 struct dadq *dp)
1043 {
1044
1045 callout_stop(&dp->dad_timer_ch);
1046 }
1047 #endif
1048
1049 /*
1050 * Start Duplicated Address Detection (DAD) for specified interface address.
1051 */
1052 void
1053 nd6_dad_start(
1054 struct ifaddr *ifa,
1055 int *tick_delay) /* minimum delay ticks for IFF_UP event */
1056 {
1057 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1058 struct dadq *dp;
1059
1060 if (!dad_init) {
1061 TAILQ_INIT(&dadq);
1062 dad_init++;
1063 }
1064
1065 /*
1066 * If we don't need DAD, don't do it.
1067 * There are several cases:
1068 * - DAD is disabled (ip6_dad_count == 0)
1069 * - the interface address is anycast
1070 */
1071 if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
1072 log(LOG_DEBUG,
1073 "nd6_dad_start: called with non-tentative address "
1074 "%s(%s)\n",
1075 ip6_sprintf(&ia->ia_addr.sin6_addr),
1076 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1077 return;
1078 }
1079 if (ia->ia6_flags & IN6_IFF_ANYCAST) {
1080 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1081 return;
1082 }
1083 if (!ip6_dad_count) {
1084 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1085 return;
1086 }
1087 if (!ifa->ifa_ifp)
1088 panic("nd6_dad_start: ifa->ifa_ifp == NULL");
1089 if (!(ifa->ifa_ifp->if_flags & IFF_UP))
1090 return;
1091 if (nd6_dad_find(ifa) != NULL) {
1092 /* DAD already in progress */
1093 return;
1094 }
1095
1096 dp = _MALLOC(sizeof(*dp), M_IP6NDP, M_NOWAIT);
1097 if (dp == NULL) {
1098 log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
1099 "%s(%s)\n",
1100 ip6_sprintf(&ia->ia_addr.sin6_addr),
1101 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1102 return;
1103 }
1104 bzero(dp, sizeof(*dp));
1105 lck_mtx_lock(dad6_mutex);
1106 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
1107 lck_mtx_unlock(dad6_mutex);
1108
1109 nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1110 ip6_sprintf(&ia->ia_addr.sin6_addr)));
1111
1112 /*
1113 * Send NS packet for DAD, ip6_dad_count times.
1114 * Note that we must delay the first transmission, if this is the
1115 * first packet to be sent from the interface after interface
1116 * (re)initialization.
1117 */
1118 dp->dad_ifa = ifa;
1119 ifaref(ifa); /*just for safety*/
1120 dp->dad_count = ip6_dad_count;
1121 dp->dad_ns_icount = dp->dad_na_icount = 0;
1122 dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1123 if (tick_delay == NULL) {
1124 nd6_dad_ns_output(dp, ifa);
1125 timeout((void (*)(void *))nd6_dad_timer, (void *)ifa,
1126 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
1127 } else {
1128 int ntick;
1129
1130 if (*tick_delay == 0)
1131 ntick = random() % (MAX_RTR_SOLICITATION_DELAY * hz);
1132 else
1133 ntick = *tick_delay + random() % (hz / 2);
1134 *tick_delay = ntick;
1135 timeout((void (*)(void *))nd6_dad_timer, (void *)ifa,
1136 ntick);
1137 }
1138 }
1139
1140 /*
1141 * terminate DAD unconditionally. used for address removals.
1142 */
1143 void
1144 nd6_dad_stop(
1145 struct ifaddr *ifa)
1146 {
1147 struct dadq *dp;
1148
1149 if (!dad_init)
1150 return;
1151 dp = nd6_dad_find(ifa);
1152 if (!dp) {
1153 /* DAD wasn't started yet */
1154 return;
1155 }
1156
1157 untimeout((void (*)(void *))nd6_dad_timer, (void *)ifa);
1158
1159 lck_mtx_lock(dad6_mutex);
1160 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1161 lck_mtx_unlock(dad6_mutex);
1162 FREE(dp, M_IP6NDP);
1163 dp = NULL;
1164 ifafree(ifa);
1165 }
1166
1167
1168 static void
1169 nd6_dad_timer(
1170 struct ifaddr *ifa)
1171 {
1172 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1173 struct dadq *dp;
1174
1175 /* Sanity check */
1176 if (ia == NULL) {
1177 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1178 goto done;
1179 }
1180 dp = nd6_dad_find(ifa);
1181 if (dp == NULL) {
1182 log(LOG_ERR, "nd6_dad_timer: DAD structure not found\n");
1183 goto done;
1184 }
1185 if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
1186 log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
1187 "%s(%s)\n",
1188 ip6_sprintf(&ia->ia_addr.sin6_addr),
1189 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1190 goto done;
1191 }
1192 if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
1193 log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
1194 "%s(%s)\n",
1195 ip6_sprintf(&ia->ia_addr.sin6_addr),
1196 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1197 goto done;
1198 }
1199
1200 /* timeouted with IFF_{RUNNING,UP} check */
1201 if (dp->dad_ns_tcount > dad_maxtry) {
1202 nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
1203 if_name(ifa->ifa_ifp)));
1204
1205 lck_mtx_lock(dad6_mutex);
1206 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1207 lck_mtx_unlock(dad6_mutex);
1208 FREE(dp, M_IP6NDP);
1209 dp = NULL;
1210 ifafree(ifa);
1211 goto done;
1212 }
1213
1214 /* Need more checks? */
1215 if (dp->dad_ns_ocount < dp->dad_count) {
1216 /*
1217 * We have more NS to go. Send NS packet for DAD.
1218 */
1219 nd6_dad_ns_output(dp, ifa);
1220 timeout((void (*)(void *))nd6_dad_timer, (void *)ifa,
1221 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
1222 } else {
1223 /*
1224 * We have transmitted sufficient number of DAD packets.
1225 * See what we've got.
1226 */
1227 int duplicate;
1228
1229 duplicate = 0;
1230
1231 if (dp->dad_na_icount) {
1232 /*
1233 * the check is in nd6_dad_na_input(),
1234 * but just in case
1235 */
1236 duplicate++;
1237 }
1238
1239 if (dp->dad_ns_icount) {
1240 #if 0 /* heuristics */
1241 /*
1242 * if
1243 * - we have sent many(?) DAD NS, and
1244 * - the number of NS we sent equals to the
1245 * number of NS we've got, and
1246 * - we've got no NA
1247 * we may have a faulty network card/driver which
1248 * loops back multicasts to myself.
1249 */
1250 if (3 < dp->dad_count
1251 && dp->dad_ns_icount == dp->dad_count
1252 && dp->dad_na_icount == 0) {
1253 log(LOG_INFO, "DAD questionable for %s(%s): "
1254 "network card loops back multicast?\n",
1255 ip6_sprintf(&ia->ia_addr.sin6_addr),
1256 if_name(ifa->ifa_ifp));
1257 /* XXX consider it a duplicate or not? */
1258 /* duplicate++; */
1259 } else {
1260 /* We've seen NS, means DAD has failed. */
1261 duplicate++;
1262 }
1263 #else
1264 /* We've seen NS, means DAD has failed. */
1265 duplicate++;
1266 #endif
1267 }
1268
1269 if (duplicate) {
1270 /* (*dp) will be freed in nd6_dad_duplicated() */
1271 dp = NULL;
1272 nd6_dad_duplicated(ifa);
1273 } else {
1274 /*
1275 * We are done with DAD. No NA came, no NS came.
1276 * duplicated address found.
1277 */
1278 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1279
1280 nd6log((LOG_DEBUG,
1281 "%s: DAD complete for %s - no duplicates found\n",
1282 if_name(ifa->ifa_ifp),
1283 ip6_sprintf(&ia->ia_addr.sin6_addr)));
1284
1285 lck_mtx_lock(dad6_mutex);
1286 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1287 lck_mtx_unlock(dad6_mutex);
1288 in6_post_msg(ia->ia_ifp, KEV_INET6_NEW_USER_ADDR, ia);
1289 FREE(dp, M_IP6NDP);
1290 dp = NULL;
1291 ifafree(ifa);
1292 }
1293 }
1294
1295 done:
1296 return;
1297 }
1298
1299 void
1300 nd6_dad_duplicated(
1301 struct ifaddr *ifa)
1302 {
1303 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1304 struct dadq *dp;
1305
1306 dp = nd6_dad_find(ifa);
1307 if (dp == NULL) {
1308 log(LOG_ERR, "nd6_dad_duplicated: DAD structure not found\n");
1309 return;
1310 }
1311
1312 log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: "
1313 "NS in/out=%d/%d, NA in=%d\n",
1314 if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr),
1315 dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_na_icount);
1316
1317 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1318 ia->ia6_flags |= IN6_IFF_DUPLICATED;
1319
1320 /* We are done with DAD, with duplicated address found. (failure) */
1321 untimeout((void (*)(void *))nd6_dad_timer, (void *)ifa);
1322
1323
1324 log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
1325 if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
1326 log(LOG_ERR, "%s: manual intervention required\n",
1327 if_name(ifa->ifa_ifp));
1328
1329 lck_mtx_lock(dad6_mutex);
1330 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1331 lck_mtx_unlock(dad6_mutex);
1332 FREE(dp, M_IP6NDP);
1333 dp = NULL;
1334 ifafree(ifa);
1335 }
1336
1337 static void
1338 nd6_dad_ns_output(
1339 struct dadq *dp,
1340 struct ifaddr *ifa)
1341 {
1342 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1343 struct ifnet *ifp = ifa->ifa_ifp;
1344
1345 dp->dad_ns_tcount++;
1346 if ((ifp->if_flags & IFF_UP) == 0) {
1347 #if 0
1348 printf("%s: interface down?\n", if_name(ifp));
1349 #endif
1350 return;
1351 }
1352 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1353 #if 0
1354 printf("%s: interface not running?\n", if_name(ifp));
1355 #endif
1356 return;
1357 }
1358
1359 dp->dad_ns_ocount++;
1360 nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL, 1, 0);
1361 }
1362
1363 static void
1364 nd6_dad_ns_input(
1365 struct ifaddr *ifa)
1366 {
1367 struct in6_ifaddr *ia;
1368 const struct in6_addr *taddr6;
1369 struct dadq *dp;
1370 int duplicate;
1371
1372 if (!ifa)
1373 panic("ifa == NULL in nd6_dad_ns_input");
1374
1375 ia = (struct in6_ifaddr *)ifa;
1376 taddr6 = &ia->ia_addr.sin6_addr;
1377 duplicate = 0;
1378 dp = nd6_dad_find(ifa);
1379
1380 /* Quickhack - completely ignore DAD NS packets */
1381 if (dad_ignore_ns) {
1382 nd6log((LOG_INFO,
1383 "nd6_dad_ns_input: ignoring DAD NS packet for "
1384 "address %s(%s)\n", ip6_sprintf(taddr6),
1385 if_name(ifa->ifa_ifp)));
1386 return;
1387 }
1388
1389 /*
1390 * if I'm yet to start DAD, someone else started using this address
1391 * first. I have a duplicate and you win.
1392 */
1393 if (!dp || dp->dad_ns_ocount == 0)
1394 duplicate++;
1395
1396 /* XXX more checks for loopback situation - see nd6_dad_timer too */
1397
1398 if (duplicate) {
1399 dp = NULL; /* will be freed in nd6_dad_duplicated() */
1400 nd6_dad_duplicated(ifa);
1401 } else {
1402 /*
1403 * not sure if I got a duplicate.
1404 * increment ns count and see what happens.
1405 */
1406 if (dp)
1407 dp->dad_ns_icount++;
1408 }
1409 }
1410
1411 static void
1412 nd6_dad_na_input(
1413 struct ifaddr *ifa)
1414 {
1415 struct dadq *dp;
1416
1417 if (!ifa)
1418 panic("ifa == NULL in nd6_dad_na_input");
1419
1420 dp = nd6_dad_find(ifa);
1421 if (dp)
1422 dp->dad_na_icount++;
1423
1424 /* remove the address. */
1425 nd6_dad_duplicated(ifa);
1426 }