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