in6_ifattach.c revision 160981
1171169Smlaier/*	$FreeBSD: head/sys/netinet6/in6_ifattach.c 160981 2006-08-04 21:27:40Z brooks $	*/
2171169Smlaier/*	$KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $	*/
3171169Smlaier
4171169Smlaier/*-
5171169Smlaier * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6171169Smlaier * All rights reserved.
7171169Smlaier *
8171169Smlaier * Redistribution and use in source and binary forms, with or without
9171169Smlaier * modification, are permitted provided that the following conditions
10171169Smlaier * are met:
11171169Smlaier * 1. Redistributions of source code must retain the above copyright
12171169Smlaier *    notice, this list of conditions and the following disclaimer.
13171169Smlaier * 2. Redistributions in binary form must reproduce the above copyright
14171169Smlaier *    notice, this list of conditions and the following disclaimer in the
15171169Smlaier *    documentation and/or other materials provided with the distribution.
16171169Smlaier * 3. Neither the name of the project nor the names of its contributors
17171169Smlaier *    may be used to endorse or promote products derived from this software
18171169Smlaier *    without specific prior written permission.
19171169Smlaier *
20171169Smlaier * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21171169Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22171169Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23171169Smlaier * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24171169Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25171169Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26171169Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27171169Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28171169Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29171169Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30171169Smlaier * SUCH DAMAGE.
31171169Smlaier */
32171169Smlaier
33171169Smlaier#include <sys/param.h>
34171169Smlaier#include <sys/systm.h>
35171169Smlaier#include <sys/malloc.h>
36171169Smlaier#include <sys/socket.h>
37171169Smlaier#include <sys/sockio.h>
38171169Smlaier#include <sys/kernel.h>
39171169Smlaier#include <sys/syslog.h>
40171169Smlaier#include <sys/md5.h>
41171169Smlaier
42171169Smlaier#include <net/if.h>
43171169Smlaier#include <net/if_dl.h>
44171169Smlaier#include <net/if_types.h>
45171169Smlaier#include <net/route.h>
46171169Smlaier
47171169Smlaier#include <netinet/in.h>
48171169Smlaier#include <netinet/in_var.h>
49171169Smlaier#include <netinet/if_ether.h>
50171169Smlaier#include <netinet/in_pcb.h>
51171169Smlaier
52171169Smlaier#include <netinet/ip6.h>
53171169Smlaier#include <netinet6/ip6_var.h>
54171169Smlaier#include <netinet6/in6_var.h>
55171169Smlaier#include <netinet6/in6_pcb.h>
56171169Smlaier#include <netinet6/in6_ifattach.h>
57171169Smlaier#include <netinet6/ip6_var.h>
58171169Smlaier#include <netinet6/nd6.h>
59171169Smlaier#include <netinet6/scope6_var.h>
60171169Smlaier
61171169Smlaierunsigned long in6_maxmtu = 0;
62171169Smlaier
63171169Smlaier#ifdef IP6_AUTO_LINKLOCAL
64171169Smlaierint ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
65171169Smlaier#else
66171169Smlaierint ip6_auto_linklocal = 1;	/* enable by default */
67171169Smlaier#endif
68171169Smlaier
69171169Smlaierstruct callout in6_tmpaddrtimer_ch;
70171169Smlaier
71171169Smlaierextern struct inpcbinfo udbinfo;
72171169Smlaierextern struct inpcbinfo ripcbinfo;
73171169Smlaier
74171169Smlaierstatic int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
75171169Smlaierstatic int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
76171169Smlaierstatic int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
77171169Smlaierstatic int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
78171169Smlaierstatic int in6_ifattach_loopback __P((struct ifnet *));
79171169Smlaier
80171169Smlaier#define EUI64_GBIT	0x01
81171169Smlaier#define EUI64_UBIT	0x02
82171169Smlaier#define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
83171169Smlaier#define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
84171169Smlaier#define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
85171169Smlaier#define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
86171169Smlaier#define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
87171169Smlaier
88171169Smlaier#define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
89171169Smlaier#define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
90171169Smlaier
91171169Smlaier/*
92171169Smlaier * Generate a last-resort interface identifier, when the machine has no
93171169Smlaier * IEEE802/EUI64 address sources.
94171169Smlaier * The goal here is to get an interface identifier that is
95171169Smlaier * (1) random enough and (2) does not change across reboot.
96171169Smlaier * We currently use MD5(hostname) for it.
97171169Smlaier */
98171169Smlaierstatic int
99171169Smlaierget_rand_ifid(ifp, in6)
100171169Smlaier	struct ifnet *ifp;
101171169Smlaier	struct in6_addr *in6;	/* upper 64bits are preserved */
102171169Smlaier{
103171169Smlaier	MD5_CTX ctxt;
104171169Smlaier	u_int8_t digest[16];
105171169Smlaier	int hostnamelen	= strlen(hostname);
106171169Smlaier
107171169Smlaier#if 0
108171169Smlaier	/* we need at least several letters as seed for ifid */
109171169Smlaier	if (hostnamelen < 3)
110171169Smlaier		return -1;
111171169Smlaier#endif
112171169Smlaier
113171169Smlaier	/* generate 8 bytes of pseudo-random value. */
114171169Smlaier	bzero(&ctxt, sizeof(ctxt));
115171169Smlaier	MD5Init(&ctxt);
116171169Smlaier	MD5Update(&ctxt, hostname, hostnamelen);
117171169Smlaier	MD5Final(digest, &ctxt);
118171169Smlaier
119171169Smlaier	/* assumes sizeof(digest) > sizeof(ifid) */
120171169Smlaier	bcopy(digest, &in6->s6_addr[8], 8);
121171169Smlaier
122171169Smlaier	/* make sure to set "u" bit to local, and "g" bit to individual. */
123171169Smlaier	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
124171169Smlaier	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
125171169Smlaier
126171169Smlaier	/* convert EUI64 into IPv6 interface identifier */
127171169Smlaier	EUI64_TO_IFID(in6);
128171169Smlaier
129171169Smlaier	return 0;
130171169Smlaier}
131171169Smlaier
132171169Smlaierstatic int
133171169Smlaiergenerate_tmp_ifid(seed0, seed1, ret)
134171169Smlaier	u_int8_t *seed0, *ret;
135171169Smlaier	const u_int8_t *seed1;
136171169Smlaier{
137171169Smlaier	MD5_CTX ctxt;
138171169Smlaier	u_int8_t seed[16], digest[16], nullbuf[8];
139171169Smlaier	u_int32_t val32;
140171169Smlaier
141171169Smlaier	/* If there's no hisotry, start with a random seed. */
142171169Smlaier	bzero(nullbuf, sizeof(nullbuf));
143171169Smlaier	if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
144171169Smlaier		int i;
145171169Smlaier
146171169Smlaier		for (i = 0; i < 2; i++) {
147171169Smlaier			val32 = arc4random();
148171169Smlaier			bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
149171169Smlaier		}
150171169Smlaier	} else
151171169Smlaier		bcopy(seed0, seed, 8);
152171169Smlaier
153171169Smlaier	/* copy the right-most 64-bits of the given address */
154171169Smlaier	/* XXX assumption on the size of IFID */
155171169Smlaier	bcopy(seed1, &seed[8], 8);
156171169Smlaier
157171169Smlaier	if (0) {		/* for debugging purposes only */
158171169Smlaier		int i;
159171169Smlaier
160171169Smlaier		printf("generate_tmp_ifid: new randomized ID from: ");
161171169Smlaier		for (i = 0; i < 16; i++)
162171169Smlaier			printf("%02x", seed[i]);
163171169Smlaier		printf(" ");
164171169Smlaier	}
165171169Smlaier
166171169Smlaier	/* generate 16 bytes of pseudo-random value. */
167171169Smlaier	bzero(&ctxt, sizeof(ctxt));
168171169Smlaier	MD5Init(&ctxt);
169171169Smlaier	MD5Update(&ctxt, seed, sizeof(seed));
170171169Smlaier	MD5Final(digest, &ctxt);
171171169Smlaier
172171169Smlaier	/*
173171169Smlaier	 * RFC 3041 3.2.1. (3)
174171169Smlaier	 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
175171169Smlaier	 * left-most bit is numbered 0) to zero.
176171169Smlaier	 */
177171169Smlaier	bcopy(digest, ret, 8);
178171169Smlaier	ret[0] &= ~EUI64_UBIT;
179171169Smlaier
180171169Smlaier	/*
181171169Smlaier	 * XXX: we'd like to ensure that the generated value is not zero
182171169Smlaier	 * for simplicity.  If the caclculated digest happens to be zero,
183171169Smlaier	 * use a random non-zero value as the last resort.
184171169Smlaier	 */
185171169Smlaier	if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
186171169Smlaier		nd6log((LOG_INFO,
187171169Smlaier		    "generate_tmp_ifid: computed MD5 value is zero.\n"));
188171169Smlaier
189171169Smlaier		val32 = arc4random();
190171169Smlaier		val32 = 1 + (val32 % (0xffffffff - 1));
191171169Smlaier	}
192171169Smlaier
193171169Smlaier	/*
194171169Smlaier	 * RFC 3041 3.2.1. (4)
195171169Smlaier	 * Take the rightmost 64-bits of the MD5 digest and save them in
196171169Smlaier	 * stable storage as the history value to be used in the next
197171169Smlaier	 * iteration of the algorithm.
198171169Smlaier	 */
199171169Smlaier	bcopy(&digest[8], seed0, 8);
200171169Smlaier
201171169Smlaier	if (0) {		/* for debugging purposes only */
202171169Smlaier		int i;
203171169Smlaier
204171169Smlaier		printf("to: ");
205171169Smlaier		for (i = 0; i < 16; i++)
206171169Smlaier			printf("%02x", digest[i]);
207171169Smlaier		printf("\n");
208171169Smlaier	}
209171169Smlaier
210171169Smlaier	return 0;
211171169Smlaier}
212171169Smlaier
213171169Smlaier/*
214171169Smlaier * Get interface identifier for the specified interface.
215171169Smlaier * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
216171169Smlaier */
217171169Smlaierint
218171169Smlaierin6_get_hw_ifid(ifp, in6)
219171169Smlaier	struct ifnet *ifp;
220171169Smlaier	struct in6_addr *in6;	/* upper 64bits are preserved */
221171169Smlaier{
222171169Smlaier	struct ifaddr *ifa;
223171169Smlaier	struct sockaddr_dl *sdl;
224171169Smlaier	u_int8_t *addr;
225171169Smlaier	size_t addrlen;
226171169Smlaier	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
227171169Smlaier	static u_int8_t allone[8] =
228171169Smlaier		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
229171169Smlaier
230171169Smlaier	for (ifa = ifp->if_addrlist.tqh_first;
231171169Smlaier	     ifa;
232171169Smlaier	     ifa = ifa->ifa_list.tqe_next) {
233171169Smlaier		if (ifa->ifa_addr->sa_family != AF_LINK)
234171169Smlaier			continue;
235171169Smlaier		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
236171169Smlaier		if (sdl == NULL)
237171169Smlaier			continue;
238171169Smlaier		if (sdl->sdl_alen == 0)
239171169Smlaier			continue;
240171169Smlaier
241171169Smlaier		goto found;
242171169Smlaier	}
243171169Smlaier
244171169Smlaier	return -1;
245171169Smlaier
246171169Smlaierfound:
247171169Smlaier	addr = LLADDR(sdl);
248171169Smlaier	addrlen = sdl->sdl_alen;
249171169Smlaier
250171169Smlaier	/* get EUI64 */
251171169Smlaier	switch (ifp->if_type) {
252171169Smlaier	case IFT_ETHER:
253171169Smlaier	case IFT_FDDI:
254171169Smlaier	case IFT_ISO88025:
255171169Smlaier	case IFT_ATM:
256171169Smlaier	case IFT_IEEE1394:
257171169Smlaier#ifdef IFT_IEEE80211
258171169Smlaier	case IFT_IEEE80211:
259171169Smlaier#endif
260171169Smlaier		/* IEEE802/EUI64 cases - what others? */
261171169Smlaier		/* IEEE1394 uses 16byte length address starting with EUI64 */
262171169Smlaier		if (addrlen > 8)
263171169Smlaier			addrlen = 8;
264171169Smlaier
265171169Smlaier		/* look at IEEE802/EUI64 only */
266171169Smlaier		if (addrlen != 8 && addrlen != 6)
267171169Smlaier			return -1;
268171169Smlaier
269171169Smlaier		/*
270171169Smlaier		 * check for invalid MAC address - on bsdi, we see it a lot
271171169Smlaier		 * since wildboar configures all-zero MAC on pccard before
272171169Smlaier		 * card insertion.
273171169Smlaier		 */
274171169Smlaier		if (bcmp(addr, allzero, addrlen) == 0)
275171169Smlaier			return -1;
276171169Smlaier		if (bcmp(addr, allone, addrlen) == 0)
277171169Smlaier			return -1;
278171169Smlaier
279171169Smlaier		/* make EUI64 address */
280171169Smlaier		if (addrlen == 8)
281171169Smlaier			bcopy(addr, &in6->s6_addr[8], 8);
282171169Smlaier		else if (addrlen == 6) {
283171169Smlaier			in6->s6_addr[8] = addr[0];
284171169Smlaier			in6->s6_addr[9] = addr[1];
285171169Smlaier			in6->s6_addr[10] = addr[2];
286171169Smlaier			in6->s6_addr[11] = 0xff;
287171169Smlaier			in6->s6_addr[12] = 0xfe;
288171169Smlaier			in6->s6_addr[13] = addr[3];
289171169Smlaier			in6->s6_addr[14] = addr[4];
290171169Smlaier			in6->s6_addr[15] = addr[5];
291171169Smlaier		}
292171169Smlaier		break;
293171169Smlaier
294171169Smlaier	case IFT_ARCNET:
295171169Smlaier		if (addrlen != 1)
296171169Smlaier			return -1;
297171169Smlaier		if (!addr[0])
298171169Smlaier			return -1;
299171169Smlaier
300171169Smlaier		bzero(&in6->s6_addr[8], 8);
301171169Smlaier		in6->s6_addr[15] = addr[0];
302171169Smlaier
303171169Smlaier		/*
304171169Smlaier		 * due to insufficient bitwidth, we mark it local.
305171169Smlaier		 */
306171169Smlaier		in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
307171169Smlaier		in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
308171169Smlaier		break;
309171169Smlaier
310171169Smlaier	case IFT_GIF:
311171169Smlaier#ifdef IFT_STF
312171169Smlaier	case IFT_STF:
313171169Smlaier#endif
314171169Smlaier		/*
315171169Smlaier		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
316171169Smlaier		 * however, IPv4 address is not very suitable as unique
317171169Smlaier		 * identifier source (can be renumbered).
318171169Smlaier		 * we don't do this.
319171169Smlaier		 */
320171169Smlaier		return -1;
321171169Smlaier
322171169Smlaier	default:
323171169Smlaier		return -1;
324171169Smlaier	}
325171169Smlaier
326171169Smlaier	/* sanity check: g bit must not indicate "group" */
327171169Smlaier	if (EUI64_GROUP(in6))
328171169Smlaier		return -1;
329171169Smlaier
330171169Smlaier	/* convert EUI64 into IPv6 interface identifier */
331171169Smlaier	EUI64_TO_IFID(in6);
332171169Smlaier
333171169Smlaier	/*
334171169Smlaier	 * sanity check: ifid must not be all zero, avoid conflict with
335171169Smlaier	 * subnet router anycast
336171169Smlaier	 */
337171169Smlaier	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
338171169Smlaier	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
339171169Smlaier		return -1;
340171169Smlaier	}
341171169Smlaier
342171169Smlaier	return 0;
343171169Smlaier}
344171169Smlaier
345171169Smlaier/*
346171169Smlaier * Get interface identifier for the specified interface.  If it is not
347171169Smlaier * available on ifp0, borrow interface identifier from other information
348171169Smlaier * sources.
349171169Smlaier */
350171169Smlaierstatic int
351171169Smlaierget_ifid(ifp0, altifp, in6)
352171169Smlaier	struct ifnet *ifp0;
353171169Smlaier	struct ifnet *altifp;	/* secondary EUI64 source */
354171169Smlaier	struct in6_addr *in6;
355171169Smlaier{
356171169Smlaier	struct ifnet *ifp;
357171169Smlaier
358171169Smlaier	/* first, try to get it from the interface itself */
359171169Smlaier	if (in6_get_hw_ifid(ifp0, in6) == 0) {
360171169Smlaier		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
361171169Smlaier		    if_name(ifp0)));
362171169Smlaier		goto success;
363171169Smlaier	}
364171169Smlaier
365171169Smlaier	/* try secondary EUI64 source. this basically is for ATM PVC */
366171169Smlaier	if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
367171169Smlaier		nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
368171169Smlaier		    if_name(ifp0), if_name(altifp)));
369171169Smlaier		goto success;
370171169Smlaier	}
371171169Smlaier
372171169Smlaier	/* next, try to get it from some other hardware interface */
373171169Smlaier	IFNET_RLOCK();
374171169Smlaier	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
375171169Smlaier		if (ifp == ifp0)
376171169Smlaier			continue;
377171169Smlaier		if (in6_get_hw_ifid(ifp, in6) != 0)
378171169Smlaier			continue;
379171169Smlaier
380171169Smlaier		/*
381171169Smlaier		 * to borrow ifid from other interface, ifid needs to be
382171169Smlaier		 * globally unique
383171169Smlaier		 */
384171169Smlaier		if (IFID_UNIVERSAL(in6)) {
385171169Smlaier			nd6log((LOG_DEBUG,
386171169Smlaier			    "%s: borrow interface identifier from %s\n",
387171169Smlaier			    if_name(ifp0), if_name(ifp)));
388171169Smlaier			IFNET_RUNLOCK();
389171169Smlaier			goto success;
390171169Smlaier		}
391171169Smlaier	}
392171169Smlaier	IFNET_RUNLOCK();
393171169Smlaier
394171169Smlaier	/* last resort: get from random number source */
395171169Smlaier	if (get_rand_ifid(ifp, in6) == 0) {
396171169Smlaier		nd6log((LOG_DEBUG,
397171169Smlaier		    "%s: interface identifier generated by random number\n",
398171169Smlaier		    if_name(ifp0)));
399171169Smlaier		goto success;
400171169Smlaier	}
401171169Smlaier
402171169Smlaier	printf("%s: failed to get interface identifier\n", if_name(ifp0));
403171169Smlaier	return -1;
404171169Smlaier
405171169Smlaiersuccess:
406171169Smlaier	nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
407171169Smlaier	    if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
408171169Smlaier	    in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
409171169Smlaier	    in6->s6_addr[14], in6->s6_addr[15]));
410171169Smlaier	return 0;
411171169Smlaier}
412171169Smlaier
413171169Smlaierstatic int
414171169Smlaierin6_ifattach_linklocal(ifp, altifp)
415171169Smlaier	struct ifnet *ifp;
416171169Smlaier	struct ifnet *altifp;	/* secondary EUI64 source */
417171169Smlaier{
418171169Smlaier	struct in6_ifaddr *ia;
419171169Smlaier	struct in6_aliasreq ifra;
420171169Smlaier	struct nd_prefixctl pr0;
421171169Smlaier	int i, error;
422171169Smlaier
423171169Smlaier	/*
424171169Smlaier	 * configure link-local address.
425171169Smlaier	 */
426171169Smlaier	bzero(&ifra, sizeof(ifra));
427171169Smlaier
428171169Smlaier	/*
429171169Smlaier	 * in6_update_ifa() does not use ifra_name, but we accurately set it
430171169Smlaier	 * for safety.
431171169Smlaier	 */
432171169Smlaier	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
433171169Smlaier
434171169Smlaier	ifra.ifra_addr.sin6_family = AF_INET6;
435171169Smlaier	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
436171169Smlaier	ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
437171169Smlaier	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
438171169Smlaier	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
439171169Smlaier		ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
440171169Smlaier		ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
441171169Smlaier	} else {
442171169Smlaier		if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
443171169Smlaier			nd6log((LOG_ERR,
444171169Smlaier			    "%s: no ifid available\n", if_name(ifp)));
445171169Smlaier			return (-1);
446171169Smlaier		}
447171169Smlaier	}
448171169Smlaier	if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
449171169Smlaier		return (-1);
450171169Smlaier
451171169Smlaier	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
452171169Smlaier	ifra.ifra_prefixmask.sin6_family = AF_INET6;
453171169Smlaier	ifra.ifra_prefixmask.sin6_addr = in6mask64;
454171169Smlaier	/* link-local addresses should NEVER expire. */
455171169Smlaier	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
456171169Smlaier	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
457171169Smlaier
458171169Smlaier	/*
459171169Smlaier	 * Now call in6_update_ifa() to do a bunch of procedures to configure
460171169Smlaier	 * a link-local address. We can set the 3rd argument to NULL, because
461171169Smlaier	 * we know there's no other link-local address on the interface
462171169Smlaier	 * and therefore we are adding one (instead of updating one).
463171169Smlaier	 */
464171169Smlaier	if ((error = in6_update_ifa(ifp, &ifra, NULL,
465171169Smlaier				    IN6_IFAUPDATE_DADDELAY)) != 0) {
466171169Smlaier		/*
467171169Smlaier		 * XXX: When the interface does not support IPv6, this call
468171169Smlaier		 * would fail in the SIOCSIFADDR ioctl.  I believe the
469171169Smlaier		 * notification is rather confusing in this case, so just
470171169Smlaier		 * suppress it.  (jinmei@kame.net 20010130)
471171169Smlaier		 */
472171169Smlaier		if (error != EAFNOSUPPORT)
473171169Smlaier			nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
474171169Smlaier			    "configure a link-local address on %s "
475171169Smlaier			    "(errno=%d)\n",
476171169Smlaier			    if_name(ifp), error));
477171169Smlaier		return (-1);
478171169Smlaier	}
479171169Smlaier
480171169Smlaier	ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
481171169Smlaier#ifdef DIAGNOSTIC
482171169Smlaier	if (!ia) {
483171169Smlaier		panic("ia == NULL in in6_ifattach_linklocal");
484171169Smlaier		/* NOTREACHED */
485171169Smlaier	}
486171169Smlaier#endif
487171169Smlaier
488171169Smlaier	/*
489171169Smlaier	 * Make the link-local prefix (fe80::%link/64) as on-link.
490171169Smlaier	 * Since we'd like to manage prefixes separately from addresses,
491171169Smlaier	 * we make an ND6 prefix structure for the link-local prefix,
492171169Smlaier	 * and add it to the prefix list as a never-expire prefix.
493171169Smlaier	 * XXX: this change might affect some existing code base...
494171169Smlaier	 */
495171169Smlaier	bzero(&pr0, sizeof(pr0));
496171169Smlaier	pr0.ndpr_ifp = ifp;
497171169Smlaier	/* this should be 64 at this moment. */
498171169Smlaier	pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
499171169Smlaier	pr0.ndpr_prefix = ifra.ifra_addr;
500171169Smlaier	/* apply the mask for safety. (nd6_prelist_add will apply it again) */
501171169Smlaier	for (i = 0; i < 4; i++) {
502171169Smlaier		pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
503171169Smlaier		    in6mask64.s6_addr32[i];
504171169Smlaier	}
505171169Smlaier	/*
506171169Smlaier	 * Initialize parameters.  The link-local prefix must always be
507171169Smlaier	 * on-link, and its lifetimes never expire.
508171169Smlaier	 */
509171169Smlaier	pr0.ndpr_raf_onlink = 1;
510171169Smlaier	pr0.ndpr_raf_auto = 1;	/* probably meaningless */
511171169Smlaier	pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
512171169Smlaier	pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
513171169Smlaier	/*
514171169Smlaier	 * Since there is no other link-local addresses, nd6_prefix_lookup()
515171169Smlaier	 * probably returns NULL.  However, we cannot always expect the result.
516171169Smlaier	 * For example, if we first remove the (only) existing link-local
517171169Smlaier	 * address, and then reconfigure another one, the prefix is still
518171169Smlaier	 * valid with referring to the old link-local address.
519171169Smlaier	 */
520171169Smlaier	if (nd6_prefix_lookup(&pr0) == NULL) {
521171169Smlaier		if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
522171169Smlaier			return (error);
523171169Smlaier	}
524171169Smlaier
525171169Smlaier	return 0;
526171169Smlaier}
527171169Smlaier
528171169Smlaierstatic int
529171169Smlaierin6_ifattach_loopback(ifp)
530171169Smlaier	struct ifnet *ifp;	/* must be IFT_LOOP */
531171169Smlaier{
532171169Smlaier	struct in6_aliasreq ifra;
533171169Smlaier	int error;
534171169Smlaier
535171169Smlaier	bzero(&ifra, sizeof(ifra));
536171169Smlaier
537171169Smlaier	/*
538171169Smlaier	 * in6_update_ifa() does not use ifra_name, but we accurately set it
539171169Smlaier	 * for safety.
540171169Smlaier	 */
541171169Smlaier	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
542171169Smlaier
543171169Smlaier	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
544171169Smlaier	ifra.ifra_prefixmask.sin6_family = AF_INET6;
545171169Smlaier	ifra.ifra_prefixmask.sin6_addr = in6mask128;
546171169Smlaier
547171169Smlaier	/*
548171169Smlaier	 * Always initialize ia_dstaddr (= broadcast address) to loopback
549171169Smlaier	 * address.  Follows IPv4 practice - see in_ifinit().
550171169Smlaier	 */
551171169Smlaier	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
552171169Smlaier	ifra.ifra_dstaddr.sin6_family = AF_INET6;
553171169Smlaier	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
554171169Smlaier
555171169Smlaier	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
556171169Smlaier	ifra.ifra_addr.sin6_family = AF_INET6;
557171169Smlaier	ifra.ifra_addr.sin6_addr = in6addr_loopback;
558171169Smlaier
559171169Smlaier	/* the loopback  address should NEVER expire. */
560171169Smlaier	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
561171169Smlaier	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
562171169Smlaier
563171169Smlaier	/* we don't need to perform DAD on loopback interfaces. */
564171169Smlaier	ifra.ifra_flags |= IN6_IFF_NODAD;
565171169Smlaier
566171169Smlaier	/* skip registration to the prefix list. XXX should be temporary. */
567171169Smlaier	ifra.ifra_flags |= IN6_IFF_NOPFX;
568171169Smlaier
569171169Smlaier	/*
570171169Smlaier	 * We are sure that this is a newly assigned address, so we can set
571171169Smlaier	 * NULL to the 3rd arg.
572171169Smlaier	 */
573171169Smlaier	if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
574171169Smlaier		nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
575171169Smlaier		    "the loopback address on %s (errno=%d)\n",
576171169Smlaier		    if_name(ifp), error));
577171169Smlaier		return (-1);
578171169Smlaier	}
579171169Smlaier
580171169Smlaier	return 0;
581171169Smlaier}
582171169Smlaier
583171169Smlaier/*
584171169Smlaier * compute NI group address, based on the current hostname setting.
585171169Smlaier * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
586171169Smlaier *
587171169Smlaier * when ifp == NULL, the caller is responsible for filling scopeid.
588171169Smlaier */
589171169Smlaierint
590171169Smlaierin6_nigroup(ifp, name, namelen, in6)
591171169Smlaier	struct ifnet *ifp;
592171169Smlaier	const char *name;
593171169Smlaier	int namelen;
594171169Smlaier	struct in6_addr *in6;
595171169Smlaier{
596171169Smlaier	const char *p;
597171169Smlaier	u_char *q;
598171169Smlaier	MD5_CTX ctxt;
599171169Smlaier	u_int8_t digest[16];
600171169Smlaier	char l;
601171169Smlaier	char n[64];	/* a single label must not exceed 63 chars */
602171169Smlaier
603171169Smlaier	if (!namelen || !name)
604171169Smlaier		return -1;
605171169Smlaier
606171169Smlaier	p = name;
607171169Smlaier	while (p && *p && *p != '.' && p - name < namelen)
608171169Smlaier		p++;
609171169Smlaier	if (p - name > sizeof(n) - 1)
610171169Smlaier		return -1;	/* label too long */
611171169Smlaier	l = p - name;
612171169Smlaier	strncpy(n, name, l);
613171169Smlaier	n[(int)l] = '\0';
614171169Smlaier	for (q = n; *q; q++) {
615171169Smlaier		if ('A' <= *q && *q <= 'Z')
616171169Smlaier			*q = *q - 'A' + 'a';
617171169Smlaier	}
618171169Smlaier
619171169Smlaier	/* generate 8 bytes of pseudo-random value. */
620171169Smlaier	bzero(&ctxt, sizeof(ctxt));
621171169Smlaier	MD5Init(&ctxt);
622171169Smlaier	MD5Update(&ctxt, &l, sizeof(l));
623171169Smlaier	MD5Update(&ctxt, n, l);
624171169Smlaier	MD5Final(digest, &ctxt);
625171169Smlaier
626171169Smlaier	bzero(in6, sizeof(*in6));
627171169Smlaier	in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
628171169Smlaier	in6->s6_addr8[11] = 2;
629171169Smlaier	bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
630171169Smlaier	if (in6_setscope(in6, ifp, NULL))
631171169Smlaier		return (-1); /* XXX: should not fail */
632171169Smlaier
633171169Smlaier	return 0;
634171169Smlaier}
635171169Smlaier
636171169Smlaier/*
637171169Smlaier * XXX multiple loopback interface needs more care.  for instance,
638171169Smlaier * nodelocal address needs to be configured onto only one of them.
639171169Smlaier * XXX multiple link-local address case
640171169Smlaier */
641171169Smlaiervoid
642171169Smlaierin6_ifattach(ifp, altifp)
643171169Smlaier	struct ifnet *ifp;
644171169Smlaier	struct ifnet *altifp;	/* secondary EUI64 source */
645171169Smlaier{
646171169Smlaier	struct in6_ifaddr *ia;
647171169Smlaier	struct in6_addr in6;
648171169Smlaier
649171169Smlaier	/* some of the interfaces are inherently not IPv6 capable */
650171169Smlaier	switch (ifp->if_type) {
651171169Smlaier	case IFT_PFLOG:
652171169Smlaier	case IFT_PFSYNC:
653171169Smlaier	case IFT_CARP:
654171169Smlaier		return;
655171169Smlaier	}
656171169Smlaier
657171169Smlaier	/*
658171169Smlaier	 * quirks based on interface type
659171169Smlaier	 */
660171169Smlaier	switch (ifp->if_type) {
661171169Smlaier#ifdef IFT_STF
662171169Smlaier	case IFT_STF:
663171169Smlaier		/*
664171169Smlaier		 * 6to4 interface is a very special kind of beast.
665171169Smlaier		 * no multicast, no linklocal.  RFC2529 specifies how to make
666171169Smlaier		 * linklocals for 6to4 interface, but there's no use and
667171169Smlaier		 * it is rather harmful to have one.
668171169Smlaier		 */
669171169Smlaier		goto statinit;
670171169Smlaier#endif
671171169Smlaier	default:
672171169Smlaier		break;
673171169Smlaier	}
674171169Smlaier
675171169Smlaier	/*
676171169Smlaier	 * usually, we require multicast capability to the interface
677171169Smlaier	 */
678171169Smlaier	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
679171169Smlaier		nd6log((LOG_INFO, "in6_ifattach: "
680171169Smlaier		    "%s is not multicast capable, IPv6 not enabled\n",
681171169Smlaier		    if_name(ifp)));
682171169Smlaier		return;
683171169Smlaier	}
684171169Smlaier
685171169Smlaier	/*
686171169Smlaier	 * assign loopback address for loopback interface.
687171169Smlaier	 * XXX multiple loopback interface case.
688171169Smlaier	 */
689171169Smlaier	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
690171169Smlaier		in6 = in6addr_loopback;
691171169Smlaier		if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
692171169Smlaier			if (in6_ifattach_loopback(ifp) != 0)
693171169Smlaier				return;
694171169Smlaier		}
695171169Smlaier	}
696171169Smlaier
697171169Smlaier	/*
698171169Smlaier	 * assign a link-local address, if there's none.
699171169Smlaier	 */
700171169Smlaier	if (ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) {
701171169Smlaier		ia = in6ifa_ifpforlinklocal(ifp, 0);
702171169Smlaier		if (ia == NULL) {
703171169Smlaier			if (in6_ifattach_linklocal(ifp, altifp) == 0) {
704171169Smlaier				/* linklocal address assigned */
705171169Smlaier			} else {
706171169Smlaier				/* failed to assign linklocal address. bark? */
707171169Smlaier			}
708171169Smlaier		}
709171169Smlaier	}
710171169Smlaier
711171169Smlaier#ifdef IFT_STF			/* XXX */
712171169Smlaierstatinit:
713171169Smlaier#endif
714171169Smlaier
715171169Smlaier	/* update dynamically. */
716171169Smlaier	if (in6_maxmtu < ifp->if_mtu)
717171169Smlaier		in6_maxmtu = ifp->if_mtu;
718171169Smlaier}
719171169Smlaier
720171169Smlaier/*
721171169Smlaier * NOTE: in6_ifdetach() does not support loopback if at this moment.
722171169Smlaier * We don't need this function in bsdi, because interfaces are never removed
723171169Smlaier * from the ifnet list in bsdi.
724171169Smlaier */
725171169Smlaiervoid
726171169Smlaierin6_ifdetach(ifp)
727171169Smlaier	struct ifnet *ifp;
728171169Smlaier{
729171169Smlaier	struct in6_ifaddr *ia, *oia;
730171169Smlaier	struct ifaddr *ifa, *next;
731171169Smlaier	struct rtentry *rt;
732171169Smlaier	short rtflags;
733171169Smlaier	struct sockaddr_in6 sin6;
734171169Smlaier	struct in6_multi *in6m;
735171169Smlaier	struct in6_multi *in6m_next;
736171169Smlaier
737171169Smlaier	/* remove neighbor management table */
738171169Smlaier	nd6_purge(ifp);
739171169Smlaier
740171169Smlaier	/* nuke any of IPv6 addresses we have */
741171169Smlaier	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
742171169Smlaier		next = ifa->ifa_list.tqe_next;
743171169Smlaier		if (ifa->ifa_addr->sa_family != AF_INET6)
744171169Smlaier			continue;
745171169Smlaier		in6_purgeaddr(ifa);
746171169Smlaier	}
747171169Smlaier
748171169Smlaier	/* undo everything done by in6_ifattach(), just in case */
749171169Smlaier	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
750171169Smlaier		next = ifa->ifa_list.tqe_next;
751171169Smlaier
752171169Smlaier		if (ifa->ifa_addr->sa_family != AF_INET6
753171169Smlaier		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
754171169Smlaier			continue;
755171169Smlaier		}
756171169Smlaier
757171169Smlaier		ia = (struct in6_ifaddr *)ifa;
758171169Smlaier
759171169Smlaier		/* remove from the routing table */
760171169Smlaier		if ((ia->ia_flags & IFA_ROUTE) &&
761171169Smlaier		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
762171169Smlaier			rtflags = rt->rt_flags;
763171169Smlaier			rtfree(rt);
764171169Smlaier			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
765171169Smlaier			    (struct sockaddr *)&ia->ia_addr,
766171169Smlaier			    (struct sockaddr *)&ia->ia_prefixmask,
767171169Smlaier			    rtflags, (struct rtentry **)0);
768171169Smlaier		}
769171169Smlaier
770171169Smlaier		/* remove from the linked list */
771171169Smlaier		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
772171169Smlaier		IFAFREE(&ia->ia_ifa);
773171169Smlaier
774171169Smlaier		/* also remove from the IPv6 address chain(itojun&jinmei) */
775171169Smlaier		oia = ia;
776171169Smlaier		if (oia == (ia = in6_ifaddr))
777171169Smlaier			in6_ifaddr = ia->ia_next;
778171169Smlaier		else {
779171169Smlaier			while (ia->ia_next && (ia->ia_next != oia))
780171169Smlaier				ia = ia->ia_next;
781171169Smlaier			if (ia->ia_next)
782171169Smlaier				ia->ia_next = oia->ia_next;
783171169Smlaier			else {
784171169Smlaier				nd6log((LOG_ERR,
785171169Smlaier				    "%s: didn't unlink in6ifaddr from list\n",
786171169Smlaier				    if_name(ifp)));
787171169Smlaier			}
788171169Smlaier		}
789171169Smlaier
790171169Smlaier		IFAFREE(&oia->ia_ifa);
791171169Smlaier	}
792171169Smlaier
793171169Smlaier	/* leave from all multicast groups joined */
794171169Smlaier
795171169Smlaier	in6_pcbpurgeif0(&udbinfo, ifp);
796171169Smlaier	in6_pcbpurgeif0(&ripcbinfo, ifp);
797171169Smlaier
798171169Smlaier	for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {
799171169Smlaier		in6m_next = LIST_NEXT(in6m, in6m_entry);
800171169Smlaier		if (in6m->in6m_ifp != ifp)
801171169Smlaier			continue;
802171169Smlaier		in6_delmulti(in6m);
803171169Smlaier		in6m = NULL;
804171169Smlaier	}
805171169Smlaier
806171169Smlaier	/*
807171169Smlaier	 * remove neighbor management table.  we call it twice just to make
808171169Smlaier	 * sure we nuke everything.  maybe we need just one call.
809171169Smlaier	 * XXX: since the first call did not release addresses, some prefixes
810171169Smlaier	 * might remain.  We should call nd6_purge() again to release the
811171169Smlaier	 * prefixes after removing all addresses above.
812171169Smlaier	 * (Or can we just delay calling nd6_purge until at this point?)
813171169Smlaier	 */
814171169Smlaier	nd6_purge(ifp);
815171169Smlaier
816171169Smlaier	/* remove route to link-local allnodes multicast (ff02::1) */
817171169Smlaier	bzero(&sin6, sizeof(sin6));
818171169Smlaier	sin6.sin6_len = sizeof(struct sockaddr_in6);
819171169Smlaier	sin6.sin6_family = AF_INET6;
820171169Smlaier	sin6.sin6_addr = in6addr_linklocal_allnodes;
821171169Smlaier	if (in6_setscope(&sin6.sin6_addr, ifp, NULL))
822171169Smlaier		/* XXX: should not fail */
823171169Smlaier		return;
824171169Smlaier	/* XXX grab lock first to avoid LOR */
825171169Smlaier	if (rt_tables[AF_INET6] != NULL) {
826171169Smlaier		RADIX_NODE_HEAD_LOCK(rt_tables[AF_INET6]);
827171169Smlaier		rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
828171169Smlaier		if (rt) {
829171169Smlaier			if (rt->rt_ifp == ifp)
830171169Smlaier				rtexpunge(rt);
831171169Smlaier			RTFREE_LOCKED(rt);
832171169Smlaier		}
833171169Smlaier		RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET6]);
834171169Smlaier	}
835171169Smlaier}
836171169Smlaier
837171169Smlaierint
838171169Smlaierin6_get_tmpifid(ifp, retbuf, baseid, generate)
839171169Smlaier	struct ifnet *ifp;
840171169Smlaier	u_int8_t *retbuf;
841171169Smlaier	const u_int8_t *baseid;
842171169Smlaier	int generate;
843171169Smlaier{
844171169Smlaier	u_int8_t nullbuf[8];
845171169Smlaier	struct nd_ifinfo *ndi = ND_IFINFO(ifp);
846171169Smlaier
847171169Smlaier	bzero(nullbuf, sizeof(nullbuf));
848171169Smlaier	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
849171169Smlaier		/* we've never created a random ID.  Create a new one. */
850171169Smlaier		generate = 1;
851171169Smlaier	}
852171169Smlaier
853171169Smlaier	if (generate) {
854171169Smlaier		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
855171169Smlaier
856171169Smlaier		/* generate_tmp_ifid will update seedn and buf */
857171169Smlaier		(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
858171169Smlaier		    ndi->randomid);
859171169Smlaier	}
860171169Smlaier	bcopy(ndi->randomid, retbuf, 8);
861171169Smlaier
862171169Smlaier	return (0);
863171169Smlaier}
864171169Smlaier
865171169Smlaiervoid
866171169Smlaierin6_tmpaddrtimer(ignored_arg)
867171169Smlaier	void *ignored_arg;
868171169Smlaier{
869171169Smlaier	struct nd_ifinfo *ndi;
870171169Smlaier	u_int8_t nullbuf[8];
871171169Smlaier	struct ifnet *ifp;
872171169Smlaier	int s = splnet();
873171169Smlaier
874171169Smlaier	callout_reset(&in6_tmpaddrtimer_ch,
875171169Smlaier	    (ip6_temp_preferred_lifetime - ip6_desync_factor -
876171169Smlaier	    ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
877171169Smlaier
878171169Smlaier	bzero(nullbuf, sizeof(nullbuf));
879	for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
880		ndi = ND_IFINFO(ifp);
881		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
882			/*
883			 * We've been generating a random ID on this interface.
884			 * Create a new one.
885			 */
886			(void)generate_tmp_ifid(ndi->randomseed0,
887			    ndi->randomseed1, ndi->randomid);
888		}
889	}
890
891	splx(s);
892}
893