nd6_nbr.c revision 1.16 1 /* $NetBSD: nd6_nbr.c,v 1.16 2000/02/26 08:39:20 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 #include <net/net_osdep.h>
63
64 #define SDL(s) ((struct sockaddr_dl *)s)
65
66 struct dadq;
67 static struct dadq *nd6_dad_find __P((struct ifaddr *));
68 static void nd6_dad_timer __P((struct ifaddr *));
69 static void nd6_dad_ns_output __P((struct dadq *, struct ifaddr *));
70 static void nd6_dad_ns_input __P((struct ifaddr *));
71 static void nd6_dad_na_input __P((struct ifaddr *));
72
73 static int dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/
74 static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
75
76 /*
77 * Input an Neighbor Solicitation Message.
78 *
79 * Based on RFC 2461
80 * Based on RFC 2462 (duplicated address detection)
81 */
82 void
83 nd6_ns_input(m, off, icmp6len)
84 struct mbuf *m;
85 int off, icmp6len;
86 {
87 struct ifnet *ifp = m->m_pkthdr.rcvif;
88 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
89 struct nd_neighbor_solicit *nd_ns;
90 struct in6_addr saddr6 = ip6->ip6_src;
91 struct in6_addr daddr6 = ip6->ip6_dst;
92 struct in6_addr taddr6;
93 struct in6_addr myaddr6;
94 char *lladdr = NULL;
95 struct ifaddr *ifa;
96 int lladdrlen = 0;
97 int anycast = 0, proxy = 0, tentative = 0;
98 int tlladdr;
99 union nd_opts ndopts;
100 struct sockaddr_dl *proxydl = NULL;
101
102 if (ip6->ip6_hlim != 255) {
103 log(LOG_ERR,
104 "nd6_ns_input: invalid hlim %d\n", ip6->ip6_hlim);
105 goto freeit;
106 }
107
108 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
109 /* dst has to be solicited node multicast address. */
110 if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL
111 /*don't check ifindex portion*/
112 && daddr6.s6_addr32[1] == 0
113 && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE
114 && daddr6.s6_addr8[12] == 0xff) {
115 ; /*good*/
116 } else {
117 log(LOG_INFO, "nd6_ns_input: bad DAD packet "
118 "(wrong ip6 dst)\n");
119 goto bad;
120 }
121 }
122
123 #ifndef PULLDOWN_TEST
124 IP6_EXTHDR_CHECK(m, off, icmp6len,);
125 nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
126 #else
127 IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
128 if (nd_ns == NULL) {
129 icmp6stat.icp6s_tooshort++;
130 return;
131 }
132 #endif
133 taddr6 = nd_ns->nd_ns_target;
134
135 if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
136 log(LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n");
137 goto bad;
138 }
139
140 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
141 taddr6.s6_addr16[1] = htons(ifp->if_index);
142
143 icmp6len -= sizeof(*nd_ns);
144 nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
145 if (nd6_options(&ndopts) < 0) {
146 log(LOG_INFO, "nd6_ns_input: invalid ND option, ignored\n");
147 goto bad;
148 }
149
150 if (ndopts.nd_opts_src_lladdr) {
151 lladdr = (char *)(ndopts.nd_opts_src_lladdr +1);
152 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
153 }
154
155 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
156 log(LOG_INFO, "nd6_ns_input: bad DAD packet "
157 "(link-layer address option)\n");
158 goto bad;
159 }
160
161 /*
162 * Attaching target link-layer address to the NA?
163 * (RFC 2461 7.2.4)
164 *
165 * NS IP dst is unicast/anycast MUST NOT add
166 * NS IP dst is solicited-node multicast MUST add
167 *
168 * In implementation, we add target link-layer address by default.
169 * We do not add one in MUST NOT cases.
170 */
171 #if 0 /* too much! */
172 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6);
173 if (ifa && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST))
174 tlladdr = 0;
175 else
176 #endif
177 if (!IN6_IS_ADDR_MULTICAST(&daddr6))
178 tlladdr = 0;
179 else
180 tlladdr = 1;
181
182 /*
183 * Target address (taddr6) must be either:
184 * (1) Valid unicast/anycast address for my receiving interface,
185 * (2) Unicast address for which I'm offering proxy service, or
186 * (3) "tentative" address on which DAD is being performed.
187 */
188 /* (1) and (3) check. */
189 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
190
191 /* (2) check. */
192 if (!ifa) {
193 struct rtentry *rt;
194 struct sockaddr_in6 tsin6;
195
196 bzero(&tsin6, sizeof tsin6);
197 tsin6.sin6_len = sizeof(struct sockaddr_in6);
198 tsin6.sin6_family = AF_INET6;
199 tsin6.sin6_addr = taddr6;
200
201 rt = rtalloc1((struct sockaddr *)&tsin6, 0
202 #ifdef __FreeBSD__
203 , 0
204 #endif /* __FreeBSD__ */
205 );
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 m->m_pkthdr.rcvif = NULL;
495 #endif /*IPSEC*/
496 ip6_output(m, NULL, NULL, dad ? IPV6_DADOUTPUT : 0, &im6o, &outif);
497 if (outif) {
498 icmp6_ifstat_inc(outif, ifs6_out_msg);
499 icmp6_ifstat_inc(outif, ifs6_out_neighborsolicit);
500 }
501 icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
502 }
503
504 /*
505 * Neighbor advertisement input handling.
506 *
507 * Based on RFC 2461
508 * Based on RFC 2462 (duplicated address detection)
509 *
510 * the following items are not implemented yet:
511 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
512 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
513 */
514 void
515 nd6_na_input(m, off, icmp6len)
516 struct mbuf *m;
517 int off, icmp6len;
518 {
519 struct ifnet *ifp = m->m_pkthdr.rcvif;
520 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
521 struct nd_neighbor_advert *nd_na;
522 #if 0
523 struct in6_addr saddr6 = ip6->ip6_src;
524 #endif
525 struct in6_addr daddr6 = ip6->ip6_dst;
526 struct in6_addr taddr6;
527 int flags;
528 int is_router;
529 int is_solicited;
530 int is_override;
531 char *lladdr = NULL;
532 int lladdrlen = 0;
533 struct ifaddr *ifa;
534 struct llinfo_nd6 *ln;
535 struct rtentry *rt;
536 struct sockaddr_dl *sdl;
537 union nd_opts ndopts;
538
539 if (ip6->ip6_hlim != 255) {
540 log(LOG_ERR,
541 "nd6_na_input: invalid hlim %d\n", ip6->ip6_hlim);
542 goto freeit;
543 }
544
545 #ifndef PULLDOWN_TEST
546 IP6_EXTHDR_CHECK(m, off, icmp6len,);
547 nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
548 #else
549 IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
550 if (nd_na == NULL) {
551 icmp6stat.icp6s_tooshort++;
552 return;
553 }
554 #endif
555 taddr6 = nd_na->nd_na_target;
556 flags = nd_na->nd_na_flags_reserved;
557 is_router = ((flags & ND_NA_FLAG_ROUTER) != 0);
558 is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0);
559 is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0);
560
561 if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
562 taddr6.s6_addr16[1] = htons(ifp->if_index);
563
564 if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
565 log(LOG_ERR,
566 "nd6_na_input: invalid target address %s\n",
567 ip6_sprintf(&taddr6));
568 goto freeit;
569 }
570 if (IN6_IS_ADDR_MULTICAST(&daddr6))
571 if (is_solicited) {
572 log(LOG_ERR,
573 "nd6_na_input: a solicited adv is multicasted\n");
574 goto freeit;
575 }
576
577 icmp6len -= sizeof(*nd_na);
578 nd6_option_init(nd_na + 1, icmp6len, &ndopts);
579 if (nd6_options(&ndopts) < 0) {
580 log(LOG_INFO, "nd6_na_input: invalid ND option, ignored\n");
581 goto freeit;
582 }
583
584 if (ndopts.nd_opts_tgt_lladdr) {
585 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
586 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
587 }
588
589 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
590
591 /*
592 * Target address matches one of my interface address.
593 *
594 * If my address is tentative, this means that there's somebody
595 * already using the same address as mine. This indicates DAD failure.
596 * This is defined in RFC 2462.
597 *
598 * Otherwise, process as defined in RFC 2461.
599 */
600 if (ifa
601 && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
602 nd6_dad_na_input(ifa);
603 goto freeit;
604 }
605
606 /* Just for safety, maybe unnecessery. */
607 if (ifa) {
608 log(LOG_ERR,
609 "nd6_na_input: duplicate IP6 address %s\n",
610 ip6_sprintf(&taddr6));
611 goto freeit;
612 }
613
614 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
615 log(LOG_INFO,
616 "nd6_na_input: lladdrlen mismatch for %s "
617 "(if %d, NA packet %d)\n",
618 ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2);
619 }
620
621 /*
622 * If no neighbor cache entry is found, NA SHOULD silently be discarded.
623 */
624 rt = nd6_lookup(&taddr6, 0, ifp);
625 if ((rt == NULL) ||
626 ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
627 ((sdl = SDL(rt->rt_gateway)) == NULL))
628 goto freeit;
629
630 if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
631 /*
632 * If the link-layer has address, and no lladdr option came,
633 * discard the packet.
634 */
635 if (ifp->if_addrlen && !lladdr)
636 goto freeit;
637
638 /*
639 * Record link-layer address, and update the state.
640 */
641 sdl->sdl_alen = ifp->if_addrlen;
642 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
643 if (is_solicited) {
644 ln->ln_state = ND6_LLINFO_REACHABLE;
645 if (ln->ln_expire)
646 ln->ln_expire = time.tv_sec +
647 nd_ifinfo[rt->rt_ifp->if_index].reachable;
648 } else
649 ln->ln_state = ND6_LLINFO_STALE;
650 ln->ln_router = is_router;
651 } else {
652 int llchange;
653
654 /*
655 * Check if the link-layer address has changed or not.
656 */
657 if (!lladdr)
658 llchange = 0;
659 else {
660 if (sdl->sdl_alen) {
661 if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
662 llchange = 1;
663 else
664 llchange = 0;
665 } else
666 llchange = 1;
667 }
668
669 /*
670 * This is VERY complex. Look at it with care.
671 *
672 * override solicit lladdr llchange action
673 * (L: record lladdr)
674 *
675 * 0 0 n -- (2c)
676 * 0 0 y n (2b) L
677 * 0 0 y y (1) REACHABLE->STALE
678 * 0 1 n -- (2c) *->REACHABLE
679 * 0 1 y n (2b) L *->REACHABLE
680 * 0 1 y y (1) REACHABLE->STALE
681 * 1 0 n -- (2a)
682 * 1 0 y n (2a) L
683 * 1 0 y y (2a) L *->STALE
684 * 1 1 n -- (2a) *->REACHABLE
685 * 1 1 y n (2a) L *->REACHABLE
686 * 1 1 y y (2a) L *->REACHABLE
687 */
688 if (!is_override && (lladdr && llchange)) { /* (1) */
689 /*
690 * If state is REACHABLE, make it STALE.
691 * no other updates should be done.
692 */
693 if (ln->ln_state == ND6_LLINFO_REACHABLE)
694 ln->ln_state = ND6_LLINFO_STALE;
695 goto freeit;
696 } else if (is_override /* (2a) */
697 || (!is_override && (lladdr && !llchange)) /* (2b) */
698 || !lladdr) { /* (2c) */
699 /*
700 * Update link-local address, if any.
701 */
702 if (lladdr) {
703 sdl->sdl_alen = ifp->if_addrlen;
704 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
705 }
706
707 /*
708 * If solicited, make the state REACHABLE.
709 * If not solicited and the link-layer address was
710 * changed, make it STALE.
711 */
712 if (is_solicited) {
713 ln->ln_state = ND6_LLINFO_REACHABLE;
714 if (ln->ln_expire) {
715 ln->ln_expire = time.tv_sec +
716 nd_ifinfo[ifp->if_index].reachable;
717 }
718 } else {
719 if (lladdr && llchange)
720 ln->ln_state = ND6_LLINFO_STALE;
721 }
722 }
723
724 if (ln->ln_router && !is_router) {
725 /*
726 * The peer dropped the router flag.
727 * Remove the sender from the Default Router List and
728 * update the Destination Cache entries.
729 */
730 struct nd_defrouter *dr;
731 struct in6_addr *in6;
732 int s;
733
734 in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
735 s = splsoftnet();
736 dr = defrouter_lookup(in6, rt->rt_ifp);
737 if (dr)
738 defrtrlist_del(dr);
739 else if (!ip6_forwarding && ip6_accept_rtadv) {
740 /*
741 * Even if the neighbor is not in the default
742 * router list, the neighbor may be used
743 * as a next hop for some destinations
744 * (e.g. redirect case). So we must
745 * call rt6_flush explicitly.
746 */
747 rt6_flush(&ip6->ip6_src, rt->rt_ifp);
748 }
749 splx(s);
750 }
751 ln->ln_router = is_router;
752 }
753 rt->rt_flags &= ~RTF_REJECT;
754 ln->ln_asked = 0;
755 if (ln->ln_hold) {
756 #ifdef OLDIP6OUTPUT
757 (*ifp->if_output)(ifp, ln->ln_hold, rt_key(rt), rt);
758 #else
759 nd6_output(ifp, ln->ln_hold,
760 (struct sockaddr_in6 *)rt_key(rt), rt);
761 #endif
762 ln->ln_hold = 0;
763 }
764
765 freeit:
766 m_freem(m);
767 }
768
769 /*
770 * Neighbor advertisement output handling.
771 *
772 * Based on RFC 2461
773 *
774 * the following items are not implemented yet:
775 * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD)
776 * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD)
777 */
778 void
779 nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
780 struct ifnet *ifp;
781 struct in6_addr *daddr6, *taddr6;
782 u_long flags;
783 int tlladdr; /* 1 if include target link-layer address */
784 struct sockaddr *sdl0; /* sockaddr_dl (= proxy NA) or NULL */
785 {
786 struct mbuf *m;
787 struct ip6_hdr *ip6;
788 struct nd_neighbor_advert *nd_na;
789 struct in6_ifaddr *ia = NULL;
790 struct ip6_moptions im6o;
791 int icmp6len;
792 int maxlen;
793 caddr_t mac;
794 struct ifnet *outif = NULL;
795
796 /* estimate the size of message */
797 maxlen = sizeof(*ip6) + sizeof(*nd_na);
798 maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
799 if (max_linkhdr + maxlen >= MCLBYTES) {
800 #ifdef DIAGNOSTIC
801 printf("nd6_na_output: max_linkhdr + maxlen >= MCLBYTES "
802 "(%d + %d > %d)\n", max_linkhdr, maxlen, MCLBYTES);
803 #endif
804 return;
805 }
806
807 MGETHDR(m, M_DONTWAIT, MT_DATA);
808 if (m && max_linkhdr + maxlen >= MHLEN) {
809 MCLGET(m, M_DONTWAIT);
810 if ((m->m_flags & M_EXT) == 0) {
811 m_free(m);
812 m = NULL;
813 }
814 }
815 if (m == NULL)
816 return;
817
818 if (IN6_IS_ADDR_MULTICAST(daddr6)) {
819 m->m_flags |= M_MCAST;
820 im6o.im6o_multicast_ifp = ifp;
821 im6o.im6o_multicast_hlim = 255;
822 im6o.im6o_multicast_loop = 0;
823 }
824
825 icmp6len = sizeof(*nd_na);
826 m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len;
827 m->m_data += max_linkhdr; /*or MH_ALIGN() equivalent?*/
828
829 /* fill neighbor advertisement packet */
830 ip6 = mtod(m, struct ip6_hdr *);
831 ip6->ip6_flow = 0;
832 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
833 ip6->ip6_vfc |= IPV6_VERSION;
834 ip6->ip6_nxt = IPPROTO_ICMPV6;
835 ip6->ip6_hlim = 255;
836 if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
837 /* reply to DAD */
838 ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
839 ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
840 ip6->ip6_dst.s6_addr32[1] = 0;
841 ip6->ip6_dst.s6_addr32[2] = 0;
842 ip6->ip6_dst.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
843 flags &= ~ND_NA_FLAG_SOLICITED;
844 } else
845 ip6->ip6_dst = *daddr6;
846
847 /*
848 * Select a source whose scope is the same as that of the dest.
849 */
850 ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
851 if (ia == NULL) {
852 m_freem(m);
853 return;
854 }
855 ip6->ip6_src = ia->ia_addr.sin6_addr;
856 nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
857 nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
858 nd_na->nd_na_code = 0;
859 nd_na->nd_na_target = *taddr6;
860 if (IN6_IS_SCOPE_LINKLOCAL(&nd_na->nd_na_target))
861 nd_na->nd_na_target.s6_addr16[1] = 0;
862
863 /*
864 * "tlladdr" indicates NS's condition for adding tlladdr or not.
865 * see nd6_ns_input() for details.
866 * Basically, if NS packet is sent to unicast/anycast addr,
867 * target lladdr option SHOULD NOT be included.
868 */
869 if (tlladdr) {
870 mac = NULL;
871 /*
872 * sdl0 != NULL indicates proxy NA. If we do proxy, use
873 * lladdr in sdl0. If we are not proxying (sending NA for
874 * my address) use lladdr configured for the interface.
875 */
876 if (sdl0 == NULL)
877 mac = nd6_ifptomac(ifp);
878 else if (sdl0->sa_family == AF_LINK) {
879 struct sockaddr_dl *sdl;
880 sdl = (struct sockaddr_dl *)sdl0;
881 if (sdl->sdl_alen == ifp->if_addrlen)
882 mac = LLADDR(sdl);
883 }
884 }
885 if (tlladdr && mac) {
886 int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
887 struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
888
889 /* roundup to 8 bytes alignment! */
890 optlen = (optlen + 7) & ~7;
891
892 m->m_pkthdr.len += optlen;
893 m->m_len += optlen;
894 icmp6len += optlen;
895 bzero((caddr_t)nd_opt, optlen);
896 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
897 nd_opt->nd_opt_len = optlen >> 3;
898 bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
899 } else
900 flags &= ~ND_NA_FLAG_OVERRIDE;
901
902 ip6->ip6_plen = htons((u_short)icmp6len);
903 nd_na->nd_na_flags_reserved = flags;
904 nd_na->nd_na_cksum = 0;
905 nd_na->nd_na_cksum =
906 in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
907
908 #ifdef IPSEC
909 m->m_pkthdr.rcvif = NULL;
910 #endif /*IPSEC*/
911 ip6_output(m, NULL, NULL, 0, &im6o, &outif);
912 if (outif) {
913 icmp6_ifstat_inc(outif, ifs6_out_msg);
914 icmp6_ifstat_inc(outif, ifs6_out_neighboradvert);
915 }
916 icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
917 }
918
919 caddr_t
920 nd6_ifptomac(ifp)
921 struct ifnet *ifp;
922 {
923 switch (ifp->if_type) {
924 case IFT_ARCNET:
925 case IFT_ETHER:
926 case IFT_FDDI:
927 return LLADDR(ifp->if_sadl);
928 break;
929 default:
930 return NULL;
931 }
932 }
933
934 TAILQ_HEAD(dadq_head, dadq);
935 struct dadq {
936 TAILQ_ENTRY(dadq) dad_list;
937 struct ifaddr *dad_ifa;
938 int dad_count; /* max NS to send */
939 int dad_ns_tcount; /* # of trials to send NS */
940 int dad_ns_ocount; /* NS sent so far */
941 int dad_ns_icount;
942 int dad_na_icount;
943 };
944
945 static struct dadq_head dadq;
946
947 static struct dadq *
948 nd6_dad_find(ifa)
949 struct ifaddr *ifa;
950 {
951 struct dadq *dp;
952
953 for (dp = dadq.tqh_first; dp; dp = dp->dad_list.tqe_next) {
954 if (dp->dad_ifa == ifa)
955 return dp;
956 }
957 return NULL;
958 }
959
960 /*
961 * Start Duplicated Address Detection (DAD) for specified interface address.
962 */
963 void
964 nd6_dad_start(ifa, tick)
965 struct ifaddr *ifa;
966 int *tick; /* minimum delay ticks for IFF_UP event */
967 {
968 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
969 struct dadq *dp;
970 static int dad_init = 0;
971
972 if (!dad_init) {
973 TAILQ_INIT(&dadq);
974 dad_init++;
975 }
976
977 /*
978 * If we don't need DAD, don't do it.
979 * There are several cases:
980 * - DAD is disabled (ip6_dad_count == 0)
981 * - the interface address is anycast
982 */
983 if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) {
984 log(LOG_DEBUG,
985 "nd6_dad_start: called with non-tentative address "
986 "%s(%s)\n",
987 ip6_sprintf(&ia->ia_addr.sin6_addr),
988 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
989 return;
990 }
991 if (ia->ia6_flags & IN6_IFF_ANYCAST) {
992 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
993 return;
994 }
995 if (!ip6_dad_count) {
996 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
997 return;
998 }
999 if (!ifa->ifa_ifp)
1000 panic("nd6_dad_start: ifa->ifa_ifp == NULL");
1001 if (!(ifa->ifa_ifp->if_flags & IFF_UP))
1002 return;
1003 if (nd6_dad_find(ifa) != NULL) {
1004 /* DAD already in progress */
1005 return;
1006 }
1007
1008 dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT);
1009 if (dp == NULL) {
1010 log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
1011 "%s(%s)\n",
1012 ip6_sprintf(&ia->ia_addr.sin6_addr),
1013 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1014 return;
1015 }
1016 bzero(dp, sizeof(*dp));
1017 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
1018
1019 log(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1020 ip6_sprintf(&ia->ia_addr.sin6_addr));
1021
1022 /*
1023 * Send NS packet for DAD, ip6_dad_count times.
1024 * Note that we must delay the first transmission, if this is the
1025 * first packet to be sent from the interface after interface
1026 * (re)initialization.
1027 */
1028 dp->dad_ifa = ifa;
1029 IFAREF(ifa); /* just for safety */
1030 dp->dad_count = ip6_dad_count;
1031 dp->dad_ns_icount = dp->dad_na_icount = 0;
1032 dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1033 if (!tick) {
1034 nd6_dad_ns_output(dp, ifa);
1035 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
1036 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
1037 } else {
1038 int ntick;
1039
1040 if (*tick == 0)
1041 ntick = random() % (MAX_RTR_SOLICITATION_DELAY * hz);
1042 else
1043 ntick = *tick + random() % (hz / 2);
1044 *tick = ntick;
1045 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
1046 ntick);
1047 }
1048 }
1049
1050 static void
1051 nd6_dad_timer(ifa)
1052 struct ifaddr *ifa;
1053 {
1054 int s;
1055 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1056 struct dadq *dp;
1057
1058 s = splsoftnet(); /*XXX*/
1059
1060 /* Sanity check */
1061 if (ia == NULL) {
1062 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1063 goto done;
1064 }
1065 dp = nd6_dad_find(ifa);
1066 if (dp == NULL) {
1067 log(LOG_ERR, "nd6_dad_timer: DAD structure not found\n");
1068 goto done;
1069 }
1070 if (ia->ia6_flags & IN6_IFF_DUPLICATED) {
1071 log(LOG_ERR, "nd6_dad_timer: called with duplicated address "
1072 "%s(%s)\n",
1073 ip6_sprintf(&ia->ia_addr.sin6_addr),
1074 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1075 goto done;
1076 }
1077 if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
1078 log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
1079 "%s(%s)\n",
1080 ip6_sprintf(&ia->ia_addr.sin6_addr),
1081 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1082 goto done;
1083 }
1084
1085 /* timeouted with IFF_{RUNNING,UP} check */
1086 if (dp->dad_ns_tcount > dad_maxtry) {
1087 log(LOG_ERR, "%s: could not run DAD, driver problem?\n",
1088 if_name(ifa->ifa_ifp));
1089
1090 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1091 free(dp, M_IP6NDP);
1092 dp = NULL;
1093 IFAFREE(ifa);
1094 goto done;
1095 }
1096
1097 /* Need more checks? */
1098 if (dp->dad_ns_ocount < dp->dad_count) {
1099 /*
1100 * We have more NS to go. Send NS packet for DAD.
1101 */
1102 nd6_dad_ns_output(dp, ifa);
1103 timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa,
1104 nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
1105 } else {
1106 /*
1107 * We have transmitted sufficient number of DAD packets.
1108 * See what we've got.
1109 */
1110 int duplicate;
1111
1112 duplicate = 0;
1113
1114 if (dp->dad_na_icount) {
1115 /*
1116 * the check is in nd6_dad_na_input(),
1117 * but just in case
1118 */
1119 duplicate++;
1120 }
1121
1122 if (dp->dad_ns_icount) {
1123 #if 0 /*heuristics*/
1124 /*
1125 * if
1126 * - we have sent many(?) DAD NS, and
1127 * - the number of NS we sent equals to the
1128 * number of NS we've got, and
1129 * - we've got no NA
1130 * we may have a faulty network card/driver which
1131 * loops back multicasts to myself.
1132 */
1133 if (3 < dp->dad_count
1134 && dp->dad_ns_icount == dp->dad_count
1135 && dp->dad_na_icount == 0) {
1136 log(LOG_INFO, "DAD questionable for %s(%s): "
1137 "network card loops back multicast?\n",
1138 ip6_sprintf(&ia->ia_addr.sin6_addr),
1139 if_name(ifa->ifa_ifp));
1140 /* XXX consider it a duplicate or not? */
1141 /* duplicate++; */
1142 } else {
1143 /* We've seen NS, means DAD has failed. */
1144 duplicate++;
1145 }
1146 #else
1147 /* We've seen NS, means DAD has failed. */
1148 duplicate++;
1149 #endif
1150 }
1151
1152 if (duplicate) {
1153 /* (*dp) will be freed in nd6_dad_duplicated() */
1154 dp = NULL;
1155 nd6_dad_duplicated(ifa);
1156 } else {
1157 /*
1158 * We are done with DAD. No NA came, no NS came.
1159 * duplicated address found.
1160 */
1161 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1162
1163 log(LOG_INFO,
1164 "%s: DAD complete for %s - no duplicates found\n",
1165 if_name(ifa->ifa_ifp),
1166 ip6_sprintf(&ia->ia_addr.sin6_addr));
1167
1168 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1169 free(dp, M_IP6NDP);
1170 dp = NULL;
1171 IFAFREE(ifa);
1172 }
1173 }
1174
1175 done:
1176 splx(s);
1177 }
1178
1179 void
1180 nd6_dad_duplicated(ifa)
1181 struct ifaddr *ifa;
1182 {
1183 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1184 struct dadq *dp;
1185
1186 dp = nd6_dad_find(ifa);
1187 if (dp == NULL) {
1188 log(LOG_ERR, "nd6_dad_duplicated: DAD structure not found\n");
1189 return;
1190 }
1191
1192 log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: %d NS, "
1193 "%d NA\n", if_name(ifa->ifa_ifp),
1194 ip6_sprintf(&ia->ia_addr.sin6_addr),
1195 dp->dad_ns_icount, dp->dad_na_icount);
1196
1197 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1198 ia->ia6_flags |= IN6_IFF_DUPLICATED;
1199
1200 /* We are done with DAD, with duplicated address found. (failure) */
1201 untimeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa);
1202
1203 log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
1204 if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
1205 log(LOG_ERR, "%s: manual intervention required\n",
1206 if_name(ifa->ifa_ifp));
1207
1208 TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
1209 free(dp, M_IP6NDP);
1210 dp = NULL;
1211 IFAFREE(ifa);
1212 }
1213
1214 static void
1215 nd6_dad_ns_output(dp, ifa)
1216 struct dadq *dp;
1217 struct ifaddr *ifa;
1218 {
1219 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1220 struct ifnet *ifp = ifa->ifa_ifp;
1221
1222 dp->dad_ns_tcount++;
1223 if ((ifp->if_flags & IFF_UP) == 0) {
1224 #if 0
1225 printf("%s: interface down?\n", if_name(ifp));
1226 #endif
1227 return;
1228 }
1229 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1230 #if 0
1231 printf("%s: interface not running?\n", if_name(ifp));
1232 #endif
1233 return;
1234 }
1235
1236 dp->dad_ns_ocount++;
1237 nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL, 1);
1238 }
1239
1240 static void
1241 nd6_dad_ns_input(ifa)
1242 struct ifaddr *ifa;
1243 {
1244 struct in6_ifaddr *ia;
1245 struct ifnet *ifp;
1246 struct in6_addr *taddr6;
1247 struct dadq *dp;
1248 int duplicate;
1249
1250 if (!ifa)
1251 panic("ifa == NULL in nd6_dad_ns_input");
1252
1253 ia = (struct in6_ifaddr *)ifa;
1254 ifp = ifa->ifa_ifp;
1255 taddr6 = &ia->ia_addr.sin6_addr;
1256 duplicate = 0;
1257 dp = nd6_dad_find(ifa);
1258
1259 /*
1260 * If it is from myself, ignore this.
1261 */
1262 if (ifp && (ifp->if_flags & IFF_LOOPBACK))
1263 return;
1264
1265 /* Quickhack - completely ignore DAD NS packets */
1266 if (dad_ignore_ns) {
1267 log(LOG_INFO, "nd6_dad_ns_input: ignoring DAD NS packet for "
1268 "address %s(%s)\n", ip6_sprintf(taddr6),
1269 if_name(ifa->ifa_ifp));
1270 return;
1271 }
1272
1273 /*
1274 * if I'm yet to start DAD, someone else started using this address
1275 * first. I have a duplicate and you win.
1276 */
1277 if (!dp || dp->dad_ns_ocount == 0)
1278 duplicate++;
1279
1280 /* XXX more checks for loopback situation - see nd6_dad_timer too */
1281
1282 if (duplicate) {
1283 dp = NULL; /* will be freed in nd6_dad_duplicated() */
1284 nd6_dad_duplicated(ifa);
1285 } else {
1286 /*
1287 * not sure if I got a duplicate.
1288 * increment ns count and see what happens.
1289 */
1290 if (dp)
1291 dp->dad_ns_icount++;
1292 }
1293 }
1294
1295 static void
1296 nd6_dad_na_input(ifa)
1297 struct ifaddr *ifa;
1298 {
1299 struct dadq *dp;
1300
1301 if (!ifa)
1302 panic("ifa == NULL in nd6_dad_na_input");
1303
1304 dp = nd6_dad_find(ifa);
1305 if (dp)
1306 dp->dad_na_icount++;
1307
1308 /* remove the address. */
1309 nd6_dad_duplicated(ifa);
1310 }
1311