1 /* $NetBSD: in6_ifattach.c,v 1.66 2006/10/12 01:32:39 christos 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.66 2006/10/12 01:32:39 christos 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 struct callout in6_tmpaddrtimer_ch = CALLOUT_INITIALIZER; 67 68 69 #if 0 70 static int get_hostid_ifid __P((struct ifnet *, struct in6_addr *)); 71 #endif 72 static int get_rand_ifid __P((struct ifnet *, struct in6_addr *)); 73 static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *)); 74 static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *)); 75 static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *)); 76 static int in6_ifattach_loopback __P((struct ifnet *)); 77 78 #define EUI64_GBIT 0x01 79 #define EUI64_UBIT 0x02 80 #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (/*CONSTCOND*/ 0) 81 #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) 82 #define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6)) 83 #define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT) 84 #define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6)) 85 86 #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) 87 #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) 88 89 #define GEN_TEMPID_RETRY_MAX 5 90 91 #if 0 92 /* 93 * Generate a last-resort interface identifier from hostid. 94 * works only for certain architectures (like sparc). 95 * also, using hostid itself may constitute a privacy threat, much worse 96 * than MAC addresses (hostids are used for software licensing). 97 * maybe we should use MD5(hostid) instead. 98 */ 99 static int 100 get_hostid_ifid(ifp, in6) 101 struct ifnet *ifp; 102 struct in6_addr *in6; /* upper 64bits are preserved */ 103 { 104 int off, len; 105 static const uint8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 106 static const uint8_t allone[8] = 107 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 108 109 if (!hostid) 110 return -1; 111 112 /* get up to 8 bytes from the hostid field - should we get */ 113 len = (sizeof(hostid) > 8) ? 8 : sizeof(hostid); 114 off = sizeof(*in6) - len; 115 memcpy(&in6->s6_addr[off], &hostid, len); 116 117 /* make sure we do not return anything bogus */ 118 if (memcmp(&in6->s6_addr[8], allzero, sizeof(allzero))) 119 return -1; 120 if (memcmp(&in6->s6_addr[8], allone, sizeof(allone))) 121 return -1; 122 123 /* make sure to set "u" bit to local, and "g" bit to individual. */ 124 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 125 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 126 127 /* convert EUI64 into IPv6 interface identifier */ 128 EUI64_TO_IFID(in6); 129 130 return 0; 131 } 132 #endif 133 134 /* 135 * Generate a last-resort interface identifier, when the machine has no 136 * IEEE802/EUI64 address sources. 137 * The goal here is to get an interface identifier that is 138 * (1) random enough and (2) does not change across reboot. 139 * We currently use MD5(hostname) for it. 140 */ 141 static int 142 get_rand_ifid(struct ifnet *ifp __unused, 143 struct in6_addr *in6) /* upper 64bits are preserved */ 144 { 145 MD5_CTX ctxt; 146 u_int8_t digest[16]; 147 148 #if 0 149 /* we need at least several letters as seed for ifid */ 150 if (hostnamelen < 3) 151 return -1; 152 #endif 153 154 /* generate 8 bytes of pseudo-random value. */ 155 memset(&ctxt, 0, sizeof(ctxt)); 156 MD5Init(&ctxt); 157 MD5Update(&ctxt, (u_char *)hostname, hostnamelen); 158 MD5Final(digest, &ctxt); 159 160 /* assumes sizeof(digest) > sizeof(ifid) */ 161 memcpy(&in6->s6_addr[8], digest, 8); 162 163 /* make sure to set "u" bit to local, and "g" bit to individual. */ 164 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 165 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 166 167 /* convert EUI64 into IPv6 interface identifier */ 168 EUI64_TO_IFID(in6); 169 170 return 0; 171 } 172 173 static int 174 generate_tmp_ifid(seed0, seed1, ret) 175 u_int8_t *seed0, *ret; 176 const u_int8_t *seed1; 177 { 178 MD5_CTX ctxt; 179 u_int8_t seed[16], digest[16], nullbuf[8]; 180 u_int32_t val32; 181 /* 182 * interface ID for subnet anycast addresses. 183 * XXX: we assume the unicast address range that requires IDs 184 * in EUI-64 format. 185 */ 186 static const uint8_t anycast_id[8] = { 0xfd, 0xff, 0xff, 0xff, 187 0xff, 0xff, 0xff, 0x80 }; 188 static const uint8_t isatap_id[4] = { 0x00, 0x00, 0x5e, 0xfe }; 189 int badid, retry = 0; 190 191 /* If there's no hisotry, start with a random seed. */ 192 memset(nullbuf, 0, sizeof(nullbuf)); 193 if (memcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) { 194 int i; 195 196 for (i = 0; i < 2; i++) { 197 val32 = arc4random(); 198 memcpy(seed + sizeof(val32) * i, &val32, sizeof(val32)); 199 } 200 } else 201 memcpy(seed, seed0, 8); 202 203 /* copy the right-most 64-bits of the given address */ 204 /* XXX assumption on the size of IFID */ 205 memcpy(&seed[8], seed1, 8); 206 207 again: 208 /* for debugging purposes only */ 209 #if 0 210 { 211 int i; 212 213 printf("generate_tmp_ifid: new randomized ID from: "); 214 for (i = 0; i < 16; i++) 215 printf("%02x", seed[i]); 216 printf(" "); 217 } 218 #endif 219 220 /* generate 16 bytes of pseudo-random value. */ 221 memset(&ctxt, 0, sizeof(ctxt)); 222 MD5Init(&ctxt); 223 MD5Update(&ctxt, seed, sizeof(seed)); 224 MD5Final(digest, &ctxt); 225 226 /* 227 * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (3) 228 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the 229 * left-most bit is numbered 0) to zero. 230 */ 231 memcpy(ret, digest, 8); 232 ret[0] &= ~EUI64_UBIT; 233 234 /* 235 * Reject inappropriate identifiers according to 236 * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (4) 237 * At this moment, we reject following cases: 238 * - all 0 identifier 239 * - identifiers that conflict with reserved subnet anycast addresses, 240 * which are defined in RFC 2526. 241 * - identifiers that conflict with ISATAP addresses 242 * - identifiers used in our own addresses 243 */ 244 badid = 0; 245 if (memcmp(nullbuf, ret, sizeof(nullbuf)) == 0) 246 badid = 1; 247 else if (memcmp(anycast_id, ret, 7) == 0 && 248 (anycast_id[7] & ret[7]) == anycast_id[7]) { 249 badid = 1; 250 } else if (memcmp(isatap_id, ret, sizeof(isatap_id)) == 0) 251 badid = 1; 252 else { 253 struct in6_ifaddr *ia; 254 255 for (ia = in6_ifaddr; ia; ia = ia->ia_next) { 256 if (!memcmp(&ia->ia_addr.sin6_addr.s6_addr[8], 257 ret, 8)) { 258 badid = 1; 259 break; 260 } 261 } 262 } 263 264 /* 265 * In the event that an unacceptable identifier has been generated, 266 * restart the process, using the right-most 64 bits of the MD5 digest 267 * obtained in place of the history value. 268 */ 269 if (badid) { 270 /* for debugging purposes only */ 271 #if 0 272 { 273 int i; 274 275 printf("unacceptable random ID: "); 276 for (i = 0; i < 16; i++) 277 printf("%02x", digest[i]); 278 printf("\n"); 279 } 280 #endif 281 282 if (++retry < GEN_TEMPID_RETRY_MAX) { 283 memcpy(seed, &digest[8], 8); 284 goto again; 285 } else { 286 /* 287 * We're so unlucky. Give up for now, and return 288 * all 0 IDs to tell the caller not to make a 289 * temporary address. 290 */ 291 nd6log((LOG_NOTICE, 292 "generate_tmp_ifid: never found a good ID\n")); 293 memset(ret, 0, 8); 294 } 295 } 296 297 /* 298 * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (6) 299 * Take the rightmost 64-bits of the MD5 digest and save them in 300 * stable storage as the history value to be used in the next 301 * iteration of the algorithm. 302 */ 303 memcpy(seed0, &digest[8], 8); 304 305 /* for debugging purposes only */ 306 #if 0 307 { 308 int i; 309 310 printf("to: "); 311 for (i = 0; i < 16; i++) 312 printf("%02x", digest[i]); 313 printf("\n"); 314 } 315 #endif 316 317 return 0; 318 } 319 /* 320 * Get interface identifier for the specified interface. 321 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface 322 */ 323 int 324 in6_get_hw_ifid(ifp, in6) 325 struct ifnet *ifp; 326 struct in6_addr *in6; /* upper 64bits are preserved */ 327 { 328 struct ifaddr *ifa; 329 struct sockaddr_dl *sdl; 330 char *addr; 331 size_t addrlen; 332 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 333 static u_int8_t allone[8] = 334 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 335 336 for (ifa = ifp->if_addrlist.tqh_first; 337 ifa; 338 ifa = ifa->ifa_list.tqe_next) 339 { 340 if (ifa->ifa_addr->sa_family != AF_LINK) 341 continue; 342 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 343 if (sdl == NULL) 344 continue; 345 if (sdl->sdl_alen == 0) 346 continue; 347 348 goto found; 349 } 350 351 return -1; 352 353 found: 354 addr = LLADDR(sdl); 355 addrlen = sdl->sdl_alen; 356 357 switch (ifp->if_type) { 358 case IFT_IEEE1394: 359 case IFT_IEEE80211: 360 /* IEEE1394 uses 16byte length address starting with EUI64 */ 361 if (addrlen > 8) 362 addrlen = 8; 363 break; 364 default: 365 break; 366 } 367 368 /* get EUI64 */ 369 switch (ifp->if_type) { 370 /* IEEE802/EUI64 cases - what others? */ 371 case IFT_ETHER: 372 case IFT_FDDI: 373 case IFT_ATM: 374 case IFT_IEEE1394: 375 case IFT_IEEE80211: 376 /* look at IEEE802/EUI64 only */ 377 if (addrlen != 8 && addrlen != 6) 378 return -1; 379 380 /* 381 * check for invalid MAC address - on bsdi, we see it a lot 382 * since wildboar configures all-zero MAC on pccard before 383 * card insertion. 384 */ 385 if (memcmp(addr, allzero, addrlen) == 0) 386 return -1; 387 if (memcmp(addr, allone, addrlen) == 0) 388 return -1; 389 390 /* make EUI64 address */ 391 if (addrlen == 8) 392 memcpy(&in6->s6_addr[8], addr, 8); 393 else if (addrlen == 6) { 394 in6->s6_addr[8] = addr[0]; 395 in6->s6_addr[9] = addr[1]; 396 in6->s6_addr[10] = addr[2]; 397 in6->s6_addr[11] = 0xff; 398 in6->s6_addr[12] = 0xfe; 399 in6->s6_addr[13] = addr[3]; 400 in6->s6_addr[14] = addr[4]; 401 in6->s6_addr[15] = addr[5]; 402 } 403 break; 404 405 case IFT_ARCNET: 406 if (addrlen != 1) 407 return -1; 408 if (!addr[0]) 409 return -1; 410 411 memset(&in6->s6_addr[8], 0, 8); 412 in6->s6_addr[15] = addr[0]; 413 414 /* 415 * due to insufficient bitwidth, we mark it local. 416 */ 417 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 418 in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 419 break; 420 421 case IFT_GIF: 422 #ifdef IFT_STF 423 case IFT_STF: 424 #endif 425 /* 426 * RFC2893 says: "SHOULD use IPv4 address as ifid source". 427 * however, IPv4 address is not very suitable as unique 428 * identifier source (can be renumbered). 429 * we don't do this. 430 */ 431 return -1; 432 433 default: 434 return -1; 435 } 436 437 /* sanity check: g bit must not indicate "group" */ 438 if (EUI64_GROUP(in6)) 439 return -1; 440 441 /* convert EUI64 into IPv6 interface identifier */ 442 EUI64_TO_IFID(in6); 443 444 /* 445 * sanity check: ifid must not be all zero, avoid conflict with 446 * subnet router anycast 447 */ 448 if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && 449 memcmp(&in6->s6_addr[9], allzero, 7) == 0) { 450 return -1; 451 } 452 453 return 0; 454 } 455 456 /* 457 * Get interface identifier for the specified interface. If it is not 458 * available on ifp0, borrow interface identifier from other information 459 * sources. 460 */ 461 static int 462 get_ifid(ifp0, altifp, in6) 463 struct ifnet *ifp0; 464 struct ifnet *altifp; /*secondary EUI64 source*/ 465 struct in6_addr *in6; 466 { 467 struct ifnet *ifp; 468 469 /* first, try to get it from the interface itself */ 470 if (in6_get_hw_ifid(ifp0, in6) == 0) { 471 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", 472 if_name(ifp0))); 473 goto success; 474 } 475 476 /* try secondary EUI64 source. this basically is for ATM PVC */ 477 if (altifp && in6_get_hw_ifid(altifp, in6) == 0) { 478 nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", 479 if_name(ifp0), if_name(altifp))); 480 goto success; 481 } 482 483 /* next, try to get it from some other hardware interface */ 484 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 485 { 486 if (ifp == ifp0) 487 continue; 488 if (in6_get_hw_ifid(ifp, in6) != 0) 489 continue; 490 491 /* 492 * to borrow ifid from other interface, ifid needs to be 493 * globally unique 494 */ 495 if (IFID_UNIVERSAL(in6)) { 496 nd6log((LOG_DEBUG, 497 "%s: borrow interface identifier from %s\n", 498 if_name(ifp0), if_name(ifp))); 499 goto success; 500 } 501 } 502 503 #if 0 504 /* get from hostid - only for certain architectures */ 505 if (get_hostid_ifid(ifp, in6) == 0) { 506 nd6log((LOG_DEBUG, 507 "%s: interface identifier generated by hostid\n", 508 if_name(ifp0))); 509 goto success; 510 } 511 #endif 512 513 /* last resort: get from random number source */ 514 if (get_rand_ifid(ifp, in6) == 0) { 515 nd6log((LOG_DEBUG, 516 "%s: interface identifier generated by random number\n", 517 if_name(ifp0))); 518 goto success; 519 } 520 521 printf("%s: failed to get interface identifier\n", if_name(ifp0)); 522 return -1; 523 524 success: 525 nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 526 if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10], 527 in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13], 528 in6->s6_addr[14], in6->s6_addr[15])); 529 return 0; 530 } 531 532 static int 533 in6_ifattach_linklocal(ifp, altifp) 534 struct ifnet *ifp; 535 struct ifnet *altifp; /*secondary EUI64 source*/ 536 { 537 struct in6_ifaddr *ia; 538 struct in6_aliasreq ifra; 539 struct nd_prefixctl pr0; 540 int i, error; 541 542 /* 543 * configure link-local address. 544 */ 545 memset(&ifra, 0, sizeof(ifra)); 546 547 /* 548 * in6_update_ifa() does not use ifra_name, but we accurately set it 549 * for safety. 550 */ 551 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name)); 552 553 ifra.ifra_addr.sin6_family = AF_INET6; 554 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); 555 ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000); 556 ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; 557 if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 558 ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; 559 ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); 560 } else { 561 if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) { 562 nd6log((LOG_ERR, 563 "%s: no ifid available\n", if_name(ifp))); 564 return (-1); 565 } 566 } 567 if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL)) 568 return (-1); 569 570 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 571 ifra.ifra_prefixmask.sin6_family = AF_INET6; 572 ifra.ifra_prefixmask.sin6_addr = in6mask64; 573 /* link-local addresses should NEVER expire. */ 574 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 575 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 576 577 /* 578 * Now call in6_update_ifa() to do a bunch of procedures to configure 579 * a link-local address. We can set NULL to the 3rd argument, because 580 * we know there's no other link-local address on the interface 581 * and therefore we are adding one (instead of updating one). 582 */ 583 if ((error = in6_update_ifa(ifp, &ifra, NULL, 584 IN6_IFAUPDATE_DADDELAY)) != 0) { 585 /* 586 * XXX: When the interface does not support IPv6, this call 587 * would fail in the SIOCSIFADDR ioctl. I believe the 588 * notification is rather confusing in this case, so just 589 * suppress it. (jinmei@kame.net 20010130) 590 */ 591 if (error != EAFNOSUPPORT) 592 nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to " 593 "configure a link-local address on %s " 594 "(errno=%d)\n", 595 if_name(ifp), error)); 596 return (-1); 597 } 598 599 ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */ 600 #ifdef DIAGNOSTIC 601 if (!ia) { 602 panic("ia == NULL in in6_ifattach_linklocal"); 603 /* NOTREACHED */ 604 } 605 #endif 606 607 /* 608 * Make the link-local prefix (fe80::/64%link) as on-link. 609 * Since we'd like to manage prefixes separately from addresses, 610 * we make an ND6 prefix structure for the link-local prefix, 611 * and add it to the prefix list as a never-expire prefix. 612 * XXX: this change might affect some existing code base... 613 */ 614 memset(&pr0, 0, sizeof(pr0)); 615 pr0.ndpr_ifp = ifp; 616 /* this should be 64 at this moment. */ 617 pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL); 618 pr0.ndpr_prefix = ifra.ifra_addr; 619 /* apply the mask for safety. (nd6_prelist_add will apply it again) */ 620 for (i = 0; i < 4; i++) { 621 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &= 622 in6mask64.s6_addr32[i]; 623 } 624 /* 625 * Initialize parameters. The link-local prefix must always be 626 * on-link, and its lifetimes never expire. 627 */ 628 pr0.ndpr_raf_onlink = 1; 629 pr0.ndpr_raf_auto = 1; /* probably meaningless */ 630 pr0.ndpr_vltime = ND6_INFINITE_LIFETIME; 631 pr0.ndpr_pltime = ND6_INFINITE_LIFETIME; 632 /* 633 * Since there is no other link-local addresses, nd6_prefix_lookup() 634 * probably returns NULL. However, we cannot always expect the result. 635 * For example, if we first remove the (only) existing link-local 636 * address, and then reconfigure another one, the prefix is still 637 * valid with referring to the old link-local address. 638 */ 639 if (nd6_prefix_lookup(&pr0) == NULL) { 640 if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0) 641 return (error); 642 } 643 644 return 0; 645 } 646 647 static int 648 in6_ifattach_loopback(ifp) 649 struct ifnet *ifp; /* must be IFT_LOOP */ 650 { 651 struct in6_aliasreq ifra; 652 int error; 653 654 memset(&ifra, 0, sizeof(ifra)); 655 656 /* 657 * in6_update_ifa() does not use ifra_name, but we accurately set it 658 * for safety. 659 */ 660 strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name)); 661 662 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); 663 ifra.ifra_prefixmask.sin6_family = AF_INET6; 664 ifra.ifra_prefixmask.sin6_addr = in6mask128; 665 666 /* 667 * Always initialize ia_dstaddr (= broadcast address) to loopback 668 * address. Follows IPv4 practice - see in_ifinit(). 669 */ 670 ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 671 ifra.ifra_dstaddr.sin6_family = AF_INET6; 672 ifra.ifra_dstaddr.sin6_addr = in6addr_loopback; 673 674 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); 675 ifra.ifra_addr.sin6_family = AF_INET6; 676 ifra.ifra_addr.sin6_addr = in6addr_loopback; 677 678 /* the loopback address should NEVER expire. */ 679 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 680 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 681 682 /* we don't need to perform DAD on loopback interfaces. */ 683 ifra.ifra_flags |= IN6_IFF_NODAD; 684 685 /* 686 * We are sure that this is a newly assigned address, so we can set 687 * NULL to the 3rd arg. 688 */ 689 if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) { 690 nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure " 691 "the loopback address on %s (errno=%d)\n", 692 if_name(ifp), error)); 693 return (-1); 694 } 695 696 return 0; 697 } 698 699 /* 700 * compute NI group address, based on the current hostname setting. 701 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later). 702 * 703 * when ifp == NULL, the caller is responsible for filling scopeid. 704 */ 705 int 706 in6_nigroup(ifp, name, namelen, sa6) 707 struct ifnet *ifp; 708 const char *name; 709 int namelen; 710 struct sockaddr_in6 *sa6; 711 { 712 const char *p; 713 u_int8_t *q; 714 MD5_CTX ctxt; 715 u_int8_t digest[16]; 716 u_int8_t l; 717 u_int8_t n[64]; /* a single label must not exceed 63 chars */ 718 719 if (!namelen || !name) 720 return -1; 721 722 p = name; 723 while (p && *p && *p != '.' && p - name < namelen) 724 p++; 725 if (p - name > sizeof(n) - 1) 726 return -1; /* label too long */ 727 l = p - name; 728 strncpy((char *)n, name, l); 729 n[(int)l] = '\0'; 730 for (q = n; *q; q++) { 731 if ('A' <= *q && *q <= 'Z') 732 *q = *q - 'A' + 'a'; 733 } 734 735 /* generate 8 bytes of pseudo-random value. */ 736 memset(&ctxt, 0, sizeof(ctxt)); 737 MD5Init(&ctxt); 738 MD5Update(&ctxt, &l, sizeof(l)); 739 MD5Update(&ctxt, n, l); 740 MD5Final(digest, &ctxt); 741 742 memset(sa6, 0, sizeof(*sa6)); 743 sa6->sin6_family = AF_INET6; 744 sa6->sin6_len = sizeof(*sa6); 745 sa6->sin6_addr.s6_addr16[0] = htons(0xff02); 746 sa6->sin6_addr.s6_addr8[11] = 2; 747 memcpy(&sa6->sin6_addr.s6_addr32[3], digest, 748 sizeof(sa6->sin6_addr.s6_addr32[3])); 749 if (in6_setscope(&sa6->sin6_addr, ifp, NULL)) 750 return (-1); /* XXX: should not fail */ 751 752 return 0; 753 } 754 755 /* 756 * XXX multiple loopback interface needs more care. for instance, 757 * nodelocal address needs to be configured onto only one of them. 758 * XXX multiple link-local address case 759 */ 760 void 761 in6_ifattach(ifp, altifp) 762 struct ifnet *ifp; 763 struct ifnet *altifp; /* secondary EUI64 source */ 764 { 765 struct in6_ifaddr *ia; 766 struct in6_addr in6; 767 768 /* some of the interfaces are inherently not IPv6 capable */ 769 switch (ifp->if_type) { 770 case IFT_BRIDGE: 771 #ifdef IFT_PFLOG 772 case IFT_PFLOG: 773 #endif 774 #ifdef IFT_PFSYNC 775 case IFT_PFSYNC: 776 #endif 777 return; 778 } 779 780 /* 781 * if link mtu is too small, don't try to configure IPv6. 782 * remember there could be some link-layer that has special 783 * fragmentation logic. 784 */ 785 if (ifp->if_mtu < IPV6_MMTU) { 786 nd6log((LOG_INFO, "in6_ifattach: " 787 "%s has too small MTU, IPv6 not enabled\n", 788 if_name(ifp))); 789 return; 790 } 791 792 /* create a multicast kludge storage (if we have not had one) */ 793 in6_createmkludge(ifp); 794 795 /* 796 * quirks based on interface type 797 */ 798 switch (ifp->if_type) { 799 #ifdef IFT_STF 800 case IFT_STF: 801 /* 802 * 6to4 interface is a very special kind of beast. 803 * no multicast, no linklocal. RFC2529 specifies how to make 804 * linklocals for 6to4 interface, but there's no use and 805 * it is rather harmful to have one. 806 */ 807 return; 808 #endif 809 case IFT_CARP: 810 return; 811 default: 812 break; 813 } 814 815 /* 816 * usually, we require multicast capability to the interface 817 */ 818 if ((ifp->if_flags & IFF_MULTICAST) == 0) { 819 nd6log((LOG_INFO, "in6_ifattach: " 820 "%s is not multicast capable, IPv6 not enabled\n", 821 if_name(ifp))); 822 return; 823 } 824 825 /* 826 * assign loopback address for loopback interface. 827 * XXX multiple loopback interface case. 828 */ 829 if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 830 in6 = in6addr_loopback; 831 if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) { 832 if (in6_ifattach_loopback(ifp) != 0) 833 return; 834 } 835 } 836 837 /* 838 * assign a link-local address, if there's none. 839 */ 840 if (ip6_auto_linklocal) { 841 ia = in6ifa_ifpforlinklocal(ifp, 0); 842 if (ia == NULL) { 843 if (in6_ifattach_linklocal(ifp, altifp) == 0) { 844 /* linklocal address assigned */ 845 } else { 846 /* failed to assign linklocal address. bark? */ 847 } 848 } 849 } 850 } 851 852 /* 853 * NOTE: in6_ifdetach() does not support loopback if at this moment. 854 * We don't need this function in bsdi, because interfaces are never removed 855 * from the ifnet list in bsdi. 856 */ 857 void 858 in6_ifdetach(ifp) 859 struct ifnet *ifp; 860 { 861 struct in6_ifaddr *ia, *oia; 862 struct ifaddr *ifa, *next; 863 struct rtentry *rt; 864 short rtflags; 865 struct in6_multi_mship *imm; 866 867 /* remove ip6_mrouter stuff */ 868 ip6_mrouter_detach(ifp); 869 870 /* remove neighbor management table */ 871 nd6_purge(ifp); 872 873 /* nuke any of IPv6 addresses we have */ 874 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) 875 { 876 next = ifa->ifa_list.tqe_next; 877 if (ifa->ifa_addr->sa_family != AF_INET6) 878 continue; 879 in6_purgeaddr(ifa); 880 } 881 882 /* undo everything done by in6_ifattach(), just in case */ 883 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) 884 { 885 next = ifa->ifa_list.tqe_next; 886 887 if (ifa->ifa_addr->sa_family != AF_INET6 888 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) { 889 continue; 890 } 891 892 ia = (struct in6_ifaddr *)ifa; 893 894 /* 895 * leave from multicast groups we have joined for the interface 896 */ 897 while ((imm = ia->ia6_memberships.lh_first) != NULL) { 898 LIST_REMOVE(imm, i6mm_chain); 899 in6_leavegroup(imm); 900 } 901 902 /* remove from the routing table */ 903 if ((ia->ia_flags & IFA_ROUTE) && 904 (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) { 905 rtflags = rt->rt_flags; 906 rtfree(rt); 907 rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr, 908 (struct sockaddr *)&ia->ia_addr, 909 (struct sockaddr *)&ia->ia_prefixmask, 910 rtflags, (struct rtentry **)0); 911 } 912 913 /* remove from the linked list */ 914 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); 915 IFAFREE(&ia->ia_ifa); 916 917 /* also remove from the IPv6 address chain(itojun&jinmei) */ 918 oia = ia; 919 if (oia == (ia = in6_ifaddr)) 920 in6_ifaddr = ia->ia_next; 921 else { 922 while (ia->ia_next && (ia->ia_next != oia)) 923 ia = ia->ia_next; 924 if (ia->ia_next) 925 ia->ia_next = oia->ia_next; 926 else { 927 nd6log((LOG_ERR, 928 "%s: didn't unlink in6ifaddr from list\n", 929 if_name(ifp))); 930 } 931 } 932 933 IFAFREE(&oia->ia_ifa); 934 } 935 936 /* cleanup multicast address kludge table, if there is any */ 937 in6_purgemkludge(ifp); 938 939 /* 940 * remove neighbor management table. we call it twice just to make 941 * sure we nuke everything. maybe we need just one call. 942 * XXX: since the first call did not release addresses, some prefixes 943 * might remain. We should call nd6_purge() again to release the 944 * prefixes after removing all addresses above. 945 * (Or can we just delay calling nd6_purge until at this point?) 946 */ 947 nd6_purge(ifp); 948 } 949 950 int 951 in6_get_tmpifid(ifp, retbuf, baseid, generate) 952 struct ifnet *ifp; 953 u_int8_t *retbuf; 954 const u_int8_t *baseid; 955 int generate; 956 { 957 u_int8_t nullbuf[8]; 958 struct nd_ifinfo *ndi = ND_IFINFO(ifp); 959 960 memset(nullbuf, 0, sizeof(nullbuf)); 961 if (memcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) { 962 /* we've never created a random ID. Create a new one. */ 963 generate = 1; 964 } 965 966 if (generate) { 967 memcpy(ndi->randomseed1, baseid, sizeof(ndi->randomseed1)); 968 969 /* generate_tmp_ifid will update seedn and buf */ 970 (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1, 971 ndi->randomid); 972 } 973 memcpy(retbuf, ndi->randomid, 8); 974 if (generate && memcmp(retbuf, nullbuf, sizeof(nullbuf)) == 0) { 975 /* generate_tmp_ifid could not found a good ID. */ 976 return (-1); 977 } 978 979 return (0); 980 } 981 982 void 983 in6_tmpaddrtimer(void *ignored_arg __unused) 984 { 985 struct nd_ifinfo *ndi; 986 u_int8_t nullbuf[8]; 987 struct ifnet *ifp; 988 int s = splsoftnet(); 989 990 callout_reset(&in6_tmpaddrtimer_ch, 991 (ip6_temp_preferred_lifetime - ip6_desync_factor - 992 ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL); 993 994 memset(nullbuf, 0, sizeof(nullbuf)); 995 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) { 996 ndi = ND_IFINFO(ifp); 997 if (memcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { 998 /* 999 * We've been generating a random ID on this interface. 1000 * Create a new one. 1001 */ 1002 (void)generate_tmp_ifid(ndi->randomseed0, 1003 ndi->randomseed1, ndi->randomid); 1004 } 1005 } 1006 1007 splx(s); 1008 } 1009