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