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