1139826Simp/*- 253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 353541Sshin * All rights reserved. 453541Sshin * 553541Sshin * Redistribution and use in source and binary forms, with or without 653541Sshin * modification, are permitted provided that the following conditions 753541Sshin * are met: 853541Sshin * 1. Redistributions of source code must retain the above copyright 953541Sshin * notice, this list of conditions and the following disclaimer. 1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1153541Sshin * notice, this list of conditions and the following disclaimer in the 1253541Sshin * documentation and/or other materials provided with the distribution. 1353541Sshin * 3. Neither the name of the project nor the names of its contributors 1453541Sshin * may be used to endorse or promote products derived from this software 1553541Sshin * without specific prior written permission. 1653541Sshin * 1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2053541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2753541Sshin * SUCH DAMAGE. 28174510Sobrien * 29174510Sobrien * $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $ 3053541Sshin */ 3153541Sshin 32174510Sobrien#include <sys/cdefs.h> 33174510Sobrien__FBSDID("$FreeBSD: releng/11.0/sys/netinet6/in6_ifattach.c 302054 2016-06-21 13:48:49Z bz $"); 34174510Sobrien 3553541Sshin#include <sys/param.h> 3653541Sshin#include <sys/systm.h> 3753541Sshin#include <sys/malloc.h> 3853541Sshin#include <sys/socket.h> 3953541Sshin#include <sys/sockio.h> 40193066Sjamie#include <sys/jail.h> 4153541Sshin#include <sys/kernel.h> 42286001Sae#include <sys/lock.h> 43196019Srwatson#include <sys/proc.h> 44286001Sae#include <sys/rmlock.h> 4578064Sume#include <sys/syslog.h> 4653541Sshin#include <sys/md5.h> 4753541Sshin 4853541Sshin#include <net/if.h> 49257176Sglebius#include <net/if_var.h> 5053541Sshin#include <net/if_dl.h> 5153541Sshin#include <net/if_types.h> 5253541Sshin#include <net/route.h> 53185571Sbz#include <net/vnet.h> 5453541Sshin 5553541Sshin#include <netinet/in.h> 5653541Sshin#include <netinet/in_var.h> 5753541Sshin#include <netinet/if_ether.h> 5881127Sume#include <netinet/in_pcb.h> 59195699Srwatson#include <netinet/ip_var.h> 60195699Srwatson#include <netinet/udp.h> 61195699Srwatson#include <netinet/udp_var.h> 6253541Sshin 6362587Sitojun#include <netinet/ip6.h> 6453541Sshin#include <netinet6/ip6_var.h> 6578064Sume#include <netinet6/in6_var.h> 6681127Sume#include <netinet6/in6_pcb.h> 6753541Sshin#include <netinet6/in6_ifattach.h> 6853541Sshin#include <netinet6/ip6_var.h> 6953541Sshin#include <netinet6/nd6.h> 70191672Sbms#include <netinet6/mld6_var.h> 7162587Sitojun#include <netinet6/scope6_var.h> 7253541Sshin 73207369SbzVNET_DEFINE(unsigned long, in6_maxmtu) = 0; 74207369Sbz 75207369Sbz#ifdef IP6_AUTO_LINKLOCAL 76207369SbzVNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL; 77207369Sbz#else 78207369SbzVNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */ 79207369Sbz#endif 80207369Sbz 81195699SrwatsonVNET_DEFINE(struct callout, in6_tmpaddrtimer_ch); 82195727Srwatson#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch) 83195699Srwatson 84195699SrwatsonVNET_DECLARE(struct inpcbinfo, ripcbinfo); 85195727Srwatson#define V_ripcbinfo VNET(ripcbinfo) 86195699Srwatson 87175162Sobrienstatic int get_rand_ifid(struct ifnet *, struct in6_addr *); 88175162Sobrienstatic int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *); 89175162Sobrienstatic int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *); 90175162Sobrienstatic int in6_ifattach_linklocal(struct ifnet *, struct ifnet *); 91175162Sobrienstatic int in6_ifattach_loopback(struct ifnet *); 92175162Sobrienstatic void in6_purgemaddrs(struct ifnet *); 9353541Sshin 9462587Sitojun#define EUI64_GBIT 0x01 9562587Sitojun#define EUI64_UBIT 0x02 9662587Sitojun#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0) 9762587Sitojun#define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) 9862587Sitojun#define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6)) 9962587Sitojun#define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT) 10062587Sitojun#define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6)) 10153541Sshin 10262587Sitojun#define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) 10362587Sitojun#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) 10453541Sshin 10553541Sshin/* 10653541Sshin * Generate a last-resort interface identifier, when the machine has no 10753541Sshin * IEEE802/EUI64 address sources. 10862587Sitojun * The goal here is to get an interface identifier that is 10962587Sitojun * (1) random enough and (2) does not change across reboot. 11062587Sitojun * We currently use MD5(hostname) for it. 111171259Sdelphij * 112171259Sdelphij * in6 - upper 64bits are preserved 11353541Sshin */ 11453541Sshinstatic int 115171259Sdelphijget_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) 11653541Sshin{ 11753541Sshin MD5_CTX ctxt; 118193066Sjamie struct prison *pr; 11953541Sshin u_int8_t digest[16]; 120180291Srwatson int hostnamelen; 12153541Sshin 122193066Sjamie pr = curthread->td_ucred->cr_prison; 123193066Sjamie mtx_lock(&pr->pr_mtx); 124194118Sjamie hostnamelen = strlen(pr->pr_hostname); 12562587Sitojun#if 0 12662587Sitojun /* we need at least several letters as seed for ifid */ 127193066Sjamie if (hostnamelen < 3) { 128193066Sjamie mtx_unlock(&pr->pr_mtx); 12962587Sitojun return -1; 130193066Sjamie } 13162587Sitojun#endif 13262587Sitojun 13362587Sitojun /* generate 8 bytes of pseudo-random value. */ 13453541Sshin bzero(&ctxt, sizeof(ctxt)); 13553541Sshin MD5Init(&ctxt); 136194118Sjamie MD5Update(&ctxt, pr->pr_hostname, hostnamelen); 137193066Sjamie mtx_unlock(&pr->pr_mtx); 13853541Sshin MD5Final(digest, &ctxt); 13953541Sshin 14062587Sitojun /* assumes sizeof(digest) > sizeof(ifid) */ 14162587Sitojun bcopy(digest, &in6->s6_addr[8], 8); 14253541Sshin 14353541Sshin /* make sure to set "u" bit to local, and "g" bit to individual. */ 14462587Sitojun in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 14562587Sitojun in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 14653541Sshin 14762587Sitojun /* convert EUI64 into IPv6 interface identifier */ 14862587Sitojun EUI64_TO_IFID(in6); 14962587Sitojun 15053541Sshin return 0; 15153541Sshin} 15253541Sshin 15378064Sumestatic int 154171259Sdelphijgenerate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret) 15578064Sume{ 15678064Sume MD5_CTX ctxt; 15778064Sume u_int8_t seed[16], digest[16], nullbuf[8]; 15878064Sume u_int32_t val32; 15978064Sume 160171259Sdelphij /* If there's no history, start with a random seed. */ 16178064Sume bzero(nullbuf, sizeof(nullbuf)); 16278064Sume if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) { 16378064Sume int i; 16478064Sume 16578064Sume for (i = 0; i < 2; i++) { 166121807Sume val32 = arc4random(); 16778064Sume bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32)); 16878064Sume } 169120913Sume } else 17078064Sume bcopy(seed0, seed, 8); 17178064Sume 17278064Sume /* copy the right-most 64-bits of the given address */ 17378064Sume /* XXX assumption on the size of IFID */ 17478064Sume bcopy(seed1, &seed[8], 8); 17578064Sume 17678064Sume if (0) { /* for debugging purposes only */ 17778064Sume int i; 17878064Sume 17978064Sume printf("generate_tmp_ifid: new randomized ID from: "); 18078064Sume for (i = 0; i < 16; i++) 18178064Sume printf("%02x", seed[i]); 18278064Sume printf(" "); 18378064Sume } 18478064Sume 18578064Sume /* generate 16 bytes of pseudo-random value. */ 18678064Sume bzero(&ctxt, sizeof(ctxt)); 18778064Sume MD5Init(&ctxt); 18878064Sume MD5Update(&ctxt, seed, sizeof(seed)); 18978064Sume MD5Final(digest, &ctxt); 19078064Sume 19178064Sume /* 19278064Sume * RFC 3041 3.2.1. (3) 19378064Sume * Take the left-most 64-bits of the MD5 digest and set bit 6 (the 19478064Sume * left-most bit is numbered 0) to zero. 19578064Sume */ 19678064Sume bcopy(digest, ret, 8); 19778064Sume ret[0] &= ~EUI64_UBIT; 19878064Sume 19978064Sume /* 20078064Sume * XXX: we'd like to ensure that the generated value is not zero 20178064Sume * for simplicity. If the caclculated digest happens to be zero, 20278064Sume * use a random non-zero value as the last resort. 20378064Sume */ 20478064Sume if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) { 205151465Ssuz nd6log((LOG_INFO, 206151465Ssuz "generate_tmp_ifid: computed MD5 value is zero.\n")); 20778064Sume 208121807Sume val32 = arc4random(); 20978064Sume val32 = 1 + (val32 % (0xffffffff - 1)); 21078064Sume } 21178064Sume 21278064Sume /* 21378064Sume * RFC 3041 3.2.1. (4) 21478064Sume * Take the rightmost 64-bits of the MD5 digest and save them in 21578064Sume * stable storage as the history value to be used in the next 216120913Sume * iteration of the algorithm. 21778064Sume */ 21878064Sume bcopy(&digest[8], seed0, 8); 21978064Sume 22078064Sume if (0) { /* for debugging purposes only */ 22178064Sume int i; 22278064Sume 22378064Sume printf("to: "); 22478064Sume for (i = 0; i < 16; i++) 22578064Sume printf("%02x", digest[i]); 22678064Sume printf("\n"); 22778064Sume } 22878064Sume 22978064Sume return 0; 23078064Sume} 23178064Sume 23253541Sshin/* 23362587Sitojun * Get interface identifier for the specified interface. 23462587Sitojun * XXX assumes single sockaddr_dl (AF_LINK address) per an interface 235171259Sdelphij * 236171259Sdelphij * in6 - upper 64bits are preserved 23753541Sshin */ 238151477Ssuzint 239171259Sdelphijin6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) 24053541Sshin{ 24153541Sshin struct ifaddr *ifa; 24253541Sshin struct sockaddr_dl *sdl; 24362587Sitojun u_int8_t *addr; 24462587Sitojun size_t addrlen; 24562587Sitojun static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 24662587Sitojun static u_int8_t allone[8] = 24762587Sitojun { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 24853541Sshin 249229621Sjhb IF_ADDR_RLOCK(ifp); 250191340Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 25162587Sitojun if (ifa->ifa_addr->sa_family != AF_LINK) 25253541Sshin continue; 25362587Sitojun sdl = (struct sockaddr_dl *)ifa->ifa_addr; 25462587Sitojun if (sdl == NULL) 25562587Sitojun continue; 25662587Sitojun if (sdl->sdl_alen == 0) 25762587Sitojun continue; 25862587Sitojun 25962587Sitojun goto found; 26053541Sshin } 261229621Sjhb IF_ADDR_RUNLOCK(ifp); 26253541Sshin 26362587Sitojun return -1; 26462587Sitojun 26553541Sshinfound: 266194760Srwatson IF_ADDR_LOCK_ASSERT(ifp); 26762587Sitojun addr = LLADDR(sdl); 26862587Sitojun addrlen = sdl->sdl_alen; 26953541Sshin 27062587Sitojun /* get EUI64 */ 27162587Sitojun switch (ifp->if_type) { 272252511Shrs case IFT_BRIDGE: 27362587Sitojun case IFT_ETHER: 274216650Sjhay case IFT_L2VLAN: 27562587Sitojun case IFT_FDDI: 276120049Smdodd case IFT_ISO88025: 27762587Sitojun case IFT_ATM: 27878064Sume case IFT_IEEE1394: 27978064Sume case IFT_IEEE80211: 28062587Sitojun /* IEEE802/EUI64 cases - what others? */ 28178064Sume /* IEEE1394 uses 16byte length address starting with EUI64 */ 28278064Sume if (addrlen > 8) 28378064Sume addrlen = 8; 28453541Sshin 28562587Sitojun /* look at IEEE802/EUI64 only */ 286191337Srwatson if (addrlen != 8 && addrlen != 6) { 287229621Sjhb IF_ADDR_RUNLOCK(ifp); 28862587Sitojun return -1; 289191337Srwatson } 29053541Sshin 29162587Sitojun /* 29262587Sitojun * check for invalid MAC address - on bsdi, we see it a lot 29362587Sitojun * since wildboar configures all-zero MAC on pccard before 29462587Sitojun * card insertion. 29562587Sitojun */ 296191337Srwatson if (bcmp(addr, allzero, addrlen) == 0) { 297229621Sjhb IF_ADDR_RUNLOCK(ifp); 29862587Sitojun return -1; 299191337Srwatson } 300191337Srwatson if (bcmp(addr, allone, addrlen) == 0) { 301229621Sjhb IF_ADDR_RUNLOCK(ifp); 30262587Sitojun return -1; 303191337Srwatson } 30462587Sitojun 30562587Sitojun /* make EUI64 address */ 30662587Sitojun if (addrlen == 8) 30762587Sitojun bcopy(addr, &in6->s6_addr[8], 8); 30862587Sitojun else if (addrlen == 6) { 30962587Sitojun in6->s6_addr[8] = addr[0]; 31062587Sitojun in6->s6_addr[9] = addr[1]; 31162587Sitojun in6->s6_addr[10] = addr[2]; 31262587Sitojun in6->s6_addr[11] = 0xff; 31362587Sitojun in6->s6_addr[12] = 0xfe; 31462587Sitojun in6->s6_addr[13] = addr[3]; 31562587Sitojun in6->s6_addr[14] = addr[4]; 31662587Sitojun in6->s6_addr[15] = addr[5]; 31762587Sitojun } 31862587Sitojun break; 31962587Sitojun 32062587Sitojun case IFT_ARCNET: 321191337Srwatson if (addrlen != 1) { 322229621Sjhb IF_ADDR_RUNLOCK(ifp); 32362587Sitojun return -1; 324191337Srwatson } 325191337Srwatson if (!addr[0]) { 326229621Sjhb IF_ADDR_RUNLOCK(ifp); 32762587Sitojun return -1; 328191337Srwatson } 32962587Sitojun 33062587Sitojun bzero(&in6->s6_addr[8], 8); 33162587Sitojun in6->s6_addr[15] = addr[0]; 33262587Sitojun 33362587Sitojun /* 33462587Sitojun * due to insufficient bitwidth, we mark it local. 33562587Sitojun */ 33662587Sitojun in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 33762587Sitojun in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 33862587Sitojun break; 33962587Sitojun 34062587Sitojun case IFT_GIF: 34162587Sitojun case IFT_STF: 34262587Sitojun /* 34378064Sume * RFC2893 says: "SHOULD use IPv4 address as ifid source". 34462587Sitojun * however, IPv4 address is not very suitable as unique 34562587Sitojun * identifier source (can be renumbered). 34662587Sitojun * we don't do this. 34762587Sitojun */ 348229621Sjhb IF_ADDR_RUNLOCK(ifp); 34962587Sitojun return -1; 35062587Sitojun 35162587Sitojun default: 352229621Sjhb IF_ADDR_RUNLOCK(ifp); 35362587Sitojun return -1; 35453541Sshin } 35562587Sitojun 35662587Sitojun /* sanity check: g bit must not indicate "group" */ 357191337Srwatson if (EUI64_GROUP(in6)) { 358229621Sjhb IF_ADDR_RUNLOCK(ifp); 35962587Sitojun return -1; 360191337Srwatson } 36162587Sitojun 36262587Sitojun /* convert EUI64 into IPv6 interface identifier */ 36362587Sitojun EUI64_TO_IFID(in6); 36462587Sitojun 36562587Sitojun /* 36662587Sitojun * sanity check: ifid must not be all zero, avoid conflict with 36762587Sitojun * subnet router anycast 36862587Sitojun */ 36962587Sitojun if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && 37062587Sitojun bcmp(&in6->s6_addr[9], allzero, 7) == 0) { 371229621Sjhb IF_ADDR_RUNLOCK(ifp); 37262587Sitojun return -1; 37362587Sitojun } 37462587Sitojun 375229621Sjhb IF_ADDR_RUNLOCK(ifp); 37662587Sitojun return 0; 37753541Sshin} 37853541Sshin 37953541Sshin/* 38062587Sitojun * Get interface identifier for the specified interface. If it is not 38162587Sitojun * available on ifp0, borrow interface identifier from other information 38262587Sitojun * sources. 383171259Sdelphij * 384171259Sdelphij * altifp - secondary EUI64 source 38553541Sshin */ 38662587Sitojunstatic int 387171259Sdelphijget_ifid(struct ifnet *ifp0, struct ifnet *altifp, 388171259Sdelphij struct in6_addr *in6) 38953541Sshin{ 39053541Sshin struct ifnet *ifp; 39153541Sshin 39262587Sitojun /* first, try to get it from the interface itself */ 393151477Ssuz if (in6_get_hw_ifid(ifp0, in6) == 0) { 39478064Sume nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", 39578064Sume if_name(ifp0))); 39662587Sitojun goto success; 39762587Sitojun } 39853541Sshin 39962587Sitojun /* try secondary EUI64 source. this basically is for ATM PVC */ 400151477Ssuz if (altifp && in6_get_hw_ifid(altifp, in6) == 0) { 40178064Sume nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", 40278064Sume if_name(ifp0), if_name(altifp))); 40362587Sitojun goto success; 40462587Sitojun } 40562587Sitojun 40662587Sitojun /* next, try to get it from some other hardware interface */ 407196481Srwatson IFNET_RLOCK_NOSLEEP(); 408274345Sglebius TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 40962587Sitojun if (ifp == ifp0) 41062587Sitojun continue; 411151477Ssuz if (in6_get_hw_ifid(ifp, in6) != 0) 41262587Sitojun continue; 41362587Sitojun 41462587Sitojun /* 41562587Sitojun * to borrow ifid from other interface, ifid needs to be 41662587Sitojun * globally unique 41762587Sitojun */ 41862587Sitojun if (IFID_UNIVERSAL(in6)) { 41978064Sume nd6log((LOG_DEBUG, 42078064Sume "%s: borrow interface identifier from %s\n", 42178064Sume if_name(ifp0), if_name(ifp))); 422196481Srwatson IFNET_RUNLOCK_NOSLEEP(); 42362587Sitojun goto success; 42462587Sitojun } 42562587Sitojun } 426196481Srwatson IFNET_RUNLOCK_NOSLEEP(); 42762587Sitojun 42862587Sitojun /* last resort: get from random number source */ 42962587Sitojun if (get_rand_ifid(ifp, in6) == 0) { 43078064Sume nd6log((LOG_DEBUG, 43178064Sume "%s: interface identifier generated by random number\n", 43278064Sume if_name(ifp0))); 43362587Sitojun goto success; 43462587Sitojun } 43562587Sitojun 43666504Sitojun printf("%s: failed to get interface identifier\n", if_name(ifp0)); 43762587Sitojun return -1; 43862587Sitojun 43962587Sitojunsuccess: 440120913Sume nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 441120913Sume if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10], 442120913Sume in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13], 443120913Sume in6->s6_addr[14], in6->s6_addr[15])); 44462587Sitojun return 0; 44562587Sitojun} 44662587Sitojun 447171259Sdelphij/* 448171259Sdelphij * altifp - secondary EUI64 source 449171259Sdelphij */ 45062587Sitojunstatic int 451171259Sdelphijin6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) 45278064Sume{ 45362587Sitojun struct in6_ifaddr *ia; 45478064Sume struct in6_aliasreq ifra; 455151539Ssuz struct nd_prefixctl pr0; 456260458Smelifaro int error; 45762587Sitojun 45862587Sitojun /* 45978064Sume * configure link-local address. 46062587Sitojun */ 461260860Smelifaro in6_prepare_ifra(&ifra, NULL, &in6mask64); 46262587Sitojun 463148385Sume ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000); 46478064Sume ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; 46578064Sume if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 46678064Sume ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; 46778064Sume ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); 46878064Sume } else { 46978064Sume if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) { 47078064Sume nd6log((LOG_ERR, 47178064Sume "%s: no ifid available\n", if_name(ifp))); 472120913Sume return (-1); 47362587Sitojun } 47462587Sitojun } 475148385Sume if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL)) 476148385Sume return (-1); 47762587Sitojun 47878064Sume /* link-local addresses should NEVER expire. */ 47978064Sume ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 48078064Sume ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 48162587Sitojun 48278064Sume /* 48378064Sume * Now call in6_update_ifa() to do a bunch of procedures to configure 484151465Ssuz * a link-local address. We can set the 3rd argument to NULL, because 48595023Ssuz * we know there's no other link-local address on the interface 48695023Ssuz * and therefore we are adding one (instead of updating one). 48778064Sume */ 488151539Ssuz if ((error = in6_update_ifa(ifp, &ifra, NULL, 489151539Ssuz IN6_IFAUPDATE_DADDELAY)) != 0) { 49062587Sitojun /* 49178064Sume * XXX: When the interface does not support IPv6, this call 49278064Sume * would fail in the SIOCSIFADDR ioctl. I believe the 49378064Sume * notification is rather confusing in this case, so just 494120913Sume * suppress it. (jinmei@kame.net 20010130) 49562587Sitojun */ 49678064Sume if (error != EAFNOSUPPORT) 497151465Ssuz nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to " 49878064Sume "configure a link-local address on %s " 49978064Sume "(errno=%d)\n", 500151465Ssuz if_name(ifp), error)); 501120856Sume return (-1); 50262587Sitojun } 50362587Sitojun 50478064Sume ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */ 505229546Sbz KASSERT(ia != NULL, ("%s: ia == NULL, ifp=%p", __func__, ifp)); 506229546Sbz 507194760Srwatson ifa_free(&ia->ia_ifa); 50853541Sshin 50978064Sume /* 510120913Sume * Make the link-local prefix (fe80::%link/64) as on-link. 51178064Sume * Since we'd like to manage prefixes separately from addresses, 51278064Sume * we make an ND6 prefix structure for the link-local prefix, 51378064Sume * and add it to the prefix list as a never-expire prefix. 51478064Sume * XXX: this change might affect some existing code base... 51578064Sume */ 51678064Sume bzero(&pr0, sizeof(pr0)); 51778064Sume pr0.ndpr_ifp = ifp; 51878064Sume /* this should be 64 at this moment. */ 51978064Sume pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL); 52078064Sume pr0.ndpr_prefix = ifra.ifra_addr; 52178064Sume /* apply the mask for safety. (nd6_prelist_add will apply it again) */ 522260458Smelifaro IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, &in6mask64); 52378064Sume /* 52478064Sume * Initialize parameters. The link-local prefix must always be 52578064Sume * on-link, and its lifetimes never expire. 52678064Sume */ 52778064Sume pr0.ndpr_raf_onlink = 1; 52878064Sume pr0.ndpr_raf_auto = 1; /* probably meaningless */ 52978064Sume pr0.ndpr_vltime = ND6_INFINITE_LIFETIME; 53078064Sume pr0.ndpr_pltime = ND6_INFINITE_LIFETIME; 53178064Sume /* 53278064Sume * Since there is no other link-local addresses, nd6_prefix_lookup() 53378064Sume * probably returns NULL. However, we cannot always expect the result. 53478064Sume * For example, if we first remove the (only) existing link-local 53578064Sume * address, and then reconfigure another one, the prefix is still 53678064Sume * valid with referring to the old link-local address. 53778064Sume */ 53878064Sume if (nd6_prefix_lookup(&pr0) == NULL) { 53978064Sume if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0) 540120856Sume return (error); 54178064Sume } 54262587Sitojun 54362587Sitojun return 0; 54462587Sitojun} 54562587Sitojun 546171259Sdelphij/* 547171259Sdelphij * ifp - must be IFT_LOOP 548171259Sdelphij */ 54962587Sitojunstatic int 550171259Sdelphijin6_ifattach_loopback(struct ifnet *ifp) 55162587Sitojun{ 55278064Sume struct in6_aliasreq ifra; 55378064Sume int error; 55462587Sitojun 555260860Smelifaro in6_prepare_ifra(&ifra, &in6addr_loopback, &in6mask128); 55678064Sume 55762587Sitojun /* 55862587Sitojun * Always initialize ia_dstaddr (= broadcast address) to loopback 55978064Sume * address. Follows IPv4 practice - see in_ifinit(). 56062587Sitojun */ 56178064Sume ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 56278064Sume ifra.ifra_dstaddr.sin6_family = AF_INET6; 56378064Sume ifra.ifra_dstaddr.sin6_addr = in6addr_loopback; 56462587Sitojun 56578064Sume /* the loopback address should NEVER expire. */ 56678064Sume ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 56778064Sume ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 56862587Sitojun 56978064Sume /* 57095023Ssuz * We are sure that this is a newly assigned address, so we can set 57195023Ssuz * NULL to the 3rd arg. 57278064Sume */ 573151539Ssuz if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) { 574151465Ssuz nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure " 57578064Sume "the loopback address on %s (errno=%d)\n", 576151465Ssuz if_name(ifp), error)); 577120856Sume return (-1); 57862587Sitojun } 57962587Sitojun 58062587Sitojun return 0; 58162587Sitojun} 58262587Sitojun 58362587Sitojun/* 58462587Sitojun * compute NI group address, based on the current hostname setting. 585250251Shrs * see RFC 4620. 58662587Sitojun * 58762587Sitojun * when ifp == NULL, the caller is responsible for filling scopeid. 588250251Shrs * 589250251Shrs * If oldmcprefix == 1, FF02:0:0:0:0:2::/96 is used for NI group address 590250251Shrs * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620. 59162587Sitojun */ 592250251Shrsstatic int 593250251Shrsin6_nigroup0(struct ifnet *ifp, const char *name, int namelen, 594250251Shrs struct in6_addr *in6, int oldmcprefix) 59562587Sitojun{ 596193066Sjamie struct prison *pr; 59762587Sitojun const char *p; 59878064Sume u_char *q; 59962587Sitojun MD5_CTX ctxt; 60062587Sitojun u_int8_t digest[16]; 60162587Sitojun char l; 60278064Sume char n[64]; /* a single label must not exceed 63 chars */ 60362587Sitojun 604192895Sjamie /* 605192895Sjamie * If no name is given and namelen is -1, 606192895Sjamie * we try to do the hostname lookup ourselves. 607192895Sjamie */ 608192895Sjamie if (!name && namelen == -1) { 609193066Sjamie pr = curthread->td_ucred->cr_prison; 610193066Sjamie mtx_lock(&pr->pr_mtx); 611194118Sjamie name = pr->pr_hostname; 612192895Sjamie namelen = strlen(name); 613192895Sjamie } else 614193066Sjamie pr = NULL; 615192895Sjamie if (!name || !namelen) { 616193066Sjamie if (pr != NULL) 617193066Sjamie mtx_unlock(&pr->pr_mtx); 61862587Sitojun return -1; 619192895Sjamie } 62062587Sitojun 62162587Sitojun p = name; 62262587Sitojun while (p && *p && *p != '.' && p - name < namelen) 62362587Sitojun p++; 624192895Sjamie if (p == name || p - name > sizeof(n) - 1) { 625193066Sjamie if (pr != NULL) 626193066Sjamie mtx_unlock(&pr->pr_mtx); 62795023Ssuz return -1; /* label too long */ 628192895Sjamie } 62962587Sitojun l = p - name; 63078064Sume strncpy(n, name, l); 631193066Sjamie if (pr != NULL) 632193066Sjamie mtx_unlock(&pr->pr_mtx); 63378064Sume n[(int)l] = '\0'; 63478064Sume for (q = n; *q; q++) { 63578064Sume if ('A' <= *q && *q <= 'Z') 63678064Sume *q = *q - 'A' + 'a'; 63778064Sume } 63862587Sitojun 639250251Shrs /* generate 16 bytes of pseudo-random value. */ 64062587Sitojun bzero(&ctxt, sizeof(ctxt)); 64162587Sitojun MD5Init(&ctxt); 64262587Sitojun MD5Update(&ctxt, &l, sizeof(l)); 64378064Sume MD5Update(&ctxt, n, l); 64462587Sitojun MD5Final(digest, &ctxt); 64562587Sitojun 64662587Sitojun bzero(in6, sizeof(*in6)); 647151465Ssuz in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL; 64862587Sitojun in6->s6_addr8[11] = 2; 649250251Shrs if (oldmcprefix == 0) { 650250251Shrs in6->s6_addr8[12] = 0xff; 651250251Shrs /* Copy the first 24 bits of 128-bit hash into the address. */ 652250251Shrs bcopy(digest, &in6->s6_addr8[13], 3); 653250251Shrs } else { 654250251Shrs /* Copy the first 32 bits of 128-bit hash into the address. */ 655250251Shrs bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3])); 656250251Shrs } 657148385Sume if (in6_setscope(in6, ifp, NULL)) 658148385Sume return (-1); /* XXX: should not fail */ 65962587Sitojun 66062587Sitojun return 0; 66162587Sitojun} 66262587Sitojun 663250251Shrsint 664250251Shrsin6_nigroup(struct ifnet *ifp, const char *name, int namelen, 665250251Shrs struct in6_addr *in6) 666250251Shrs{ 667250251Shrs 668250251Shrs return (in6_nigroup0(ifp, name, namelen, in6, 0)); 669250251Shrs} 670250251Shrs 671250251Shrsint 672250251Shrsin6_nigroup_oldmcprefix(struct ifnet *ifp, const char *name, int namelen, 673250251Shrs struct in6_addr *in6) 674250251Shrs{ 675250251Shrs 676250251Shrs return (in6_nigroup0(ifp, name, namelen, in6, 1)); 677250251Shrs} 678250251Shrs 67962587Sitojun/* 68062587Sitojun * XXX multiple loopback interface needs more care. for instance, 68162587Sitojun * nodelocal address needs to be configured onto only one of them. 68262587Sitojun * XXX multiple link-local address case 683171259Sdelphij * 684171259Sdelphij * altifp - secondary EUI64 source 68562587Sitojun */ 68662587Sitojunvoid 687171259Sdelphijin6_ifattach(struct ifnet *ifp, struct ifnet *altifp) 68862587Sitojun{ 68962587Sitojun struct in6_ifaddr *ia; 69062587Sitojun struct in6_addr in6; 69162587Sitojun 692253841Shrs if (ifp->if_afdata[AF_INET6] == NULL) 69378064Sume return; 69453541Sshin /* 69562587Sitojun * quirks based on interface type 69653541Sshin */ 69762587Sitojun switch (ifp->if_type) { 69862587Sitojun case IFT_STF: 69962587Sitojun /* 70095023Ssuz * 6to4 interface is a very special kind of beast. 70195023Ssuz * no multicast, no linklocal. RFC2529 specifies how to make 70295023Ssuz * linklocals for 6to4 interface, but there's no use and 70395023Ssuz * it is rather harmful to have one. 70462587Sitojun */ 705252511Shrs ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; 706252511Shrs break; 70762587Sitojun default: 70862587Sitojun break; 70953541Sshin } 71053541Sshin 71153541Sshin /* 71262587Sitojun * usually, we require multicast capability to the interface 71353541Sshin */ 71462587Sitojun if ((ifp->if_flags & IFF_MULTICAST) == 0) { 715151465Ssuz nd6log((LOG_INFO, "in6_ifattach: " 71678064Sume "%s is not multicast capable, IPv6 not enabled\n", 717151465Ssuz if_name(ifp))); 71862587Sitojun return; 71962587Sitojun } 72062587Sitojun 72153541Sshin /* 72278064Sume * assign loopback address for loopback interface. 72378064Sume * XXX multiple loopback interface case. 72453541Sshin */ 72578064Sume if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 726194760Srwatson struct ifaddr *ifa; 727194760Srwatson 72878064Sume in6 = in6addr_loopback; 729194760Srwatson ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &in6); 730194760Srwatson if (ifa == NULL) { 73162587Sitojun if (in6_ifattach_loopback(ifp) != 0) 73262587Sitojun return; 733194760Srwatson } else 734194760Srwatson ifa_free(ifa); 73562587Sitojun } 73653541Sshin 73753541Sshin /* 738120913Sume * assign a link-local address, if there's none. 73953541Sshin */ 740252511Shrs if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && 741197138Shrs ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) { 742197138Shrs int error; 743197138Shrs 74478064Sume ia = in6ifa_ifpforlinklocal(ifp, 0); 74578064Sume if (ia == NULL) { 746197138Shrs error = in6_ifattach_linklocal(ifp, altifp); 747197996Shrs#if 0 748197138Shrs if (error) 749197138Shrs log(LOG_NOTICE, "in6_ifattach_linklocal: " 750197138Shrs "failed to add a link-local addr to %s\n", 751197138Shrs if_name(ifp)); 752197996Shrs#endif 753194760Srwatson } else 754194760Srwatson ifa_free(&ia->ia_ifa); 75553541Sshin } 75653541Sshin 75753541Sshin /* update dynamically. */ 758181803Sbz if (V_in6_maxmtu < ifp->if_mtu) 759181803Sbz V_in6_maxmtu = ifp->if_mtu; 76053541Sshin} 76153541Sshin 76262587Sitojun/* 76362587Sitojun * NOTE: in6_ifdetach() does not support loopback if at this moment. 764302054Sbz * 765302054Sbz * When shutting down a VNET we clean up layers top-down. In that case 766302054Sbz * upper layer protocols (ulp) are cleaned up already and locks are destroyed 767302054Sbz * and we must not call into these cleanup functions anymore, thus purgeulp 768302054Sbz * is set to 0 in that case by in6_ifdetach_destroy(). 769302054Sbz * The normal case of destroying a (cloned) interface still needs to cleanup 770302054Sbz * everything related to the interface and will have purgeulp set to 1. 77162587Sitojun */ 772302054Sbzstatic void 773302054Sbz_in6_ifdetach(struct ifnet *ifp, int purgeulp) 77453541Sshin{ 77562587Sitojun struct ifaddr *ifa, *next; 77653541Sshin 777256258Shrs if (ifp->if_afdata[AF_INET6] == NULL) 778256258Shrs return; 779256258Shrs 780302054Sbz /* 781302054Sbz * Remove neighbor management table. 782302054Sbz * Enabling the nd6_purge will panic on vmove for interfaces on VNET 783302054Sbz * teardown as the IPv6 layer is cleaned up already and the locks 784302054Sbz * are destroyed. 785302054Sbz */ 786302054Sbz if (purgeulp) 787302054Sbz nd6_purge(ifp); 78862587Sitojun 789273858Sae /* 790273858Sae * nuke any of IPv6 addresses we have 791273858Sae * XXX: all addresses should be already removed 792273858Sae */ 793191340Srwatson TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) { 79462587Sitojun if (ifa->ifa_addr->sa_family != AF_INET6) 79562587Sitojun continue; 79678064Sume in6_purgeaddr(ifa); 79762587Sitojun } 798302054Sbz if (purgeulp) { 799302054Sbz in6_pcbpurgeif0(&V_udbinfo, ifp); 800302054Sbz in6_pcbpurgeif0(&V_ulitecbinfo, ifp); 801302054Sbz in6_pcbpurgeif0(&V_ripcbinfo, ifp); 802302054Sbz } 803170613Sbms /* leave from all multicast groups joined */ 804170613Sbms in6_purgemaddrs(ifp); 805120913Sume 80678064Sume /* 80778064Sume * remove neighbor management table. we call it twice just to make 80878064Sume * sure we nuke everything. maybe we need just one call. 80978064Sume * XXX: since the first call did not release addresses, some prefixes 81078064Sume * might remain. We should call nd6_purge() again to release the 81178064Sume * prefixes after removing all addresses above. 81278064Sume * (Or can we just delay calling nd6_purge until at this point?) 81378064Sume */ 814302054Sbz if (purgeulp) 815302054Sbz nd6_purge(ifp); 81653541Sshin} 81778064Sume 818302054Sbzvoid 819302054Sbzin6_ifdetach(struct ifnet *ifp) 820302054Sbz{ 821302054Sbz 822302054Sbz _in6_ifdetach(ifp, 1); 823302054Sbz} 824302054Sbz 825302054Sbzvoid 826302054Sbzin6_ifdetach_destroy(struct ifnet *ifp) 827302054Sbz{ 828302054Sbz 829302054Sbz _in6_ifdetach(ifp, 0); 830302054Sbz} 831302054Sbz 832151539Ssuzint 833171259Sdelphijin6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf, 834171259Sdelphij const u_int8_t *baseid, int generate) 83578064Sume{ 83678064Sume u_int8_t nullbuf[8]; 837121161Sume struct nd_ifinfo *ndi = ND_IFINFO(ifp); 83878064Sume 83978064Sume bzero(nullbuf, sizeof(nullbuf)); 84078064Sume if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) { 84178064Sume /* we've never created a random ID. Create a new one. */ 84278064Sume generate = 1; 84378064Sume } 84478064Sume 84578064Sume if (generate) { 84678064Sume bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1)); 84778064Sume 84878064Sume /* generate_tmp_ifid will update seedn and buf */ 84978064Sume (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1, 850120913Sume ndi->randomid); 85178064Sume } 85278064Sume bcopy(ndi->randomid, retbuf, 8); 853151539Ssuz 854151539Ssuz return (0); 85578064Sume} 85678064Sume 85778064Sumevoid 858191688Szecin6_tmpaddrtimer(void *arg) 85978064Sume{ 860191688Szec CURVNET_SET((struct vnet *) arg); 86178064Sume struct nd_ifinfo *ndi; 86278064Sume u_int8_t nullbuf[8]; 863121161Sume struct ifnet *ifp; 86478064Sume 865181803Sbz callout_reset(&V_in6_tmpaddrtimer_ch, 866181803Sbz (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor - 867191688Szec V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet); 86878064Sume 86978064Sume bzero(nullbuf, sizeof(nullbuf)); 870274345Sglebius TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 871253950Shrs if (ifp->if_afdata[AF_INET6] == NULL) 872253950Shrs continue; 873121161Sume ndi = ND_IFINFO(ifp); 87478064Sume if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { 87578064Sume /* 87678064Sume * We've been generating a random ID on this interface. 87778064Sume * Create a new one. 87878064Sume */ 87978064Sume (void)generate_tmp_ifid(ndi->randomseed0, 880120913Sume ndi->randomseed1, ndi->randomid); 88178064Sume } 88278064Sume } 88378064Sume 884191688Szec CURVNET_RESTORE(); 88578064Sume} 886170613Sbms 887170613Sbmsstatic void 888171259Sdelphijin6_purgemaddrs(struct ifnet *ifp) 889170613Sbms{ 890191672Sbms LIST_HEAD(,in6_multi) purgeinms; 891191672Sbms struct in6_multi *inm, *tinm; 892191672Sbms struct ifmultiaddr *ifma; 893170613Sbms 894191672Sbms LIST_INIT(&purgeinms); 895191672Sbms IN6_MULTI_LOCK(); 896191672Sbms 897191672Sbms /* 898191672Sbms * Extract list of in6_multi associated with the detaching ifp 899191672Sbms * which the PF_INET6 layer is about to release. 900191672Sbms * We need to do this as IF_ADDR_LOCK() may be re-acquired 901191672Sbms * by code further down. 902191672Sbms */ 903229621Sjhb IF_ADDR_RLOCK(ifp); 904191672Sbms TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 905191672Sbms if (ifma->ifma_addr->sa_family != AF_INET6 || 906191672Sbms ifma->ifma_protospec == NULL) 907191672Sbms continue; 908191672Sbms inm = (struct in6_multi *)ifma->ifma_protospec; 909191672Sbms LIST_INSERT_HEAD(&purgeinms, inm, in6m_entry); 910170613Sbms } 911229621Sjhb IF_ADDR_RUNLOCK(ifp); 912191672Sbms 913191672Sbms LIST_FOREACH_SAFE(inm, &purgeinms, in6m_entry, tinm) { 914191672Sbms LIST_REMOVE(inm, in6m_entry); 915191672Sbms in6m_release_locked(inm); 916191672Sbms } 917191672Sbms mld_ifdetach(ifp); 918191672Sbms 919191672Sbms IN6_MULTI_UNLOCK(); 920170613Sbms} 921297192Sbz 922297192Sbzvoid 923297192Sbzin6_ifattach_destroy(void) 924297192Sbz{ 925297192Sbz 926297192Sbz callout_drain(&V_in6_tmpaddrtimer_ch); 927297192Sbz} 928297192Sbz 929297192Sbzstatic void 930297192Sbzin6_ifattach_init(void *dummy) 931297192Sbz{ 932297192Sbz 933297192Sbz /* Timer for regeneranation of temporary addresses randomize ID. */ 934297192Sbz callout_init(&V_in6_tmpaddrtimer_ch, 0); 935297192Sbz callout_reset(&V_in6_tmpaddrtimer_ch, 936297192Sbz (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor - 937297192Sbz V_ip6_temp_regen_advance) * hz, 938297192Sbz in6_tmpaddrtimer, curvnet); 939297192Sbz} 940297192Sbz 941297192Sbz/* 942297192Sbz * Cheat. 943297192Sbz * This must be after route_init(), which is now SI_ORDER_THIRD. 944297192Sbz */ 945297192SbzSYSINIT(in6_ifattach_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, 946297192Sbz in6_ifattach_init, NULL); 947