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