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