in6_ifattach.c revision 180291
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 180291 2008-07-05 13:10:10Z rwatson $");
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>
4053541Sshin#include <sys/kernel.h>
4178064Sume#include <sys/syslog.h>
4253541Sshin#include <sys/md5.h>
4353541Sshin
4453541Sshin#include <net/if.h>
4553541Sshin#include <net/if_dl.h>
4653541Sshin#include <net/if_types.h>
4753541Sshin#include <net/route.h>
4853541Sshin
4953541Sshin#include <netinet/in.h>
5053541Sshin#include <netinet/in_var.h>
5153541Sshin#include <netinet/if_ether.h>
5281127Sume#include <netinet/in_pcb.h>
5353541Sshin
5462587Sitojun#include <netinet/ip6.h>
5553541Sshin#include <netinet6/ip6_var.h>
5678064Sume#include <netinet6/in6_var.h>
5781127Sume#include <netinet6/in6_pcb.h>
5853541Sshin#include <netinet6/in6_ifattach.h>
5953541Sshin#include <netinet6/ip6_var.h>
6053541Sshin#include <netinet6/nd6.h>
6162587Sitojun#include <netinet6/scope6_var.h>
6253541Sshin
6362587Sitojununsigned long in6_maxmtu = 0;
6453541Sshin
6578064Sume#ifdef IP6_AUTO_LINKLOCAL
6678064Sumeint ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
6778064Sume#else
68163306Sumeint ip6_auto_linklocal = 1;	/* enable by default */
6978064Sume#endif
7078064Sume
7178064Sumestruct callout in6_tmpaddrtimer_ch;
7278064Sume
7381127Sumeextern struct inpcbinfo udbinfo;
7481127Sumeextern struct inpcbinfo ripcbinfo;
7581127Sume
76175162Sobrienstatic int get_rand_ifid(struct ifnet *, struct in6_addr *);
77175162Sobrienstatic int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
78175162Sobrienstatic int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
79175162Sobrienstatic int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
80175162Sobrienstatic int in6_ifattach_loopback(struct ifnet *);
81175162Sobrienstatic void in6_purgemaddrs(struct ifnet *);
8253541Sshin
8362587Sitojun#define EUI64_GBIT	0x01
8462587Sitojun#define EUI64_UBIT	0x02
8562587Sitojun#define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
8662587Sitojun#define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
8762587Sitojun#define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
8862587Sitojun#define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
8962587Sitojun#define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
9053541Sshin
9162587Sitojun#define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
9262587Sitojun#define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
9353541Sshin
9453541Sshin/*
9553541Sshin * Generate a last-resort interface identifier, when the machine has no
9653541Sshin * IEEE802/EUI64 address sources.
9762587Sitojun * The goal here is to get an interface identifier that is
9862587Sitojun * (1) random enough and (2) does not change across reboot.
9962587Sitojun * We currently use MD5(hostname) for it.
100171259Sdelphij *
101171259Sdelphij * in6 - upper 64bits are preserved
10253541Sshin */
10353541Sshinstatic int
104171259Sdelphijget_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
10553541Sshin{
10653541Sshin	MD5_CTX ctxt;
10753541Sshin	u_int8_t digest[16];
108180291Srwatson	int hostnamelen;
10953541Sshin
110180291Srwatson	mtx_lock(&hostname_mtx);
111180291Srwatson	hostnamelen = strlen(hostname);
11262587Sitojun#if 0
11362587Sitojun	/* we need at least several letters as seed for ifid */
11462587Sitojun	if (hostnamelen < 3)
11562587Sitojun		return -1;
11662587Sitojun#endif
11762587Sitojun
11862587Sitojun	/* generate 8 bytes of pseudo-random value. */
11953541Sshin	bzero(&ctxt, sizeof(ctxt));
12053541Sshin	MD5Init(&ctxt);
12153541Sshin	MD5Update(&ctxt, hostname, hostnamelen);
122180291Srwatson	mtx_unlock(&hostname_mtx);
12353541Sshin	MD5Final(digest, &ctxt);
12453541Sshin
12562587Sitojun	/* assumes sizeof(digest) > sizeof(ifid) */
12662587Sitojun	bcopy(digest, &in6->s6_addr[8], 8);
12753541Sshin
12853541Sshin	/* make sure to set "u" bit to local, and "g" bit to individual. */
12962587Sitojun	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
13062587Sitojun	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
13153541Sshin
13262587Sitojun	/* convert EUI64 into IPv6 interface identifier */
13362587Sitojun	EUI64_TO_IFID(in6);
13462587Sitojun
13553541Sshin	return 0;
13653541Sshin}
13753541Sshin
13878064Sumestatic int
139171259Sdelphijgenerate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
14078064Sume{
14178064Sume	MD5_CTX ctxt;
14278064Sume	u_int8_t seed[16], digest[16], nullbuf[8];
14378064Sume	u_int32_t val32;
14478064Sume
145171259Sdelphij	/* If there's no history, start with a random seed. */
14678064Sume	bzero(nullbuf, sizeof(nullbuf));
14778064Sume	if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
14878064Sume		int i;
14978064Sume
15078064Sume		for (i = 0; i < 2; i++) {
151121807Sume			val32 = arc4random();
15278064Sume			bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
15378064Sume		}
154120913Sume	} else
15578064Sume		bcopy(seed0, seed, 8);
15678064Sume
15778064Sume	/* copy the right-most 64-bits of the given address */
15878064Sume	/* XXX assumption on the size of IFID */
15978064Sume	bcopy(seed1, &seed[8], 8);
16078064Sume
16178064Sume	if (0) {		/* for debugging purposes only */
16278064Sume		int i;
16378064Sume
16478064Sume		printf("generate_tmp_ifid: new randomized ID from: ");
16578064Sume		for (i = 0; i < 16; i++)
16678064Sume			printf("%02x", seed[i]);
16778064Sume		printf(" ");
16878064Sume	}
16978064Sume
17078064Sume	/* generate 16 bytes of pseudo-random value. */
17178064Sume	bzero(&ctxt, sizeof(ctxt));
17278064Sume	MD5Init(&ctxt);
17378064Sume	MD5Update(&ctxt, seed, sizeof(seed));
17478064Sume	MD5Final(digest, &ctxt);
17578064Sume
17678064Sume	/*
17778064Sume	 * RFC 3041 3.2.1. (3)
17878064Sume	 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
17978064Sume	 * left-most bit is numbered 0) to zero.
18078064Sume	 */
18178064Sume	bcopy(digest, ret, 8);
18278064Sume	ret[0] &= ~EUI64_UBIT;
18378064Sume
18478064Sume	/*
18578064Sume	 * XXX: we'd like to ensure that the generated value is not zero
18678064Sume	 * for simplicity.  If the caclculated digest happens to be zero,
18778064Sume	 * use a random non-zero value as the last resort.
18878064Sume	 */
18978064Sume	if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
190151465Ssuz		nd6log((LOG_INFO,
191151465Ssuz		    "generate_tmp_ifid: computed MD5 value is zero.\n"));
19278064Sume
193121807Sume		val32 = arc4random();
19478064Sume		val32 = 1 + (val32 % (0xffffffff - 1));
19578064Sume	}
19678064Sume
19778064Sume	/*
19878064Sume	 * RFC 3041 3.2.1. (4)
19978064Sume	 * Take the rightmost 64-bits of the MD5 digest and save them in
20078064Sume	 * stable storage as the history value to be used in the next
201120913Sume	 * iteration of the algorithm.
20278064Sume	 */
20378064Sume	bcopy(&digest[8], seed0, 8);
20478064Sume
20578064Sume	if (0) {		/* for debugging purposes only */
20678064Sume		int i;
20778064Sume
20878064Sume		printf("to: ");
20978064Sume		for (i = 0; i < 16; i++)
21078064Sume			printf("%02x", digest[i]);
21178064Sume		printf("\n");
21278064Sume	}
21378064Sume
21478064Sume	return 0;
21578064Sume}
21678064Sume
21753541Sshin/*
21862587Sitojun * Get interface identifier for the specified interface.
21962587Sitojun * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
220171259Sdelphij *
221171259Sdelphij * in6 - upper 64bits are preserved
22253541Sshin */
223151477Ssuzint
224171259Sdelphijin6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
22553541Sshin{
22653541Sshin	struct ifaddr *ifa;
22753541Sshin	struct sockaddr_dl *sdl;
22862587Sitojun	u_int8_t *addr;
22962587Sitojun	size_t addrlen;
23062587Sitojun	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
23162587Sitojun	static u_int8_t allone[8] =
23262587Sitojun		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
23353541Sshin
23462587Sitojun	for (ifa = ifp->if_addrlist.tqh_first;
23562587Sitojun	     ifa;
236120913Sume	     ifa = ifa->ifa_list.tqe_next) {
23762587Sitojun		if (ifa->ifa_addr->sa_family != AF_LINK)
23853541Sshin			continue;
23962587Sitojun		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
24062587Sitojun		if (sdl == NULL)
24162587Sitojun			continue;
24262587Sitojun		if (sdl->sdl_alen == 0)
24362587Sitojun			continue;
24462587Sitojun
24562587Sitojun		goto found;
24653541Sshin	}
24753541Sshin
24862587Sitojun	return -1;
24962587Sitojun
25053541Sshinfound:
25162587Sitojun	addr = LLADDR(sdl);
25262587Sitojun	addrlen = sdl->sdl_alen;
25353541Sshin
25462587Sitojun	/* get EUI64 */
25562587Sitojun	switch (ifp->if_type) {
25662587Sitojun	case IFT_ETHER:
25762587Sitojun	case IFT_FDDI:
258120049Smdodd	case IFT_ISO88025:
25962587Sitojun	case IFT_ATM:
26078064Sume	case IFT_IEEE1394:
26178064Sume#ifdef IFT_IEEE80211
26278064Sume	case IFT_IEEE80211:
26378064Sume#endif
26462587Sitojun		/* IEEE802/EUI64 cases - what others? */
26578064Sume		/* IEEE1394 uses 16byte length address starting with EUI64 */
26678064Sume		if (addrlen > 8)
26778064Sume			addrlen = 8;
26853541Sshin
26962587Sitojun		/* look at IEEE802/EUI64 only */
27062587Sitojun		if (addrlen != 8 && addrlen != 6)
27162587Sitojun			return -1;
27253541Sshin
27362587Sitojun		/*
27462587Sitojun		 * check for invalid MAC address - on bsdi, we see it a lot
27562587Sitojun		 * since wildboar configures all-zero MAC on pccard before
27662587Sitojun		 * card insertion.
27762587Sitojun		 */
27862587Sitojun		if (bcmp(addr, allzero, addrlen) == 0)
27962587Sitojun			return -1;
28062587Sitojun		if (bcmp(addr, allone, addrlen) == 0)
28162587Sitojun			return -1;
28262587Sitojun
28362587Sitojun		/* make EUI64 address */
28462587Sitojun		if (addrlen == 8)
28562587Sitojun			bcopy(addr, &in6->s6_addr[8], 8);
28662587Sitojun		else if (addrlen == 6) {
28762587Sitojun			in6->s6_addr[8] = addr[0];
28862587Sitojun			in6->s6_addr[9] = addr[1];
28962587Sitojun			in6->s6_addr[10] = addr[2];
29062587Sitojun			in6->s6_addr[11] = 0xff;
29162587Sitojun			in6->s6_addr[12] = 0xfe;
29262587Sitojun			in6->s6_addr[13] = addr[3];
29362587Sitojun			in6->s6_addr[14] = addr[4];
29462587Sitojun			in6->s6_addr[15] = addr[5];
29562587Sitojun		}
29662587Sitojun		break;
29762587Sitojun
29862587Sitojun	case IFT_ARCNET:
29962587Sitojun		if (addrlen != 1)
30062587Sitojun			return -1;
30162587Sitojun		if (!addr[0])
30262587Sitojun			return -1;
30362587Sitojun
30462587Sitojun		bzero(&in6->s6_addr[8], 8);
30562587Sitojun		in6->s6_addr[15] = addr[0];
30662587Sitojun
30762587Sitojun		/*
30862587Sitojun		 * due to insufficient bitwidth, we mark it local.
30962587Sitojun		 */
31062587Sitojun		in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
31162587Sitojun		in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
31262587Sitojun		break;
31362587Sitojun
31462587Sitojun	case IFT_GIF:
31562587Sitojun#ifdef IFT_STF
31662587Sitojun	case IFT_STF:
31753541Sshin#endif
31862587Sitojun		/*
31978064Sume		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
32062587Sitojun		 * however, IPv4 address is not very suitable as unique
32162587Sitojun		 * identifier source (can be renumbered).
32262587Sitojun		 * we don't do this.
32362587Sitojun		 */
32462587Sitojun		return -1;
32562587Sitojun
32662587Sitojun	default:
32762587Sitojun		return -1;
32853541Sshin	}
32962587Sitojun
33062587Sitojun	/* sanity check: g bit must not indicate "group" */
33162587Sitojun	if (EUI64_GROUP(in6))
33262587Sitojun		return -1;
33362587Sitojun
33462587Sitojun	/* convert EUI64 into IPv6 interface identifier */
33562587Sitojun	EUI64_TO_IFID(in6);
33662587Sitojun
33762587Sitojun	/*
33862587Sitojun	 * sanity check: ifid must not be all zero, avoid conflict with
33962587Sitojun	 * subnet router anycast
34062587Sitojun	 */
34162587Sitojun	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
34262587Sitojun	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
34362587Sitojun		return -1;
34462587Sitojun	}
34562587Sitojun
34662587Sitojun	return 0;
34753541Sshin}
34853541Sshin
34953541Sshin/*
35062587Sitojun * Get interface identifier for the specified interface.  If it is not
35162587Sitojun * available on ifp0, borrow interface identifier from other information
35262587Sitojun * sources.
353171259Sdelphij *
354171259Sdelphij * altifp - secondary EUI64 source
35553541Sshin */
35662587Sitojunstatic int
357171259Sdelphijget_ifid(struct ifnet *ifp0, struct ifnet *altifp,
358171259Sdelphij    struct in6_addr *in6)
35953541Sshin{
36053541Sshin	struct ifnet *ifp;
36153541Sshin
36262587Sitojun	/* first, try to get it from the interface itself */
363151477Ssuz	if (in6_get_hw_ifid(ifp0, in6) == 0) {
36478064Sume		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
36578064Sume		    if_name(ifp0)));
36662587Sitojun		goto success;
36762587Sitojun	}
36853541Sshin
36962587Sitojun	/* try secondary EUI64 source. this basically is for ATM PVC */
370151477Ssuz	if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
37178064Sume		nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
37278064Sume		    if_name(ifp0), if_name(altifp)));
37362587Sitojun		goto success;
37462587Sitojun	}
37562587Sitojun
37662587Sitojun	/* next, try to get it from some other hardware interface */
377108172Shsu	IFNET_RLOCK();
378120913Sume	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
37962587Sitojun		if (ifp == ifp0)
38062587Sitojun			continue;
381151477Ssuz		if (in6_get_hw_ifid(ifp, in6) != 0)
38262587Sitojun			continue;
38362587Sitojun
38462587Sitojun		/*
38562587Sitojun		 * to borrow ifid from other interface, ifid needs to be
38662587Sitojun		 * globally unique
38762587Sitojun		 */
38862587Sitojun		if (IFID_UNIVERSAL(in6)) {
38978064Sume			nd6log((LOG_DEBUG,
39078064Sume			    "%s: borrow interface identifier from %s\n",
39178064Sume			    if_name(ifp0), if_name(ifp)));
392108172Shsu			IFNET_RUNLOCK();
39362587Sitojun			goto success;
39462587Sitojun		}
39562587Sitojun	}
396108172Shsu	IFNET_RUNLOCK();
39762587Sitojun
39862587Sitojun	/* last resort: get from random number source */
39962587Sitojun	if (get_rand_ifid(ifp, in6) == 0) {
40078064Sume		nd6log((LOG_DEBUG,
40178064Sume		    "%s: interface identifier generated by random number\n",
40278064Sume		    if_name(ifp0)));
40362587Sitojun		goto success;
40462587Sitojun	}
40562587Sitojun
40666504Sitojun	printf("%s: failed to get interface identifier\n", if_name(ifp0));
40762587Sitojun	return -1;
40862587Sitojun
40962587Sitojunsuccess:
410120913Sume	nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
411120913Sume	    if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
412120913Sume	    in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
413120913Sume	    in6->s6_addr[14], in6->s6_addr[15]));
41462587Sitojun	return 0;
41562587Sitojun}
41662587Sitojun
417171259Sdelphij/*
418171259Sdelphij * altifp - secondary EUI64 source
419171259Sdelphij */
42062587Sitojunstatic int
421171259Sdelphijin6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
42278064Sume{
42362587Sitojun	struct in6_ifaddr *ia;
42478064Sume	struct in6_aliasreq ifra;
425151539Ssuz	struct nd_prefixctl pr0;
42678064Sume	int i, error;
42762587Sitojun
42862587Sitojun	/*
42978064Sume	 * configure link-local address.
43062587Sitojun	 */
43178064Sume	bzero(&ifra, sizeof(ifra));
43262587Sitojun
43362587Sitojun	/*
43478064Sume	 * in6_update_ifa() does not use ifra_name, but we accurately set it
43578064Sume	 * for safety.
43662587Sitojun	 */
43778064Sume	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
43862587Sitojun
43978064Sume	ifra.ifra_addr.sin6_family = AF_INET6;
44078064Sume	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
441148385Sume	ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
44278064Sume	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
44378064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
44478064Sume		ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
44578064Sume		ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
44678064Sume	} else {
44778064Sume		if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
44878064Sume			nd6log((LOG_ERR,
44978064Sume			    "%s: no ifid available\n", if_name(ifp)));
450120913Sume			return (-1);
45162587Sitojun		}
45262587Sitojun	}
453148385Sume	if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
454148385Sume		return (-1);
45562587Sitojun
45678064Sume	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
45778064Sume	ifra.ifra_prefixmask.sin6_family = AF_INET6;
45878064Sume	ifra.ifra_prefixmask.sin6_addr = in6mask64;
45978064Sume	/* link-local addresses should NEVER expire. */
46078064Sume	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
46178064Sume	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
46262587Sitojun
46378064Sume	/*
46478064Sume	 * Now call in6_update_ifa() to do a bunch of procedures to configure
465151465Ssuz	 * a link-local address. We can set the 3rd argument to NULL, because
46695023Ssuz	 * we know there's no other link-local address on the interface
46795023Ssuz	 * and therefore we are adding one (instead of updating one).
46878064Sume	 */
469151539Ssuz	if ((error = in6_update_ifa(ifp, &ifra, NULL,
470151539Ssuz				    IN6_IFAUPDATE_DADDELAY)) != 0) {
47162587Sitojun		/*
47278064Sume		 * XXX: When the interface does not support IPv6, this call
47378064Sume		 * would fail in the SIOCSIFADDR ioctl.  I believe the
47478064Sume		 * notification is rather confusing in this case, so just
475120913Sume		 * suppress it.  (jinmei@kame.net 20010130)
47662587Sitojun		 */
47778064Sume		if (error != EAFNOSUPPORT)
478151465Ssuz			nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
47978064Sume			    "configure a link-local address on %s "
48078064Sume			    "(errno=%d)\n",
481151465Ssuz			    if_name(ifp), error));
482120856Sume		return (-1);
48362587Sitojun	}
48462587Sitojun
48578064Sume	ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
48678064Sume#ifdef DIAGNOSTIC
48778064Sume	if (!ia) {
48878064Sume		panic("ia == NULL in in6_ifattach_linklocal");
48995023Ssuz		/* NOTREACHED */
49078064Sume	}
49162587Sitojun#endif
49253541Sshin
49378064Sume	/*
494120913Sume	 * Make the link-local prefix (fe80::%link/64) as on-link.
49578064Sume	 * Since we'd like to manage prefixes separately from addresses,
49678064Sume	 * we make an ND6 prefix structure for the link-local prefix,
49778064Sume	 * and add it to the prefix list as a never-expire prefix.
49878064Sume	 * XXX: this change might affect some existing code base...
49978064Sume	 */
50078064Sume	bzero(&pr0, sizeof(pr0));
50178064Sume	pr0.ndpr_ifp = ifp;
50278064Sume	/* this should be 64 at this moment. */
50378064Sume	pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
50478064Sume	pr0.ndpr_prefix = ifra.ifra_addr;
50578064Sume	/* apply the mask for safety. (nd6_prelist_add will apply it again) */
50678064Sume	for (i = 0; i < 4; i++) {
50778064Sume		pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
508120913Sume		    in6mask64.s6_addr32[i];
50962587Sitojun	}
51078064Sume	/*
51178064Sume	 * Initialize parameters.  The link-local prefix must always be
51278064Sume	 * on-link, and its lifetimes never expire.
51378064Sume	 */
51478064Sume	pr0.ndpr_raf_onlink = 1;
51578064Sume	pr0.ndpr_raf_auto = 1;	/* probably meaningless */
51678064Sume	pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
51778064Sume	pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
51878064Sume	/*
51978064Sume	 * Since there is no other link-local addresses, nd6_prefix_lookup()
52078064Sume	 * probably returns NULL.  However, we cannot always expect the result.
52178064Sume	 * For example, if we first remove the (only) existing link-local
52278064Sume	 * address, and then reconfigure another one, the prefix is still
52378064Sume	 * valid with referring to the old link-local address.
52478064Sume	 */
52578064Sume	if (nd6_prefix_lookup(&pr0) == NULL) {
52678064Sume		if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
527120856Sume			return (error);
52878064Sume	}
52962587Sitojun
53062587Sitojun	return 0;
53162587Sitojun}
53262587Sitojun
533171259Sdelphij/*
534171259Sdelphij * ifp - must be IFT_LOOP
535171259Sdelphij */
53662587Sitojunstatic int
537171259Sdelphijin6_ifattach_loopback(struct ifnet *ifp)
53862587Sitojun{
53978064Sume	struct in6_aliasreq ifra;
54078064Sume	int error;
54162587Sitojun
54278064Sume	bzero(&ifra, sizeof(ifra));
54378064Sume
54462587Sitojun	/*
54578064Sume	 * in6_update_ifa() does not use ifra_name, but we accurately set it
54678064Sume	 * for safety.
54762587Sitojun	 */
54878064Sume	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
54962587Sitojun
55078064Sume	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
55178064Sume	ifra.ifra_prefixmask.sin6_family = AF_INET6;
55278064Sume	ifra.ifra_prefixmask.sin6_addr = in6mask128;
55362587Sitojun
55462587Sitojun	/*
55562587Sitojun	 * Always initialize ia_dstaddr (= broadcast address) to loopback
55678064Sume	 * address.  Follows IPv4 practice - see in_ifinit().
55762587Sitojun	 */
55878064Sume	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
55978064Sume	ifra.ifra_dstaddr.sin6_family = AF_INET6;
56078064Sume	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
56162587Sitojun
56278064Sume	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
56378064Sume	ifra.ifra_addr.sin6_family = AF_INET6;
56478064Sume	ifra.ifra_addr.sin6_addr = in6addr_loopback;
56562587Sitojun
56678064Sume	/* the loopback  address should NEVER expire. */
56778064Sume	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
56878064Sume	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
56962587Sitojun
57095023Ssuz	/* we don't need to perform DAD on loopback interfaces. */
57178064Sume	ifra.ifra_flags |= IN6_IFF_NODAD;
57278064Sume
57378064Sume	/* skip registration to the prefix list. XXX should be temporary. */
57478064Sume	ifra.ifra_flags |= IN6_IFF_NOPFX;
57578064Sume
57678064Sume	/*
57795023Ssuz	 * We are sure that this is a newly assigned address, so we can set
57895023Ssuz	 * NULL to the 3rd arg.
57978064Sume	 */
580151539Ssuz	if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
581151465Ssuz		nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
58278064Sume		    "the loopback address on %s (errno=%d)\n",
583151465Ssuz		    if_name(ifp), error));
584120856Sume		return (-1);
58562587Sitojun	}
58662587Sitojun
58762587Sitojun	return 0;
58862587Sitojun}
58962587Sitojun
59062587Sitojun/*
59162587Sitojun * compute NI group address, based on the current hostname setting.
59262587Sitojun * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
59362587Sitojun *
59462587Sitojun * when ifp == NULL, the caller is responsible for filling scopeid.
59562587Sitojun */
59678064Sumeint
597171259Sdelphijin6_nigroup(struct ifnet *ifp, const char *name, int namelen,
598171259Sdelphij    struct in6_addr *in6)
59962587Sitojun{
60062587Sitojun	const char *p;
60178064Sume	u_char *q;
60262587Sitojun	MD5_CTX ctxt;
60362587Sitojun	u_int8_t digest[16];
60462587Sitojun	char l;
60578064Sume	char n[64];	/* a single label must not exceed 63 chars */
60662587Sitojun
60762587Sitojun	if (!namelen || !name)
60862587Sitojun		return -1;
60962587Sitojun
61062587Sitojun	p = name;
61162587Sitojun	while (p && *p && *p != '.' && p - name < namelen)
61262587Sitojun		p++;
61378064Sume	if (p - name > sizeof(n) - 1)
61495023Ssuz		return -1;	/* label too long */
61562587Sitojun	l = p - name;
61678064Sume	strncpy(n, name, l);
61778064Sume	n[(int)l] = '\0';
61878064Sume	for (q = n; *q; q++) {
61978064Sume		if ('A' <= *q && *q <= 'Z')
62078064Sume			*q = *q - 'A' + 'a';
62178064Sume	}
62262587Sitojun
62362587Sitojun	/* generate 8 bytes of pseudo-random value. */
62462587Sitojun	bzero(&ctxt, sizeof(ctxt));
62562587Sitojun	MD5Init(&ctxt);
62662587Sitojun	MD5Update(&ctxt, &l, sizeof(l));
62778064Sume	MD5Update(&ctxt, n, l);
62862587Sitojun	MD5Final(digest, &ctxt);
62962587Sitojun
63062587Sitojun	bzero(in6, sizeof(*in6));
631151465Ssuz	in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
63262587Sitojun	in6->s6_addr8[11] = 2;
63362587Sitojun	bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
634148385Sume	if (in6_setscope(in6, ifp, NULL))
635148385Sume		return (-1); /* XXX: should not fail */
63662587Sitojun
63762587Sitojun	return 0;
63862587Sitojun}
63962587Sitojun
64062587Sitojun/*
64162587Sitojun * XXX multiple loopback interface needs more care.  for instance,
64262587Sitojun * nodelocal address needs to be configured onto only one of them.
64362587Sitojun * XXX multiple link-local address case
644171259Sdelphij *
645171259Sdelphij * altifp - secondary EUI64 source
64662587Sitojun */
64762587Sitojunvoid
648171259Sdelphijin6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
64962587Sitojun{
65062587Sitojun	struct in6_ifaddr *ia;
65162587Sitojun	struct in6_addr in6;
65262587Sitojun
65378064Sume	/* some of the interfaces are inherently not IPv6 capable */
65478064Sume	switch (ifp->if_type) {
655126263Smlaier	case IFT_PFLOG:
656126263Smlaier	case IFT_PFSYNC:
657142215Sglebius	case IFT_CARP:
65878064Sume		return;
65978064Sume	}
66078064Sume
66153541Sshin	/*
66262587Sitojun	 * quirks based on interface type
66353541Sshin	 */
66462587Sitojun	switch (ifp->if_type) {
66562587Sitojun#ifdef IFT_STF
66662587Sitojun	case IFT_STF:
66762587Sitojun		/*
66895023Ssuz		 * 6to4 interface is a very special kind of beast.
66995023Ssuz		 * no multicast, no linklocal.  RFC2529 specifies how to make
67095023Ssuz		 * linklocals for 6to4 interface, but there's no use and
67195023Ssuz		 * it is rather harmful to have one.
67262587Sitojun		 */
67362587Sitojun		goto statinit;
67462587Sitojun#endif
67562587Sitojun	default:
67662587Sitojun		break;
67753541Sshin	}
67853541Sshin
67953541Sshin	/*
68062587Sitojun	 * usually, we require multicast capability to the interface
68153541Sshin	 */
68262587Sitojun	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
683151465Ssuz		nd6log((LOG_INFO, "in6_ifattach: "
68478064Sume		    "%s is not multicast capable, IPv6 not enabled\n",
685151465Ssuz		    if_name(ifp)));
68662587Sitojun		return;
68762587Sitojun	}
68862587Sitojun
68953541Sshin	/*
69078064Sume	 * assign loopback address for loopback interface.
69178064Sume	 * XXX multiple loopback interface case.
69253541Sshin	 */
69378064Sume	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
69478064Sume		in6 = in6addr_loopback;
69562587Sitojun		if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
69662587Sitojun			if (in6_ifattach_loopback(ifp) != 0)
69762587Sitojun				return;
69862587Sitojun		}
69962587Sitojun	}
70053541Sshin
70153541Sshin	/*
702120913Sume	 * assign a link-local address, if there's none.
70353541Sshin	 */
704149829Sthompsa	if (ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) {
70578064Sume		ia = in6ifa_ifpforlinklocal(ifp, 0);
70678064Sume		if (ia == NULL) {
70778064Sume			if (in6_ifattach_linklocal(ifp, altifp) == 0) {
70878064Sume				/* linklocal address assigned */
70978064Sume			} else {
71078064Sume				/* failed to assign linklocal address. bark? */
71162587Sitojun			}
71262587Sitojun		}
71353541Sshin	}
71453541Sshin
71578064Sume#ifdef IFT_STF			/* XXX */
716120913Sumestatinit:
71778064Sume#endif
71862587Sitojun
71953541Sshin	/* update dynamically. */
72053541Sshin	if (in6_maxmtu < ifp->if_mtu)
72153541Sshin		in6_maxmtu = ifp->if_mtu;
72253541Sshin}
72353541Sshin
72462587Sitojun/*
72562587Sitojun * NOTE: in6_ifdetach() does not support loopback if at this moment.
72678064Sume * We don't need this function in bsdi, because interfaces are never removed
72778064Sume * from the ifnet list in bsdi.
72862587Sitojun */
72953541Sshinvoid
730171259Sdelphijin6_ifdetach(struct ifnet *ifp)
73153541Sshin{
73253541Sshin	struct in6_ifaddr *ia, *oia;
73362587Sitojun	struct ifaddr *ifa, *next;
73453541Sshin	struct rtentry *rt;
73553541Sshin	short rtflags;
73662587Sitojun	struct sockaddr_in6 sin6;
737170202Sjinmei	struct in6_multi_mship *imm;
73853541Sshin
73962587Sitojun	/* remove neighbor management table */
74062587Sitojun	nd6_purge(ifp);
74162587Sitojun
74262587Sitojun	/* nuke any of IPv6 addresses we have */
743120913Sume	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
74462587Sitojun		next = ifa->ifa_list.tqe_next;
74562587Sitojun		if (ifa->ifa_addr->sa_family != AF_INET6)
74662587Sitojun			continue;
74778064Sume		in6_purgeaddr(ifa);
74862587Sitojun	}
74962587Sitojun
75062587Sitojun	/* undo everything done by in6_ifattach(), just in case */
751120913Sume	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
75262587Sitojun		next = ifa->ifa_list.tqe_next;
75362587Sitojun
75453541Sshin		if (ifa->ifa_addr->sa_family != AF_INET6
75553541Sshin		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
75653541Sshin			continue;
75753541Sshin		}
75853541Sshin
75953541Sshin		ia = (struct in6_ifaddr *)ifa;
76053541Sshin
761170202Sjinmei		/*
762170202Sjinmei		 * leave from multicast groups we have joined for the interface
763170202Sjinmei		 */
764170202Sjinmei		while ((imm = ia->ia6_memberships.lh_first) != NULL) {
765170202Sjinmei			LIST_REMOVE(imm, i6mm_chain);
766170202Sjinmei			in6_leavegroup(imm);
767170202Sjinmei		}
768170202Sjinmei
76953541Sshin		/* remove from the routing table */
770120913Sume		if ((ia->ia_flags & IFA_ROUTE) &&
771120913Sume		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
77253541Sshin			rtflags = rt->rt_flags;
77353541Sshin			rtfree(rt);
774120913Sume			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
775120913Sume			    (struct sockaddr *)&ia->ia_addr,
776120913Sume			    (struct sockaddr *)&ia->ia_prefixmask,
777120913Sume			    rtflags, (struct rtentry **)0);
77853541Sshin		}
77953541Sshin
78053541Sshin		/* remove from the linked list */
78153541Sshin		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
78262587Sitojun		IFAFREE(&ia->ia_ifa);
78353541Sshin
78453541Sshin		/* also remove from the IPv6 address chain(itojun&jinmei) */
78553541Sshin		oia = ia;
78653541Sshin		if (oia == (ia = in6_ifaddr))
78753541Sshin			in6_ifaddr = ia->ia_next;
78853541Sshin		else {
78953541Sshin			while (ia->ia_next && (ia->ia_next != oia))
79053541Sshin				ia = ia->ia_next;
79153541Sshin			if (ia->ia_next)
79253541Sshin				ia->ia_next = oia->ia_next;
79378064Sume			else {
794120913Sume				nd6log((LOG_ERR,
795120913Sume				    "%s: didn't unlink in6ifaddr from list\n",
796120913Sume				    if_name(ifp)));
79778064Sume			}
79853541Sshin		}
79953541Sshin
80062587Sitojun		IFAFREE(&oia->ia_ifa);
80153541Sshin	}
80262587Sitojun
803157978Srwatson	in6_pcbpurgeif0(&udbinfo, ifp);
804157978Srwatson	in6_pcbpurgeif0(&ripcbinfo, ifp);
805170613Sbms	/* leave from all multicast groups joined */
806170613Sbms	in6_purgemaddrs(ifp);
807120913Sume
80878064Sume	/*
80978064Sume	 * remove neighbor management table.  we call it twice just to make
81078064Sume	 * sure we nuke everything.  maybe we need just one call.
81178064Sume	 * XXX: since the first call did not release addresses, some prefixes
81278064Sume	 * might remain.  We should call nd6_purge() again to release the
81378064Sume	 * prefixes after removing all addresses above.
81478064Sume	 * (Or can we just delay calling nd6_purge until at this point?)
81578064Sume	 */
81662587Sitojun	nd6_purge(ifp);
81762587Sitojun
81862587Sitojun	/* remove route to link-local allnodes multicast (ff02::1) */
81962587Sitojun	bzero(&sin6, sizeof(sin6));
82062587Sitojun	sin6.sin6_len = sizeof(struct sockaddr_in6);
82162587Sitojun	sin6.sin6_family = AF_INET6;
82262587Sitojun	sin6.sin6_addr = in6addr_linklocal_allnodes;
823148385Sume	if (in6_setscope(&sin6.sin6_addr, ifp, NULL))
824148385Sume		/* XXX: should not fail */
825148385Sume		return;
826121770Ssam	/* XXX grab lock first to avoid LOR */
827178888Sjulian	if (rt_tables[0][AF_INET6] != NULL) {
828178888Sjulian		RADIX_NODE_HEAD_LOCK(rt_tables[0][AF_INET6]);
829124333Struckman		rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
830124333Struckman		if (rt) {
831124333Struckman			if (rt->rt_ifp == ifp)
832124333Struckman				rtexpunge(rt);
833124333Struckman			RTFREE_LOCKED(rt);
834124333Struckman		}
835178888Sjulian		RADIX_NODE_HEAD_UNLOCK(rt_tables[0][AF_INET6]);
83662587Sitojun	}
83753541Sshin}
83878064Sume
839151539Ssuzint
840171259Sdelphijin6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
841171259Sdelphij    const u_int8_t *baseid, int generate)
84278064Sume{
84378064Sume	u_int8_t nullbuf[8];
844121161Sume	struct nd_ifinfo *ndi = ND_IFINFO(ifp);
84578064Sume
84678064Sume	bzero(nullbuf, sizeof(nullbuf));
84778064Sume	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
84878064Sume		/* we've never created a random ID.  Create a new one. */
84978064Sume		generate = 1;
85078064Sume	}
85178064Sume
85278064Sume	if (generate) {
85378064Sume		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
85478064Sume
85578064Sume		/* generate_tmp_ifid will update seedn and buf */
85678064Sume		(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
857120913Sume		    ndi->randomid);
85878064Sume	}
85978064Sume	bcopy(ndi->randomid, retbuf, 8);
860151539Ssuz
861151539Ssuz	return (0);
86278064Sume}
86378064Sume
86478064Sumevoid
865171259Sdelphijin6_tmpaddrtimer(void *ignored_arg)
86678064Sume{
86778064Sume	struct nd_ifinfo *ndi;
86878064Sume	u_int8_t nullbuf[8];
869121161Sume	struct ifnet *ifp;
87078064Sume	int s = splnet();
87178064Sume
87278064Sume	callout_reset(&in6_tmpaddrtimer_ch,
873120913Sume	    (ip6_temp_preferred_lifetime - ip6_desync_factor -
874120913Sume	    ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
87578064Sume
87678064Sume	bzero(nullbuf, sizeof(nullbuf));
877121161Sume	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
878121161Sume		ndi = ND_IFINFO(ifp);
87978064Sume		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
88078064Sume			/*
88178064Sume			 * We've been generating a random ID on this interface.
88278064Sume			 * Create a new one.
88378064Sume			 */
88478064Sume			(void)generate_tmp_ifid(ndi->randomseed0,
885120913Sume			    ndi->randomseed1, ndi->randomid);
88678064Sume		}
88778064Sume	}
88878064Sume
88978064Sume	splx(s);
89078064Sume}
891170613Sbms
892170613Sbmsstatic void
893171259Sdelphijin6_purgemaddrs(struct ifnet *ifp)
894170613Sbms{
895170613Sbms	struct in6_multi *in6m;
896170613Sbms	struct in6_multi *oin6m;
897170613Sbms
898170613Sbms#ifdef DIAGNOSTIC
899170613Sbms	printf("%s: purging ifp %p\n", __func__, ifp);
900170613Sbms#endif
901170613Sbms
902170613Sbms	IFF_LOCKGIANT(ifp);
903170613Sbms	LIST_FOREACH_SAFE(in6m, &in6_multihead, in6m_entry, oin6m) {
904170613Sbms		if (in6m->in6m_ifp == ifp)
905170613Sbms			in6_delmulti(in6m);
906170613Sbms	}
907170613Sbms	IFF_UNLOCKGIANT(ifp);
908170613Sbms}
909