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