1/*
2 * Copyright (c) 2003-2022 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
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/*
59 * Copyright (c) 1982, 1986, 1991, 1993
60 * The Regents of the University of California. All rights reserved.
61 *
62 * Redistribution and use in source and binary forms, with or without
63 * modification, are permitted provided that the following conditions
64 * are met:
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in the
69 * documentation and/or other materials provided with the distribution.
70 * 3. All advertising materials mentioning features or use of this software
71 * must display the following acknowledgement:
72 * This product includes software developed by the University of
73 * California, Berkeley and its contributors.
74 * 4. Neither the name of the University nor the names of its contributors
75 * may be used to endorse or promote products derived from this software
76 * without specific prior written permission.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE.
89 *
90 * @(#)in.c 8.2 (Berkeley) 11/15/93
91 */
92
93
94#include <sys/param.h>
95#include <sys/ioctl.h>
96#include <sys/errno.h>
97#include <sys/malloc.h>
98#include <sys/socket.h>
99#include <sys/socketvar.h>
100#include <sys/sockio.h>
101#include <sys/systm.h>
102#include <sys/time.h>
103#include <sys/kernel.h>
104#include <sys/syslog.h>
105#include <sys/kern_event.h>
106#include <sys/mcache.h>
107#include <sys/protosw.h>
108
109#include <kern/locks.h>
110#include <kern/zalloc.h>
111#include <libkern/OSAtomic.h>
112#include <machine/machine_routines.h>
113#include <mach/boolean.h>
114
115#include <net/if.h>
116#include <net/if_types.h>
117#include <net/if_var.h>
118#include <net/route.h>
119#include <net/if_dl.h>
120#include <net/kpi_protocol.h>
121#include <net/nwk_wq.h>
122
123#include <netinet/in.h>
124#include <netinet/in_var.h>
125#include <netinet/if_ether.h>
126#include <netinet/in_systm.h>
127#include <netinet/ip.h>
128#include <netinet/in_pcb.h>
129#include <netinet/icmp6.h>
130#include <netinet/tcp.h>
131#include <netinet/tcp_seq.h>
132#include <netinet/tcp_var.h>
133
134#include <netinet6/nd6.h>
135#include <netinet/ip6.h>
136#include <netinet6/ip6_var.h>
137#include <netinet6/mld6_var.h>
138#include <netinet6/in6_ifattach.h>
139#include <netinet6/scope6_var.h>
140#include <netinet6/in6_var.h>
141#include <netinet6/in6_pcb.h>
142
143#include <net/net_osdep.h>
144
145#include <net/dlil.h>
146
147#if PF
148#include <net/pfvar.h>
149#endif /* PF */
150
151#include <net/sockaddr_utils.h>
152
153/*
154 * Definitions of some costant IP6 addresses.
155 */
156const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
157const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
158const struct in6_addr in6addr_nodelocal_allnodes =
159 IN6ADDR_NODELOCAL_ALLNODES_INIT;
160const struct in6_addr in6addr_linklocal_allnodes =
161 IN6ADDR_LINKLOCAL_ALLNODES_INIT;
162const struct in6_addr in6addr_linklocal_allrouters =
163 IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
164const struct in6_addr in6addr_linklocal_allv2routers =
165 IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT;
166const struct in6_addr in6addr_multicast_prefix =
167 IN6ADDR_MULTICAST_PREFIX;
168
169const struct in6_addr in6mask0 = IN6MASK0;
170const struct in6_addr in6mask7 = IN6MASK7;
171const struct in6_addr in6mask8 = IN6MASK8;
172const struct in6_addr in6mask16 = IN6MASK16;
173const struct in6_addr in6mask32 = IN6MASK32;
174const struct in6_addr in6mask64 = IN6MASK64;
175const struct in6_addr in6mask96 = IN6MASK96;
176const struct in6_addr in6mask128 = IN6MASK128;
177
178const struct sockaddr_in6 sa6_any = {
179 .sin6_len = sizeof(sa6_any),
180 .sin6_family = AF_INET6,
181 .sin6_port = 0,
182 .sin6_flowinfo = 0,
183 .sin6_addr = IN6ADDR_ANY_INIT,
184 .sin6_scope_id = 0
185};
186
187static int in6ctl_associd(struct socket *, u_long, caddr_t);
188static int in6ctl_connid(struct socket *, u_long, caddr_t);
189static int in6ctl_conninfo(struct socket *, u_long, caddr_t);
190static int in6ctl_llstart(struct ifnet *, u_long, caddr_t);
191static int in6ctl_llstop(struct ifnet *);
192static int in6ctl_cgastart(struct ifnet *, u_long, caddr_t);
193static int in6ctl_gifaddr(struct ifnet *, struct in6_ifaddr *, u_long,
194 struct in6_ifreq *);
195static int in6ctl_gifstat(struct ifnet *, u_long, struct in6_ifreq *);
196static int in6ctl_alifetime(struct in6_ifaddr *, u_long, struct in6_ifreq *,
197 boolean_t);
198static int in6ctl_aifaddr(struct ifnet *, struct in6_aliasreq *);
199static void in6ctl_difaddr(struct ifnet *, struct in6_ifaddr *);
200static int in6_autoconf(struct ifnet *, int);
201static int in6_setrouter(struct ifnet *, ipv6_router_mode_t);
202static int in6_ifinit(struct ifnet *, struct in6_ifaddr *, int);
203static int in6_ifaupdate_aux(struct in6_ifaddr *, struct ifnet *, int);
204static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
205static struct in6_ifaddr *in6_ifaddr_alloc(zalloc_flags_t);
206static void in6_ifaddr_free(struct ifaddr *);
207#if defined(__LP64__)
208static void in6_cgareq_32_to_64(const struct in6_cgareq_32 *,
209 struct in6_cgareq_64 *);
210#else
211static void in6_cgareq_64_to_32(const struct in6_cgareq_64 *,
212 struct in6_cgareq_32 *);
213#endif
214static struct in6_aliasreq *in6_aliasreq_to_native(void *, int,
215 struct in6_aliasreq *);
216static int in6_to_kamescope(struct sockaddr_in6 *, struct ifnet *);
217static int in6_getassocids(struct socket *, uint32_t *, user_addr_t);
218static int in6_getconnids(struct socket *, sae_associd_t, uint32_t *,
219 user_addr_t);
220
221static void in6_if_up_dad_start(struct ifnet *);
222
223#define IA6_HASH_INIT(ia) { \
224 (ia)->ia6_hash.tqe_next = (void *)(uintptr_t)-1; \
225 (ia)->ia6_hash.tqe_prev = (void *)(uintptr_t)-1; \
226}
227
228#define IA6_IS_HASHED(ia) \
229 (!((ia)->ia6_hash.tqe_next == (void *)(uintptr_t)-1 || \
230 (ia)->ia6_hash.tqe_prev == (void *)(uintptr_t)-1))
231
232static void in6_iahash_remove(struct in6_ifaddr *);
233static void in6_iahash_insert(struct in6_ifaddr *);
234static void in6_iahash_insert_ptp(struct in6_ifaddr *);
235
236struct eventhandler_lists_ctxt in6_evhdlr_ctxt;
237struct eventhandler_lists_ctxt in6_clat46_evhdlr_ctxt;
238/*
239 * Subroutine for in6_ifaddloop() and in6_ifremloop().
240 * This routine does actual work.
241 */
242static void
243in6_ifloop_request(int cmd, struct ifaddr *ifa)
244{
245 struct sockaddr_in6 all1_sa;
246 struct rtentry *nrt __single = NULL;
247 int e;
248
249 SOCKADDR_ZERO(&all1_sa, sizeof(all1_sa));
250 all1_sa.sin6_family = AF_INET6;
251 all1_sa.sin6_len = sizeof(struct sockaddr_in6);
252 all1_sa.sin6_addr = in6mask128;
253
254 /*
255 * We specify the address itself as the gateway, and set the
256 * RTF_LLINFO flag, so that the corresponding host route would have
257 * the flag, and thus applications that assume traditional behavior
258 * would be happy. Note that we assume the caller of the function
259 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
260 * which changes the outgoing interface to the loopback interface.
261 * ifa_addr for INET6 is set once during init; no need to hold lock.
262 */
263 lck_mtx_lock(rnh_lock);
264 e = rtrequest_locked(cmd, ifa->ifa_addr, ifa->ifa_addr,
265 SA(&all1_sa), RTF_UP | RTF_HOST | RTF_LLINFO, &nrt);
266 if (e != 0) {
267 log(LOG_ERR, "in6_ifloop_request: "
268 "%s operation failed for %s (errno=%d)\n",
269 cmd == RTM_ADD ? "ADD" : "DELETE",
270 ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
271 e);
272 }
273
274 if (nrt != NULL) {
275 RT_LOCK(nrt);
276 }
277 /*
278 * Make sure rt_ifa be equal to IFA, the second argument of the
279 * function.
280 * We need this because when we refer to rt_ifa->ia6_flags in
281 * ip6_input, we assume that the rt_ifa points to the address instead
282 * of the loopback address.
283 */
284 if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
285 rtsetifa(nrt, ifa);
286 }
287
288 /*
289 * Report the addition/removal of the address to the routing socket.
290 * XXX: since we called rtinit for a p2p interface with a destination,
291 * we end up reporting twice in such a case. Should we rather
292 * omit the second report?
293 */
294 if (nrt != NULL) {
295 rt_newaddrmsg((u_char)cmd, ifa, e, nrt);
296 if (cmd == RTM_DELETE) {
297 RT_UNLOCK(nrt);
298 rtfree_locked(nrt);
299 } else {
300 /* the cmd must be RTM_ADD here */
301 RT_REMREF_LOCKED(nrt);
302 RT_UNLOCK(nrt);
303 }
304 }
305 lck_mtx_unlock(rnh_lock);
306}
307
308/*
309 * Add ownaddr as loopback rtentry. We previously add the route only if
310 * necessary (ex. on a p2p link). However, since we now manage addresses
311 * separately from prefixes, we should always add the route. We can't
312 * rely on the cloning mechanism from the corresponding interface route
313 * any more.
314 */
315static void
316in6_ifaddloop(struct ifaddr *ifa)
317{
318 struct rtentry *rt;
319
320 /*
321 * If there is no loopback entry, allocate one. ifa_addr for
322 * INET6 is set once during init; no need to hold lock.
323 */
324 rt = rtalloc1(ifa->ifa_addr, 0, 0);
325 if (rt != NULL) {
326 RT_LOCK(rt);
327 }
328 if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
329 (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) {
330 if (rt != NULL) {
331 RT_REMREF_LOCKED(rt);
332 RT_UNLOCK(rt);
333 }
334 in6_ifloop_request(RTM_ADD, ifa);
335 } else if (rt != NULL) {
336 RT_REMREF_LOCKED(rt);
337 RT_UNLOCK(rt);
338 }
339}
340
341/*
342 * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
343 * if it exists.
344 */
345static void
346in6_ifremloop(struct ifaddr *ifa)
347{
348 struct in6_ifaddr *ia;
349 struct rtentry *rt;
350 int ia_count = 0;
351
352 /*
353 * Some of BSD variants do not remove cloned routes
354 * from an interface direct route, when removing the direct route
355 * (see comments in net/net_osdep.h). Even for variants that do remove
356 * cloned routes, they could fail to remove the cloned routes when
357 * we handle multple addresses that share a common prefix.
358 * So, we should remove the route corresponding to the deleted address
359 * regardless of the result of in6_is_ifloop_auto().
360 */
361
362 /*
363 * Delete the entry only if exact one ifa exists. More than one ifa
364 * can exist if we assign a same single address to multiple
365 * (probably p2p) interfaces.
366 * XXX: we should avoid such a configuration in IPv6...
367 */
368 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
369 TAILQ_FOREACH(ia, IN6ADDR_HASH(IFA_IN6(ifa)), ia6_hash) {
370 IFA_LOCK(&ia->ia_ifa);
371 if (in6_are_addr_equal_scoped(IFA_IN6(ifa), &ia->ia_addr.sin6_addr, IFA_SIN6(ifa)->sin6_scope_id, ia->ia_addr.sin6_scope_id)) {
372 ia_count++;
373 if (ia_count > 1) {
374 IFA_UNLOCK(&ia->ia_ifa);
375 break;
376 }
377 }
378 IFA_UNLOCK(&ia->ia_ifa);
379 }
380 lck_rw_done(lck: &in6_ifaddr_rwlock);
381
382 if (ia_count == 1) {
383 /*
384 * Before deleting, check if a corresponding loopbacked host
385 * route surely exists. With this check, we can avoid to
386 * delete an interface direct route whose destination is same
387 * as the address being removed. This can happen when removing
388 * a subnet-router anycast address on an interface attahced
389 * to a shared medium. ifa_addr for INET6 is set once during
390 * init; no need to hold lock.
391 */
392 rt = rtalloc1(ifa->ifa_addr, 0, 0);
393 if (rt != NULL) {
394 RT_LOCK(rt);
395 if ((rt->rt_flags & RTF_HOST) != 0 &&
396 (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
397 RT_REMREF_LOCKED(rt);
398 RT_UNLOCK(rt);
399 in6_ifloop_request(RTM_DELETE, ifa);
400 } else {
401 RT_UNLOCK(rt);
402 }
403 }
404 }
405}
406
407
408int
409in6_mask2len(struct in6_addr *mask, u_char *lim0)
410{
411 int x = 0, y;
412 u_char *lim = lim0, *p;
413
414 /* ignore the scope_id part */
415 if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask)) {
416 lim = (u_char *)mask + sizeof(*mask);
417 }
418 for (p = (u_char *)mask; p < lim; x++, p++) {
419 if (*p != 0xff) {
420 break;
421 }
422 }
423 y = 0;
424 if (p < lim) {
425 for (y = 0; y < 8; y++) {
426 if ((*p & (0x80 >> y)) == 0) {
427 break;
428 }
429 }
430 }
431
432 /*
433 * when the limit pointer is given, do a stricter check on the
434 * remaining bits.
435 */
436 if (p < lim) {
437 if (y != 0 && (*p & (0x00ff >> y)) != 0) {
438 return -1;
439 }
440 for (p = p + 1; p < lim; p++) {
441 if (*p != 0) {
442 return -1;
443 }
444 }
445 }
446
447 return x * 8 + y;
448}
449
450void
451in6_len2mask(struct in6_addr *mask, int len)
452{
453 int i;
454
455 bzero(s: mask, n: sizeof(*mask));
456 for (i = 0; i < len / 8; i++) {
457 mask->s6_addr8[i] = 0xff;
458 }
459 if (len % 8) {
460 mask->s6_addr8[i] = (0xff00 >> (len % 8)) & 0xff;
461 }
462}
463
464void
465in6_aliasreq_64_to_32(struct in6_aliasreq_64 *src, struct in6_aliasreq_32 *dst)
466{
467 bzero(s: dst, n: sizeof(*dst));
468 bcopy(src: src->ifra_name, dst: dst->ifra_name, n: sizeof(dst->ifra_name));
469 dst->ifra_addr = src->ifra_addr;
470 dst->ifra_dstaddr = src->ifra_dstaddr;
471 dst->ifra_prefixmask = src->ifra_prefixmask;
472 dst->ifra_flags = src->ifra_flags;
473 dst->ifra_lifetime.ia6t_expire = (u_int32_t)src->ifra_lifetime.ia6t_expire;
474 dst->ifra_lifetime.ia6t_preferred = (u_int32_t)src->ifra_lifetime.ia6t_preferred;
475 dst->ifra_lifetime.ia6t_vltime = src->ifra_lifetime.ia6t_vltime;
476 dst->ifra_lifetime.ia6t_pltime = src->ifra_lifetime.ia6t_pltime;
477}
478
479void
480in6_aliasreq_32_to_64(struct in6_aliasreq_32 *src, struct in6_aliasreq_64 *dst)
481{
482 bzero(s: dst, n: sizeof(*dst));
483 bcopy(src: src->ifra_name, dst: dst->ifra_name, n: sizeof(dst->ifra_name));
484 dst->ifra_addr = src->ifra_addr;
485 dst->ifra_dstaddr = src->ifra_dstaddr;
486 dst->ifra_prefixmask = src->ifra_prefixmask;
487 dst->ifra_flags = src->ifra_flags;
488 dst->ifra_lifetime.ia6t_expire = src->ifra_lifetime.ia6t_expire;
489 dst->ifra_lifetime.ia6t_preferred = src->ifra_lifetime.ia6t_preferred;
490 dst->ifra_lifetime.ia6t_vltime = src->ifra_lifetime.ia6t_vltime;
491 dst->ifra_lifetime.ia6t_pltime = src->ifra_lifetime.ia6t_pltime;
492}
493
494#if defined(__LP64__)
495static void
496in6_cgareq_32_to_64(const struct in6_cgareq_32 *src,
497 struct in6_cgareq_64 *dst)
498{
499 bzero(s: dst, n: sizeof(*dst));
500 bcopy(src: src->cgar_name, dst: dst->cgar_name, n: sizeof(dst->cgar_name));
501 dst->cgar_flags = src->cgar_flags;
502 bcopy(src: src->cgar_cgaprep.cga_modifier.octets,
503 dst: dst->cgar_cgaprep.cga_modifier.octets,
504 n: sizeof(dst->cgar_cgaprep.cga_modifier.octets));
505 dst->cgar_cgaprep.cga_security_level =
506 src->cgar_cgaprep.cga_security_level;
507 dst->cgar_lifetime.ia6t_expire = src->cgar_lifetime.ia6t_expire;
508 dst->cgar_lifetime.ia6t_preferred = src->cgar_lifetime.ia6t_preferred;
509 dst->cgar_lifetime.ia6t_vltime = src->cgar_lifetime.ia6t_vltime;
510 dst->cgar_lifetime.ia6t_pltime = src->cgar_lifetime.ia6t_pltime;
511 dst->cgar_collision_count = src->cgar_collision_count;
512}
513#endif
514
515#if !defined(__LP64__)
516static void
517in6_cgareq_64_to_32(const struct in6_cgareq_64 *src,
518 struct in6_cgareq_32 *dst)
519{
520 bzero(dst, sizeof(*dst));
521 bcopy(src->cgar_name, dst->cgar_name, sizeof(dst->cgar_name));
522 dst->cgar_flags = src->cgar_flags;
523 bcopy(src->cgar_cgaprep.cga_modifier.octets,
524 dst->cgar_cgaprep.cga_modifier.octets,
525 sizeof(dst->cgar_cgaprep.cga_modifier.octets));
526 dst->cgar_cgaprep.cga_security_level =
527 src->cgar_cgaprep.cga_security_level;
528 dst->cgar_lifetime.ia6t_expire = (u_int32_t)src->cgar_lifetime.ia6t_expire;
529 dst->cgar_lifetime.ia6t_preferred = (u_int32_t)src->cgar_lifetime.ia6t_preferred;
530 dst->cgar_lifetime.ia6t_vltime = src->cgar_lifetime.ia6t_vltime;
531 dst->cgar_lifetime.ia6t_pltime = src->cgar_lifetime.ia6t_pltime;
532 dst->cgar_collision_count = src->cgar_collision_count;
533}
534#endif
535
536static struct in6_aliasreq *
537in6_aliasreq_to_native(void *data, int data_is_64, struct in6_aliasreq *dst)
538{
539#if defined(__LP64__)
540 if (data_is_64) {
541 bcopy(src: data, dst, n: sizeof(*dst));
542 } else {
543 in6_aliasreq_32_to_64(src: (struct in6_aliasreq_32 *)data,
544 dst: (struct in6_aliasreq_64 *)dst);
545 }
546#else
547 if (data_is_64) {
548 in6_aliasreq_64_to_32((struct in6_aliasreq_64 *)data,
549 (struct in6_aliasreq_32 *)dst);
550 } else {
551 bcopy(data, dst, sizeof(*dst));
552 }
553#endif /* __LP64__ */
554 return dst;
555}
556
557void
558in6_cgareq_copy_from_user(const void *user_data, int user_is_64,
559 struct in6_cgareq *cgareq)
560{
561#if defined(__LP64__)
562 if (user_is_64) {
563 bcopy(src: user_data, dst: cgareq, n: sizeof(*cgareq));
564 } else {
565 in6_cgareq_32_to_64(src: (const struct in6_cgareq_32 *)user_data,
566 dst: (struct in6_cgareq_64 *)cgareq);
567 }
568#else
569 if (user_is_64) {
570 in6_cgareq_64_to_32((const struct in6_cgareq_64 *)user_data,
571 (struct in6_cgareq_32 *)cgareq);
572 } else {
573 bcopy(user_data, cgareq, sizeof(*cgareq));
574 }
575#endif /* __LP64__ */
576}
577
578static __attribute__((noinline)) int
579in6ctl_associd(struct socket *so, u_long cmd, caddr_t data)
580{
581 int error = 0;
582 union {
583 struct so_aidreq32 a32;
584 struct so_aidreq64 a64;
585 } u;
586
587 VERIFY(so != NULL);
588
589 switch (cmd) {
590 case SIOCGASSOCIDS32: { /* struct so_aidreq32 */
591 bcopy(src: data, dst: &u.a32, n: sizeof(u.a32));
592 error = in6_getassocids(so, &u.a32.sar_cnt, u.a32.sar_aidp);
593 if (error == 0) {
594 bcopy(src: &u.a32, dst: data, n: sizeof(u.a32));
595 }
596 break;
597 }
598
599 case SIOCGASSOCIDS64: { /* struct so_aidreq64 */
600 bcopy(src: data, dst: &u.a64, n: sizeof(u.a64));
601 error = in6_getassocids(so, &u.a64.sar_cnt, (user_addr_t)u.a64.sar_aidp);
602 if (error == 0) {
603 bcopy(src: &u.a64, dst: data, n: sizeof(u.a64));
604 }
605 break;
606 }
607
608 default:
609 VERIFY(0);
610 /* NOTREACHED */
611 }
612
613 return error;
614}
615
616static __attribute__((noinline)) int
617in6ctl_connid(struct socket *so, u_long cmd, caddr_t data)
618{
619 int error = 0;
620 union {
621 struct so_cidreq32 c32;
622 struct so_cidreq64 c64;
623 } u;
624
625 VERIFY(so != NULL);
626
627 switch (cmd) {
628 case SIOCGCONNIDS32: { /* struct so_cidreq32 */
629 bcopy(src: data, dst: &u.c32, n: sizeof(u.c32));
630 error = in6_getconnids(so, u.c32.scr_aid, &u.c32.scr_cnt,
631 u.c32.scr_cidp);
632 if (error == 0) {
633 bcopy(src: &u.c32, dst: data, n: sizeof(u.c32));
634 }
635 break;
636 }
637
638 case SIOCGCONNIDS64: { /* struct so_cidreq64 */
639 bcopy(src: data, dst: &u.c64, n: sizeof(u.c64));
640 error = in6_getconnids(so, u.c64.scr_aid, &u.c64.scr_cnt,
641 (user_addr_t)u.c64.scr_cidp);
642 if (error == 0) {
643 bcopy(src: &u.c64, dst: data, n: sizeof(u.c64));
644 }
645 break;
646 }
647
648 default:
649 VERIFY(0);
650 /* NOTREACHED */
651 }
652
653 return error;
654}
655
656static __attribute__((noinline)) int
657in6ctl_conninfo(struct socket *so, u_long cmd, caddr_t data)
658{
659 int error = 0;
660 union {
661 struct so_cinforeq32 ci32;
662 struct so_cinforeq64 ci64;
663 } u;
664
665 VERIFY(so != NULL);
666
667 switch (cmd) {
668 case SIOCGCONNINFO32: { /* struct so_cinforeq32 */
669 bcopy(src: data, dst: &u.ci32, n: sizeof(u.ci32));
670 error = in6_getconninfo(so, u.ci32.scir_cid, &u.ci32.scir_flags,
671 &u.ci32.scir_ifindex, &u.ci32.scir_error, u.ci32.scir_src,
672 &u.ci32.scir_src_len, u.ci32.scir_dst, &u.ci32.scir_dst_len,
673 &u.ci32.scir_aux_type, u.ci32.scir_aux_data,
674 &u.ci32.scir_aux_len);
675 if (error == 0) {
676 bcopy(src: &u.ci32, dst: data, n: sizeof(u.ci32));
677 }
678 break;
679 }
680
681 case SIOCGCONNINFO64: { /* struct so_cinforeq64 */
682 bcopy(src: data, dst: &u.ci64, n: sizeof(u.ci64));
683 error = in6_getconninfo(so, u.ci64.scir_cid, &u.ci64.scir_flags,
684 &u.ci64.scir_ifindex, &u.ci64.scir_error, (user_addr_t)u.ci64.scir_src,
685 &u.ci64.scir_src_len, (user_addr_t)u.ci64.scir_dst, &u.ci64.scir_dst_len,
686 &u.ci64.scir_aux_type, (user_addr_t)u.ci64.scir_aux_data,
687 &u.ci64.scir_aux_len);
688 if (error == 0) {
689 bcopy(src: &u.ci64, dst: data, n: sizeof(u.ci64));
690 }
691 break;
692 }
693
694 default:
695 VERIFY(0);
696 /* NOTREACHED */
697 }
698
699 return error;
700}
701
702static __attribute__((noinline)) int
703in6ctl_llstart(struct ifnet *ifp, u_long cmd, caddr_t data)
704{
705 struct in6_aliasreq sifra, *ifra = NULL;
706 boolean_t is64;
707 int error = 0;
708
709 VERIFY(ifp != NULL);
710
711 switch (cmd) {
712 case SIOCLL_START_32: /* struct in6_aliasreq_32 */
713 case SIOCLL_START_64: /* struct in6_aliasreq_64 */
714 is64 = (cmd == SIOCLL_START_64);
715 /*
716 * Convert user ifra to the kernel form, when appropriate.
717 * This allows the conversion between different data models
718 * to be centralized, so that it can be passed around to other
719 * routines that are expecting the kernel form.
720 */
721 ifra = in6_aliasreq_to_native(data, data_is_64: is64, dst: &sifra);
722
723 /*
724 * NOTE: All the interface specific DLIL attachements should
725 * be done here. They are currently done in in6_ifattach_aux()
726 * for the interfaces that need it.
727 */
728 if (ifra->ifra_addr.sin6_family == AF_INET6 &&
729 /* Only check ifra_dstaddr if valid */
730 (ifra->ifra_dstaddr.sin6_len == 0 ||
731 ifra->ifra_dstaddr.sin6_family == AF_INET6)) {
732 /* some interfaces may provide LinkLocal addresses */
733 error = in6_ifattach_aliasreq(ifp, NULL, ifra);
734 } else {
735 error = in6_ifattach_aliasreq(ifp, NULL, NULL);
736 }
737 if (error == 0) {
738 in6_if_up_dad_start(ifp);
739 }
740 break;
741
742 default:
743 VERIFY(0);
744 /* NOTREACHED */
745 }
746
747 return error;
748}
749
750static __attribute__((noinline)) int
751in6ctl_llstop(struct ifnet *ifp)
752{
753 struct in6_ifaddr *ia;
754 struct nd_prefix pr0, *pr;
755
756 VERIFY(ifp != NULL);
757
758 /* Remove link local addresses from interface */
759 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
760 boolean_t from_begining = TRUE;
761 while (from_begining) {
762 from_begining = FALSE;
763 TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
764 if (ia->ia_ifa.ifa_ifp != ifp) {
765 continue;
766 }
767 IFA_LOCK(&ia->ia_ifa);
768 if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
769 ifa_addref(ifa: &ia->ia_ifa); /* for us */
770 IFA_UNLOCK(&ia->ia_ifa);
771 lck_rw_done(lck: &in6_ifaddr_rwlock);
772 in6_purgeaddr(&ia->ia_ifa);
773 ifa_remref(ifa: &ia->ia_ifa); /* for us */
774 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
775 /*
776 * Purging the address caused in6_ifaddr_rwlock
777 * to be dropped and reacquired;
778 * therefore search again from the beginning
779 * of in6_ifaddrs list.
780 */
781 from_begining = TRUE;
782 break;
783 }
784 IFA_UNLOCK(&ia->ia_ifa);
785 }
786 }
787 lck_rw_done(lck: &in6_ifaddr_rwlock);
788
789 /* Delete the link local prefix */
790 bzero(s: &pr0, n: sizeof(pr0));
791 pr0.ndpr_plen = 64;
792 pr0.ndpr_ifp = ifp;
793 pr0.ndpr_prefix.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_ULL;
794 (void)in6_setscope(&pr0.ndpr_prefix.sin6_addr, ifp, IN6_NULL_IF_EMBEDDED_SCOPE(&pr0.ndpr_prefix.sin6_scope_id));
795 pr = nd6_prefix_lookup(&pr0, ND6_PREFIX_EXPIRY_UNSPEC);
796 if (pr) {
797 lck_mtx_lock(nd6_mutex);
798 NDPR_LOCK(pr);
799 prelist_remove(pr);
800 NDPR_UNLOCK(pr);
801 NDPR_REMREF(pr); /* Drop the reference from lookup */
802 lck_mtx_unlock(nd6_mutex);
803 }
804
805 return 0;
806}
807
808/*
809 * This routine configures secure link local address
810 */
811static __attribute__((noinline)) int
812in6ctl_cgastart(struct ifnet *ifp, u_long cmd, caddr_t data)
813{
814 struct in6_cgareq llcgasr;
815 int is64, error = 0;
816
817 VERIFY(ifp != NULL);
818
819 switch (cmd) {
820 case SIOCLL_CGASTART_32: /* struct in6_cgareq_32 */
821 case SIOCLL_CGASTART_64: /* struct in6_cgareq_64 */
822 is64 = (cmd == SIOCLL_CGASTART_64);
823 /*
824 * Convert user cgareq to the kernel form, when appropriate.
825 * This allows the conversion between different data models
826 * to be centralized, so that it can be passed around to other
827 * routines that are expecting the kernel form.
828 */
829 in6_cgareq_copy_from_user(user_data: data, user_is_64: is64, cgareq: &llcgasr);
830
831 /*
832 * NOTE: All the interface specific DLIL attachements
833 * should be done here. They are currently done in
834 * in6_ifattach_cgareq() for the interfaces that
835 * need it.
836 */
837 error = in6_ifattach_llcgareq(ifp, &llcgasr);
838 if (error == 0) {
839 in6_if_up_dad_start(ifp);
840 }
841 break;
842
843 default:
844 VERIFY(0);
845 /* NOTREACHED */
846 }
847
848 return error;
849}
850
851/*
852 * Caller passes in the ioctl data pointer directly via "ifr", with the
853 * expectation that this routine always uses bcopy() or other byte-aligned
854 * memory accesses.
855 */
856static __attribute__((noinline)) int
857in6ctl_gifaddr(struct ifnet *ifp, struct in6_ifaddr *ia, u_long cmd,
858 struct in6_ifreq *ifr)
859{
860 struct sockaddr_in6 addr;
861 int error = 0;
862
863 VERIFY(ifp != NULL);
864
865 if (ia == NULL) {
866 return EADDRNOTAVAIL;
867 }
868
869 switch (cmd) {
870 case SIOCGIFADDR_IN6: /* struct in6_ifreq */
871 IFA_LOCK(&ia->ia_ifa);
872 SOCKADDR_COPY(&ia->ia_addr, &addr, sizeof(addr));
873 IFA_UNLOCK(&ia->ia_ifa);
874 if ((error = sa6_recoverscope(&addr, TRUE)) != 0) {
875 break;
876 }
877 SOCKADDR_COPY(&addr, &ifr->ifr_addr, sizeof(addr));
878 break;
879
880 case SIOCGIFDSTADDR_IN6: /* struct in6_ifreq */
881 if (!(ifp->if_flags & IFF_POINTOPOINT)) {
882 error = EINVAL;
883 break;
884 }
885 /*
886 * XXX: should we check if ifa_dstaddr is NULL and return
887 * an error?
888 */
889 IFA_LOCK(&ia->ia_ifa);
890 SOCKADDR_COPY(&ia->ia_dstaddr, &addr, sizeof(addr));
891 IFA_UNLOCK(&ia->ia_ifa);
892 if ((error = sa6_recoverscope(&addr, TRUE)) != 0) {
893 break;
894 }
895 SOCKADDR_COPY(&addr, &ifr->ifr_dstaddr, sizeof(addr));
896 break;
897
898 default:
899 VERIFY(0);
900 /* NOTREACHED */
901 }
902
903 return error;
904}
905
906/*
907 * Caller passes in the ioctl data pointer directly via "ifr", with the
908 * expectation that this routine always uses bcopy() or other byte-aligned
909 * memory accesses.
910 */
911static __attribute__((noinline)) int
912in6ctl_gifstat(struct ifnet *ifp, u_long cmd, struct in6_ifreq *ifr)
913{
914 int error = 0, index;
915
916 VERIFY(ifp != NULL);
917 index = ifp->if_index;
918
919 switch (cmd) {
920 case SIOCGIFSTAT_IN6: /* struct in6_ifreq */
921 /* N.B.: if_inet6data is never freed once set. */
922 if (IN6_IFEXTRA(ifp) == NULL) {
923 /* return (EAFNOSUPPORT)? */
924 bzero(s: &ifr->ifr_ifru.ifru_stat,
925 n: sizeof(ifr->ifr_ifru.ifru_stat));
926 } else {
927 bcopy(src: &IN6_IFEXTRA(ifp)->in6_ifstat,
928 dst: &ifr->ifr_ifru.ifru_stat,
929 n: sizeof(ifr->ifr_ifru.ifru_stat));
930 }
931 break;
932
933 case SIOCGIFSTAT_ICMP6: /* struct in6_ifreq */
934 /* N.B.: if_inet6data is never freed once set. */
935 if (IN6_IFEXTRA(ifp) == NULL) {
936 /* return (EAFNOSUPPORT)? */
937 bzero(s: &ifr->ifr_ifru.ifru_icmp6stat,
938 n: sizeof(ifr->ifr_ifru.ifru_icmp6stat));
939 } else {
940 bcopy(src: &IN6_IFEXTRA(ifp)->icmp6_ifstat,
941 dst: &ifr->ifr_ifru.ifru_icmp6stat,
942 n: sizeof(ifr->ifr_ifru.ifru_icmp6stat));
943 }
944 break;
945
946 default:
947 VERIFY(0);
948 /* NOTREACHED */
949 }
950
951 return error;
952}
953
954/*
955 * Caller passes in the ioctl data pointer directly via "ifr", with the
956 * expectation that this routine always uses bcopy() or other byte-aligned
957 * memory accesses.
958 */
959static __attribute__((noinline)) int
960in6ctl_alifetime(struct in6_ifaddr *ia, u_long cmd, struct in6_ifreq *ifr,
961 boolean_t p64)
962{
963 uint64_t timenow = net_uptime();
964 struct in6_addrlifetime ia6_lt;
965 struct timeval caltime;
966 int error = 0;
967
968 if (ia == NULL) {
969 return EADDRNOTAVAIL;
970 }
971
972 switch (cmd) {
973 case SIOCGIFALIFETIME_IN6: /* struct in6_ifreq */
974 IFA_LOCK(&ia->ia_ifa);
975 /* retrieve time as calendar time (last arg is 1) */
976 in6ifa_getlifetime(ia, &ia6_lt, 1);
977 if (p64) {
978 struct in6_addrlifetime_64 lt;
979
980 bzero(s: &lt, n: sizeof(lt));
981 lt.ia6t_expire = ia6_lt.ia6t_expire;
982 lt.ia6t_preferred = ia6_lt.ia6t_preferred;
983 lt.ia6t_vltime = ia6_lt.ia6t_vltime;
984 lt.ia6t_pltime = ia6_lt.ia6t_pltime;
985 bcopy(src: &lt, dst: &ifr->ifr_ifru.ifru_lifetime, n: sizeof(ifr->ifr_ifru.ifru_lifetime));
986 } else {
987 struct in6_addrlifetime_32 lt;
988
989 bzero(s: &lt, n: sizeof(lt));
990 lt.ia6t_expire = (uint32_t)ia6_lt.ia6t_expire;
991 lt.ia6t_preferred = (uint32_t)ia6_lt.ia6t_preferred;
992 lt.ia6t_vltime = (uint32_t)ia6_lt.ia6t_vltime;
993 lt.ia6t_pltime = (uint32_t)ia6_lt.ia6t_pltime;
994 /*
995 * 32-bit userland expects a 32-bit in6_addrlifetime to
996 * come back:
997 */
998 bcopy(src: &lt, dst: &ifr->ifr_ifru.ifru_lifetime, n: sizeof(lt));
999 }
1000 IFA_UNLOCK(&ia->ia_ifa);
1001 break;
1002
1003 case SIOCSIFALIFETIME_IN6: /* struct in6_ifreq */
1004 getmicrotime(&caltime);
1005
1006 /* sanity for overflow - beware unsigned */
1007 if (p64) {
1008 struct in6_addrlifetime_64 lt;
1009
1010 bcopy(src: &ifr->ifr_ifru.ifru_lifetime, dst: &lt, n: sizeof(lt));
1011 if (lt.ia6t_vltime != ND6_INFINITE_LIFETIME &&
1012 lt.ia6t_vltime + caltime.tv_sec < caltime.tv_sec) {
1013 error = EINVAL;
1014 break;
1015 }
1016 if (lt.ia6t_pltime != ND6_INFINITE_LIFETIME &&
1017 lt.ia6t_pltime + caltime.tv_sec < caltime.tv_sec) {
1018 error = EINVAL;
1019 break;
1020 }
1021 } else {
1022 struct in6_addrlifetime_32 lt;
1023
1024 bcopy(src: &ifr->ifr_ifru.ifru_lifetime, dst: &lt, n: sizeof(lt));
1025 if (lt.ia6t_vltime != ND6_INFINITE_LIFETIME &&
1026 lt.ia6t_vltime + caltime.tv_sec < caltime.tv_sec) {
1027 error = EINVAL;
1028 break;
1029 }
1030 if (lt.ia6t_pltime != ND6_INFINITE_LIFETIME &&
1031 lt.ia6t_pltime + caltime.tv_sec < caltime.tv_sec) {
1032 error = EINVAL;
1033 break;
1034 }
1035 }
1036
1037 IFA_LOCK(&ia->ia_ifa);
1038 if (p64) {
1039 struct in6_addrlifetime_64 lt;
1040
1041 bcopy(src: &ifr->ifr_ifru.ifru_lifetime, dst: &lt, n: sizeof(lt));
1042 ia6_lt.ia6t_expire = (time_t)lt.ia6t_expire;
1043 ia6_lt.ia6t_preferred = (time_t)lt.ia6t_preferred;
1044 ia6_lt.ia6t_vltime = lt.ia6t_vltime;
1045 ia6_lt.ia6t_pltime = lt.ia6t_pltime;
1046 } else {
1047 struct in6_addrlifetime_32 lt;
1048
1049 bcopy(src: &ifr->ifr_ifru.ifru_lifetime, dst: &lt, n: sizeof(lt));
1050 ia6_lt.ia6t_expire = (uint32_t)lt.ia6t_expire;
1051 ia6_lt.ia6t_preferred = (uint32_t)lt.ia6t_preferred;
1052 ia6_lt.ia6t_vltime = lt.ia6t_vltime;
1053 ia6_lt.ia6t_pltime = lt.ia6t_pltime;
1054 }
1055 /* for sanity */
1056 if (ia6_lt.ia6t_vltime != ND6_INFINITE_LIFETIME) {
1057 ia6_lt.ia6t_expire = (time_t)(timenow + ia6_lt.ia6t_vltime);
1058 } else {
1059 ia6_lt.ia6t_expire = 0;
1060 }
1061
1062 if (ia6_lt.ia6t_pltime != ND6_INFINITE_LIFETIME) {
1063 ia6_lt.ia6t_preferred = (time_t)(timenow + ia6_lt.ia6t_pltime);
1064 } else {
1065 ia6_lt.ia6t_preferred = 0;
1066 }
1067
1068 in6ifa_setlifetime(ia, &ia6_lt);
1069 IFA_UNLOCK(&ia->ia_ifa);
1070 break;
1071
1072 default:
1073 VERIFY(0);
1074 /* NOTREACHED */
1075 }
1076
1077 return error;
1078}
1079
1080static int
1081in6ctl_clat46start(struct ifnet *ifp)
1082{
1083 struct nd_prefix *pr = NULL;
1084 struct nd_prefix *next = NULL;
1085 struct in6_ifaddr *ia6 = NULL;
1086 int error = 0;
1087
1088 if (ifp == lo_ifp) {
1089 return EINVAL;
1090 }
1091 /*
1092 * Traverse the list of prefixes and find the first non-linklocal
1093 * prefix on the interface.
1094 * For that found eligible prefix, configure a CLAT46 reserved address.
1095 */
1096 lck_mtx_lock(nd6_mutex);
1097 for (pr = nd_prefix.lh_first; pr; pr = next) {
1098 next = pr->ndpr_next;
1099
1100 NDPR_LOCK(pr);
1101 if (pr->ndpr_ifp != ifp) {
1102 NDPR_UNLOCK(pr);
1103 continue;
1104 }
1105
1106 if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) {
1107 NDPR_UNLOCK(pr);
1108 continue; /* XXX */
1109 }
1110
1111 if (pr->ndpr_raf_auto == 0) {
1112 NDPR_UNLOCK(pr);
1113 continue;
1114 }
1115
1116 if (pr->ndpr_stateflags & NDPRF_DEFUNCT) {
1117 NDPR_UNLOCK(pr);
1118 continue;
1119 }
1120
1121 if ((pr->ndpr_stateflags & NDPRF_CLAT46) == 0
1122 && pr->ndpr_vltime != 0) {
1123 NDPR_ADDREF(pr); /* Take reference for rest of the processing */
1124 NDPR_UNLOCK(pr);
1125 break;
1126 } else {
1127 NDPR_UNLOCK(pr);
1128 continue;
1129 }
1130 }
1131 lck_mtx_unlock(nd6_mutex);
1132
1133 if (pr != NULL) {
1134 if ((ia6 = in6_pfx_newpersistaddr(pr, FALSE, &error,
1135 TRUE, CLAT46_COLLISION_COUNT_OFFSET)) == NULL) {
1136 nd6log0(error,
1137 "Could not configure CLAT46 address on"
1138 " interface %s.\n", ifp->if_xname);
1139 } else {
1140 IFA_LOCK(&ia6->ia_ifa);
1141 NDPR_LOCK(pr);
1142 ia6->ia6_ndpr = pr;
1143 NDPR_ADDREF(pr); /* for addr reference */
1144 pr->ndpr_stateflags |= NDPRF_CLAT46;
1145 pr->ndpr_addrcnt++;
1146 VERIFY(pr->ndpr_addrcnt != 0);
1147 NDPR_UNLOCK(pr);
1148 IFA_UNLOCK(&ia6->ia_ifa);
1149 ifa_remref(ifa: &ia6->ia_ifa);
1150 ia6 = NULL;
1151 /*
1152 * A newly added address might affect the status
1153 * of other addresses, so we check and update it.
1154 * XXX: what if address duplication happens?
1155 */
1156 lck_mtx_lock(nd6_mutex);
1157 pfxlist_onlink_check();
1158 lck_mtx_unlock(nd6_mutex);
1159 }
1160 NDPR_REMREF(pr);
1161 }
1162 return error;
1163}
1164
1165static int
1166in6ctl_clat46stop(struct ifnet *ifp)
1167{
1168 int error = 0;
1169 struct in6_ifaddr *ia = NULL;
1170
1171 if (ifp == lo_ifp) {
1172 return EINVAL;
1173 }
1174 if ((ifp->if_eflags & IFEF_CLAT46) == 0) {
1175 /* CLAT46 isn't enabled */
1176 goto done;
1177 }
1178 if_clear_eflags(ifp, IFEF_CLAT46);
1179
1180 /* find CLAT46 address and remove it */
1181 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
1182 TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
1183 if (ia->ia_ifa.ifa_ifp != ifp) {
1184 continue;
1185 }
1186 IFA_LOCK(&ia->ia_ifa);
1187 if ((ia->ia6_flags & IN6_IFF_CLAT46) != 0) {
1188 ifa_addref(ifa: &ia->ia_ifa); /* for us */
1189 IFA_UNLOCK(&ia->ia_ifa);
1190 lck_rw_done(lck: &in6_ifaddr_rwlock);
1191 in6_purgeaddr(&ia->ia_ifa);
1192 ifa_remref(ifa: &ia->ia_ifa); /* for us */
1193 goto done;
1194 }
1195 IFA_UNLOCK(&ia->ia_ifa);
1196 }
1197 lck_rw_done(lck: &in6_ifaddr_rwlock);
1198
1199done:
1200 return error;
1201}
1202
1203#define ifa2ia6(ifa) ((struct in6_ifaddr *)(void *)(ifa))
1204
1205/*
1206 * Generic INET6 control operations (ioctl's).
1207 *
1208 * ifp is NULL if not an interface-specific ioctl.
1209 *
1210 * Most of the routines called to handle the ioctls would end up being
1211 * tail-call optimized, which unfortunately causes this routine to
1212 * consume too much stack space; this is the reason for the "noinline"
1213 * attribute used on those routines.
1214 *
1215 * If called directly from within the networking stack (as opposed to via
1216 * pru_control), the socket parameter may be NULL.
1217 */
1218int
1219in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
1220 struct proc *p)
1221{
1222 struct in6_ifreq *ifr = (struct in6_ifreq *)(void *)data;
1223 struct in6_aliasreq sifra, *ifra = NULL;
1224 struct in6_ifaddr *ia = NULL;
1225 struct sockaddr_in6 sin6, *sa6 = NULL;
1226 boolean_t privileged = (proc_suser(p) == 0);
1227 boolean_t p64 = proc_is64bit(p);
1228 boolean_t so_unlocked = FALSE;
1229 int intval, error = 0;
1230
1231 /* In case it's NULL, make sure it came from the kernel */
1232 VERIFY(so != NULL || p == kernproc);
1233
1234 /*
1235 * ioctls which don't require ifp, may require socket.
1236 */
1237 switch (cmd) {
1238 case SIOCAADDRCTL_POLICY: /* struct in6_addrpolicy */
1239 case SIOCDADDRCTL_POLICY: /* struct in6_addrpolicy */
1240 if (!privileged) {
1241 return EPERM;
1242 }
1243 return in6_src_ioctl(cmd, data);
1244 /* NOTREACHED */
1245
1246 case SIOCDRADD_IN6_32: /* struct in6_defrouter_32 */
1247 case SIOCDRADD_IN6_64: /* struct in6_defrouter_64 */
1248 case SIOCDRDEL_IN6_32: /* struct in6_defrouter_32 */
1249 case SIOCDRDEL_IN6_64: /* struct in6_defrouter_64 */
1250 if (!privileged) {
1251 return EPERM;
1252 }
1253 return defrtrlist_ioctl(cmd, data);
1254 /* NOTREACHED */
1255
1256 case SIOCGASSOCIDS32: /* struct so_aidreq32 */
1257 case SIOCGASSOCIDS64: /* struct so_aidreq64 */
1258 return in6ctl_associd(so, cmd, data);
1259 /* NOTREACHED */
1260
1261 case SIOCGCONNIDS32: /* struct so_cidreq32 */
1262 case SIOCGCONNIDS64: /* struct so_cidreq64 */
1263 return in6ctl_connid(so, cmd, data);
1264 /* NOTREACHED */
1265
1266 case SIOCGCONNINFO32: /* struct so_cinforeq32 */
1267 case SIOCGCONNINFO64: /* struct so_cinforeq64 */
1268 return in6ctl_conninfo(so, cmd, data);
1269 /* NOTREACHED */
1270 }
1271
1272 /*
1273 * The rest of ioctls require ifp; reject if we don't have one;
1274 * return ENXIO to be consistent with ifioctl().
1275 */
1276 if (ifp == NULL) {
1277 return ENXIO;
1278 }
1279
1280 /*
1281 * Unlock the socket since ifnet_ioctl() may be invoked by
1282 * one of the ioctl handlers below. Socket will be re-locked
1283 * prior to returning.
1284 */
1285 if (so != NULL) {
1286 socket_unlock(so, refcount: 0);
1287 so_unlocked = TRUE;
1288 }
1289
1290 lck_mtx_lock(lck: &ifp->if_inet6_ioctl_lock);
1291 while (ifp->if_inet6_ioctl_busy) {
1292 (void) msleep(chan: &ifp->if_inet6_ioctl_busy, mtx: &ifp->if_inet6_ioctl_lock, pri: (PZERO - 1),
1293 wmesg: __func__, NULL);
1294 LCK_MTX_ASSERT(&ifp->if_inet6_ioctl_lock, LCK_MTX_ASSERT_OWNED);
1295 }
1296 ifp->if_inet6_ioctl_busy = TRUE;
1297 lck_mtx_unlock(lck: &ifp->if_inet6_ioctl_lock);
1298
1299 /*
1300 * ioctls which require ifp but not interface address.
1301 */
1302 switch (cmd) {
1303 case SIOCAUTOCONF_START: /* struct in6_ifreq */
1304 if (!privileged) {
1305 error = EPERM;
1306 goto done;
1307 }
1308 error = in6_autoconf(ifp, TRUE);
1309 goto done;
1310
1311 case SIOCAUTOCONF_STOP: /* struct in6_ifreq */
1312 if (!privileged) {
1313 error = EPERM;
1314 goto done;
1315 }
1316 error = in6_autoconf(ifp, FALSE);
1317 goto done;
1318
1319 case SIOCLL_START_32: /* struct in6_aliasreq_32 */
1320 case SIOCLL_START_64: /* struct in6_aliasreq_64 */
1321 if (!privileged) {
1322 error = EPERM;
1323 goto done;
1324 }
1325 error = in6ctl_llstart(ifp, cmd, data);
1326 goto done;
1327
1328 case SIOCLL_STOP: /* struct in6_ifreq */
1329 if (!privileged) {
1330 error = EPERM;
1331 goto done;
1332 }
1333 error = in6ctl_llstop(ifp);
1334 goto done;
1335
1336 case SIOCCLAT46_START: /* struct in6_ifreq */
1337 if (!privileged) {
1338 error = EPERM;
1339 goto done;
1340 }
1341 error = in6ctl_clat46start(ifp);
1342 if (error == 0) {
1343 if_set_eflags(ifp, IFEF_CLAT46);
1344 }
1345 goto done;
1346
1347 case SIOCCLAT46_STOP: /* struct in6_ifreq */
1348 if (!privileged) {
1349 error = EPERM;
1350 goto done;
1351 }
1352 error = in6ctl_clat46stop(ifp);
1353 goto done;
1354 case SIOCGETROUTERMODE_IN6: /* struct in6_ifreq */
1355 intval = ifp->if_ipv6_router_mode;
1356 bcopy(src: &intval, dst: &((struct in6_ifreq *)(void *)data)->ifr_intval,
1357 n: sizeof(intval));
1358 goto done;
1359 case SIOCSETROUTERMODE_IN6: /* struct in6_ifreq */
1360 if (!privileged) {
1361 error = EPERM;
1362 goto done;
1363 }
1364 bcopy(src: &((struct in6_ifreq *)(void *)data)->ifr_intval,
1365 dst: &intval, n: sizeof(intval));
1366 switch (intval) {
1367 case IPV6_ROUTER_MODE_DISABLED:
1368 case IPV6_ROUTER_MODE_EXCLUSIVE:
1369 case IPV6_ROUTER_MODE_HYBRID:
1370 break;
1371 default:
1372 error = EINVAL;
1373 goto done;
1374 }
1375 error = in6_setrouter(ifp, (ipv6_router_mode_t)intval);
1376 goto done;
1377
1378 case SIOCPROTOATTACH_IN6_32: /* struct in6_aliasreq_32 */
1379 case SIOCPROTOATTACH_IN6_64: /* struct in6_aliasreq_64 */
1380 if (!privileged) {
1381 error = EPERM;
1382 goto done;
1383 }
1384 error = in6_domifattach(ifp);
1385 goto done;
1386
1387 case SIOCPROTODETACH_IN6: /* struct in6_ifreq */
1388 if (!privileged) {
1389 error = EPERM;
1390 goto done;
1391 }
1392 /* Cleanup interface routes and addresses */
1393 in6_purgeif(ifp);
1394
1395 if ((error = proto_unplumb(PF_INET6, ifp))) {
1396 log(LOG_ERR, "SIOCPROTODETACH_IN6: %s error=%d\n",
1397 if_name(ifp), error);
1398 }
1399 goto done;
1400
1401 case SIOCSNDFLUSH_IN6: /* struct in6_ifreq */
1402 case SIOCSPFXFLUSH_IN6: /* struct in6_ifreq */
1403 case SIOCSRTRFLUSH_IN6: /* struct in6_ifreq */
1404 case SIOCSDEFIFACE_IN6_32: /* struct in6_ndifreq_32 */
1405 case SIOCSDEFIFACE_IN6_64: /* struct in6_ndifreq_64 */
1406 case SIOCSIFINFO_FLAGS: /* struct in6_ndireq */
1407 case SIOCGIFCGAPREP_IN6_32: /* struct in6_cgareq_32 */
1408 case SIOCGIFCGAPREP_IN6_64: /* struct in6_cgareq_64 */
1409 case SIOCSIFCGAPREP_IN6_32: /* struct in6_cgareq_32 */
1410 case SIOCSIFCGAPREP_IN6_64: /* struct in6_cgareq_32 */
1411 if (!privileged) {
1412 error = EPERM;
1413 goto done;
1414 }
1415 OS_FALLTHROUGH;
1416 case OSIOCGIFINFO_IN6: /* struct in6_ondireq */
1417 case SIOCGIFINFO_IN6: /* struct in6_ondireq */
1418 case SIOCGDRLST_IN6_32: /* struct in6_drlist_32 */
1419 case SIOCGDRLST_IN6_64: /* struct in6_drlist_64 */
1420 case SIOCGPRLST_IN6_32: /* struct in6_prlist_32 */
1421 case SIOCGPRLST_IN6_64: /* struct in6_prlist_64 */
1422 case SIOCGNBRINFO_IN6_32: /* struct in6_nbrinfo_32 */
1423 case SIOCGNBRINFO_IN6_64: /* struct in6_nbrinfo_64 */
1424 case SIOCGDEFIFACE_IN6_32: /* struct in6_ndifreq_32 */
1425 case SIOCGDEFIFACE_IN6_64: /* struct in6_ndifreq_64 */
1426 error = nd6_ioctl(cmd, data, ifp);
1427 goto done;
1428
1429 case SIOCSIFPREFIX_IN6: /* struct in6_prefixreq (deprecated) */
1430 case SIOCDIFPREFIX_IN6: /* struct in6_prefixreq (deprecated) */
1431 case SIOCAIFPREFIX_IN6: /* struct in6_rrenumreq (deprecated) */
1432 case SIOCCIFPREFIX_IN6: /* struct in6_rrenumreq (deprecated) */
1433 case SIOCSGIFPREFIX_IN6: /* struct in6_rrenumreq (deprecated) */
1434 case SIOCGIFPREFIX_IN6: /* struct in6_prefixreq (deprecated) */
1435 log(LOG_NOTICE,
1436 "prefix ioctls are now invalidated. "
1437 "please use ifconfig.\n");
1438 error = EOPNOTSUPP;
1439 goto done;
1440
1441 case SIOCSSCOPE6: /* struct in6_ifreq (deprecated) */
1442 case SIOCGSCOPE6: /* struct in6_ifreq (deprecated) */
1443 case SIOCGSCOPE6DEF: /* struct in6_ifreq (deprecated) */
1444 error = EOPNOTSUPP;
1445 goto done;
1446
1447 case SIOCLL_CGASTART_32: /* struct in6_cgareq_32 */
1448 case SIOCLL_CGASTART_64: /* struct in6_cgareq_64 */
1449 if (!privileged) {
1450 error = EPERM;
1451 } else {
1452 error = in6ctl_cgastart(ifp, cmd, data);
1453 }
1454 goto done;
1455
1456 case SIOCGIFSTAT_IN6: /* struct in6_ifreq */
1457 case SIOCGIFSTAT_ICMP6: /* struct in6_ifreq */
1458 error = in6ctl_gifstat(ifp, cmd, ifr);
1459 goto done;
1460 }
1461
1462 /*
1463 * ioctls which require interface address; obtain sockaddr_in6.
1464 */
1465 switch (cmd) {
1466 case SIOCSIFADDR_IN6: /* struct in6_ifreq (deprecated) */
1467 case SIOCSIFDSTADDR_IN6: /* struct in6_ifreq (deprecated) */
1468 case SIOCSIFNETMASK_IN6: /* struct in6_ifreq (deprecated) */
1469 /*
1470 * Since IPv6 allows a node to assign multiple addresses
1471 * on a single interface, SIOCSIFxxx ioctls are deprecated.
1472 */
1473 /* we decided to obsolete this command (20000704) */
1474 error = EOPNOTSUPP;
1475 goto done;
1476
1477 case SIOCAIFADDR_IN6_32: /* struct in6_aliasreq_32 */
1478 case SIOCAIFADDR_IN6_64: /* struct in6_aliasreq_64 */
1479 if (!privileged) {
1480 error = EPERM;
1481 goto done;
1482 }
1483 /*
1484 * Convert user ifra to the kernel form, when appropriate.
1485 * This allows the conversion between different data models
1486 * to be centralized, so that it can be passed around to other
1487 * routines that are expecting the kernel form.
1488 */
1489 ifra = in6_aliasreq_to_native(data,
1490 data_is_64: (cmd == SIOCAIFADDR_IN6_64), dst: &sifra);
1491 SOCKADDR_COPY(&ifra->ifra_addr, &sin6, sizeof(sin6));
1492 sa6 = &sin6;
1493 break;
1494
1495 case SIOCDIFADDR_IN6: /* struct in6_ifreq */
1496 case SIOCSIFALIFETIME_IN6: /* struct in6_ifreq */
1497 if (!privileged) {
1498 error = EPERM;
1499 goto done;
1500 }
1501 OS_FALLTHROUGH;
1502 case SIOCGIFADDR_IN6: /* struct in6_ifreq */
1503 case SIOCGIFDSTADDR_IN6: /* struct in6_ifreq */
1504 case SIOCGIFNETMASK_IN6: /* struct in6_ifreq */
1505 case SIOCGIFAFLAG_IN6: /* struct in6_ifreq */
1506 case SIOCGIFALIFETIME_IN6: /* struct in6_ifreq */
1507 SOCKADDR_COPY(&ifr->ifr_addr, &sin6, sizeof(sin6));
1508 sa6 = &sin6;
1509 break;
1510 case SIOCGIFDSTADDR:
1511 case SIOCSIFDSTADDR:
1512 case SIOCGIFBRDADDR:
1513 case SIOCSIFBRDADDR:
1514 case SIOCGIFNETMASK:
1515 case SIOCSIFNETMASK:
1516 case SIOCGIFADDR:
1517 case SIOCSIFADDR:
1518 case SIOCAIFADDR:
1519 case SIOCDIFADDR:
1520 /* Do not handle these AF_INET commands in AF_INET6 path */
1521 error = EINVAL;
1522 goto done;
1523 }
1524
1525 /*
1526 * Find address for this interface, if it exists.
1527 *
1528 * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
1529 * only, and used the first interface address as the target of other
1530 * operations (without checking ifra_addr). This was because netinet
1531 * code/API assumed at most 1 interface address per interface.
1532 * Since IPv6 allows a node to assign multiple addresses
1533 * on a single interface, we almost always look and check the
1534 * presence of ifra_addr, and reject invalid ones here.
1535 * It also decreases duplicated code among SIOC*_IN6 operations.
1536 */
1537 VERIFY(ia == NULL);
1538 if (sa6 != NULL && sa6->sin6_family == AF_INET6) {
1539 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
1540 if (in6_embedded_scope) {
1541 if (sa6->sin6_addr.s6_addr16[1] == 0) {
1542 /* link ID is not embedded by the user */
1543 sa6->sin6_addr.s6_addr16[1] =
1544 htons(ifp->if_index);
1545 } else if (sa6->sin6_addr.s6_addr16[1] !=
1546 htons(ifp->if_index)) {
1547 error = EINVAL; /* link ID contradicts */
1548 goto done;
1549 }
1550 if (sa6->sin6_scope_id) {
1551 if (sa6->sin6_scope_id !=
1552 (u_int32_t)ifp->if_index) {
1553 error = EINVAL;
1554 goto done;
1555 }
1556 sa6->sin6_scope_id = 0; /* XXX: good way? */
1557 }
1558 } else {
1559 if (sa6->sin6_scope_id == IFSCOPE_NONE) {
1560 sa6->sin6_scope_id = ifp->if_index;
1561 } else if (sa6->sin6_scope_id != ifp->if_index) {
1562 error = EINVAL; /* link ID contradicts */
1563 goto done;
1564 }
1565 }
1566 }
1567 /*
1568 * Any failures from this point on must take into account
1569 * a non-NULL "ia" with an outstanding reference count, and
1570 * therefore requires ifa_remref. Jump to "done" label
1571 * instead of calling return if "ia" is valid.
1572 */
1573 ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
1574 }
1575
1576 /*
1577 * SIOCDIFADDR_IN6/SIOCAIFADDR_IN6 specific tests.
1578 */
1579 switch (cmd) {
1580 case SIOCDIFADDR_IN6: /* struct in6_ifreq */
1581 if (ia == NULL) {
1582 error = EADDRNOTAVAIL;
1583 goto done;
1584 }
1585 OS_FALLTHROUGH;
1586 case SIOCAIFADDR_IN6_32: /* struct in6_aliasreq_32 */
1587 case SIOCAIFADDR_IN6_64: /* struct in6_aliasreq_64 */
1588 VERIFY(sa6 != NULL);
1589 /*
1590 * We always require users to specify a valid IPv6 address for
1591 * the corresponding operation. Use "sa6" instead of "ifra"
1592 * since SIOCDIFADDR_IN6 falls thru above.
1593 */
1594 if (sa6->sin6_family != AF_INET6 ||
1595 sa6->sin6_len != sizeof(struct sockaddr_in6)) {
1596 error = EAFNOSUPPORT;
1597 goto done;
1598 }
1599
1600 if ((cmd == SIOCAIFADDR_IN6_32 || cmd == SIOCAIFADDR_IN6_64) &&
1601 (IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) ||
1602 IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr) ||
1603 IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr) ||
1604 IN6_IS_ADDR_V4COMPAT(&sa6->sin6_addr))) {
1605 error = EINVAL;
1606 goto done;
1607 }
1608 break;
1609 }
1610
1611 /*
1612 * And finally process address-related ioctls.
1613 */
1614 switch (cmd) {
1615 case SIOCGIFADDR_IN6: /* struct in6_ifreq */
1616 /* This interface is basically deprecated. use SIOCGIFCONF. */
1617 /* FALLTHRU */
1618 case SIOCGIFDSTADDR_IN6: /* struct in6_ifreq */
1619 error = in6ctl_gifaddr(ifp, ia, cmd, ifr);
1620 break;
1621
1622 case SIOCGIFNETMASK_IN6: /* struct in6_ifreq */
1623 if (ia != NULL) {
1624 IFA_LOCK(&ia->ia_ifa);
1625 SOCKADDR_COPY(&ia->ia_prefixmask, &ifr->ifr_addr,
1626 sizeof(struct sockaddr_in6));
1627 IFA_UNLOCK(&ia->ia_ifa);
1628 } else {
1629 error = EADDRNOTAVAIL;
1630 }
1631 break;
1632
1633 case SIOCGIFAFLAG_IN6: /* struct in6_ifreq */
1634 if (ia != NULL) {
1635 IFA_LOCK(&ia->ia_ifa);
1636 bcopy(src: &ia->ia6_flags, dst: &ifr->ifr_ifru.ifru_flags6,
1637 n: sizeof(ifr->ifr_ifru.ifru_flags6));
1638 IFA_UNLOCK(&ia->ia_ifa);
1639 } else {
1640 error = EADDRNOTAVAIL;
1641 }
1642 break;
1643
1644 case SIOCGIFALIFETIME_IN6: /* struct in6_ifreq */
1645 case SIOCSIFALIFETIME_IN6: /* struct in6_ifreq */
1646 error = in6ctl_alifetime(ia, cmd, ifr, p64);
1647 break;
1648
1649 case SIOCAIFADDR_IN6_32: /* struct in6_aliasreq_32 */
1650 case SIOCAIFADDR_IN6_64: /* struct in6_aliasreq_64 */
1651 error = in6ctl_aifaddr(ifp, ifra);
1652 break;
1653
1654 case SIOCDIFADDR_IN6:
1655 in6ctl_difaddr(ifp, ia);
1656 break;
1657
1658 default:
1659 error = ifnet_ioctl(interface: ifp, PF_INET6, ioctl_code: cmd, ioctl_arg: data);
1660 break;
1661 }
1662
1663done:
1664 if (ifp != NULL) {
1665 lck_mtx_lock(lck: &ifp->if_inet6_ioctl_lock);
1666 ifp->if_inet6_ioctl_busy = FALSE;
1667 lck_mtx_unlock(lck: &ifp->if_inet6_ioctl_lock);
1668 wakeup(chan: &ifp->if_inet6_ioctl_busy);
1669 }
1670
1671 if (ia != NULL) {
1672 ifa_remref(ifa: &ia->ia_ifa);
1673 }
1674 if (so_unlocked) {
1675 socket_lock(so, refcount: 0);
1676 }
1677
1678 return error;
1679}
1680
1681static __attribute__((noinline)) int
1682in6ctl_aifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra)
1683{
1684 int i, error, addtmp;
1685 uint8_t plen;
1686 struct nd_prefix pr0, *pr;
1687 struct in6_ifaddr *ia;
1688
1689 VERIFY(ifp != NULL && ifra != NULL);
1690 ia = NULL;
1691
1692 /*
1693 * XXX This interface is not meant to be used for static LLA
1694 * configuration.
1695 * Instead one can use SIOCLL_START can be used to configure LLA
1696 * statically.
1697 * For bin-compat reasons though, allow it for now and only make
1698 * sure that scope gets communicated correctly.
1699 */
1700 if (IN6_IS_ADDR_LINKLOCAL(&ifra->ifra_addr.sin6_addr)) {
1701 if (in6_embedded_scope) {
1702 ifra->ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1703 } else {
1704 /*
1705 * XXX May be we should rather also check if sin6_scope_id
1706 * is already set or enforce if set that it is same
1707 * as interface index?
1708 * For now to avoid any unintended consequence, just use
1709 * interface index and set sin6_scope_id.
1710 * Also should we just prohibit this interface to configure
1711 * additional link local and limti LLA configuration through
1712 * other *_start ioctls?
1713 */
1714 ifra->ifra_addr.sin6_addr.s6_addr16[1] = 0;
1715 ifra->ifra_addr.sin6_scope_id = ifp->if_index;
1716 }
1717 }
1718
1719 /* Attempt to attach the protocol, in case it isn't attached */
1720 error = in6_domifattach(ifp);
1721 if (error == 0) {
1722 /* PF_INET6 wasn't previously attached */
1723 error = in6_ifattach_aliasreq(ifp, NULL, NULL);
1724 if (error != 0) {
1725 goto done;
1726 }
1727
1728 in6_if_up_dad_start(ifp);
1729 } else if (error != EEXIST) {
1730 goto done;
1731 }
1732
1733 /*
1734 * First, make or update the interface address structure, and link it
1735 * to the list.
1736 */
1737 error = in6_update_ifa(ifp, ifra, 0, &ia);
1738 if (error != 0) {
1739 goto done;
1740 }
1741 VERIFY(ia != NULL);
1742
1743 /* Now, make the prefix on-link on the interface. */
1744 plen = (uint8_t)in6_mask2len(mask: &ifra->ifra_prefixmask.sin6_addr, NULL);
1745 if (plen == 128) {
1746 goto done;
1747 }
1748
1749 /*
1750 * NOTE: We'd rather create the prefix before the address, but we need
1751 * at least one address to install the corresponding interface route,
1752 * so we configure the address first.
1753 */
1754
1755 /*
1756 * Convert mask to prefix length (prefixmask has already been validated
1757 * in in6_update_ifa().
1758 */
1759 bzero(s: &pr0, n: sizeof(pr0));
1760 pr0.ndpr_plen = plen;
1761 pr0.ndpr_ifp = ifp;
1762 pr0.ndpr_prefix = ifra->ifra_addr;
1763 pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
1764
1765 /* apply the mask for safety. */
1766 for (i = 0; i < 4; i++) {
1767 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
1768 ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
1769 }
1770
1771 /*
1772 * Since we don't have an API to set prefix (not address) lifetimes, we
1773 * just use the same lifetimes as addresses. The (temporarily)
1774 * installed lifetimes can be overridden by later advertised RAs (when
1775 * accept_rtadv is non 0), which is an intended behavior.
1776 */
1777 pr0.ndpr_raf_onlink = 1; /* should be configurable? */
1778 pr0.ndpr_raf_auto = !!(ifra->ifra_flags & IN6_IFF_AUTOCONF);
1779 if (ifra->ifra_flags & (IN6_IFF_AUTOCONF | IN6_IFF_DYNAMIC)) {
1780 pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
1781 pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
1782 } else {
1783 pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
1784 pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
1785 }
1786 pr0.ndpr_stateflags |= NDPRF_STATIC;
1787 lck_mtx_init(lck: &pr0.ndpr_lock, grp: &ifa_mtx_grp, attr: &ifa_mtx_attr);
1788
1789 /* add the prefix if there's none. */
1790 if ((pr = nd6_prefix_lookup(&pr0, ND6_PREFIX_EXPIRY_NEVER)) == NULL) {
1791 /*
1792 * nd6_prelist_add will install the corresponding interface
1793 * route.
1794 */
1795 error = nd6_prelist_add(&pr0, NULL, &pr, FALSE);
1796 if (error != 0) {
1797 goto done;
1798 }
1799
1800 if (pr == NULL) {
1801 log(LOG_ERR, "%s: nd6_prelist_add okay, but"
1802 " no prefix.\n", __func__);
1803 error = EINVAL;
1804 goto done;
1805 }
1806 }
1807
1808 IFA_LOCK(&ia->ia_ifa);
1809
1810 /* if this is a new autoconfed addr */
1811 addtmp = FALSE;
1812 if (ia->ia6_ndpr == NULL) {
1813 NDPR_LOCK(pr);
1814 ++pr->ndpr_addrcnt;
1815 if (!(ia->ia6_flags & IN6_IFF_NOTMANUAL)) {
1816 ++pr->ndpr_manual_addrcnt;
1817 VERIFY(pr->ndpr_manual_addrcnt != 0);
1818 }
1819 VERIFY(pr->ndpr_addrcnt != 0);
1820 ia->ia6_ndpr = pr;
1821 NDPR_ADDREF(pr); /* for addr reference */
1822
1823 /*
1824 * If this is the first autoconf address from the prefix,
1825 * create a temporary address as well (when specified).
1826 */
1827 if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0 &&
1828 ip6_use_tempaddr &&
1829 pr->ndpr_addrcnt == 1 &&
1830 (!IN6_IS_ADDR_UNIQUE_LOCAL(&ia->ia_addr.sin6_addr)
1831 || ip6_ula_use_tempaddr)) {
1832 addtmp = true;
1833 }
1834 NDPR_UNLOCK(pr);
1835 }
1836
1837 IFA_UNLOCK(&ia->ia_ifa);
1838
1839 if (addtmp) {
1840 int e;
1841 e = in6_tmpifadd(ia, 1);
1842 if (e != 0) {
1843 log(LOG_NOTICE, "%s: failed to create a"
1844 " temporary address, error=%d\n",
1845 __func__, e);
1846 }
1847 }
1848
1849 /*
1850 * This might affect the status of autoconfigured addresses, that is,
1851 * this address might make other addresses detached.
1852 */
1853 lck_mtx_lock(nd6_mutex);
1854 pfxlist_onlink_check();
1855 lck_mtx_unlock(nd6_mutex);
1856
1857 /* Drop use count held above during lookup/add */
1858 NDPR_REMREF(pr);
1859
1860done:
1861 if (ia != NULL) {
1862 ifa_remref(ifa: &ia->ia_ifa);
1863 }
1864 return error;
1865}
1866
1867static __attribute__((noinline)) void
1868in6ctl_difaddr(struct ifnet *ifp, struct in6_ifaddr *ia)
1869{
1870 int i = 0;
1871 struct nd_prefix pr0, *pr;
1872
1873 VERIFY(ifp != NULL && ia != NULL);
1874
1875 /*
1876 * If the address being deleted is the only one that owns
1877 * the corresponding prefix, expire the prefix as well.
1878 * XXX: theoretically, we don't have to worry about such
1879 * relationship, since we separate the address management
1880 * and the prefix management. We do this, however, to provide
1881 * as much backward compatibility as possible in terms of
1882 * the ioctl operation.
1883 * Note that in6_purgeaddr() will decrement ndpr_addrcnt.
1884 */
1885 IFA_LOCK(&ia->ia_ifa);
1886 bzero(s: &pr0, n: sizeof(pr0));
1887 pr0.ndpr_ifp = ifp;
1888 pr0.ndpr_plen = (uint8_t)in6_mask2len(mask: &ia->ia_prefixmask.sin6_addr, NULL);
1889 if (pr0.ndpr_plen == 128) {
1890 IFA_UNLOCK(&ia->ia_ifa);
1891 goto purgeaddr;
1892 }
1893 pr0.ndpr_prefix = ia->ia_addr;
1894 pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
1895 for (i = 0; i < 4; i++) {
1896 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
1897 ia->ia_prefixmask.sin6_addr.s6_addr32[i];
1898 }
1899 IFA_UNLOCK(&ia->ia_ifa);
1900
1901 if ((pr = nd6_prefix_lookup(&pr0, ND6_PREFIX_EXPIRY_UNSPEC)) != NULL) {
1902 IFA_LOCK(&ia->ia_ifa);
1903 NDPR_LOCK(pr);
1904 if (pr->ndpr_addrcnt == 1) {
1905 /* XXX: just for expiration */
1906 pr->ndpr_expire = 1;
1907 }
1908 NDPR_UNLOCK(pr);
1909 IFA_UNLOCK(&ia->ia_ifa);
1910
1911 /* Drop use count held above during lookup */
1912 NDPR_REMREF(pr);
1913 }
1914
1915purgeaddr:
1916 in6_purgeaddr(&ia->ia_ifa);
1917}
1918
1919static __attribute__((noinline)) int
1920in6_autoconf(struct ifnet *ifp, int enable)
1921{
1922 int error = 0;
1923
1924 VERIFY(ifp != NULL);
1925
1926 if (ifp->if_flags & IFF_LOOPBACK) {
1927 return EINVAL;
1928 }
1929
1930 if (enable) {
1931 /*
1932 * An interface in IPv6 router mode implies that it
1933 * is either configured with a static IP address or
1934 * autoconfigured via a locally-generated RA. Prevent
1935 * SIOCAUTOCONF_START from being set in that mode.
1936 */
1937 ifnet_lock_exclusive(ifp);
1938 if (ifp->if_ipv6_router_mode == IPV6_ROUTER_MODE_EXCLUSIVE) {
1939 if_clear_eflags(ifp, IFEF_ACCEPT_RTADV);
1940 error = EBUSY;
1941 } else {
1942 if_set_eflags(ifp, IFEF_ACCEPT_RTADV);
1943 }
1944 ifnet_lock_done(ifp);
1945 } else {
1946 struct in6_ifaddr *ia = NULL;
1947
1948 if_clear_eflags(ifp, IFEF_ACCEPT_RTADV);
1949
1950 /* Remove autoconfigured address from interface */
1951 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
1952 boolean_t from_begining = TRUE;
1953 while (from_begining) {
1954 from_begining = FALSE;
1955 TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
1956 if (ia->ia_ifa.ifa_ifp != ifp) {
1957 continue;
1958 }
1959 IFA_LOCK(&ia->ia_ifa);
1960 if (ia->ia6_flags & IN6_IFF_AUTOCONF) {
1961 ifa_addref(ifa: &ia->ia_ifa); /* for us */
1962 IFA_UNLOCK(&ia->ia_ifa);
1963 lck_rw_done(lck: &in6_ifaddr_rwlock);
1964 in6_purgeaddr(&ia->ia_ifa);
1965 ifa_remref(ifa: &ia->ia_ifa); /* for us */
1966 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
1967 /*
1968 * Purging the address caused in6_ifaddr_rwlock
1969 * to be dropped and reacquired;
1970 * therefore search again from the beginning
1971 * of in6_ifaddrs list.
1972 */
1973 from_begining = TRUE;
1974 break;
1975 }
1976 IFA_UNLOCK(&ia->ia_ifa);
1977 }
1978 }
1979 lck_rw_done(lck: &in6_ifaddr_rwlock);
1980 }
1981 return error;
1982}
1983
1984/*
1985 * Handle SIOCSETROUTERMODE_IN6 to set the IPv6 router mode on the interface
1986 * Entering or exiting IPV6_ROUTER_MODE_EXCLUSIVE will result in the removal of
1987 * autoconfigured IPv6 addresses on the interface.
1988 */
1989static __attribute__((noinline)) int
1990in6_setrouter(struct ifnet *ifp, ipv6_router_mode_t mode)
1991{
1992 int error = 0;
1993 ipv6_router_mode_t prev_mode;
1994
1995 VERIFY(ifp != NULL);
1996
1997 if (ifp->if_flags & IFF_LOOPBACK) {
1998 return ENODEV;
1999 }
2000
2001 prev_mode = ifp->if_ipv6_router_mode;
2002 if (prev_mode == mode) {
2003 /* no mode change, there's nothing to do */
2004 return 0;
2005 }
2006 if (mode == IPV6_ROUTER_MODE_EXCLUSIVE) {
2007 struct nd_ifinfo *ndi = NULL;
2008
2009 ndi = ND_IFINFO(ifp);
2010 if (ndi != NULL && ndi->initialized) {
2011 lck_mtx_lock(lck: &ndi->lock);
2012 if (ndi->flags & ND6_IFF_PROXY_PREFIXES) {
2013 /* No proxy if we are an advertising router */
2014 ndi->flags &= ~ND6_IFF_PROXY_PREFIXES;
2015 lck_mtx_unlock(lck: &ndi->lock);
2016 (void) nd6_if_prproxy(ifp, FALSE);
2017 } else {
2018 lck_mtx_unlock(lck: &ndi->lock);
2019 }
2020 }
2021 }
2022
2023 ifp->if_ipv6_router_mode = mode;
2024 lck_mtx_lock(nd6_mutex);
2025 defrouter_select(ifp, NULL);
2026 lck_mtx_unlock(nd6_mutex);
2027 if_allmulti(ifp, (mode == IPV6_ROUTER_MODE_EXCLUSIVE));
2028 if (mode == IPV6_ROUTER_MODE_EXCLUSIVE ||
2029 (prev_mode == IPV6_ROUTER_MODE_EXCLUSIVE
2030 && mode == IPV6_ROUTER_MODE_DISABLED)) {
2031 error = in6_autoconf(ifp, FALSE);
2032 }
2033 return error;
2034}
2035
2036static int
2037in6_to_kamescope(struct sockaddr_in6 *sin6, struct ifnet *ifp)
2038{
2039 struct sockaddr_in6 tmp;
2040 int error, id;
2041
2042 VERIFY(sin6 != NULL);
2043 tmp = *sin6;
2044
2045 error = in6_recoverscope(&tmp, &sin6->sin6_addr, ifp);
2046 if (error != 0) {
2047 return error;
2048 }
2049
2050 id = in6_addr2scopeid(ifp, &tmp.sin6_addr);
2051 if (tmp.sin6_scope_id == 0) {
2052 tmp.sin6_scope_id = id;
2053 } else if (tmp.sin6_scope_id != id) {
2054 return EINVAL; /* scope ID mismatch. */
2055 }
2056 error = in6_embedscope(&tmp.sin6_addr, &tmp, NULL, NULL, NULL, IN6_NULL_IF_EMBEDDED_SCOPE(&tmp.sin6_scope_id));
2057 if (error != 0) {
2058 return error;
2059 }
2060
2061 if (in6_embedded_scope || !IN6_IS_SCOPE_EMBED(&tmp.sin6_addr)) {
2062 tmp.sin6_scope_id = 0;
2063 }
2064 *sin6 = tmp;
2065 return 0;
2066}
2067
2068/*
2069 * When the address is being configured we should clear out certain flags
2070 * coming in from the caller.
2071 */
2072#define IN6_IFF_CLR_ADDR_FLAG_MASK (~(IN6_IFF_DEPRECATED | IN6_IFF_DETACHED | IN6_IFF_DUPLICATED))
2073
2074static int
2075in6_ifaupdate_aux(struct in6_ifaddr *ia, struct ifnet *ifp, int ifaupflags)
2076{
2077 struct sockaddr_in6 mltaddr, mltmask;
2078 struct in6_addr llsol;
2079 struct ifaddr *ifa;
2080 struct in6_multi *in6m_sol;
2081 struct in6_multi_mship *imm;
2082 struct rtentry *rt;
2083 int delay, error = 0;
2084
2085 VERIFY(ifp != NULL && ia != NULL);
2086 ifa = &ia->ia_ifa;
2087 in6m_sol = NULL;
2088
2089 nd6log2(debug, "%s - %s ifp %s ia6_flags 0x%x ifaupflags 0x%x\n",
2090 __func__,
2091 ip6_sprintf(&ia->ia_addr.sin6_addr),
2092 if_name(ia->ia_ifp),
2093 ia->ia6_flags,
2094 ifaupflags);
2095
2096 /*
2097 * Just to be safe, always clear certain flags when address
2098 * is being configured
2099 */
2100 ia->ia6_flags &= IN6_IFF_CLR_ADDR_FLAG_MASK;
2101
2102 /*
2103 * Mark the address as tentative before joining multicast addresses,
2104 * so that corresponding MLD responses would not have a tentative
2105 * source address.
2106 */
2107 if (in6if_do_dad(ifp)) {
2108 in6_ifaddr_set_dadprogress(ia);
2109 /*
2110 * Do not delay sending neighbor solicitations when using optimistic
2111 * duplicate address detection, c.f. RFC 4429.
2112 */
2113 if (ia->ia6_flags & IN6_IFF_OPTIMISTIC) {
2114 ifaupflags &= ~IN6_IFAUPDATE_DADDELAY;
2115 } else {
2116 ifaupflags |= IN6_IFAUPDATE_DADDELAY;
2117 }
2118 } else {
2119 /*
2120 * If the interface has been marked to not perform
2121 * DAD, make sure to reset DAD in progress flags
2122 * that may come in from the caller.
2123 */
2124 ia->ia6_flags &= ~IN6_IFF_DADPROGRESS;
2125 }
2126
2127 /* Join necessary multicast groups */
2128 if ((ifp->if_flags & IFF_MULTICAST) != 0) {
2129 /* join solicited multicast addr for new host id */
2130 bzero(s: &llsol, n: sizeof(struct in6_addr));
2131 llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
2132 llsol.s6_addr32[1] = 0;
2133 llsol.s6_addr32[2] = htonl(1);
2134 llsol.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];
2135 llsol.s6_addr8[12] = 0xff;
2136 if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
2137 /* XXX: should not happen */
2138 log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
2139 goto unwind;
2140 }
2141 delay = 0;
2142 if ((ifaupflags & IN6_IFAUPDATE_DADDELAY)) {
2143 /*
2144 * We need a random delay for DAD on the address
2145 * being configured. It also means delaying
2146 * transmission of the corresponding MLD report to
2147 * avoid report collision. [RFC 4862]
2148 */
2149 delay = random() % MAX_RTR_SOLICITATION_DELAY;
2150 }
2151 imm = in6_joingroup(ifp, &llsol, &error, delay);
2152 if (imm == NULL) {
2153 nd6log(info,
2154 "%s: addmulti failed for %s on %s (errno=%d)\n",
2155 __func__, ip6_sprintf(&llsol), if_name(ifp),
2156 error);
2157 VERIFY(error != 0);
2158 goto unwind;
2159 }
2160 in6m_sol = imm->i6mm_maddr;
2161 /* take a refcount for this routine */
2162 IN6M_ADDREF(in6m_sol);
2163
2164 IFA_LOCK_SPIN(ifa);
2165 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
2166 IFA_UNLOCK(ifa);
2167
2168 SOCKADDR_ZERO(&mltmask, sizeof(mltmask));
2169 mltmask.sin6_len = sizeof(struct sockaddr_in6);
2170 mltmask.sin6_family = AF_INET6;
2171 mltmask.sin6_addr = in6mask32;
2172#define MLTMASK_LEN 4 /* mltmask's masklen (=32bit=4octet) */
2173
2174 /*
2175 * join link-local all-nodes address
2176 */
2177 SOCKADDR_ZERO(&mltaddr, sizeof(mltaddr));
2178 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
2179 mltaddr.sin6_family = AF_INET6;
2180 mltaddr.sin6_addr = in6addr_linklocal_allnodes;
2181 if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, IN6_NULL_IF_EMBEDDED_SCOPE(&mltaddr.sin6_scope_id))) != 0) {
2182 goto unwind; /* XXX: should not fail */
2183 }
2184 /*
2185 * XXX: do we really need this automatic routes?
2186 * We should probably reconsider this stuff. Most applications
2187 * actually do not need the routes, since they usually specify
2188 * the outgoing interface.
2189 */
2190 rt = rtalloc1_scoped(SA(&mltaddr), 0, 0UL,
2191 ia->ia_ifp->if_index);
2192 if (rt) {
2193 if (memcmp(s1: &mltaddr.sin6_addr, s2: &SIN6(rt_key(rt))->sin6_addr, MLTMASK_LEN)) {
2194 rtfree(rt);
2195 rt = NULL;
2196 }
2197 }
2198 if (!rt) {
2199 error = rtrequest_scoped(RTM_ADD,
2200 SA(&mltaddr),
2201 SA(&ia->ia_addr),
2202 SA(&mltmask), RTF_UP | RTF_CLONING,
2203 NULL, ia->ia_ifp->if_index);
2204 if (error) {
2205 goto unwind;
2206 }
2207 } else {
2208 rtfree(rt);
2209 }
2210
2211 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
2212 if (!imm) {
2213 nd6log(info,
2214 "%s: addmulti failed for %s on %s (errno=%d)\n",
2215 __func__, ip6_sprintf(&mltaddr.sin6_addr),
2216 if_name(ifp), error);
2217 VERIFY(error != 0);
2218 goto unwind;
2219 }
2220 IFA_LOCK_SPIN(ifa);
2221 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
2222 IFA_UNLOCK(ifa);
2223
2224 /*
2225 * join node information group address
2226 */
2227#define hostnamelen strlen(hostname)
2228 delay = 0;
2229 if ((ifaupflags & IN6_IFAUPDATE_DADDELAY)) {
2230 /*
2231 * The spec doesn't say anything about delay for this
2232 * group, but the same logic should apply.
2233 */
2234 delay = random() % MAX_RTR_SOLICITATION_DELAY;
2235 }
2236 lck_mtx_lock(lck: &hostname_lock);
2237 int n = in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr, IN6_NULL_IF_EMBEDDED_SCOPE(&mltaddr.sin6_scope_id));
2238 lck_mtx_unlock(lck: &hostname_lock);
2239 if (n == 0) {
2240 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
2241 delay); /* XXX jinmei */
2242 if (!imm) {
2243 nd6log(info,
2244 "%s: addmulti failed for %s on %s "
2245 "(errno=%d)\n",
2246 __func__, ip6_sprintf(&mltaddr.sin6_addr),
2247 if_name(ifp), error);
2248 /* XXX not very fatal, go on... */
2249 error = 0;
2250 } else {
2251 IFA_LOCK_SPIN(ifa);
2252 LIST_INSERT_HEAD(&ia->ia6_memberships,
2253 imm, i6mm_chain);
2254 IFA_UNLOCK(ifa);
2255 }
2256 }
2257#undef hostnamelen
2258
2259 /*
2260 * join interface-local all-nodes address.
2261 * (ff01::1%ifN, and ff01::%ifN/32)
2262 */
2263 mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
2264 if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, IN6_NULL_IF_EMBEDDED_SCOPE(&mltaddr.sin6_scope_id))) != 0) {
2265 goto unwind; /* XXX: should not fail */
2266 }
2267 /* XXX: again, do we really need the route? */
2268 rt = rtalloc1_scoped(SA(&mltaddr), 0, 0UL,
2269 ia->ia_ifp->if_index);
2270 if (rt) {
2271 if (memcmp(s1: &mltaddr.sin6_addr, s2: &(SIN6(rt_key(rt)))->sin6_addr, MLTMASK_LEN)) {
2272 rtfree(rt);
2273 rt = NULL;
2274 }
2275 }
2276 if (!rt) {
2277 error = rtrequest_scoped(RTM_ADD,
2278 SA(&mltaddr),
2279 SA(&ia->ia_addr),
2280 SA(&mltmask), RTF_UP | RTF_CLONING,
2281 NULL, ia->ia_ifp->if_index);
2282 if (error) {
2283 goto unwind;
2284 }
2285 } else {
2286 rtfree(rt);
2287 }
2288
2289 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
2290 if (!imm) {
2291 nd6log(info,
2292 "%s: addmulti failed for %s on %s (errno=%d)\n",
2293 __func__, ip6_sprintf(&mltaddr.sin6_addr),
2294 if_name(ifp), error);
2295 VERIFY(error != 0);
2296 goto unwind;
2297 }
2298 IFA_LOCK(ifa);
2299 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
2300 IFA_UNLOCK(ifa);
2301#undef MLTMASK_LEN
2302
2303 /*
2304 * create a ff00::/8 route
2305 */
2306 SOCKADDR_ZERO(&mltmask, sizeof(mltmask));
2307 mltmask.sin6_len = sizeof(struct sockaddr_in6);
2308 mltmask.sin6_family = AF_INET6;
2309 mltmask.sin6_addr = in6mask8;
2310#define MLTMASK_LEN_8_BITS 1 /* ff00::/8 mltmask's masklen (=8bit=1octet) */
2311
2312 SOCKADDR_ZERO(&mltaddr, sizeof(mltaddr));
2313 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
2314 mltaddr.sin6_family = AF_INET6;
2315 mltaddr.sin6_addr = in6addr_multicast_prefix;
2316
2317 rt = rtalloc1_scoped(SA(&mltaddr), 0, 0UL,
2318 ia->ia_ifp->if_index);
2319 if (rt) {
2320 if (memcmp(s1: &mltaddr.sin6_addr, s2: &(SIN6(rt_key(rt)))->sin6_addr, MLTMASK_LEN_8_BITS)) {
2321 rtfree(rt);
2322 rt = NULL;
2323 }
2324 }
2325 if (!rt) {
2326 error = rtrequest_scoped(RTM_ADD,
2327 SA(&mltaddr),
2328 SA(&ia->ia_addr),
2329 SA(&mltmask), RTF_UP | RTF_CLONING,
2330 NULL, ia->ia_ifp->if_index);
2331 if (error) {
2332 goto unwind;
2333 }
2334 } else {
2335 rtfree(rt);
2336 }
2337 }
2338#undef MLTMASK_LEN_8_BITS
2339
2340 /* Ensure nd6_service() is scheduled as soon as it's convenient */
2341 ++nd6_sched_timeout_want;
2342
2343 /*
2344 * Perform DAD, if:
2345 * * Interface is marked to perform DAD, AND
2346 * * Address is not marked to skip DAD, AND
2347 * * Address is in a pre-DAD state (Tentative or Optimistic)
2348 */
2349 IFA_LOCK_SPIN(ifa);
2350 if (in6if_do_dad(ifp) && (ia->ia6_flags & IN6_IFF_NODAD) == 0 &&
2351 (ia->ia6_flags & IN6_IFF_DADPROGRESS) != 0) {
2352 int mindelay, maxdelay;
2353 int *delayptr, delayval;
2354
2355 IFA_UNLOCK(ifa);
2356 delayptr = NULL;
2357 /*
2358 * Avoid the DAD delay if the caller wants us to skip it.
2359 * This is not compliant with RFC 2461, but it's only being
2360 * used for signalling and not for actual DAD.
2361 */
2362 if ((ifaupflags & IN6_IFAUPDATE_DADDELAY) &&
2363 !(ia->ia6_flags & IN6_IFF_SWIFTDAD)) {
2364 /*
2365 * We need to impose a delay before sending an NS
2366 * for DAD. Check if we also needed a delay for the
2367 * corresponding MLD message. If we did, the delay
2368 * should be larger than the MLD delay (this could be
2369 * relaxed a bit, but this simple logic is at least
2370 * safe).
2371 */
2372 mindelay = 0;
2373 if (in6m_sol != NULL) {
2374 IN6M_LOCK(in6m_sol);
2375 if (in6m_sol->in6m_state ==
2376 MLD_REPORTING_MEMBER) {
2377 mindelay = in6m_sol->in6m_timer;
2378 }
2379 IN6M_UNLOCK(in6m_sol);
2380 }
2381 maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
2382 if (maxdelay - mindelay == 0) {
2383 delayval = 0;
2384 } else {
2385 delayval =
2386 (random() % (maxdelay - mindelay)) +
2387 mindelay;
2388 }
2389 delayptr = &delayval;
2390 }
2391
2392 nd6_dad_start((struct ifaddr *)ia, delayptr);
2393 } else {
2394 IFA_UNLOCK(ifa);
2395 }
2396
2397 goto done;
2398
2399unwind:
2400 VERIFY(error != 0);
2401 in6_purgeaddr(&ia->ia_ifa);
2402
2403done:
2404 /* release reference held for this routine */
2405 if (in6m_sol != NULL) {
2406 IN6M_REMREF(in6m_sol);
2407 }
2408 return error;
2409}
2410
2411/*
2412 * Request an IPv6 interface address. If the address is new, then it will be
2413 * constructed and appended to the interface address chains. The interface
2414 * address structure is optionally returned with a reference for the caller.
2415 */
2416int
2417in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, int ifaupflags,
2418 struct in6_ifaddr **iar)
2419{
2420 struct in6_addrlifetime ia6_lt;
2421 struct in6_ifaddr *ia;
2422 struct ifaddr *ifa;
2423 struct ifaddr *xifa;
2424 struct in6_addrlifetime *lt;
2425 uint64_t timenow;
2426 int plen, error;
2427
2428 /* Sanity check parameters and initialize locals */
2429 VERIFY(ifp != NULL && ifra != NULL && iar != NULL);
2430 ia = NULL;
2431 ifa = NULL;
2432 error = 0;
2433
2434 /*
2435 * We always require users to specify a valid IPv6 address for
2436 * the corresponding operation.
2437 */
2438 if (ifra->ifra_addr.sin6_family != AF_INET6 ||
2439 ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
2440 error = EAFNOSUPPORT;
2441 goto unwind;
2442 }
2443
2444 /* Validate ifra_prefixmask.sin6_len is properly bounded. */
2445 if (ifra->ifra_prefixmask.sin6_len == 0 ||
2446 ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6)) {
2447 error = EINVAL;
2448 goto unwind;
2449 }
2450
2451 /* Validate prefix length extracted from ifra_prefixmask structure. */
2452 plen = (uint8_t)in6_mask2len(mask: &ifra->ifra_prefixmask.sin6_addr,
2453 lim0: (u_char *)&ifra->ifra_prefixmask + ifra->ifra_prefixmask.sin6_len);
2454 if (plen <= 0) {
2455 error = EINVAL;
2456 goto unwind;
2457 }
2458
2459 /* Validate lifetimes */
2460 lt = &ifra->ifra_lifetime;
2461 if (lt->ia6t_pltime > lt->ia6t_vltime) {
2462 log(LOG_INFO,
2463 "%s: pltime 0x%x > vltime 0x%x for %s\n", __func__,
2464 lt->ia6t_pltime, lt->ia6t_vltime,
2465 ip6_sprintf(&ifra->ifra_addr.sin6_addr));
2466 error = EINVAL;
2467 goto unwind;
2468 }
2469 if (lt->ia6t_vltime == 0) {
2470 /*
2471 * the following log might be noisy, but this is a typical
2472 * configuration mistake or a tool's bug.
2473 */
2474 log(LOG_INFO, "%s: valid lifetime is 0 for %s\n", __func__,
2475 ip6_sprintf(&ifra->ifra_addr.sin6_addr));
2476 }
2477
2478 /*
2479 * Before we lock the ifnet structure, we first check to see if the
2480 * address already exists. If so, then we don't allocate and link a
2481 * new one here.
2482 */
2483 struct sockaddr_in6 lookup_address = ifra->ifra_addr;
2484 if (IN6_IS_ADDR_LINKLOCAL(&lookup_address.sin6_addr)) {
2485 if (in6_embedded_scope) {
2486 if (lookup_address.sin6_addr.s6_addr16[1] == 0) {
2487 /* link ID is not embedded by the user */
2488 lookup_address.sin6_addr.s6_addr16[1] =
2489 htons(ifp->if_index);
2490 } else if (lookup_address.sin6_addr.s6_addr16[1] !=
2491 htons(ifp->if_index)) {
2492 error = EINVAL; /* link ID contradicts */
2493 goto done;
2494 }
2495 } else {
2496 if (lookup_address.sin6_scope_id == IFSCOPE_NONE) {
2497 lookup_address.sin6_scope_id = ifp->if_index;
2498 }
2499 }
2500 if (lookup_address.sin6_scope_id != 0 &&
2501 lookup_address.sin6_scope_id !=
2502 (u_int32_t)ifp->if_index) {
2503 error = EINVAL;
2504 goto done;
2505 }
2506 }
2507
2508 ia = in6ifa_ifpwithaddr(ifp, &lookup_address.sin6_addr);
2509 if (ia != NULL) {
2510 ifa = &ia->ia_ifa;
2511 }
2512
2513 /*
2514 * Validate destination address on interface types that require it.
2515 */
2516 if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) {
2517 switch (ifra->ifra_dstaddr.sin6_family) {
2518 case AF_INET6:
2519 if (plen != 128) {
2520 /* noisy message for diagnostic purposes */
2521 log(LOG_INFO,
2522 "%s: prefix length < 128 with"
2523 " explicit dstaddr.\n", __func__);
2524 error = EINVAL;
2525 goto unwind;
2526 }
2527 break;
2528
2529 case AF_UNSPEC:
2530 break;
2531
2532 default:
2533 error = EAFNOSUPPORT;
2534 goto unwind;
2535 }
2536 } else if (ifra->ifra_dstaddr.sin6_family != AF_UNSPEC) {
2537 log(LOG_INFO,
2538 "%s: dstaddr valid only on p2p and loopback interfaces.\n",
2539 __func__);
2540 error = EINVAL;
2541 goto unwind;
2542 }
2543
2544 timenow = net_uptime();
2545
2546 if (ia == NULL) {
2547 zalloc_flags_t how;
2548
2549 /* Is this the first new IPv6 address for the interface? */
2550 ifaupflags |= IN6_IFAUPDATE_NEWADDR;
2551
2552 /* Allocate memory for IPv6 interface address structure. */
2553 how = (ifaupflags & IN6_IFAUPDATE_NOWAIT) ? Z_NOWAIT : Z_WAITOK;
2554 ia = in6_ifaddr_alloc(how);
2555 if (ia == NULL) {
2556 error = ENOBUFS;
2557 goto unwind;
2558 }
2559
2560 ifa = &ia->ia_ifa;
2561
2562 /*
2563 * Initialize interface address structure.
2564 *
2565 * Note well: none of these sockaddr_in6 structures contain a
2566 * valid sin6_port, sin6_flowinfo or even a sin6_scope_id field.
2567 * We still embed link-local scope identifiers at the end of an
2568 * arbitrary fe80::/32 prefix, for historical reasons. Also, the
2569 * ifa_dstaddr field is always non-NULL on point-to-point and
2570 * loopback interfaces, and conventionally points to a socket
2571 * address of AF_UNSPEC family when there is no destination.
2572 *
2573 * Please enjoy the dancing sea turtle.
2574 */
2575 IA6_HASH_INIT(ia);
2576 ifa->ifa_addr = SA(&ia->ia_addr);
2577 if (ifra->ifra_dstaddr.sin6_family == AF_INET6 ||
2578 (ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
2579 ifa->ifa_dstaddr = SA(&ia->ia_dstaddr);
2580 }
2581 ifa->ifa_netmask = SA(&ia->ia_prefixmask);
2582 ifa->ifa_ifp = ifp;
2583 ifa->ifa_metric = ifp->if_metric;
2584 ifa->ifa_rtrequest = nd6_rtrequest;
2585
2586 LIST_INIT(&ia->ia6_memberships);
2587 ia->ia_addr.sin6_family = AF_INET6;
2588 ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
2589 ia->ia_addr.sin6_addr = ifra->ifra_addr.sin6_addr;
2590 ia->ia_prefixmask.sin6_family = AF_INET6;
2591 ia->ia_prefixmask.sin6_len = sizeof(ia->ia_prefixmask);
2592 ia->ia_prefixmask.sin6_addr = ifra->ifra_prefixmask.sin6_addr;
2593 error = in6_to_kamescope(sin6: &ia->ia_addr, ifp);
2594 if (error != 0) {
2595 goto unwind;
2596 }
2597 if (ifa->ifa_dstaddr != NULL) {
2598 ia->ia_dstaddr = ifra->ifra_dstaddr;
2599 error = in6_to_kamescope(sin6: &ia->ia_dstaddr, ifp);
2600 if (error != 0) {
2601 goto unwind;
2602 }
2603 }
2604
2605 /* Append to address chains */
2606 ifnet_lock_exclusive(ifp);
2607 ifaupflags |= IN6_IFAUPDATE_1STADDR;
2608 TAILQ_FOREACH(xifa, &ifp->if_addrlist, ifa_list) {
2609 IFA_LOCK_SPIN(xifa);
2610 if (xifa->ifa_addr->sa_family != AF_INET6) {
2611 IFA_UNLOCK(xifa);
2612 ifaupflags &= ~IN6_IFAUPDATE_1STADDR;
2613 break;
2614 }
2615 IFA_UNLOCK(xifa);
2616 }
2617
2618 IFA_LOCK_SPIN(ifa);
2619 if_attach_ifa(ifp, ifa); /* holds reference for ifnet link */
2620 IFA_UNLOCK(ifa);
2621 ifnet_lock_done(ifp);
2622
2623 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
2624 TAILQ_INSERT_TAIL(&in6_ifaddrhead, ia, ia6_link);
2625 ifa_addref(ifa); /* hold for in6_ifaddrs link */
2626 os_atomic_inc(&in6_ifaddrlist_genid, relaxed);
2627 lck_rw_done(lck: &in6_ifaddr_rwlock);
2628 } else {
2629 ifa = &ia->ia_ifa;
2630 ifaupflags &= ~(IN6_IFAUPDATE_NEWADDR | IN6_IFAUPDATE_1STADDR);
2631 }
2632
2633 VERIFY(ia != NULL && ifa == &ia->ia_ifa);
2634
2635 if (!(ifaupflags & IN6_IFAUPDATE_NEWADDR) && ia->ia6_ndpr != NULL) {
2636 /* If we're flopping between address configuration methods, adjust the counts. */
2637 struct nd_prefix *pr = ia->ia6_ndpr;
2638 NDPR_LOCK(pr);
2639 if ((ia->ia6_flags & IN6_IFF_NOTMANUAL) && !(ifra->ifra_flags & IN6_IFF_NOTMANUAL)) {
2640 log(LOG_DEBUG, "address %s already exists in automatic form", ip6_sprintf(&ia->ia_addr.sin6_addr));
2641 pr->ndpr_manual_addrcnt--;
2642 } else if (!(ia->ia6_flags & IN6_IFF_NOTMANUAL) && (ifra->ifra_flags & IN6_IFF_NOTMANUAL)) {
2643 log(LOG_DEBUG, "address %s already exists in manual form", ip6_sprintf(&ia->ia_addr.sin6_addr));
2644 /* no need to adjust counts here as npdr_addrcnt is always adjusted no matter the interface type */
2645 }
2646 NDPR_UNLOCK(pr);
2647 }
2648
2649 IFA_LOCK(ifa);
2650
2651 /*
2652 * Set lifetimes. We do not refer to ia6t_expire and ia6t_preferred
2653 * to see if the address is deprecated or invalidated, but initialize
2654 * these members for applications.
2655 */
2656 ia->ia6_updatetime = ia->ia6_createtime = timenow;
2657 ia6_lt = *lt;
2658 if (ia6_lt.ia6t_vltime != ND6_INFINITE_LIFETIME) {
2659 ia6_lt.ia6t_expire = (time_t)(timenow + ia6_lt.ia6t_vltime);
2660 } else {
2661 ia6_lt.ia6t_expire = 0;
2662 }
2663 if (ia6_lt.ia6t_pltime != ND6_INFINITE_LIFETIME) {
2664 ia6_lt.ia6t_preferred = (time_t)(timenow + ia6_lt.ia6t_pltime);
2665 } else {
2666 ia6_lt.ia6t_preferred = 0;
2667 }
2668 in6ifa_setlifetime(ia, &ia6_lt);
2669
2670 /*
2671 * Backward compatibility - if IN6_IFF_DEPRECATED is set from the
2672 * userland, make it deprecated.
2673 */
2674 if ((ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
2675 ia->ia6_lifetime.ia6ti_pltime = 0;
2676 ia->ia6_lifetime.ia6ti_preferred = timenow;
2677 }
2678
2679 /*
2680 * Update flag or prefix length
2681 */
2682 ia->ia_plen = plen;
2683 ia->ia6_flags = ifra->ifra_flags;
2684
2685 /* Release locks (new address available to concurrent tasks) */
2686 IFA_UNLOCK(ifa);
2687
2688 /* Further initialization of the interface address */
2689 error = in6_ifinit(ifp, ia, ifaupflags);
2690 if (error != 0) {
2691 goto unwind;
2692 }
2693
2694 /* Finish updating the address while other tasks are working with it */
2695 error = in6_ifaupdate_aux(ia, ifp, ifaupflags);
2696 if (error != 0) {
2697 goto unwind;
2698 }
2699
2700 /* Return success (optionally w/ address for caller). */
2701 VERIFY(error == 0);
2702 (void) ifnet_notify_address(ifp, AF_INET6);
2703
2704 goto done;
2705
2706unwind:
2707 VERIFY(error != 0);
2708 if (ia != NULL) {
2709 VERIFY(ifa == &ia->ia_ifa);
2710 ifa_remref(ifa);
2711 ia = NULL;
2712 }
2713
2714done:
2715 *iar = ia;
2716 return error;
2717}
2718
2719void
2720in6_purgeaddr(struct ifaddr *ifa)
2721{
2722 struct ifnet *ifp = ifa->ifa_ifp;
2723 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
2724 struct in6_multi_mship *imm;
2725
2726 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
2727
2728 /* stop DAD processing */
2729 nd6_dad_stop(ifa);
2730
2731 /*
2732 * delete route to the destination of the address being purged.
2733 * The interface must be p2p or loopback in this case.
2734 */
2735 IFA_LOCK(ifa);
2736 if ((ia->ia_flags & IFA_ROUTE) && ia->ia_plen == 128) {
2737 int error, rtf;
2738
2739 IFA_UNLOCK(ifa);
2740 rtf = (ia->ia_dstaddr.sin6_family == AF_INET6) ? RTF_HOST : 0;
2741 error = rtinit(&(ia->ia_ifa), RTM_DELETE, rtf);
2742 if (error != 0) {
2743 log(LOG_ERR, "in6_purgeaddr: failed to remove "
2744 "a route to the p2p destination: %s on %s, "
2745 "errno=%d\n",
2746 ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),
2747 error);
2748 /* proceed anyway... */
2749 }
2750 IFA_LOCK_SPIN(ifa);
2751 ia->ia_flags &= ~IFA_ROUTE;
2752 }
2753 IFA_UNLOCK(ifa);
2754
2755 /* Remove ownaddr's loopback rtentry, if it exists. */
2756 in6_ifremloop(ifa: &(ia->ia_ifa));
2757
2758 /*
2759 * leave from multicast groups we have joined for the interface
2760 */
2761 IFA_LOCK(ifa);
2762 while ((imm = ia->ia6_memberships.lh_first) != NULL) {
2763 LIST_REMOVE(imm, i6mm_chain);
2764 IFA_UNLOCK(ifa);
2765 in6_leavegroup(imm);
2766 IFA_LOCK(ifa);
2767 }
2768 IFA_UNLOCK(ifa);
2769
2770 /* in6_unlink_ifa() will need exclusive access */
2771 in6_unlink_ifa(ia, ifp);
2772 in6_post_msg(ifp, KEV_INET6_ADDR_DELETED, ia, NULL);
2773
2774 (void) ifnet_notify_address(ifp, AF_INET6);
2775}
2776
2777static void
2778in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
2779{
2780 struct in6_ifaddr *nia;
2781 struct ifaddr *ifa;
2782 int unlinked;
2783
2784 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
2785
2786 ifa = &ia->ia_ifa;
2787 ifa_addref(ifa);
2788
2789 ifnet_lock_exclusive(ifp);
2790 IFA_LOCK(ifa);
2791 if (ifa->ifa_debug & IFD_ATTACHED) {
2792 if_detach_ifa(ifp, ifa);
2793 }
2794 IFA_UNLOCK(ifa);
2795 ifnet_lock_done(ifp);
2796
2797 unlinked = 0;
2798 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
2799 TAILQ_FOREACH(nia, &in6_ifaddrhead, ia6_link) {
2800 if (ia == nia) {
2801 TAILQ_REMOVE(&in6_ifaddrhead, ia, ia6_link);
2802 os_atomic_inc(&in6_ifaddrlist_genid, relaxed);
2803 IFA_LOCK(ifa);
2804 if (IA6_IS_HASHED(ia)) {
2805 in6_iahash_remove(ia);
2806 }
2807 IFA_UNLOCK(ifa);
2808 unlinked = 1;
2809 break;
2810 }
2811 }
2812
2813 /*
2814 * When IPv6 address is being removed, release the
2815 * reference to the base prefix.
2816 * Also, since the release might, affect the status
2817 * of other (detached) addresses, call
2818 * pfxlist_onlink_check().
2819 */
2820 IFA_LOCK(ifa);
2821 /*
2822 * Only log the below message for addresses other than
2823 * link local.
2824 * Only one LLA (auto-configured or statically) is allowed
2825 * on an interface.
2826 * LLA prefix, while added to the prefix list, is not
2827 * reference countedi (as it is the only one).
2828 * The prefix also never expires on its own as LLAs
2829 * have infinite lifetime.
2830 *
2831 * For now quiece down the log message for LLAs.
2832 */
2833 if (!IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
2834 if (ia->ia6_ndpr == NULL) {
2835 log(LOG_NOTICE, "in6_unlink_ifa: IPv6 address "
2836 "0x%llx has no prefix\n",
2837 (uint64_t)VM_KERNEL_ADDRPERM(ia));
2838 } else {
2839 struct nd_prefix *pr = ia->ia6_ndpr;
2840
2841 NDPR_LOCK(pr);
2842 if (!(ia->ia6_flags & IN6_IFF_NOTMANUAL)) {
2843 VERIFY(pr->ndpr_manual_addrcnt != 0);
2844 pr->ndpr_manual_addrcnt--;
2845 }
2846 ia->ia6_flags &= ~IN6_IFF_AUTOCONF;
2847 ia->ia6_ndpr = NULL;
2848 VERIFY(pr->ndpr_addrcnt != 0);
2849 pr->ndpr_addrcnt--;
2850 if (ia->ia6_flags & IN6_IFF_CLAT46) {
2851 pr->ndpr_stateflags &= ~NDPRF_CLAT46;
2852 }
2853 NDPR_UNLOCK(pr);
2854 NDPR_REMREF(pr); /* release addr reference */
2855 }
2856 }
2857 IFA_UNLOCK(ifa);
2858 lck_rw_done(lck: &in6_ifaddr_rwlock);
2859
2860 if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
2861 lck_mtx_lock(nd6_mutex);
2862 pfxlist_onlink_check();
2863 lck_mtx_unlock(nd6_mutex);
2864 }
2865 /*
2866 * release another refcnt for the link from in6_ifaddrs.
2867 * Do this only if it's not already unlinked in the event that we lost
2868 * the race, since in6_ifaddr_rwlock was momentarily dropped above.
2869 */
2870 if (unlinked) {
2871 ifa_remref(ifa);
2872 }
2873
2874 /* release reference held for this routine */
2875 ifa_remref(ifa);
2876
2877 /* invalidate route caches */
2878 routegenid_inet6_update();
2879}
2880
2881void
2882in6_purgeif(struct ifnet *ifp)
2883{
2884 struct in6_ifaddr *ia;
2885
2886 if (ifp == NULL) {
2887 return;
2888 }
2889
2890 LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
2891
2892 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
2893 boolean_t from_begining = TRUE;
2894 while (from_begining) {
2895 from_begining = FALSE;
2896 TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
2897 if (ia->ia_ifa.ifa_ifp != ifp) {
2898 continue;
2899 }
2900 ifa_addref(ifa: &ia->ia_ifa); /* for us */
2901 lck_rw_done(lck: &in6_ifaddr_rwlock);
2902 in6_purgeaddr(ifa: &ia->ia_ifa);
2903 ifa_remref(ifa: &ia->ia_ifa); /* for us */
2904 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
2905 /*
2906 * Purging the address would have caused
2907 * in6_ifaddr_rwlock to be dropped and reacquired;
2908 * therefore search again from the beginning
2909 * of in6_ifaddrs list.
2910 */
2911 from_begining = TRUE;
2912 break;
2913 }
2914 }
2915 lck_rw_done(lck: &in6_ifaddr_rwlock);
2916
2917 in6_ifdetach(ifp);
2918}
2919
2920/*
2921 * Initialize an interface's internet6 address and routing table entry.
2922 */
2923static int
2924in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia, int ifaupflags)
2925{
2926 int error;
2927 struct ifaddr *ifa;
2928
2929 error = 0;
2930 ifa = &ia->ia_ifa;
2931
2932 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
2933 IFA_LOCK(&ia->ia_ifa);
2934 if (IA6_IS_HASHED(ia)) {
2935 in6_iahash_remove(ia);
2936 }
2937 if ((ifp->if_flags & IFF_POINTOPOINT)) {
2938 in6_iahash_insert_ptp(ia);
2939 } else {
2940 in6_iahash_insert(ia);
2941 }
2942 IFA_UNLOCK(&ia->ia_ifa);
2943 lck_rw_done(lck: &in6_ifaddr_rwlock);
2944
2945 /*
2946 * NOTE: SIOCSIFADDR is defined with struct ifreq as parameter,
2947 * but here we are sending it down to the interface with a pointer
2948 * to struct ifaddr, for legacy reasons.
2949 */
2950 if ((ifaupflags & IN6_IFAUPDATE_1STADDR) != 0) {
2951 error = ifnet_ioctl(interface: ifp, PF_INET6, SIOCSIFADDR, ioctl_arg: ia);
2952 if (error != 0) {
2953 if (error != EOPNOTSUPP) {
2954 goto failed;
2955 }
2956 error = 0;
2957 }
2958 }
2959
2960 IFA_LOCK(ifa);
2961
2962 /*
2963 * Special case:
2964 * If the destination address is specified for a point-to-point
2965 * interface, install a route to the destination as an interface
2966 * direct route.
2967 */
2968 if (!(ia->ia_flags & IFA_ROUTE) && ia->ia_plen == 128 &&
2969 ia->ia_dstaddr.sin6_family == AF_INET6) {
2970 IFA_UNLOCK(ifa);
2971 error = rtinit(ifa, RTM_ADD, RTF_UP | RTF_HOST);
2972 if (error != 0) {
2973 goto failed;
2974 }
2975 IFA_LOCK(ifa);
2976 ia->ia_flags |= IFA_ROUTE;
2977 }
2978 IFA_LOCK_ASSERT_HELD(ifa);
2979 if (ia->ia_plen < 128) {
2980 /*
2981 * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
2982 */
2983 ia->ia_flags |= RTF_CLONING;
2984 }
2985
2986 IFA_UNLOCK(ifa);
2987
2988 /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
2989 if ((ifaupflags & IN6_IFAUPDATE_NEWADDR) != 0) {
2990 in6_ifaddloop(ifa);
2991 }
2992
2993 /* invalidate route caches */
2994 routegenid_inet6_update();
2995
2996 VERIFY(error == 0);
2997 return 0;
2998failed:
2999 VERIFY(error != 0);
3000 lck_rw_lock_exclusive(lck: &in6_ifaddr_rwlock);
3001 IFA_LOCK(&ia->ia_ifa);
3002 if (IA6_IS_HASHED(ia)) {
3003 in6_iahash_remove(ia);
3004 }
3005 IFA_UNLOCK(&ia->ia_ifa);
3006 lck_rw_done(lck: &in6_ifaddr_rwlock);
3007
3008 return error;
3009}
3010
3011void
3012in6_purgeaddrs(struct ifnet *ifp)
3013{
3014 in6_purgeif(ifp);
3015}
3016
3017/*
3018 * Find an IPv6 interface link-local address specific to an interface.
3019 */
3020struct in6_ifaddr *
3021in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
3022{
3023 struct ifaddr *ifa;
3024
3025 ifnet_lock_shared(ifp);
3026 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
3027 {
3028 IFA_LOCK_SPIN(ifa);
3029 if (ifa->ifa_addr->sa_family != AF_INET6) {
3030 IFA_UNLOCK(ifa);
3031 continue;
3032 }
3033 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
3034 if ((((struct in6_ifaddr *)ifa)->ia6_flags &
3035 ignoreflags) != 0) {
3036 IFA_UNLOCK(ifa);
3037 continue;
3038 }
3039 ifa_addref(ifa); /* for caller */
3040 IFA_UNLOCK(ifa);
3041 break;
3042 }
3043 IFA_UNLOCK(ifa);
3044 }
3045 ifnet_lock_done(ifp);
3046
3047 return (struct in6_ifaddr *)ifa;
3048}
3049
3050struct in6_ifaddr *
3051in6ifa_ifpwithflag(struct ifnet * ifp, int flag)
3052{
3053 struct ifaddr *ifa;
3054
3055 ifnet_lock_shared(ifp);
3056 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
3057 {
3058 IFA_LOCK_SPIN(ifa);
3059 if (ifa->ifa_addr->sa_family != AF_INET6) {
3060 IFA_UNLOCK(ifa);
3061 continue;
3062 }
3063 if ((((struct in6_ifaddr *)ifa)->ia6_flags & flag) == flag) {
3064 ifa_addref(ifa);
3065 IFA_UNLOCK(ifa);
3066 break;
3067 }
3068 IFA_UNLOCK(ifa);
3069 }
3070 ifnet_lock_done(ifp);
3071
3072 return (struct in6_ifaddr *)ifa;
3073}
3074
3075/*
3076 * find the internet address corresponding to a given interface and address.
3077 */
3078struct in6_ifaddr *
3079in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
3080{
3081 struct ifaddr *ifa;
3082
3083 ifnet_lock_shared(ifp);
3084 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
3085 {
3086 IFA_LOCK_SPIN(ifa);
3087 if (ifa->ifa_addr->sa_family != AF_INET6) {
3088 IFA_UNLOCK(ifa);
3089 continue;
3090 }
3091 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) {
3092 ifa_addref(ifa); /* for caller */
3093 IFA_UNLOCK(ifa);
3094 break;
3095 }
3096 IFA_UNLOCK(ifa);
3097 }
3098 ifnet_lock_done(ifp);
3099
3100 return (struct in6_ifaddr *)ifa;
3101}
3102
3103struct in6_ifaddr *
3104in6ifa_prproxyaddr(struct in6_addr *addr, uint32_t ifscope)
3105{
3106 struct in6_ifaddr *ia;
3107
3108 lck_rw_lock_shared(lck: &in6_ifaddr_rwlock);
3109 TAILQ_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) {
3110 IFA_LOCK(&ia->ia_ifa);
3111 if (in6_are_addr_equal_scoped(addr, IFA_IN6(&ia->ia_ifa), ifscope, ia->ia_ifp->if_index)) {
3112 ifa_addref(ifa: &ia->ia_ifa); /* for caller */
3113 IFA_UNLOCK(&ia->ia_ifa);
3114 break;
3115 }
3116 IFA_UNLOCK(&ia->ia_ifa);
3117 }
3118 lck_rw_done(lck: &in6_ifaddr_rwlock);
3119
3120 if (ia != NULL && !nd6_prproxy_ifaddr(ia)) {
3121 ifa_remref(ifa: &ia->ia_ifa);
3122 ia = NULL;
3123 }
3124
3125 return ia;
3126}
3127
3128void
3129in6ifa_getlifetime(struct in6_ifaddr *ia6, struct in6_addrlifetime *t_dst,
3130 int iscalendar)
3131{
3132 struct in6_addrlifetime_i *t_src = &ia6->ia6_lifetime;
3133 struct timeval caltime;
3134
3135 t_dst->ia6t_vltime = t_src->ia6ti_vltime;
3136 t_dst->ia6t_pltime = t_src->ia6ti_pltime;
3137 t_dst->ia6t_expire = 0;
3138 t_dst->ia6t_preferred = 0;
3139
3140 /* account for system time change */
3141 getmicrotime(&caltime);
3142 t_src->ia6ti_base_calendartime +=
3143 NET_CALCULATE_CLOCKSKEW(caltime,
3144 t_src->ia6ti_base_calendartime, net_uptime(),
3145 t_src->ia6ti_base_uptime);
3146
3147 if (iscalendar) {
3148 if (t_src->ia6ti_expire != 0 &&
3149 t_src->ia6ti_vltime != ND6_INFINITE_LIFETIME) {
3150 t_dst->ia6t_expire = (time_t)(t_src->ia6ti_base_calendartime +
3151 t_src->ia6ti_expire - t_src->ia6ti_base_uptime);
3152 }
3153
3154 if (t_src->ia6ti_preferred != 0 &&
3155 t_src->ia6ti_pltime != ND6_INFINITE_LIFETIME) {
3156 t_dst->ia6t_preferred = (time_t)(t_src->ia6ti_base_calendartime +
3157 t_src->ia6ti_preferred - t_src->ia6ti_base_uptime);
3158 }
3159 } else {
3160 if (t_src->ia6ti_expire != 0 &&
3161 t_src->ia6ti_vltime != ND6_INFINITE_LIFETIME) {
3162 t_dst->ia6t_expire = (time_t)t_src->ia6ti_expire;
3163 }
3164
3165 if (t_src->ia6ti_preferred != 0 &&
3166 t_src->ia6ti_pltime != ND6_INFINITE_LIFETIME) {
3167 t_dst->ia6t_preferred = (time_t)t_src->ia6ti_preferred;
3168 }
3169 }
3170}
3171
3172void
3173in6ifa_setlifetime(struct in6_ifaddr *ia6, struct in6_addrlifetime *t_src)
3174{
3175 struct in6_addrlifetime_i *t_dst = &ia6->ia6_lifetime;
3176 struct timeval caltime;
3177
3178 /* account for system time change */
3179 getmicrotime(&caltime);
3180 t_dst->ia6ti_base_calendartime +=
3181 NET_CALCULATE_CLOCKSKEW(caltime,
3182 t_dst->ia6ti_base_calendartime, net_uptime(),
3183 t_dst->ia6ti_base_uptime);
3184
3185 /* trust the caller for the values */
3186 t_dst->ia6ti_expire = t_src->ia6t_expire;
3187 t_dst->ia6ti_preferred = t_src->ia6t_preferred;
3188 t_dst->ia6ti_vltime = t_src->ia6t_vltime;
3189 t_dst->ia6ti_pltime = t_src->ia6t_pltime;
3190}
3191
3192/*
3193 * Convert IP6 address to printable (loggable) representation.
3194 */
3195char *
3196ip6_sprintf(const struct in6_addr *addr)
3197{
3198 static const char digits[] = "0123456789abcdef";
3199 static int ip6round = 0;
3200 static char ip6buf[8][48];
3201
3202 int i;
3203 char *cp;
3204 const u_short *a = (const u_short *)addr;
3205 const u_char *d;
3206 u_char n;
3207 int dcolon = 0;
3208 int zpad = 0;
3209
3210 ip6round = (ip6round + 1) & 7;
3211 cp = ip6buf[ip6round];
3212
3213 for (i = 0; i < 8; i++) {
3214 if (dcolon == 1) {
3215 if (*a == 0) {
3216 if (i == 7) {
3217 *cp++ = ':';
3218 }
3219 a++;
3220 continue;
3221 } else {
3222 dcolon = 2;
3223 }
3224 }
3225 if (*a == 0) {
3226 if (dcolon == 0 && *(a + 1) == 0) {
3227 if (i == 0) {
3228 *cp++ = ':';
3229 }
3230 *cp++ = ':';
3231 dcolon = 1;
3232 } else {
3233 *cp++ = '0';
3234 *cp++ = ':';
3235 }
3236 a++;
3237 continue;
3238 }
3239 d = (const u_char *)a;
3240 zpad = 0;
3241 if ((n = *d >> 4) != 0) {
3242 *cp++ = digits[n];
3243 zpad = 1;
3244 }
3245 if ((n = *d++ & 0xf) != 0 || zpad) {
3246 *cp++ = digits[n];
3247 zpad = 1;
3248 }
3249 if ((n = *d >> 4) != 0 || zpad) {
3250 *cp++ = digits[n];
3251 zpad = 1;
3252 }
3253 if ((n = *d & 0xf) != 0 || zpad) {
3254 *cp++ = digits[n];
3255 }
3256 *cp++ = ':';
3257 a++;
3258 }
3259 *--cp = 0;
3260 return ip6buf[ip6round];
3261}
3262
3263int
3264in6addr_local(struct in6_addr *in6)
3265{
3266 struct rtentry *rt;
3267 struct sockaddr_in6 sin6;
3268 int local = 0;
3269
3270 if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_SCOPE_LINKLOCAL(in6)) {
3271 return 1;
3272 }
3273
3274 sin6.sin6_family = AF_INET6;
3275 sin6.sin6_len = sizeof(sin6);
3276 bcopy(src: in6, dst: &sin6.sin6_addr, n: sizeof(*in6));
3277 rt = rtalloc1(SA(&sin6), 0, 0);
3278
3279 if (rt != NULL) {
3280 RT_LOCK_SPIN(rt);
3281 if (rt->rt_gateway->sa_family == AF_LINK) {
3282 local = 1;
3283 }
3284 RT_UNLOCK(rt);
3285 rtfree(rt);
3286 } else {
3287 local = in6_localaddr(in6);
3288 }
3289 return local;
3290}
3291
3292int
3293in6_localaddr(struct in6_addr *in6)
3294{
3295 struct in6_ifaddr *ia;
3296
3297 if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_MC_UNICAST_BASED_LINKLOCAL(in6)) {
3298 return 1;
3299 }
3300
3301 lck_rw_lock_shared(lck: &in6_ifaddr_rwlock);
3302 TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
3303 IFA_LOCK_SPIN(&ia->ia_ifa);
3304 if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
3305 &ia->ia_prefixmask.sin6_addr)) {
3306 IFA_UNLOCK(&ia->ia_ifa);
3307 lck_rw_done(lck: &in6_ifaddr_rwlock);
3308 return 1;
3309 }
3310 IFA_UNLOCK(&ia->ia_ifa);
3311 }
3312 lck_rw_done(lck: &in6_ifaddr_rwlock);
3313 return 0;
3314}
3315
3316/*
3317 * return length of part which dst and src are equal
3318 * hard coding...
3319 */
3320int
3321in6_matchlen(struct in6_addr *src, struct in6_addr *dst)
3322{
3323 int match = 0;
3324 u_char *s = (u_char *)src, *d = (u_char *)dst;
3325 u_char *lim = s + 16, r;
3326
3327 while (s < lim) {
3328 if ((r = (*d++ ^ *s++)) != 0) {
3329 while (r < 128) {
3330 match++;
3331 r = (u_char)(r << 1);
3332 }
3333 break;
3334 } else {
3335 match += 8;
3336 }
3337 }
3338 return match;
3339}
3340
3341/* XXX: to be scope conscious */
3342int
3343in6_are_prefix_equal(struct in6_addr *p1, uint32_t ifscope1, struct in6_addr *p2, uint32_t ifscope2, int len)
3344{
3345 int bytelen, bitlen;
3346
3347 /* sanity check */
3348 if (0 > len || len > 128) {
3349 log(LOG_ERR, "%s: invalid prefix length(%d)\n", __func__, len);
3350 return 0;
3351 }
3352
3353 bytelen = len / 8;
3354 bitlen = len % 8;
3355
3356 if (bcmp(s1: &p1->s6_addr, s2: &p2->s6_addr, n: bytelen)) {
3357 return 0;
3358 }
3359 if (bitlen != 0 &&
3360 p1->s6_addr[bytelen] >> (8 - bitlen) !=
3361 p2->s6_addr[bytelen] >> (8 - bitlen)) {
3362 return 0;
3363 }
3364
3365 if (IN6_IS_SCOPE_EMBED(p1) && !in6_embedded_scope) {
3366 return ifscope1 == ifscope2;
3367 }
3368
3369 return 1;
3370}
3371
3372void
3373in6_prefixlen2mask(struct in6_addr *maskp, int len)
3374{
3375 u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
3376 int bytelen, bitlen, i;
3377
3378 /* sanity check */
3379 if (0 > len || len > 128) {
3380 log(LOG_ERR, "%s: invalid prefix length(%d)\n", __func__, len);
3381 return;
3382 }
3383
3384 bzero(s: maskp, n: sizeof(*maskp));
3385 bytelen = len / 8;
3386 bitlen = len % 8;
3387 for (i = 0; i < bytelen; i++) {
3388 maskp->s6_addr[i] = 0xff;
3389 }
3390 if (bitlen) {
3391 maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
3392 }
3393}
3394
3395/*
3396 * return the best address out of the same scope
3397 */
3398struct in6_ifaddr *
3399in6_ifawithscope(struct ifnet *oifp, struct in6_addr *dst)
3400{
3401 int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0;
3402 int blen = -1;
3403 struct ifaddr *ifa;
3404 struct ifnet *ifp;
3405 struct in6_ifaddr *ifa_best = NULL;
3406
3407 if (oifp == NULL) {
3408 return NULL;
3409 }
3410
3411 /*
3412 * We search for all addresses on all interfaces from the beginning.
3413 * Comparing an interface with the outgoing interface will be done
3414 * only at the final stage of tiebreaking.
3415 */
3416 ifnet_head_lock_shared();
3417 TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
3418 /*
3419 * We can never take an address that breaks the scope zone
3420 * of the destination.
3421 */
3422 if (in6_addr2scopeid(ifp, dst) != in6_addr2scopeid(oifp, dst)) {
3423 continue;
3424 }
3425
3426 ifnet_lock_shared(ifp);
3427 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
3428 int tlen = -1, dscopecmp, bscopecmp, matchcmp;
3429
3430 IFA_LOCK(ifa);
3431 if (ifa->ifa_addr->sa_family != AF_INET6) {
3432 IFA_UNLOCK(ifa);
3433 continue;
3434 }
3435 src_scope = in6_addrscope(IFA_IN6(ifa));
3436
3437 /*
3438 * Don't use an address before completing DAD
3439 * nor a duplicated address.
3440 */
3441 if (((struct in6_ifaddr *)ifa)->ia6_flags &
3442 (IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) {
3443 IFA_UNLOCK(ifa);
3444 continue;
3445 }
3446 /* XXX: is there any case to allow anycasts? */
3447 if (((struct in6_ifaddr *)ifa)->ia6_flags &
3448 IN6_IFF_ANYCAST) {
3449 IFA_UNLOCK(ifa);
3450 continue;
3451 }
3452 if (((struct in6_ifaddr *)ifa)->ia6_flags &
3453 IN6_IFF_DETACHED) {
3454 IFA_UNLOCK(ifa);
3455 continue;
3456 }
3457 /*
3458 * If this is the first address we find,
3459 * keep it anyway.
3460 */
3461 if (ifa_best == NULL) {
3462 goto replace;
3463 }
3464
3465 /*
3466 * ifa_best is never NULL beyond this line except
3467 * within the block labeled "replace".
3468 */
3469
3470 /*
3471 * If ifa_best has a smaller scope than dst and
3472 * the current address has a larger one than
3473 * (or equal to) dst, always replace ifa_best.
3474 * Also, if the current address has a smaller scope
3475 * than dst, ignore it unless ifa_best also has a
3476 * smaller scope.
3477 * Consequently, after the two if-clause below,
3478 * the followings must be satisfied:
3479 * (scope(src) < scope(dst) &&
3480 * scope(best) < scope(dst))
3481 * OR
3482 * (scope(best) >= scope(dst) &&
3483 * scope(src) >= scope(dst))
3484 */
3485 if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0 &&
3486 IN6_ARE_SCOPE_CMP(src_scope, dst_scope) >= 0) {
3487 goto replace; /* (A) */
3488 }
3489 if (IN6_ARE_SCOPE_CMP(src_scope, dst_scope) < 0 &&
3490 IN6_ARE_SCOPE_CMP(best_scope, dst_scope) >= 0) {
3491 IFA_UNLOCK(ifa);
3492 continue; /* (B) */
3493 }
3494 /*
3495 * A deprecated address SHOULD NOT be used in new
3496 * communications if an alternate (non-deprecated)
3497 * address is available and has sufficient scope.
3498 * RFC 4862, Section 5.5.4.
3499 */
3500 if (((struct in6_ifaddr *)ifa)->ia6_flags &
3501 IN6_IFF_DEPRECATED) {
3502 /*
3503 * Ignore any deprecated addresses if
3504 * specified by configuration.
3505 */
3506 if (!ip6_use_deprecated) {
3507 IFA_UNLOCK(ifa);
3508 continue;
3509 }
3510 /*
3511 * If we have already found a non-deprecated
3512 * candidate, just ignore deprecated addresses.
3513 */
3514 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED)
3515 == 0) {
3516 IFA_UNLOCK(ifa);
3517 continue;
3518 }
3519 }
3520
3521 /*
3522 * A non-deprecated address is always preferred
3523 * to a deprecated one regardless of scopes and
3524 * address matching (Note invariants ensured by the
3525 * conditions (A) and (B) above.)
3526 */
3527 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) &&
3528 (((struct in6_ifaddr *)ifa)->ia6_flags &
3529 IN6_IFF_DEPRECATED) == 0) {
3530 goto replace;
3531 }
3532
3533 /*
3534 * When we use temporary addresses described in
3535 * RFC 4941, we prefer temporary addresses to
3536 * public autoconf addresses. Again, note the
3537 * invariants from (A) and (B). Also note that we
3538 * don't have any preference between static addresses
3539 * and autoconf addresses (despite of whether or not
3540 * the latter is temporary or public.)
3541 */
3542 if (ip6_use_tempaddr) {
3543 struct in6_ifaddr *ifat;
3544
3545 ifat = (struct in6_ifaddr *)ifa;
3546 if ((ifa_best->ia6_flags &
3547 (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY))
3548 == IN6_IFF_AUTOCONF &&
3549 (ifat->ia6_flags &
3550 (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY))
3551 == (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)) {
3552 goto replace;
3553 }
3554 if ((ifa_best->ia6_flags &
3555 (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY))
3556 == (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY) &&
3557 (ifat->ia6_flags &
3558 (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY))
3559 == IN6_IFF_AUTOCONF) {
3560 IFA_UNLOCK(ifa);
3561 continue;
3562 }
3563 }
3564
3565 /*
3566 * At this point, we have two cases:
3567 * 1. we are looking at a non-deprecated address,
3568 * and ifa_best is also non-deprecated.
3569 * 2. we are looking at a deprecated address,
3570 * and ifa_best is also deprecated.
3571 * Also, we do not have to consider a case where
3572 * the scope of if_best is larger(smaller) than dst and
3573 * the scope of the current address is smaller(larger)
3574 * than dst. Such a case has already been covered.
3575 * Tiebreaking is done according to the following
3576 * items:
3577 * - the scope comparison between the address and
3578 * dst (dscopecmp)
3579 * - the scope comparison between the address and
3580 * ifa_best (bscopecmp)
3581 * - if the address match dst longer than ifa_best
3582 * (matchcmp)
3583 * - if the address is on the outgoing I/F (outI/F)
3584 *
3585 * Roughly speaking, the selection policy is
3586 * - the most important item is scope. The same scope
3587 * is best. Then search for a larger scope.
3588 * Smaller scopes are the last resort.
3589 * - A deprecated address is chosen only when we have
3590 * no address that has an enough scope, but is
3591 * prefered to any addresses of smaller scopes
3592 * (this must be already done above.)
3593 * - addresses on the outgoing I/F are preferred to
3594 * ones on other interfaces if none of above
3595 * tiebreaks. In the table below, the column "bI"
3596 * means if the best_ifa is on the outgoing
3597 * interface, and the column "sI" means if the ifa
3598 * is on the outgoing interface.
3599 * - If there is no other reasons to choose one,
3600 * longest address match against dst is considered.
3601 *
3602 * The precise decision table is as follows:
3603 * dscopecmp bscopecmp match bI oI | replace?
3604 * N/A equal N/A Y N | No (1)
3605 * N/A equal N/A N Y | Yes (2)
3606 * N/A equal larger N/A | Yes (3)
3607 * N/A equal !larger N/A | No (4)
3608 * larger larger N/A N/A | No (5)
3609 * larger smaller N/A N/A | Yes (6)
3610 * smaller larger N/A N/A | Yes (7)
3611 * smaller smaller N/A N/A | No (8)
3612 * equal smaller N/A N/A | Yes (9)
3613 * equal larger (already done at A above)
3614 */
3615 dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
3616 bscopecmp = IN6_ARE_SCOPE_CMP(src_scope, best_scope);
3617
3618 if (bscopecmp == 0) {
3619 struct ifnet *bifp = ifa_best->ia_ifp;
3620
3621 if (bifp == oifp && ifp != oifp) { /* (1) */
3622 IFA_UNLOCK(ifa);
3623 continue;
3624 }
3625 if (bifp != oifp && ifp == oifp) { /* (2) */
3626 goto replace;
3627 }
3628
3629 /*
3630 * Both bifp and ifp are on the outgoing
3631 * interface, or both two are on a different
3632 * interface from the outgoing I/F.
3633 * now we need address matching against dst
3634 * for tiebreaking.
3635 */
3636 tlen = in6_matchlen(IFA_IN6(ifa), dst);
3637 matchcmp = tlen - blen;
3638 if (matchcmp > 0) { /* (3) */
3639 goto replace;
3640 }
3641 IFA_UNLOCK(ifa);
3642 continue; /* (4) */
3643 }
3644 if (dscopecmp > 0) {
3645 if (bscopecmp > 0) { /* (5) */
3646 IFA_UNLOCK(ifa);
3647 continue;
3648 }
3649 goto replace; /* (6) */
3650 }
3651 if (dscopecmp < 0) {
3652 if (bscopecmp > 0) { /* (7) */
3653 goto replace;
3654 }
3655 IFA_UNLOCK(ifa);
3656 continue; /* (8) */
3657 }
3658
3659 /* now dscopecmp must be 0 */
3660 if (bscopecmp < 0) {
3661 goto replace; /* (9) */
3662 }
3663replace:
3664 ifa_addref(ifa); /* for ifa_best */
3665 blen = tlen >= 0 ? tlen :
3666 in6_matchlen(IFA_IN6(ifa), dst);
3667 best_scope =
3668 in6_addrscope(&ifa2ia6(ifa)->ia_addr.sin6_addr);
3669 IFA_UNLOCK(ifa);
3670 if (ifa_best) {
3671 ifa_remref(ifa: &ifa_best->ia_ifa);
3672 }
3673 ifa_best = (struct in6_ifaddr *)ifa;
3674 }
3675 ifnet_lock_done(ifp);
3676 }
3677 ifnet_head_done();
3678
3679 /* count statistics for future improvements */
3680 if (ifa_best == NULL) {
3681 ip6stat.ip6s_sources_none++;
3682 } else {
3683 IFA_LOCK_SPIN(&ifa_best->ia_ifa);
3684 if (oifp == ifa_best->ia_ifp) {
3685 ip6stat.ip6s_sources_sameif[best_scope]++;
3686 } else {
3687 ip6stat.ip6s_sources_otherif[best_scope]++;
3688 }
3689
3690 if (best_scope == dst_scope) {
3691 ip6stat.ip6s_sources_samescope[best_scope]++;
3692 } else {
3693 ip6stat.ip6s_sources_otherscope[best_scope]++;
3694 }
3695
3696 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) != 0) {
3697 ip6stat.ip6s_sources_deprecated[best_scope]++;
3698 }
3699 IFA_UNLOCK(&ifa_best->ia_ifa);
3700 }
3701
3702 return ifa_best;
3703}
3704
3705/*
3706 * return the best address out of the same scope. if no address was
3707 * found, return the first valid address from designated IF.
3708 */
3709struct in6_ifaddr *
3710in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
3711{
3712 int dst_scope = in6_addrscope(dst), blen = -1, tlen;
3713 struct ifaddr *ifa;
3714 struct in6_ifaddr *besta = NULL;
3715 struct in6_ifaddr *dep[2]; /* last-resort: deprecated */
3716
3717 dep[0] = dep[1] = NULL;
3718
3719 /*
3720 * We first look for addresses in the same scope.
3721 * If there is one, return it.
3722 * If two or more, return one which matches the dst longest.
3723 * If none, return one of global addresses assigned other ifs.
3724 */
3725 ifnet_lock_shared(ifp);
3726 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
3727 IFA_LOCK(ifa);
3728 if (ifa->ifa_addr->sa_family != AF_INET6) {
3729 IFA_UNLOCK(ifa);
3730 continue;
3731 }
3732 if (ifa2ia6(ifa)->ia6_flags & IN6_IFF_ANYCAST) {
3733 IFA_UNLOCK(ifa);
3734 continue; /* XXX: is there any case to allow anycast? */
3735 }
3736 if (ifa2ia6(ifa)->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) {
3737 IFA_UNLOCK(ifa);
3738 continue; /* don't use this interface */
3739 }
3740 if (ifa2ia6(ifa)->ia6_flags & IN6_IFF_DETACHED) {
3741 IFA_UNLOCK(ifa);
3742 continue;
3743 }
3744 if (ifa2ia6(ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
3745 if (ip6_use_deprecated) {
3746 ifa_addref(ifa); /* for dep[0] */
3747 IFA_UNLOCK(ifa);
3748 if (dep[0] != NULL) {
3749 ifa_remref(ifa: &dep[0]->ia_ifa);
3750 }
3751 dep[0] = (struct in6_ifaddr *)ifa;
3752 } else {
3753 IFA_UNLOCK(ifa);
3754 }
3755 continue;
3756 }
3757
3758 if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
3759 /*
3760 * call in6_matchlen() as few as possible
3761 */
3762 if (besta) {
3763 if (blen == -1) {
3764 IFA_UNLOCK(ifa);
3765 IFA_LOCK(&besta->ia_ifa);
3766 blen = in6_matchlen(
3767 src: &besta->ia_addr.sin6_addr, dst);
3768 IFA_UNLOCK(&besta->ia_ifa);
3769 IFA_LOCK(ifa);
3770 }
3771 tlen = in6_matchlen(IFA_IN6(ifa), dst);
3772 if (tlen > blen) {
3773 blen = tlen;
3774 ifa_addref(ifa); /* for besta */
3775 IFA_UNLOCK(ifa);
3776 ifa_remref(ifa: &besta->ia_ifa);
3777 besta = (struct in6_ifaddr *)ifa;
3778 } else {
3779 IFA_UNLOCK(ifa);
3780 }
3781 } else {
3782 besta = (struct in6_ifaddr *)ifa;
3783 ifa_addref(ifa); /* for besta */
3784 IFA_UNLOCK(ifa);
3785 }
3786 } else {
3787 IFA_UNLOCK(ifa);
3788 }
3789 }
3790 if (besta) {
3791 ifnet_lock_done(ifp);
3792 if (dep[0] != NULL) {
3793 ifa_remref(ifa: &dep[0]->ia_ifa);
3794 }
3795 return besta;
3796 }
3797
3798 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
3799 IFA_LOCK(ifa);
3800 if (ifa->ifa_addr->sa_family != AF_INET6) {
3801 IFA_UNLOCK(ifa);
3802 continue;
3803 }
3804 if (ifa2ia6(ifa)->ia6_flags & IN6_IFF_ANYCAST) {
3805 IFA_UNLOCK(ifa);
3806 continue; /* XXX: is there any case to allow anycast? */
3807 }
3808 if (ifa2ia6(ifa)->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) {
3809 IFA_UNLOCK(ifa);
3810 continue; /* don't use this interface */
3811 }
3812 if (ifa2ia6(ifa)->ia6_flags & IN6_IFF_DETACHED) {
3813 IFA_UNLOCK(ifa);
3814 continue;
3815 }
3816 if (ifa2ia6(ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
3817 if (ip6_use_deprecated) {
3818 ifa_addref(ifa); /* for dep[1] */
3819 IFA_UNLOCK(ifa);
3820 if (dep[1] != NULL) {
3821 ifa_remref(ifa: &dep[1]->ia_ifa);
3822 }
3823 dep[1] = (struct in6_ifaddr *)ifa;
3824 } else {
3825 IFA_UNLOCK(ifa);
3826 }
3827 continue;
3828 }
3829 ifa_addref(ifa); /* for caller */
3830 IFA_UNLOCK(ifa);
3831 ifnet_lock_done(ifp);
3832 if (dep[0] != NULL) {
3833 ifa_remref(ifa: &dep[0]->ia_ifa);
3834 }
3835 if (dep[1] != NULL) {
3836 ifa_remref(ifa: &dep[1]->ia_ifa);
3837 }
3838 return (struct in6_ifaddr *)ifa;
3839 }
3840 ifnet_lock_done(ifp);
3841
3842 /* use the last-resort values, that are, deprecated addresses */
3843 if (dep[0]) {
3844 if (dep[1] != NULL) {
3845 ifa_remref(ifa: &dep[1]->ia_ifa);
3846 }
3847 return dep[0];
3848 }
3849 if (dep[1]) {
3850 return dep[1];
3851 }
3852
3853 return NULL;
3854}
3855
3856/*
3857 * perform DAD when interface becomes IFF_UP.
3858 */
3859static void
3860in6_if_up_dad_start(struct ifnet *ifp)
3861{
3862 struct ifaddr *ifa;
3863 struct nd_ifinfo *ndi = NULL;
3864
3865 ndi = ND_IFINFO(ifp);
3866 VERIFY((NULL != ndi) && (TRUE == ndi->initialized));
3867 if (!(ndi->flags & ND6_IFF_DAD)) {
3868 return;
3869 }
3870
3871 /* start DAD on all the interface addresses */
3872 ifnet_lock_exclusive(ifp);
3873 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
3874 struct in6_ifaddr *ia6;
3875
3876 IFA_LOCK_SPIN(ifa);
3877 if (ifa->ifa_addr->sa_family != AF_INET6) {
3878 IFA_UNLOCK(ifa);
3879 continue;
3880 }
3881 ia6 = (struct in6_ifaddr *)ifa;
3882 if (ia6->ia6_flags & IN6_IFF_DADPROGRESS) {
3883 int delay = 0; /* delay ticks before DAD output */
3884 IFA_UNLOCK(ifa);
3885 nd6_dad_start(ifa, &delay);
3886 } else {
3887 IFA_UNLOCK(ifa);
3888 }
3889 }
3890 ifnet_lock_done(ifp);
3891}
3892
3893int
3894in6if_do_dad(
3895 struct ifnet *ifp)
3896{
3897 struct nd_ifinfo *ndi = NULL;
3898
3899 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
3900 return 0;
3901 }
3902
3903 ndi = ND_IFINFO(ifp);
3904 VERIFY((NULL != ndi) && (TRUE == ndi->initialized));
3905 if (!(ndi->flags & ND6_IFF_DAD)) {
3906 return 0;
3907 }
3908
3909 /*
3910 * If we are using the alternative neighbor discovery
3911 * interface on this interface, then skip DAD.
3912 *
3913 * Also, skip it for interfaces marked "local private"
3914 * for now, even when not marked as using the alternative
3915 * interface. This is for historical reasons.
3916 */
3917 if (ifp->if_eflags &
3918 (IFEF_IPV6_ND6ALT | IFEF_LOCALNET_PRIVATE | IFEF_DIRECTLINK)) {
3919 return 0;
3920 }
3921
3922 if (ifp->if_family == IFNET_FAMILY_IPSEC ||
3923 ifp->if_family == IFNET_FAMILY_UTUN) {
3924 /*
3925 * Ignore DAD for tunneling virtual interfaces, which get
3926 * their IPv6 address explicitly assigned.
3927 */
3928 return 0;
3929 }
3930
3931 switch (ifp->if_type) {
3932#if IFT_DUMMY
3933 case IFT_DUMMY:
3934#endif
3935 case IFT_FAITH:
3936 /*
3937 * These interfaces do not have the IFF_LOOPBACK flag,
3938 * but loop packets back. We do not have to do DAD on such
3939 * interfaces. We should even omit it, because loop-backed
3940 * NS would confuse the DAD procedure.
3941 */
3942 return 0;
3943 default:
3944 /*
3945 * Our DAD routine requires the interface up and running.
3946 * However, some interfaces can be up before the RUNNING
3947 * status. Additionaly, users may try to assign addresses
3948 * before the interface becomes up (or running).
3949 * We simply skip DAD in such a case as a work around.
3950 * XXX: we should rather mark "tentative" on such addresses,
3951 * and do DAD after the interface becomes ready.
3952 */
3953 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
3954 (IFF_UP | IFF_RUNNING)) {
3955 return 0;
3956 }
3957
3958 return 1;
3959 }
3960}
3961
3962/*
3963 * Calculate max IPv6 MTU through all the interfaces and store it
3964 * to in6_maxmtu.
3965 */
3966void
3967in6_setmaxmtu(void)
3968{
3969 u_int32_t maxmtu = 0;
3970 struct ifnet *ifp;
3971
3972 ifnet_head_lock_shared();
3973 TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
3974 struct nd_ifinfo *ndi = NULL;
3975
3976 if ((ndi = ND_IFINFO(ifp)) != NULL && !ndi->initialized) {
3977 ndi = NULL;
3978 }
3979 if (ndi != NULL) {
3980 lck_mtx_lock(lck: &ndi->lock);
3981 }
3982 if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
3983 IN6_LINKMTU(ifp) > maxmtu) {
3984 maxmtu = IN6_LINKMTU(ifp);
3985 }
3986 if (ndi != NULL) {
3987 lck_mtx_unlock(lck: &ndi->lock);
3988 }
3989 }
3990 ifnet_head_done();
3991 if (maxmtu) { /* update only when maxmtu is positive */
3992 in6_maxmtu = maxmtu;
3993 }
3994}
3995/*
3996 * Provide the length of interface identifiers to be used for the link attached
3997 * to the given interface. The length should be defined in "IPv6 over
3998 * xxx-link" document. Note that address architecture might also define
3999 * the length for a particular set of address prefixes, regardless of the
4000 * link type. Also see RFC 4862 for additional background.
4001 */
4002int
4003in6_if2idlen(struct ifnet *ifp)
4004{
4005 switch (ifp->if_type) {
4006 case IFT_ETHER: /* RFC2464 */
4007 case IFT_IEEE8023ADLAG: /* IEEE802.3ad Link Aggregate */
4008#ifdef IFT_PROPVIRTUAL
4009 case IFT_PROPVIRTUAL: /* XXX: no RFC. treat it as ether */
4010#endif
4011#ifdef IFT_L2VLAN
4012 case IFT_L2VLAN: /* ditto */
4013#endif
4014#ifdef IFT_IEEE80211
4015 case IFT_IEEE80211: /* ditto */
4016#endif
4017#ifdef IFT_MIP
4018 case IFT_MIP: /* ditto */
4019#endif
4020 return 64;
4021 case IFT_FDDI: /* RFC2467 */
4022 return 64;
4023 case IFT_ISO88025: /* RFC2470 (IPv6 over Token Ring) */
4024 return 64;
4025 case IFT_PPP: /* RFC2472 */
4026 return 64;
4027 case IFT_ARCNET: /* RFC2497 */
4028 return 64;
4029 case IFT_FRELAY: /* RFC2590 */
4030 return 64;
4031 case IFT_IEEE1394: /* RFC3146 */
4032 return 64;
4033 case IFT_GIF:
4034 return 64; /* draft-ietf-v6ops-mech-v2-07 */
4035 case IFT_LOOP:
4036 return 64; /* XXX: is this really correct? */
4037 case IFT_OTHER:
4038 return 64; /* for utun interfaces */
4039 case IFT_CELLULAR:
4040 return 64; /* Packet Data over Cellular */
4041 case IFT_BRIDGE:
4042 return 64; /* Transparent bridge interface */
4043 default:
4044 /*
4045 * Unknown link type:
4046 * It might be controversial to use the today's common constant
4047 * of 64 for these cases unconditionally. For full compliance,
4048 * we should return an error in this case. On the other hand,
4049 * if we simply miss the standard for the link type or a new
4050 * standard is defined for a new link type, the IFID length
4051 * is very likely to be the common constant. As a compromise,
4052 * we always use the constant, but make an explicit notice
4053 * indicating the "unknown" case.
4054 */
4055 log(LOG_NOTICE, "%s: unknown link type (%d)\n", __func__,
4056 ifp->if_type);
4057 return 64;
4058 }
4059}
4060/*
4061 * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be
4062 * v4 mapped addr or v4 compat addr
4063 */
4064void
4065in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
4066{
4067 SOCKADDR_ZERO(sin, sizeof(*sin));
4068 sin->sin_len = sizeof(struct sockaddr_in);
4069 sin->sin_family = AF_INET;
4070 sin->sin_port = sin6->sin6_port;
4071 sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
4072}
4073
4074/* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
4075void
4076in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
4077{
4078 SOCKADDR_ZERO(sin6, sizeof(*sin6));
4079 sin6->sin6_len = sizeof(struct sockaddr_in6);
4080 sin6->sin6_family = AF_INET6;
4081 sin6->sin6_port = sin->sin_port;
4082 sin6->sin6_addr.s6_addr32[0] = 0;
4083 sin6->sin6_addr.s6_addr32[1] = 0;
4084 if (sin->sin_addr.s_addr) {
4085 sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
4086 sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
4087 } else {
4088 sin6->sin6_addr.s6_addr32[2] = 0;
4089 sin6->sin6_addr.s6_addr32[3] = 0;
4090 }
4091}
4092
4093/* Convert sockaddr_in6 into sockaddr_in. */
4094void
4095in6_sin6_2_sin_in_sock(struct sockaddr *nam)
4096{
4097 struct sockaddr_in *sin_p;
4098 struct sockaddr_in6 sin6;
4099
4100 /*
4101 * Save original sockaddr_in6 addr and convert it
4102 * to sockaddr_in.
4103 */
4104 sin6 = *SIN6(nam);
4105 sin_p = SIN(nam);
4106 in6_sin6_2_sin(sin: sin_p, sin6: &sin6);
4107}
4108
4109/* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
4110int
4111in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
4112{
4113 struct sockaddr_in *sin_p;
4114 struct sockaddr_in6 *sin6_p;
4115
4116 sin6_p = SIN6(alloc_sockaddr(sizeof(*sin6_p),
4117 Z_WAITOK | Z_NOFAIL));
4118
4119 sin_p = SIN(*nam);
4120 in6_sin_2_v4mapsin6(sin: sin_p, sin6: sin6_p);
4121 free_sockaddr(*nam);
4122 *nam = SA(sin6_p);
4123
4124 return 0;
4125}
4126
4127/*
4128 * Posts in6_event_data message kernel events.
4129 *
4130 * To get the same size of kev_in6_data between ILP32 and LP64 data models
4131 * we are using a special version of the in6_addrlifetime structure that
4132 * uses only 32 bits fields to be compatible with Leopard, and that
4133 * are large enough to span 68 years.
4134 */
4135void
4136in6_post_msg(struct ifnet *ifp, u_int32_t event_code, struct in6_ifaddr *ifa,
4137 uint8_t *mac)
4138{
4139 struct kev_msg ev_msg;
4140 struct kev_in6_data in6_event_data;
4141 struct in6_addrlifetime ia6_lt;
4142
4143 bzero(s: &in6_event_data, n: sizeof(struct kev_in6_data));
4144 bzero(s: &ev_msg, n: sizeof(struct kev_msg));
4145 ev_msg.vendor_code = KEV_VENDOR_APPLE;
4146 ev_msg.kev_class = KEV_NETWORK_CLASS;
4147 ev_msg.kev_subclass = KEV_INET6_SUBCLASS;
4148 ev_msg.event_code = event_code;
4149
4150 if (ifa) {
4151 IFA_LOCK(&ifa->ia_ifa);
4152 in6_event_data.ia_addr = ifa->ia_addr;
4153 in6_event_data.ia_net = ifa->ia_net;
4154 in6_event_data.ia_dstaddr = ifa->ia_dstaddr;
4155 in6_event_data.ia_prefixmask = ifa->ia_prefixmask;
4156 in6_event_data.ia_plen = ifa->ia_plen;
4157 in6_event_data.ia6_flags = (u_int32_t)ifa->ia6_flags;
4158
4159 /* retrieve time as calendar time (last arg is 1) */
4160 in6ifa_getlifetime(ia6: ifa, t_dst: &ia6_lt, iscalendar: 1);
4161 in6_event_data.ia_lifetime.ia6t_expire = (u_int32_t)ia6_lt.ia6t_expire;
4162 in6_event_data.ia_lifetime.ia6t_preferred = (u_int32_t)ia6_lt.ia6t_preferred;
4163 in6_event_data.ia_lifetime.ia6t_vltime = ia6_lt.ia6t_vltime;
4164 in6_event_data.ia_lifetime.ia6t_pltime = ia6_lt.ia6t_pltime;
4165 IFA_UNLOCK(&ifa->ia_ifa);
4166 }
4167
4168 if (ifp != NULL) {
4169 (void) strlcpy(dst: &in6_event_data.link_data.if_name[0],
4170 src: ifp->if_name, IFNAMSIZ);
4171 in6_event_data.link_data.if_family = ifp->if_family;
4172 in6_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
4173 }
4174
4175 if (mac != NULL) {
4176 memcpy(dst: &in6_event_data.ia_mac, src: mac,
4177 n: sizeof(in6_event_data.ia_mac));
4178 }
4179
4180 ev_msg.dv[0].data_ptr = &in6_event_data;
4181 ev_msg.dv[0].data_length = sizeof(in6_event_data);
4182 ev_msg.dv[1].data_length = 0;
4183
4184 dlil_post_complete_msg(NULL, &ev_msg);
4185}
4186
4187/*
4188 * Called as part of ip6_init
4189 */
4190void
4191in6_ifaddr_init(void)
4192{
4193 in6_cga_init();
4194}
4195
4196static struct in6_ifaddr *
4197in6_ifaddr_alloc(zalloc_flags_t how)
4198{
4199 struct in6_ifaddr *in6ifa;
4200
4201 in6ifa = kalloc_type(struct in6_ifaddr, Z_ZERO | how);
4202 if (in6ifa == NULL) {
4203 return NULL;
4204 }
4205
4206 in6ifa->ia_ifa.ifa_free = in6_ifaddr_free;
4207 in6ifa->ia_ifa.ifa_debug |= IFD_ALLOC;
4208 in6ifa->ia_ifa.ifa_del_wc = &in6ifa->ia_ifa.ifa_debug;
4209 in6ifa->ia_ifa.ifa_del_waiters = 0;
4210 ifa_lock_init(&in6ifa->ia_ifa);
4211 ifa_initref(&in6ifa->ia_ifa);
4212
4213 return in6ifa;
4214}
4215
4216static void
4217in6_ifaddr_free(struct ifaddr *ifa)
4218{
4219 struct in6_ifaddr *in6ifa = (struct in6_ifaddr *)ifa;
4220
4221 IFA_LOCK_ASSERT_HELD(ifa);
4222
4223 if (!(ifa->ifa_debug & IFD_ALLOC)) {
4224 panic("%s: ifa %p cannot be freed", __func__, ifa);
4225 /* NOTREACHED */
4226 }
4227 IFA_UNLOCK(ifa);
4228 ifa_lock_destroy(ifa);
4229
4230 kfree_type(struct in6_ifaddr, in6ifa);
4231}
4232
4233/*
4234 * Handle SIOCGASSOCIDS ioctl for PF_INET6 domain.
4235 */
4236static int
4237in6_getassocids(struct socket *so, uint32_t *cnt, user_addr_t aidp)
4238{
4239 struct in6pcb *in6p = sotoin6pcb(so);
4240 sae_associd_t aid;
4241
4242 if (in6p == NULL || in6p->inp_state == INPCB_STATE_DEAD) {
4243 return EINVAL;
4244 }
4245
4246 /* IN6PCB has no concept of association */
4247 aid = SAE_ASSOCID_ANY;
4248 *cnt = 0;
4249
4250 /* just asking how many there are? */
4251 if (aidp == USER_ADDR_NULL) {
4252 return 0;
4253 }
4254
4255 return copyout(&aid, aidp, sizeof(aid));
4256}
4257
4258/*
4259 * Handle SIOCGCONNIDS ioctl for PF_INET6 domain.
4260 */
4261static int
4262in6_getconnids(struct socket *so, sae_associd_t aid, uint32_t *cnt,
4263 user_addr_t cidp)
4264{
4265 struct in6pcb *in6p = sotoin6pcb(so);
4266 sae_connid_t cid;
4267
4268 if (in6p == NULL || in6p->inp_state == INPCB_STATE_DEAD) {
4269 return EINVAL;
4270 }
4271
4272 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL) {
4273 return EINVAL;
4274 }
4275
4276 /* if connected, return 1 connection count */
4277 *cnt = ((so->so_state & SS_ISCONNECTED) ? 1 : 0);
4278
4279 /* just asking how many there are? */
4280 if (cidp == USER_ADDR_NULL) {
4281 return 0;
4282 }
4283
4284 /* if IN6PCB is connected, assign it connid 1 */
4285 cid = ((*cnt != 0) ? 1 : SAE_CONNID_ANY);
4286
4287 return copyout(&cid, cidp, sizeof(cid));
4288}
4289
4290/*
4291 * Handle SIOCGCONNINFO ioctl for PF_INET6 domain.
4292 */
4293int
4294in6_getconninfo(struct socket *so, sae_connid_t cid, uint32_t *flags,
4295 uint32_t *ifindex, int32_t *soerror, user_addr_t src, socklen_t *src_len,
4296 user_addr_t dst, socklen_t *dst_len, uint32_t *aux_type,
4297 user_addr_t aux_data, uint32_t *aux_len)
4298{
4299 struct in6pcb *in6p = sotoin6pcb(so);
4300 struct sockaddr_in6 sin6;
4301 struct ifnet *ifp = NULL;
4302 int error = 0;
4303 u_int32_t copy_len = 0;
4304
4305 /*
4306 * Don't test for INPCB_STATE_DEAD since this may be called
4307 * after SOF_PCBCLEARING is set, e.g. after tcp_close().
4308 */
4309 if (in6p == NULL) {
4310 error = EINVAL;
4311 goto out;
4312 }
4313
4314 if (cid != SAE_CONNID_ANY && cid != SAE_CONNID_ALL && cid != 1) {
4315 error = EINVAL;
4316 goto out;
4317 }
4318
4319 ifp = in6p->in6p_last_outifp;
4320 *ifindex = ((ifp != NULL) ? ifp->if_index : 0);
4321 *soerror = so->so_error;
4322 *flags = 0;
4323 if (so->so_state & SS_ISCONNECTED) {
4324 *flags |= (CIF_CONNECTED | CIF_PREFERRED);
4325 }
4326 if (in6p->in6p_flags & INP_BOUND_IF) {
4327 *flags |= CIF_BOUND_IF;
4328 }
4329 if (!(in6p->in6p_flags & INP_IN6ADDR_ANY)) {
4330 *flags |= CIF_BOUND_IP;
4331 }
4332 if (!(in6p->in6p_flags & INP_ANONPORT)) {
4333 *flags |= CIF_BOUND_PORT;
4334 }
4335
4336 SOCKADDR_ZERO(&sin6, sizeof(sin6));
4337 sin6.sin6_len = sizeof(sin6);
4338 sin6.sin6_family = AF_INET6;
4339
4340 /* source address and port */
4341 sin6.sin6_port = in6p->in6p_lport;
4342 if (!in6_embedded_scope) {
4343 sin6.sin6_scope_id = in6p->inp_lifscope;
4344 }
4345 in6_recoverscope(&sin6, &in6p->in6p_laddr, NULL);
4346 if (*src_len == 0) {
4347 *src_len = sin6.sin6_len;
4348 } else {
4349 if (src != USER_ADDR_NULL) {
4350 copy_len = min(a: *src_len, b: sizeof(sin6));
4351 error = copyout(&sin6, src, copy_len);
4352 if (error != 0) {
4353 goto out;
4354 }
4355 *src_len = copy_len;
4356 }
4357 }
4358
4359 /* destination address and port */
4360 sin6.sin6_port = in6p->in6p_fport;
4361 if (!in6_embedded_scope) {
4362 sin6.sin6_scope_id = in6p->inp_fifscope;
4363 }
4364 in6_recoverscope(&sin6, &in6p->in6p_faddr, NULL);
4365 if (*dst_len == 0) {
4366 *dst_len = sin6.sin6_len;
4367 } else {
4368 if (dst != USER_ADDR_NULL) {
4369 copy_len = min(a: *dst_len, b: sizeof(sin6));
4370 error = copyout(&sin6, dst, copy_len);
4371 if (error != 0) {
4372 goto out;
4373 }
4374 *dst_len = copy_len;
4375 }
4376 }
4377
4378 if (SOCK_PROTO(so) == IPPROTO_TCP) {
4379 struct conninfo_tcp tcp_ci;
4380
4381 *aux_type = CIAUX_TCP;
4382 if (*aux_len == 0) {
4383 *aux_len = sizeof(tcp_ci);
4384 } else {
4385 if (aux_data != USER_ADDR_NULL) {
4386 copy_len = min(a: *aux_len, b: sizeof(tcp_ci));
4387 bzero(s: &tcp_ci, n: sizeof(tcp_ci));
4388 tcp_getconninfo(so, &tcp_ci);
4389 error = copyout(&tcp_ci, aux_data, copy_len);
4390 if (error != 0) {
4391 goto out;
4392 }
4393 *aux_len = copy_len;
4394 }
4395 }
4396 } else {
4397 *aux_type = 0;
4398 *aux_len = 0;
4399 }
4400
4401out:
4402 return error;
4403}
4404
4405/*
4406 * 'u' group ioctls.
4407 *
4408 * The switch statement below does nothing at runtime, as it serves as a
4409 * compile time check to ensure that all of the socket 'u' ioctls (those
4410 * in the 'u' group going thru soo_ioctl) that are made available by the
4411 * networking stack is unique. This works as long as this routine gets
4412 * updated each time a new interface ioctl gets added.
4413 *
4414 * Any failures at compile time indicates duplicated ioctl values.
4415 */
4416static __attribute__((unused)) void
4417in6ioctl_cassert(void)
4418{
4419 /*
4420 * This is equivalent to _CASSERT() and the compiler wouldn't
4421 * generate any instructions, thus for compile time only.
4422 */
4423 switch ((u_long)0) {
4424 case 0:
4425
4426 /* bsd/netinet6/in6_var.h */
4427 case SIOCAADDRCTL_POLICY:
4428 case SIOCDADDRCTL_POLICY:
4429 case SIOCDRADD_IN6_32:
4430 case SIOCDRADD_IN6_64:
4431 case SIOCDRDEL_IN6_32:
4432 case SIOCDRDEL_IN6_64:
4433 ;
4434 }
4435}
4436
4437void
4438in6_ip6_to_sockaddr(const struct in6_addr *ip6, u_int16_t port, uint32_t ifscope,
4439 struct sockaddr_in6 *sin6, u_int32_t maxlen)
4440{
4441 if (maxlen < sizeof(struct sockaddr_in6)) {
4442 return;
4443 }
4444
4445 *sin6 = (struct sockaddr_in6) {
4446 .sin6_family = AF_INET6,
4447 .sin6_len = sizeof(*sin6),
4448 .sin6_port = port,
4449 .sin6_addr = *ip6,
4450 .sin6_scope_id = IN6_IS_SCOPE_EMBED(ip6) ? ifscope : IFSCOPE_NONE,
4451 };
4452
4453 if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) {
4454 in6_verify_ifscope(&sin6->sin6_addr, ifscope);
4455 if (in6_embedded_scope) {
4456 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
4457 sin6->sin6_addr.s6_addr16[1] = 0;
4458 }
4459 }
4460}
4461
4462/* IPv6 events */
4463struct in6_event {
4464 in6_evhdlr_code_t in6_event_code;
4465 struct ifnet *in6_ifp;
4466 struct in6_addr in6_address;
4467 uint32_t val;
4468};
4469
4470struct in6_event2kev in6_event2kev_array[IN6_EVENT_MAX] = {
4471 {
4472 .in6_event_code = IN6_ADDR_MARKED_DUPLICATED,
4473 .in6_event_kev_subclass = KEV_ND6_SUBCLASS,
4474 .in6_event_kev_code = KEV_ND6_DAD_FAILURE,
4475 .in6_event_str = "IN6_ADDR_MARKED_DUPLICATED",
4476 },
4477 {
4478 .in6_event_code = IN6_ADDR_MARKED_DETACHED,
4479 .in6_event_kev_subclass = KEV_ND6_SUBCLASS,
4480 .in6_event_kev_code = KEV_ND6_ADDR_DETACHED,
4481 .in6_event_str = "IN6_ADDR_MARKED_DETACHED",
4482 },
4483 {
4484 .in6_event_code = IN6_ADDR_MARKED_DEPRECATED,
4485 .in6_event_kev_subclass = KEV_ND6_SUBCLASS,
4486 .in6_event_kev_code = KEV_ND6_ADDR_DEPRECATED,
4487 .in6_event_str = "IN6_ADDR_MARKED_DEPRECATED",
4488 },
4489 {
4490 .in6_event_code = IN6_NDP_RTR_EXPIRY,
4491 .in6_event_kev_subclass = KEV_ND6_SUBCLASS,
4492 .in6_event_kev_code = KEV_ND6_RTR_EXPIRED,
4493 .in6_event_str = "IN6_NDP_RTR_EXPIRY",
4494 },
4495 {
4496 .in6_event_code = IN6_NDP_PFX_EXPIRY,
4497 .in6_event_kev_subclass = KEV_ND6_SUBCLASS,
4498 .in6_event_kev_code = KEV_ND6_PFX_EXPIRED,
4499 .in6_event_str = "IN6_NDP_PFX_EXPIRY",
4500 },
4501 {
4502 .in6_event_code = IN6_NDP_ADDR_EXPIRY,
4503 .in6_event_kev_subclass = KEV_ND6_SUBCLASS,
4504 .in6_event_kev_code = KEV_ND6_ADDR_EXPIRED,
4505 .in6_event_str = "IN6_NDP_ADDR_EXPIRY",
4506 },
4507};
4508
4509void
4510in6_eventhdlr_callback(struct eventhandler_entry_arg arg0 __unused,
4511 in6_evhdlr_code_t in6_ev_code, struct ifnet *ifp,
4512 struct in6_addr *p_addr6, uint32_t val)
4513{
4514 struct kev_msg ev_msg;
4515 struct kev_nd6_event nd6_event;
4516
4517 bzero(s: &ev_msg, n: sizeof(ev_msg));
4518 bzero(s: &nd6_event, n: sizeof(nd6_event));
4519
4520 nd6log0(info, "%s Event %s received for %s\n",
4521 __func__, in6_event2kev_array[in6_ev_code].in6_event_str,
4522 ip6_sprintf(p_addr6));
4523
4524 ev_msg.vendor_code = KEV_VENDOR_APPLE;
4525 ev_msg.kev_class = KEV_NETWORK_CLASS;
4526 ev_msg.kev_subclass =
4527 in6_event2kev_array[in6_ev_code].in6_event_kev_subclass;
4528 ev_msg.event_code =
4529 in6_event2kev_array[in6_ev_code].in6_event_kev_code;
4530
4531 nd6_event.link_data.if_family = ifp->if_family;
4532 nd6_event.link_data.if_unit = ifp->if_unit;
4533 strlcpy(dst: nd6_event.link_data.if_name, src: ifp->if_name,
4534 n: sizeof(nd6_event.link_data.if_name));
4535
4536 VERIFY(p_addr6 != NULL);
4537 bcopy(src: p_addr6, dst: &nd6_event.in6_address,
4538 n: sizeof(nd6_event.in6_address));
4539 nd6_event.val = val;
4540
4541 ev_msg.dv[0].data_ptr = &nd6_event;
4542 ev_msg.dv[0].data_length = sizeof(nd6_event);
4543
4544 kev_post_msg(event: &ev_msg);
4545}
4546
4547struct in6_event_nwk_wq_entry {
4548 struct nwk_wq_entry nwk_wqe;
4549 struct in6_event in6_ev_arg;
4550};
4551
4552static void
4553in6_event_callback(struct nwk_wq_entry *nwk_item)
4554{
4555 struct in6_event_nwk_wq_entry *p_ev;
4556
4557 p_ev = __container_of(nwk_item, struct in6_event_nwk_wq_entry, nwk_wqe);
4558
4559 EVENTHANDLER_INVOKE(&in6_evhdlr_ctxt, in6_event,
4560 p_ev->in6_ev_arg.in6_event_code, p_ev->in6_ev_arg.in6_ifp,
4561 &p_ev->in6_ev_arg.in6_address, p_ev->in6_ev_arg.val);
4562
4563 kfree_type(struct in6_event_nwk_wq_entry, p_ev);
4564}
4565
4566void
4567in6_event_enqueue_nwk_wq_entry(in6_evhdlr_code_t in6_event_code,
4568 struct ifnet *ifp, struct in6_addr *p_addr6,
4569 uint32_t val)
4570{
4571 struct in6_event_nwk_wq_entry *p_in6_ev = NULL;
4572
4573 p_in6_ev = kalloc_type(struct in6_event_nwk_wq_entry,
4574 Z_WAITOK | Z_ZERO | Z_NOFAIL);
4575
4576 p_in6_ev->nwk_wqe.func = in6_event_callback;
4577 p_in6_ev->in6_ev_arg.in6_event_code = in6_event_code;
4578 p_in6_ev->in6_ev_arg.in6_ifp = ifp;
4579 if (p_addr6 != NULL) {
4580 bcopy(src: p_addr6, dst: &p_in6_ev->in6_ev_arg.in6_address,
4581 n: sizeof(p_in6_ev->in6_ev_arg.in6_address));
4582 }
4583 p_in6_ev->in6_ev_arg.val = val;
4584
4585 nwk_wq_enqueue(nwk_item: &p_in6_ev->nwk_wqe);
4586}
4587
4588/*
4589 * Caller must hold in6_ifaddr_rwlock as writer.
4590 */
4591static void
4592in6_iahash_remove(struct in6_ifaddr *ia)
4593{
4594 LCK_RW_ASSERT(&in6_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
4595 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
4596
4597 if (!IA6_IS_HASHED(ia)) {
4598 panic("%s: attempt to remove wrong ia %p from ipv6 hash table", __func__, ia);
4599 /* NOTREACHED */
4600 }
4601 TAILQ_REMOVE(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash);
4602 IA6_HASH_INIT(ia);
4603 ifa_remref(ifa: &ia->ia_ifa);
4604}
4605
4606/*
4607 * Caller must hold in6_ifaddr_rwlock as writer.
4608 */
4609static void
4610in6_iahash_insert(struct in6_ifaddr *ia)
4611{
4612 LCK_RW_ASSERT(&in6_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
4613 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
4614
4615 if (ia->ia_addr.sin6_family != AF_INET6) {
4616 panic("%s: attempt to insert wrong ia %p into hash table", __func__, ia);
4617 /* NOTREACHED */
4618 } else if (IA6_IS_HASHED(ia)) {
4619 panic("%s: attempt to double-insert ia %p into hash table", __func__, ia);
4620 /* NOTREACHED */
4621 }
4622 TAILQ_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr),
4623 ia, ia6_hash);
4624 ifa_addref(ifa: &ia->ia_ifa);
4625}
4626
4627/*
4628 * Some point to point interfaces that are tunnels borrow the address from
4629 * an underlying interface (e.g. VPN server). In order for source address
4630 * selection logic to find the underlying interface first, we add the address
4631 * of borrowing point to point interfaces at the end of the list.
4632 * (see rdar://6733789)
4633 *
4634 * Caller must hold in6_ifaddr_rwlock as writer.
4635 */
4636static void
4637in6_iahash_insert_ptp(struct in6_ifaddr *ia)
4638{
4639 struct in6_ifaddr *tmp_ifa;
4640 struct ifnet *tmp_ifp;
4641
4642 LCK_RW_ASSERT(&in6_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
4643 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
4644
4645 if (ia->ia_addr.sin6_family != AF_INET6) {
4646 panic("%s: attempt to insert wrong ia %p into hash table", __func__, ia);
4647 /* NOTREACHED */
4648 } else if (IA6_IS_HASHED(ia)) {
4649 panic("%s: attempt to double-insert ia %p into hash table", __func__, ia);
4650 /* NOTREACHED */
4651 }
4652 IFA_UNLOCK(&ia->ia_ifa);
4653 TAILQ_FOREACH(tmp_ifa, IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia6_hash) {
4654 IFA_LOCK(&tmp_ifa->ia_ifa);
4655 /* ia->ia_addr won't change, so check without lock */
4656 if (in6_are_addr_equal_scoped(&tmp_ifa->ia_addr.sin6_addr, &ia->ia_addr.sin6_addr, tmp_ifa->ia_addr.sin6_scope_id, ia->ia_addr.sin6_scope_id)) {
4657 IFA_UNLOCK(&tmp_ifa->ia_ifa);
4658 break;
4659 }
4660 IFA_UNLOCK(&tmp_ifa->ia_ifa);
4661 }
4662 tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
4663
4664 IFA_LOCK(&ia->ia_ifa);
4665 if (tmp_ifp == NULL) {
4666 TAILQ_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr),
4667 ia, ia6_hash);
4668 } else {
4669 TAILQ_INSERT_TAIL(IN6ADDR_HASH(&ia->ia_addr.sin6_addr),
4670 ia, ia6_hash);
4671 }
4672 ifa_addref(ifa: &ia->ia_ifa);
4673}
4674
4675/*
4676 * ipv6 socket options.
4677 *
4678 * The switch statement below does nothing at runtime, as it serves as a
4679 * compile time check to ensure that all of the ipv6 socket options are
4680 * unique. This works as long as this routine gets updated each time a
4681 * new ipv6 socket option gets added.
4682 *
4683 * Any failures at compile time indicates duplicated ipv6 socket option
4684 * values.
4685 */
4686static __attribute__((unused)) void
4687tcpsockopt_cassert(void)
4688{
4689 /*
4690 * This is equivalent to _CASSERT() and the compiler wouldn't
4691 * generate any instructions, thus for compile time only.
4692 */
4693 switch ((int)0) {
4694 case 0:
4695
4696 /* bsd/netinet6/in6.h */
4697 case IPV6_SOCKOPT_RESERVED1:
4698 case IPV6_UNICAST_HOPS:
4699 case IPV6_MULTICAST_IF:
4700 case IPV6_MULTICAST_HOPS:
4701 case IPV6_MULTICAST_LOOP:
4702 case IPV6_JOIN_GROUP:
4703 case IPV6_LEAVE_GROUP:
4704 case IPV6_PORTRANGE:
4705 case ICMP6_FILTER:
4706 case IPV6_2292PKTINFO:
4707 case IPV6_2292HOPLIMIT:
4708 case IPV6_2292NEXTHOP:
4709 case IPV6_2292HOPOPTS:
4710 case IPV6_2292DSTOPTS:
4711 case IPV6_2292RTHDR:
4712 case IPV6_2292PKTOPTIONS:
4713#ifdef __APPLE_USE_RFC_2292
4714// #define IPV6_PKTINFO IPV6_3542PKTINFO
4715// #define IPV6_HOPLIMIT IPV6_3542HOPLIMIT
4716// #define IPV6_NEXTHOP IPV6_3542NEXTHOP
4717// #define IPV6_HOPOPTS IPV6_3542HOPOPTS
4718// #define IPV6_DSTOPTS IPV6_3542DSTOPTS
4719// #define IPV6_RTHDR IPV6_3542RTHDR
4720 case IPV6_PKTOPTIONS:
4721#endif /* __APPLE_USE_RFC_2292 */
4722 case IPV6_CHECKSUM:
4723 case IPV6_V6ONLY:
4724#ifndef KERNEL
4725// #define IPV6_BINDV6ONLY IPV6_V6ONLY
4726#endif /* KERNEL */
4727 case IPV6_IPSEC_POLICY:
4728 case IPV6_FAITH:
4729 case IPV6_FW_ADD:
4730 case IPV6_FW_DEL:
4731 case IPV6_FW_FLUSH:
4732 case IPV6_FW_ZERO:
4733 case IPV6_FW_GET:
4734 case IPV6_RECVTCLASS:
4735 case IPV6_TCLASS:
4736#ifdef __APPLE_USE_RFC_3542
4737 case IPV6_RTHDRDSTOPTS:
4738 case IPV6_RECVPKTINFO:
4739 case IPV6_RECVHOPLIMIT:
4740 case IPV6_RECVRTHDR:
4741 case IPV6_RECVHOPOPTS:
4742 case IPV6_RECVDSTOPTS:
4743#ifdef KERNEL
4744 case IPV6_RECVRTHDRDSTOPTS:
4745#endif
4746 case IPV6_USE_MIN_MTU:
4747 case IPV6_RECVPATHMTU:
4748 case IPV6_PATHMTU:
4749 case IPV6_3542PKTINFO:
4750 case IPV6_3542HOPLIMIT:
4751 case IPV6_3542NEXTHOP:
4752 case IPV6_3542HOPOPTS:
4753 case IPV6_3542DSTOPTS:
4754 case IPV6_3542RTHDR:
4755// #define IPV6_PKTINFO IPV6_3542PKTINFO
4756// #define IPV6_HOPLIMIT IPV6_3542HOPLIMIT
4757// #define IPV6_NEXTHOP IPV6_3542NEXTHOP
4758// #define IPV6_HOPOPTS IPV6_3542HOPOPTS
4759// #define IPV6_DSTOPTS IPV6_3542DSTOPTS
4760// #define IPV6_RTHDR IPV6_3542RTHDR
4761 case IPV6_AUTOFLOWLABEL:
4762 case IPV6_DONTFRAG:
4763 case IPV6_PREFER_TEMPADDR:
4764 case IPV6_MSFILTER:
4765#endif /* __APPLE_USE_RFC_3542 */
4766 case IPV6_BOUND_IF:
4767
4768 /* bsd/netinet6/in6_private.h */
4769 case IPV6_NO_IFT_CELLULAR:
4770 case IPV6_OUT_IF:
4771 ;
4772 }
4773}
4774