xref: /freebsd/sys/netinet6/in6_ifattach.c (revision 9e792f7ef7298080c058fbc2d36a4e60e596dae9)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	$KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/jail.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/proc.h>
43 #include <sys/rmlock.h>
44 #include <sys/syslog.h>
45 #include <sys/md5.h>
46 
47 #include <net/if.h>
48 #include <net/if_var.h>
49 #include <net/if_dl.h>
50 #include <net/if_private.h>
51 #include <net/if_types.h>
52 #include <net/route.h>
53 #include <net/vnet.h>
54 
55 #include <netinet/in.h>
56 #include <netinet/in_var.h>
57 #include <netinet/if_ether.h>
58 #include <netinet/in_pcb.h>
59 #include <netinet/ip_var.h>
60 #include <netinet/udp.h>
61 #include <netinet/udp_var.h>
62 
63 #include <netinet/ip6.h>
64 #include <netinet6/ip6_var.h>
65 #include <netinet6/in6_var.h>
66 #include <netinet6/in6_pcb.h>
67 #include <netinet6/in6_ifattach.h>
68 #include <netinet6/ip6_var.h>
69 #include <netinet6/nd6.h>
70 #include <netinet6/mld6_var.h>
71 #include <netinet6/scope6_var.h>
72 
73 #ifdef IP6_AUTO_LINKLOCAL
74 VNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL;
75 #else
76 VNET_DEFINE(int, ip6_auto_linklocal) = 1;	/* enabled by default */
77 #endif
78 
79 VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch);
80 #define	V_in6_tmpaddrtimer_ch		VNET(in6_tmpaddrtimer_ch)
81 
82 VNET_DECLARE(struct inpcbinfo, ripcbinfo);
83 #define	V_ripcbinfo			VNET(ripcbinfo)
84 
85 static int get_rand_ifid(struct ifnet *, struct in6_addr *);
86 static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
87 static int in6_ifattach_loopback(struct ifnet *);
88 static void in6_purgemaddrs(struct ifnet *);
89 
90 #define EUI64_GBIT	0x01
91 #define EUI64_UBIT	0x02
92 #define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
93 #define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
94 #define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
95 #define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
96 #define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
97 
98 #define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
99 #define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
100 
101 /*
102  * Generate a last-resort interface identifier, when the machine has no
103  * IEEE802/EUI64 address sources.
104  * The goal here is to get an interface identifier that is
105  * (1) random enough and (2) does not change across reboot.
106  * We currently use MD5(hostname) for it.
107  *
108  * in6 - upper 64bits are preserved
109  */
110 static int
get_rand_ifid(struct ifnet * ifp,struct in6_addr * in6)111 get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
112 {
113 	MD5_CTX ctxt;
114 	struct prison *pr;
115 	u_int8_t digest[16];
116 	int hostnamelen;
117 
118 	pr = curthread->td_ucred->cr_prison;
119 	mtx_lock(&pr->pr_mtx);
120 	hostnamelen = strlen(pr->pr_hostname);
121 #if 0
122 	/* we need at least several letters as seed for ifid */
123 	if (hostnamelen < 3) {
124 		mtx_unlock(&pr->pr_mtx);
125 		return -1;
126 	}
127 #endif
128 
129 	/* generate 8 bytes of pseudo-random value. */
130 	bzero(&ctxt, sizeof(ctxt));
131 	MD5Init(&ctxt);
132 	MD5Update(&ctxt, pr->pr_hostname, hostnamelen);
133 	mtx_unlock(&pr->pr_mtx);
134 	MD5Final(digest, &ctxt);
135 
136 	/* assumes sizeof(digest) > sizeof(ifid) */
137 	bcopy(digest, &in6->s6_addr[8], 8);
138 
139 	/* make sure to set "u" bit to local, and "g" bit to individual. */
140 	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
141 	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
142 
143 	/* convert EUI64 into IPv6 interface identifier */
144 	EUI64_TO_IFID(in6);
145 
146 	return 0;
147 }
148 
149 
150 /*
151  * Get interface identifier for the specified interface.
152  * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
153  *
154  * in6 - upper 64bits are preserved
155  */
156 int
in6_get_hw_ifid(struct ifnet * ifp,struct in6_addr * in6)157 in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
158 {
159 	struct ifaddr *ifa;
160 	struct sockaddr_dl *sdl;
161 	u_int8_t *addr;
162 	size_t addrlen;
163 	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
164 	static u_int8_t allone[8] =
165 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
166 
167 	NET_EPOCH_ASSERT();
168 
169 	CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
170 		if (ifa->ifa_addr->sa_family != AF_LINK)
171 			continue;
172 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
173 		if (sdl == NULL)
174 			continue;
175 		if (sdl->sdl_alen == 0)
176 			continue;
177 
178 		goto found;
179 	}
180 
181 	return -1;
182 
183 found:
184 	addr = LLADDR(sdl);
185 	addrlen = sdl->sdl_alen;
186 
187 	/* get EUI64 */
188 	switch (ifp->if_type) {
189 	case IFT_BRIDGE:
190 	case IFT_ETHER:
191 	case IFT_L2VLAN:
192 	case IFT_ATM:
193 	case IFT_IEEE1394:
194 		/* IEEE802/EUI64 cases - what others? */
195 		/* IEEE1394 uses 16byte length address starting with EUI64 */
196 		if (addrlen > 8)
197 			addrlen = 8;
198 
199 		/* look at IEEE802/EUI64 only */
200 		if (addrlen != 8 && addrlen != 6)
201 			return -1;
202 
203 		/*
204 		 * check for invalid MAC address - on bsdi, we see it a lot
205 		 * since wildboar configures all-zero MAC on pccard before
206 		 * card insertion.
207 		 */
208 		if (bcmp(addr, allzero, addrlen) == 0)
209 			return -1;
210 		if (bcmp(addr, allone, addrlen) == 0)
211 			return -1;
212 
213 		/* make EUI64 address */
214 		if (addrlen == 8)
215 			bcopy(addr, &in6->s6_addr[8], 8);
216 		else if (addrlen == 6) {
217 			in6->s6_addr[8] = addr[0];
218 			in6->s6_addr[9] = addr[1];
219 			in6->s6_addr[10] = addr[2];
220 			in6->s6_addr[11] = 0xff;
221 			in6->s6_addr[12] = 0xfe;
222 			in6->s6_addr[13] = addr[3];
223 			in6->s6_addr[14] = addr[4];
224 			in6->s6_addr[15] = addr[5];
225 		}
226 		break;
227 
228 	case IFT_GIF:
229 	case IFT_STF:
230 		/*
231 		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
232 		 * however, IPv4 address is not very suitable as unique
233 		 * identifier source (can be renumbered).
234 		 * we don't do this.
235 		 */
236 		return -1;
237 
238 	case IFT_INFINIBAND:
239 		if (addrlen != 20)
240 			return -1;
241 		bcopy(addr + 12, &in6->s6_addr[8], 8);
242 		break;
243 
244 	default:
245 		return -1;
246 	}
247 
248 	/* sanity check: g bit must not indicate "group" */
249 	if (EUI64_GROUP(in6))
250 		return -1;
251 
252 	/* convert EUI64 into IPv6 interface identifier */
253 	EUI64_TO_IFID(in6);
254 
255 	/*
256 	 * sanity check: ifid must not be all zero, avoid conflict with
257 	 * subnet router anycast
258 	 */
259 	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
260 	    bcmp(&in6->s6_addr[9], allzero, 7) == 0)
261 		return -1;
262 
263 	return 0;
264 }
265 
266 /*
267  * Get interface identifier for the specified interface.  If it is not
268  * available on ifp0, borrow interface identifier from other information
269  * sources.
270  *
271  * altifp - secondary EUI64 source
272  */
273 int
in6_get_ifid(struct ifnet * ifp0,struct ifnet * altifp,struct in6_addr * in6)274 in6_get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
275     struct in6_addr *in6)
276 {
277 	struct ifnet *ifp;
278 
279 	NET_EPOCH_ASSERT();
280 
281 	/* first, try to get it from the interface itself */
282 	if (in6_get_hw_ifid(ifp0, in6) == 0) {
283 		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
284 		    if_name(ifp0)));
285 		goto success;
286 	}
287 
288 	/* try secondary EUI64 source. this basically is for ATM PVC */
289 	if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
290 		nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
291 		    if_name(ifp0), if_name(altifp)));
292 		goto success;
293 	}
294 
295 	/* next, try to get it from some other hardware interface */
296 	CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
297 		if (ifp == ifp0)
298 			continue;
299 		if (in6_get_hw_ifid(ifp, in6) != 0)
300 			continue;
301 
302 		/*
303 		 * to borrow ifid from other interface, ifid needs to be
304 		 * globally unique
305 		 */
306 		if (IFID_UNIVERSAL(in6)) {
307 			nd6log((LOG_DEBUG,
308 			    "%s: borrow interface identifier from %s\n",
309 			    if_name(ifp0), if_name(ifp)));
310 			goto success;
311 		}
312 	}
313 
314 	/* last resort: get from random number source */
315 	if (get_rand_ifid(ifp, in6) == 0) {
316 		nd6log((LOG_DEBUG,
317 		    "%s: interface identifier generated by random number\n",
318 		    if_name(ifp0)));
319 		goto success;
320 	}
321 
322 	printf("%s: failed to get interface identifier\n", if_name(ifp0));
323 	return -1;
324 
325 success:
326 	nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
327 	    if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
328 	    in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
329 	    in6->s6_addr[14], in6->s6_addr[15]));
330 	return 0;
331 }
332 
333 /*
334  * altifp - secondary EUI64 source
335  */
336 static int
in6_ifattach_linklocal(struct ifnet * ifp,struct ifnet * altifp)337 in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
338 {
339 	struct in6_ifaddr *ia;
340 	struct in6_aliasreq ifra;
341 	struct nd_prefixctl pr0;
342 	struct epoch_tracker et;
343 	struct nd_prefix *pr;
344 	int error;
345 
346 	/*
347 	 * configure link-local address.
348 	 */
349 	in6_prepare_ifra(&ifra, NULL, &in6mask64);
350 
351 	ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
352 	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
353 	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
354 		ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
355 		ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
356 	} else {
357 		NET_EPOCH_ENTER(et);
358 		error = in6_get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr);
359 		NET_EPOCH_EXIT(et);
360 		if (error != 0) {
361 			nd6log((LOG_ERR,
362 			    "%s: no ifid available\n", if_name(ifp)));
363 			return (-1);
364 		}
365 	}
366 	if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
367 		return (-1);
368 
369 	/* link-local addresses should NEVER expire. */
370 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
371 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
372 
373 	/*
374 	 * Now call in6_update_ifa() to do a bunch of procedures to configure
375 	 * a link-local address. We can set the 3rd argument to NULL, because
376 	 * we know there's no other link-local address on the interface
377 	 * and therefore we are adding one (instead of updating one).
378 	 */
379 	if ((error = in6_update_ifa(ifp, &ifra, NULL,
380 				    IN6_IFAUPDATE_DADDELAY)) != 0) {
381 		/*
382 		 * XXX: When the interface does not support IPv6, this call
383 		 * would fail in the SIOCSIFADDR ioctl.  I believe the
384 		 * notification is rather confusing in this case, so just
385 		 * suppress it.  (jinmei@kame.net 20010130)
386 		 */
387 		if (error != EAFNOSUPPORT)
388 			nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
389 			    "configure a link-local address on %s "
390 			    "(errno=%d)\n",
391 			    if_name(ifp), error));
392 		return (-1);
393 	}
394 
395 	NET_EPOCH_ENTER(et);
396 	ia = in6ifa_ifpforlinklocal(ifp, 0);
397 	NET_EPOCH_EXIT(et);
398 	if (ia == NULL) {
399 		/*
400 		 * Another thread removed the address that we just added.
401 		 * This should be rare, but it happens.
402 		 */
403 		nd6log((LOG_NOTICE, "%s: %s: new link-local address "
404 			"disappeared\n", __func__, if_name(ifp)));
405 		return (-1);
406 	}
407 	ifa_free(&ia->ia_ifa);
408 
409 	/*
410 	 * Make the link-local prefix (fe80::%link/64) as on-link.
411 	 * Since we'd like to manage prefixes separately from addresses,
412 	 * we make an ND6 prefix structure for the link-local prefix,
413 	 * and add it to the prefix list as a never-expire prefix.
414 	 * XXX: this change might affect some existing code base...
415 	 */
416 	bzero(&pr0, sizeof(pr0));
417 	pr0.ndpr_ifp = ifp;
418 	/* this should be 64 at this moment. */
419 	pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
420 	pr0.ndpr_prefix = ifra.ifra_addr;
421 	/* apply the mask for safety. (nd6_prelist_add will apply it again) */
422 	IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, &in6mask64);
423 	/*
424 	 * Initialize parameters.  The link-local prefix must always be
425 	 * on-link, and its lifetimes never expire.
426 	 */
427 	pr0.ndpr_raf_onlink = 1;
428 	pr0.ndpr_raf_auto = 1;	/* probably meaningless */
429 	pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
430 	pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
431 	/*
432 	 * Since there is no other link-local addresses, nd6_prefix_lookup()
433 	 * probably returns NULL.  However, we cannot always expect the result.
434 	 * For example, if we first remove the (only) existing link-local
435 	 * address, and then reconfigure another one, the prefix is still
436 	 * valid with referring to the old link-local address.
437 	 */
438 	if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
439 		if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
440 			return (error);
441 		/* Reference prefix */
442 		ia->ia6_ndpr = pr;
443 		pr->ndpr_addrcnt++;
444 	} else
445 		nd6_prefix_rele(pr);
446 
447 	return 0;
448 }
449 
450 /*
451  * ifp - must be IFT_LOOP
452  */
453 static int
in6_ifattach_loopback(struct ifnet * ifp)454 in6_ifattach_loopback(struct ifnet *ifp)
455 {
456 	struct in6_aliasreq ifra;
457 	int error;
458 
459 	in6_prepare_ifra(&ifra, &in6addr_loopback, &in6mask128);
460 
461 	/*
462 	 * Always initialize ia_dstaddr (= broadcast address) to loopback
463 	 * address.  Follows IPv4 practice - see in_ifinit().
464 	 */
465 	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
466 	ifra.ifra_dstaddr.sin6_family = AF_INET6;
467 	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
468 
469 	/* the loopback  address should NEVER expire. */
470 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
471 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
472 
473 	/*
474 	 * We are sure that this is a newly assigned address, so we can set
475 	 * NULL to the 3rd arg.
476 	 */
477 	if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
478 		nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
479 		    "the loopback address on %s (errno=%d)\n",
480 		    if_name(ifp), error));
481 		return (-1);
482 	}
483 
484 	return 0;
485 }
486 
487 /*
488  * compute NI group address, based on the current hostname setting.
489  * see RFC 4620.
490  *
491  * when ifp == NULL, the caller is responsible for filling scopeid.
492  *
493  * If oldmcprefix == 1, FF02:0:0:0:0:2::/96 is used for NI group address
494  * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620.
495  */
496 static int
in6_nigroup0(struct ifnet * ifp,const char * name,int namelen,struct in6_addr * in6,int oldmcprefix)497 in6_nigroup0(struct ifnet *ifp, const char *name, int namelen,
498     struct in6_addr *in6, int oldmcprefix)
499 {
500 	struct prison *pr;
501 	const char *p;
502 	u_char *q;
503 	MD5_CTX ctxt;
504 	u_int8_t digest[16];
505 	char l;
506 	char n[64];	/* a single label must not exceed 63 chars */
507 
508 	/*
509 	 * If no name is given and namelen is -1,
510 	 * we try to do the hostname lookup ourselves.
511 	 */
512 	if (!name && namelen == -1) {
513 		pr = curthread->td_ucred->cr_prison;
514 		mtx_lock(&pr->pr_mtx);
515 		name = pr->pr_hostname;
516 		namelen = strlen(name);
517 	} else
518 		pr = NULL;
519 	if (!name || !namelen) {
520 		if (pr != NULL)
521 			mtx_unlock(&pr->pr_mtx);
522 		return -1;
523 	}
524 
525 	p = name;
526 	while (p && *p && *p != '.' && p - name < namelen)
527 		p++;
528 	if (p == name || p - name > sizeof(n) - 1) {
529 		if (pr != NULL)
530 			mtx_unlock(&pr->pr_mtx);
531 		return -1;	/* label too long */
532 	}
533 	l = p - name;
534 	strncpy(n, name, l);
535 	if (pr != NULL)
536 		mtx_unlock(&pr->pr_mtx);
537 	n[(int)l] = '\0';
538 	for (q = n; *q; q++) {
539 		if ('A' <= *q && *q <= 'Z')
540 			*q = *q - 'A' + 'a';
541 	}
542 
543 	/* generate 16 bytes of pseudo-random value. */
544 	bzero(&ctxt, sizeof(ctxt));
545 	MD5Init(&ctxt);
546 	MD5Update(&ctxt, &l, sizeof(l));
547 	MD5Update(&ctxt, n, l);
548 	MD5Final(digest, &ctxt);
549 
550 	bzero(in6, sizeof(*in6));
551 	in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
552 	in6->s6_addr8[11] = 2;
553 	if (oldmcprefix == 0) {
554 		in6->s6_addr8[12] = 0xff;
555 	 	/* Copy the first 24 bits of 128-bit hash into the address. */
556 		bcopy(digest, &in6->s6_addr8[13], 3);
557 	} else {
558 	 	/* Copy the first 32 bits of 128-bit hash into the address. */
559 		bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
560 	}
561 	if (in6_setscope(in6, ifp, NULL))
562 		return (-1); /* XXX: should not fail */
563 
564 	return 0;
565 }
566 
567 int
in6_nigroup(struct ifnet * ifp,const char * name,int namelen,struct in6_addr * in6)568 in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
569     struct in6_addr *in6)
570 {
571 
572 	return (in6_nigroup0(ifp, name, namelen, in6, 0));
573 }
574 
575 int
in6_nigroup_oldmcprefix(struct ifnet * ifp,const char * name,int namelen,struct in6_addr * in6)576 in6_nigroup_oldmcprefix(struct ifnet *ifp, const char *name, int namelen,
577     struct in6_addr *in6)
578 {
579 
580 	return (in6_nigroup0(ifp, name, namelen, in6, 1));
581 }
582 
583 /*
584  * XXX multiple loopback interface needs more care.  for instance,
585  * nodelocal address needs to be configured onto only one of them.
586  * XXX multiple link-local address case
587  *
588  * altifp - secondary EUI64 source
589  */
590 void
in6_ifattach(struct ifnet * ifp,struct ifnet * altifp)591 in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
592 {
593 	struct in6_ifaddr *ia;
594 
595 	if (ifp->if_afdata[AF_INET6] == NULL)
596 		return;
597 	/*
598 	 * quirks based on interface type
599 	 */
600 	switch (ifp->if_type) {
601 	case IFT_STF:
602 		/*
603 		 * 6to4 interface is a very special kind of beast.
604 		 * no multicast, no linklocal.  RFC2529 specifies how to make
605 		 * linklocals for 6to4 interface, but there's no use and
606 		 * it is rather harmful to have one.
607 		 */
608 		ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
609 		ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD;
610 		break;
611 	default:
612 		break;
613 	}
614 
615 	/*
616 	 * usually, we require multicast capability to the interface
617 	 */
618 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
619 		nd6log((LOG_INFO, "in6_ifattach: "
620 		    "%s is not multicast capable, IPv6 not enabled\n",
621 		    if_name(ifp)));
622 		return;
623 	}
624 
625 	/*
626 	 * assign loopback address for loopback interface.
627 	 */
628 	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
629 		/*
630 		 * check that loopback address doesn't exist yet.
631 		 */
632 		ia = in6ifa_ifwithaddr(&in6addr_loopback, 0, false);
633 		if (ia == NULL)
634 			in6_ifattach_loopback(ifp);
635 	}
636 
637 	/*
638 	 * assign a link-local address, if there's none.
639 	 */
640 	if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
641 	    ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) {
642 		struct epoch_tracker et;
643 
644 		NET_EPOCH_ENTER(et);
645 		ia = in6ifa_ifpforlinklocal(ifp, 0);
646 		NET_EPOCH_EXIT(et);
647 		if (ia == NULL)
648 			in6_ifattach_linklocal(ifp, altifp);
649 		else
650 			ifa_free(&ia->ia_ifa);
651 	}
652 }
653 
654 /*
655  * NOTE: in6_ifdetach() does not support loopback if at this moment.
656  *
657  * When shutting down a VNET we clean up layers top-down.  In that case
658  * upper layer protocols (ulp) are cleaned up already and locks are destroyed
659  * and we must not call into these cleanup functions anymore, thus purgeulp
660  * is set to 0 in that case by in6_ifdetach_destroy().
661  * The normal case of destroying a (cloned) interface still needs to cleanup
662  * everything related to the interface and will have purgeulp set to 1.
663  */
664 static void
_in6_ifdetach(struct ifnet * ifp,int purgeulp)665 _in6_ifdetach(struct ifnet *ifp, int purgeulp)
666 {
667 	struct ifaddr *ifa, *next;
668 
669 	if (ifp->if_afdata[AF_INET6] == NULL)
670 		return;
671 
672 	/*
673 	 * nuke any of IPv6 addresses we have
674 	 */
675 	CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
676 		if (ifa->ifa_addr->sa_family != AF_INET6)
677 			continue;
678 		in6_purgeaddr(ifa);
679 	}
680 	if (purgeulp) {
681 		IN6_MULTI_LOCK();
682 		in6_pcbpurgeif0(&V_udbinfo, ifp);
683 		in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
684 		in6_pcbpurgeif0(&V_ripcbinfo, ifp);
685 		IN6_MULTI_UNLOCK();
686 	}
687 	/* leave from all multicast groups joined */
688 	in6_purgemaddrs(ifp);
689 
690 	/*
691 	 * Remove neighbor management table.
692 	 * Enabling the nd6_purge will panic on vmove for interfaces on VNET
693 	 * teardown as the IPv6 layer is cleaned up already and the locks
694 	 * are destroyed.
695 	 */
696 	if (purgeulp)
697 		nd6_purge(ifp);
698 }
699 
700 void
in6_ifdetach(struct ifnet * ifp)701 in6_ifdetach(struct ifnet *ifp)
702 {
703 
704 	_in6_ifdetach(ifp, 1);
705 }
706 
707 void
in6_ifdetach_destroy(struct ifnet * ifp)708 in6_ifdetach_destroy(struct ifnet *ifp)
709 {
710 
711 	_in6_ifdetach(ifp, 0);
712 }
713 
714 void
in6_tmpaddrtimer(void * arg)715 in6_tmpaddrtimer(void *arg)
716 {
717 	CURVNET_SET((struct vnet *) arg);
718 
719 	callout_reset(&V_in6_tmpaddrtimer_ch,
720 	    (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
721 	    V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);
722 
723 	CURVNET_RESTORE();
724 }
725 
726 static void
in6_purgemaddrs(struct ifnet * ifp)727 in6_purgemaddrs(struct ifnet *ifp)
728 {
729 	struct in6_multi_head inmh;
730 
731 	SLIST_INIT(&inmh);
732 	IN6_MULTI_LOCK();
733 	IN6_MULTI_LIST_LOCK();
734 	mld_ifdetach(ifp, &inmh);
735 	IN6_MULTI_LIST_UNLOCK();
736 	IN6_MULTI_UNLOCK();
737 	in6m_release_list_deferred(&inmh);
738 
739 	/*
740 	 * Make sure all multicast deletions invoking if_ioctl() are
741 	 * completed before returning. Else we risk accessing a freed
742 	 * ifnet structure pointer.
743 	 */
744 	in6m_release_wait(NULL);
745 }
746 
747 void
in6_ifattach_destroy(void)748 in6_ifattach_destroy(void)
749 {
750 
751 	callout_drain(&V_in6_tmpaddrtimer_ch);
752 }
753 
754 static void
in6_ifattach_init(void * dummy)755 in6_ifattach_init(void *dummy)
756 {
757 
758 	/* Timer for regeneranation of temporary addresses randomize ID. */
759 	callout_init(&V_in6_tmpaddrtimer_ch, 1);
760 	callout_reset(&V_in6_tmpaddrtimer_ch,
761 	    (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
762 	    V_ip6_temp_regen_advance) * hz,
763 	    in6_tmpaddrtimer, curvnet);
764 }
765 
766 /*
767  * Cheat.
768  * This must be after route_init(), which is now SI_ORDER_THIRD.
769  */
770 SYSINIT(in6_ifattach_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
771     in6_ifattach_init, NULL);
772