xref: /freebsd/sys/netinet6/in6_ifattach.c (revision a97719482dd97b6690bed7276136b54af7f22a21)
1686cdd19SJun-ichiro itojun Hagino /*	$FreeBSD$	*/
233841545SHajimu UMEMOTO /*	$KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $	*/
3686cdd19SJun-ichiro itojun Hagino 
4caf43b02SWarner Losh /*-
582cd038dSYoshinobu Inoue  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
682cd038dSYoshinobu Inoue  * All rights reserved.
782cd038dSYoshinobu Inoue  *
882cd038dSYoshinobu Inoue  * Redistribution and use in source and binary forms, with or without
982cd038dSYoshinobu Inoue  * modification, are permitted provided that the following conditions
1082cd038dSYoshinobu Inoue  * are met:
1182cd038dSYoshinobu Inoue  * 1. Redistributions of source code must retain the above copyright
1282cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer.
1382cd038dSYoshinobu Inoue  * 2. Redistributions in binary form must reproduce the above copyright
1482cd038dSYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer in the
1582cd038dSYoshinobu Inoue  *    documentation and/or other materials provided with the distribution.
1682cd038dSYoshinobu Inoue  * 3. Neither the name of the project nor the names of its contributors
1782cd038dSYoshinobu Inoue  *    may be used to endorse or promote products derived from this software
1882cd038dSYoshinobu Inoue  *    without specific prior written permission.
1982cd038dSYoshinobu Inoue  *
2082cd038dSYoshinobu Inoue  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2182cd038dSYoshinobu Inoue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2282cd038dSYoshinobu Inoue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2382cd038dSYoshinobu Inoue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2482cd038dSYoshinobu Inoue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2582cd038dSYoshinobu Inoue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2682cd038dSYoshinobu Inoue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2782cd038dSYoshinobu Inoue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2882cd038dSYoshinobu Inoue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2982cd038dSYoshinobu Inoue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3082cd038dSYoshinobu Inoue  * SUCH DAMAGE.
3182cd038dSYoshinobu Inoue  */
3282cd038dSYoshinobu Inoue 
3382cd038dSYoshinobu Inoue #include <sys/param.h>
3482cd038dSYoshinobu Inoue #include <sys/systm.h>
3582cd038dSYoshinobu Inoue #include <sys/malloc.h>
3682cd038dSYoshinobu Inoue #include <sys/socket.h>
3782cd038dSYoshinobu Inoue #include <sys/sockio.h>
3882cd038dSYoshinobu Inoue #include <sys/kernel.h>
3933841545SHajimu UMEMOTO #include <sys/syslog.h>
4082cd038dSYoshinobu Inoue #include <sys/md5.h>
4182cd038dSYoshinobu Inoue 
4282cd038dSYoshinobu Inoue #include <net/if.h>
4382cd038dSYoshinobu Inoue #include <net/if_dl.h>
4482cd038dSYoshinobu Inoue #include <net/if_types.h>
4582cd038dSYoshinobu Inoue #include <net/route.h>
4682cd038dSYoshinobu Inoue 
4782cd038dSYoshinobu Inoue #include <netinet/in.h>
4882cd038dSYoshinobu Inoue #include <netinet/in_var.h>
4982cd038dSYoshinobu Inoue #include <netinet/if_ether.h>
50e43cc4aeSHajimu UMEMOTO #include <netinet/in_pcb.h>
5182cd038dSYoshinobu Inoue 
52686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h>
5382cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h>
5433841545SHajimu UMEMOTO #include <netinet6/in6_var.h>
55e43cc4aeSHajimu UMEMOTO #include <netinet6/in6_pcb.h>
5682cd038dSYoshinobu Inoue #include <netinet6/in6_ifattach.h>
5782cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h>
5882cd038dSYoshinobu Inoue #include <netinet6/nd6.h>
59686cdd19SJun-ichiro itojun Hagino #include <netinet6/scope6_var.h>
6082cd038dSYoshinobu Inoue 
6182cd038dSYoshinobu Inoue #include <net/net_osdep.h>
6282cd038dSYoshinobu Inoue 
6382cd038dSYoshinobu Inoue unsigned long in6_maxmtu = 0;
6482cd038dSYoshinobu Inoue 
6533841545SHajimu UMEMOTO #ifdef IP6_AUTO_LINKLOCAL
6633841545SHajimu UMEMOTO int ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
6733841545SHajimu UMEMOTO #else
6833841545SHajimu UMEMOTO int ip6_auto_linklocal = 1;	/* enable by default */
6933841545SHajimu UMEMOTO #endif
7033841545SHajimu UMEMOTO 
7133841545SHajimu UMEMOTO struct callout in6_tmpaddrtimer_ch;
7233841545SHajimu UMEMOTO 
73e43cc4aeSHajimu UMEMOTO extern struct inpcbinfo udbinfo;
74e43cc4aeSHajimu UMEMOTO extern struct inpcbinfo ripcbinfo;
75e43cc4aeSHajimu UMEMOTO 
76686cdd19SJun-ichiro itojun Hagino static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
7733841545SHajimu UMEMOTO static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
78686cdd19SJun-ichiro itojun Hagino static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
79686cdd19SJun-ichiro itojun Hagino static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
80686cdd19SJun-ichiro itojun Hagino static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
81686cdd19SJun-ichiro itojun Hagino static int in6_ifattach_loopback __P((struct ifnet *));
8282cd038dSYoshinobu Inoue 
83686cdd19SJun-ichiro itojun Hagino #define EUI64_GBIT	0x01
84686cdd19SJun-ichiro itojun Hagino #define EUI64_UBIT	0x02
85686cdd19SJun-ichiro itojun Hagino #define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
86686cdd19SJun-ichiro itojun Hagino #define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
87686cdd19SJun-ichiro itojun Hagino #define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
88686cdd19SJun-ichiro itojun Hagino #define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
89686cdd19SJun-ichiro itojun Hagino #define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
9082cd038dSYoshinobu Inoue 
91686cdd19SJun-ichiro itojun Hagino #define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
92686cdd19SJun-ichiro itojun Hagino #define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
9382cd038dSYoshinobu Inoue 
9482cd038dSYoshinobu Inoue /*
9582cd038dSYoshinobu Inoue  * Generate a last-resort interface identifier, when the machine has no
9682cd038dSYoshinobu Inoue  * IEEE802/EUI64 address sources.
97686cdd19SJun-ichiro itojun Hagino  * The goal here is to get an interface identifier that is
98686cdd19SJun-ichiro itojun Hagino  * (1) random enough and (2) does not change across reboot.
99686cdd19SJun-ichiro itojun Hagino  * We currently use MD5(hostname) for it.
10082cd038dSYoshinobu Inoue  */
10182cd038dSYoshinobu Inoue static int
102686cdd19SJun-ichiro itojun Hagino get_rand_ifid(ifp, in6)
103686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;
104686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *in6;	/* upper 64bits are preserved */
10582cd038dSYoshinobu Inoue {
10682cd038dSYoshinobu Inoue 	MD5_CTX ctxt;
10782cd038dSYoshinobu Inoue 	u_int8_t digest[16];
10882cd038dSYoshinobu Inoue 	int hostnamelen	= strlen(hostname);
10982cd038dSYoshinobu Inoue 
110686cdd19SJun-ichiro itojun Hagino #if 0
111686cdd19SJun-ichiro itojun Hagino 	/* we need at least several letters as seed for ifid */
112686cdd19SJun-ichiro itojun Hagino 	if (hostnamelen < 3)
113686cdd19SJun-ichiro itojun Hagino 		return -1;
114686cdd19SJun-ichiro itojun Hagino #endif
115686cdd19SJun-ichiro itojun Hagino 
11682cd038dSYoshinobu Inoue 	/* generate 8 bytes of pseudo-random value. */
11782cd038dSYoshinobu Inoue 	bzero(&ctxt, sizeof(ctxt));
11882cd038dSYoshinobu Inoue 	MD5Init(&ctxt);
11982cd038dSYoshinobu Inoue 	MD5Update(&ctxt, hostname, hostnamelen);
12082cd038dSYoshinobu Inoue 	MD5Final(digest, &ctxt);
12182cd038dSYoshinobu Inoue 
122686cdd19SJun-ichiro itojun Hagino 	/* assumes sizeof(digest) > sizeof(ifid) */
123686cdd19SJun-ichiro itojun Hagino 	bcopy(digest, &in6->s6_addr[8], 8);
12482cd038dSYoshinobu Inoue 
12582cd038dSYoshinobu Inoue 	/* make sure to set "u" bit to local, and "g" bit to individual. */
126686cdd19SJun-ichiro itojun Hagino 	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
127686cdd19SJun-ichiro itojun Hagino 	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
128686cdd19SJun-ichiro itojun Hagino 
129686cdd19SJun-ichiro itojun Hagino 	/* convert EUI64 into IPv6 interface identifier */
130686cdd19SJun-ichiro itojun Hagino 	EUI64_TO_IFID(in6);
13182cd038dSYoshinobu Inoue 
13282cd038dSYoshinobu Inoue 	return 0;
13382cd038dSYoshinobu Inoue }
13482cd038dSYoshinobu Inoue 
13533841545SHajimu UMEMOTO static int
13633841545SHajimu UMEMOTO generate_tmp_ifid(seed0, seed1, ret)
13733841545SHajimu UMEMOTO 	u_int8_t *seed0, *ret;
13833841545SHajimu UMEMOTO 	const u_int8_t *seed1;
13933841545SHajimu UMEMOTO {
14033841545SHajimu UMEMOTO 	MD5_CTX ctxt;
14133841545SHajimu UMEMOTO 	u_int8_t seed[16], digest[16], nullbuf[8];
14233841545SHajimu UMEMOTO 	u_int32_t val32;
14333841545SHajimu UMEMOTO 
14433841545SHajimu UMEMOTO 	/* If there's no hisotry, start with a random seed. */
14533841545SHajimu UMEMOTO 	bzero(nullbuf, sizeof(nullbuf));
14633841545SHajimu UMEMOTO 	if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
14733841545SHajimu UMEMOTO 		int i;
14833841545SHajimu UMEMOTO 
14933841545SHajimu UMEMOTO 		for (i = 0; i < 2; i++) {
150a02e1e2bSHajimu UMEMOTO 			val32 = arc4random();
15133841545SHajimu UMEMOTO 			bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
15233841545SHajimu UMEMOTO 		}
1537efe5d92SHajimu UMEMOTO 	} else
15433841545SHajimu UMEMOTO 		bcopy(seed0, seed, 8);
15533841545SHajimu UMEMOTO 
15633841545SHajimu UMEMOTO 	/* copy the right-most 64-bits of the given address */
15733841545SHajimu UMEMOTO 	/* XXX assumption on the size of IFID */
15833841545SHajimu UMEMOTO 	bcopy(seed1, &seed[8], 8);
15933841545SHajimu UMEMOTO 
16033841545SHajimu UMEMOTO 	if (0) {		/* for debugging purposes only */
16133841545SHajimu UMEMOTO 		int i;
16233841545SHajimu UMEMOTO 
16333841545SHajimu UMEMOTO 		printf("generate_tmp_ifid: new randomized ID from: ");
16433841545SHajimu UMEMOTO 		for (i = 0; i < 16; i++)
16533841545SHajimu UMEMOTO 			printf("%02x", seed[i]);
16633841545SHajimu UMEMOTO 		printf(" ");
16733841545SHajimu UMEMOTO 	}
16833841545SHajimu UMEMOTO 
16933841545SHajimu UMEMOTO 	/* generate 16 bytes of pseudo-random value. */
17033841545SHajimu UMEMOTO 	bzero(&ctxt, sizeof(ctxt));
17133841545SHajimu UMEMOTO 	MD5Init(&ctxt);
17233841545SHajimu UMEMOTO 	MD5Update(&ctxt, seed, sizeof(seed));
17333841545SHajimu UMEMOTO 	MD5Final(digest, &ctxt);
17433841545SHajimu UMEMOTO 
17533841545SHajimu UMEMOTO 	/*
17633841545SHajimu UMEMOTO 	 * RFC 3041 3.2.1. (3)
17733841545SHajimu UMEMOTO 	 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
17833841545SHajimu UMEMOTO 	 * left-most bit is numbered 0) to zero.
17933841545SHajimu UMEMOTO 	 */
18033841545SHajimu UMEMOTO 	bcopy(digest, ret, 8);
18133841545SHajimu UMEMOTO 	ret[0] &= ~EUI64_UBIT;
18233841545SHajimu UMEMOTO 
18333841545SHajimu UMEMOTO 	/*
18433841545SHajimu UMEMOTO 	 * XXX: we'd like to ensure that the generated value is not zero
18533841545SHajimu UMEMOTO 	 * for simplicity.  If the caclculated digest happens to be zero,
18633841545SHajimu UMEMOTO 	 * use a random non-zero value as the last resort.
18733841545SHajimu UMEMOTO 	 */
18833841545SHajimu UMEMOTO 	if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
18933841545SHajimu UMEMOTO 		log(LOG_INFO,
19033841545SHajimu UMEMOTO 		    "generate_tmp_ifid: computed MD5 value is zero.\n");
19133841545SHajimu UMEMOTO 
192a02e1e2bSHajimu UMEMOTO 		val32 = arc4random();
19333841545SHajimu UMEMOTO 		val32 = 1 + (val32 % (0xffffffff - 1));
19433841545SHajimu UMEMOTO 	}
19533841545SHajimu UMEMOTO 
19633841545SHajimu UMEMOTO 	/*
19733841545SHajimu UMEMOTO 	 * RFC 3041 3.2.1. (4)
19833841545SHajimu UMEMOTO 	 * Take the rightmost 64-bits of the MD5 digest and save them in
19933841545SHajimu UMEMOTO 	 * stable storage as the history value to be used in the next
20033841545SHajimu UMEMOTO 	 * iteration of the algorithm.
20133841545SHajimu UMEMOTO 	 */
20233841545SHajimu UMEMOTO 	bcopy(&digest[8], seed0, 8);
20333841545SHajimu UMEMOTO 
20433841545SHajimu UMEMOTO 	if (0) {		/* for debugging purposes only */
20533841545SHajimu UMEMOTO 		int i;
20633841545SHajimu UMEMOTO 
20733841545SHajimu UMEMOTO 		printf("to: ");
20833841545SHajimu UMEMOTO 		for (i = 0; i < 16; i++)
20933841545SHajimu UMEMOTO 			printf("%02x", digest[i]);
21033841545SHajimu UMEMOTO 		printf("\n");
21133841545SHajimu UMEMOTO 	}
21233841545SHajimu UMEMOTO 
21333841545SHajimu UMEMOTO 	return 0;
21433841545SHajimu UMEMOTO }
21533841545SHajimu UMEMOTO 
21682cd038dSYoshinobu Inoue /*
217686cdd19SJun-ichiro itojun Hagino  * Get interface identifier for the specified interface.
218686cdd19SJun-ichiro itojun Hagino  * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
21982cd038dSYoshinobu Inoue  */
220686cdd19SJun-ichiro itojun Hagino static int
221686cdd19SJun-ichiro itojun Hagino get_hw_ifid(ifp, in6)
22282cd038dSYoshinobu Inoue 	struct ifnet *ifp;
223686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *in6;	/* upper 64bits are preserved */
22482cd038dSYoshinobu Inoue {
225686cdd19SJun-ichiro itojun Hagino 	struct ifaddr *ifa;
226686cdd19SJun-ichiro itojun Hagino 	struct sockaddr_dl *sdl;
227686cdd19SJun-ichiro itojun Hagino 	u_int8_t *addr;
228686cdd19SJun-ichiro itojun Hagino 	size_t addrlen;
229686cdd19SJun-ichiro itojun Hagino 	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
230686cdd19SJun-ichiro itojun Hagino 	static u_int8_t allone[8] =
231686cdd19SJun-ichiro itojun Hagino 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
232686cdd19SJun-ichiro itojun Hagino 
233686cdd19SJun-ichiro itojun Hagino 	for (ifa = ifp->if_addrlist.tqh_first;
234686cdd19SJun-ichiro itojun Hagino 	     ifa;
2357efe5d92SHajimu UMEMOTO 	     ifa = ifa->ifa_list.tqe_next) {
23682cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_LINK)
23782cd038dSYoshinobu Inoue 			continue;
23882cd038dSYoshinobu Inoue 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
23982cd038dSYoshinobu Inoue 		if (sdl == NULL)
24082cd038dSYoshinobu Inoue 			continue;
24182cd038dSYoshinobu Inoue 		if (sdl->sdl_alen == 0)
24282cd038dSYoshinobu Inoue 			continue;
243686cdd19SJun-ichiro itojun Hagino 
244686cdd19SJun-ichiro itojun Hagino 		goto found;
245686cdd19SJun-ichiro itojun Hagino 	}
246686cdd19SJun-ichiro itojun Hagino 
247686cdd19SJun-ichiro itojun Hagino 	return -1;
248686cdd19SJun-ichiro itojun Hagino 
249686cdd19SJun-ichiro itojun Hagino found:
250686cdd19SJun-ichiro itojun Hagino 	addr = LLADDR(sdl);
251686cdd19SJun-ichiro itojun Hagino 	addrlen = sdl->sdl_alen;
252686cdd19SJun-ichiro itojun Hagino 
253686cdd19SJun-ichiro itojun Hagino 	/* get EUI64 */
25482cd038dSYoshinobu Inoue 	switch (ifp->if_type) {
25582cd038dSYoshinobu Inoue 	case IFT_ETHER:
25682cd038dSYoshinobu Inoue 	case IFT_FDDI:
2572049fdeeSMatthew N. Dodd 	case IFT_ISO88025:
25882cd038dSYoshinobu Inoue 	case IFT_ATM:
25933841545SHajimu UMEMOTO 	case IFT_IEEE1394:
26033841545SHajimu UMEMOTO #ifdef IFT_IEEE80211
26133841545SHajimu UMEMOTO 	case IFT_IEEE80211:
26233841545SHajimu UMEMOTO #endif
26382cd038dSYoshinobu Inoue 		/* IEEE802/EUI64 cases - what others? */
26433841545SHajimu UMEMOTO 		/* IEEE1394 uses 16byte length address starting with EUI64 */
26533841545SHajimu UMEMOTO 		if (addrlen > 8)
26633841545SHajimu UMEMOTO 			addrlen = 8;
267686cdd19SJun-ichiro itojun Hagino 
268686cdd19SJun-ichiro itojun Hagino 		/* look at IEEE802/EUI64 only */
269686cdd19SJun-ichiro itojun Hagino 		if (addrlen != 8 && addrlen != 6)
270686cdd19SJun-ichiro itojun Hagino 			return -1;
271686cdd19SJun-ichiro itojun Hagino 
27282cd038dSYoshinobu Inoue 		/*
273686cdd19SJun-ichiro itojun Hagino 		 * check for invalid MAC address - on bsdi, we see it a lot
274686cdd19SJun-ichiro itojun Hagino 		 * since wildboar configures all-zero MAC on pccard before
275686cdd19SJun-ichiro itojun Hagino 		 * card insertion.
27682cd038dSYoshinobu Inoue 		 */
277686cdd19SJun-ichiro itojun Hagino 		if (bcmp(addr, allzero, addrlen) == 0)
278686cdd19SJun-ichiro itojun Hagino 			return -1;
279686cdd19SJun-ichiro itojun Hagino 		if (bcmp(addr, allone, addrlen) == 0)
280686cdd19SJun-ichiro itojun Hagino 			return -1;
281686cdd19SJun-ichiro itojun Hagino 
282686cdd19SJun-ichiro itojun Hagino 		/* make EUI64 address */
283686cdd19SJun-ichiro itojun Hagino 		if (addrlen == 8)
284686cdd19SJun-ichiro itojun Hagino 			bcopy(addr, &in6->s6_addr[8], 8);
285686cdd19SJun-ichiro itojun Hagino 		else if (addrlen == 6) {
286686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[8] = addr[0];
287686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[9] = addr[1];
288686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[10] = addr[2];
289686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[11] = 0xff;
290686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[12] = 0xfe;
291686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[13] = addr[3];
292686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[14] = addr[4];
293686cdd19SJun-ichiro itojun Hagino 			in6->s6_addr[15] = addr[5];
294686cdd19SJun-ichiro itojun Hagino 		}
29582cd038dSYoshinobu Inoue 		break;
296686cdd19SJun-ichiro itojun Hagino 
29782cd038dSYoshinobu Inoue 	case IFT_ARCNET:
298686cdd19SJun-ichiro itojun Hagino 		if (addrlen != 1)
299686cdd19SJun-ichiro itojun Hagino 			return -1;
300686cdd19SJun-ichiro itojun Hagino 		if (!addr[0])
301686cdd19SJun-ichiro itojun Hagino 			return -1;
302686cdd19SJun-ichiro itojun Hagino 
303686cdd19SJun-ichiro itojun Hagino 		bzero(&in6->s6_addr[8], 8);
304686cdd19SJun-ichiro itojun Hagino 		in6->s6_addr[15] = addr[0];
305686cdd19SJun-ichiro itojun Hagino 
30682cd038dSYoshinobu Inoue 		/*
307686cdd19SJun-ichiro itojun Hagino 		 * due to insufficient bitwidth, we mark it local.
30882cd038dSYoshinobu Inoue 		 */
309686cdd19SJun-ichiro itojun Hagino 		in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
310686cdd19SJun-ichiro itojun Hagino 		in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
31182cd038dSYoshinobu Inoue 		break;
312686cdd19SJun-ichiro itojun Hagino 
313686cdd19SJun-ichiro itojun Hagino 	case IFT_GIF:
314686cdd19SJun-ichiro itojun Hagino #ifdef IFT_STF
315686cdd19SJun-ichiro itojun Hagino 	case IFT_STF:
31682cd038dSYoshinobu Inoue #endif
317686cdd19SJun-ichiro itojun Hagino 		/*
31833841545SHajimu UMEMOTO 		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
319686cdd19SJun-ichiro itojun Hagino 		 * however, IPv4 address is not very suitable as unique
320686cdd19SJun-ichiro itojun Hagino 		 * identifier source (can be renumbered).
321686cdd19SJun-ichiro itojun Hagino 		 * we don't do this.
322686cdd19SJun-ichiro itojun Hagino 		 */
323686cdd19SJun-ichiro itojun Hagino 		return -1;
32482cd038dSYoshinobu Inoue 
325686cdd19SJun-ichiro itojun Hagino 	default:
326686cdd19SJun-ichiro itojun Hagino 		return -1;
327686cdd19SJun-ichiro itojun Hagino 	}
32882cd038dSYoshinobu Inoue 
329686cdd19SJun-ichiro itojun Hagino 	/* sanity check: g bit must not indicate "group" */
330686cdd19SJun-ichiro itojun Hagino 	if (EUI64_GROUP(in6))
331686cdd19SJun-ichiro itojun Hagino 		return -1;
33282cd038dSYoshinobu Inoue 
333686cdd19SJun-ichiro itojun Hagino 	/* convert EUI64 into IPv6 interface identifier */
334686cdd19SJun-ichiro itojun Hagino 	EUI64_TO_IFID(in6);
335686cdd19SJun-ichiro itojun Hagino 
336686cdd19SJun-ichiro itojun Hagino 	/*
337686cdd19SJun-ichiro itojun Hagino 	 * sanity check: ifid must not be all zero, avoid conflict with
338686cdd19SJun-ichiro itojun Hagino 	 * subnet router anycast
339686cdd19SJun-ichiro itojun Hagino 	 */
340686cdd19SJun-ichiro itojun Hagino 	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
341686cdd19SJun-ichiro itojun Hagino 	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
342686cdd19SJun-ichiro itojun Hagino 		return -1;
343686cdd19SJun-ichiro itojun Hagino 	}
34482cd038dSYoshinobu Inoue 
34582cd038dSYoshinobu Inoue 	return 0;
346686cdd19SJun-ichiro itojun Hagino }
347686cdd19SJun-ichiro itojun Hagino 
348686cdd19SJun-ichiro itojun Hagino /*
349686cdd19SJun-ichiro itojun Hagino  * Get interface identifier for the specified interface.  If it is not
350686cdd19SJun-ichiro itojun Hagino  * available on ifp0, borrow interface identifier from other information
351686cdd19SJun-ichiro itojun Hagino  * sources.
352686cdd19SJun-ichiro itojun Hagino  */
353686cdd19SJun-ichiro itojun Hagino static int
354686cdd19SJun-ichiro itojun Hagino get_ifid(ifp0, altifp, in6)
355686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp0;
356686cdd19SJun-ichiro itojun Hagino 	struct ifnet *altifp;	/* secondary EUI64 source */
357686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *in6;
358686cdd19SJun-ichiro itojun Hagino {
359686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;
360686cdd19SJun-ichiro itojun Hagino 
361686cdd19SJun-ichiro itojun Hagino 	/* first, try to get it from the interface itself */
362686cdd19SJun-ichiro itojun Hagino 	if (get_hw_ifid(ifp0, in6) == 0) {
36333841545SHajimu UMEMOTO 		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
36433841545SHajimu UMEMOTO 		    if_name(ifp0)));
365686cdd19SJun-ichiro itojun Hagino 		goto success;
366686cdd19SJun-ichiro itojun Hagino 	}
367686cdd19SJun-ichiro itojun Hagino 
368686cdd19SJun-ichiro itojun Hagino 	/* try secondary EUI64 source. this basically is for ATM PVC */
369686cdd19SJun-ichiro itojun Hagino 	if (altifp && get_hw_ifid(altifp, in6) == 0) {
37033841545SHajimu UMEMOTO 		nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
37133841545SHajimu UMEMOTO 		    if_name(ifp0), if_name(altifp)));
372686cdd19SJun-ichiro itojun Hagino 		goto success;
373686cdd19SJun-ichiro itojun Hagino 	}
374686cdd19SJun-ichiro itojun Hagino 
375686cdd19SJun-ichiro itojun Hagino 	/* next, try to get it from some other hardware interface */
376b30a244cSJeffrey Hsu 	IFNET_RLOCK();
3777efe5d92SHajimu UMEMOTO 	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
378686cdd19SJun-ichiro itojun Hagino 		if (ifp == ifp0)
379686cdd19SJun-ichiro itojun Hagino 			continue;
380686cdd19SJun-ichiro itojun Hagino 		if (get_hw_ifid(ifp, in6) != 0)
381686cdd19SJun-ichiro itojun Hagino 			continue;
382686cdd19SJun-ichiro itojun Hagino 
383686cdd19SJun-ichiro itojun Hagino 		/*
384686cdd19SJun-ichiro itojun Hagino 		 * to borrow ifid from other interface, ifid needs to be
385686cdd19SJun-ichiro itojun Hagino 		 * globally unique
386686cdd19SJun-ichiro itojun Hagino 		 */
387686cdd19SJun-ichiro itojun Hagino 		if (IFID_UNIVERSAL(in6)) {
38833841545SHajimu UMEMOTO 			nd6log((LOG_DEBUG,
38933841545SHajimu UMEMOTO 			    "%s: borrow interface identifier from %s\n",
39033841545SHajimu UMEMOTO 			    if_name(ifp0), if_name(ifp)));
391b30a244cSJeffrey Hsu 			IFNET_RUNLOCK();
392686cdd19SJun-ichiro itojun Hagino 			goto success;
393686cdd19SJun-ichiro itojun Hagino 		}
394686cdd19SJun-ichiro itojun Hagino 	}
395b30a244cSJeffrey Hsu 	IFNET_RUNLOCK();
396686cdd19SJun-ichiro itojun Hagino 
397686cdd19SJun-ichiro itojun Hagino 	/* last resort: get from random number source */
398686cdd19SJun-ichiro itojun Hagino 	if (get_rand_ifid(ifp, in6) == 0) {
39933841545SHajimu UMEMOTO 		nd6log((LOG_DEBUG,
40033841545SHajimu UMEMOTO 		    "%s: interface identifier generated by random number\n",
40133841545SHajimu UMEMOTO 		    if_name(ifp0)));
402686cdd19SJun-ichiro itojun Hagino 		goto success;
403686cdd19SJun-ichiro itojun Hagino 	}
404686cdd19SJun-ichiro itojun Hagino 
405de9c893eSJun-ichiro itojun Hagino 	printf("%s: failed to get interface identifier\n", if_name(ifp0));
406686cdd19SJun-ichiro itojun Hagino 	return -1;
407686cdd19SJun-ichiro itojun Hagino 
408686cdd19SJun-ichiro itojun Hagino success:
4097efe5d92SHajimu UMEMOTO 	nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
4107efe5d92SHajimu UMEMOTO 	    if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
4117efe5d92SHajimu UMEMOTO 	    in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
41233841545SHajimu UMEMOTO 	    in6->s6_addr[14], in6->s6_addr[15]));
413686cdd19SJun-ichiro itojun Hagino 	return 0;
414686cdd19SJun-ichiro itojun Hagino }
415686cdd19SJun-ichiro itojun Hagino 
416686cdd19SJun-ichiro itojun Hagino static int
417686cdd19SJun-ichiro itojun Hagino in6_ifattach_linklocal(ifp, altifp)
418686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;
419686cdd19SJun-ichiro itojun Hagino 	struct ifnet *altifp;	/* secondary EUI64 source */
420686cdd19SJun-ichiro itojun Hagino {
421686cdd19SJun-ichiro itojun Hagino 	struct in6_ifaddr *ia;
42233841545SHajimu UMEMOTO 	struct in6_aliasreq ifra;
42333841545SHajimu UMEMOTO 	struct nd_prefix pr0;
42433841545SHajimu UMEMOTO 	int i, error;
425686cdd19SJun-ichiro itojun Hagino 
426686cdd19SJun-ichiro itojun Hagino 	/*
42733841545SHajimu UMEMOTO 	 * configure link-local address.
428686cdd19SJun-ichiro itojun Hagino 	 */
42933841545SHajimu UMEMOTO 	bzero(&ifra, sizeof(ifra));
430686cdd19SJun-ichiro itojun Hagino 
43133841545SHajimu UMEMOTO 	/*
43233841545SHajimu UMEMOTO 	 * in6_update_ifa() does not use ifra_name, but we accurately set it
43333841545SHajimu UMEMOTO 	 * for safety.
43433841545SHajimu UMEMOTO 	 */
43533841545SHajimu UMEMOTO 	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
43633841545SHajimu UMEMOTO 
43733841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_family = AF_INET6;
43833841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
43933841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
44033841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */
44133841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
44233841545SHajimu UMEMOTO 	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
44333841545SHajimu UMEMOTO 		ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
44433841545SHajimu UMEMOTO 		ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
44533841545SHajimu UMEMOTO 	} else {
44633841545SHajimu UMEMOTO 		if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
44733841545SHajimu UMEMOTO 			nd6log((LOG_ERR,
44833841545SHajimu UMEMOTO 			    "%s: no ifid available\n", if_name(ifp)));
4497efe5d92SHajimu UMEMOTO 			return (-1);
45033841545SHajimu UMEMOTO 		}
45133841545SHajimu UMEMOTO 	}
45233841545SHajimu UMEMOTO 
45333841545SHajimu UMEMOTO 	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
45433841545SHajimu UMEMOTO 	ifra.ifra_prefixmask.sin6_family = AF_INET6;
45533841545SHajimu UMEMOTO 	ifra.ifra_prefixmask.sin6_addr = in6mask64;
45633841545SHajimu UMEMOTO 	/* link-local addresses should NEVER expire. */
45733841545SHajimu UMEMOTO 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
45833841545SHajimu UMEMOTO 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
459686cdd19SJun-ichiro itojun Hagino 
46033841545SHajimu UMEMOTO 	/*
46133841545SHajimu UMEMOTO 	 * Do not let in6_update_ifa() do DAD, since we need a random delay
46288ff5695SSUZUKI Shinsuke 	 * before sending an NS at the first time the interface becomes up.
46333841545SHajimu UMEMOTO 	 * Instead, in6_if_up() will start DAD with a proper random delay.
46433841545SHajimu UMEMOTO 	 */
46533841545SHajimu UMEMOTO 	ifra.ifra_flags |= IN6_IFF_NODAD;
466686cdd19SJun-ichiro itojun Hagino 
46733841545SHajimu UMEMOTO 	/*
46833841545SHajimu UMEMOTO 	 * Now call in6_update_ifa() to do a bunch of procedures to configure
46933841545SHajimu UMEMOTO 	 * a link-local address. We can set NULL to the 3rd argument, because
47088ff5695SSUZUKI Shinsuke 	 * we know there's no other link-local address on the interface
47188ff5695SSUZUKI Shinsuke 	 * and therefore we are adding one (instead of updating one).
47233841545SHajimu UMEMOTO 	 */
47333841545SHajimu UMEMOTO 	if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
47433841545SHajimu UMEMOTO 		/*
47533841545SHajimu UMEMOTO 		 * XXX: When the interface does not support IPv6, this call
47633841545SHajimu UMEMOTO 		 * would fail in the SIOCSIFADDR ioctl.  I believe the
47733841545SHajimu UMEMOTO 		 * notification is rather confusing in this case, so just
4787efe5d92SHajimu UMEMOTO 		 * suppress it.  (jinmei@kame.net 20010130)
47933841545SHajimu UMEMOTO 		 */
48033841545SHajimu UMEMOTO 		if (error != EAFNOSUPPORT)
48133841545SHajimu UMEMOTO 			log(LOG_NOTICE, "in6_ifattach_linklocal: failed to "
48233841545SHajimu UMEMOTO 			    "configure a link-local address on %s "
48333841545SHajimu UMEMOTO 			    "(errno=%d)\n",
48433841545SHajimu UMEMOTO 			    if_name(ifp), error);
48533841545SHajimu UMEMOTO 		return (-1);
486686cdd19SJun-ichiro itojun Hagino 	}
48733841545SHajimu UMEMOTO 
48833841545SHajimu UMEMOTO 	/*
48933841545SHajimu UMEMOTO 	 * Adjust ia6_flags so that in6_if_up will perform DAD.
49033841545SHajimu UMEMOTO 	 * XXX: Some P2P interfaces seem not to send packets just after
49133841545SHajimu UMEMOTO 	 * becoming up, so we skip p2p interfaces for safety.
49233841545SHajimu UMEMOTO 	 */
49333841545SHajimu UMEMOTO 	ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
49433841545SHajimu UMEMOTO #ifdef DIAGNOSTIC
49533841545SHajimu UMEMOTO 	if (!ia) {
49633841545SHajimu UMEMOTO 		panic("ia == NULL in in6_ifattach_linklocal");
49733841545SHajimu UMEMOTO 		/* NOTREACHED */
498686cdd19SJun-ichiro itojun Hagino 	}
499686cdd19SJun-ichiro itojun Hagino #endif
50033841545SHajimu UMEMOTO 	if (in6if_do_dad(ifp) && (ifp->if_flags & IFF_POINTOPOINT) == 0) {
50133841545SHajimu UMEMOTO 		ia->ia6_flags &= ~IN6_IFF_NODAD;
50233841545SHajimu UMEMOTO 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
50333841545SHajimu UMEMOTO 	}
504686cdd19SJun-ichiro itojun Hagino 
50533841545SHajimu UMEMOTO 	/*
5067efe5d92SHajimu UMEMOTO 	 * Make the link-local prefix (fe80::%link/64) as on-link.
50733841545SHajimu UMEMOTO 	 * Since we'd like to manage prefixes separately from addresses,
50833841545SHajimu UMEMOTO 	 * we make an ND6 prefix structure for the link-local prefix,
50933841545SHajimu UMEMOTO 	 * and add it to the prefix list as a never-expire prefix.
51033841545SHajimu UMEMOTO 	 * XXX: this change might affect some existing code base...
51133841545SHajimu UMEMOTO 	 */
51233841545SHajimu UMEMOTO 	bzero(&pr0, sizeof(pr0));
51333841545SHajimu UMEMOTO 	pr0.ndpr_ifp = ifp;
51433841545SHajimu UMEMOTO 	/* this should be 64 at this moment. */
51533841545SHajimu UMEMOTO 	pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
51633841545SHajimu UMEMOTO 	pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr;
51733841545SHajimu UMEMOTO 	pr0.ndpr_prefix = ifra.ifra_addr;
51833841545SHajimu UMEMOTO 	/* apply the mask for safety. (nd6_prelist_add will apply it again) */
51933841545SHajimu UMEMOTO 	for (i = 0; i < 4; i++) {
52033841545SHajimu UMEMOTO 		pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
52133841545SHajimu UMEMOTO 		    in6mask64.s6_addr32[i];
52233841545SHajimu UMEMOTO 	}
52333841545SHajimu UMEMOTO 	/*
52433841545SHajimu UMEMOTO 	 * Initialize parameters.  The link-local prefix must always be
52533841545SHajimu UMEMOTO 	 * on-link, and its lifetimes never expire.
52633841545SHajimu UMEMOTO 	 */
52733841545SHajimu UMEMOTO 	pr0.ndpr_raf_onlink = 1;
52833841545SHajimu UMEMOTO 	pr0.ndpr_raf_auto = 1;	/* probably meaningless */
52933841545SHajimu UMEMOTO 	pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
53033841545SHajimu UMEMOTO 	pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
53133841545SHajimu UMEMOTO 	/*
53233841545SHajimu UMEMOTO 	 * Since there is no other link-local addresses, nd6_prefix_lookup()
53333841545SHajimu UMEMOTO 	 * probably returns NULL.  However, we cannot always expect the result.
53433841545SHajimu UMEMOTO 	 * For example, if we first remove the (only) existing link-local
53533841545SHajimu UMEMOTO 	 * address, and then reconfigure another one, the prefix is still
53633841545SHajimu UMEMOTO 	 * valid with referring to the old link-local address.
53733841545SHajimu UMEMOTO 	 */
53833841545SHajimu UMEMOTO 	if (nd6_prefix_lookup(&pr0) == NULL) {
53933841545SHajimu UMEMOTO 		if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
54033841545SHajimu UMEMOTO 			return (error);
541686cdd19SJun-ichiro itojun Hagino 	}
542686cdd19SJun-ichiro itojun Hagino 
543686cdd19SJun-ichiro itojun Hagino 	return 0;
544686cdd19SJun-ichiro itojun Hagino }
545686cdd19SJun-ichiro itojun Hagino 
546686cdd19SJun-ichiro itojun Hagino static int
547686cdd19SJun-ichiro itojun Hagino in6_ifattach_loopback(ifp)
548686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;	/* must be IFT_LOOP */
549686cdd19SJun-ichiro itojun Hagino {
55033841545SHajimu UMEMOTO 	struct in6_aliasreq ifra;
55133841545SHajimu UMEMOTO 	int error;
55233841545SHajimu UMEMOTO 
55333841545SHajimu UMEMOTO 	bzero(&ifra, sizeof(ifra));
554686cdd19SJun-ichiro itojun Hagino 
555686cdd19SJun-ichiro itojun Hagino 	/*
55633841545SHajimu UMEMOTO 	 * in6_update_ifa() does not use ifra_name, but we accurately set it
55733841545SHajimu UMEMOTO 	 * for safety.
558686cdd19SJun-ichiro itojun Hagino 	 */
55933841545SHajimu UMEMOTO 	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
560686cdd19SJun-ichiro itojun Hagino 
56133841545SHajimu UMEMOTO 	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
56233841545SHajimu UMEMOTO 	ifra.ifra_prefixmask.sin6_family = AF_INET6;
56333841545SHajimu UMEMOTO 	ifra.ifra_prefixmask.sin6_addr = in6mask128;
564686cdd19SJun-ichiro itojun Hagino 
565686cdd19SJun-ichiro itojun Hagino 	/*
566686cdd19SJun-ichiro itojun Hagino 	 * Always initialize ia_dstaddr (= broadcast address) to loopback
56733841545SHajimu UMEMOTO 	 * address.  Follows IPv4 practice - see in_ifinit().
568686cdd19SJun-ichiro itojun Hagino 	 */
56933841545SHajimu UMEMOTO 	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
57033841545SHajimu UMEMOTO 	ifra.ifra_dstaddr.sin6_family = AF_INET6;
57133841545SHajimu UMEMOTO 	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
572686cdd19SJun-ichiro itojun Hagino 
57333841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
57433841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_family = AF_INET6;
57533841545SHajimu UMEMOTO 	ifra.ifra_addr.sin6_addr = in6addr_loopback;
576686cdd19SJun-ichiro itojun Hagino 
57733841545SHajimu UMEMOTO 	/* the loopback  address should NEVER expire. */
57833841545SHajimu UMEMOTO 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
57933841545SHajimu UMEMOTO 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
580686cdd19SJun-ichiro itojun Hagino 
58188ff5695SSUZUKI Shinsuke 	/* we don't need to perform DAD on loopback interfaces. */
58233841545SHajimu UMEMOTO 	ifra.ifra_flags |= IN6_IFF_NODAD;
58333841545SHajimu UMEMOTO 
58433841545SHajimu UMEMOTO 	/* skip registration to the prefix list. XXX should be temporary. */
58533841545SHajimu UMEMOTO 	ifra.ifra_flags |= IN6_IFF_NOPFX;
58633841545SHajimu UMEMOTO 
58733841545SHajimu UMEMOTO 	/*
58888ff5695SSUZUKI Shinsuke 	 * We are sure that this is a newly assigned address, so we can set
58988ff5695SSUZUKI Shinsuke 	 * NULL to the 3rd arg.
59033841545SHajimu UMEMOTO 	 */
59133841545SHajimu UMEMOTO 	if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
59233841545SHajimu UMEMOTO 		log(LOG_ERR, "in6_ifattach_loopback: failed to configure "
59333841545SHajimu UMEMOTO 		    "the loopback address on %s (errno=%d)\n",
59433841545SHajimu UMEMOTO 		    if_name(ifp), error);
59533841545SHajimu UMEMOTO 		return (-1);
596686cdd19SJun-ichiro itojun Hagino 	}
597686cdd19SJun-ichiro itojun Hagino 
598686cdd19SJun-ichiro itojun Hagino 	return 0;
599686cdd19SJun-ichiro itojun Hagino }
600686cdd19SJun-ichiro itojun Hagino 
601686cdd19SJun-ichiro itojun Hagino /*
602686cdd19SJun-ichiro itojun Hagino  * compute NI group address, based on the current hostname setting.
603686cdd19SJun-ichiro itojun Hagino  * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
604686cdd19SJun-ichiro itojun Hagino  *
605686cdd19SJun-ichiro itojun Hagino  * when ifp == NULL, the caller is responsible for filling scopeid.
606686cdd19SJun-ichiro itojun Hagino  */
60733841545SHajimu UMEMOTO int
60833841545SHajimu UMEMOTO in6_nigroup(ifp, name, namelen, in6)
609686cdd19SJun-ichiro itojun Hagino 	struct ifnet *ifp;
610686cdd19SJun-ichiro itojun Hagino 	const char *name;
611686cdd19SJun-ichiro itojun Hagino 	int namelen;
612686cdd19SJun-ichiro itojun Hagino 	struct in6_addr *in6;
613686cdd19SJun-ichiro itojun Hagino {
614686cdd19SJun-ichiro itojun Hagino 	const char *p;
61533841545SHajimu UMEMOTO 	u_char *q;
616686cdd19SJun-ichiro itojun Hagino 	MD5_CTX ctxt;
617686cdd19SJun-ichiro itojun Hagino 	u_int8_t digest[16];
618686cdd19SJun-ichiro itojun Hagino 	char l;
61933841545SHajimu UMEMOTO 	char n[64];	/* a single label must not exceed 63 chars */
620686cdd19SJun-ichiro itojun Hagino 
621686cdd19SJun-ichiro itojun Hagino 	if (!namelen || !name)
622686cdd19SJun-ichiro itojun Hagino 		return -1;
623686cdd19SJun-ichiro itojun Hagino 
624686cdd19SJun-ichiro itojun Hagino 	p = name;
625686cdd19SJun-ichiro itojun Hagino 	while (p && *p && *p != '.' && p - name < namelen)
626686cdd19SJun-ichiro itojun Hagino 		p++;
62733841545SHajimu UMEMOTO 	if (p - name > sizeof(n) - 1)
628686cdd19SJun-ichiro itojun Hagino 		return -1;	/* label too long */
629686cdd19SJun-ichiro itojun Hagino 	l = p - name;
63033841545SHajimu UMEMOTO 	strncpy(n, name, l);
63133841545SHajimu UMEMOTO 	n[(int)l] = '\0';
63233841545SHajimu UMEMOTO 	for (q = n; *q; q++) {
63333841545SHajimu UMEMOTO 		if ('A' <= *q && *q <= 'Z')
63433841545SHajimu UMEMOTO 			*q = *q - 'A' + 'a';
63533841545SHajimu UMEMOTO 	}
636686cdd19SJun-ichiro itojun Hagino 
637686cdd19SJun-ichiro itojun Hagino 	/* generate 8 bytes of pseudo-random value. */
638686cdd19SJun-ichiro itojun Hagino 	bzero(&ctxt, sizeof(ctxt));
639686cdd19SJun-ichiro itojun Hagino 	MD5Init(&ctxt);
640686cdd19SJun-ichiro itojun Hagino 	MD5Update(&ctxt, &l, sizeof(l));
64133841545SHajimu UMEMOTO 	MD5Update(&ctxt, n, l);
642686cdd19SJun-ichiro itojun Hagino 	MD5Final(digest, &ctxt);
643686cdd19SJun-ichiro itojun Hagino 
644686cdd19SJun-ichiro itojun Hagino 	bzero(in6, sizeof(*in6));
645686cdd19SJun-ichiro itojun Hagino 	in6->s6_addr16[0] = htons(0xff02);
646686cdd19SJun-ichiro itojun Hagino 	if (ifp)
647686cdd19SJun-ichiro itojun Hagino 		in6->s6_addr16[1] = htons(ifp->if_index);
648686cdd19SJun-ichiro itojun Hagino 	in6->s6_addr8[11] = 2;
649686cdd19SJun-ichiro itojun Hagino 	bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
650686cdd19SJun-ichiro itojun Hagino 
651686cdd19SJun-ichiro itojun Hagino 	return 0;
652686cdd19SJun-ichiro itojun Hagino }
653686cdd19SJun-ichiro itojun Hagino 
65482cd038dSYoshinobu Inoue /*
655686cdd19SJun-ichiro itojun Hagino  * XXX multiple loopback interface needs more care.  for instance,
656686cdd19SJun-ichiro itojun Hagino  * nodelocal address needs to be configured onto only one of them.
657686cdd19SJun-ichiro itojun Hagino  * XXX multiple link-local address case
65882cd038dSYoshinobu Inoue  */
65982cd038dSYoshinobu Inoue void
660686cdd19SJun-ichiro itojun Hagino in6_ifattach(ifp, altifp)
66182cd038dSYoshinobu Inoue 	struct ifnet *ifp;
662686cdd19SJun-ichiro itojun Hagino 	struct ifnet *altifp;	/* secondary EUI64 source */
66382cd038dSYoshinobu Inoue {
664686cdd19SJun-ichiro itojun Hagino 	struct in6_ifaddr *ia;
665686cdd19SJun-ichiro itojun Hagino 	struct in6_addr in6;
66633841545SHajimu UMEMOTO 
66733841545SHajimu UMEMOTO 	/* some of the interfaces are inherently not IPv6 capable */
66833841545SHajimu UMEMOTO 	switch (ifp->if_type) {
6697efe5d92SHajimu UMEMOTO #ifdef IFT_BRIDGE	/* OpenBSD 2.8, NetBSD 1.6 */
67033841545SHajimu UMEMOTO 	case IFT_BRIDGE:
67133841545SHajimu UMEMOTO #endif
672cc5934f5SMax Laier 	case IFT_PFLOG:
673cc5934f5SMax Laier 	case IFT_PFSYNC:
674a9771948SGleb Smirnoff 	case IFT_CARP:
675cc5934f5SMax Laier 		return;
67633841545SHajimu UMEMOTO 	}
67782cd038dSYoshinobu Inoue 
67882cd038dSYoshinobu Inoue 	/*
679686cdd19SJun-ichiro itojun Hagino 	 * quirks based on interface type
68082cd038dSYoshinobu Inoue 	 */
681686cdd19SJun-ichiro itojun Hagino 	switch (ifp->if_type) {
682686cdd19SJun-ichiro itojun Hagino #ifdef IFT_STF
683686cdd19SJun-ichiro itojun Hagino 	case IFT_STF:
68482cd038dSYoshinobu Inoue 		/*
68588ff5695SSUZUKI Shinsuke 		 * 6to4 interface is a very special kind of beast.
68688ff5695SSUZUKI Shinsuke 		 * no multicast, no linklocal.  RFC2529 specifies how to make
68788ff5695SSUZUKI Shinsuke 		 * linklocals for 6to4 interface, but there's no use and
68888ff5695SSUZUKI Shinsuke 		 * it is rather harmful to have one.
68982cd038dSYoshinobu Inoue 		 */
690686cdd19SJun-ichiro itojun Hagino 		goto statinit;
691686cdd19SJun-ichiro itojun Hagino #endif
69282cd038dSYoshinobu Inoue 	default:
69382cd038dSYoshinobu Inoue 		break;
69482cd038dSYoshinobu Inoue 	}
69582cd038dSYoshinobu Inoue 
696686cdd19SJun-ichiro itojun Hagino 	/*
697686cdd19SJun-ichiro itojun Hagino 	 * usually, we require multicast capability to the interface
698686cdd19SJun-ichiro itojun Hagino 	 */
699686cdd19SJun-ichiro itojun Hagino 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
70033841545SHajimu UMEMOTO 		log(LOG_INFO, "in6_ifattach: "
70133841545SHajimu UMEMOTO 		    "%s is not multicast capable, IPv6 not enabled\n",
702686cdd19SJun-ichiro itojun Hagino 		    if_name(ifp));
70382cd038dSYoshinobu Inoue 		return;
70482cd038dSYoshinobu Inoue 	}
705686cdd19SJun-ichiro itojun Hagino 
706686cdd19SJun-ichiro itojun Hagino 	/*
70733841545SHajimu UMEMOTO 	 * assign loopback address for loopback interface.
70833841545SHajimu UMEMOTO 	 * XXX multiple loopback interface case.
709686cdd19SJun-ichiro itojun Hagino 	 */
71033841545SHajimu UMEMOTO 	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
711686cdd19SJun-ichiro itojun Hagino 		in6 = in6addr_loopback;
712686cdd19SJun-ichiro itojun Hagino 		if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
713686cdd19SJun-ichiro itojun Hagino 			if (in6_ifattach_loopback(ifp) != 0)
714686cdd19SJun-ichiro itojun Hagino 				return;
71582cd038dSYoshinobu Inoue 		}
716686cdd19SJun-ichiro itojun Hagino 	}
717686cdd19SJun-ichiro itojun Hagino 
71833841545SHajimu UMEMOTO 	/*
71933841545SHajimu UMEMOTO 	 * assign a link-local address, if there's none.
72033841545SHajimu UMEMOTO 	 */
72133841545SHajimu UMEMOTO 	if (ip6_auto_linklocal) {
72233841545SHajimu UMEMOTO 		ia = in6ifa_ifpforlinklocal(ifp, 0);
72333841545SHajimu UMEMOTO 		if (ia == NULL) {
72433841545SHajimu UMEMOTO 			if (in6_ifattach_linklocal(ifp, altifp) == 0) {
72533841545SHajimu UMEMOTO 				/* linklocal address assigned */
72633841545SHajimu UMEMOTO 			} else {
72733841545SHajimu UMEMOTO 				/* failed to assign linklocal address. bark? */
728686cdd19SJun-ichiro itojun Hagino 			}
72933841545SHajimu UMEMOTO 		}
73033841545SHajimu UMEMOTO 	}
73133841545SHajimu UMEMOTO 
73233841545SHajimu UMEMOTO #ifdef IFT_STF			/* XXX */
73333841545SHajimu UMEMOTO statinit:
734686cdd19SJun-ichiro itojun Hagino #endif
73582cd038dSYoshinobu Inoue 
73682cd038dSYoshinobu Inoue 	/* update dynamically. */
73782cd038dSYoshinobu Inoue 	if (in6_maxmtu < ifp->if_mtu)
73882cd038dSYoshinobu Inoue 		in6_maxmtu = ifp->if_mtu;
73982cd038dSYoshinobu Inoue }
74082cd038dSYoshinobu Inoue 
741686cdd19SJun-ichiro itojun Hagino /*
742686cdd19SJun-ichiro itojun Hagino  * NOTE: in6_ifdetach() does not support loopback if at this moment.
74333841545SHajimu UMEMOTO  * We don't need this function in bsdi, because interfaces are never removed
74433841545SHajimu UMEMOTO  * from the ifnet list in bsdi.
745686cdd19SJun-ichiro itojun Hagino  */
74682cd038dSYoshinobu Inoue void
74782cd038dSYoshinobu Inoue in6_ifdetach(ifp)
74882cd038dSYoshinobu Inoue 	struct ifnet *ifp;
74982cd038dSYoshinobu Inoue {
75082cd038dSYoshinobu Inoue 	struct in6_ifaddr *ia, *oia;
751686cdd19SJun-ichiro itojun Hagino 	struct ifaddr *ifa, *next;
75282cd038dSYoshinobu Inoue 	struct rtentry *rt;
75382cd038dSYoshinobu Inoue 	short rtflags;
754686cdd19SJun-ichiro itojun Hagino 	struct sockaddr_in6 sin6;
755686cdd19SJun-ichiro itojun Hagino 	struct in6_multi *in6m;
756686cdd19SJun-ichiro itojun Hagino 	struct in6_multi *in6m_next;
75782cd038dSYoshinobu Inoue 
758686cdd19SJun-ichiro itojun Hagino 	/* remove neighbor management table */
759686cdd19SJun-ichiro itojun Hagino 	nd6_purge(ifp);
760686cdd19SJun-ichiro itojun Hagino 
761686cdd19SJun-ichiro itojun Hagino 	/* nuke any of IPv6 addresses we have */
7627efe5d92SHajimu UMEMOTO 	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
763686cdd19SJun-ichiro itojun Hagino 		next = ifa->ifa_list.tqe_next;
764686cdd19SJun-ichiro itojun Hagino 		if (ifa->ifa_addr->sa_family != AF_INET6)
765686cdd19SJun-ichiro itojun Hagino 			continue;
76633841545SHajimu UMEMOTO 		in6_purgeaddr(ifa);
767686cdd19SJun-ichiro itojun Hagino 	}
768686cdd19SJun-ichiro itojun Hagino 
769686cdd19SJun-ichiro itojun Hagino 	/* undo everything done by in6_ifattach(), just in case */
7707efe5d92SHajimu UMEMOTO 	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
771686cdd19SJun-ichiro itojun Hagino 		next = ifa->ifa_list.tqe_next;
772686cdd19SJun-ichiro itojun Hagino 
77382cd038dSYoshinobu Inoue 		if (ifa->ifa_addr->sa_family != AF_INET6
77482cd038dSYoshinobu Inoue 		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
77582cd038dSYoshinobu Inoue 			continue;
77682cd038dSYoshinobu Inoue 		}
77782cd038dSYoshinobu Inoue 
77882cd038dSYoshinobu Inoue 		ia = (struct in6_ifaddr *)ifa;
77982cd038dSYoshinobu Inoue 
78082cd038dSYoshinobu Inoue 		/* remove from the routing table */
7817efe5d92SHajimu UMEMOTO 		if ((ia->ia_flags & IFA_ROUTE) &&
7827efe5d92SHajimu UMEMOTO 		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
78382cd038dSYoshinobu Inoue 			rtflags = rt->rt_flags;
78482cd038dSYoshinobu Inoue 			rtfree(rt);
7857efe5d92SHajimu UMEMOTO 			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
78682cd038dSYoshinobu Inoue 			    (struct sockaddr *)&ia->ia_addr,
78782cd038dSYoshinobu Inoue 			    (struct sockaddr *)&ia->ia_prefixmask,
78882cd038dSYoshinobu Inoue 			    rtflags, (struct rtentry **)0);
78982cd038dSYoshinobu Inoue 		}
79082cd038dSYoshinobu Inoue 
79182cd038dSYoshinobu Inoue 		/* remove from the linked list */
79282cd038dSYoshinobu Inoue 		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
793686cdd19SJun-ichiro itojun Hagino 		IFAFREE(&ia->ia_ifa);
79482cd038dSYoshinobu Inoue 
79582cd038dSYoshinobu Inoue 		/* also remove from the IPv6 address chain(itojun&jinmei) */
79682cd038dSYoshinobu Inoue 		oia = ia;
79782cd038dSYoshinobu Inoue 		if (oia == (ia = in6_ifaddr))
79882cd038dSYoshinobu Inoue 			in6_ifaddr = ia->ia_next;
79982cd038dSYoshinobu Inoue 		else {
80082cd038dSYoshinobu Inoue 			while (ia->ia_next && (ia->ia_next != oia))
80182cd038dSYoshinobu Inoue 				ia = ia->ia_next;
80282cd038dSYoshinobu Inoue 			if (ia->ia_next)
80382cd038dSYoshinobu Inoue 				ia->ia_next = oia->ia_next;
80433841545SHajimu UMEMOTO 			else {
80533841545SHajimu UMEMOTO 				nd6log((LOG_ERR,
8067efe5d92SHajimu UMEMOTO 				    "%s: didn't unlink in6ifaddr from list\n",
8077efe5d92SHajimu UMEMOTO 				    if_name(ifp)));
80833841545SHajimu UMEMOTO 			}
80982cd038dSYoshinobu Inoue 		}
81082cd038dSYoshinobu Inoue 
811686cdd19SJun-ichiro itojun Hagino 		IFAFREE(&oia->ia_ifa);
812686cdd19SJun-ichiro itojun Hagino 	}
813686cdd19SJun-ichiro itojun Hagino 
814686cdd19SJun-ichiro itojun Hagino 	/* leave from all multicast groups joined */
8157efe5d92SHajimu UMEMOTO 
816dcdc6667SBill Paul 	if (udbinfo.listhead != NULL)
817e43cc4aeSHajimu UMEMOTO 		in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);
818dcdc6667SBill Paul 	if (ripcbinfo.listhead != NULL)
819e43cc4aeSHajimu UMEMOTO 		in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);
8207efe5d92SHajimu UMEMOTO 
821686cdd19SJun-ichiro itojun Hagino 	for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {
822686cdd19SJun-ichiro itojun Hagino 		in6m_next = LIST_NEXT(in6m, in6m_entry);
823686cdd19SJun-ichiro itojun Hagino 		if (in6m->in6m_ifp != ifp)
824686cdd19SJun-ichiro itojun Hagino 			continue;
825686cdd19SJun-ichiro itojun Hagino 		in6_delmulti(in6m);
826686cdd19SJun-ichiro itojun Hagino 		in6m = NULL;
827686cdd19SJun-ichiro itojun Hagino 	}
828686cdd19SJun-ichiro itojun Hagino 
82933841545SHajimu UMEMOTO 	/*
83033841545SHajimu UMEMOTO 	 * remove neighbor management table.  we call it twice just to make
83133841545SHajimu UMEMOTO 	 * sure we nuke everything.  maybe we need just one call.
83233841545SHajimu UMEMOTO 	 * XXX: since the first call did not release addresses, some prefixes
83333841545SHajimu UMEMOTO 	 * might remain.  We should call nd6_purge() again to release the
83433841545SHajimu UMEMOTO 	 * prefixes after removing all addresses above.
83533841545SHajimu UMEMOTO 	 * (Or can we just delay calling nd6_purge until at this point?)
83633841545SHajimu UMEMOTO 	 */
837686cdd19SJun-ichiro itojun Hagino 	nd6_purge(ifp);
838686cdd19SJun-ichiro itojun Hagino 
839686cdd19SJun-ichiro itojun Hagino 	/* remove route to link-local allnodes multicast (ff02::1) */
840686cdd19SJun-ichiro itojun Hagino 	bzero(&sin6, sizeof(sin6));
841686cdd19SJun-ichiro itojun Hagino 	sin6.sin6_len = sizeof(struct sockaddr_in6);
842686cdd19SJun-ichiro itojun Hagino 	sin6.sin6_family = AF_INET6;
843686cdd19SJun-ichiro itojun Hagino 	sin6.sin6_addr = in6addr_linklocal_allnodes;
844686cdd19SJun-ichiro itojun Hagino 	sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
8459c63e9dbSSam Leffler 	/* XXX grab lock first to avoid LOR */
8463f02eaf3SDon Lewis 	if (rt_tables[AF_INET6] != NULL) {
8479c63e9dbSSam Leffler 		RADIX_NODE_HEAD_LOCK(rt_tables[AF_INET6]);
848e699b0aeSHajimu UMEMOTO 		rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
849d1dd20beSSam Leffler 		if (rt) {
8509c63e9dbSSam Leffler 			if (rt->rt_ifp == ifp)
8519c63e9dbSSam Leffler 				rtexpunge(rt);
8529c63e9dbSSam Leffler 			RTFREE_LOCKED(rt);
85382cd038dSYoshinobu Inoue 		}
8549c63e9dbSSam Leffler 		RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET6]);
85582cd038dSYoshinobu Inoue 	}
8563f02eaf3SDon Lewis }
85733841545SHajimu UMEMOTO 
85833841545SHajimu UMEMOTO void
85933841545SHajimu UMEMOTO in6_get_tmpifid(ifp, retbuf, baseid, generate)
86033841545SHajimu UMEMOTO 	struct ifnet *ifp;
86133841545SHajimu UMEMOTO 	u_int8_t *retbuf;
86233841545SHajimu UMEMOTO 	const u_int8_t *baseid;
86333841545SHajimu UMEMOTO 	int generate;
86433841545SHajimu UMEMOTO {
86533841545SHajimu UMEMOTO 	u_int8_t nullbuf[8];
86631b1bfe1SHajimu UMEMOTO 	struct nd_ifinfo *ndi = ND_IFINFO(ifp);
86733841545SHajimu UMEMOTO 
86833841545SHajimu UMEMOTO 	bzero(nullbuf, sizeof(nullbuf));
86933841545SHajimu UMEMOTO 	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
87033841545SHajimu UMEMOTO 		/* we've never created a random ID.  Create a new one. */
87133841545SHajimu UMEMOTO 		generate = 1;
87233841545SHajimu UMEMOTO 	}
87333841545SHajimu UMEMOTO 
87433841545SHajimu UMEMOTO 	if (generate) {
87533841545SHajimu UMEMOTO 		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
87633841545SHajimu UMEMOTO 
87733841545SHajimu UMEMOTO 		/* generate_tmp_ifid will update seedn and buf */
87833841545SHajimu UMEMOTO 		(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
87933841545SHajimu UMEMOTO 		    ndi->randomid);
88033841545SHajimu UMEMOTO 	}
88133841545SHajimu UMEMOTO 	bcopy(ndi->randomid, retbuf, 8);
88233841545SHajimu UMEMOTO }
88333841545SHajimu UMEMOTO 
88433841545SHajimu UMEMOTO void
88533841545SHajimu UMEMOTO in6_tmpaddrtimer(ignored_arg)
88633841545SHajimu UMEMOTO 	void *ignored_arg;
88733841545SHajimu UMEMOTO {
88833841545SHajimu UMEMOTO 	struct nd_ifinfo *ndi;
88933841545SHajimu UMEMOTO 	u_int8_t nullbuf[8];
89031b1bfe1SHajimu UMEMOTO 	struct ifnet *ifp;
89133841545SHajimu UMEMOTO 	int s = splnet();
89233841545SHajimu UMEMOTO 
89333841545SHajimu UMEMOTO 	callout_reset(&in6_tmpaddrtimer_ch,
89433841545SHajimu UMEMOTO 	    (ip6_temp_preferred_lifetime - ip6_desync_factor -
8957efe5d92SHajimu UMEMOTO 	    ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
89633841545SHajimu UMEMOTO 
89733841545SHajimu UMEMOTO 	bzero(nullbuf, sizeof(nullbuf));
89831b1bfe1SHajimu UMEMOTO 	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
89931b1bfe1SHajimu UMEMOTO 		ndi = ND_IFINFO(ifp);
90033841545SHajimu UMEMOTO 		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
90133841545SHajimu UMEMOTO 			/*
90233841545SHajimu UMEMOTO 			 * We've been generating a random ID on this interface.
90333841545SHajimu UMEMOTO 			 * Create a new one.
90433841545SHajimu UMEMOTO 			 */
90533841545SHajimu UMEMOTO 			(void)generate_tmp_ifid(ndi->randomseed0,
9067efe5d92SHajimu UMEMOTO 			    ndi->randomseed1, ndi->randomid);
90733841545SHajimu UMEMOTO 		}
90833841545SHajimu UMEMOTO 	}
90933841545SHajimu UMEMOTO 
91033841545SHajimu UMEMOTO 	splx(s);
91133841545SHajimu UMEMOTO }
912