1 /* $NetBSD: in6_ifattach.c,v 1.41 2001/12/21 08:54:54 itojun 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.41 2001/12/21 08:54:54 itojun 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/ip6_var.h> 55 #include <netinet6/in6_ifattach.h> 56 #include <netinet6/ip6_var.h> 57 #include <netinet6/nd6.h> 58 59 #include <net/net_osdep.h> 60 61 struct in6_ifstat **in6_ifstat = NULL; 62 struct icmp6_ifstat **icmp6_ifstat = NULL; 63 size_t in6_ifstatmax = 0; 64 size_t icmp6_ifstatmax = 0; 65 unsigned long in6_maxmtu = 0; 66 67 static int get_rand_ifid __P((struct ifnet *, struct in6_addr *)); 68 static int get_hw_ifid __P((struct ifnet *, struct in6_addr *)); 69 static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *)); 70 static int in6_ifattach_addaddr __P((struct ifnet *, struct in6_ifaddr *)); 71 static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *)); 72 static int in6_ifattach_loopback __P((struct ifnet *)); 73 74 #define EUI64_GBIT 0x01 75 #define EUI64_UBIT 0x02 76 #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0) 77 #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) 78 #define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6)) 79 #define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT) 80 #define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6)) 81 82 #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) 83 #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) 84 85 /* 86 * Generate a last-resort interface identifier, when the machine has no 87 * IEEE802/EUI64 address sources. 88 * The goal here is to get an interface identifier that is 89 * (1) random enough and (2) does not change across reboot. 90 * We currently use MD5(hostname) for it. 91 */ 92 static int 93 get_rand_ifid(ifp, in6) 94 struct ifnet *ifp; 95 struct in6_addr *in6; /* upper 64bits are preserved */ 96 { 97 MD5_CTX ctxt; 98 u_int8_t digest[16]; 99 100 #if 0 101 /* we need at least several letters as seed for ifid */ 102 if (hostnamelen < 3) 103 return -1; 104 #endif 105 106 /* generate 8 bytes of pseudo-random value. */ 107 bzero(&ctxt, sizeof(ctxt)); 108 MD5Init(&ctxt); 109 MD5Update(&ctxt, hostname, hostnamelen); 110 MD5Final(digest, &ctxt); 111 112 /* assumes sizeof(digest) > sizeof(ifid) */ 113 bcopy(digest, &in6->s6_addr[8], 8); 114 115 /* make sure to set "u" bit to local, and "g" bit to individual. */ 116 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 117 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 118 119 /* convert EUI64 into IPv6 interface identifier */ 120 EUI64_TO_IFID(in6); 121 122 return 0; 123 } 124 125 /* 126 * Get interface identifier for the specified interface. 127 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface 128 */ 129 static int 130 get_hw_ifid(ifp, in6) 131 struct ifnet *ifp; 132 struct in6_addr *in6; /* upper 64bits are preserved */ 133 { 134 struct ifaddr *ifa; 135 struct sockaddr_dl *sdl; 136 u_int8_t *addr; 137 size_t addrlen; 138 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 139 static u_int8_t allone[8] = 140 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 141 142 for (ifa = ifp->if_addrlist.tqh_first; 143 ifa; 144 ifa = ifa->ifa_list.tqe_next) 145 { 146 if (ifa->ifa_addr->sa_family != AF_LINK) 147 continue; 148 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 149 if (sdl == NULL) 150 continue; 151 if (sdl->sdl_alen == 0) 152 continue; 153 154 goto found; 155 } 156 157 return -1; 158 159 found: 160 addr = LLADDR(sdl); 161 addrlen = sdl->sdl_alen; 162 163 /* get EUI64 */ 164 switch (ifp->if_type) { 165 case IFT_ETHER: 166 case IFT_FDDI: 167 case IFT_ATM: 168 case IFT_IEEE1394: 169 /* IEEE802/EUI64 cases - what others? */ 170 /* IEEE1394 uses 16byte length address starting with EUI64 */ 171 if (addrlen > 8) 172 addrlen = 8; 173 174 /* look at IEEE802/EUI64 only */ 175 if (addrlen != 8 && addrlen != 6) 176 return -1; 177 178 /* 179 * check for invalid MAC address - on bsdi, we see it a lot 180 * since wildboar configures all-zero MAC on pccard before 181 * card insertion. 182 */ 183 if (bcmp(addr, allzero, addrlen) == 0) 184 return -1; 185 if (bcmp(addr, allone, addrlen) == 0) 186 return -1; 187 188 /* make EUI64 address */ 189 if (addrlen == 8) 190 bcopy(addr, &in6->s6_addr[8], 8); 191 else if (addrlen == 6) { 192 in6->s6_addr[8] = addr[0]; 193 in6->s6_addr[9] = addr[1]; 194 in6->s6_addr[10] = addr[2]; 195 in6->s6_addr[11] = 0xff; 196 in6->s6_addr[12] = 0xfe; 197 in6->s6_addr[13] = addr[3]; 198 in6->s6_addr[14] = addr[4]; 199 in6->s6_addr[15] = addr[5]; 200 } 201 break; 202 203 case IFT_ARCNET: 204 if (addrlen != 1) 205 return -1; 206 if (!addr[0]) 207 return -1; 208 209 bzero(&in6->s6_addr[8], 8); 210 in6->s6_addr[15] = addr[0]; 211 212 /* 213 * due to insufficient bitwidth, we mark it local. 214 */ 215 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 216 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 217 break; 218 219 case IFT_GIF: 220 #ifdef IFT_STF 221 case IFT_STF: 222 #endif 223 /* 224 * RFC2893 says: "SHOULD use IPv4 address as ifid source". 225 * however, IPv4 address is not very suitable as unique 226 * identifier source (can be renumbered). 227 * we don't do this. 228 */ 229 return -1; 230 231 default: 232 return -1; 233 } 234 235 /* sanity check: g bit must not indicate "group" */ 236 if (EUI64_GROUP(in6)) 237 return -1; 238 239 /* convert EUI64 into IPv6 interface identifier */ 240 EUI64_TO_IFID(in6); 241 242 /* 243 * sanity check: ifid must not be all zero, avoid conflict with 244 * subnet router anycast 245 */ 246 if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && 247 bcmp(&in6->s6_addr[9], allzero, 7) == 0) { 248 return -1; 249 } 250 251 return 0; 252 } 253 254 /* 255 * Get interface identifier for the specified interface. If it is not 256 * available on ifp0, borrow interface identifier from other information 257 * sources. 258 */ 259 static int 260 get_ifid(ifp0, altifp, in6) 261 struct ifnet *ifp0; 262 struct ifnet *altifp; /*secondary EUI64 source*/ 263 struct in6_addr *in6; 264 { 265 struct ifnet *ifp; 266 267 /* first, try to get it from the interface itself */ 268 if (get_hw_ifid(ifp0, in6) == 0) { 269 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", 270 if_name(ifp0))); 271 goto success; 272 } 273 274 /* try secondary EUI64 source. this basically is for ATM PVC */ 275 if (altifp && get_hw_ifid(altifp, in6) == 0) { 276 nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", 277 if_name(ifp0), if_name(altifp))); 278 goto success; 279 } 280 281 /* next, try to get it from some other hardware interface */ 282 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 283 { 284 if (ifp == ifp0) 285 continue; 286 if (get_hw_ifid(ifp, in6) != 0) 287 continue; 288 289 /* 290 * to borrow ifid from other interface, ifid needs to be 291 * globally unique 292 */ 293 if (IFID_UNIVERSAL(in6)) { 294 nd6log((LOG_DEBUG, 295 "%s: borrow interface identifier from %s\n", 296 if_name(ifp0), if_name(ifp))); 297 goto success; 298 } 299 } 300 301 /* last resort: get from random number source */ 302 if (get_rand_ifid(ifp, in6) == 0) { 303 nd6log((LOG_DEBUG, 304 "%s: interface identifier generated by random number\n", 305 if_name(ifp0))); 306 goto success; 307 } 308 309 printf("%s: failed to get interface identifier\n", if_name(ifp0)); 310 return -1; 311 312 success: 313 nd6log((LOG_INFO, "%s: ifid: " 314 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 315 if_name(ifp0), 316 in6->s6_addr[8], in6->s6_addr[9], 317 in6->s6_addr[10], in6->s6_addr[11], 318 in6->s6_addr[12], in6->s6_addr[13], 319 in6->s6_addr[14], in6->s6_addr[15])); 320 return 0; 321 } 322 323 /* 324 * configure IPv6 interface address. XXX code duplicated with in.c 325 */ 326 static int 327 in6_ifattach_addaddr(ifp, ia) 328 struct ifnet *ifp; 329 struct in6_ifaddr *ia; 330 { 331 struct in6_ifaddr *oia; 332 struct ifaddr *ifa; 333 int error; 334 int rtflag; 335 struct in6_addr llsol; 336 337 /* 338 * initialize if_addrlist, if we are the very first one 339 */ 340 ifa = TAILQ_FIRST(&ifp->if_addrlist); 341 if (ifa == NULL) { 342 TAILQ_INIT(&ifp->if_addrlist); 343 } 344 345 /* 346 * link the interface address to global list 347 */ 348 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 349 IFAREF(&ia->ia_ifa); 350 351 /* 352 * Also link into the IPv6 address chain beginning with in6_ifaddr. 353 * kazu opposed it, but itojun & jinmei wanted. 354 */ 355 if ((oia = in6_ifaddr) != NULL) { 356 for (; oia->ia_next; oia = oia->ia_next) 357 continue; 358 oia->ia_next = ia; 359 } else 360 in6_ifaddr = ia; 361 IFAREF(&ia->ia_ifa); 362 363 /* 364 * give the interface a chance to initialize, in case this 365 * is the first address to be added. 366 */ 367 if (ifp->if_ioctl != NULL) { 368 int s; 369 s = splnet(); 370 error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); 371 splx(s); 372 } else 373 error = 0; 374 if (error) { 375 switch (error) { 376 case EAFNOSUPPORT: 377 printf("%s: IPv6 not supported\n", if_name(ifp)); 378 break; 379 default: 380 printf("%s: SIOCSIFADDR error %d\n", if_name(ifp), 381 error); 382 break; 383 } 384 385 /* undo changes */ 386 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 387 IFAFREE(&ia->ia_ifa); 388 if (oia) 389 oia->ia_next = ia->ia_next; 390 else 391 in6_ifaddr = ia->ia_next; 392 IFAFREE(&ia->ia_ifa); 393 return -1; 394 } 395 396 /* configure link-layer address resolution */ 397 rtflag = 0; 398 if (IN6_ARE_ADDR_EQUAL(&ia->ia_prefixmask.sin6_addr, &in6mask128)) 399 rtflag = RTF_HOST; 400 else { 401 switch (ifp->if_type) { 402 case IFT_LOOP: 403 #ifdef IFT_STF 404 case IFT_STF: 405 #endif 406 rtflag = 0; 407 break; 408 default: 409 ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; 410 ia->ia_ifa.ifa_flags |= RTF_CLONING; 411 rtflag = RTF_CLONING; 412 break; 413 } 414 } 415 416 /* add route to the interface. */ 417 rtrequest(RTM_ADD, 418 (struct sockaddr *)&ia->ia_addr, 419 (struct sockaddr *)&ia->ia_addr, 420 (struct sockaddr *)&ia->ia_prefixmask, 421 RTF_UP | rtflag, 422 (struct rtentry **)0); 423 ia->ia_flags |= IFA_ROUTE; 424 425 if ((rtflag & RTF_CLONING) != 0 && 426 (ifp->if_flags & IFF_MULTICAST) != 0) { 427 /* Restore saved multicast addresses (if any). */ 428 in6_restoremkludge(ia, ifp); 429 430 /* 431 * join solicited multicast address 432 */ 433 bzero(&llsol, sizeof(llsol)); 434 llsol.s6_addr16[0] = htons(0xff02); 435 llsol.s6_addr16[1] = htons(ifp->if_index); 436 llsol.s6_addr32[1] = 0; 437 llsol.s6_addr32[2] = htonl(1); 438 llsol.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3]; 439 llsol.s6_addr8[12] = 0xff; 440 if (!in6_addmulti(&llsol, ifp, &error)) { 441 nd6log((LOG_ERR, "%s: failed to join %s (errno=%d)\n", 442 if_name(ifp), ip6_sprintf(&llsol), error)); 443 } 444 445 /* XXX should we run DAD on other interface types? */ 446 switch (ifp->if_type) { 447 #if 1 448 case IFT_ARCNET: 449 case IFT_ETHER: 450 case IFT_FDDI: 451 case IFT_IEEE1394: 452 #else 453 default: 454 #endif 455 /* mark the address TENTATIVE, if needed. */ 456 ia->ia6_flags |= IN6_IFF_TENTATIVE; 457 /* nd6_dad_start() will be called in in6_if_up */ 458 } 459 } 460 461 return 0; 462 } 463 464 static int 465 in6_ifattach_linklocal(ifp, altifp) 466 struct ifnet *ifp; 467 struct ifnet *altifp; /*secondary EUI64 source*/ 468 { 469 struct in6_ifaddr *ia; 470 471 /* 472 * configure link-local address 473 */ 474 ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK); 475 bzero((caddr_t)ia, sizeof(*ia)); 476 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 477 if (ifp->if_flags & IFF_POINTOPOINT) 478 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; 479 else 480 ia->ia_ifa.ifa_dstaddr = NULL; 481 ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; 482 ia->ia_ifp = ifp; 483 484 bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); 485 ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 486 ia->ia_prefixmask.sin6_family = AF_INET6; 487 ia->ia_prefixmask.sin6_addr = in6mask64; 488 489 /* just in case */ 490 bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr)); 491 ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 492 ia->ia_dstaddr.sin6_family = AF_INET6; 493 494 bzero(&ia->ia_addr, sizeof(ia->ia_addr)); 495 ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6); 496 ia->ia_addr.sin6_family = AF_INET6; 497 ia->ia_addr.sin6_addr.s6_addr16[0] = htons(0xfe80); 498 ia->ia_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 499 ia->ia_addr.sin6_addr.s6_addr32[1] = 0; 500 if (ifp->if_flags & IFF_LOOPBACK) { 501 ia->ia_addr.sin6_addr.s6_addr32[2] = 0; 502 ia->ia_addr.sin6_addr.s6_addr32[3] = htonl(1); 503 } else { 504 if (get_ifid(ifp, altifp, &ia->ia_addr.sin6_addr) != 0) { 505 nd6log((LOG_ERR, 506 "%s: no ifid available\n", if_name(ifp))); 507 free(ia, M_IFADDR); 508 return -1; 509 } 510 } 511 512 ia->ia_ifa.ifa_metric = ifp->if_metric; 513 514 if (in6_ifattach_addaddr(ifp, ia) != 0) { 515 /* ia will be freed on failure */ 516 return -1; 517 } 518 519 return 0; 520 } 521 522 static int 523 in6_ifattach_loopback(ifp) 524 struct ifnet *ifp; /* must be IFT_LOOP */ 525 { 526 struct in6_ifaddr *ia; 527 528 /* 529 * configure link-local address 530 */ 531 ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK); 532 bzero((caddr_t)ia, sizeof(*ia)); 533 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 534 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; 535 ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; 536 ia->ia_ifp = ifp; 537 538 bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); 539 ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 540 ia->ia_prefixmask.sin6_family = AF_INET6; 541 ia->ia_prefixmask.sin6_addr = in6mask128; 542 543 /* 544 * Always initialize ia_dstaddr (= broadcast address) to loopback 545 * address, to make getifaddr happier. 546 * 547 * For BSDI, it is mandatory. The BSDI version of 548 * ifa_ifwithroute() rejects to add a route to the loopback 549 * interface. Even for other systems, loopback looks somewhat 550 * special. 551 */ 552 bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr)); 553 ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 554 ia->ia_dstaddr.sin6_family = AF_INET6; 555 ia->ia_dstaddr.sin6_addr = in6addr_loopback; 556 557 bzero(&ia->ia_addr, sizeof(ia->ia_addr)); 558 ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6); 559 ia->ia_addr.sin6_family = AF_INET6; 560 ia->ia_addr.sin6_addr = in6addr_loopback; 561 562 ia->ia_ifa.ifa_metric = ifp->if_metric; 563 564 if (in6_ifattach_addaddr(ifp, ia) != 0) { 565 /* ia will be freed on failure */ 566 return -1; 567 } 568 569 return 0; 570 } 571 572 /* 573 * XXX multiple loopback interface needs more care. for instance, 574 * nodelocal address needs to be configured onto only one of them. 575 * XXX multiple link-local address case 576 */ 577 void 578 in6_ifattach(ifp, altifp) 579 struct ifnet *ifp; 580 struct ifnet *altifp; /* secondary EUI64 source */ 581 { 582 static size_t if_indexlim = 8; 583 struct sockaddr_in6 mltaddr; 584 struct sockaddr_in6 mltmask; 585 struct sockaddr_in6 gate; 586 struct sockaddr_in6 mask; 587 struct in6_ifaddr *ia; 588 struct in6_addr in6; 589 590 /* some of the interfaces are inherently not IPv6 capable */ 591 switch (ifp->if_type) { 592 case IFT_PROPVIRTUAL: 593 if (strncmp("bridge", ifp->if_xname, sizeof("bridge")) == 0 && 594 '0' <= ifp->if_xname[sizeof("bridge")] && 595 ifp->if_xname[sizeof("bridge")] <= '9') 596 return; 597 break; 598 } 599 600 /* 601 * We have some arrays that should be indexed by if_index. 602 * since if_index will grow dynamically, they should grow too. 603 * struct in6_ifstat **in6_ifstat 604 * struct icmp6_ifstat **icmp6_ifstat 605 */ 606 if (in6_ifstat == NULL || icmp6_ifstat == NULL || 607 if_index >= if_indexlim) { 608 size_t n; 609 caddr_t q; 610 size_t olim; 611 612 olim = if_indexlim; 613 while (if_index >= if_indexlim) 614 if_indexlim <<= 1; 615 616 /* grow in6_ifstat */ 617 n = if_indexlim * sizeof(struct in6_ifstat *); 618 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); 619 bzero(q, n); 620 if (in6_ifstat) { 621 bcopy((caddr_t)in6_ifstat, q, 622 olim * sizeof(struct in6_ifstat *)); 623 free((caddr_t)in6_ifstat, M_IFADDR); 624 } 625 in6_ifstat = (struct in6_ifstat **)q; 626 in6_ifstatmax = if_indexlim; 627 628 /* grow icmp6_ifstat */ 629 n = if_indexlim * sizeof(struct icmp6_ifstat *); 630 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); 631 bzero(q, n); 632 if (icmp6_ifstat) { 633 bcopy((caddr_t)icmp6_ifstat, q, 634 olim * sizeof(struct icmp6_ifstat *)); 635 free((caddr_t)icmp6_ifstat, M_IFADDR); 636 } 637 icmp6_ifstat = (struct icmp6_ifstat **)q; 638 icmp6_ifstatmax = if_indexlim; 639 } 640 641 /* create a multicast kludge storage (if we have not had one) */ 642 in6_createmkludge(ifp); 643 644 /* 645 * quirks based on interface type 646 */ 647 switch (ifp->if_type) { 648 #ifdef IFT_STF 649 case IFT_STF: 650 /* 651 * 6to4 interface is a very special kind of beast. 652 * no multicast, no linklocal. RFC2529 specifies how to make 653 * linklocals for 6to4 interface, but there's no use and 654 * it is rather harmful to have one. 655 */ 656 goto statinit; 657 #endif 658 default: 659 break; 660 } 661 662 /* 663 * usually, we require multicast capability to the interface 664 */ 665 if ((ifp->if_flags & IFF_MULTICAST) == 0) { 666 log(LOG_INFO, "in6_ifattach: " 667 "%s is not multicast capable, IPv6 not enabled\n", 668 if_name(ifp)); 669 return; 670 } 671 672 /* 673 * assign link-local address, if there's none 674 */ 675 ia = in6ifa_ifpforlinklocal(ifp, 0); 676 if (ia == NULL) { 677 if (in6_ifattach_linklocal(ifp, altifp) != 0) 678 return; 679 ia = in6ifa_ifpforlinklocal(ifp, 0); 680 681 if (ia == NULL) { 682 printf("%s: failed to add link-local address\n", 683 if_name(ifp)); 684 685 /* we can't initialize multicasts without link-local */ 686 goto statinit; 687 } 688 } 689 690 if (ifp->if_flags & IFF_POINTOPOINT) { 691 /* 692 * route local address to loopback 693 */ 694 bzero(&gate, sizeof(gate)); 695 gate.sin6_len = sizeof(struct sockaddr_in6); 696 gate.sin6_family = AF_INET6; 697 gate.sin6_addr = in6addr_loopback; 698 bzero(&mask, sizeof(mask)); 699 mask.sin6_len = sizeof(struct sockaddr_in6); 700 mask.sin6_family = AF_INET6; 701 mask.sin6_addr = in6mask64; 702 rtrequest(RTM_ADD, 703 (struct sockaddr *)&ia->ia_addr, 704 (struct sockaddr *)&gate, 705 (struct sockaddr *)&mask, 706 RTF_UP|RTF_HOST, 707 (struct rtentry **)0); 708 } 709 710 /* 711 * assign loopback address for loopback interface 712 * XXX multiple loopback interface case 713 */ 714 in6 = in6addr_loopback; 715 if (ifp->if_flags & IFF_LOOPBACK) { 716 if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) { 717 if (in6_ifattach_loopback(ifp) != 0) 718 return; 719 } 720 } 721 722 #ifdef DIAGNOSTIC 723 if (!ia) { 724 panic("ia == NULL in in6_ifattach"); 725 /*NOTREACHED*/ 726 } 727 #endif 728 729 /* 730 * join multicast 731 */ 732 if (ifp->if_flags & IFF_MULTICAST) { 733 int error; /* not used */ 734 struct in6_multi *in6m; 735 736 /* Restore saved multicast addresses (if any). */ 737 in6_restoremkludge(ia, ifp); 738 739 bzero(&mltmask, sizeof(mltmask)); 740 mltmask.sin6_len = sizeof(struct sockaddr_in6); 741 mltmask.sin6_family = AF_INET6; 742 mltmask.sin6_addr = in6mask32; 743 744 /* 745 * join link-local all-nodes address 746 */ 747 bzero(&mltaddr, sizeof(mltaddr)); 748 mltaddr.sin6_len = sizeof(struct sockaddr_in6); 749 mltaddr.sin6_family = AF_INET6; 750 mltaddr.sin6_addr = in6addr_linklocal_allnodes; 751 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 752 753 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m); 754 if (in6m == NULL) { 755 rtrequest(RTM_ADD, 756 (struct sockaddr *)&mltaddr, 757 (struct sockaddr *)&ia->ia_addr, 758 (struct sockaddr *)&mltmask, 759 RTF_UP|RTF_CLONING, /* xxx */ 760 (struct rtentry **)0); 761 if (!in6_addmulti(&mltaddr.sin6_addr, ifp, &error)) { 762 nd6log((LOG_ERR, "%s: failed to join %s " 763 "(errno=%d)\n", if_name(ifp), 764 ip6_sprintf(&mltaddr.sin6_addr), 765 error)); 766 } 767 } 768 769 if (ifp->if_flags & IFF_LOOPBACK) { 770 in6 = in6addr_loopback; 771 ia = in6ifa_ifpwithaddr(ifp, &in6); 772 /* 773 * join node-local all-nodes address, on loopback 774 */ 775 mltaddr.sin6_addr = in6addr_nodelocal_allnodes; 776 777 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m); 778 if (in6m == NULL && ia != NULL) { 779 rtrequest(RTM_ADD, 780 (struct sockaddr *)&mltaddr, 781 (struct sockaddr *)&ia->ia_addr, 782 (struct sockaddr *)&mltmask, 783 RTF_UP, 784 (struct rtentry **)0); 785 if (!in6_addmulti(&mltaddr.sin6_addr, ifp, 786 &error)) { 787 nd6log((LOG_ERR, "%s: failed to join " 788 "%s (errno=%d)\n", if_name(ifp), 789 ip6_sprintf(&mltaddr.sin6_addr), 790 error)); 791 } 792 } 793 } 794 } 795 796 statinit:; 797 798 /* update dynamically. */ 799 if (in6_maxmtu < ifp->if_mtu) 800 in6_maxmtu = ifp->if_mtu; 801 802 if (in6_ifstat[ifp->if_index] == NULL) { 803 in6_ifstat[ifp->if_index] = (struct in6_ifstat *) 804 malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK); 805 bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat)); 806 } 807 if (icmp6_ifstat[ifp->if_index] == NULL) { 808 icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *) 809 malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK); 810 bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat)); 811 } 812 813 /* initialize NDP variables */ 814 nd6_ifattach(ifp); 815 } 816 817 /* 818 * NOTE: in6_ifdetach() does not support loopback if at this moment. 819 * We don't need this function in bsdi, because interfaces are never removed 820 * from the ifnet list in bsdi. 821 */ 822 void 823 in6_ifdetach(ifp) 824 struct ifnet *ifp; 825 { 826 struct in6_ifaddr *ia, *oia; 827 struct ifaddr *ifa, *next; 828 struct rtentry *rt; 829 short rtflags; 830 struct sockaddr_in6 sin6; 831 832 /* nuke prefix list. this may try to remove some of ifaddrs as well */ 833 in6_purgeprefix(ifp); 834 835 /* remove neighbor management table */ 836 nd6_purge(ifp); 837 838 /* nuke any of IPv6 addresses we have */ 839 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) 840 { 841 next = ifa->ifa_list.tqe_next; 842 if (ifa->ifa_addr->sa_family != AF_INET6) 843 continue; 844 in6_purgeaddr(ifa, ifp); 845 } 846 847 /* undo everything done by in6_ifattach(), just in case */ 848 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) 849 { 850 next = ifa->ifa_list.tqe_next; 851 852 853 if (ifa->ifa_addr->sa_family != AF_INET6 854 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) { 855 continue; 856 } 857 858 ia = (struct in6_ifaddr *)ifa; 859 860 /* remove from the routing table */ 861 if ((ia->ia_flags & IFA_ROUTE) 862 && (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) { 863 rtflags = rt->rt_flags; 864 rtfree(rt); 865 rtrequest(RTM_DELETE, 866 (struct sockaddr *)&ia->ia_addr, 867 (struct sockaddr *)&ia->ia_addr, 868 (struct sockaddr *)&ia->ia_prefixmask, 869 rtflags, (struct rtentry **)0); 870 } 871 872 /* remove from the linked list */ 873 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 874 IFAFREE(&ia->ia_ifa); 875 876 /* also remove from the IPv6 address chain(itojun&jinmei) */ 877 oia = ia; 878 if (oia == (ia = in6_ifaddr)) 879 in6_ifaddr = ia->ia_next; 880 else { 881 while (ia->ia_next && (ia->ia_next != oia)) 882 ia = ia->ia_next; 883 if (ia->ia_next) 884 ia->ia_next = oia->ia_next; 885 else { 886 nd6log((LOG_ERR, 887 "%s: didn't unlink in6ifaddr from " 888 "list\n", if_name(ifp))); 889 } 890 } 891 892 IFAFREE(&oia->ia_ifa); 893 } 894 895 /* cleanup multicast address kludge table, if there is any */ 896 in6_purgemkludge(ifp); 897 898 /* 899 * remove neighbor management table. we call it twice just to make 900 * sure we nuke everything. maybe we need just one call. 901 * XXX: since the first call did not release addresses, some prefixes 902 * might remain. We should call nd6_purge() again to release the 903 * prefixes after removing all addresses above. 904 * (Or can we just delay calling nd6_purge until at this point?) 905 */ 906 nd6_purge(ifp); 907 908 /* remove route to link-local allnodes multicast (ff02::1) */ 909 bzero(&sin6, sizeof(sin6)); 910 sin6.sin6_len = sizeof(struct sockaddr_in6); 911 sin6.sin6_family = AF_INET6; 912 sin6.sin6_addr = in6addr_linklocal_allnodes; 913 sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 914 rt = rtalloc1((struct sockaddr *)&sin6, 0); 915 if (rt && rt->rt_ifp == ifp) { 916 rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), 917 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); 918 rtfree(rt); 919 } 920 } 921