xref: /xnu-10002.61.3/bsd/netinet6/in6_ifattach.c (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1*0f4c859eSApple OSS Distributions /*
2*0f4c859eSApple OSS Distributions  * Copyright (c) 2003-2021 Apple Inc. All rights reserved.
3*0f4c859eSApple OSS Distributions  *
4*0f4c859eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*0f4c859eSApple OSS Distributions  *
6*0f4c859eSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*0f4c859eSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*0f4c859eSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*0f4c859eSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*0f4c859eSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*0f4c859eSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*0f4c859eSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*0f4c859eSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*0f4c859eSApple OSS Distributions  *
15*0f4c859eSApple OSS Distributions  * Please obtain a copy of the License at
16*0f4c859eSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*0f4c859eSApple OSS Distributions  *
18*0f4c859eSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*0f4c859eSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*0f4c859eSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*0f4c859eSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*0f4c859eSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*0f4c859eSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*0f4c859eSApple OSS Distributions  * limitations under the License.
25*0f4c859eSApple OSS Distributions  *
26*0f4c859eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*0f4c859eSApple OSS Distributions  */
28*0f4c859eSApple OSS Distributions 
29*0f4c859eSApple OSS Distributions /*
30*0f4c859eSApple OSS Distributions  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
31*0f4c859eSApple OSS Distributions  * All rights reserved.
32*0f4c859eSApple OSS Distributions  *
33*0f4c859eSApple OSS Distributions  * Redistribution and use in source and binary forms, with or without
34*0f4c859eSApple OSS Distributions  * modification, are permitted provided that the following conditions
35*0f4c859eSApple OSS Distributions  * are met:
36*0f4c859eSApple OSS Distributions  * 1. Redistributions of source code must retain the above copyright
37*0f4c859eSApple OSS Distributions  *    notice, this list of conditions and the following disclaimer.
38*0f4c859eSApple OSS Distributions  * 2. Redistributions in binary form must reproduce the above copyright
39*0f4c859eSApple OSS Distributions  *    notice, this list of conditions and the following disclaimer in the
40*0f4c859eSApple OSS Distributions  *    documentation and/or other materials provided with the distribution.
41*0f4c859eSApple OSS Distributions  * 3. Neither the name of the project nor the names of its contributors
42*0f4c859eSApple OSS Distributions  *    may be used to endorse or promote products derived from this software
43*0f4c859eSApple OSS Distributions  *    without specific prior written permission.
44*0f4c859eSApple OSS Distributions  *
45*0f4c859eSApple OSS Distributions  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
46*0f4c859eSApple OSS Distributions  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47*0f4c859eSApple OSS Distributions  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48*0f4c859eSApple OSS Distributions  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
49*0f4c859eSApple OSS Distributions  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50*0f4c859eSApple OSS Distributions  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51*0f4c859eSApple OSS Distributions  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52*0f4c859eSApple OSS Distributions  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53*0f4c859eSApple OSS Distributions  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54*0f4c859eSApple OSS Distributions  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55*0f4c859eSApple OSS Distributions  * SUCH DAMAGE.
56*0f4c859eSApple OSS Distributions  */
57*0f4c859eSApple OSS Distributions 
58*0f4c859eSApple OSS Distributions #include <sys/param.h>
59*0f4c859eSApple OSS Distributions #include <sys/systm.h>
60*0f4c859eSApple OSS Distributions #include <sys/malloc.h>
61*0f4c859eSApple OSS Distributions #include <sys/socket.h>
62*0f4c859eSApple OSS Distributions #include <sys/socketvar.h>
63*0f4c859eSApple OSS Distributions #include <sys/sockio.h>
64*0f4c859eSApple OSS Distributions #include <sys/kernel.h>
65*0f4c859eSApple OSS Distributions #include <sys/syslog.h>
66*0f4c859eSApple OSS Distributions #include <libkern/crypto/sha2.h>
67*0f4c859eSApple OSS Distributions #include <libkern/OSAtomic.h>
68*0f4c859eSApple OSS Distributions #include <kern/locks.h>
69*0f4c859eSApple OSS Distributions 
70*0f4c859eSApple OSS Distributions #include <net/if.h>
71*0f4c859eSApple OSS Distributions #include <net/if_dl.h>
72*0f4c859eSApple OSS Distributions #include <net/if_types.h>
73*0f4c859eSApple OSS Distributions #include <net/route.h>
74*0f4c859eSApple OSS Distributions #include <net/kpi_protocol.h>
75*0f4c859eSApple OSS Distributions 
76*0f4c859eSApple OSS Distributions #include <netinet/in.h>
77*0f4c859eSApple OSS Distributions #include <netinet/in_var.h>
78*0f4c859eSApple OSS Distributions #include <netinet/if_ether.h>
79*0f4c859eSApple OSS Distributions #include <netinet/in_pcb.h>
80*0f4c859eSApple OSS Distributions #include <netinet/icmp6.h>
81*0f4c859eSApple OSS Distributions 
82*0f4c859eSApple OSS Distributions #include <netinet/ip6.h>
83*0f4c859eSApple OSS Distributions #include <netinet6/ip6_var.h>
84*0f4c859eSApple OSS Distributions #include <netinet6/in6_var.h>
85*0f4c859eSApple OSS Distributions #include <netinet6/in6_pcb.h>
86*0f4c859eSApple OSS Distributions #include <netinet6/in6_ifattach.h>
87*0f4c859eSApple OSS Distributions #include <netinet6/ip6_var.h>
88*0f4c859eSApple OSS Distributions #include <netinet6/nd6.h>
89*0f4c859eSApple OSS Distributions #include <netinet6/scope6_var.h>
90*0f4c859eSApple OSS Distributions 
91*0f4c859eSApple OSS Distributions #include <net/net_osdep.h>
92*0f4c859eSApple OSS Distributions #include <dev/random/randomdev.h>
93*0f4c859eSApple OSS Distributions 
94*0f4c859eSApple OSS Distributions u_int32_t in6_maxmtu = 0;
95*0f4c859eSApple OSS Distributions 
96*0f4c859eSApple OSS Distributions #if IP6_AUTO_LINKLOCAL
97*0f4c859eSApple OSS Distributions int ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
98*0f4c859eSApple OSS Distributions #else
99*0f4c859eSApple OSS Distributions int ip6_auto_linklocal = 1;     /* enable by default */
100*0f4c859eSApple OSS Distributions #endif
101*0f4c859eSApple OSS Distributions 
102*0f4c859eSApple OSS Distributions extern struct inpcbinfo udbinfo;
103*0f4c859eSApple OSS Distributions extern struct inpcbinfo ripcbinfo;
104*0f4c859eSApple OSS Distributions 
105*0f4c859eSApple OSS Distributions static int get_rand_iid(struct ifnet *, struct in6_addr *);
106*0f4c859eSApple OSS Distributions static int in6_generate_tmp_iid(u_int8_t *, const u_int8_t *, u_int8_t *);
107*0f4c859eSApple OSS Distributions static int in6_select_iid_from_all_hw(struct ifnet *, struct ifnet *,
108*0f4c859eSApple OSS Distributions     struct in6_addr *);
109*0f4c859eSApple OSS Distributions static int in6_ifattach_linklocal(struct ifnet *, struct in6_aliasreq *);
110*0f4c859eSApple OSS Distributions static int in6_ifattach_loopback(struct ifnet *);
111*0f4c859eSApple OSS Distributions 
112*0f4c859eSApple OSS Distributions /*
113*0f4c859eSApple OSS Distributions  * Generate a last-resort interface identifier, when the machine has no
114*0f4c859eSApple OSS Distributions  * IEEE802/EUI64 address sources.
115*0f4c859eSApple OSS Distributions  * The goal here is to get an interface identifier that is
116*0f4c859eSApple OSS Distributions  * (1) random enough and (2) does not change across reboot.
117*0f4c859eSApple OSS Distributions  * We currently use SHA256(hostname) for it.
118*0f4c859eSApple OSS Distributions  *
119*0f4c859eSApple OSS Distributions  * in6 - upper 64bits are preserved
120*0f4c859eSApple OSS Distributions  */
121*0f4c859eSApple OSS Distributions static int
get_rand_iid(__unused struct ifnet * ifp,struct in6_addr * in6)122*0f4c859eSApple OSS Distributions get_rand_iid(
123*0f4c859eSApple OSS Distributions 	__unused struct ifnet *ifp,
124*0f4c859eSApple OSS Distributions 	struct in6_addr *in6)   /* upper 64bits are preserved */
125*0f4c859eSApple OSS Distributions {
126*0f4c859eSApple OSS Distributions 	SHA256_CTX ctxt;
127*0f4c859eSApple OSS Distributions 	u_int8_t digest[SHA256_DIGEST_LENGTH];
128*0f4c859eSApple OSS Distributions 	size_t hostnlen;
129*0f4c859eSApple OSS Distributions 
130*0f4c859eSApple OSS Distributions 	/* generate 8 bytes of pseudo-random value. */
131*0f4c859eSApple OSS Distributions 	bzero(&ctxt, sizeof(ctxt));
132*0f4c859eSApple OSS Distributions 	SHA256_Init(&ctxt);
133*0f4c859eSApple OSS Distributions 	lck_mtx_lock(&hostname_lock);
134*0f4c859eSApple OSS Distributions 	hostnlen = strlen(hostname);
135*0f4c859eSApple OSS Distributions 	SHA256_Update(&ctxt, hostname, hostnlen);
136*0f4c859eSApple OSS Distributions 	lck_mtx_unlock(&hostname_lock);
137*0f4c859eSApple OSS Distributions 	SHA256_Final(digest, &ctxt);
138*0f4c859eSApple OSS Distributions 
139*0f4c859eSApple OSS Distributions 	/* assumes sizeof (digest) > sizeof (iid) */
140*0f4c859eSApple OSS Distributions 	bcopy(digest, &in6->s6_addr[8], 8);
141*0f4c859eSApple OSS Distributions 
142*0f4c859eSApple OSS Distributions 	/* make sure to set "u" bit to local, and "g" bit to individual. */
143*0f4c859eSApple OSS Distributions 	in6->s6_addr[8] &= ~ND6_EUI64_GBIT;     /* g bit to "individual" */
144*0f4c859eSApple OSS Distributions 	in6->s6_addr[8] |= ND6_EUI64_UBIT;      /* u bit to "local" */
145*0f4c859eSApple OSS Distributions 
146*0f4c859eSApple OSS Distributions 	/* convert EUI64 into IPv6 interface identifier */
147*0f4c859eSApple OSS Distributions 	ND6_EUI64_TO_IFID(in6);
148*0f4c859eSApple OSS Distributions 
149*0f4c859eSApple OSS Distributions 	return 0;
150*0f4c859eSApple OSS Distributions }
151*0f4c859eSApple OSS Distributions 
152*0f4c859eSApple OSS Distributions static int
in6_generate_tmp_iid(u_int8_t * seed0,const u_int8_t * seed1,u_int8_t * ret)153*0f4c859eSApple OSS Distributions in6_generate_tmp_iid(
154*0f4c859eSApple OSS Distributions 	u_int8_t *seed0,
155*0f4c859eSApple OSS Distributions 	const u_int8_t *seed1,
156*0f4c859eSApple OSS Distributions 	u_int8_t *ret)
157*0f4c859eSApple OSS Distributions {
158*0f4c859eSApple OSS Distributions 	SHA256_CTX ctxt;
159*0f4c859eSApple OSS Distributions 	u_int8_t seed[16], nullbuf[8], digest[SHA256_DIGEST_LENGTH];
160*0f4c859eSApple OSS Distributions 	u_int32_t val32;
161*0f4c859eSApple OSS Distributions 	struct timeval tv;
162*0f4c859eSApple OSS Distributions 
163*0f4c859eSApple OSS Distributions 	/* If there's no history, start with a random seed. */
164*0f4c859eSApple OSS Distributions 	bzero(nullbuf, sizeof(nullbuf));
165*0f4c859eSApple OSS Distributions 	if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
166*0f4c859eSApple OSS Distributions 		int i;
167*0f4c859eSApple OSS Distributions 
168*0f4c859eSApple OSS Distributions 		for (i = 0; i < 2; i++) {
169*0f4c859eSApple OSS Distributions 			getmicrotime(&tv);
170*0f4c859eSApple OSS Distributions 			val32 = RandomULong() ^ tv.tv_usec;
171*0f4c859eSApple OSS Distributions 			bcopy(&val32, seed + sizeof(val32) * i,
172*0f4c859eSApple OSS Distributions 			    sizeof(val32));
173*0f4c859eSApple OSS Distributions 		}
174*0f4c859eSApple OSS Distributions 	} else {
175*0f4c859eSApple OSS Distributions 		bcopy(seed0, seed, 8);
176*0f4c859eSApple OSS Distributions 	}
177*0f4c859eSApple OSS Distributions 
178*0f4c859eSApple OSS Distributions 	/* copy the right-most 64-bits of the given address */
179*0f4c859eSApple OSS Distributions 	/* XXX assumption on the size of IFID */
180*0f4c859eSApple OSS Distributions 	bcopy(seed1, &seed[8], 8);
181*0f4c859eSApple OSS Distributions 
182*0f4c859eSApple OSS Distributions #if DEVELOPMENT || DEBUG
183*0f4c859eSApple OSS Distributions 	if ((0)) {              /* for debugging purposes only */
184*0f4c859eSApple OSS Distributions 		int i;
185*0f4c859eSApple OSS Distributions 
186*0f4c859eSApple OSS Distributions 		printf("%s: new randomized ID from: ", __func__);
187*0f4c859eSApple OSS Distributions 		for (i = 0; i < 16; i++) {
188*0f4c859eSApple OSS Distributions 			printf("%02x", seed[i]);
189*0f4c859eSApple OSS Distributions 		}
190*0f4c859eSApple OSS Distributions 		printf(" ");
191*0f4c859eSApple OSS Distributions 	}
192*0f4c859eSApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
193*0f4c859eSApple OSS Distributions 
194*0f4c859eSApple OSS Distributions 	/* generate 16 bytes of pseudo-random value. */
195*0f4c859eSApple OSS Distributions 	bzero(&ctxt, sizeof(ctxt));
196*0f4c859eSApple OSS Distributions 	SHA256_Init(&ctxt);
197*0f4c859eSApple OSS Distributions 	SHA256_Update(&ctxt, seed, sizeof(seed));
198*0f4c859eSApple OSS Distributions 	SHA256_Final(digest, &ctxt);
199*0f4c859eSApple OSS Distributions 
200*0f4c859eSApple OSS Distributions 	/*
201*0f4c859eSApple OSS Distributions 	 * RFC 4941 3.2.1. (3)
202*0f4c859eSApple OSS Distributions 	 * Take the left-most 64-bits of the SHA256 digest and set bit 6 (the
203*0f4c859eSApple OSS Distributions 	 * left-most bit is numbered 0) to zero.
204*0f4c859eSApple OSS Distributions 	 */
205*0f4c859eSApple OSS Distributions 	bcopy(digest, ret, 8);
206*0f4c859eSApple OSS Distributions 	ret[0] &= ~ND6_EUI64_UBIT;
207*0f4c859eSApple OSS Distributions 
208*0f4c859eSApple OSS Distributions 	/*
209*0f4c859eSApple OSS Distributions 	 * XXX: we'd like to ensure that the generated value is not zero
210*0f4c859eSApple OSS Distributions 	 * for simplicity.  If the caclculated digest happens to be zero,
211*0f4c859eSApple OSS Distributions 	 * use a random non-zero value as the last resort.
212*0f4c859eSApple OSS Distributions 	 */
213*0f4c859eSApple OSS Distributions 	if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
214*0f4c859eSApple OSS Distributions 		nd6log(info,
215*0f4c859eSApple OSS Distributions 		    "%s: computed SHA256 value is zero.\n", __func__);
216*0f4c859eSApple OSS Distributions 
217*0f4c859eSApple OSS Distributions 		getmicrotime(&tv);
218*0f4c859eSApple OSS Distributions 		val32 = random() ^ tv.tv_usec;
219*0f4c859eSApple OSS Distributions 		val32 = 1 + (val32 % (0xffffffff - 1));
220*0f4c859eSApple OSS Distributions 	}
221*0f4c859eSApple OSS Distributions 
222*0f4c859eSApple OSS Distributions 	/*
223*0f4c859eSApple OSS Distributions 	 * RFC 4941 3.2.1. (4)
224*0f4c859eSApple OSS Distributions 	 * Take the next 64-bits of the SHA256 digest and save them in
225*0f4c859eSApple OSS Distributions 	 * stable storage as the history value to be used in the next
226*0f4c859eSApple OSS Distributions 	 * iteration of the algorithm.
227*0f4c859eSApple OSS Distributions 	 */
228*0f4c859eSApple OSS Distributions 	bcopy(&digest[8], seed0, 8);
229*0f4c859eSApple OSS Distributions 
230*0f4c859eSApple OSS Distributions #if DEVELOPMENT || DEBUG
231*0f4c859eSApple OSS Distributions 	if ((0)) {              /* for debugging purposes only */
232*0f4c859eSApple OSS Distributions 		int i;
233*0f4c859eSApple OSS Distributions 
234*0f4c859eSApple OSS Distributions 		printf("to: ");
235*0f4c859eSApple OSS Distributions 		for (i = 0; i < 16; i++) {
236*0f4c859eSApple OSS Distributions 			printf("%02x", digest[i]);
237*0f4c859eSApple OSS Distributions 		}
238*0f4c859eSApple OSS Distributions 		printf("\n");
239*0f4c859eSApple OSS Distributions 	}
240*0f4c859eSApple OSS Distributions #endif
241*0f4c859eSApple OSS Distributions 
242*0f4c859eSApple OSS Distributions 	return 0;
243*0f4c859eSApple OSS Distributions }
244*0f4c859eSApple OSS Distributions 
245*0f4c859eSApple OSS Distributions /*
246*0f4c859eSApple OSS Distributions  * Get interface identifier for the specified interface using the method in
247*0f4c859eSApple OSS Distributions  * Appendix A of RFC 4291.
248*0f4c859eSApple OSS Distributions  *
249*0f4c859eSApple OSS Distributions  * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
250*0f4c859eSApple OSS Distributions  *
251*0f4c859eSApple OSS Distributions  * in6 - upper 64bits are preserved
252*0f4c859eSApple OSS Distributions  */
253*0f4c859eSApple OSS Distributions int
in6_iid_from_hw(struct ifnet * ifp,struct in6_addr * in6)254*0f4c859eSApple OSS Distributions in6_iid_from_hw(struct ifnet *ifp, struct in6_addr *in6)
255*0f4c859eSApple OSS Distributions {
256*0f4c859eSApple OSS Distributions 	struct ifaddr *ifa = NULL;
257*0f4c859eSApple OSS Distributions 	struct sockaddr_dl *sdl;
258*0f4c859eSApple OSS Distributions 	u_int8_t *addr;
259*0f4c859eSApple OSS Distributions 	size_t addrlen;
260*0f4c859eSApple OSS Distributions 	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
261*0f4c859eSApple OSS Distributions 	static u_int8_t allone[8] =
262*0f4c859eSApple OSS Distributions 	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
263*0f4c859eSApple OSS Distributions 	int err = -1;
264*0f4c859eSApple OSS Distributions 
265*0f4c859eSApple OSS Distributions 	/* Why doesn't this code use ifnet_addrs? */
266*0f4c859eSApple OSS Distributions 	ifnet_lock_shared(ifp);
267*0f4c859eSApple OSS Distributions 	ifa = ifp->if_lladdr;
268*0f4c859eSApple OSS Distributions 	sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
269*0f4c859eSApple OSS Distributions 	if (sdl->sdl_alen == 0) {
270*0f4c859eSApple OSS Distributions 		ifnet_lock_done(ifp);
271*0f4c859eSApple OSS Distributions 		return -1;
272*0f4c859eSApple OSS Distributions 	}
273*0f4c859eSApple OSS Distributions 	IFA_ADDREF(ifa);        /* for this routine */
274*0f4c859eSApple OSS Distributions 	ifnet_lock_done(ifp);
275*0f4c859eSApple OSS Distributions 
276*0f4c859eSApple OSS Distributions 	IFA_LOCK(ifa);
277*0f4c859eSApple OSS Distributions 	addr = (u_int8_t *) LLADDR(sdl);
278*0f4c859eSApple OSS Distributions 	addrlen = sdl->sdl_alen;
279*0f4c859eSApple OSS Distributions 
280*0f4c859eSApple OSS Distributions 	/* get EUI64 */
281*0f4c859eSApple OSS Distributions 	switch (ifp->if_type) {
282*0f4c859eSApple OSS Distributions 	case IFT_ETHER:
283*0f4c859eSApple OSS Distributions 	case IFT_FDDI:
284*0f4c859eSApple OSS Distributions 	case IFT_ISO88025:
285*0f4c859eSApple OSS Distributions 	case IFT_ATM:
286*0f4c859eSApple OSS Distributions 	case IFT_IEEE1394:
287*0f4c859eSApple OSS Distributions 	case IFT_L2VLAN:
288*0f4c859eSApple OSS Distributions 	case IFT_IEEE8023ADLAG:
289*0f4c859eSApple OSS Distributions #if IFT_IEEE80211
290*0f4c859eSApple OSS Distributions 	case IFT_IEEE80211:
291*0f4c859eSApple OSS Distributions #endif
292*0f4c859eSApple OSS Distributions 	case IFT_BRIDGE:
293*0f4c859eSApple OSS Distributions 		/* IEEE802/EUI64 cases - what others? */
294*0f4c859eSApple OSS Distributions 		/* IEEE1394 uses 16byte length address starting with EUI64 */
295*0f4c859eSApple OSS Distributions 		if (addrlen > 8) {
296*0f4c859eSApple OSS Distributions 			addrlen = 8;
297*0f4c859eSApple OSS Distributions 		}
298*0f4c859eSApple OSS Distributions 
299*0f4c859eSApple OSS Distributions 		/* look at IEEE802/EUI64 only */
300*0f4c859eSApple OSS Distributions 		if (addrlen != 8 && addrlen != 6) {
301*0f4c859eSApple OSS Distributions 			goto done;
302*0f4c859eSApple OSS Distributions 		}
303*0f4c859eSApple OSS Distributions 
304*0f4c859eSApple OSS Distributions 		/*
305*0f4c859eSApple OSS Distributions 		 * check for invalid MAC address - on bsdi, we see it a lot
306*0f4c859eSApple OSS Distributions 		 * since wildboar configures all-zero MAC on pccard before
307*0f4c859eSApple OSS Distributions 		 * card insertion.
308*0f4c859eSApple OSS Distributions 		 */
309*0f4c859eSApple OSS Distributions 		if (bcmp(addr, allzero, addrlen) == 0) {
310*0f4c859eSApple OSS Distributions 			goto done;
311*0f4c859eSApple OSS Distributions 		}
312*0f4c859eSApple OSS Distributions 		if (bcmp(addr, allone, addrlen) == 0) {
313*0f4c859eSApple OSS Distributions 			goto done;
314*0f4c859eSApple OSS Distributions 		}
315*0f4c859eSApple OSS Distributions 
316*0f4c859eSApple OSS Distributions 		/* make EUI64 address */
317*0f4c859eSApple OSS Distributions 		if (addrlen == 8) {
318*0f4c859eSApple OSS Distributions 			bcopy(addr, &in6->s6_addr[8], 8);
319*0f4c859eSApple OSS Distributions 		} else if (addrlen == 6) {
320*0f4c859eSApple OSS Distributions 			in6->s6_addr[8] = addr[0];
321*0f4c859eSApple OSS Distributions 			in6->s6_addr[9] = addr[1];
322*0f4c859eSApple OSS Distributions 			in6->s6_addr[10] = addr[2];
323*0f4c859eSApple OSS Distributions 			in6->s6_addr[11] = 0xff;
324*0f4c859eSApple OSS Distributions 			in6->s6_addr[12] = 0xfe;
325*0f4c859eSApple OSS Distributions 			in6->s6_addr[13] = addr[3];
326*0f4c859eSApple OSS Distributions 			in6->s6_addr[14] = addr[4];
327*0f4c859eSApple OSS Distributions 			in6->s6_addr[15] = addr[5];
328*0f4c859eSApple OSS Distributions 		}
329*0f4c859eSApple OSS Distributions 		break;
330*0f4c859eSApple OSS Distributions 
331*0f4c859eSApple OSS Distributions 	case IFT_ARCNET:
332*0f4c859eSApple OSS Distributions 		if (addrlen != 1) {
333*0f4c859eSApple OSS Distributions 			goto done;
334*0f4c859eSApple OSS Distributions 		}
335*0f4c859eSApple OSS Distributions 		if (!addr[0]) {
336*0f4c859eSApple OSS Distributions 			goto done;
337*0f4c859eSApple OSS Distributions 		}
338*0f4c859eSApple OSS Distributions 
339*0f4c859eSApple OSS Distributions 		bzero(&in6->s6_addr[8], 8);
340*0f4c859eSApple OSS Distributions 		in6->s6_addr[15] = addr[0];
341*0f4c859eSApple OSS Distributions 
342*0f4c859eSApple OSS Distributions 		/*
343*0f4c859eSApple OSS Distributions 		 * due to insufficient bitwidth, we mark it local.
344*0f4c859eSApple OSS Distributions 		 */
345*0f4c859eSApple OSS Distributions 		in6->s6_addr[8] &= ~ND6_EUI64_GBIT;     /* g to "individual" */
346*0f4c859eSApple OSS Distributions 		in6->s6_addr[8] |= ND6_EUI64_UBIT;      /* u to "local" */
347*0f4c859eSApple OSS Distributions 		break;
348*0f4c859eSApple OSS Distributions 
349*0f4c859eSApple OSS Distributions 	case IFT_GIF:
350*0f4c859eSApple OSS Distributions #if IFT_STF
351*0f4c859eSApple OSS Distributions 	case IFT_STF:
352*0f4c859eSApple OSS Distributions #endif
353*0f4c859eSApple OSS Distributions 		/*
354*0f4c859eSApple OSS Distributions 		 * RFC2893 says: "SHOULD use IPv4 address as IID source".
355*0f4c859eSApple OSS Distributions 		 * however, IPv4 address is not very suitable as unique
356*0f4c859eSApple OSS Distributions 		 * identifier source (can be renumbered).
357*0f4c859eSApple OSS Distributions 		 * we don't do this.
358*0f4c859eSApple OSS Distributions 		 */
359*0f4c859eSApple OSS Distributions 		goto done;
360*0f4c859eSApple OSS Distributions 
361*0f4c859eSApple OSS Distributions 	case IFT_CELLULAR:
362*0f4c859eSApple OSS Distributions 		goto done;
363*0f4c859eSApple OSS Distributions 
364*0f4c859eSApple OSS Distributions 	default:
365*0f4c859eSApple OSS Distributions 		goto done;
366*0f4c859eSApple OSS Distributions 	}
367*0f4c859eSApple OSS Distributions 
368*0f4c859eSApple OSS Distributions 	/* sanity check: g bit must not indicate "group" */
369*0f4c859eSApple OSS Distributions 	if (ND6_EUI64_GROUP(in6)) {
370*0f4c859eSApple OSS Distributions 		goto done;
371*0f4c859eSApple OSS Distributions 	}
372*0f4c859eSApple OSS Distributions 
373*0f4c859eSApple OSS Distributions 	/* convert EUI64 into IPv6 interface identifier */
374*0f4c859eSApple OSS Distributions 	ND6_EUI64_TO_IFID(in6);
375*0f4c859eSApple OSS Distributions 
376*0f4c859eSApple OSS Distributions 	/*
377*0f4c859eSApple OSS Distributions 	 * sanity check: iid must not be all zero, avoid conflict with
378*0f4c859eSApple OSS Distributions 	 * subnet router anycast
379*0f4c859eSApple OSS Distributions 	 */
380*0f4c859eSApple OSS Distributions 	if ((in6->s6_addr[8] & ~(ND6_EUI64_GBIT | ND6_EUI64_UBIT)) == 0x00 &&
381*0f4c859eSApple OSS Distributions 	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
382*0f4c859eSApple OSS Distributions 		goto done;
383*0f4c859eSApple OSS Distributions 	}
384*0f4c859eSApple OSS Distributions 
385*0f4c859eSApple OSS Distributions 	err = 0;        /* found */
386*0f4c859eSApple OSS Distributions 
387*0f4c859eSApple OSS Distributions done:
388*0f4c859eSApple OSS Distributions 	/* This must not be the last reference to the lladdr */
389*0f4c859eSApple OSS Distributions 	if (IFA_REMREF_LOCKED(ifa) == NULL) {
390*0f4c859eSApple OSS Distributions 		panic("%s: unexpected (missing) refcnt ifa=%p", __func__, ifa);
391*0f4c859eSApple OSS Distributions 		/* NOTREACHED */
392*0f4c859eSApple OSS Distributions 	}
393*0f4c859eSApple OSS Distributions 	IFA_UNLOCK(ifa);
394*0f4c859eSApple OSS Distributions 	return err;
395*0f4c859eSApple OSS Distributions }
396*0f4c859eSApple OSS Distributions 
397*0f4c859eSApple OSS Distributions /*
398*0f4c859eSApple OSS Distributions  * Get interface identifier for the specified interface using the method in
399*0f4c859eSApple OSS Distributions  * Appendix A of RFC 4291.  If it is not available on ifp0, borrow interface
400*0f4c859eSApple OSS Distributions  * identifier from other information sources.
401*0f4c859eSApple OSS Distributions  *
402*0f4c859eSApple OSS Distributions  * ifp     - primary EUI64 source
403*0f4c859eSApple OSS Distributions  * altifp  - secondary EUI64 source
404*0f4c859eSApple OSS Distributions  * in6     - IPv6 address to output IID
405*0f4c859eSApple OSS Distributions  */
406*0f4c859eSApple OSS Distributions static int
in6_select_iid_from_all_hw(struct ifnet * ifp0,struct ifnet * altifp,struct in6_addr * in6)407*0f4c859eSApple OSS Distributions in6_select_iid_from_all_hw(
408*0f4c859eSApple OSS Distributions 	struct ifnet *ifp0,
409*0f4c859eSApple OSS Distributions 	struct ifnet *altifp,   /* secondary EUI64 source */
410*0f4c859eSApple OSS Distributions 	struct in6_addr *in6)
411*0f4c859eSApple OSS Distributions {
412*0f4c859eSApple OSS Distributions 	struct ifnet *ifp;
413*0f4c859eSApple OSS Distributions 
414*0f4c859eSApple OSS Distributions 	/* first, try to get it from the interface itself */
415*0f4c859eSApple OSS Distributions 	if (in6_iid_from_hw(ifp0, in6) == 0) {
416*0f4c859eSApple OSS Distributions 		nd6log(debug, "%s: IID derived from HW interface.\n",
417*0f4c859eSApple OSS Distributions 		    if_name(ifp0));
418*0f4c859eSApple OSS Distributions 		goto success;
419*0f4c859eSApple OSS Distributions 	}
420*0f4c859eSApple OSS Distributions 
421*0f4c859eSApple OSS Distributions 	/* try secondary EUI64 source. this basically is for ATM PVC */
422*0f4c859eSApple OSS Distributions 	if (altifp && in6_iid_from_hw(altifp, in6) == 0) {
423*0f4c859eSApple OSS Distributions 		nd6log(debug, "%s: IID from alterate HW interface %s.\n",
424*0f4c859eSApple OSS Distributions 		    if_name(ifp0), if_name(altifp));
425*0f4c859eSApple OSS Distributions 		goto success;
426*0f4c859eSApple OSS Distributions 	}
427*0f4c859eSApple OSS Distributions 
428*0f4c859eSApple OSS Distributions 	/* next, try to get it from some other hardware interface */
429*0f4c859eSApple OSS Distributions 	ifnet_head_lock_shared();
430*0f4c859eSApple OSS Distributions 	TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
431*0f4c859eSApple OSS Distributions 		if (ifp == ifp0) {
432*0f4c859eSApple OSS Distributions 			continue;
433*0f4c859eSApple OSS Distributions 		}
434*0f4c859eSApple OSS Distributions 		if (in6_iid_from_hw(ifp, in6) != 0) {
435*0f4c859eSApple OSS Distributions 			continue;
436*0f4c859eSApple OSS Distributions 		}
437*0f4c859eSApple OSS Distributions 
438*0f4c859eSApple OSS Distributions 		/*
439*0f4c859eSApple OSS Distributions 		 * to borrow IID from other interface, IID needs to be
440*0f4c859eSApple OSS Distributions 		 * globally unique
441*0f4c859eSApple OSS Distributions 		 */
442*0f4c859eSApple OSS Distributions 		if (ND6_IFID_UNIVERSAL(in6)) {
443*0f4c859eSApple OSS Distributions 			nd6log(debug, "%s: borrowed IID from %s\n",
444*0f4c859eSApple OSS Distributions 			    if_name(ifp0), if_name(ifp));
445*0f4c859eSApple OSS Distributions 			ifnet_head_done();
446*0f4c859eSApple OSS Distributions 			goto success;
447*0f4c859eSApple OSS Distributions 		}
448*0f4c859eSApple OSS Distributions 	}
449*0f4c859eSApple OSS Distributions 	ifnet_head_done();
450*0f4c859eSApple OSS Distributions 
451*0f4c859eSApple OSS Distributions 	/* last resort: get from random number source */
452*0f4c859eSApple OSS Distributions 	if (get_rand_iid(ifp, in6) == 0) {
453*0f4c859eSApple OSS Distributions 		nd6log(debug, "%s: IID from PRNG.\n", if_name(ifp0));
454*0f4c859eSApple OSS Distributions 		goto success;
455*0f4c859eSApple OSS Distributions 	}
456*0f4c859eSApple OSS Distributions 
457*0f4c859eSApple OSS Distributions 	printf("%s: failed to get interface identifier\n", if_name(ifp0));
458*0f4c859eSApple OSS Distributions 	return -1;
459*0f4c859eSApple OSS Distributions 
460*0f4c859eSApple OSS Distributions success:
461*0f4c859eSApple OSS Distributions 	nd6log(info, "%s: IID: "
462*0f4c859eSApple OSS Distributions 	    "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
463*0f4c859eSApple OSS Distributions 	    if_name(ifp0),
464*0f4c859eSApple OSS Distributions 	    in6->s6_addr[8], in6->s6_addr[9],
465*0f4c859eSApple OSS Distributions 	    in6->s6_addr[10], in6->s6_addr[11],
466*0f4c859eSApple OSS Distributions 	    in6->s6_addr[12], in6->s6_addr[13],
467*0f4c859eSApple OSS Distributions 	    in6->s6_addr[14], in6->s6_addr[15]);
468*0f4c859eSApple OSS Distributions 	return 0;
469*0f4c859eSApple OSS Distributions }
470*0f4c859eSApple OSS Distributions 
471*0f4c859eSApple OSS Distributions static int
in6_ifattach_linklocal(struct ifnet * ifp,struct in6_aliasreq * ifra)472*0f4c859eSApple OSS Distributions in6_ifattach_linklocal(struct ifnet *ifp, struct in6_aliasreq *ifra)
473*0f4c859eSApple OSS Distributions {
474*0f4c859eSApple OSS Distributions 	struct in6_ifaddr *ia;
475*0f4c859eSApple OSS Distributions 	struct nd_prefix pr0, *pr;
476*0f4c859eSApple OSS Distributions 	int i, error;
477*0f4c859eSApple OSS Distributions 
478*0f4c859eSApple OSS Distributions 	VERIFY(ifra != NULL);
479*0f4c859eSApple OSS Distributions 
480*0f4c859eSApple OSS Distributions 	proto_plumb(PF_INET6, ifp);
481*0f4c859eSApple OSS Distributions 
482*0f4c859eSApple OSS Distributions 	error = in6_update_ifa(ifp, ifra, IN6_IFAUPDATE_DADDELAY, &ia);
483*0f4c859eSApple OSS Distributions 	if (error != 0) {
484*0f4c859eSApple OSS Distributions 		/*
485*0f4c859eSApple OSS Distributions 		 * XXX: When the interface does not support IPv6, this call
486*0f4c859eSApple OSS Distributions 		 * would fail in the SIOCSIFADDR ioctl.  I believe the
487*0f4c859eSApple OSS Distributions 		 * notification is rather confusing in this case, so just
488*0f4c859eSApple OSS Distributions 		 * suppress it.  ([email protected] 20010130)
489*0f4c859eSApple OSS Distributions 		 */
490*0f4c859eSApple OSS Distributions 		if (error != EAFNOSUPPORT) {
491*0f4c859eSApple OSS Distributions 			nd6log(info, "%s: failed to "
492*0f4c859eSApple OSS Distributions 			    "configure a link-local address on %s "
493*0f4c859eSApple OSS Distributions 			    "(errno=%d)\n",
494*0f4c859eSApple OSS Distributions 			    __func__, if_name(ifp), error);
495*0f4c859eSApple OSS Distributions 		}
496*0f4c859eSApple OSS Distributions 		return EADDRNOTAVAIL;
497*0f4c859eSApple OSS Distributions 	}
498*0f4c859eSApple OSS Distributions 	VERIFY(ia != NULL);
499*0f4c859eSApple OSS Distributions 
500*0f4c859eSApple OSS Distributions 	/*
501*0f4c859eSApple OSS Distributions 	 * Make the link-local prefix (fe80::%link/64) as on-link.
502*0f4c859eSApple OSS Distributions 	 * Since we'd like to manage prefixes separately from addresses,
503*0f4c859eSApple OSS Distributions 	 * we make an ND6 prefix structure for the link-local prefix,
504*0f4c859eSApple OSS Distributions 	 * and add it to the prefix list as a never-expire prefix.
505*0f4c859eSApple OSS Distributions 	 * XXX: this change might affect some existing code base...
506*0f4c859eSApple OSS Distributions 	 */
507*0f4c859eSApple OSS Distributions 	bzero(&pr0, sizeof(pr0));
508*0f4c859eSApple OSS Distributions 	lck_mtx_init(&pr0.ndpr_lock, &ifa_mtx_grp, &ifa_mtx_attr);
509*0f4c859eSApple OSS Distributions 	pr0.ndpr_ifp = ifp;
510*0f4c859eSApple OSS Distributions 	/* this should be 64 at this moment. */
511*0f4c859eSApple OSS Distributions 	pr0.ndpr_plen = (u_char)in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, NULL);
512*0f4c859eSApple OSS Distributions 	pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
513*0f4c859eSApple OSS Distributions 	pr0.ndpr_prefix = ifra->ifra_addr;
514*0f4c859eSApple OSS Distributions 	/* apply the mask for safety. (nd6_prelist_add will apply it again) */
515*0f4c859eSApple OSS Distributions 	for (i = 0; i < 4; i++) {
516*0f4c859eSApple OSS Distributions 		pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
517*0f4c859eSApple OSS Distributions 		    in6mask64.s6_addr32[i];
518*0f4c859eSApple OSS Distributions 	}
519*0f4c859eSApple OSS Distributions 	/*
520*0f4c859eSApple OSS Distributions 	 * Initialize parameters.  The link-local prefix must always be
521*0f4c859eSApple OSS Distributions 	 * on-link, and its lifetimes never expire.
522*0f4c859eSApple OSS Distributions 	 */
523*0f4c859eSApple OSS Distributions 	pr0.ndpr_raf_onlink = 1;
524*0f4c859eSApple OSS Distributions 	pr0.ndpr_raf_auto = 1;  /* probably meaningless */
525*0f4c859eSApple OSS Distributions 	pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
526*0f4c859eSApple OSS Distributions 	pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
527*0f4c859eSApple OSS Distributions 	pr0.ndpr_stateflags |= NDPRF_STATIC;
528*0f4c859eSApple OSS Distributions 	/*
529*0f4c859eSApple OSS Distributions 	 * Since there is no other link-local addresses, nd6_prefix_lookup()
530*0f4c859eSApple OSS Distributions 	 * probably returns NULL.  However, we cannot always expect the result.
531*0f4c859eSApple OSS Distributions 	 * For example, if we first remove the (only) existing link-local
532*0f4c859eSApple OSS Distributions 	 * address, and then reconfigure another one, the prefix is still
533*0f4c859eSApple OSS Distributions 	 * valid with referring to the old link-local address.
534*0f4c859eSApple OSS Distributions 	 */
535*0f4c859eSApple OSS Distributions 	if ((pr = nd6_prefix_lookup(&pr0, ND6_PREFIX_EXPIRY_UNSPEC)) == NULL) {
536*0f4c859eSApple OSS Distributions 		if ((error = nd6_prelist_add(&pr0, NULL, &pr, TRUE)) != 0) {
537*0f4c859eSApple OSS Distributions 			IFA_REMREF(&ia->ia_ifa);
538*0f4c859eSApple OSS Distributions 			lck_mtx_destroy(&pr0.ndpr_lock, &ifa_mtx_grp);
539*0f4c859eSApple OSS Distributions 			return error;
540*0f4c859eSApple OSS Distributions 		}
541*0f4c859eSApple OSS Distributions 	}
542*0f4c859eSApple OSS Distributions 
543*0f4c859eSApple OSS Distributions 	in6_post_msg(ifp, KEV_INET6_NEW_LL_ADDR, ia, NULL);
544*0f4c859eSApple OSS Distributions 	IFA_REMREF(&ia->ia_ifa);
545*0f4c859eSApple OSS Distributions 
546*0f4c859eSApple OSS Distributions 	/* Drop use count held above during lookup/add */
547*0f4c859eSApple OSS Distributions 	if (pr != NULL) {
548*0f4c859eSApple OSS Distributions 		NDPR_REMREF(pr);
549*0f4c859eSApple OSS Distributions 	}
550*0f4c859eSApple OSS Distributions 
551*0f4c859eSApple OSS Distributions 	lck_mtx_destroy(&pr0.ndpr_lock, &ifa_mtx_grp);
552*0f4c859eSApple OSS Distributions 	return 0;
553*0f4c859eSApple OSS Distributions }
554*0f4c859eSApple OSS Distributions 
555*0f4c859eSApple OSS Distributions static int
in6_ifattach_loopback(struct ifnet * ifp)556*0f4c859eSApple OSS Distributions in6_ifattach_loopback(
557*0f4c859eSApple OSS Distributions 	struct ifnet *ifp)      /* must be IFT_LOOP */
558*0f4c859eSApple OSS Distributions {
559*0f4c859eSApple OSS Distributions 	struct in6_aliasreq ifra;
560*0f4c859eSApple OSS Distributions 	struct in6_ifaddr *ia;
561*0f4c859eSApple OSS Distributions 	int error;
562*0f4c859eSApple OSS Distributions 
563*0f4c859eSApple OSS Distributions 	bzero(&ifra, sizeof(ifra));
564*0f4c859eSApple OSS Distributions 
565*0f4c859eSApple OSS Distributions 	/*
566*0f4c859eSApple OSS Distributions 	 * in6_update_ifa() does not use ifra_name, but we accurately set it
567*0f4c859eSApple OSS Distributions 	 * for safety.
568*0f4c859eSApple OSS Distributions 	 */
569*0f4c859eSApple OSS Distributions 	strlcpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
570*0f4c859eSApple OSS Distributions 
571*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
572*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_family = AF_INET6;
573*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_addr = in6mask128;
574*0f4c859eSApple OSS Distributions 
575*0f4c859eSApple OSS Distributions 	/*
576*0f4c859eSApple OSS Distributions 	 * Always initialize ia_dstaddr (= broadcast address) to loopback
577*0f4c859eSApple OSS Distributions 	 * address.  Follows IPv4 practice - see in_ifinit().
578*0f4c859eSApple OSS Distributions 	 */
579*0f4c859eSApple OSS Distributions 	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
580*0f4c859eSApple OSS Distributions 	ifra.ifra_dstaddr.sin6_family = AF_INET6;
581*0f4c859eSApple OSS Distributions 	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
582*0f4c859eSApple OSS Distributions 
583*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
584*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_family = AF_INET6;
585*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_addr = in6addr_loopback;
586*0f4c859eSApple OSS Distributions 
587*0f4c859eSApple OSS Distributions 	/* the loopback  address should NEVER expire. */
588*0f4c859eSApple OSS Distributions 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
589*0f4c859eSApple OSS Distributions 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
590*0f4c859eSApple OSS Distributions 
591*0f4c859eSApple OSS Distributions 	/* we don't need to perform DAD on loopback interfaces. */
592*0f4c859eSApple OSS Distributions 	ifra.ifra_flags |= IN6_IFF_NODAD;
593*0f4c859eSApple OSS Distributions 
594*0f4c859eSApple OSS Distributions 	/* add the new interface address */
595*0f4c859eSApple OSS Distributions 	error = in6_update_ifa(ifp, &ifra, 0, &ia);
596*0f4c859eSApple OSS Distributions 	if (error != 0) {
597*0f4c859eSApple OSS Distributions 		nd6log(error,
598*0f4c859eSApple OSS Distributions 		    "%s: failed to configure loopback address %s (error=%d)\n",
599*0f4c859eSApple OSS Distributions 		    __func__, if_name(ifp), error);
600*0f4c859eSApple OSS Distributions 		VERIFY(ia == NULL);
601*0f4c859eSApple OSS Distributions 		return EADDRNOTAVAIL;
602*0f4c859eSApple OSS Distributions 	}
603*0f4c859eSApple OSS Distributions 
604*0f4c859eSApple OSS Distributions 	VERIFY(ia != NULL);
605*0f4c859eSApple OSS Distributions 	IFA_REMREF(&ia->ia_ifa);
606*0f4c859eSApple OSS Distributions 	return 0;
607*0f4c859eSApple OSS Distributions }
608*0f4c859eSApple OSS Distributions 
609*0f4c859eSApple OSS Distributions /*
610*0f4c859eSApple OSS Distributions  * compute NI group address, based on the current hostname setting.
611*0f4c859eSApple OSS Distributions  * see RFC 4620.
612*0f4c859eSApple OSS Distributions  *
613*0f4c859eSApple OSS Distributions  * when ifp == NULL, the caller is responsible for filling scopeid.
614*0f4c859eSApple OSS Distributions  */
615*0f4c859eSApple OSS Distributions int
in6_nigroup(struct ifnet * ifp,const char * name,size_t namelen,struct in6_addr * in6,uint32_t * ifscopep)616*0f4c859eSApple OSS Distributions in6_nigroup(
617*0f4c859eSApple OSS Distributions 	struct ifnet *ifp,
618*0f4c859eSApple OSS Distributions 	const char *name,
619*0f4c859eSApple OSS Distributions 	size_t namelen,
620*0f4c859eSApple OSS Distributions 	struct in6_addr *in6,
621*0f4c859eSApple OSS Distributions 	uint32_t *ifscopep)
622*0f4c859eSApple OSS Distributions {
623*0f4c859eSApple OSS Distributions 	const char *p;
624*0f4c859eSApple OSS Distributions 	u_char *q;
625*0f4c859eSApple OSS Distributions 	SHA256_CTX ctxt;
626*0f4c859eSApple OSS Distributions 	u_int8_t digest[SHA256_DIGEST_LENGTH];
627*0f4c859eSApple OSS Distributions 	size_t l;
628*0f4c859eSApple OSS Distributions 	char n[64];     /* a single label must not exceed 63 chars */
629*0f4c859eSApple OSS Distributions 
630*0f4c859eSApple OSS Distributions 	if (!namelen || !name) {
631*0f4c859eSApple OSS Distributions 		return -1;
632*0f4c859eSApple OSS Distributions 	}
633*0f4c859eSApple OSS Distributions 
634*0f4c859eSApple OSS Distributions 	p = name;
635*0f4c859eSApple OSS Distributions 	while (p && *p && *p != '.' && p - name < namelen) {
636*0f4c859eSApple OSS Distributions 		p++;
637*0f4c859eSApple OSS Distributions 	}
638*0f4c859eSApple OSS Distributions 	if (p - name > sizeof(n) - 1) {
639*0f4c859eSApple OSS Distributions 		return -1;    /* label too long */
640*0f4c859eSApple OSS Distributions 	}
641*0f4c859eSApple OSS Distributions 	l = p - name;
642*0f4c859eSApple OSS Distributions 	strlcpy(n, name, l);
643*0f4c859eSApple OSS Distributions 	n[(int)l] = '\0';
644*0f4c859eSApple OSS Distributions 	for (q = (u_char *) n; *q; q++) {
645*0f4c859eSApple OSS Distributions 		if ('A' <= *q && *q <= 'Z') {
646*0f4c859eSApple OSS Distributions 			*q = *q - 'A' + 'a';
647*0f4c859eSApple OSS Distributions 		}
648*0f4c859eSApple OSS Distributions 	}
649*0f4c859eSApple OSS Distributions 
650*0f4c859eSApple OSS Distributions 	/* generate 16 bytes of pseudo-random value. */
651*0f4c859eSApple OSS Distributions 	bzero(&ctxt, sizeof(ctxt));
652*0f4c859eSApple OSS Distributions 	SHA256_Init(&ctxt);
653*0f4c859eSApple OSS Distributions 	SHA256_Update(&ctxt, &l, sizeof(l));
654*0f4c859eSApple OSS Distributions 	SHA256_Update(&ctxt, n, l);
655*0f4c859eSApple OSS Distributions 	SHA256_Final(digest, &ctxt);
656*0f4c859eSApple OSS Distributions 
657*0f4c859eSApple OSS Distributions 	bzero(in6, sizeof(*in6));
658*0f4c859eSApple OSS Distributions 	in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
659*0f4c859eSApple OSS Distributions 	in6->s6_addr8[11] = 2;
660*0f4c859eSApple OSS Distributions 	in6->s6_addr8[12] = 0xff;
661*0f4c859eSApple OSS Distributions 	/* copy first 3 bytes of prefix into address */
662*0f4c859eSApple OSS Distributions 	bcopy(digest, &in6->s6_addr8[13], 3);
663*0f4c859eSApple OSS Distributions 	if (in6_setscope(in6, ifp, ifscopep)) {
664*0f4c859eSApple OSS Distributions 		return -1; /* XXX: should not fail */
665*0f4c859eSApple OSS Distributions 	}
666*0f4c859eSApple OSS Distributions 	return 0;
667*0f4c859eSApple OSS Distributions }
668*0f4c859eSApple OSS Distributions 
669*0f4c859eSApple OSS Distributions int
in6_domifattach(struct ifnet * ifp)670*0f4c859eSApple OSS Distributions in6_domifattach(struct ifnet *ifp)
671*0f4c859eSApple OSS Distributions {
672*0f4c859eSApple OSS Distributions 	int error;
673*0f4c859eSApple OSS Distributions 
674*0f4c859eSApple OSS Distributions 	VERIFY(ifp != NULL);
675*0f4c859eSApple OSS Distributions 
676*0f4c859eSApple OSS Distributions 	error = proto_plumb(PF_INET6, ifp);
677*0f4c859eSApple OSS Distributions 	if (error != 0) {
678*0f4c859eSApple OSS Distributions 		if (error != EEXIST) {
679*0f4c859eSApple OSS Distributions 			log(LOG_ERR, "%s: proto_plumb returned %d if=%s\n",
680*0f4c859eSApple OSS Distributions 			    __func__, error, if_name(ifp));
681*0f4c859eSApple OSS Distributions 		}
682*0f4c859eSApple OSS Distributions 	} else {
683*0f4c859eSApple OSS Distributions 		error = in6_ifattach_prelim(ifp);
684*0f4c859eSApple OSS Distributions 		if (error != 0) {
685*0f4c859eSApple OSS Distributions 			int errorx;
686*0f4c859eSApple OSS Distributions 
687*0f4c859eSApple OSS Distributions 			log(LOG_ERR,
688*0f4c859eSApple OSS Distributions 			    "%s: in6_ifattach_prelim returned %d if=%s%d\n",
689*0f4c859eSApple OSS Distributions 			    __func__, error, ifp->if_name, ifp->if_unit);
690*0f4c859eSApple OSS Distributions 
691*0f4c859eSApple OSS Distributions 			errorx = proto_unplumb(PF_INET6, ifp);
692*0f4c859eSApple OSS Distributions 			if (errorx != 0) { /* XXX should not fail */
693*0f4c859eSApple OSS Distributions 				log(LOG_ERR,
694*0f4c859eSApple OSS Distributions 				    "%s: proto_unplumb returned %d if=%s%d\n",
695*0f4c859eSApple OSS Distributions 				    __func__, errorx, ifp->if_name,
696*0f4c859eSApple OSS Distributions 				    ifp->if_unit);
697*0f4c859eSApple OSS Distributions 			}
698*0f4c859eSApple OSS Distributions 		}
699*0f4c859eSApple OSS Distributions 	}
700*0f4c859eSApple OSS Distributions 
701*0f4c859eSApple OSS Distributions 	return error;
702*0f4c859eSApple OSS Distributions }
703*0f4c859eSApple OSS Distributions 
704*0f4c859eSApple OSS Distributions int
in6_ifattach_prelim(struct ifnet * ifp)705*0f4c859eSApple OSS Distributions in6_ifattach_prelim(struct ifnet *ifp)
706*0f4c859eSApple OSS Distributions {
707*0f4c859eSApple OSS Distributions 	int error = 0;
708*0f4c859eSApple OSS Distributions 	struct in6_ifaddr *ia6 = NULL;
709*0f4c859eSApple OSS Distributions 
710*0f4c859eSApple OSS Distributions 	VERIFY(ifp != NULL);
711*0f4c859eSApple OSS Distributions 
712*0f4c859eSApple OSS Distributions 	/* quirks based on interface type */
713*0f4c859eSApple OSS Distributions 	switch (ifp->if_type) {
714*0f4c859eSApple OSS Distributions #if IFT_STF
715*0f4c859eSApple OSS Distributions 	case IFT_STF:
716*0f4c859eSApple OSS Distributions 		/*
717*0f4c859eSApple OSS Distributions 		 * 6to4 interface is a very special kind of beast.
718*0f4c859eSApple OSS Distributions 		 * no multicast, no linklocal.  RFC2529 specifies how to make
719*0f4c859eSApple OSS Distributions 		 * linklocals for 6to4 interface, but there's no use and
720*0f4c859eSApple OSS Distributions 		 * it is rather harmful to have one.
721*0f4c859eSApple OSS Distributions 		 */
722*0f4c859eSApple OSS Distributions 		goto skipmcast;
723*0f4c859eSApple OSS Distributions #endif
724*0f4c859eSApple OSS Distributions 	default:
725*0f4c859eSApple OSS Distributions 		break;
726*0f4c859eSApple OSS Distributions 	}
727*0f4c859eSApple OSS Distributions 
728*0f4c859eSApple OSS Distributions 	/*
729*0f4c859eSApple OSS Distributions 	 * IPv6 requires multicast capability at the interface.
730*0f4c859eSApple OSS Distributions 	 *   (previously, this was a silent error.)
731*0f4c859eSApple OSS Distributions 	 */
732*0f4c859eSApple OSS Distributions 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
733*0f4c859eSApple OSS Distributions 		nd6log0(info, "in6_ifattach: %s is not multicast capable, IPv6 not enabled\n",
734*0f4c859eSApple OSS Distributions 		    if_name(ifp));
735*0f4c859eSApple OSS Distributions 		return EINVAL;
736*0f4c859eSApple OSS Distributions 	}
737*0f4c859eSApple OSS Distributions 
738*0f4c859eSApple OSS Distributions #if IFT_STF
739*0f4c859eSApple OSS Distributions skipmcast:
740*0f4c859eSApple OSS Distributions #endif
741*0f4c859eSApple OSS Distributions 
742*0f4c859eSApple OSS Distributions 	if (ifp->if_inet6data == NULL) {
743*0f4c859eSApple OSS Distributions 		ifp->if_inet6data = zalloc_permanent_type(struct in6_ifextra);
744*0f4c859eSApple OSS Distributions 	} else {
745*0f4c859eSApple OSS Distributions 		/*
746*0f4c859eSApple OSS Distributions 		 * Since the structure is never freed, we need to zero out
747*0f4c859eSApple OSS Distributions 		 * some of its members. We avoid zeroing out the scope6
748*0f4c859eSApple OSS Distributions 		 * structure on purpose because other threads might be
749*0f4c859eSApple OSS Distributions 		 * using its contents.
750*0f4c859eSApple OSS Distributions 		 */
751*0f4c859eSApple OSS Distributions 		bzero(&IN6_IFEXTRA(ifp)->icmp6_ifstat,
752*0f4c859eSApple OSS Distributions 		    sizeof(IN6_IFEXTRA(ifp)->icmp6_ifstat));
753*0f4c859eSApple OSS Distributions 		bzero(&IN6_IFEXTRA(ifp)->in6_ifstat,
754*0f4c859eSApple OSS Distributions 		    sizeof(IN6_IFEXTRA(ifp)->in6_ifstat));
755*0f4c859eSApple OSS Distributions 		/*
756*0f4c859eSApple OSS Distributions 		 * XXX When recycling, nd_ifinfo gets initialized, other
757*0f4c859eSApple OSS Distributions 		 * than the lock, inside nd6_ifattach
758*0f4c859eSApple OSS Distributions 		 */
759*0f4c859eSApple OSS Distributions 	}
760*0f4c859eSApple OSS Distributions 
761*0f4c859eSApple OSS Distributions 	/*
762*0f4c859eSApple OSS Distributions 	 * XXX Only initialize IPv6 configuration for the interface
763*0f4c859eSApple OSS Distributions 	 * if interface has not yet been configured with
764*0f4c859eSApple OSS Distributions 	 * link local IPv6 address.
765*0f4c859eSApple OSS Distributions 	 * Could possibly be optimized with an interface flag if need
766*0f4c859eSApple OSS Distributions 	 * be. For now using in6ifa_ifpforlinklocal.
767*0f4c859eSApple OSS Distributions 	 */
768*0f4c859eSApple OSS Distributions 	ia6 = in6ifa_ifpforlinklocal(ifp, 0);
769*0f4c859eSApple OSS Distributions 	if (ia6 == NULL) {
770*0f4c859eSApple OSS Distributions 		IN6_IFEXTRA(ifp)->netsig_len = 0;
771*0f4c859eSApple OSS Distributions 		bzero(&IN6_IFEXTRA(ifp)->netsig,
772*0f4c859eSApple OSS Distributions 		    sizeof(IN6_IFEXTRA(ifp)->netsig));
773*0f4c859eSApple OSS Distributions 		bzero(IN6_IFEXTRA(ifp)->nat64_prefixes,
774*0f4c859eSApple OSS Distributions 		    sizeof(IN6_IFEXTRA(ifp)->nat64_prefixes));
775*0f4c859eSApple OSS Distributions 		/* initialize NDP variables */
776*0f4c859eSApple OSS Distributions 		nd6_ifattach(ifp);
777*0f4c859eSApple OSS Distributions 	} else {
778*0f4c859eSApple OSS Distributions 		VERIFY(ND_IFINFO(ifp)->initialized);
779*0f4c859eSApple OSS Distributions 		IFA_REMREF(&ia6->ia_ifa);
780*0f4c859eSApple OSS Distributions 		ia6 = NULL;
781*0f4c859eSApple OSS Distributions 	}
782*0f4c859eSApple OSS Distributions 	scope6_ifattach(ifp);
783*0f4c859eSApple OSS Distributions 
784*0f4c859eSApple OSS Distributions 	/* initialize loopback interface address */
785*0f4c859eSApple OSS Distributions 	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
786*0f4c859eSApple OSS Distributions 		error = in6_ifattach_loopback(ifp);
787*0f4c859eSApple OSS Distributions 		if (error != 0) {
788*0f4c859eSApple OSS Distributions 			log(LOG_ERR, "%s: in6_ifattach_loopback returned %d\n",
789*0f4c859eSApple OSS Distributions 			    __func__, error);
790*0f4c859eSApple OSS Distributions 			return error;
791*0f4c859eSApple OSS Distributions 		}
792*0f4c859eSApple OSS Distributions 	}
793*0f4c859eSApple OSS Distributions 
794*0f4c859eSApple OSS Distributions 	/* update dynamically. */
795*0f4c859eSApple OSS Distributions 	if (in6_maxmtu < ifp->if_mtu) {
796*0f4c859eSApple OSS Distributions 		in6_maxmtu = ifp->if_mtu;
797*0f4c859eSApple OSS Distributions 	}
798*0f4c859eSApple OSS Distributions 
799*0f4c859eSApple OSS Distributions 	VERIFY(error == 0);
800*0f4c859eSApple OSS Distributions 	return 0;
801*0f4c859eSApple OSS Distributions }
802*0f4c859eSApple OSS Distributions 
803*0f4c859eSApple OSS Distributions /*
804*0f4c859eSApple OSS Distributions  * This routine is only meant to configure IPv6 Link Local
805*0f4c859eSApple OSS Distributions  * addresses.
806*0f4c859eSApple OSS Distributions  */
807*0f4c859eSApple OSS Distributions int
in6_ifattach_aliasreq(struct ifnet * ifp,struct ifnet * altifp,struct in6_aliasreq * ifra0)808*0f4c859eSApple OSS Distributions in6_ifattach_aliasreq(struct ifnet *ifp, struct ifnet *altifp,
809*0f4c859eSApple OSS Distributions     struct in6_aliasreq *ifra0)
810*0f4c859eSApple OSS Distributions {
811*0f4c859eSApple OSS Distributions 	int error;
812*0f4c859eSApple OSS Distributions 	struct in6_ifaddr *ia6;
813*0f4c859eSApple OSS Distributions 	struct in6_aliasreq ifra;
814*0f4c859eSApple OSS Distributions 
815*0f4c859eSApple OSS Distributions 	error = in6_ifattach_prelim(ifp);
816*0f4c859eSApple OSS Distributions 	if (error != 0) {
817*0f4c859eSApple OSS Distributions 		return error;
818*0f4c859eSApple OSS Distributions 	}
819*0f4c859eSApple OSS Distributions 
820*0f4c859eSApple OSS Distributions 	if (!ip6_auto_linklocal) {
821*0f4c859eSApple OSS Distributions 		return 0;
822*0f4c859eSApple OSS Distributions 	}
823*0f4c859eSApple OSS Distributions 
824*0f4c859eSApple OSS Distributions 	/*
825*0f4c859eSApple OSS Distributions 	 * Assign a link-local address, only if there isn't one here already.
826*0f4c859eSApple OSS Distributions 	 * XXX If we ever allow more than one LLA on the interface
827*0f4c859eSApple OSS Distributions 	 * make sure that the corresponding prefix on the prefixlist
828*0f4c859eSApple OSS Distributions 	 * is reference counted and the address's prefix pointer
829*0f4c859eSApple OSS Distributions 	 * points to the prefix.
830*0f4c859eSApple OSS Distributions 	 */
831*0f4c859eSApple OSS Distributions 	ia6 = in6ifa_ifpforlinklocal(ifp, 0);
832*0f4c859eSApple OSS Distributions 	if (ia6 != NULL) {
833*0f4c859eSApple OSS Distributions 		IFA_REMREF(&ia6->ia_ifa);
834*0f4c859eSApple OSS Distributions 		return 0;
835*0f4c859eSApple OSS Distributions 	}
836*0f4c859eSApple OSS Distributions 
837*0f4c859eSApple OSS Distributions 	bzero(&ifra, sizeof(ifra));
838*0f4c859eSApple OSS Distributions 
839*0f4c859eSApple OSS Distributions 	/*
840*0f4c859eSApple OSS Distributions 	 * in6_update_ifa() does not use ifra_name, but we accurately set it
841*0f4c859eSApple OSS Distributions 	 * for safety.
842*0f4c859eSApple OSS Distributions 	 */
843*0f4c859eSApple OSS Distributions 	strlcpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
844*0f4c859eSApple OSS Distributions 
845*0f4c859eSApple OSS Distributions 	/* Initialize the IPv6 interface address in our in6_aliasreq block */
846*0f4c859eSApple OSS Distributions 	if (ifra0 != NULL) {
847*0f4c859eSApple OSS Distributions 		/* interface provided both addresses for us */
848*0f4c859eSApple OSS Distributions 		struct sockaddr_in6 *sin6 = &ifra.ifra_addr;
849*0f4c859eSApple OSS Distributions 		struct in6_addr *in6 = &sin6->sin6_addr;
850*0f4c859eSApple OSS Distributions 		boolean_t ok = TRUE;
851*0f4c859eSApple OSS Distributions 
852*0f4c859eSApple OSS Distributions 		bcopy(&ifra0->ifra_addr, sin6, sizeof(struct sockaddr_in6));
853*0f4c859eSApple OSS Distributions 
854*0f4c859eSApple OSS Distributions 		if (sin6->sin6_family != AF_INET6 || sin6->sin6_port != 0) {
855*0f4c859eSApple OSS Distributions 			ok = FALSE;
856*0f4c859eSApple OSS Distributions 		}
857*0f4c859eSApple OSS Distributions 		if (ok && (in6->s6_addr16[0] != htons(0xfe80))) {
858*0f4c859eSApple OSS Distributions 			ok = FALSE;
859*0f4c859eSApple OSS Distributions 		}
860*0f4c859eSApple OSS Distributions 
861*0f4c859eSApple OSS Distributions 		if (ok) {
862*0f4c859eSApple OSS Distributions 			if (sin6->sin6_scope_id == 0 && in6->s6_addr16[1] == 0) {
863*0f4c859eSApple OSS Distributions 				if (in6_embedded_scope) {
864*0f4c859eSApple OSS Distributions 					in6->s6_addr16[1] = htons(ifp->if_index);
865*0f4c859eSApple OSS Distributions 				} else {
866*0f4c859eSApple OSS Distributions 					sin6->sin6_scope_id = ifp->if_index;
867*0f4c859eSApple OSS Distributions 				}
868*0f4c859eSApple OSS Distributions 			} else if (sin6->sin6_scope_id != 0 &&
869*0f4c859eSApple OSS Distributions 			    sin6->sin6_scope_id != ifp->if_index) {
870*0f4c859eSApple OSS Distributions 				ok = FALSE;
871*0f4c859eSApple OSS Distributions 			} else if (in6_embedded_scope && in6->s6_addr16[1] != 0 &&
872*0f4c859eSApple OSS Distributions 			    ntohs(in6->s6_addr16[1]) != ifp->if_index) {
873*0f4c859eSApple OSS Distributions 				ok = FALSE;
874*0f4c859eSApple OSS Distributions 			}
875*0f4c859eSApple OSS Distributions 		}
876*0f4c859eSApple OSS Distributions 		if (ok && (in6->s6_addr32[1] != 0)) {
877*0f4c859eSApple OSS Distributions 			ok = FALSE;
878*0f4c859eSApple OSS Distributions 		}
879*0f4c859eSApple OSS Distributions 		if (!ok) {
880*0f4c859eSApple OSS Distributions 			return EINVAL;
881*0f4c859eSApple OSS Distributions 		}
882*0f4c859eSApple OSS Distributions 	} else {
883*0f4c859eSApple OSS Distributions 		ifra.ifra_addr.sin6_family = AF_INET6;
884*0f4c859eSApple OSS Distributions 		ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
885*0f4c859eSApple OSS Distributions 		ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
886*0f4c859eSApple OSS Distributions 		if (in6_embedded_scope) {
887*0f4c859eSApple OSS Distributions 			ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
888*0f4c859eSApple OSS Distributions 		} else {
889*0f4c859eSApple OSS Distributions 			ifra.ifra_addr.sin6_addr.s6_addr16[1] = 0;
890*0f4c859eSApple OSS Distributions 			ifra.ifra_addr.sin6_scope_id = ifp->if_index;
891*0f4c859eSApple OSS Distributions 		}
892*0f4c859eSApple OSS Distributions 		ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
893*0f4c859eSApple OSS Distributions 		if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
894*0f4c859eSApple OSS Distributions 			ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
895*0f4c859eSApple OSS Distributions 			ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
896*0f4c859eSApple OSS Distributions 			if (!in6_embedded_scope) {
897*0f4c859eSApple OSS Distributions 				ifra.ifra_addr.sin6_scope_id = ifp->if_index;
898*0f4c859eSApple OSS Distributions 			}
899*0f4c859eSApple OSS Distributions 		} else {
900*0f4c859eSApple OSS Distributions 			if (in6_select_iid_from_all_hw(ifp, altifp,
901*0f4c859eSApple OSS Distributions 			    &ifra.ifra_addr.sin6_addr) != 0) {
902*0f4c859eSApple OSS Distributions 				nd6log(error, "%s: no IID available\n",
903*0f4c859eSApple OSS Distributions 				    if_name(ifp));
904*0f4c859eSApple OSS Distributions 				return EADDRNOTAVAIL;
905*0f4c859eSApple OSS Distributions 			}
906*0f4c859eSApple OSS Distributions 		}
907*0f4c859eSApple OSS Distributions 	}
908*0f4c859eSApple OSS Distributions 
909*0f4c859eSApple OSS Distributions 	if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, IN6_NULL_IF_EMBEDDED_SCOPE(&ifra.ifra_addr.sin6_scope_id))) {
910*0f4c859eSApple OSS Distributions 		return EADDRNOTAVAIL;
911*0f4c859eSApple OSS Distributions 	}
912*0f4c859eSApple OSS Distributions 
913*0f4c859eSApple OSS Distributions 	/* Set the prefix mask */
914*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
915*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_family = AF_INET6;
916*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_addr = in6mask64;
917*0f4c859eSApple OSS Distributions 
918*0f4c859eSApple OSS Distributions 	/* link-local addresses should NEVER expire. */
919*0f4c859eSApple OSS Distributions 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
920*0f4c859eSApple OSS Distributions 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
921*0f4c859eSApple OSS Distributions 
922*0f4c859eSApple OSS Distributions 	/* Attach the link-local address */
923*0f4c859eSApple OSS Distributions 	if (in6_ifattach_linklocal(ifp, &ifra) != 0) {
924*0f4c859eSApple OSS Distributions 		nd6log(info,
925*0f4c859eSApple OSS Distributions 		    "%s: %s could not attach link-local address.\n",
926*0f4c859eSApple OSS Distributions 		    __func__, if_name(ifp));
927*0f4c859eSApple OSS Distributions 		/* NB: not an error */
928*0f4c859eSApple OSS Distributions 	}
929*0f4c859eSApple OSS Distributions 
930*0f4c859eSApple OSS Distributions 	return 0;
931*0f4c859eSApple OSS Distributions }
932*0f4c859eSApple OSS Distributions 
933*0f4c859eSApple OSS Distributions int
in6_ifattach_llcgareq(struct ifnet * ifp,struct in6_cgareq * llcgasr)934*0f4c859eSApple OSS Distributions in6_ifattach_llcgareq(struct ifnet *ifp, struct in6_cgareq *llcgasr)
935*0f4c859eSApple OSS Distributions {
936*0f4c859eSApple OSS Distributions 	struct in6_aliasreq ifra;
937*0f4c859eSApple OSS Distributions 	struct in6_ifaddr *ia6 = NULL;
938*0f4c859eSApple OSS Distributions 	struct nd_ifinfo *ndi = NULL;
939*0f4c859eSApple OSS Distributions 	int error;
940*0f4c859eSApple OSS Distributions 
941*0f4c859eSApple OSS Distributions 	VERIFY(llcgasr != NULL);
942*0f4c859eSApple OSS Distributions 
943*0f4c859eSApple OSS Distributions 	error = in6_ifattach_prelim(ifp);
944*0f4c859eSApple OSS Distributions 	if (error != 0) {
945*0f4c859eSApple OSS Distributions 		return error;
946*0f4c859eSApple OSS Distributions 	}
947*0f4c859eSApple OSS Distributions 
948*0f4c859eSApple OSS Distributions 	if (!ip6_auto_linklocal) {
949*0f4c859eSApple OSS Distributions 		return 0;
950*0f4c859eSApple OSS Distributions 	}
951*0f4c859eSApple OSS Distributions 
952*0f4c859eSApple OSS Distributions 	if (nd6_send_opstate == ND6_SEND_OPMODE_DISABLED) {
953*0f4c859eSApple OSS Distributions 		return ENXIO;
954*0f4c859eSApple OSS Distributions 	}
955*0f4c859eSApple OSS Distributions 
956*0f4c859eSApple OSS Distributions 	ndi = ND_IFINFO(ifp);
957*0f4c859eSApple OSS Distributions 	VERIFY(ndi != NULL && ndi->initialized);
958*0f4c859eSApple OSS Distributions 	if ((ndi->flags & ND6_IFF_INSECURE) != 0) {
959*0f4c859eSApple OSS Distributions 		return ENXIO;
960*0f4c859eSApple OSS Distributions 	}
961*0f4c859eSApple OSS Distributions 
962*0f4c859eSApple OSS Distributions 	/*
963*0f4c859eSApple OSS Distributions 	 * Assign a link-local address, only if there isn't one here already.
964*0f4c859eSApple OSS Distributions 	 * XXX If we ever allow more than one LLA on the interface
965*0f4c859eSApple OSS Distributions 	 * make sure that the corresponding prefix on the prefixlist
966*0f4c859eSApple OSS Distributions 	 * is reference counted and the address's prefix pointer
967*0f4c859eSApple OSS Distributions 	 * points to the prefix.
968*0f4c859eSApple OSS Distributions 	 */
969*0f4c859eSApple OSS Distributions 	ia6 = in6ifa_ifpforlinklocal(ifp, 0);
970*0f4c859eSApple OSS Distributions 	if (ia6 != NULL) {
971*0f4c859eSApple OSS Distributions 		IFA_REMREF(&ia6->ia_ifa);
972*0f4c859eSApple OSS Distributions 		return 0;
973*0f4c859eSApple OSS Distributions 	}
974*0f4c859eSApple OSS Distributions 
975*0f4c859eSApple OSS Distributions 	bzero(&ifra, sizeof(ifra));
976*0f4c859eSApple OSS Distributions 	strlcpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
977*0f4c859eSApple OSS Distributions 
978*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_family = AF_INET6;
979*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
980*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
981*0f4c859eSApple OSS Distributions 	if (in6_embedded_scope) {
982*0f4c859eSApple OSS Distributions 		ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
983*0f4c859eSApple OSS Distributions 	} else {
984*0f4c859eSApple OSS Distributions 		ifra.ifra_addr.sin6_addr.s6_addr16[1] = 0;
985*0f4c859eSApple OSS Distributions 	}
986*0f4c859eSApple OSS Distributions 	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
987*0f4c859eSApple OSS Distributions 	ifra.ifra_flags = IN6_IFF_SECURED;
988*0f4c859eSApple OSS Distributions 
989*0f4c859eSApple OSS Distributions 	in6_cga_node_lock();
990*0f4c859eSApple OSS Distributions 	if (in6_cga_generate(&llcgasr->cgar_cgaprep, llcgasr->cgar_collision_count,
991*0f4c859eSApple OSS Distributions 	    &ifra.ifra_addr.sin6_addr, ifp)) {
992*0f4c859eSApple OSS Distributions 		in6_cga_node_unlock();
993*0f4c859eSApple OSS Distributions 		return EADDRNOTAVAIL;
994*0f4c859eSApple OSS Distributions 	}
995*0f4c859eSApple OSS Distributions 	in6_cga_node_unlock();
996*0f4c859eSApple OSS Distributions 
997*0f4c859eSApple OSS Distributions 	if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, IN6_NULL_IF_EMBEDDED_SCOPE(&ifra.ifra_addr.sin6_scope_id))) {
998*0f4c859eSApple OSS Distributions 		return EADDRNOTAVAIL;
999*0f4c859eSApple OSS Distributions 	}
1000*0f4c859eSApple OSS Distributions 
1001*0f4c859eSApple OSS Distributions 	/* Set the prefix mask */
1002*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1003*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_family = AF_INET6;
1004*0f4c859eSApple OSS Distributions 	ifra.ifra_prefixmask.sin6_addr = in6mask64;
1005*0f4c859eSApple OSS Distributions 
1006*0f4c859eSApple OSS Distributions 	/*
1007*0f4c859eSApple OSS Distributions 	 * link-local addresses should NEVER expire, but cryptographic
1008*0f4c859eSApple OSS Distributions 	 * ones may have finite preferred lifetime [if it's important to
1009*0f4c859eSApple OSS Distributions 	 * keep them from being used by applications as persistent device
1010*0f4c859eSApple OSS Distributions 	 * identifiers].
1011*0f4c859eSApple OSS Distributions 	 */
1012*0f4c859eSApple OSS Distributions 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
1013*0f4c859eSApple OSS Distributions 	ifra.ifra_lifetime.ia6t_pltime = llcgasr->cgar_lifetime.ia6t_pltime;
1014*0f4c859eSApple OSS Distributions 
1015*0f4c859eSApple OSS Distributions 	/* Attach the link-local address */
1016*0f4c859eSApple OSS Distributions 	if (in6_ifattach_linklocal(ifp, &ifra) != 0) {
1017*0f4c859eSApple OSS Distributions 		/* NB: not an error */
1018*0f4c859eSApple OSS Distributions 		nd6log(info,
1019*0f4c859eSApple OSS Distributions 		    "%s: %s could not attach link-local address.\n",
1020*0f4c859eSApple OSS Distributions 		    __func__, if_name(ifp));
1021*0f4c859eSApple OSS Distributions 	}
1022*0f4c859eSApple OSS Distributions 
1023*0f4c859eSApple OSS Distributions 	VERIFY(error == 0);
1024*0f4c859eSApple OSS Distributions 	return error;
1025*0f4c859eSApple OSS Distributions }
1026*0f4c859eSApple OSS Distributions 
1027*0f4c859eSApple OSS Distributions /*
1028*0f4c859eSApple OSS Distributions  * NOTE: in6_ifdetach() does not support loopback if at this moment.
1029*0f4c859eSApple OSS Distributions  */
1030*0f4c859eSApple OSS Distributions void
in6_ifdetach(struct ifnet * ifp)1031*0f4c859eSApple OSS Distributions in6_ifdetach(struct ifnet *ifp)
1032*0f4c859eSApple OSS Distributions {
1033*0f4c859eSApple OSS Distributions 	struct in6_ifaddr *ia, *nia;
1034*0f4c859eSApple OSS Distributions 	struct ifaddr *ifa;
1035*0f4c859eSApple OSS Distributions 	struct rtentry *rt;
1036*0f4c859eSApple OSS Distributions 	struct sockaddr_in6 sin6;
1037*0f4c859eSApple OSS Distributions 	struct in6_multi_mship *imm;
1038*0f4c859eSApple OSS Distributions 	int unlinked;
1039*0f4c859eSApple OSS Distributions 
1040*0f4c859eSApple OSS Distributions 	LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
1041*0f4c859eSApple OSS Distributions 
1042*0f4c859eSApple OSS Distributions 	/* remove neighbor management table */
1043*0f4c859eSApple OSS Distributions 	nd6_purge(ifp);
1044*0f4c859eSApple OSS Distributions 
1045*0f4c859eSApple OSS Distributions 	/* nuke any of IPv6 addresses we have */
1046*0f4c859eSApple OSS Distributions 	lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
1047*0f4c859eSApple OSS Distributions 	boolean_t from_begining = TRUE;
1048*0f4c859eSApple OSS Distributions 	while (from_begining) {
1049*0f4c859eSApple OSS Distributions 		from_begining = FALSE;
1050*0f4c859eSApple OSS Distributions 		TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
1051*0f4c859eSApple OSS Distributions 			if (ia->ia_ifa.ifa_ifp != ifp) {
1052*0f4c859eSApple OSS Distributions 				continue;
1053*0f4c859eSApple OSS Distributions 			}
1054*0f4c859eSApple OSS Distributions 			IFA_ADDREF(&ia->ia_ifa);        /* for us */
1055*0f4c859eSApple OSS Distributions 			lck_rw_done(&in6_ifaddr_rwlock);
1056*0f4c859eSApple OSS Distributions 			in6_purgeaddr(&ia->ia_ifa);
1057*0f4c859eSApple OSS Distributions 			IFA_REMREF(&ia->ia_ifa);        /* for us */
1058*0f4c859eSApple OSS Distributions 			lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
1059*0f4c859eSApple OSS Distributions 			/*
1060*0f4c859eSApple OSS Distributions 			 * Purging the address caused in6_ifaddr_rwlock
1061*0f4c859eSApple OSS Distributions 			 * to be dropped and reacquired;
1062*0f4c859eSApple OSS Distributions 			 * therefore search again from the beginning
1063*0f4c859eSApple OSS Distributions 			 * of in6_ifaddrs list.
1064*0f4c859eSApple OSS Distributions 			 */
1065*0f4c859eSApple OSS Distributions 			from_begining = TRUE;
1066*0f4c859eSApple OSS Distributions 			break;
1067*0f4c859eSApple OSS Distributions 		}
1068*0f4c859eSApple OSS Distributions 	}
1069*0f4c859eSApple OSS Distributions 	lck_rw_done(&in6_ifaddr_rwlock);
1070*0f4c859eSApple OSS Distributions 
1071*0f4c859eSApple OSS Distributions 	ifnet_lock_exclusive(ifp);
1072*0f4c859eSApple OSS Distributions 
1073*0f4c859eSApple OSS Distributions 	/* undo everything done by in6_ifattach(), just in case */
1074*0f4c859eSApple OSS Distributions 	ifa = TAILQ_FIRST(&ifp->if_addrlist);
1075*0f4c859eSApple OSS Distributions 	while (ifa != NULL) {
1076*0f4c859eSApple OSS Distributions 		IFA_LOCK(ifa);
1077*0f4c859eSApple OSS Distributions 		if (ifa->ifa_addr->sa_family != AF_INET6 ||
1078*0f4c859eSApple OSS Distributions 		    !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->
1079*0f4c859eSApple OSS Distributions 		    sin6_addr)) {
1080*0f4c859eSApple OSS Distributions 			IFA_UNLOCK(ifa);
1081*0f4c859eSApple OSS Distributions 			ifa = TAILQ_NEXT(ifa, ifa_list);
1082*0f4c859eSApple OSS Distributions 			continue;
1083*0f4c859eSApple OSS Distributions 		}
1084*0f4c859eSApple OSS Distributions 
1085*0f4c859eSApple OSS Distributions 		ia = (struct in6_ifaddr *)ifa;
1086*0f4c859eSApple OSS Distributions 
1087*0f4c859eSApple OSS Distributions 		/* hold a reference for this routine */
1088*0f4c859eSApple OSS Distributions 		IFA_ADDREF_LOCKED(ifa);
1089*0f4c859eSApple OSS Distributions 		/* remove from the linked list */
1090*0f4c859eSApple OSS Distributions 		if_detach_ifa(ifp, ifa);
1091*0f4c859eSApple OSS Distributions 		IFA_UNLOCK(ifa);
1092*0f4c859eSApple OSS Distributions 
1093*0f4c859eSApple OSS Distributions 		/*
1094*0f4c859eSApple OSS Distributions 		 * Leaving the multicast group(s) may involve freeing the
1095*0f4c859eSApple OSS Distributions 		 * link address multicast structure(s) for the interface,
1096*0f4c859eSApple OSS Distributions 		 * which is protected by ifnet lock.  To avoid violating
1097*0f4c859eSApple OSS Distributions 		 * lock ordering, we must drop ifnet lock before doing so.
1098*0f4c859eSApple OSS Distributions 		 * The ifa won't go away since we held a refcnt above.
1099*0f4c859eSApple OSS Distributions 		 */
1100*0f4c859eSApple OSS Distributions 		ifnet_lock_done(ifp);
1101*0f4c859eSApple OSS Distributions 
1102*0f4c859eSApple OSS Distributions 		/*
1103*0f4c859eSApple OSS Distributions 		 * We have to do this work manually here instead of calling
1104*0f4c859eSApple OSS Distributions 		 * in6_purgeaddr() since in6_purgeaddr() uses the RTM_HOST flag.
1105*0f4c859eSApple OSS Distributions 		 */
1106*0f4c859eSApple OSS Distributions 
1107*0f4c859eSApple OSS Distributions 		/*
1108*0f4c859eSApple OSS Distributions 		 * leave from multicast groups we have joined for the interface
1109*0f4c859eSApple OSS Distributions 		 */
1110*0f4c859eSApple OSS Distributions 		IFA_LOCK(ifa);
1111*0f4c859eSApple OSS Distributions 		while ((imm = ia->ia6_memberships.lh_first) != NULL) {
1112*0f4c859eSApple OSS Distributions 			LIST_REMOVE(imm, i6mm_chain);
1113*0f4c859eSApple OSS Distributions 			IFA_UNLOCK(ifa);
1114*0f4c859eSApple OSS Distributions 			in6_leavegroup(imm);
1115*0f4c859eSApple OSS Distributions 			IFA_LOCK(ifa);
1116*0f4c859eSApple OSS Distributions 		}
1117*0f4c859eSApple OSS Distributions 
1118*0f4c859eSApple OSS Distributions 		/* remove from the routing table */
1119*0f4c859eSApple OSS Distributions 		if (ia->ia_flags & IFA_ROUTE) {
1120*0f4c859eSApple OSS Distributions 			IFA_UNLOCK(ifa);
1121*0f4c859eSApple OSS Distributions 			rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0);
1122*0f4c859eSApple OSS Distributions 			if (rt != NULL) {
1123*0f4c859eSApple OSS Distributions 				(void) rtrequest(RTM_DELETE,
1124*0f4c859eSApple OSS Distributions 				    (struct sockaddr *)&ia->ia_addr,
1125*0f4c859eSApple OSS Distributions 				    (struct sockaddr *)&ia->ia_addr,
1126*0f4c859eSApple OSS Distributions 				    (struct sockaddr *)&ia->ia_prefixmask,
1127*0f4c859eSApple OSS Distributions 				    rt->rt_flags, (struct rtentry **)0);
1128*0f4c859eSApple OSS Distributions 				rtfree(rt);
1129*0f4c859eSApple OSS Distributions 			}
1130*0f4c859eSApple OSS Distributions 		} else {
1131*0f4c859eSApple OSS Distributions 			IFA_UNLOCK(ifa);
1132*0f4c859eSApple OSS Distributions 		}
1133*0f4c859eSApple OSS Distributions 
1134*0f4c859eSApple OSS Distributions 		/* also remove from the IPv6 address chain(itojun&jinmei) */
1135*0f4c859eSApple OSS Distributions 		unlinked = 0;
1136*0f4c859eSApple OSS Distributions 		lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
1137*0f4c859eSApple OSS Distributions 		TAILQ_FOREACH(nia, &in6_ifaddrhead, ia6_link) {
1138*0f4c859eSApple OSS Distributions 			if (ia == nia) {
1139*0f4c859eSApple OSS Distributions 				TAILQ_REMOVE(&in6_ifaddrhead, ia, ia6_link);
1140*0f4c859eSApple OSS Distributions 				os_atomic_inc(&in6_ifaddrlist_genid, relaxed);
1141*0f4c859eSApple OSS Distributions 				unlinked = 1;
1142*0f4c859eSApple OSS Distributions 				break;
1143*0f4c859eSApple OSS Distributions 			}
1144*0f4c859eSApple OSS Distributions 		}
1145*0f4c859eSApple OSS Distributions 		lck_rw_done(&in6_ifaddr_rwlock);
1146*0f4c859eSApple OSS Distributions 
1147*0f4c859eSApple OSS Distributions 		/*
1148*0f4c859eSApple OSS Distributions 		 * release another refcnt for the link from in6_ifaddrs.
1149*0f4c859eSApple OSS Distributions 		 * Do this only if it's not already unlinked in the event
1150*0f4c859eSApple OSS Distributions 		 * that we lost the race, since in6_ifaddr_rwlock was
1151*0f4c859eSApple OSS Distributions 		 * momentarily dropped above.
1152*0f4c859eSApple OSS Distributions 		 */
1153*0f4c859eSApple OSS Distributions 		if (unlinked) {
1154*0f4c859eSApple OSS Distributions 			IFA_REMREF(ifa);
1155*0f4c859eSApple OSS Distributions 		}
1156*0f4c859eSApple OSS Distributions 		/* release reference held for this routine */
1157*0f4c859eSApple OSS Distributions 		IFA_REMREF(ifa);
1158*0f4c859eSApple OSS Distributions 
1159*0f4c859eSApple OSS Distributions 		/*
1160*0f4c859eSApple OSS Distributions 		 * This is suboptimal, but since we dropped ifnet lock above
1161*0f4c859eSApple OSS Distributions 		 * the list might have changed.  Repeat the search from the
1162*0f4c859eSApple OSS Distributions 		 * beginning until we find the first eligible IPv6 address.
1163*0f4c859eSApple OSS Distributions 		 */
1164*0f4c859eSApple OSS Distributions 		ifnet_lock_exclusive(ifp);
1165*0f4c859eSApple OSS Distributions 		ifa = TAILQ_FIRST(&ifp->if_addrlist);
1166*0f4c859eSApple OSS Distributions 	}
1167*0f4c859eSApple OSS Distributions 	ifnet_lock_done(ifp);
1168*0f4c859eSApple OSS Distributions 
1169*0f4c859eSApple OSS Distributions 	/* invalidate route caches */
1170*0f4c859eSApple OSS Distributions 	routegenid_inet6_update();
1171*0f4c859eSApple OSS Distributions 
1172*0f4c859eSApple OSS Distributions 	/*
1173*0f4c859eSApple OSS Distributions 	 * remove neighbor management table.  we call it twice just to make
1174*0f4c859eSApple OSS Distributions 	 * sure we nuke everything.  maybe we need just one call.
1175*0f4c859eSApple OSS Distributions 	 * XXX: since the first call did not release addresses, some prefixes
1176*0f4c859eSApple OSS Distributions 	 * might remain.  We should call nd6_purge() again to release the
1177*0f4c859eSApple OSS Distributions 	 * prefixes after removing all addresses above.
1178*0f4c859eSApple OSS Distributions 	 * (Or can we just delay calling nd6_purge until at this point?)
1179*0f4c859eSApple OSS Distributions 	 */
1180*0f4c859eSApple OSS Distributions 	nd6_purge(ifp);
1181*0f4c859eSApple OSS Distributions 
1182*0f4c859eSApple OSS Distributions 	/* remove route to link-local allnodes multicast (ff02::1) */
1183*0f4c859eSApple OSS Distributions 	bzero(&sin6, sizeof(sin6));
1184*0f4c859eSApple OSS Distributions 	sin6.sin6_len = sizeof(struct sockaddr_in6);
1185*0f4c859eSApple OSS Distributions 	sin6.sin6_family = AF_INET6;
1186*0f4c859eSApple OSS Distributions 	sin6.sin6_addr = in6addr_linklocal_allnodes;
1187*0f4c859eSApple OSS Distributions 	if (in6_embedded_scope) {
1188*0f4c859eSApple OSS Distributions 		sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1189*0f4c859eSApple OSS Distributions 	} else {
1190*0f4c859eSApple OSS Distributions 		sin6.sin6_scope_id = ifp->if_index;
1191*0f4c859eSApple OSS Distributions 	}
1192*0f4c859eSApple OSS Distributions 	rt = rtalloc1((struct sockaddr *)&sin6, 0, 0);
1193*0f4c859eSApple OSS Distributions 	if (rt != NULL) {
1194*0f4c859eSApple OSS Distributions 		RT_LOCK(rt);
1195*0f4c859eSApple OSS Distributions 		if (rt->rt_ifp == ifp) {
1196*0f4c859eSApple OSS Distributions 			/*
1197*0f4c859eSApple OSS Distributions 			 * Prevent another thread from modifying rt_key,
1198*0f4c859eSApple OSS Distributions 			 * rt_gateway via rt_setgate() after the rt_lock
1199*0f4c859eSApple OSS Distributions 			 * is dropped by marking the route as defunct.
1200*0f4c859eSApple OSS Distributions 			 */
1201*0f4c859eSApple OSS Distributions 			rt->rt_flags |= RTF_CONDEMNED;
1202*0f4c859eSApple OSS Distributions 			RT_UNLOCK(rt);
1203*0f4c859eSApple OSS Distributions 			(void) rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
1204*0f4c859eSApple OSS Distributions 			    rt_mask(rt), rt->rt_flags, 0);
1205*0f4c859eSApple OSS Distributions 		} else {
1206*0f4c859eSApple OSS Distributions 			RT_UNLOCK(rt);
1207*0f4c859eSApple OSS Distributions 		}
1208*0f4c859eSApple OSS Distributions 		rtfree(rt);
1209*0f4c859eSApple OSS Distributions 	}
1210*0f4c859eSApple OSS Distributions }
1211*0f4c859eSApple OSS Distributions 
1212*0f4c859eSApple OSS Distributions void
in6_iid_mktmp(struct ifnet * ifp,u_int8_t * retbuf,const u_int8_t * baseid,int generate)1213*0f4c859eSApple OSS Distributions in6_iid_mktmp(struct ifnet *ifp, u_int8_t *retbuf, const u_int8_t *baseid,
1214*0f4c859eSApple OSS Distributions     int generate)
1215*0f4c859eSApple OSS Distributions {
1216*0f4c859eSApple OSS Distributions 	u_int8_t nullbuf[8];
1217*0f4c859eSApple OSS Distributions 	struct nd_ifinfo *ndi = ND_IFINFO(ifp);
1218*0f4c859eSApple OSS Distributions 
1219*0f4c859eSApple OSS Distributions 	VERIFY(ndi != NULL && ndi->initialized);
1220*0f4c859eSApple OSS Distributions 	lck_mtx_lock(&ndi->lock);
1221*0f4c859eSApple OSS Distributions 	bzero(nullbuf, sizeof(nullbuf));
1222*0f4c859eSApple OSS Distributions 	if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
1223*0f4c859eSApple OSS Distributions 		/* we've never created a random ID.  Create a new one. */
1224*0f4c859eSApple OSS Distributions 		generate = 1;
1225*0f4c859eSApple OSS Distributions 	}
1226*0f4c859eSApple OSS Distributions 
1227*0f4c859eSApple OSS Distributions 	if (generate) {
1228*0f4c859eSApple OSS Distributions 		bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
1229*0f4c859eSApple OSS Distributions 
1230*0f4c859eSApple OSS Distributions 		/* in6_generate_tmp_iid will update seedn and buf */
1231*0f4c859eSApple OSS Distributions 		(void) in6_generate_tmp_iid(ndi->randomseed0, ndi->randomseed1,
1232*0f4c859eSApple OSS Distributions 		    ndi->randomid);
1233*0f4c859eSApple OSS Distributions 	}
1234*0f4c859eSApple OSS Distributions 
1235*0f4c859eSApple OSS Distributions 	bcopy(ndi->randomid, retbuf, 8);
1236*0f4c859eSApple OSS Distributions 	lck_mtx_unlock(&ndi->lock);
1237*0f4c859eSApple OSS Distributions }
1238*0f4c859eSApple OSS Distributions 
1239*0f4c859eSApple OSS Distributions void
in6_tmpaddrtimer(void * arg)1240*0f4c859eSApple OSS Distributions in6_tmpaddrtimer(void *arg)
1241*0f4c859eSApple OSS Distributions {
1242*0f4c859eSApple OSS Distributions #pragma unused(arg)
1243*0f4c859eSApple OSS Distributions 	struct ifnet *ifp = NULL;
1244*0f4c859eSApple OSS Distributions 	struct nd_ifinfo *ndi = NULL;
1245*0f4c859eSApple OSS Distributions 	u_int8_t nullbuf[8];
1246*0f4c859eSApple OSS Distributions 
1247*0f4c859eSApple OSS Distributions 	timeout(in6_tmpaddrtimer, (caddr_t)0, (ip6_temp_preferred_lifetime -
1248*0f4c859eSApple OSS Distributions 	    ip6_desync_factor - ip6_temp_regen_advance) * hz);
1249*0f4c859eSApple OSS Distributions 
1250*0f4c859eSApple OSS Distributions 	bzero(nullbuf, sizeof(nullbuf));
1251*0f4c859eSApple OSS Distributions 	ifnet_head_lock_shared();
1252*0f4c859eSApple OSS Distributions 	for (ifp = ifnet_head.tqh_first; ifp;
1253*0f4c859eSApple OSS Distributions 	    ifp = ifp->if_link.tqe_next) {
1254*0f4c859eSApple OSS Distributions 		ndi = ND_IFINFO(ifp);
1255*0f4c859eSApple OSS Distributions 		if ((NULL == ndi) || (FALSE == ndi->initialized)) {
1256*0f4c859eSApple OSS Distributions 			continue;
1257*0f4c859eSApple OSS Distributions 		}
1258*0f4c859eSApple OSS Distributions 		lck_mtx_lock(&ndi->lock);
1259*0f4c859eSApple OSS Distributions 		if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
1260*0f4c859eSApple OSS Distributions 			/*
1261*0f4c859eSApple OSS Distributions 			 * We've been generating a random ID on this interface.
1262*0f4c859eSApple OSS Distributions 			 * Create a new one.
1263*0f4c859eSApple OSS Distributions 			 */
1264*0f4c859eSApple OSS Distributions 			(void) in6_generate_tmp_iid(ndi->randomseed0,
1265*0f4c859eSApple OSS Distributions 			    ndi->randomseed1, ndi->randomid);
1266*0f4c859eSApple OSS Distributions 		}
1267*0f4c859eSApple OSS Distributions 		lck_mtx_unlock(&ndi->lock);
1268*0f4c859eSApple OSS Distributions 	}
1269*0f4c859eSApple OSS Distributions 	ifnet_head_done();
1270*0f4c859eSApple OSS Distributions }
1271