1 /* $NetBSD: in6_ifattach.c,v 1.63 2006/01/21 00:15:36 rpaulo Exp $ */ 2 /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 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 <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.63 2006/01/21 00:15:36 rpaulo Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/socket.h> 40 #include <sys/sockio.h> 41 #include <sys/kernel.h> 42 #include <sys/syslog.h> 43 #include <sys/md5.h> 44 45 #include <net/if.h> 46 #include <net/if_dl.h> 47 #include <net/if_types.h> 48 #include <net/route.h> 49 50 #include <netinet/in.h> 51 #include <netinet/in_var.h> 52 53 #include <netinet/ip6.h> 54 #include <netinet6/in6_ifattach.h> 55 #include <netinet6/ip6_var.h> 56 #include <netinet6/nd6.h> 57 #include <netinet6/ip6_mroute.h> 58 #include <netinet6/scope6_var.h> 59 60 #include <net/net_osdep.h> 61 62 unsigned long in6_maxmtu = 0; 63 64 int ip6_auto_linklocal = 1; /* enable by default */ 65 66 static int get_rand_ifid __P((struct ifnet *, struct in6_addr *)); 67 static int get_hw_ifid __P((struct ifnet *, struct in6_addr *)); 68 static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *)); 69 static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *)); 70 static int in6_ifattach_loopback __P((struct ifnet *)); 71 72 #define EUI64_GBIT 0x01 73 #define EUI64_UBIT 0x02 74 #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (/*CONSTCOND*/ 0) 75 #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) 76 #define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6)) 77 #define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT) 78 #define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6)) 79 80 #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) 81 #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) 82 83 /* 84 * Generate a last-resort interface identifier, when the machine has no 85 * IEEE802/EUI64 address sources. 86 * The goal here is to get an interface identifier that is 87 * (1) random enough and (2) does not change across reboot. 88 * We currently use MD5(hostname) for it. 89 */ 90 static int 91 get_rand_ifid(ifp, in6) 92 struct ifnet *ifp; 93 struct in6_addr *in6; /* upper 64bits are preserved */ 94 { 95 MD5_CTX ctxt; 96 u_int8_t digest[16]; 97 98 #if 0 99 /* we need at least several letters as seed for ifid */ 100 if (hostnamelen < 3) 101 return -1; 102 #endif 103 104 /* generate 8 bytes of pseudo-random value. */ 105 bzero(&ctxt, sizeof(ctxt)); 106 MD5Init(&ctxt); 107 MD5Update(&ctxt, (u_char *)hostname, hostnamelen); 108 MD5Final(digest, &ctxt); 109 110 /* assumes sizeof(digest) > sizeof(ifid) */ 111 bcopy(digest, &in6->s6_addr[8], 8); 112 113 /* make sure to set "u" bit to local, and "g" bit to individual. */ 114 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 115 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 116 117 /* convert EUI64 into IPv6 interface identifier */ 118 EUI64_TO_IFID(in6); 119 120 return 0; 121 } 122 123 /* 124 * Get interface identifier for the specified interface. 125 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface 126 */ 127 static int 128 get_hw_ifid(ifp, in6) 129 struct ifnet *ifp; 130 struct in6_addr *in6; /* upper 64bits are preserved */ 131 { 132 struct ifaddr *ifa; 133 struct sockaddr_dl *sdl; 134 char *addr; 135 size_t addrlen; 136 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 137 static u_int8_t allone[8] = 138 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 139 140 for (ifa = ifp->if_addrlist.tqh_first; 141 ifa; 142 ifa = ifa->ifa_list.tqe_next) 143 { 144 if (ifa->ifa_addr->sa_family != AF_LINK) 145 continue; 146 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 147 if (sdl == NULL) 148 continue; 149 if (sdl->sdl_alen == 0) 150 continue; 151 152 goto found; 153 } 154 155 return -1; 156 157 found: 158 addr = LLADDR(sdl); 159 addrlen = sdl->sdl_alen; 160 161 switch (ifp->if_type) { 162 case IFT_IEEE1394: 163 case IFT_IEEE80211: 164 /* IEEE1394 uses 16byte length address starting with EUI64 */ 165 if (addrlen > 8) 166 addrlen = 8; 167 break; 168 default: 169 break; 170 } 171 172 /* get EUI64 */ 173 switch (ifp->if_type) { 174 /* IEEE802/EUI64 cases - what others? */ 175 case IFT_ETHER: 176 case IFT_FDDI: 177 case IFT_ATM: 178 case IFT_IEEE1394: 179 case IFT_IEEE80211: 180 /* look at IEEE802/EUI64 only */ 181 if (addrlen != 8 && addrlen != 6) 182 return -1; 183 184 /* 185 * check for invalid MAC address - on bsdi, we see it a lot 186 * since wildboar configures all-zero MAC on pccard before 187 * card insertion. 188 */ 189 if (bcmp(addr, allzero, addrlen) == 0) 190 return -1; 191 if (bcmp(addr, allone, addrlen) == 0) 192 return -1; 193 194 /* make EUI64 address */ 195 if (addrlen == 8) 196 bcopy(addr, &in6->s6_addr[8], 8); 197 else if (addrlen == 6) { 198 in6->s6_addr[8] = addr[0]; 199 in6->s6_addr[9] = addr[1]; 200 in6->s6_addr[10] = addr[2]; 201 in6->s6_addr[11] = 0xff; 202 in6->s6_addr[12] = 0xfe; 203 in6->s6_addr[13] = addr[3]; 204 in6->s6_addr[14] = addr[4]; 205 in6->s6_addr[15] = addr[5]; 206 } 207 break; 208 209 case IFT_ARCNET: 210 if (addrlen != 1) 211 return -1; 212 if (!addr[0]) 213 return -1; 214 215 bzero(&in6->s6_addr[8], 8); 216 in6->s6_addr[15] = addr[0]; 217 218 /* 219 * due to insufficient bitwidth, we mark it local. 220 */ 221 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 222 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 223 break; 224 225 case IFT_GIF: 226 #ifdef IFT_STF 227 case IFT_STF: 228 #endif 229 /* 230 * RFC2893 says: "SHOULD use IPv4 address as ifid source". 231 * however, IPv4 address is not very suitable as unique 232 * identifier source (can be renumbered). 233 * we don't do this. 234 */ 235 return -1; 236 237 default: 238 return -1; 239 } 240 241 /* sanity check: g bit must not indicate "group" */ 242 if (EUI64_GROUP(in6)) 243 return -1; 244 245 /* convert EUI64 into IPv6 interface identifier */ 246 EUI64_TO_IFID(in6); 247 248 /* 249 * sanity check: ifid must not be all zero, avoid conflict with 250 * subnet router anycast 251 */ 252 if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && 253 bcmp(&in6->s6_addr[9], allzero, 7) == 0) { 254 return -1; 255 } 256 257 return 0; 258 } 259 260 /* 261 * Get interface identifier for the specified interface. If it is not 262 * available on ifp0, borrow interface identifier from other information 263 * sources. 264 */ 265 static int 266 get_ifid(ifp0, altifp, in6) 267 struct ifnet *ifp0; 268 struct ifnet *altifp; /*secondary EUI64 source*/ 269 struct in6_addr *in6; 270 { 271 struct ifnet *ifp; 272 273 /* first, try to get it from the interface itself */ 274 if (get_hw_ifid(ifp0, in6) == 0) { 275 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", 276 if_name(ifp0))); 277 goto success; 278 } 279 280 /* try secondary EUI64 source. this basically is for ATM PVC */ 281 if (altifp && get_hw_ifid(altifp, in6) == 0) { 282 nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", 283 if_name(ifp0), if_name(altifp))); 284 goto success; 285 } 286 287 /* next, try to get it from some other hardware interface */ 288 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 289 { 290 if (ifp == ifp0) 291 continue; 292 if (get_hw_ifid(ifp, in6) != 0) 293 continue; 294 295 /* 296 * to borrow ifid from other interface, ifid needs to be 297 * globally unique 298 */ 299 if (IFID_UNIVERSAL(in6)) { 300 nd6log((LOG_DEBUG, 301 "%s: borrow interface identifier from %s\n", 302 if_name(ifp0), if_name(ifp))); 303 goto success; 304 } 305 } 306 307 /* last resort: get from random number source */ 308 if (get_rand_ifid(ifp, in6) == 0) { 309 nd6log((LOG_DEBUG, 310 "%s: interface identifier generated by random number\n", 311 if_name(ifp0))); 312 goto success; 313 } 314 315 printf("%s: failed to get interface identifier\n", if_name(ifp0)); 316 return -1; 317 318 success: 319 nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 320 if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10], 321 in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13], 322 in6->s6_addr[14], in6->s6_addr[15])); 323 return 0; 324 } 325 326 static int 327 in6_ifattach_linklocal(ifp, altifp) 328 struct ifnet *ifp; 329 struct ifnet *altifp; /*secondary EUI64 source*/ 330 { 331 struct in6_ifaddr *ia; 332 struct in6_aliasreq ifra; 333 struct nd_prefix pr0; 334 int i, error; 335 336 /* 337 * configure link-local address. 338 */ 339 bzero(&ifra, sizeof(ifra)); 340 341 /* 342 * in6_update_ifa() does not use ifra_name, but we accurately set it 343 * for safety. 344 */ 345 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name)); 346 347 ifra.ifra_addr.sin6_family = AF_INET6; 348 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); 349 ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000); 350 ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; 351 if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 352 ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; 353 ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); 354 } else { 355 if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) { 356 nd6log((LOG_ERR, 357 "%s: no ifid available\n", if_name(ifp))); 358 return (-1); 359 } 360 } 361 if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL)) 362 return (-1); 363 364 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 365 ifra.ifra_prefixmask.sin6_family = AF_INET6; 366 ifra.ifra_prefixmask.sin6_addr = in6mask64; 367 /* link-local addresses should NEVER expire. */ 368 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 369 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 370 371 /* 372 * Do not let in6_update_ifa() do DAD, since we need a random delay 373 * before sending an NS at the first time the interface becomes up. 374 * Instead, in6_if_up() will start DAD with a proper random delay. 375 */ 376 ifra.ifra_flags |= IN6_IFF_NODAD; 377 378 /* 379 * Now call in6_update_ifa() to do a bunch of procedures to configure 380 * a link-local address. We can set NULL to the 3rd argument, because 381 * we know there's no other link-local address on the interface 382 * and therefore we are adding one (instead of updating one). 383 */ 384 if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) { 385 /* 386 * XXX: When the interface does not support IPv6, this call 387 * would fail in the SIOCSIFADDR ioctl. I believe the 388 * notification is rather confusing in this case, so just 389 * suppress it. (jinmei@kame.net 20010130) 390 */ 391 if (error != EAFNOSUPPORT) 392 nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to " 393 "configure a link-local address on %s " 394 "(errno=%d)\n", 395 if_name(ifp), error)); 396 return (-1); 397 } 398 399 /* 400 * Adjust ia6_flags so that in6_if_up will perform DAD. 401 * XXX: Some P2P interfaces seem not to send packets just after 402 * becoming up, so we skip p2p interfaces for safety. 403 */ 404 ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */ 405 #ifdef DIAGNOSTIC 406 if (!ia) { 407 panic("ia == NULL in in6_ifattach_linklocal"); 408 /* NOTREACHED */ 409 } 410 #endif 411 if (in6if_do_dad(ifp) && (ifp->if_flags & IFF_POINTOPOINT) == 0) { 412 ia->ia6_flags &= ~IN6_IFF_NODAD; 413 ia->ia6_flags |= IN6_IFF_TENTATIVE; 414 } 415 416 /* 417 * Make the link-local prefix (fe80::/64%link) as on-link. 418 * Since we'd like to manage prefixes separately from addresses, 419 * we make an ND6 prefix structure for the link-local prefix, 420 * and add it to the prefix list as a never-expire prefix. 421 * XXX: this change might affect some existing code base... 422 */ 423 bzero(&pr0, sizeof(pr0)); 424 pr0.ndpr_ifp = ifp; 425 /* this should be 64 at this moment. */ 426 pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL); 427 pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr; 428 pr0.ndpr_prefix = ifra.ifra_addr; 429 /* apply the mask for safety. (nd6_prelist_add will apply it again) */ 430 for (i = 0; i < 4; i++) { 431 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &= 432 in6mask64.s6_addr32[i]; 433 } 434 /* 435 * Initialize parameters. The link-local prefix must always be 436 * on-link, and its lifetimes never expire. 437 */ 438 pr0.ndpr_raf_onlink = 1; 439 pr0.ndpr_raf_auto = 1; /* probably meaningless */ 440 pr0.ndpr_vltime = ND6_INFINITE_LIFETIME; 441 pr0.ndpr_pltime = ND6_INFINITE_LIFETIME; 442 /* 443 * Since there is no other link-local addresses, nd6_prefix_lookup() 444 * probably returns NULL. However, we cannot always expect the result. 445 * For example, if we first remove the (only) existing link-local 446 * address, and then reconfigure another one, the prefix is still 447 * valid with referring to the old link-local address. 448 */ 449 if (nd6_prefix_lookup(&pr0) == NULL) { 450 if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0) 451 return (error); 452 } 453 454 return 0; 455 } 456 457 static int 458 in6_ifattach_loopback(ifp) 459 struct ifnet *ifp; /* must be IFT_LOOP */ 460 { 461 struct in6_aliasreq ifra; 462 int error; 463 464 bzero(&ifra, sizeof(ifra)); 465 466 /* 467 * in6_update_ifa() does not use ifra_name, but we accurately set it 468 * for safety. 469 */ 470 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name)); 471 472 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 473 ifra.ifra_prefixmask.sin6_family = AF_INET6; 474 ifra.ifra_prefixmask.sin6_addr = in6mask128; 475 476 /* 477 * Always initialize ia_dstaddr (= broadcast address) to loopback 478 * address. Follows IPv4 practice - see in_ifinit(). 479 */ 480 ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 481 ifra.ifra_dstaddr.sin6_family = AF_INET6; 482 ifra.ifra_dstaddr.sin6_addr = in6addr_loopback; 483 484 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); 485 ifra.ifra_addr.sin6_family = AF_INET6; 486 ifra.ifra_addr.sin6_addr = in6addr_loopback; 487 488 /* the loopback address should NEVER expire. */ 489 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 490 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 491 492 /* we don't need to perform DAD on loopback interfaces. */ 493 ifra.ifra_flags |= IN6_IFF_NODAD; 494 495 /* 496 * We are sure that this is a newly assigned address, so we can set 497 * NULL to the 3rd arg. 498 */ 499 if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) { 500 nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure " 501 "the loopback address on %s (errno=%d)\n", 502 if_name(ifp), error)); 503 return (-1); 504 } 505 506 return 0; 507 } 508 509 /* 510 * compute NI group address, based on the current hostname setting. 511 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later). 512 * 513 * when ifp == NULL, the caller is responsible for filling scopeid. 514 */ 515 int 516 in6_nigroup(ifp, name, namelen, sa6) 517 struct ifnet *ifp; 518 const char *name; 519 int namelen; 520 struct sockaddr_in6 *sa6; 521 { 522 const char *p; 523 u_int8_t *q; 524 MD5_CTX ctxt; 525 u_int8_t digest[16]; 526 u_int8_t l; 527 u_int8_t n[64]; /* a single label must not exceed 63 chars */ 528 529 if (!namelen || !name) 530 return -1; 531 532 p = name; 533 while (p && *p && *p != '.' && p - name < namelen) 534 p++; 535 if (p - name > sizeof(n) - 1) 536 return -1; /* label too long */ 537 l = p - name; 538 strncpy((char *)n, name, l); 539 n[(int)l] = '\0'; 540 for (q = n; *q; q++) { 541 if ('A' <= *q && *q <= 'Z') 542 *q = *q - 'A' + 'a'; 543 } 544 545 /* generate 8 bytes of pseudo-random value. */ 546 bzero(&ctxt, sizeof(ctxt)); 547 MD5Init(&ctxt); 548 MD5Update(&ctxt, &l, sizeof(l)); 549 MD5Update(&ctxt, n, l); 550 MD5Final(digest, &ctxt); 551 552 bzero(sa6, sizeof(*sa6)); 553 sa6->sin6_family = AF_INET6; 554 sa6->sin6_len = sizeof(*sa6); 555 sa6->sin6_addr.s6_addr16[0] = htons(0xff02); 556 sa6->sin6_addr.s6_addr8[11] = 2; 557 bcopy(digest, &sa6->sin6_addr.s6_addr32[3], 558 sizeof(sa6->sin6_addr.s6_addr32[3])); 559 if (in6_setscope(&sa6->sin6_addr, ifp, NULL)) 560 return (-1); /* XXX: should not fail */ 561 562 return 0; 563 } 564 565 /* 566 * XXX multiple loopback interface needs more care. for instance, 567 * nodelocal address needs to be configured onto only one of them. 568 * XXX multiple link-local address case 569 */ 570 void 571 in6_ifattach(ifp, altifp) 572 struct ifnet *ifp; 573 struct ifnet *altifp; /* secondary EUI64 source */ 574 { 575 struct in6_ifaddr *ia; 576 struct in6_addr in6; 577 578 /* some of the interfaces are inherently not IPv6 capable */ 579 switch (ifp->if_type) { 580 case IFT_BRIDGE: 581 #ifdef IFT_PFLOG 582 case IFT_PFLOG: 583 #endif 584 #ifdef IFT_PFSYNC 585 case IFT_PFSYNC: 586 #endif 587 return; 588 } 589 590 /* 591 * if link mtu is too small, don't try to configure IPv6. 592 * remember there could be some link-layer that has special 593 * fragmentation logic. 594 */ 595 if (ifp->if_mtu < IPV6_MMTU) { 596 nd6log((LOG_INFO, "in6_ifattach: " 597 "%s has too small MTU, IPv6 not enabled\n", 598 if_name(ifp))); 599 return; 600 } 601 602 /* create a multicast kludge storage (if we have not had one) */ 603 in6_createmkludge(ifp); 604 605 /* 606 * quirks based on interface type 607 */ 608 switch (ifp->if_type) { 609 #ifdef IFT_STF 610 case IFT_STF: 611 /* 612 * 6to4 interface is a very special kind of beast. 613 * no multicast, no linklocal. RFC2529 specifies how to make 614 * linklocals for 6to4 interface, but there's no use and 615 * it is rather harmful to have one. 616 */ 617 return; 618 #endif 619 default: 620 break; 621 } 622 623 /* 624 * usually, we require multicast capability to the interface 625 */ 626 if ((ifp->if_flags & IFF_MULTICAST) == 0) { 627 nd6log((LOG_INFO, "in6_ifattach: " 628 "%s is not multicast capable, IPv6 not enabled\n", 629 if_name(ifp))); 630 return; 631 } 632 633 /* 634 * assign loopback address for loopback interface. 635 * XXX multiple loopback interface case. 636 */ 637 if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 638 in6 = in6addr_loopback; 639 if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) { 640 if (in6_ifattach_loopback(ifp) != 0) 641 return; 642 } 643 } 644 645 /* 646 * assign a link-local address, if there's none. 647 */ 648 if (ip6_auto_linklocal) { 649 ia = in6ifa_ifpforlinklocal(ifp, 0); 650 if (ia == NULL) { 651 if (in6_ifattach_linklocal(ifp, altifp) == 0) { 652 /* linklocal address assigned */ 653 } else { 654 /* failed to assign linklocal address. bark? */ 655 } 656 } 657 } 658 } 659 660 /* 661 * NOTE: in6_ifdetach() does not support loopback if at this moment. 662 * We don't need this function in bsdi, because interfaces are never removed 663 * from the ifnet list in bsdi. 664 */ 665 void 666 in6_ifdetach(ifp) 667 struct ifnet *ifp; 668 { 669 struct in6_ifaddr *ia, *oia; 670 struct ifaddr *ifa, *next; 671 struct rtentry *rt; 672 short rtflags; 673 struct in6_multi_mship *imm; 674 675 /* remove ip6_mrouter stuff */ 676 ip6_mrouter_detach(ifp); 677 678 /* remove neighbor management table */ 679 nd6_purge(ifp); 680 681 /* nuke any of IPv6 addresses we have */ 682 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) 683 { 684 next = ifa->ifa_list.tqe_next; 685 if (ifa->ifa_addr->sa_family != AF_INET6) 686 continue; 687 in6_purgeaddr(ifa); 688 } 689 690 /* undo everything done by in6_ifattach(), just in case */ 691 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) 692 { 693 next = ifa->ifa_list.tqe_next; 694 695 if (ifa->ifa_addr->sa_family != AF_INET6 696 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) { 697 continue; 698 } 699 700 ia = (struct in6_ifaddr *)ifa; 701 702 /* 703 * leave from multicast groups we have joined for the interface 704 */ 705 while ((imm = ia->ia6_memberships.lh_first) != NULL) { 706 LIST_REMOVE(imm, i6mm_chain); 707 in6_leavegroup(imm); 708 } 709 710 /* remove from the routing table */ 711 if ((ia->ia_flags & IFA_ROUTE) && 712 (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) { 713 rtflags = rt->rt_flags; 714 rtfree(rt); 715 rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr, 716 (struct sockaddr *)&ia->ia_addr, 717 (struct sockaddr *)&ia->ia_prefixmask, 718 rtflags, (struct rtentry **)0); 719 } 720 721 /* remove from the linked list */ 722 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 723 IFAFREE(&ia->ia_ifa); 724 725 /* also remove from the IPv6 address chain(itojun&jinmei) */ 726 oia = ia; 727 if (oia == (ia = in6_ifaddr)) 728 in6_ifaddr = ia->ia_next; 729 else { 730 while (ia->ia_next && (ia->ia_next != oia)) 731 ia = ia->ia_next; 732 if (ia->ia_next) 733 ia->ia_next = oia->ia_next; 734 else { 735 nd6log((LOG_ERR, 736 "%s: didn't unlink in6ifaddr from list\n", 737 if_name(ifp))); 738 } 739 } 740 741 IFAFREE(&oia->ia_ifa); 742 } 743 744 /* cleanup multicast address kludge table, if there is any */ 745 in6_purgemkludge(ifp); 746 747 /* 748 * remove neighbor management table. we call it twice just to make 749 * sure we nuke everything. maybe we need just one call. 750 * XXX: since the first call did not release addresses, some prefixes 751 * might remain. We should call nd6_purge() again to release the 752 * prefixes after removing all addresses above. 753 * (Or can we just delay calling nd6_purge until at this point?) 754 */ 755 nd6_purge(ifp); 756 } 757