xref: /netbsd-src/sys/netinet6/in6_ifattach.c (revision 5e4c038a45edbc7d63b7c2daa76e29f88b64a4e3)
1 /*	$NetBSD: in6_ifattach.c,v 1.46 2002/05/29 07:53:40 itojun Exp $	*/
2 /*	$KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei 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/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.46 2002/05/29 07:53:40 itojun Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/socket.h>
40 #include <sys/sockio.h>
41 #include <sys/kernel.h>
42 #include <sys/syslog.h>
43 #include <sys/md5.h>
44 
45 #include <net/if.h>
46 #include <net/if_dl.h>
47 #include <net/if_types.h>
48 #include <net/route.h>
49 
50 #include <netinet/in.h>
51 #include <netinet/in_var.h>
52 
53 #include <netinet/ip6.h>
54 #include <netinet6/ip6_var.h>
55 #include <netinet6/in6_ifattach.h>
56 #include <netinet6/ip6_var.h>
57 #include <netinet6/nd6.h>
58 
59 #include <net/net_osdep.h>
60 
61 unsigned long in6_maxmtu = 0;
62 
63 static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
64 static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
65 static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
66 static int in6_ifattach_addaddr __P((struct ifnet *, struct in6_ifaddr *));
67 static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
68 static int in6_ifattach_loopback __P((struct ifnet *));
69 
70 #define EUI64_GBIT	0x01
71 #define EUI64_UBIT	0x02
72 #define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
73 #define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
74 #define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
75 #define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
76 #define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
77 
78 #define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
79 #define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
80 
81 /*
82  * Generate a last-resort interface identifier, when the machine has no
83  * IEEE802/EUI64 address sources.
84  * The goal here is to get an interface identifier that is
85  * (1) random enough and (2) does not change across reboot.
86  * We currently use MD5(hostname) for it.
87  */
88 static int
89 get_rand_ifid(ifp, in6)
90 	struct ifnet *ifp;
91 	struct in6_addr *in6;	/* upper 64bits are preserved */
92 {
93 	MD5_CTX ctxt;
94 	u_int8_t digest[16];
95 
96 #if 0
97 	/* we need at least several letters as seed for ifid */
98 	if (hostnamelen < 3)
99 		return -1;
100 #endif
101 
102 	/* generate 8 bytes of pseudo-random value. */
103 	bzero(&ctxt, sizeof(ctxt));
104 	MD5Init(&ctxt);
105 	MD5Update(&ctxt, hostname, hostnamelen);
106 	MD5Final(digest, &ctxt);
107 
108 	/* assumes sizeof(digest) > sizeof(ifid) */
109 	bcopy(digest, &in6->s6_addr[8], 8);
110 
111 	/* make sure to set "u" bit to local, and "g" bit to individual. */
112 	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
113 	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
114 
115 	/* convert EUI64 into IPv6 interface identifier */
116 	EUI64_TO_IFID(in6);
117 
118 	return 0;
119 }
120 
121 /*
122  * Get interface identifier for the specified interface.
123  * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
124  */
125 static int
126 get_hw_ifid(ifp, in6)
127 	struct ifnet *ifp;
128 	struct in6_addr *in6;	/* upper 64bits are preserved */
129 {
130 	struct ifaddr *ifa;
131 	struct sockaddr_dl *sdl;
132 	u_int8_t *addr;
133 	size_t addrlen;
134 	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
135 	static u_int8_t allone[8] =
136 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
137 
138 	for (ifa = ifp->if_addrlist.tqh_first;
139 	     ifa;
140 	     ifa = ifa->ifa_list.tqe_next)
141 	{
142 		if (ifa->ifa_addr->sa_family != AF_LINK)
143 			continue;
144 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
145 		if (sdl == NULL)
146 			continue;
147 		if (sdl->sdl_alen == 0)
148 			continue;
149 
150 		goto found;
151 	}
152 
153 	return -1;
154 
155 found:
156 	addr = LLADDR(sdl);
157 	addrlen = sdl->sdl_alen;
158 
159 	/* get EUI64 */
160 	switch (ifp->if_type) {
161 	case IFT_ETHER:
162 	case IFT_FDDI:
163 	case IFT_ATM:
164 	case IFT_IEEE1394:
165 		/* IEEE802/EUI64 cases - what others? */
166 		/* IEEE1394 uses 16byte length address starting with EUI64 */
167 		if (addrlen > 8)
168 			addrlen = 8;
169 
170 		/* look at IEEE802/EUI64 only */
171 		if (addrlen != 8 && addrlen != 6)
172 			return -1;
173 
174 		/*
175 		 * check for invalid MAC address - on bsdi, we see it a lot
176 		 * since wildboar configures all-zero MAC on pccard before
177 		 * card insertion.
178 		 */
179 		if (bcmp(addr, allzero, addrlen) == 0)
180 			return -1;
181 		if (bcmp(addr, allone, addrlen) == 0)
182 			return -1;
183 
184 		/* make EUI64 address */
185 		if (addrlen == 8)
186 			bcopy(addr, &in6->s6_addr[8], 8);
187 		else if (addrlen == 6) {
188 			in6->s6_addr[8] = addr[0];
189 			in6->s6_addr[9] = addr[1];
190 			in6->s6_addr[10] = addr[2];
191 			in6->s6_addr[11] = 0xff;
192 			in6->s6_addr[12] = 0xfe;
193 			in6->s6_addr[13] = addr[3];
194 			in6->s6_addr[14] = addr[4];
195 			in6->s6_addr[15] = addr[5];
196 		}
197 		break;
198 
199 	case IFT_ARCNET:
200 		if (addrlen != 1)
201 			return -1;
202 		if (!addr[0])
203 			return -1;
204 
205 		bzero(&in6->s6_addr[8], 8);
206 		in6->s6_addr[15] = addr[0];
207 
208 		/*
209 		 * due to insufficient bitwidth, we mark it local.
210 		 */
211 		in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
212 		in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
213 		break;
214 
215 	case IFT_GIF:
216 #ifdef IFT_STF
217 	case IFT_STF:
218 #endif
219 		/*
220 		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
221 		 * however, IPv4 address is not very suitable as unique
222 		 * identifier source (can be renumbered).
223 		 * we don't do this.
224 		 */
225 		return -1;
226 
227 	default:
228 		return -1;
229 	}
230 
231 	/* sanity check: g bit must not indicate "group" */
232 	if (EUI64_GROUP(in6))
233 		return -1;
234 
235 	/* convert EUI64 into IPv6 interface identifier */
236 	EUI64_TO_IFID(in6);
237 
238 	/*
239 	 * sanity check: ifid must not be all zero, avoid conflict with
240 	 * subnet router anycast
241 	 */
242 	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
243 	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
244 		return -1;
245 	}
246 
247 	return 0;
248 }
249 
250 /*
251  * Get interface identifier for the specified interface.  If it is not
252  * available on ifp0, borrow interface identifier from other information
253  * sources.
254  */
255 static int
256 get_ifid(ifp0, altifp, in6)
257 	struct ifnet *ifp0;
258 	struct ifnet *altifp;	/*secondary EUI64 source*/
259 	struct in6_addr *in6;
260 {
261 	struct ifnet *ifp;
262 
263 	/* first, try to get it from the interface itself */
264 	if (get_hw_ifid(ifp0, in6) == 0) {
265 		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
266 		    if_name(ifp0)));
267 		goto success;
268 	}
269 
270 	/* try secondary EUI64 source. this basically is for ATM PVC */
271 	if (altifp && get_hw_ifid(altifp, in6) == 0) {
272 		nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
273 		    if_name(ifp0), if_name(altifp)));
274 		goto success;
275 	}
276 
277 	/* next, try to get it from some other hardware interface */
278 	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
279 	{
280 		if (ifp == ifp0)
281 			continue;
282 		if (get_hw_ifid(ifp, in6) != 0)
283 			continue;
284 
285 		/*
286 		 * to borrow ifid from other interface, ifid needs to be
287 		 * globally unique
288 		 */
289 		if (IFID_UNIVERSAL(in6)) {
290 			nd6log((LOG_DEBUG,
291 			    "%s: borrow interface identifier from %s\n",
292 			    if_name(ifp0), if_name(ifp)));
293 			goto success;
294 		}
295 	}
296 
297 	/* last resort: get from random number source */
298 	if (get_rand_ifid(ifp, in6) == 0) {
299 		nd6log((LOG_DEBUG,
300 		    "%s: interface identifier generated by random number\n",
301 		    if_name(ifp0)));
302 		goto success;
303 	}
304 
305 	printf("%s: failed to get interface identifier\n", if_name(ifp0));
306 	return -1;
307 
308 success:
309 	nd6log((LOG_INFO, "%s: ifid: "
310 		"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
311 		if_name(ifp0),
312 		in6->s6_addr[8], in6->s6_addr[9],
313 		in6->s6_addr[10], in6->s6_addr[11],
314 		in6->s6_addr[12], in6->s6_addr[13],
315 		in6->s6_addr[14], in6->s6_addr[15]));
316 	return 0;
317 }
318 
319 /*
320  * configure IPv6 interface address.  XXX code duplicated with in.c
321  */
322 static int
323 in6_ifattach_addaddr(ifp, ia)
324 	struct ifnet *ifp;
325 	struct in6_ifaddr *ia;
326 {
327 	struct in6_ifaddr *oia;
328 	struct ifaddr *ifa;
329 	int error;
330 	int rtflag;
331 	struct in6_addr llsol;
332 
333 	/*
334 	 * initialize if_addrlist, if we are the very first one
335 	 */
336 	ifa = TAILQ_FIRST(&ifp->if_addrlist);
337 	if (ifa == NULL) {
338 		TAILQ_INIT(&ifp->if_addrlist);
339 	}
340 
341 	/*
342 	 * link the interface address to global list
343 	 */
344 	TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
345 	IFAREF(&ia->ia_ifa);
346 
347 	/*
348 	 * Also link into the IPv6 address chain beginning with in6_ifaddr.
349 	 * kazu opposed it, but itojun & jinmei wanted.
350 	 */
351 	if ((oia = in6_ifaddr) != NULL) {
352 		for (; oia->ia_next; oia = oia->ia_next)
353 			continue;
354 		oia->ia_next = ia;
355 	} else
356 		in6_ifaddr = ia;
357 	IFAREF(&ia->ia_ifa);
358 
359 	/*
360 	 * give the interface a chance to initialize, in case this
361 	 * is the first address to be added.
362 	 */
363 	if (ifp->if_ioctl != NULL) {
364 		int s;
365 		s = splnet();
366 		error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
367 		splx(s);
368 	} else
369 		error = 0;
370 	if (error) {
371 		switch (error) {
372 		case EAFNOSUPPORT:
373 			printf("%s: IPv6 not supported\n", if_name(ifp));
374 			break;
375 		default:
376 			printf("%s: SIOCSIFADDR error %d\n", if_name(ifp),
377 			    error);
378 			break;
379 		}
380 
381 		/* undo changes */
382 		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
383 		IFAFREE(&ia->ia_ifa);
384 		if (oia)
385 			oia->ia_next = ia->ia_next;
386 		else
387 			in6_ifaddr = ia->ia_next;
388 		IFAFREE(&ia->ia_ifa);
389 		return -1;
390 	}
391 
392 	/* configure link-layer address resolution */
393 	rtflag = 0;
394 	if (IN6_ARE_ADDR_EQUAL(&ia->ia_prefixmask.sin6_addr, &in6mask128))
395 		rtflag = RTF_HOST;
396 	else {
397 		switch (ifp->if_type) {
398 		case IFT_LOOP:
399 #ifdef IFT_STF
400 		case IFT_STF:
401 #endif
402 			rtflag = 0;
403 			break;
404 		default:
405 			ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
406 			ia->ia_ifa.ifa_flags |= RTF_CLONING;
407 			rtflag = RTF_CLONING;
408 			break;
409 		}
410 	}
411 
412 	/* add route to the interface. */
413 	rtrequest(RTM_ADD,
414 		  (struct sockaddr *)&ia->ia_addr,
415 		  (struct sockaddr *)&ia->ia_addr,
416 		  (struct sockaddr *)&ia->ia_prefixmask,
417 		  RTF_UP | rtflag,
418 		  (struct rtentry **)0);
419 	ia->ia_flags |= IFA_ROUTE;
420 
421 	if ((rtflag & RTF_CLONING) != 0 &&
422 	    (ifp->if_flags & IFF_MULTICAST) != 0) {
423 		/* Restore saved multicast addresses (if any). */
424 		in6_restoremkludge(ia, ifp);
425 
426 		/*
427 		 * join solicited multicast address
428 		 */
429 		bzero(&llsol, sizeof(llsol));
430 		llsol.s6_addr16[0] = htons(0xff02);
431 		llsol.s6_addr16[1] = htons(ifp->if_index);
432 		llsol.s6_addr32[1] = 0;
433 		llsol.s6_addr32[2] = htonl(1);
434 		llsol.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];
435 		llsol.s6_addr8[12] = 0xff;
436 		if (!in6_addmulti(&llsol, ifp, &error)) {
437 			nd6log((LOG_ERR, "%s: failed to join %s (errno=%d)\n",
438 			    if_name(ifp), ip6_sprintf(&llsol), error));
439 		}
440 
441 		if (in6if_do_dad(ifp)) {
442 			/* mark the address TENTATIVE, if needed. */
443 			ia->ia6_flags |= IN6_IFF_TENTATIVE;
444 			/* nd6_dad_start() will be called in in6_if_up */
445 		}
446 	}
447 
448 	return 0;
449 }
450 
451 static int
452 in6_ifattach_linklocal(ifp, altifp)
453 	struct ifnet *ifp;
454 	struct ifnet *altifp;	/*secondary EUI64 source*/
455 {
456 	struct in6_ifaddr *ia;
457 
458 	/*
459 	 * configure link-local address
460 	 */
461 	ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
462 	bzero((caddr_t)ia, sizeof(*ia));
463 	ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
464 	if (ifp->if_flags & IFF_POINTOPOINT)
465 		ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
466 	else
467 		ia->ia_ifa.ifa_dstaddr = NULL;
468 	ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
469 	ia->ia_ifp = ifp;
470 
471 	bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
472 	ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
473 	ia->ia_prefixmask.sin6_family = AF_INET6;
474 	ia->ia_prefixmask.sin6_addr = in6mask64;
475 
476 	/* just in case */
477 	bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr));
478 	ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
479 	ia->ia_dstaddr.sin6_family = AF_INET6;
480 
481 	bzero(&ia->ia_addr, sizeof(ia->ia_addr));
482 	ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
483 	ia->ia_addr.sin6_family = AF_INET6;
484 	ia->ia_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
485 	ia->ia_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
486 	ia->ia_addr.sin6_addr.s6_addr32[1] = 0;
487 	if (ifp->if_flags & IFF_LOOPBACK) {
488 		ia->ia_addr.sin6_addr.s6_addr32[2] = 0;
489 		ia->ia_addr.sin6_addr.s6_addr32[3] = htonl(1);
490 	} else {
491 		if (get_ifid(ifp, altifp, &ia->ia_addr.sin6_addr) != 0) {
492 			nd6log((LOG_ERR,
493 			    "%s: no ifid available\n", if_name(ifp)));
494 			free(ia, M_IFADDR);
495 			return -1;
496 		}
497 	}
498 
499 	ia->ia_ifa.ifa_metric = ifp->if_metric;
500 
501 	if (in6_ifattach_addaddr(ifp, ia) != 0) {
502 		/* ia will be freed on failure */
503 		return -1;
504 	}
505 
506 	return 0;
507 }
508 
509 static int
510 in6_ifattach_loopback(ifp)
511 	struct ifnet *ifp;	/* must be IFT_LOOP */
512 {
513 	struct in6_ifaddr *ia;
514 
515 	/*
516 	 * configure link-local address
517 	 */
518 	ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
519 	bzero((caddr_t)ia, sizeof(*ia));
520 	ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
521 	ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
522 	ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
523 	ia->ia_ifp = ifp;
524 
525 	bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
526 	ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
527 	ia->ia_prefixmask.sin6_family = AF_INET6;
528 	ia->ia_prefixmask.sin6_addr = in6mask128;
529 
530 	/*
531 	 * Always initialize ia_dstaddr (= broadcast address) to loopback
532 	 * address, to make getifaddr happier.
533 	 *
534 	 * For BSDI, it is mandatory.  The BSDI version of
535 	 * ifa_ifwithroute() rejects to add a route to the loopback
536 	 * interface.  Even for other systems, loopback looks somewhat
537 	 * special.
538 	 */
539 	bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr));
540 	ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
541 	ia->ia_dstaddr.sin6_family = AF_INET6;
542 	ia->ia_dstaddr.sin6_addr = in6addr_loopback;
543 
544 	bzero(&ia->ia_addr, sizeof(ia->ia_addr));
545 	ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
546 	ia->ia_addr.sin6_family = AF_INET6;
547 	ia->ia_addr.sin6_addr = in6addr_loopback;
548 
549 	ia->ia_ifa.ifa_metric = ifp->if_metric;
550 
551 	if (in6_ifattach_addaddr(ifp, ia) != 0) {
552 		/* ia will be freed on failure */
553 		return -1;
554 	}
555 
556 	return 0;
557 }
558 
559 /*
560  * XXX multiple loopback interface needs more care.  for instance,
561  * nodelocal address needs to be configured onto only one of them.
562  * XXX multiple link-local address case
563  */
564 void
565 in6_ifattach(ifp, altifp)
566 	struct ifnet *ifp;
567 	struct ifnet *altifp;	/* secondary EUI64 source */
568 {
569 	struct sockaddr_in6 mltaddr;
570 	struct sockaddr_in6 mltmask;
571 	struct sockaddr_in6 gate;
572 	struct sockaddr_in6 mask;
573 	struct in6_ifaddr *ia;
574 	struct in6_addr in6;
575 
576 	/* some of the interfaces are inherently not IPv6 capable */
577 	switch (ifp->if_type) {
578 	case IFT_BRIDGE:
579 		return;
580 	}
581 
582 	/*
583 	 * if link mtu is too small, don't try to configure IPv6.
584 	 * remember there could be some link-layer that has special
585 	 * fragmentation logic.
586 	 */
587 	if (ifp->if_mtu < IPV6_MMTU)
588 		return;
589 
590 	/* create a multicast kludge storage (if we have not had one) */
591 	in6_createmkludge(ifp);
592 
593 	/*
594 	 * quirks based on interface type
595 	 */
596 	switch (ifp->if_type) {
597 #ifdef IFT_STF
598 	case IFT_STF:
599 		/*
600 		 * 6to4 interface is a very special kind of beast.
601 		 * no multicast, no linklocal.  RFC2529 specifies how to make
602 		 * linklocals for 6to4 interface, but there's no use and
603 		 * it is rather harmful to have one.
604 		 */
605 		return;
606 #endif
607 	default:
608 		break;
609 	}
610 
611 	/*
612 	 * usually, we require multicast capability to the interface
613 	 */
614 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
615 		log(LOG_INFO, "in6_ifattach: "
616 		    "%s is not multicast capable, IPv6 not enabled\n",
617 		    if_name(ifp));
618 		return;
619 	}
620 
621 	/*
622 	 * assign link-local address, if there's none
623 	 */
624 	ia = in6ifa_ifpforlinklocal(ifp, 0);
625 	if (ia == NULL) {
626 		if (in6_ifattach_linklocal(ifp, altifp) != 0)
627 			return;
628 		ia = in6ifa_ifpforlinklocal(ifp, 0);
629 
630 		if (ia == NULL) {
631 			printf("%s: failed to add link-local address\n",
632 			    if_name(ifp));
633 
634 			/* we can't initialize multicasts without link-local */
635 			return;
636 		}
637 	}
638 
639 	if (ifp->if_flags & IFF_POINTOPOINT) {
640 		/*
641 		 * route local address to loopback
642 		 */
643 		bzero(&gate, sizeof(gate));
644 		gate.sin6_len = sizeof(struct sockaddr_in6);
645 		gate.sin6_family = AF_INET6;
646 		gate.sin6_addr = in6addr_loopback;
647 		bzero(&mask, sizeof(mask));
648 		mask.sin6_len = sizeof(struct sockaddr_in6);
649 		mask.sin6_family = AF_INET6;
650 		mask.sin6_addr = in6mask64;
651 		rtrequest(RTM_ADD,
652 			  (struct sockaddr *)&ia->ia_addr,
653 			  (struct sockaddr *)&gate,
654 			  (struct sockaddr *)&mask,
655 			  RTF_UP|RTF_HOST,
656 			  (struct rtentry **)0);
657 	}
658 
659 	/*
660 	 * assign loopback address for loopback interface
661 	 * XXX multiple loopback interface case
662 	 */
663 	in6 = in6addr_loopback;
664 	if (ifp->if_flags & IFF_LOOPBACK) {
665 		if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
666 			if (in6_ifattach_loopback(ifp) != 0)
667 				return;
668 		}
669 	}
670 
671 #ifdef DIAGNOSTIC
672 	if (!ia) {
673 		panic("ia == NULL in in6_ifattach");
674 		/*NOTREACHED*/
675 	}
676 #endif
677 
678 	/*
679 	 * join multicast
680 	 */
681 	if (ifp->if_flags & IFF_MULTICAST) {
682 		int error;	/* not used */
683 		struct in6_multi *in6m;
684 
685 		/* Restore saved multicast addresses (if any). */
686 		in6_restoremkludge(ia, ifp);
687 
688 		bzero(&mltmask, sizeof(mltmask));
689 		mltmask.sin6_len = sizeof(struct sockaddr_in6);
690 		mltmask.sin6_family = AF_INET6;
691 		mltmask.sin6_addr = in6mask32;
692 
693 		/*
694 		 * join link-local all-nodes address
695 		 */
696 		bzero(&mltaddr, sizeof(mltaddr));
697 		mltaddr.sin6_len = sizeof(struct sockaddr_in6);
698 		mltaddr.sin6_family = AF_INET6;
699 		mltaddr.sin6_addr = in6addr_linklocal_allnodes;
700 		mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
701 
702 		IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
703 		if (in6m == NULL) {
704 			rtrequest(RTM_ADD,
705 				  (struct sockaddr *)&mltaddr,
706 				  (struct sockaddr *)&ia->ia_addr,
707 				  (struct sockaddr *)&mltmask,
708 				  RTF_UP|RTF_CLONING,  /* xxx */
709 				  (struct rtentry **)0);
710 			if (!in6_addmulti(&mltaddr.sin6_addr, ifp, &error)) {
711 				nd6log((LOG_ERR, "%s: failed to join %s "
712 				    "(errno=%d)\n", if_name(ifp),
713 				    ip6_sprintf(&mltaddr.sin6_addr),
714 				    error));
715 			}
716 		}
717 
718 		if (ifp->if_flags & IFF_LOOPBACK) {
719 			in6 = in6addr_loopback;
720 			ia = in6ifa_ifpwithaddr(ifp, &in6);
721 			/*
722 			 * join node-local all-nodes address, on loopback
723 			 */
724 			mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
725 
726 			IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
727 			if (in6m == NULL && ia != NULL) {
728 				rtrequest(RTM_ADD,
729 					  (struct sockaddr *)&mltaddr,
730 					  (struct sockaddr *)&ia->ia_addr,
731 					  (struct sockaddr *)&mltmask,
732 					  RTF_UP,
733 					  (struct rtentry **)0);
734 				if (!in6_addmulti(&mltaddr.sin6_addr, ifp,
735 				    &error)) {
736 					nd6log((LOG_ERR, "%s: failed to join "
737 					    "%s (errno=%d)\n", if_name(ifp),
738 					    ip6_sprintf(&mltaddr.sin6_addr),
739 					    error));
740 				}
741 			}
742 		}
743 	}
744 }
745 
746 /*
747  * NOTE: in6_ifdetach() does not support loopback if at this moment.
748  * We don't need this function in bsdi, because interfaces are never removed
749  * from the ifnet list in bsdi.
750  */
751 void
752 in6_ifdetach(ifp)
753 	struct ifnet *ifp;
754 {
755 	struct in6_ifaddr *ia, *oia;
756 	struct ifaddr *ifa, *next;
757 	struct rtentry *rt;
758 	short rtflags;
759 	struct sockaddr_in6 sin6;
760 
761 	/* nuke prefix list.  this may try to remove some of ifaddrs as well */
762 	in6_purgeprefix(ifp);
763 
764 	/* remove neighbor management table */
765 	nd6_purge(ifp);
766 
767 	/* nuke any of IPv6 addresses we have */
768 	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
769 	{
770 		next = ifa->ifa_list.tqe_next;
771 		if (ifa->ifa_addr->sa_family != AF_INET6)
772 			continue;
773 		in6_purgeaddr(ifa, ifp);
774 	}
775 
776 	/* undo everything done by in6_ifattach(), just in case */
777 	for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
778 	{
779 		next = ifa->ifa_list.tqe_next;
780 
781 
782 		if (ifa->ifa_addr->sa_family != AF_INET6
783 		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
784 			continue;
785 		}
786 
787 		ia = (struct in6_ifaddr *)ifa;
788 
789 		/* remove from the routing table */
790 		if ((ia->ia_flags & IFA_ROUTE)
791 		 && (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
792 			rtflags = rt->rt_flags;
793 			rtfree(rt);
794 			rtrequest(RTM_DELETE,
795 				(struct sockaddr *)&ia->ia_addr,
796 				(struct sockaddr *)&ia->ia_addr,
797 				(struct sockaddr *)&ia->ia_prefixmask,
798 				rtflags, (struct rtentry **)0);
799 		}
800 
801 		/* remove from the linked list */
802 		TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
803 		IFAFREE(&ia->ia_ifa);
804 
805 		/* also remove from the IPv6 address chain(itojun&jinmei) */
806 		oia = ia;
807 		if (oia == (ia = in6_ifaddr))
808 			in6_ifaddr = ia->ia_next;
809 		else {
810 			while (ia->ia_next && (ia->ia_next != oia))
811 				ia = ia->ia_next;
812 			if (ia->ia_next)
813 				ia->ia_next = oia->ia_next;
814 			else {
815 				nd6log((LOG_ERR,
816 				    "%s: didn't unlink in6ifaddr from "
817 				    "list\n", if_name(ifp)));
818 			}
819 		}
820 
821 		IFAFREE(&oia->ia_ifa);
822 	}
823 
824 	/* cleanup multicast address kludge table, if there is any */
825 	in6_purgemkludge(ifp);
826 
827 	/*
828 	 * remove neighbor management table.  we call it twice just to make
829 	 * sure we nuke everything.  maybe we need just one call.
830 	 * XXX: since the first call did not release addresses, some prefixes
831 	 * might remain.  We should call nd6_purge() again to release the
832 	 * prefixes after removing all addresses above.
833 	 * (Or can we just delay calling nd6_purge until at this point?)
834 	 */
835 	nd6_purge(ifp);
836 
837 	/* remove route to link-local allnodes multicast (ff02::1) */
838 	bzero(&sin6, sizeof(sin6));
839 	sin6.sin6_len = sizeof(struct sockaddr_in6);
840 	sin6.sin6_family = AF_INET6;
841 	sin6.sin6_addr = in6addr_linklocal_allnodes;
842 	sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
843 	rt = rtalloc1((struct sockaddr *)&sin6, 0);
844 	if (rt && rt->rt_ifp == ifp) {
845 		rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
846 			rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
847 		rtfree(rt);
848 	}
849 }
850