in6_ifattach.c revision 274345
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: head/sys/netinet6/in6_ifattach.c 274345 2014-11-10 15:56:30Z glebius $"); 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> 42196019Srwatson#include <sys/proc.h> 4378064Sume#include <sys/syslog.h> 4453541Sshin#include <sys/md5.h> 4553541Sshin 4653541Sshin#include <net/if.h> 47257176Sglebius#include <net/if_var.h> 4853541Sshin#include <net/if_dl.h> 4953541Sshin#include <net/if_types.h> 5053541Sshin#include <net/route.h> 51185571Sbz#include <net/vnet.h> 5253541Sshin 5353541Sshin#include <netinet/in.h> 5453541Sshin#include <netinet/in_var.h> 5553541Sshin#include <netinet/if_ether.h> 5681127Sume#include <netinet/in_pcb.h> 57195699Srwatson#include <netinet/ip_var.h> 58195699Srwatson#include <netinet/udp.h> 59195699Srwatson#include <netinet/udp_var.h> 6053541Sshin 6162587Sitojun#include <netinet/ip6.h> 6253541Sshin#include <netinet6/ip6_var.h> 6378064Sume#include <netinet6/in6_var.h> 6481127Sume#include <netinet6/in6_pcb.h> 6553541Sshin#include <netinet6/in6_ifattach.h> 6653541Sshin#include <netinet6/ip6_var.h> 6753541Sshin#include <netinet6/nd6.h> 68191672Sbms#include <netinet6/mld6_var.h> 6962587Sitojun#include <netinet6/scope6_var.h> 7053541Sshin 71207369SbzVNET_DEFINE(unsigned long, in6_maxmtu) = 0; 72207369Sbz 73207369Sbz#ifdef IP6_AUTO_LINKLOCAL 74207369SbzVNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL; 75207369Sbz#else 76207369SbzVNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */ 77207369Sbz#endif 78207369Sbz 79195699SrwatsonVNET_DEFINE(struct callout, in6_tmpaddrtimer_ch); 80195727Srwatson#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch) 81195699Srwatson 82195699SrwatsonVNET_DECLARE(struct inpcbinfo, ripcbinfo); 83195727Srwatson#define V_ripcbinfo VNET(ripcbinfo) 84195699Srwatson 85175162Sobrienstatic int get_rand_ifid(struct ifnet *, struct in6_addr *); 86175162Sobrienstatic int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *); 87175162Sobrienstatic int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *); 88175162Sobrienstatic int in6_ifattach_linklocal(struct ifnet *, struct ifnet *); 89175162Sobrienstatic int in6_ifattach_loopback(struct ifnet *); 90175162Sobrienstatic void in6_purgemaddrs(struct ifnet *); 9153541Sshin 9262587Sitojun#define EUI64_GBIT 0x01 9362587Sitojun#define EUI64_UBIT 0x02 9462587Sitojun#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0) 9562587Sitojun#define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT) 9662587Sitojun#define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6)) 9762587Sitojun#define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT) 9862587Sitojun#define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6)) 9953541Sshin 10062587Sitojun#define IFID_LOCAL(in6) (!EUI64_LOCAL(in6)) 10162587Sitojun#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6)) 10253541Sshin 10353541Sshin/* 10453541Sshin * Generate a last-resort interface identifier, when the machine has no 10553541Sshin * IEEE802/EUI64 address sources. 10662587Sitojun * The goal here is to get an interface identifier that is 10762587Sitojun * (1) random enough and (2) does not change across reboot. 10862587Sitojun * We currently use MD5(hostname) for it. 109171259Sdelphij * 110171259Sdelphij * in6 - upper 64bits are preserved 11153541Sshin */ 11253541Sshinstatic int 113171259Sdelphijget_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) 11453541Sshin{ 11553541Sshin MD5_CTX ctxt; 116193066Sjamie struct prison *pr; 11753541Sshin u_int8_t digest[16]; 118180291Srwatson int hostnamelen; 11953541Sshin 120193066Sjamie pr = curthread->td_ucred->cr_prison; 121193066Sjamie mtx_lock(&pr->pr_mtx); 122194118Sjamie hostnamelen = strlen(pr->pr_hostname); 12362587Sitojun#if 0 12462587Sitojun /* we need at least several letters as seed for ifid */ 125193066Sjamie if (hostnamelen < 3) { 126193066Sjamie mtx_unlock(&pr->pr_mtx); 12762587Sitojun return -1; 128193066Sjamie } 12962587Sitojun#endif 13062587Sitojun 13162587Sitojun /* generate 8 bytes of pseudo-random value. */ 13253541Sshin bzero(&ctxt, sizeof(ctxt)); 13353541Sshin MD5Init(&ctxt); 134194118Sjamie MD5Update(&ctxt, pr->pr_hostname, hostnamelen); 135193066Sjamie mtx_unlock(&pr->pr_mtx); 13653541Sshin MD5Final(digest, &ctxt); 13753541Sshin 13862587Sitojun /* assumes sizeof(digest) > sizeof(ifid) */ 13962587Sitojun bcopy(digest, &in6->s6_addr[8], 8); 14053541Sshin 14153541Sshin /* make sure to set "u" bit to local, and "g" bit to individual. */ 14262587Sitojun in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ 14362587Sitojun in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ 14453541Sshin 14562587Sitojun /* convert EUI64 into IPv6 interface identifier */ 14662587Sitojun EUI64_TO_IFID(in6); 14762587Sitojun 14853541Sshin return 0; 14953541Sshin} 15053541Sshin 15178064Sumestatic int 152171259Sdelphijgenerate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret) 15378064Sume{ 15478064Sume MD5_CTX ctxt; 15578064Sume u_int8_t seed[16], digest[16], nullbuf[8]; 15678064Sume u_int32_t val32; 15778064Sume 158171259Sdelphij /* If there's no history, start with a random seed. */ 15978064Sume bzero(nullbuf, sizeof(nullbuf)); 16078064Sume if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) { 16178064Sume int i; 16278064Sume 16378064Sume for (i = 0; i < 2; i++) { 164121807Sume val32 = arc4random(); 16578064Sume bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32)); 16678064Sume } 167120913Sume } else 16878064Sume bcopy(seed0, seed, 8); 16978064Sume 17078064Sume /* copy the right-most 64-bits of the given address */ 17178064Sume /* XXX assumption on the size of IFID */ 17278064Sume bcopy(seed1, &seed[8], 8); 17378064Sume 17478064Sume if (0) { /* for debugging purposes only */ 17578064Sume int i; 17678064Sume 17778064Sume printf("generate_tmp_ifid: new randomized ID from: "); 17878064Sume for (i = 0; i < 16; i++) 17978064Sume printf("%02x", seed[i]); 18078064Sume printf(" "); 18178064Sume } 18278064Sume 18378064Sume /* generate 16 bytes of pseudo-random value. */ 18478064Sume bzero(&ctxt, sizeof(ctxt)); 18578064Sume MD5Init(&ctxt); 18678064Sume MD5Update(&ctxt, seed, sizeof(seed)); 18778064Sume MD5Final(digest, &ctxt); 18878064Sume 18978064Sume /* 19078064Sume * RFC 3041 3.2.1. (3) 19178064Sume * Take the left-most 64-bits of the MD5 digest and set bit 6 (the 19278064Sume * left-most bit is numbered 0) to zero. 19378064Sume */ 19478064Sume bcopy(digest, ret, 8); 19578064Sume ret[0] &= ~EUI64_UBIT; 19678064Sume 19778064Sume /* 19878064Sume * XXX: we'd like to ensure that the generated value is not zero 19978064Sume * for simplicity. If the caclculated digest happens to be zero, 20078064Sume * use a random non-zero value as the last resort. 20178064Sume */ 20278064Sume if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) { 203151465Ssuz nd6log((LOG_INFO, 204151465Ssuz "generate_tmp_ifid: computed MD5 value is zero.\n")); 20578064Sume 206121807Sume val32 = arc4random(); 20778064Sume val32 = 1 + (val32 % (0xffffffff - 1)); 20878064Sume } 20978064Sume 21078064Sume /* 21178064Sume * RFC 3041 3.2.1. (4) 21278064Sume * Take the rightmost 64-bits of the MD5 digest and save them in 21378064Sume * stable storage as the history value to be used in the next 214120913Sume * iteration of the algorithm. 21578064Sume */ 21678064Sume bcopy(&digest[8], seed0, 8); 21778064Sume 21878064Sume if (0) { /* for debugging purposes only */ 21978064Sume int i; 22078064Sume 22178064Sume printf("to: "); 22278064Sume for (i = 0; i < 16; i++) 22378064Sume printf("%02x", digest[i]); 22478064Sume printf("\n"); 22578064Sume } 22678064Sume 22778064Sume return 0; 22878064Sume} 22978064Sume 23053541Sshin/* 23162587Sitojun * Get interface identifier for the specified interface. 23262587Sitojun * XXX assumes single sockaddr_dl (AF_LINK address) per an interface 233171259Sdelphij * 234171259Sdelphij * in6 - upper 64bits are preserved 23553541Sshin */ 236151477Ssuzint 237171259Sdelphijin6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) 23853541Sshin{ 23953541Sshin struct ifaddr *ifa; 24053541Sshin struct sockaddr_dl *sdl; 24162587Sitojun u_int8_t *addr; 24262587Sitojun size_t addrlen; 24362587Sitojun static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 24462587Sitojun static u_int8_t allone[8] = 24562587Sitojun { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 24653541Sshin 247229621Sjhb IF_ADDR_RLOCK(ifp); 248191340Srwatson TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 24962587Sitojun if (ifa->ifa_addr->sa_family != AF_LINK) 25053541Sshin continue; 25162587Sitojun sdl = (struct sockaddr_dl *)ifa->ifa_addr; 25262587Sitojun if (sdl == NULL) 25362587Sitojun continue; 25462587Sitojun if (sdl->sdl_alen == 0) 25562587Sitojun continue; 25662587Sitojun 25762587Sitojun goto found; 25853541Sshin } 259229621Sjhb IF_ADDR_RUNLOCK(ifp); 26053541Sshin 26162587Sitojun return -1; 26262587Sitojun 26353541Sshinfound: 264194760Srwatson IF_ADDR_LOCK_ASSERT(ifp); 26562587Sitojun addr = LLADDR(sdl); 26662587Sitojun addrlen = sdl->sdl_alen; 26753541Sshin 26862587Sitojun /* get EUI64 */ 26962587Sitojun switch (ifp->if_type) { 270252511Shrs case IFT_BRIDGE: 27162587Sitojun case IFT_ETHER: 272216650Sjhay case IFT_L2VLAN: 27362587Sitojun case IFT_FDDI: 274120049Smdodd case IFT_ISO88025: 27562587Sitojun case IFT_ATM: 27678064Sume case IFT_IEEE1394: 27778064Sume#ifdef IFT_IEEE80211 27878064Sume case IFT_IEEE80211: 27978064Sume#endif 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#ifdef IFT_STF 34262587Sitojun case IFT_STF: 34353541Sshin#endif 34462587Sitojun /* 34578064Sume * RFC2893 says: "SHOULD use IPv4 address as ifid source". 34662587Sitojun * however, IPv4 address is not very suitable as unique 34762587Sitojun * identifier source (can be renumbered). 34862587Sitojun * we don't do this. 34962587Sitojun */ 350229621Sjhb IF_ADDR_RUNLOCK(ifp); 35162587Sitojun return -1; 35262587Sitojun 35362587Sitojun default: 354229621Sjhb IF_ADDR_RUNLOCK(ifp); 35562587Sitojun return -1; 35653541Sshin } 35762587Sitojun 35862587Sitojun /* sanity check: g bit must not indicate "group" */ 359191337Srwatson if (EUI64_GROUP(in6)) { 360229621Sjhb IF_ADDR_RUNLOCK(ifp); 36162587Sitojun return -1; 362191337Srwatson } 36362587Sitojun 36462587Sitojun /* convert EUI64 into IPv6 interface identifier */ 36562587Sitojun EUI64_TO_IFID(in6); 36662587Sitojun 36762587Sitojun /* 36862587Sitojun * sanity check: ifid must not be all zero, avoid conflict with 36962587Sitojun * subnet router anycast 37062587Sitojun */ 37162587Sitojun if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 && 37262587Sitojun bcmp(&in6->s6_addr[9], allzero, 7) == 0) { 373229621Sjhb IF_ADDR_RUNLOCK(ifp); 37462587Sitojun return -1; 37562587Sitojun } 37662587Sitojun 377229621Sjhb IF_ADDR_RUNLOCK(ifp); 37862587Sitojun return 0; 37953541Sshin} 38053541Sshin 38153541Sshin/* 38262587Sitojun * Get interface identifier for the specified interface. If it is not 38362587Sitojun * available on ifp0, borrow interface identifier from other information 38462587Sitojun * sources. 385171259Sdelphij * 386171259Sdelphij * altifp - secondary EUI64 source 38753541Sshin */ 38862587Sitojunstatic int 389171259Sdelphijget_ifid(struct ifnet *ifp0, struct ifnet *altifp, 390171259Sdelphij struct in6_addr *in6) 39153541Sshin{ 39253541Sshin struct ifnet *ifp; 39353541Sshin 39462587Sitojun /* first, try to get it from the interface itself */ 395151477Ssuz if (in6_get_hw_ifid(ifp0, in6) == 0) { 39678064Sume nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n", 39778064Sume if_name(ifp0))); 39862587Sitojun goto success; 39962587Sitojun } 40053541Sshin 40162587Sitojun /* try secondary EUI64 source. this basically is for ATM PVC */ 402151477Ssuz if (altifp && in6_get_hw_ifid(altifp, in6) == 0) { 40378064Sume nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", 40478064Sume if_name(ifp0), if_name(altifp))); 40562587Sitojun goto success; 40662587Sitojun } 40762587Sitojun 40862587Sitojun /* next, try to get it from some other hardware interface */ 409196481Srwatson IFNET_RLOCK_NOSLEEP(); 410274345Sglebius TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 41162587Sitojun if (ifp == ifp0) 41262587Sitojun continue; 413151477Ssuz if (in6_get_hw_ifid(ifp, in6) != 0) 41462587Sitojun continue; 41562587Sitojun 41662587Sitojun /* 41762587Sitojun * to borrow ifid from other interface, ifid needs to be 41862587Sitojun * globally unique 41962587Sitojun */ 42062587Sitojun if (IFID_UNIVERSAL(in6)) { 42178064Sume nd6log((LOG_DEBUG, 42278064Sume "%s: borrow interface identifier from %s\n", 42378064Sume if_name(ifp0), if_name(ifp))); 424196481Srwatson IFNET_RUNLOCK_NOSLEEP(); 42562587Sitojun goto success; 42662587Sitojun } 42762587Sitojun } 428196481Srwatson IFNET_RUNLOCK_NOSLEEP(); 42962587Sitojun 43062587Sitojun /* last resort: get from random number source */ 43162587Sitojun if (get_rand_ifid(ifp, in6) == 0) { 43278064Sume nd6log((LOG_DEBUG, 43378064Sume "%s: interface identifier generated by random number\n", 43478064Sume if_name(ifp0))); 43562587Sitojun goto success; 43662587Sitojun } 43762587Sitojun 43866504Sitojun printf("%s: failed to get interface identifier\n", if_name(ifp0)); 43962587Sitojun return -1; 44062587Sitojun 44162587Sitojunsuccess: 442120913Sume nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 443120913Sume if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10], 444120913Sume in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13], 445120913Sume in6->s6_addr[14], in6->s6_addr[15])); 44662587Sitojun return 0; 44762587Sitojun} 44862587Sitojun 449171259Sdelphij/* 450171259Sdelphij * altifp - secondary EUI64 source 451171259Sdelphij */ 45262587Sitojunstatic int 453171259Sdelphijin6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) 45478064Sume{ 45562587Sitojun struct in6_ifaddr *ia; 45678064Sume struct in6_aliasreq ifra; 457151539Ssuz struct nd_prefixctl pr0; 458260458Smelifaro int error; 45962587Sitojun 46062587Sitojun /* 46178064Sume * configure link-local address. 46262587Sitojun */ 463260860Smelifaro in6_prepare_ifra(&ifra, NULL, &in6mask64); 46462587Sitojun 465148385Sume ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000); 46678064Sume ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; 46778064Sume if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 46878064Sume ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; 46978064Sume ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); 47078064Sume } else { 47178064Sume if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) { 47278064Sume nd6log((LOG_ERR, 47378064Sume "%s: no ifid available\n", if_name(ifp))); 474120913Sume return (-1); 47562587Sitojun } 47662587Sitojun } 477148385Sume if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL)) 478148385Sume return (-1); 47962587Sitojun 48078064Sume /* link-local addresses should NEVER expire. */ 48178064Sume ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 48278064Sume ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 48362587Sitojun 48478064Sume /* 48578064Sume * Now call in6_update_ifa() to do a bunch of procedures to configure 486151465Ssuz * a link-local address. We can set the 3rd argument to NULL, because 48795023Ssuz * we know there's no other link-local address on the interface 48895023Ssuz * and therefore we are adding one (instead of updating one). 48978064Sume */ 490151539Ssuz if ((error = in6_update_ifa(ifp, &ifra, NULL, 491151539Ssuz IN6_IFAUPDATE_DADDELAY)) != 0) { 49262587Sitojun /* 49378064Sume * XXX: When the interface does not support IPv6, this call 49478064Sume * would fail in the SIOCSIFADDR ioctl. I believe the 49578064Sume * notification is rather confusing in this case, so just 496120913Sume * suppress it. (jinmei@kame.net 20010130) 49762587Sitojun */ 49878064Sume if (error != EAFNOSUPPORT) 499151465Ssuz nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to " 50078064Sume "configure a link-local address on %s " 50178064Sume "(errno=%d)\n", 502151465Ssuz if_name(ifp), error)); 503120856Sume return (-1); 50462587Sitojun } 50562587Sitojun 50678064Sume ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */ 507229546Sbz KASSERT(ia != NULL, ("%s: ia == NULL, ifp=%p", __func__, ifp)); 508229546Sbz 509194760Srwatson ifa_free(&ia->ia_ifa); 51053541Sshin 51178064Sume /* 512120913Sume * Make the link-local prefix (fe80::%link/64) as on-link. 51378064Sume * Since we'd like to manage prefixes separately from addresses, 51478064Sume * we make an ND6 prefix structure for the link-local prefix, 51578064Sume * and add it to the prefix list as a never-expire prefix. 51678064Sume * XXX: this change might affect some existing code base... 51778064Sume */ 51878064Sume bzero(&pr0, sizeof(pr0)); 51978064Sume pr0.ndpr_ifp = ifp; 52078064Sume /* this should be 64 at this moment. */ 52178064Sume pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL); 52278064Sume pr0.ndpr_prefix = ifra.ifra_addr; 52378064Sume /* apply the mask for safety. (nd6_prelist_add will apply it again) */ 524260458Smelifaro IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, &in6mask64); 52578064Sume /* 52678064Sume * Initialize parameters. The link-local prefix must always be 52778064Sume * on-link, and its lifetimes never expire. 52878064Sume */ 52978064Sume pr0.ndpr_raf_onlink = 1; 53078064Sume pr0.ndpr_raf_auto = 1; /* probably meaningless */ 53178064Sume pr0.ndpr_vltime = ND6_INFINITE_LIFETIME; 53278064Sume pr0.ndpr_pltime = ND6_INFINITE_LIFETIME; 53378064Sume /* 53478064Sume * Since there is no other link-local addresses, nd6_prefix_lookup() 53578064Sume * probably returns NULL. However, we cannot always expect the result. 53678064Sume * For example, if we first remove the (only) existing link-local 53778064Sume * address, and then reconfigure another one, the prefix is still 53878064Sume * valid with referring to the old link-local address. 53978064Sume */ 54078064Sume if (nd6_prefix_lookup(&pr0) == NULL) { 54178064Sume if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0) 542120856Sume return (error); 54378064Sume } 54462587Sitojun 54562587Sitojun return 0; 54662587Sitojun} 54762587Sitojun 548171259Sdelphij/* 549171259Sdelphij * ifp - must be IFT_LOOP 550171259Sdelphij */ 55162587Sitojunstatic int 552171259Sdelphijin6_ifattach_loopback(struct ifnet *ifp) 55362587Sitojun{ 55478064Sume struct in6_aliasreq ifra; 55578064Sume int error; 55662587Sitojun 557260860Smelifaro in6_prepare_ifra(&ifra, &in6addr_loopback, &in6mask128); 55878064Sume 55962587Sitojun /* 56062587Sitojun * Always initialize ia_dstaddr (= broadcast address) to loopback 56178064Sume * address. Follows IPv4 practice - see in_ifinit(). 56262587Sitojun */ 56378064Sume ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); 56478064Sume ifra.ifra_dstaddr.sin6_family = AF_INET6; 56578064Sume ifra.ifra_dstaddr.sin6_addr = in6addr_loopback; 56662587Sitojun 56778064Sume /* the loopback address should NEVER expire. */ 56878064Sume ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 56978064Sume ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 57062587Sitojun 57195023Ssuz /* we don't need to perform DAD on loopback interfaces. */ 57278064Sume ifra.ifra_flags |= IN6_IFF_NODAD; 57378064Sume 57478064Sume /* skip registration to the prefix list. XXX should be temporary. */ 57578064Sume ifra.ifra_flags |= IN6_IFF_NOPFX; 57678064Sume 57778064Sume /* 57895023Ssuz * We are sure that this is a newly assigned address, so we can set 57995023Ssuz * NULL to the 3rd arg. 58078064Sume */ 581151539Ssuz if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) { 582151465Ssuz nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure " 58378064Sume "the loopback address on %s (errno=%d)\n", 584151465Ssuz if_name(ifp), error)); 585120856Sume return (-1); 58662587Sitojun } 58762587Sitojun 58862587Sitojun return 0; 58962587Sitojun} 59062587Sitojun 59162587Sitojun/* 59262587Sitojun * compute NI group address, based on the current hostname setting. 593250251Shrs * see RFC 4620. 59462587Sitojun * 59562587Sitojun * when ifp == NULL, the caller is responsible for filling scopeid. 596250251Shrs * 597250251Shrs * If oldmcprefix == 1, FF02:0:0:0:0:2::/96 is used for NI group address 598250251Shrs * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620. 59962587Sitojun */ 600250251Shrsstatic int 601250251Shrsin6_nigroup0(struct ifnet *ifp, const char *name, int namelen, 602250251Shrs struct in6_addr *in6, int oldmcprefix) 60362587Sitojun{ 604193066Sjamie struct prison *pr; 60562587Sitojun const char *p; 60678064Sume u_char *q; 60762587Sitojun MD5_CTX ctxt; 60862587Sitojun u_int8_t digest[16]; 60962587Sitojun char l; 61078064Sume char n[64]; /* a single label must not exceed 63 chars */ 61162587Sitojun 612192895Sjamie /* 613192895Sjamie * If no name is given and namelen is -1, 614192895Sjamie * we try to do the hostname lookup ourselves. 615192895Sjamie */ 616192895Sjamie if (!name && namelen == -1) { 617193066Sjamie pr = curthread->td_ucred->cr_prison; 618193066Sjamie mtx_lock(&pr->pr_mtx); 619194118Sjamie name = pr->pr_hostname; 620192895Sjamie namelen = strlen(name); 621192895Sjamie } else 622193066Sjamie pr = NULL; 623192895Sjamie if (!name || !namelen) { 624193066Sjamie if (pr != NULL) 625193066Sjamie mtx_unlock(&pr->pr_mtx); 62662587Sitojun return -1; 627192895Sjamie } 62862587Sitojun 62962587Sitojun p = name; 63062587Sitojun while (p && *p && *p != '.' && p - name < namelen) 63162587Sitojun p++; 632192895Sjamie if (p == name || p - name > sizeof(n) - 1) { 633193066Sjamie if (pr != NULL) 634193066Sjamie mtx_unlock(&pr->pr_mtx); 63595023Ssuz return -1; /* label too long */ 636192895Sjamie } 63762587Sitojun l = p - name; 63878064Sume strncpy(n, name, l); 639193066Sjamie if (pr != NULL) 640193066Sjamie mtx_unlock(&pr->pr_mtx); 64178064Sume n[(int)l] = '\0'; 64278064Sume for (q = n; *q; q++) { 64378064Sume if ('A' <= *q && *q <= 'Z') 64478064Sume *q = *q - 'A' + 'a'; 64578064Sume } 64662587Sitojun 647250251Shrs /* generate 16 bytes of pseudo-random value. */ 64862587Sitojun bzero(&ctxt, sizeof(ctxt)); 64962587Sitojun MD5Init(&ctxt); 65062587Sitojun MD5Update(&ctxt, &l, sizeof(l)); 65178064Sume MD5Update(&ctxt, n, l); 65262587Sitojun MD5Final(digest, &ctxt); 65362587Sitojun 65462587Sitojun bzero(in6, sizeof(*in6)); 655151465Ssuz in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL; 65662587Sitojun in6->s6_addr8[11] = 2; 657250251Shrs if (oldmcprefix == 0) { 658250251Shrs in6->s6_addr8[12] = 0xff; 659250251Shrs /* Copy the first 24 bits of 128-bit hash into the address. */ 660250251Shrs bcopy(digest, &in6->s6_addr8[13], 3); 661250251Shrs } else { 662250251Shrs /* Copy the first 32 bits of 128-bit hash into the address. */ 663250251Shrs bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3])); 664250251Shrs } 665148385Sume if (in6_setscope(in6, ifp, NULL)) 666148385Sume return (-1); /* XXX: should not fail */ 66762587Sitojun 66862587Sitojun return 0; 66962587Sitojun} 67062587Sitojun 671250251Shrsint 672250251Shrsin6_nigroup(struct ifnet *ifp, const char *name, int namelen, 673250251Shrs struct in6_addr *in6) 674250251Shrs{ 675250251Shrs 676250251Shrs return (in6_nigroup0(ifp, name, namelen, in6, 0)); 677250251Shrs} 678250251Shrs 679250251Shrsint 680250251Shrsin6_nigroup_oldmcprefix(struct ifnet *ifp, const char *name, int namelen, 681250251Shrs struct in6_addr *in6) 682250251Shrs{ 683250251Shrs 684250251Shrs return (in6_nigroup0(ifp, name, namelen, in6, 1)); 685250251Shrs} 686250251Shrs 68762587Sitojun/* 68862587Sitojun * XXX multiple loopback interface needs more care. for instance, 68962587Sitojun * nodelocal address needs to be configured onto only one of them. 69062587Sitojun * XXX multiple link-local address case 691171259Sdelphij * 692171259Sdelphij * altifp - secondary EUI64 source 69362587Sitojun */ 69462587Sitojunvoid 695171259Sdelphijin6_ifattach(struct ifnet *ifp, struct ifnet *altifp) 69662587Sitojun{ 69762587Sitojun struct in6_ifaddr *ia; 69862587Sitojun struct in6_addr in6; 69962587Sitojun 700253841Shrs if (ifp->if_afdata[AF_INET6] == NULL) 70178064Sume return; 70253541Sshin /* 70362587Sitojun * quirks based on interface type 70453541Sshin */ 70562587Sitojun switch (ifp->if_type) { 70662587Sitojun case IFT_STF: 70762587Sitojun /* 70895023Ssuz * 6to4 interface is a very special kind of beast. 70995023Ssuz * no multicast, no linklocal. RFC2529 specifies how to make 71095023Ssuz * linklocals for 6to4 interface, but there's no use and 71195023Ssuz * it is rather harmful to have one. 71262587Sitojun */ 713252511Shrs ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; 714252511Shrs break; 71562587Sitojun default: 71662587Sitojun break; 71753541Sshin } 71853541Sshin 71953541Sshin /* 72062587Sitojun * usually, we require multicast capability to the interface 72153541Sshin */ 72262587Sitojun if ((ifp->if_flags & IFF_MULTICAST) == 0) { 723151465Ssuz nd6log((LOG_INFO, "in6_ifattach: " 72478064Sume "%s is not multicast capable, IPv6 not enabled\n", 725151465Ssuz if_name(ifp))); 72662587Sitojun return; 72762587Sitojun } 72862587Sitojun 72953541Sshin /* 73078064Sume * assign loopback address for loopback interface. 73178064Sume * XXX multiple loopback interface case. 73253541Sshin */ 73378064Sume if ((ifp->if_flags & IFF_LOOPBACK) != 0) { 734194760Srwatson struct ifaddr *ifa; 735194760Srwatson 73678064Sume in6 = in6addr_loopback; 737194760Srwatson ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &in6); 738194760Srwatson if (ifa == NULL) { 73962587Sitojun if (in6_ifattach_loopback(ifp) != 0) 74062587Sitojun return; 741194760Srwatson } else 742194760Srwatson ifa_free(ifa); 74362587Sitojun } 74453541Sshin 74553541Sshin /* 746120913Sume * assign a link-local address, if there's none. 74753541Sshin */ 748252511Shrs if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && 749197138Shrs ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) { 750197138Shrs int error; 751197138Shrs 75278064Sume ia = in6ifa_ifpforlinklocal(ifp, 0); 75378064Sume if (ia == NULL) { 754197138Shrs error = in6_ifattach_linklocal(ifp, altifp); 755197996Shrs#if 0 756197138Shrs if (error) 757197138Shrs log(LOG_NOTICE, "in6_ifattach_linklocal: " 758197138Shrs "failed to add a link-local addr to %s\n", 759197138Shrs if_name(ifp)); 760197996Shrs#endif 761194760Srwatson } else 762194760Srwatson ifa_free(&ia->ia_ifa); 76353541Sshin } 76453541Sshin 76553541Sshin /* update dynamically. */ 766181803Sbz if (V_in6_maxmtu < ifp->if_mtu) 767181803Sbz V_in6_maxmtu = ifp->if_mtu; 76853541Sshin} 76953541Sshin 77062587Sitojun/* 77162587Sitojun * NOTE: in6_ifdetach() does not support loopback if at this moment. 77278064Sume * We don't need this function in bsdi, because interfaces are never removed 77378064Sume * from the ifnet list in bsdi. 77462587Sitojun */ 77553541Sshinvoid 776171259Sdelphijin6_ifdetach(struct ifnet *ifp) 77753541Sshin{ 77862587Sitojun struct ifaddr *ifa, *next; 77953541Sshin 780256258Shrs if (ifp->if_afdata[AF_INET6] == NULL) 781256258Shrs return; 782256258Shrs 78362587Sitojun /* remove neighbor management table */ 78462587Sitojun nd6_purge(ifp); 78562587Sitojun 786273858Sae /* 787273858Sae * nuke any of IPv6 addresses we have 788273858Sae * XXX: all addresses should be already removed 789273858Sae */ 790191340Srwatson TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) { 79162587Sitojun if (ifa->ifa_addr->sa_family != AF_INET6) 79262587Sitojun continue; 79378064Sume in6_purgeaddr(ifa); 79462587Sitojun } 795181803Sbz in6_pcbpurgeif0(&V_udbinfo, ifp); 796264212Skevlo in6_pcbpurgeif0(&V_ulitecbinfo, ifp); 797181803Sbz in6_pcbpurgeif0(&V_ripcbinfo, ifp); 798170613Sbms /* leave from all multicast groups joined */ 799170613Sbms in6_purgemaddrs(ifp); 800120913Sume 80178064Sume /* 80278064Sume * remove neighbor management table. we call it twice just to make 80378064Sume * sure we nuke everything. maybe we need just one call. 80478064Sume * XXX: since the first call did not release addresses, some prefixes 80578064Sume * might remain. We should call nd6_purge() again to release the 80678064Sume * prefixes after removing all addresses above. 80778064Sume * (Or can we just delay calling nd6_purge until at this point?) 80878064Sume */ 80962587Sitojun nd6_purge(ifp); 81053541Sshin} 81178064Sume 812151539Ssuzint 813171259Sdelphijin6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf, 814171259Sdelphij const u_int8_t *baseid, int generate) 81578064Sume{ 81678064Sume u_int8_t nullbuf[8]; 817121161Sume struct nd_ifinfo *ndi = ND_IFINFO(ifp); 81878064Sume 81978064Sume bzero(nullbuf, sizeof(nullbuf)); 82078064Sume if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) { 82178064Sume /* we've never created a random ID. Create a new one. */ 82278064Sume generate = 1; 82378064Sume } 82478064Sume 82578064Sume if (generate) { 82678064Sume bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1)); 82778064Sume 82878064Sume /* generate_tmp_ifid will update seedn and buf */ 82978064Sume (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1, 830120913Sume ndi->randomid); 83178064Sume } 83278064Sume bcopy(ndi->randomid, retbuf, 8); 833151539Ssuz 834151539Ssuz return (0); 83578064Sume} 83678064Sume 83778064Sumevoid 838191688Szecin6_tmpaddrtimer(void *arg) 83978064Sume{ 840191688Szec CURVNET_SET((struct vnet *) arg); 84178064Sume struct nd_ifinfo *ndi; 84278064Sume u_int8_t nullbuf[8]; 843121161Sume struct ifnet *ifp; 84478064Sume 845181803Sbz callout_reset(&V_in6_tmpaddrtimer_ch, 846181803Sbz (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor - 847191688Szec V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet); 84878064Sume 84978064Sume bzero(nullbuf, sizeof(nullbuf)); 850274345Sglebius TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 851253950Shrs if (ifp->if_afdata[AF_INET6] == NULL) 852253950Shrs continue; 853121161Sume ndi = ND_IFINFO(ifp); 85478064Sume if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { 85578064Sume /* 85678064Sume * We've been generating a random ID on this interface. 85778064Sume * Create a new one. 85878064Sume */ 85978064Sume (void)generate_tmp_ifid(ndi->randomseed0, 860120913Sume ndi->randomseed1, ndi->randomid); 86178064Sume } 86278064Sume } 86378064Sume 864191688Szec CURVNET_RESTORE(); 86578064Sume} 866170613Sbms 867170613Sbmsstatic void 868171259Sdelphijin6_purgemaddrs(struct ifnet *ifp) 869170613Sbms{ 870191672Sbms LIST_HEAD(,in6_multi) purgeinms; 871191672Sbms struct in6_multi *inm, *tinm; 872191672Sbms struct ifmultiaddr *ifma; 873170613Sbms 874191672Sbms LIST_INIT(&purgeinms); 875191672Sbms IN6_MULTI_LOCK(); 876191672Sbms 877191672Sbms /* 878191672Sbms * Extract list of in6_multi associated with the detaching ifp 879191672Sbms * which the PF_INET6 layer is about to release. 880191672Sbms * We need to do this as IF_ADDR_LOCK() may be re-acquired 881191672Sbms * by code further down. 882191672Sbms */ 883229621Sjhb IF_ADDR_RLOCK(ifp); 884191672Sbms TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 885191672Sbms if (ifma->ifma_addr->sa_family != AF_INET6 || 886191672Sbms ifma->ifma_protospec == NULL) 887191672Sbms continue; 888191672Sbms inm = (struct in6_multi *)ifma->ifma_protospec; 889191672Sbms LIST_INSERT_HEAD(&purgeinms, inm, in6m_entry); 890170613Sbms } 891229621Sjhb IF_ADDR_RUNLOCK(ifp); 892191672Sbms 893191672Sbms LIST_FOREACH_SAFE(inm, &purgeinms, in6m_entry, tinm) { 894191672Sbms LIST_REMOVE(inm, in6m_entry); 895191672Sbms in6m_release_locked(inm); 896191672Sbms } 897191672Sbms mld_ifdetach(ifp); 898191672Sbms 899191672Sbms IN6_MULTI_UNLOCK(); 900170613Sbms} 901