in6_ifattach.c revision 163306
1/*	$FreeBSD: head/sys/netinet6/in6_ifattach.c 163306 2006-10-13 12:41:36Z ume $	*/
2/*	$KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $	*/
3
4/*-
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/socket.h>
37#include <sys/sockio.h>
38#include <sys/kernel.h>
39#include <sys/syslog.h>
40#include <sys/md5.h>
41
42#include <net/if.h>
43#include <net/if_dl.h>
44#include <net/if_types.h>
45#include <net/route.h>
46
47#include <netinet/in.h>
48#include <netinet/in_var.h>
49#include <netinet/if_ether.h>
50#include <netinet/in_pcb.h>
51
52#include <netinet/ip6.h>
53#include <netinet6/ip6_var.h>
54#include <netinet6/in6_var.h>
55#include <netinet6/in6_pcb.h>
56#include <netinet6/in6_ifattach.h>
57#include <netinet6/ip6_var.h>
58#include <netinet6/nd6.h>
59#include <netinet6/scope6_var.h>
60
61unsigned long in6_maxmtu = 0;
62
63#ifdef IP6_AUTO_LINKLOCAL
64int ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
65#else
66int ip6_auto_linklocal = 1;	/* enable by default */
67#endif
68
69struct callout in6_tmpaddrtimer_ch;
70
71extern struct inpcbinfo udbinfo;
72extern struct inpcbinfo ripcbinfo;
73
74static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
75static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
76static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
77static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
78static int in6_ifattach_loopback __P((struct ifnet *));
79
80#define EUI64_GBIT	0x01
81#define EUI64_UBIT	0x02
82#define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
83#define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
84#define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
85#define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
86#define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
87
88#define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
89#define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
90
91/*
92 * Generate a last-resort interface identifier, when the machine has no
93 * IEEE802/EUI64 address sources.
94 * The goal here is to get an interface identifier that is
95 * (1) random enough and (2) does not change across reboot.
96 * We currently use MD5(hostname) for it.
97 */
98static int
99get_rand_ifid(ifp, in6)
100	struct ifnet *ifp;
101	struct in6_addr *in6;	/* upper 64bits are preserved */
102{
103	MD5_CTX ctxt;
104	u_int8_t digest[16];
105	int hostnamelen	= strlen(hostname);
106
107#if 0
108	/* we need at least several letters as seed for ifid */
109	if (hostnamelen < 3)
110		return -1;
111#endif
112
113	/* generate 8 bytes of pseudo-random value. */
114	bzero(&ctxt, sizeof(ctxt));
115	MD5Init(&ctxt);
116	MD5Update(&ctxt, hostname, hostnamelen);
117	MD5Final(digest, &ctxt);
118
119	/* assumes sizeof(digest) > sizeof(ifid) */
120	bcopy(digest, &in6->s6_addr[8], 8);
121
122	/* make sure to set "u" bit to local, and "g" bit to individual. */
123	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
124	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
125
126	/* convert EUI64 into IPv6 interface identifier */
127	EUI64_TO_IFID(in6);
128
129	return 0;
130}
131
132static int
133generate_tmp_ifid(seed0, seed1, ret)
134	u_int8_t *seed0, *ret;
135	const u_int8_t *seed1;
136{
137	MD5_CTX ctxt;
138	u_int8_t seed[16], digest[16], nullbuf[8];
139	u_int32_t val32;
140
141	/* If there's no hisotry, start with a random seed. */
142	bzero(nullbuf, sizeof(nullbuf));
143	if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
144		int i;
145
146		for (i = 0; i < 2; i++) {
147			val32 = arc4random();
148			bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
149		}
150	} else
151		bcopy(seed0, seed, 8);
152
153	/* copy the right-most 64-bits of the given address */
154	/* XXX assumption on the size of IFID */
155	bcopy(seed1, &seed[8], 8);
156
157	if (0) {		/* for debugging purposes only */
158		int i;
159
160		printf("generate_tmp_ifid: new randomized ID from: ");
161		for (i = 0; i < 16; i++)
162			printf("%02x", seed[i]);
163		printf(" ");
164	}
165
166	/* generate 16 bytes of pseudo-random value. */
167	bzero(&ctxt, sizeof(ctxt));
168	MD5Init(&ctxt);
169	MD5Update(&ctxt, seed, sizeof(seed));
170	MD5Final(digest, &ctxt);
171
172	/*
173	 * RFC 3041 3.2.1. (3)
174	 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
175	 * left-most bit is numbered 0) to zero.
176	 */
177	bcopy(digest, ret, 8);
178	ret[0] &= ~EUI64_UBIT;
179
180	/*
181	 * XXX: we'd like to ensure that the generated value is not zero
182	 * for simplicity.  If the caclculated digest happens to be zero,
183	 * use a random non-zero value as the last resort.
184	 */
185	if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
186		nd6log((LOG_INFO,
187		    "generate_tmp_ifid: computed MD5 value is zero.\n"));
188
189		val32 = arc4random();
190		val32 = 1 + (val32 % (0xffffffff - 1));
191	}
192
193	/*
194	 * RFC 3041 3.2.1. (4)
195	 * Take the rightmost 64-bits of the MD5 digest and save them in
196	 * stable storage as the history value to be used in the next
197	 * iteration of the algorithm.
198	 */
199	bcopy(&digest[8], seed0, 8);
200
201	if (0) {		/* for debugging purposes only */
202		int i;
203
204		printf("to: ");
205		for (i = 0; i < 16; i++)
206			printf("%02x", digest[i]);
207		printf("\n");
208	}
209
210	return 0;
211}
212
213/*
214 * Get interface identifier for the specified interface.
215 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
216 */
217int
218in6_get_hw_ifid(ifp, in6)
219	struct ifnet *ifp;
220	struct in6_addr *in6;	/* upper 64bits are preserved */
221{
222	struct ifaddr *ifa;
223	struct sockaddr_dl *sdl;
224	u_int8_t *addr;
225	size_t addrlen;
226	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
227	static u_int8_t allone[8] =
228		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
229
230	for (ifa = ifp->if_addrlist.tqh_first;
231	     ifa;
232	     ifa = ifa->ifa_list.tqe_next) {
233		if (ifa->ifa_addr->sa_family != AF_LINK)
234			continue;
235		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
236		if (sdl == NULL)
237			continue;
238		if (sdl->sdl_alen == 0)
239			continue;
240
241		goto found;
242	}
243
244	return -1;
245
246found:
247	addr = LLADDR(sdl);
248	addrlen = sdl->sdl_alen;
249
250	/* get EUI64 */
251	switch (ifp->if_type) {
252	case IFT_ETHER:
253	case IFT_FDDI:
254	case IFT_ISO88025:
255	case IFT_ATM:
256	case IFT_IEEE1394:
257#ifdef IFT_IEEE80211
258	case IFT_IEEE80211:
259#endif
260		/* IEEE802/EUI64 cases - what others? */
261		/* IEEE1394 uses 16byte length address starting with EUI64 */
262		if (addrlen > 8)
263			addrlen = 8;
264
265		/* look at IEEE802/EUI64 only */
266		if (addrlen != 8 && addrlen != 6)
267			return -1;
268
269		/*
270		 * check for invalid MAC address - on bsdi, we see it a lot
271		 * since wildboar configures all-zero MAC on pccard before
272		 * card insertion.
273		 */
274		if (bcmp(addr, allzero, addrlen) == 0)
275			return -1;
276		if (bcmp(addr, allone, addrlen) == 0)
277			return -1;
278
279		/* make EUI64 address */
280		if (addrlen == 8)
281			bcopy(addr, &in6->s6_addr[8], 8);
282		else if (addrlen == 6) {
283			in6->s6_addr[8] = addr[0];
284			in6->s6_addr[9] = addr[1];
285			in6->s6_addr[10] = addr[2];
286			in6->s6_addr[11] = 0xff;
287			in6->s6_addr[12] = 0xfe;
288			in6->s6_addr[13] = addr[3];
289			in6->s6_addr[14] = addr[4];
290			in6->s6_addr[15] = addr[5];
291		}
292		break;
293
294	case IFT_ARCNET:
295		if (addrlen != 1)
296			return -1;
297		if (!addr[0])
298			return -1;
299
300		bzero(&in6->s6_addr[8], 8);
301		in6->s6_addr[15] = addr[0];
302
303		/*
304		 * due to insufficient bitwidth, we mark it local.
305		 */
306		in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
307		in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
308		break;
309
310	case IFT_GIF:
311#ifdef IFT_STF
312	case IFT_STF:
313#endif
314		/*
315		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
316		 * however, IPv4 address is not very suitable as unique
317		 * identifier source (can be renumbered).
318		 * we don't do this.
319		 */
320		return -1;
321
322	default:
323		return -1;
324	}
325
326	/* sanity check: g bit must not indicate "group" */
327	if (EUI64_GROUP(in6))
328		return -1;
329
330	/* convert EUI64 into IPv6 interface identifier */
331	EUI64_TO_IFID(in6);
332
333	/*
334	 * sanity check: ifid must not be all zero, avoid conflict with
335	 * subnet router anycast
336	 */
337	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
338	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
339		return -1;
340	}
341
342	return 0;
343}
344
345/*
346 * Get interface identifier for the specified interface.  If it is not
347 * available on ifp0, borrow interface identifier from other information
348 * sources.
349 */
350static int
351get_ifid(ifp0, altifp, in6)
352	struct ifnet *ifp0;
353	struct ifnet *altifp;	/* secondary EUI64 source */
354	struct in6_addr *in6;
355{
356	struct ifnet *ifp;
357
358	/* first, try to get it from the interface itself */
359	if (in6_get_hw_ifid(ifp0, in6) == 0) {
360		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
361		    if_name(ifp0)));
362		goto success;
363	}
364
365	/* try secondary EUI64 source. this basically is for ATM PVC */
366	if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
367		nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
368		    if_name(ifp0), if_name(altifp)));
369		goto success;
370	}
371
372	/* next, try to get it from some other hardware interface */
373	IFNET_RLOCK();
374	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
375		if (ifp == ifp0)
376			continue;
377		if (in6_get_hw_ifid(ifp, in6) != 0)
378			continue;
379
380		/*
381		 * to borrow ifid from other interface, ifid needs to be
382		 * globally unique
383		 */
384		if (IFID_UNIVERSAL(in6)) {
385			nd6log((LOG_DEBUG,
386			    "%s: borrow interface identifier from %s\n",
387			    if_name(ifp0), if_name(ifp)));
388			IFNET_RUNLOCK();
389			goto success;
390		}
391	}
392	IFNET_RUNLOCK();
393
394	/* last resort: get from random number source */
395	if (get_rand_ifid(ifp, in6) == 0) {
396		nd6log((LOG_DEBUG,
397		    "%s: interface identifier generated by random number\n",
398		    if_name(ifp0)));
399		goto success;
400	}
401
402	printf("%s: failed to get interface identifier\n", if_name(ifp0));
403	return -1;
404
405success:
406	nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
407	    if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
408	    in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
409	    in6->s6_addr[14], in6->s6_addr[15]));
410	return 0;
411}
412
413static int
414in6_ifattach_linklocal(ifp, altifp)
415	struct ifnet *ifp;
416	struct ifnet *altifp;	/* secondary EUI64 source */
417{
418	struct in6_ifaddr *ia;
419	struct in6_aliasreq ifra;
420	struct nd_prefixctl pr0;
421	int i, error;
422
423	/*
424	 * configure link-local address.
425	 */
426	bzero(&ifra, sizeof(ifra));
427
428	/*
429	 * in6_update_ifa() does not use ifra_name, but we accurately set it
430	 * for safety.
431	 */
432	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
433
434	ifra.ifra_addr.sin6_family = AF_INET6;
435	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
436	ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
437	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
438	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
439		ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
440		ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
441	} else {
442		if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
443			nd6log((LOG_ERR,
444			    "%s: no ifid available\n", if_name(ifp)));
445			return (-1);
446		}
447	}
448	if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
449		return (-1);
450
451	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
452	ifra.ifra_prefixmask.sin6_family = AF_INET6;
453	ifra.ifra_prefixmask.sin6_addr = in6mask64;
454	/* link-local addresses should NEVER expire. */
455	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
456	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
457
458	/*
459	 * Now call in6_update_ifa() to do a bunch of procedures to configure
460	 * a link-local address. We can set the 3rd argument to NULL, because
461	 * we know there's no other link-local address on the interface
462	 * and therefore we are adding one (instead of updating one).
463	 */
464	if ((error = in6_update_ifa(ifp, &ifra, NULL,
465				    IN6_IFAUPDATE_DADDELAY)) != 0) {
466		/*
467		 * XXX: When the interface does not support IPv6, this call
468		 * would fail in the SIOCSIFADDR ioctl.  I believe the
469		 * notification is rather confusing in this case, so just
470		 * suppress it.  (jinmei@kame.net 20010130)
471		 */
472		if (error != EAFNOSUPPORT)
473			nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
474			    "configure a link-local address on %s "
475			    "(errno=%d)\n",
476			    if_name(ifp), error));
477		return (-1);
478	}
479
480	ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
481#ifdef DIAGNOSTIC
482	if (!ia) {
483		panic("ia == NULL in in6_ifattach_linklocal");
484		/* NOTREACHED */
485	}
486#endif
487
488	/*
489	 * Make the link-local prefix (fe80::%link/64) as on-link.
490	 * Since we'd like to manage prefixes separately from addresses,
491	 * we make an ND6 prefix structure for the link-local prefix,
492	 * and add it to the prefix list as a never-expire prefix.
493	 * XXX: this change might affect some existing code base...
494	 */
495	bzero(&pr0, sizeof(pr0));
496	pr0.ndpr_ifp = ifp;
497	/* this should be 64 at this moment. */
498	pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
499	pr0.ndpr_prefix = ifra.ifra_addr;
500	/* apply the mask for safety. (nd6_prelist_add will apply it again) */
501	for (i = 0; i < 4; i++) {
502		pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
503		    in6mask64.s6_addr32[i];
504	}
505	/*
506	 * Initialize parameters.  The link-local prefix must always be
507	 * on-link, and its lifetimes never expire.
508	 */
509	pr0.ndpr_raf_onlink = 1;
510	pr0.ndpr_raf_auto = 1;	/* probably meaningless */
511	pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
512	pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
513	/*
514	 * Since there is no other link-local addresses, nd6_prefix_lookup()
515	 * probably returns NULL.  However, we cannot always expect the result.
516	 * For example, if we first remove the (only) existing link-local
517	 * address, and then reconfigure another one, the prefix is still
518	 * valid with referring to the old link-local address.
519	 */
520	if (nd6_prefix_lookup(&pr0) == NULL) {
521		if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
522			return (error);
523	}
524
525	return 0;
526}
527
528static int
529in6_ifattach_loopback(ifp)
530	struct ifnet *ifp;	/* must be IFT_LOOP */
531{
532	struct in6_aliasreq ifra;
533	int error;
534
535	bzero(&ifra, sizeof(ifra));
536
537	/*
538	 * in6_update_ifa() does not use ifra_name, but we accurately set it
539	 * for safety.
540	 */
541	strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
542
543	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
544	ifra.ifra_prefixmask.sin6_family = AF_INET6;
545	ifra.ifra_prefixmask.sin6_addr = in6mask128;
546
547	/*
548	 * Always initialize ia_dstaddr (= broadcast address) to loopback
549	 * address.  Follows IPv4 practice - see in_ifinit().
550	 */
551	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
552	ifra.ifra_dstaddr.sin6_family = AF_INET6;
553	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
554
555	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
556	ifra.ifra_addr.sin6_family = AF_INET6;
557	ifra.ifra_addr.sin6_addr = in6addr_loopback;
558
559	/* the loopback  address should NEVER expire. */
560	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
561	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
562
563	/* we don't need to perform DAD on loopback interfaces. */
564	ifra.ifra_flags |= IN6_IFF_NODAD;
565
566	/* skip registration to the prefix list. XXX should be temporary. */
567	ifra.ifra_flags |= IN6_IFF_NOPFX;
568
569	/*
570	 * We are sure that this is a newly assigned address, so we can set
571	 * NULL to the 3rd arg.
572	 */
573	if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
574		nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
575		    "the loopback address on %s (errno=%d)\n",
576		    if_name(ifp), error));
577		return (-1);
578	}
579
580	return 0;
581}
582
583/*
584 * compute NI group address, based on the current hostname setting.
585 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
586 *
587 * when ifp == NULL, the caller is responsible for filling scopeid.
588 */
589int
590in6_nigroup(ifp, name, namelen, in6)
591	struct ifnet *ifp;
592	const char *name;
593	int namelen;
594	struct in6_addr *in6;
595{
596	const char *p;
597	u_char *q;
598	MD5_CTX ctxt;
599	u_int8_t digest[16];
600	char l;
601	char n[64];	/* a single label must not exceed 63 chars */
602
603	if (!namelen || !name)
604		return -1;
605
606	p = name;
607	while (p && *p && *p != '.' && p - name < namelen)
608		p++;
609	if (p - name > sizeof(n) - 1)
610		return -1;	/* label too long */
611	l = p - name;
612	strncpy(n, name, l);
613	n[(int)l] = '\0';
614	for (q = n; *q; q++) {
615		if ('A' <= *q && *q <= 'Z')
616			*q = *q - 'A' + 'a';
617	}
618
619	/* generate 8 bytes of pseudo-random value. */
620	bzero(&ctxt, sizeof(ctxt));
621	MD5Init(&ctxt);
622	MD5Update(&ctxt, &l, sizeof(l));
623	MD5Update(&ctxt, n, l);
624	MD5Final(digest, &ctxt);
625
626	bzero(in6, sizeof(*in6));
627	in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
628	in6->s6_addr8[11] = 2;
629	bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
630	if (in6_setscope(in6, ifp, NULL))
631		return (-1); /* XXX: should not fail */
632
633	return 0;
634}
635
636/*
637 * XXX multiple loopback interface needs more care.  for instance,
638 * nodelocal address needs to be configured onto only one of them.
639 * XXX multiple link-local address case
640 */
641void
642in6_ifattach(ifp, altifp)
643	struct ifnet *ifp;
644	struct ifnet *altifp;	/* secondary EUI64 source */
645{
646	struct in6_ifaddr *ia;
647	struct in6_addr in6;
648
649	/* some of the interfaces are inherently not IPv6 capable */
650	switch (ifp->if_type) {
651	case IFT_PFLOG:
652	case IFT_PFSYNC:
653	case IFT_CARP:
654		return;
655	}
656
657	/*
658	 * quirks based on interface type
659	 */
660	switch (ifp->if_type) {
661#ifdef IFT_STF
662	case IFT_STF:
663		/*
664		 * 6to4 interface is a very special kind of beast.
665		 * no multicast, no linklocal.  RFC2529 specifies how to make
666		 * linklocals for 6to4 interface, but there's no use and
667		 * it is rather harmful to have one.
668		 */
669		goto statinit;
670#endif
671	default:
672		break;
673	}
674
675	/*
676	 * usually, we require multicast capability to the interface
677	 */
678	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
679		nd6log((LOG_INFO, "in6_ifattach: "
680		    "%s is not multicast capable, IPv6 not enabled\n",
681		    if_name(ifp)));
682		return;
683	}
684
685	/*
686	 * assign loopback address for loopback interface.
687	 * XXX multiple loopback interface case.
688	 */
689	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
690		in6 = in6addr_loopback;
691		if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
692			if (in6_ifattach_loopback(ifp) != 0)
693				return;
694		}
695	}
696
697	/*
698	 * assign a link-local address, if there's none.
699	 */
700	if (ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) {
701		ia = in6ifa_ifpforlinklocal(ifp, 0);
702		if (ia == NULL) {
703			if (in6_ifattach_linklocal(ifp, altifp) == 0) {
704				/* linklocal address assigned */
705			} else {
706				/* failed to assign linklocal address. bark? */
707			}
708		}
709	}
710
711#ifdef IFT_STF			/* XXX */
712statinit:
713#endif
714
715	/* update dynamically. */
716	if (in6_maxmtu < ifp->if_mtu)
717		in6_maxmtu = ifp->if_mtu;
718}
719
720/*
721 * NOTE: in6_ifdetach() does not support loopback if at this moment.
722 * We don't need this function in bsdi, because interfaces are never removed
723 * from the ifnet list in bsdi.
724 */
725void
726in6_ifdetach(ifp)
727	struct ifnet *ifp;
728{
729	struct in6_ifaddr *ia, *oia;
730	struct ifaddr *ifa, *next;
731	struct rtentry *rt;
732	short rtflags;
733	struct sockaddr_in6 sin6;
734	struct in6_multi *in6m;
735	struct in6_multi *in6m_next;
736
737	/* remove neighbor management table */
738	nd6_purge(ifp);
739
740	/* nuke any of IPv6 addresses we have */
741	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
742		next = ifa->ifa_list.tqe_next;
743		if (ifa->ifa_addr->sa_family != AF_INET6)
744			continue;
745		in6_purgeaddr(ifa);
746	}
747
748	/* undo everything done by in6_ifattach(), just in case */
749	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next) {
750		next = ifa->ifa_list.tqe_next;
751
752		if (ifa->ifa_addr->sa_family != AF_INET6
753		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
754			continue;
755		}
756
757		ia = (struct in6_ifaddr *)ifa;
758
759		/* remove from the routing table */
760		if ((ia->ia_flags & IFA_ROUTE) &&
761		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
762			rtflags = rt->rt_flags;
763			rtfree(rt);
764			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
765			    (struct sockaddr *)&ia->ia_addr,
766			    (struct sockaddr *)&ia->ia_prefixmask,
767			    rtflags, (struct rtentry **)0);
768		}
769
770		/* remove from the linked list */
771		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
772		IFAFREE(&ia->ia_ifa);
773
774		/* also remove from the IPv6 address chain(itojun&jinmei) */
775		oia = ia;
776		if (oia == (ia = in6_ifaddr))
777			in6_ifaddr = ia->ia_next;
778		else {
779			while (ia->ia_next && (ia->ia_next != oia))
780				ia = ia->ia_next;
781			if (ia->ia_next)
782				ia->ia_next = oia->ia_next;
783			else {
784				nd6log((LOG_ERR,
785				    "%s: didn't unlink in6ifaddr from list\n",
786				    if_name(ifp)));
787			}
788		}
789
790		IFAFREE(&oia->ia_ifa);
791	}
792
793	/* leave from all multicast groups joined */
794
795	in6_pcbpurgeif0(&udbinfo, ifp);
796	in6_pcbpurgeif0(&ripcbinfo, ifp);
797
798	for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {
799		in6m_next = LIST_NEXT(in6m, in6m_entry);
800		if (in6m->in6m_ifp != ifp)
801			continue;
802		in6_delmulti(in6m);
803		in6m = NULL;
804	}
805
806	/*
807	 * remove neighbor management table.  we call it twice just to make
808	 * sure we nuke everything.  maybe we need just one call.
809	 * XXX: since the first call did not release addresses, some prefixes
810	 * might remain.  We should call nd6_purge() again to release the
811	 * prefixes after removing all addresses above.
812	 * (Or can we just delay calling nd6_purge until at this point?)
813	 */
814	nd6_purge(ifp);
815
816	/* remove route to link-local allnodes multicast (ff02::1) */
817	bzero(&sin6, sizeof(sin6));
818	sin6.sin6_len = sizeof(struct sockaddr_in6);
819	sin6.sin6_family = AF_INET6;
820	sin6.sin6_addr = in6addr_linklocal_allnodes;
821	if (in6_setscope(&sin6.sin6_addr, ifp, NULL))
822		/* XXX: should not fail */
823		return;
824	/* XXX grab lock first to avoid LOR */
825	if (rt_tables[AF_INET6] != NULL) {
826		RADIX_NODE_HEAD_LOCK(rt_tables[AF_INET6]);
827		rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
828		if (rt) {
829			if (rt->rt_ifp == ifp)
830				rtexpunge(rt);
831			RTFREE_LOCKED(rt);
832		}
833		RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET6]);
834	}
835}
836
837int
838in6_get_tmpifid(ifp, retbuf, baseid, generate)
839	struct ifnet *ifp;
840	u_int8_t *retbuf;
841	const u_int8_t *baseid;
842	int generate;
843{
844	u_int8_t nullbuf[8];
845	struct nd_ifinfo *ndi = ND_IFINFO(ifp);
846
847	bzero(nullbuf, sizeof(nullbuf));
848	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
849		/* we've never created a random ID.  Create a new one. */
850		generate = 1;
851	}
852
853	if (generate) {
854		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
855
856		/* generate_tmp_ifid will update seedn and buf */
857		(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
858		    ndi->randomid);
859	}
860	bcopy(ndi->randomid, retbuf, 8);
861
862	return (0);
863}
864
865void
866in6_tmpaddrtimer(ignored_arg)
867	void *ignored_arg;
868{
869	struct nd_ifinfo *ndi;
870	u_int8_t nullbuf[8];
871	struct ifnet *ifp;
872	int s = splnet();
873
874	callout_reset(&in6_tmpaddrtimer_ch,
875	    (ip6_temp_preferred_lifetime - ip6_desync_factor -
876	    ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
877
878	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