xref: /xnu-8792.81.2/bsd/net/if.c (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1 /*
2  * Copyright (c) 2000-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  * Copyright (c) 1980, 1986, 1993
30  *	The Regents of the University of California.  All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  * 2. Redistributions in binary form must reproduce the above copyright
38  *    notice, this list of conditions and the following disclaimer in the
39  *    documentation and/or other materials provided with the distribution.
40  * 3. All advertising materials mentioning features or use of this software
41  *    must display the following acknowledgement:
42  *	This product includes software developed by the University of
43  *	California, Berkeley and its contributors.
44  * 4. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  *	@(#)if.c	8.3 (Berkeley) 1/4/94
61  * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $
62  */
63 /*
64  * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
65  * support for mandatory and extensible security protections.  This notice
66  * is included in support of clause 2.2 (b) of the Apple Public License,
67  * Version 2.0.
68  */
69 
70 #include <kern/locks.h>
71 
72 #include <sys/param.h>
73 #include <sys/malloc.h>
74 #include <sys/mbuf.h>
75 #include <sys/systm.h>
76 #include <sys/proc.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/protosw.h>
80 #include <sys/kernel.h>
81 #include <sys/sockio.h>
82 #include <sys/syslog.h>
83 #include <sys/sysctl.h>
84 #include <sys/mcache.h>
85 #include <sys/kauth.h>
86 #include <sys/priv.h>
87 #include <kern/zalloc.h>
88 #include <mach/boolean.h>
89 
90 #include <machine/endian.h>
91 
92 #include <pexpert/pexpert.h>
93 
94 #include <net/if.h>
95 #include <net/if_arp.h>
96 #include <net/if_dl.h>
97 #include <net/if_types.h>
98 #include <net/if_var.h>
99 #include <net/if_media.h>
100 #include <net/if_ppp.h>
101 #include <net/ethernet.h>
102 #include <net/network_agent.h>
103 #include <net/pktsched/pktsched_netem.h>
104 #include <net/radix.h>
105 #include <net/route.h>
106 #include <net/dlil.h>
107 #include <net/nwk_wq.h>
108 
109 #include <sys/domain.h>
110 #include <libkern/OSAtomic.h>
111 
112 #if INET
113 #include <netinet/in.h>
114 #include <netinet/in_var.h>
115 #include <netinet/in_tclass.h>
116 #include <netinet/ip_var.h>
117 #include <netinet/ip.h>
118 #include <netinet/ip6.h>
119 #include <netinet/ip_var.h>
120 #include <netinet/tcp.h>
121 #include <netinet/tcp_var.h>
122 #include <netinet/udp.h>
123 #include <netinet/udp_var.h>
124 #include <netinet6/in6_var.h>
125 #include <netinet6/in6_ifattach.h>
126 #include <netinet6/ip6_var.h>
127 #include <netinet6/nd6.h>
128 #endif /* INET */
129 
130 #if SKYWALK
131 #include <skywalk/nexus/netif/nx_netif.h>
132 #endif /* SKYWALK */
133 
134 #include <os/log.h>
135 
136 /*
137  * System initialization
138  */
139 
140 extern char *proc_name_address(void *);
141 
142 /* Lock group and attribute for ifaddr lock */
143 LCK_ATTR_DECLARE(ifa_mtx_attr, 0, 0);
144 LCK_GRP_DECLARE(ifa_mtx_grp, "ifaddr");
145 
146 static int ifioctl_ifreq(struct socket *, u_long, struct ifreq *,
147     struct proc *);
148 static int ifioctl_ifconf(u_long, caddr_t);
149 static int ifioctl_ifclone(u_long, caddr_t);
150 static int ifioctl_iforder(u_long, caddr_t);
151 static int ifioctl_ifdesc(struct ifnet *, u_long, caddr_t, struct proc *);
152 static int ifioctl_linkparams(struct ifnet *, u_long, caddr_t, struct proc *);
153 static int ifioctl_qstats(struct ifnet *, u_long, caddr_t);
154 static int ifioctl_throttle(struct ifnet *, u_long, caddr_t, struct proc *);
155 static int ifioctl_netsignature(struct ifnet *, u_long, caddr_t);
156 static int ifconf(u_long cmd, user_addr_t ifrp, int * ret_space);
157 __private_extern__ void link_rtrequest(int, struct rtentry *, struct sockaddr *);
158 void if_rtproto_del(struct ifnet *ifp, int protocol);
159 
160 static int if_addmulti_common(struct ifnet *, const struct sockaddr *,
161     struct ifmultiaddr **, int);
162 static int if_delmulti_common(struct ifmultiaddr *, struct ifnet *,
163     const struct sockaddr *, int);
164 static struct ifnet *ifunit_common(const char *, boolean_t);
165 
166 static int if_rtmtu(struct radix_node *, void *);
167 static void if_rtmtu_update(struct ifnet *);
168 
169 static int if_clone_list(int, int *, user_addr_t);
170 
171 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
172 
173 struct  ifnethead ifnet_head = TAILQ_HEAD_INITIALIZER(ifnet_head);
174 
175 /* ifnet_ordered_head and if_ordered_count are protected by the ifnet_head lock */
176 struct  ifnethead ifnet_ordered_head = TAILQ_HEAD_INITIALIZER(ifnet_ordered_head);
177 static  u_int32_t if_ordered_count = 0;
178 
179 static int      if_cloners_count;
180 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
181 
182 static struct ifaddr *ifa_ifwithnet_common(const struct sockaddr *,
183     unsigned int);
184 static void if_attach_ifa_common(struct ifnet *, struct ifaddr *, int);
185 static void if_detach_ifa_common(struct ifnet *, struct ifaddr *, int);
186 
187 static void if_attach_ifma(struct ifnet *, struct ifmultiaddr *, int);
188 static int if_detach_ifma(struct ifnet *, struct ifmultiaddr *, int);
189 
190 static struct ifmultiaddr *ifma_alloc(zalloc_flags_t);
191 static void ifma_free(struct ifmultiaddr *);
192 static void ifma_trace(struct ifmultiaddr *, int);
193 
194 #if DEBUG
195 static TUNABLE(bool, ifma_debug, "ifma_debug", true); /* debugging (enabled) */
196 #else
197 static TUNABLE(bool, ifma_debug, "ifma_debug", false); /* debugging (disabled) */
198 #endif /* !DEBUG */
199 static struct zone *ifma_zone;          /* zone for ifmultiaddr */
200 
201 #define IFMA_TRACE_HIST_SIZE    32      /* size of trace history */
202 
203 /* For gdb */
204 __private_extern__ unsigned int ifma_trace_hist_size = IFMA_TRACE_HIST_SIZE;
205 
206 struct ifmultiaddr_dbg {
207 	struct ifmultiaddr      ifma;                   /* ifmultiaddr */
208 	u_int16_t               ifma_refhold_cnt;       /* # of ref */
209 	u_int16_t               ifma_refrele_cnt;       /* # of rele */
210 	/*
211 	 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
212 	 */
213 	ctrace_t                ifma_refhold[IFMA_TRACE_HIST_SIZE];
214 	ctrace_t                ifma_refrele[IFMA_TRACE_HIST_SIZE];
215 	/*
216 	 * Trash list linkage
217 	 */
218 	TAILQ_ENTRY(ifmultiaddr_dbg) ifma_trash_link;
219 };
220 
221 /* List of trash ifmultiaddr entries protected by ifma_trash_lock */
222 static TAILQ_HEAD(, ifmultiaddr_dbg) ifma_trash_head;
223 static LCK_MTX_DECLARE_ATTR(ifma_trash_lock, &ifa_mtx_grp, &ifa_mtx_attr);
224 
225 #define IFMA_ZONE_MAX           64              /* maximum elements in zone */
226 #define IFMA_ZONE_NAME          "ifmultiaddr"   /* zone name */
227 
228 /*
229  * XXX: declare here to avoid to include many inet6 related files..
230  * should be more generalized?
231  */
232 extern void     nd6_setmtu(struct ifnet *);
233 
234 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "Link layers");
235 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
236     "Generic link-management");
237 
238 SYSCTL_DECL(_net_link_generic_system);
239 
240 static uint32_t if_verbose = 0;
241 SYSCTL_INT(_net_link_generic_system, OID_AUTO, if_verbose,
242     CTLFLAG_RW | CTLFLAG_LOCKED, &if_verbose, 0, "");
243 
244 #if (DEBUG || DEVELOPMENT)
245 static uint32_t default_tcp_kao_max = 0;
246 SYSCTL_INT(_net_link_generic_system, OID_AUTO, default_tcp_kao_max,
247     CTLFLAG_RW | CTLFLAG_LOCKED, &default_tcp_kao_max, 0, "");
248 #else
249 static const uint32_t default_tcp_kao_max = 0;
250 #endif /* (DEBUG || DEVELOPMENT) */
251 
252 u_int32_t companion_link_sock_buffer_limit = 0;
253 
254 static int
255 sysctl_set_companion_link_sock_buf_limit SYSCTL_HANDLER_ARGS
256 {
257 #pragma unused(arg1, arg2)
258 	int error, tmp = companion_link_sock_buffer_limit;
259 	error = sysctl_handle_int(oidp, &tmp, 0, req);
260 	if (tmp < 0) {
261 		return EINVAL;
262 	}
263 	if ((error = priv_check_cred(kauth_cred_get(),
264 	    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
265 		return error;
266 	}
267 
268 	u_int32_t new_limit = tmp;
269 	if (new_limit == companion_link_sock_buffer_limit) {
270 		return 0;
271 	}
272 
273 	bool recover = new_limit == 0 ? true : false;
274 	if (recover) {
275 		error = inp_recover_companion_link(&tcbinfo);
276 	} else {
277 		error = inp_limit_companion_link(&tcbinfo, new_limit);
278 	}
279 	if (!error) {
280 		companion_link_sock_buffer_limit = new_limit;
281 	}
282 	return error;
283 }
284 
285 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, companion_sndbuf_limit,
286     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
287     &companion_link_sock_buffer_limit, 0, sysctl_set_companion_link_sock_buf_limit,
288     "I", "set sock send buffer limit of connections using companion links");
289 
290 TUNABLE(bool, intcoproc_unrestricted, "intcoproc_unrestricted", false);
291 
292 /* Eventhandler context for interface events */
293 struct eventhandler_lists_ctxt ifnet_evhdlr_ctxt;
294 
295 void
ifa_init(void)296 ifa_init(void)
297 {
298 	size_t ifma_size = (ifma_debug == 0) ? sizeof(struct ifmultiaddr) :
299 	    sizeof(struct ifmultiaddr_dbg);
300 
301 	ifma_zone = zone_create(IFMA_ZONE_NAME, ifma_size, ZC_NONE);
302 	TAILQ_INIT(&ifma_trash_head);
303 }
304 
305 /*
306  * Network interface utility routines.
307  *
308  * Routines with ifa_ifwith* names take sockaddr *'s as
309  * parameters.
310  */
311 
312 int if_index;
313 struct ifaddr **ifnet_addrs;
314 struct ifnet **ifindex2ifnet;
315 
316 __private_extern__ void
if_attach_ifa(struct ifnet * ifp,struct ifaddr * ifa)317 if_attach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
318 {
319 	if_attach_ifa_common(ifp, ifa, 0);
320 }
321 
322 __private_extern__ void
if_attach_link_ifa(struct ifnet * ifp,struct ifaddr * ifa)323 if_attach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
324 {
325 	if_attach_ifa_common(ifp, ifa, 1);
326 }
327 
328 static void
if_attach_ifa_common(struct ifnet * ifp,struct ifaddr * ifa,int link)329 if_attach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
330 {
331 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
332 	IFA_LOCK_ASSERT_HELD(ifa);
333 
334 	if (ifa->ifa_ifp != ifp) {
335 		panic("%s: Mismatch ifa_ifp=%p != ifp=%p", __func__,
336 		    ifa->ifa_ifp, ifp);
337 		/* NOTREACHED */
338 	} else if (ifa->ifa_debug & IFD_ATTACHED) {
339 		panic("%s: Attempt to attach an already attached ifa=%p",
340 		    __func__, ifa);
341 		/* NOTREACHED */
342 	} else if (link && !(ifa->ifa_debug & IFD_LINK)) {
343 		panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
344 		/* NOTREACHED */
345 	} else if (!link && (ifa->ifa_debug & IFD_LINK)) {
346 		panic("%s: Unexpected link address ifa=%p", __func__, ifa);
347 		/* NOTREACHED */
348 	}
349 	IFA_ADDREF_LOCKED(ifa);
350 	ifa->ifa_debug |= IFD_ATTACHED;
351 
352 	if (link) {
353 		TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
354 	} else {
355 		TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
356 	}
357 
358 	if (ifa->ifa_attached != NULL) {
359 		(*ifa->ifa_attached)(ifa);
360 	}
361 
362 #if SKYWALK
363 	SK_NXS_MS_IF_ADDR_GENCNT_INC(ifp);
364 #endif /* SKYWALK */
365 }
366 
367 __private_extern__ void
if_detach_ifa(struct ifnet * ifp,struct ifaddr * ifa)368 if_detach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
369 {
370 	if_detach_ifa_common(ifp, ifa, 0);
371 }
372 
373 __private_extern__ void
if_detach_link_ifa(struct ifnet * ifp,struct ifaddr * ifa)374 if_detach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
375 {
376 	if_detach_ifa_common(ifp, ifa, 1);
377 }
378 
379 static void
if_detach_ifa_common(struct ifnet * ifp,struct ifaddr * ifa,int link)380 if_detach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
381 {
382 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
383 	IFA_LOCK_ASSERT_HELD(ifa);
384 
385 	if (link && !(ifa->ifa_debug & IFD_LINK)) {
386 		panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
387 		/* NOTREACHED */
388 	} else if (link && ifa != TAILQ_FIRST(&ifp->if_addrhead)) {
389 		panic("%s: Link address ifa=%p not first", __func__, ifa);
390 		/* NOTREACHED */
391 	} else if (!link && (ifa->ifa_debug & IFD_LINK)) {
392 		panic("%s: Unexpected link address ifa=%p", __func__, ifa);
393 		/* NOTREACHED */
394 	} else if (!(ifa->ifa_debug & IFD_ATTACHED)) {
395 		panic("%s: Attempt to detach an unattached address ifa=%p",
396 		    __func__, ifa);
397 		/* NOTREACHED */
398 	} else if (ifa->ifa_ifp != ifp) {
399 		panic("%s: Mismatch ifa_ifp=%p, ifp=%p", __func__,
400 		    ifa->ifa_ifp, ifp);
401 		/* NOTREACHED */
402 	} else if (ifa->ifa_debug & IFD_DEBUG) {
403 		struct ifaddr *ifa2;
404 		TAILQ_FOREACH(ifa2, &ifp->if_addrhead, ifa_link) {
405 			if (ifa2 == ifa) {
406 				break;
407 			}
408 		}
409 		if (ifa2 != ifa) {
410 			panic("%s: Attempt to detach a stray address ifa=%p",
411 			    __func__, ifa);
412 			/* NOTREACHED */
413 		}
414 	}
415 	TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
416 	/* This must not be the last reference to the ifaddr */
417 	if (IFA_REMREF_LOCKED(ifa) == NULL) {
418 		panic("%s: unexpected (missing) refcnt ifa=%p", __func__, ifa);
419 		/* NOTREACHED */
420 	}
421 	ifa->ifa_debug &= ~IFD_ATTACHED;
422 
423 	if (ifa->ifa_detached != NULL) {
424 		(*ifa->ifa_detached)(ifa);
425 	}
426 
427 #if SKYWALK
428 	SK_NXS_MS_IF_ADDR_GENCNT_INC(ifp);
429 #endif /* SKYWALK */
430 }
431 
432 #define INITIAL_IF_INDEXLIM     8
433 
434 /*
435  * Function: if_next_index
436  * Purpose:
437  *   Return the next available interface index.
438  *   Grow the ifnet_addrs[] and ifindex2ifnet[] arrays to accomodate the
439  *   added entry when necessary.
440  *
441  * Note:
442  *   ifnet_addrs[] is indexed by (if_index - 1), whereas
443  *   ifindex2ifnet[] is indexed by ifp->if_index.  That requires us to
444  *   always allocate one extra element to hold ifindex2ifnet[0], which
445  *   is unused.
446  */
447 int if_next_index(void);
448 
449 __private_extern__ int
if_next_index(void)450 if_next_index(void)
451 {
452 	static int      if_indexlim = 0;
453 	int             new_index;
454 
455 	/*
456 	 * Although we are returning an integer,
457 	 * ifnet's if_index is a uint16_t which means
458 	 * that's our upper bound.
459 	 */
460 	if (if_index >= UINT16_MAX) {
461 		return -1;
462 	}
463 	new_index = ++if_index;
464 	if (if_index > if_indexlim) {
465 		unsigned        n;
466 		int             new_if_indexlim;
467 		caddr_t         new_ifnet_addrs;
468 		caddr_t         new_ifindex2ifnet;
469 		caddr_t         old_ifnet_addrs;
470 		size_t          old_ifnet_size;
471 
472 		old_ifnet_addrs = (caddr_t)ifnet_addrs;
473 		old_ifnet_size = (size_t)(2 * if_indexlim + 1);
474 		if (ifnet_addrs == NULL) {
475 			new_if_indexlim = INITIAL_IF_INDEXLIM;
476 		} else {
477 			new_if_indexlim = if_indexlim << 1;
478 		}
479 
480 		/* allocate space for the larger arrays */
481 		n = (2 * new_if_indexlim + 1);
482 		new_ifnet_addrs = (caddr_t)kalloc_type(caddr_t, n, Z_WAITOK | Z_ZERO);
483 		if (new_ifnet_addrs == NULL) {
484 			--if_index;
485 			return -1;
486 		}
487 
488 		new_ifindex2ifnet = new_ifnet_addrs + new_if_indexlim * sizeof(caddr_t);
489 		if (ifnet_addrs != NULL) {
490 			/* copy the existing data */
491 			bcopy(ifnet_addrs, new_ifnet_addrs, if_indexlim * sizeof(caddr_t));
492 			bcopy(ifindex2ifnet, new_ifindex2ifnet, (if_indexlim + 1) * sizeof(caddr_t));
493 		}
494 
495 		/* switch to the new tables and size */
496 		ifnet_addrs = (struct ifaddr **)(void *)new_ifnet_addrs;
497 		ifindex2ifnet = (struct ifnet **)(void *)new_ifindex2ifnet;
498 		if_indexlim = new_if_indexlim;
499 
500 		/* release the old data */
501 		if (old_ifnet_addrs != NULL) {
502 			void *old_ifnet_addrs_p = (void *)old_ifnet_addrs;
503 			kfree_type(caddr_t, old_ifnet_size, old_ifnet_addrs_p);
504 		}
505 	}
506 	return new_index;
507 }
508 
509 /*
510  * Create a clone network interface.
511  */
512 static int
if_clone_create(char * name,int len,void * params)513 if_clone_create(char *name, int len, void *params)
514 {
515 	struct if_clone *ifc;
516 	char *dp;
517 	int wildcard;
518 	u_int32_t bytoff, bitoff;
519 	u_int32_t unit;
520 	int err;
521 
522 	ifc = if_clone_lookup(name, &unit);
523 	if (ifc == NULL) {
524 		return EINVAL;
525 	}
526 
527 	if (ifunit(name) != NULL) {
528 		return EEXIST;
529 	}
530 
531 	bytoff = bitoff = 0;
532 	wildcard = (unit == UINT32_MAX);
533 	/*
534 	 * Find a free unit if none was given.
535 	 */
536 	lck_mtx_lock(&ifc->ifc_mutex);
537 again:
538 	if (wildcard) {
539 		while ((bytoff < ifc->ifc_bmlen) &&
540 		    (ifc->ifc_units[bytoff] == 0xff)) {
541 			bytoff++;
542 		}
543 		if (bytoff >= ifc->ifc_bmlen) {
544 			lck_mtx_lock(&ifc->ifc_mutex);
545 			return ENOSPC;
546 		}
547 		while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0) {
548 			bitoff++;
549 		}
550 		unit = (bytoff << 3) + bitoff;
551 	}
552 
553 	if (unit > ifc->ifc_maxunit) {
554 		lck_mtx_unlock(&ifc->ifc_mutex);
555 		return ENXIO;
556 	}
557 
558 	err = (*ifc->ifc_create)(ifc, unit, params);
559 	if (err != 0) {
560 		if (wildcard && err == EBUSY) {
561 			bitoff++;
562 			goto again;
563 		}
564 		lck_mtx_unlock(&ifc->ifc_mutex);
565 		return err;
566 	}
567 
568 	if (!wildcard) {
569 		bytoff = unit >> 3;
570 		bitoff = unit - (bytoff << 3);
571 	}
572 
573 	/*
574 	 * Allocate the unit in the bitmap.
575 	 */
576 	KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
577 	    ("%s: bit is already set", __func__));
578 	ifc->ifc_units[bytoff] |= (1 << bitoff);
579 
580 	/* In the wildcard case, we need to update the name. */
581 	if (wildcard) {
582 		for (dp = name; *dp != '\0'; dp++) {
583 			;
584 		}
585 		if (snprintf(dp, len - (dp - name), "%d", unit) >
586 		    len - (dp - name) - 1) {
587 			/*
588 			 * This can only be a programmer error and
589 			 * there's no straightforward way to recover if
590 			 * it happens.
591 			 */
592 			panic("%s: interface name too long", __func__);
593 			/* NOTREACHED */
594 		}
595 	}
596 	lck_mtx_unlock(&ifc->ifc_mutex);
597 
598 	return 0;
599 }
600 
601 /*
602  * Destroy a clone network interface.
603  */
604 static int
if_clone_destroy(const char * name)605 if_clone_destroy(const char *name)
606 {
607 	struct if_clone *ifc = NULL;
608 	struct ifnet *ifp = NULL;
609 	int bytoff, bitoff;
610 	u_int32_t unit;
611 	int error = 0;
612 
613 	ifc = if_clone_lookup(name, &unit);
614 
615 	if (ifc == NULL) {
616 		error = EINVAL;
617 		goto done;
618 	}
619 
620 	if (unit < ifc->ifc_minifs) {
621 		error = EINVAL;
622 		goto done;
623 	}
624 
625 	ifp = ifunit_ref(name);
626 	if (ifp == NULL) {
627 		error = ENXIO;
628 		goto done;
629 	}
630 
631 	if (ifc->ifc_destroy == NULL) {
632 		error = EOPNOTSUPP;
633 		goto done;
634 	}
635 
636 	lck_mtx_lock(&ifc->ifc_mutex);
637 	error = (*ifc->ifc_destroy)(ifp);
638 
639 	if (error) {
640 		lck_mtx_unlock(&ifc->ifc_mutex);
641 		goto done;
642 	}
643 
644 	/* Compute offset in the bitmap and deallocate the unit. */
645 	bytoff = unit >> 3;
646 	bitoff = unit - (bytoff << 3);
647 	KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
648 	    ("%s: bit is already cleared", __func__));
649 	ifc->ifc_units[bytoff] &= ~(1 << bitoff);
650 	lck_mtx_unlock(&ifc->ifc_mutex);
651 
652 done:
653 	if (ifp != NULL) {
654 		ifnet_decr_iorefcnt(ifp);
655 	}
656 	return error;
657 }
658 
659 /*
660  * Look up a network interface cloner.
661  */
662 
663 __private_extern__ struct if_clone *
if_clone_lookup(const char * name,u_int32_t * unitp)664 if_clone_lookup(const char *name, u_int32_t *unitp)
665 {
666 	struct if_clone *ifc;
667 	const char *cp;
668 	u_int32_t i;
669 
670 	LIST_FOREACH(ifc, &if_cloners, ifc_list) {
671 		if (strncmp(name, ifc->ifc_name, ifc->ifc_namelen) == 0) {
672 			cp = name + ifc->ifc_namelen;
673 			goto found_name;
674 		}
675 	}
676 
677 	/* No match. */
678 	return (struct if_clone *)NULL;
679 
680 found_name:
681 	if (*cp == '\0') {
682 		i = UINT32_MAX;
683 	} else {
684 		for (i = 0; *cp != '\0'; cp++) {
685 			if (*cp < '0' || *cp > '9') {
686 				/* Bogus unit number. */
687 				return NULL;
688 			}
689 			i = (i * 10) + (*cp - '0');
690 		}
691 	}
692 
693 	if (unitp != NULL) {
694 		*unitp = i;
695 	}
696 	return ifc;
697 }
698 
699 void *
if_clone_softc_allocate(const struct if_clone * ifc)700 if_clone_softc_allocate(const struct if_clone *ifc)
701 {
702 	VERIFY(ifc != NULL);
703 
704 	return zalloc_flags(ifc->ifc_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
705 }
706 
707 void
if_clone_softc_deallocate(const struct if_clone * ifc,void * p_softc)708 if_clone_softc_deallocate(const struct if_clone *ifc, void *p_softc)
709 {
710 	VERIFY(ifc != NULL && p_softc != NULL);
711 	bzero(p_softc, ifc->ifc_softc_size);
712 	zfree(ifc->ifc_zone, p_softc);
713 }
714 
715 /*
716  * Register a network interface cloner.
717  */
718 int
if_clone_attach(struct if_clone * ifc)719 if_clone_attach(struct if_clone *ifc)
720 {
721 	int bytoff, bitoff;
722 	int err;
723 	int len, maxclone;
724 	u_int32_t unit;
725 
726 	KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
727 	    ("%s: %s requested more units then allowed (%d > %d)",
728 	    __func__, ifc->ifc_name, ifc->ifc_minifs,
729 	    ifc->ifc_maxunit + 1));
730 	/*
731 	 * Compute bitmap size and allocate it.
732 	 */
733 	maxclone = ifc->ifc_maxunit + 1;
734 	len = maxclone >> 3;
735 	if ((len << 3) < maxclone) {
736 		len++;
737 	}
738 	ifc->ifc_units = (unsigned char *)kalloc_data(len, Z_WAITOK | Z_ZERO);
739 	if (ifc->ifc_units == NULL) {
740 		return ENOBUFS;
741 	}
742 	ifc->ifc_bmlen = len;
743 	lck_mtx_init(&ifc->ifc_mutex, &ifnet_lock_group, &ifnet_lock_attr);
744 
745 	if (ifc->ifc_softc_size != 0) {
746 		ifc->ifc_zone = zone_create(ifc->ifc_name, ifc->ifc_softc_size,
747 		    ZC_PGZ_USE_GUARDS | ZC_ZFREE_CLEARMEM);
748 	}
749 
750 	LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
751 	if_cloners_count++;
752 
753 	for (unit = 0; unit < ifc->ifc_minifs; unit++) {
754 		err = (*ifc->ifc_create)(ifc, unit, NULL);
755 		KASSERT(err == 0,
756 		    ("%s: failed to create required interface %s%d",
757 		    __func__, ifc->ifc_name, unit));
758 
759 		/* Allocate the unit in the bitmap. */
760 		bytoff = unit >> 3;
761 		bitoff = unit - (bytoff << 3);
762 		ifc->ifc_units[bytoff] |= (1 << bitoff);
763 	}
764 
765 	return 0;
766 }
767 
768 /*
769  * Unregister a network interface cloner.
770  */
771 void
if_clone_detach(struct if_clone * ifc)772 if_clone_detach(struct if_clone *ifc)
773 {
774 	LIST_REMOVE(ifc, ifc_list);
775 	kfree_data(ifc->ifc_units, ifc->ifc_bmlen);
776 	if (ifc->ifc_softc_size != 0) {
777 		zdestroy(ifc->ifc_zone);
778 	}
779 
780 	lck_mtx_destroy(&ifc->ifc_mutex, &ifnet_lock_group);
781 	if_cloners_count--;
782 }
783 
784 /*
785  * Provide list of interface cloners to userspace.
786  */
787 static int
if_clone_list(int count,int * ret_total,user_addr_t dst)788 if_clone_list(int count, int *ret_total, user_addr_t dst)
789 {
790 	char outbuf[IFNAMSIZ];
791 	struct if_clone *ifc;
792 	int error = 0;
793 
794 	*ret_total = if_cloners_count;
795 	if (dst == USER_ADDR_NULL) {
796 		/* Just asking how many there are. */
797 		return 0;
798 	}
799 
800 	if (count < 0) {
801 		return EINVAL;
802 	}
803 
804 	count = (if_cloners_count < count) ? if_cloners_count : count;
805 
806 	for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
807 	    ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
808 		bzero(outbuf, sizeof(outbuf));
809 		strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
810 		error = copyout(outbuf, dst, IFNAMSIZ);
811 		if (error) {
812 			break;
813 		}
814 	}
815 
816 	return error;
817 }
818 
819 u_int32_t
if_functional_type(struct ifnet * ifp,bool exclude_delegate)820 if_functional_type(struct ifnet *ifp, bool exclude_delegate)
821 {
822 	u_int32_t ret = IFRTYPE_FUNCTIONAL_UNKNOWN;
823 
824 	if (ifp != NULL) {
825 		if (ifp->if_flags & IFF_LOOPBACK) {
826 			ret = IFRTYPE_FUNCTIONAL_LOOPBACK;
827 		} else if (IFNET_IS_COMPANION_LINK(ifp)) {
828 			ret = IFRTYPE_FUNCTIONAL_COMPANIONLINK;
829 		} else if ((exclude_delegate &&
830 		    (ifp->if_family == IFNET_FAMILY_ETHERNET &&
831 		    ifp->if_subfamily == IFNET_SUBFAMILY_WIFI)) ||
832 		    (!exclude_delegate && IFNET_IS_WIFI(ifp))) {
833 			if (ifp->if_eflags & IFEF_AWDL) {
834 				ret = IFRTYPE_FUNCTIONAL_WIFI_AWDL;
835 			} else {
836 				ret = IFRTYPE_FUNCTIONAL_WIFI_INFRA;
837 			}
838 		} else if ((exclude_delegate &&
839 		    (ifp->if_type == IFT_CELLULAR ||
840 		    (ifp->if_family == IFNET_FAMILY_ETHERNET &&
841 		    ifp->if_subfamily == IFNET_SUBFAMILY_SIMCELL))) ||
842 		    (!exclude_delegate && IFNET_IS_CELLULAR(ifp))) {
843 			ret = IFRTYPE_FUNCTIONAL_CELLULAR;
844 		} else if (IFNET_IS_INTCOPROC(ifp)) {
845 			ret = IFRTYPE_FUNCTIONAL_INTCOPROC;
846 		} else if ((exclude_delegate &&
847 		    (ifp->if_family == IFNET_FAMILY_ETHERNET ||
848 		    ifp->if_family == IFNET_FAMILY_BOND ||
849 		    ifp->if_family == IFNET_FAMILY_VLAN ||
850 		    ifp->if_family == IFNET_FAMILY_FIREWIRE)) ||
851 		    (!exclude_delegate && IFNET_IS_WIRED(ifp))) {
852 			ret = IFRTYPE_FUNCTIONAL_WIRED;
853 		}
854 	}
855 
856 	return ret;
857 }
858 
859 /*
860  * Similar to ifa_ifwithaddr, except that this is IPv4 specific
861  * and that it matches only the local (not broadcast) address.
862  */
863 __private_extern__ struct in_ifaddr *
ifa_foraddr(unsigned int addr)864 ifa_foraddr(unsigned int addr)
865 {
866 	return ifa_foraddr_scoped(addr, IFSCOPE_NONE);
867 }
868 
869 /*
870  * Similar to ifa_foraddr, except with the added interface scope
871  * constraint (unless the caller passes in IFSCOPE_NONE in which
872  * case there is no scope restriction).
873  */
874 __private_extern__ struct in_ifaddr *
ifa_foraddr_scoped(unsigned int addr,unsigned int scope)875 ifa_foraddr_scoped(unsigned int addr, unsigned int scope)
876 {
877 	struct in_ifaddr *ia = NULL;
878 
879 	lck_rw_lock_shared(&in_ifaddr_rwlock);
880 	TAILQ_FOREACH(ia, INADDR_HASH(addr), ia_hash) {
881 		IFA_LOCK_SPIN(&ia->ia_ifa);
882 		if (ia->ia_addr.sin_addr.s_addr == addr &&
883 		    (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
884 			IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
885 			IFA_UNLOCK(&ia->ia_ifa);
886 			break;
887 		}
888 		IFA_UNLOCK(&ia->ia_ifa);
889 	}
890 	lck_rw_done(&in_ifaddr_rwlock);
891 	return ia;
892 }
893 
894 /*
895  * Similar to ifa_foraddr, except that this for IPv6.
896  */
897 __private_extern__ struct in6_ifaddr *
ifa_foraddr6(struct in6_addr * addr6)898 ifa_foraddr6(struct in6_addr *addr6)
899 {
900 	return ifa_foraddr6_scoped(addr6, IFSCOPE_NONE);
901 }
902 
903 __private_extern__ struct in6_ifaddr *
ifa_foraddr6_scoped(struct in6_addr * addr6,unsigned int scope)904 ifa_foraddr6_scoped(struct in6_addr *addr6, unsigned int scope)
905 {
906 	struct in6_ifaddr *ia = NULL;
907 
908 	lck_rw_lock_shared(&in6_ifaddr_rwlock);
909 	TAILQ_FOREACH(ia, IN6ADDR_HASH(addr6), ia6_hash) {
910 		IFA_LOCK(&ia->ia_ifa);
911 		if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, addr6) &&
912 		    (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
913 			IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
914 			IFA_UNLOCK(&ia->ia_ifa);
915 			break;
916 		}
917 		IFA_UNLOCK(&ia->ia_ifa);
918 	}
919 	lck_rw_done(&in6_ifaddr_rwlock);
920 
921 	return ia;
922 }
923 
924 /*
925  * Return the first (primary) address of a given family on an interface.
926  */
927 __private_extern__ struct ifaddr *
ifa_ifpgetprimary(struct ifnet * ifp,int family)928 ifa_ifpgetprimary(struct ifnet *ifp, int family)
929 {
930 	struct ifaddr *ifa;
931 
932 	ifnet_lock_shared(ifp);
933 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
934 		IFA_LOCK_SPIN(ifa);
935 		if (ifa->ifa_addr->sa_family == family) {
936 			IFA_ADDREF_LOCKED(ifa); /* for caller */
937 			IFA_UNLOCK(ifa);
938 			break;
939 		}
940 		IFA_UNLOCK(ifa);
941 	}
942 	ifnet_lock_done(ifp);
943 
944 	return ifa;
945 }
946 
947 inline boolean_t
sa_equal(const struct sockaddr * sa1,const struct sockaddr * sa2)948 sa_equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
949 {
950 	if (!sa1 || !sa2) {
951 		return FALSE;
952 	}
953 	if (sa1->sa_len != sa2->sa_len) {
954 		return FALSE;
955 	}
956 
957 	return bcmp(sa1, sa2, sa1->sa_len) == 0;
958 }
959 
960 /*
961  * Locate an interface based on a complete address.
962  */
963 struct ifaddr *
ifa_ifwithaddr_locked(const struct sockaddr * addr)964 ifa_ifwithaddr_locked(const struct sockaddr *addr)
965 {
966 	struct ifnet *ifp;
967 	struct ifaddr *ifa;
968 	struct ifaddr *result = NULL;
969 
970 	for (ifp = ifnet_head.tqh_first; ifp && !result;
971 	    ifp = ifp->if_link.tqe_next) {
972 		ifnet_lock_shared(ifp);
973 		for (ifa = ifp->if_addrhead.tqh_first; ifa;
974 		    ifa = ifa->ifa_link.tqe_next) {
975 			IFA_LOCK_SPIN(ifa);
976 			if (ifa->ifa_addr->sa_family != addr->sa_family) {
977 				IFA_UNLOCK(ifa);
978 				continue;
979 			}
980 			if (sa_equal(addr, ifa->ifa_addr)) {
981 				result = ifa;
982 				IFA_ADDREF_LOCKED(ifa); /* for caller */
983 				IFA_UNLOCK(ifa);
984 				break;
985 			}
986 			if ((ifp->if_flags & IFF_BROADCAST) &&
987 			    ifa->ifa_broadaddr != NULL &&
988 			    /* IP6 doesn't have broadcast */
989 			    ifa->ifa_broadaddr->sa_len != 0 &&
990 			    sa_equal(ifa->ifa_broadaddr, addr)) {
991 				result = ifa;
992 				IFA_ADDREF_LOCKED(ifa); /* for caller */
993 				IFA_UNLOCK(ifa);
994 				break;
995 			}
996 			IFA_UNLOCK(ifa);
997 		}
998 		ifnet_lock_done(ifp);
999 	}
1000 
1001 	return result;
1002 }
1003 
1004 struct ifaddr *
ifa_ifwithaddr(const struct sockaddr * addr)1005 ifa_ifwithaddr(const struct sockaddr *addr)
1006 {
1007 	struct ifaddr *result = NULL;
1008 
1009 	ifnet_head_lock_shared();
1010 
1011 	result = ifa_ifwithaddr_locked(addr);
1012 
1013 	ifnet_head_done();
1014 
1015 	return result;
1016 }
1017 /*
1018  * Locate the point to point interface with a given destination address.
1019  */
1020 /*ARGSUSED*/
1021 struct ifaddr *
ifa_ifwithdstaddr(const struct sockaddr * addr)1022 ifa_ifwithdstaddr(const struct sockaddr *addr)
1023 {
1024 	struct ifnet *ifp;
1025 	struct ifaddr *ifa;
1026 	struct ifaddr *result = NULL;
1027 
1028 	ifnet_head_lock_shared();
1029 	for (ifp = ifnet_head.tqh_first; ifp && !result;
1030 	    ifp = ifp->if_link.tqe_next) {
1031 		if ((ifp->if_flags & IFF_POINTOPOINT)) {
1032 			ifnet_lock_shared(ifp);
1033 			for (ifa = ifp->if_addrhead.tqh_first; ifa;
1034 			    ifa = ifa->ifa_link.tqe_next) {
1035 				IFA_LOCK_SPIN(ifa);
1036 				if (ifa->ifa_addr->sa_family !=
1037 				    addr->sa_family) {
1038 					IFA_UNLOCK(ifa);
1039 					continue;
1040 				}
1041 				if (sa_equal(addr, ifa->ifa_dstaddr)) {
1042 					result = ifa;
1043 					IFA_ADDREF_LOCKED(ifa); /* for caller */
1044 					IFA_UNLOCK(ifa);
1045 					break;
1046 				}
1047 				IFA_UNLOCK(ifa);
1048 			}
1049 			ifnet_lock_done(ifp);
1050 		}
1051 	}
1052 	ifnet_head_done();
1053 	return result;
1054 }
1055 
1056 /*
1057  * Locate the source address of an interface based on a complete address.
1058  */
1059 struct ifaddr *
ifa_ifwithaddr_scoped_locked(const struct sockaddr * addr,unsigned int ifscope)1060 ifa_ifwithaddr_scoped_locked(const struct sockaddr *addr, unsigned int ifscope)
1061 {
1062 	struct ifaddr *result = NULL;
1063 	struct ifnet *ifp;
1064 
1065 	if (ifscope == IFSCOPE_NONE) {
1066 		return ifa_ifwithaddr_locked(addr);
1067 	}
1068 
1069 	if (ifscope > (unsigned int)if_index) {
1070 		return NULL;
1071 	}
1072 
1073 	ifp = ifindex2ifnet[ifscope];
1074 	if (ifp != NULL) {
1075 		struct ifaddr *ifa = NULL;
1076 
1077 		/*
1078 		 * This is suboptimal; there should be a better way
1079 		 * to search for a given address of an interface
1080 		 * for any given address family.
1081 		 */
1082 		ifnet_lock_shared(ifp);
1083 		for (ifa = ifp->if_addrhead.tqh_first; ifa != NULL;
1084 		    ifa = ifa->ifa_link.tqe_next) {
1085 			IFA_LOCK_SPIN(ifa);
1086 			if (ifa->ifa_addr->sa_family != addr->sa_family) {
1087 				IFA_UNLOCK(ifa);
1088 				continue;
1089 			}
1090 			if (sa_equal(addr, ifa->ifa_addr)) {
1091 				result = ifa;
1092 				IFA_ADDREF_LOCKED(ifa); /* for caller */
1093 				IFA_UNLOCK(ifa);
1094 				break;
1095 			}
1096 			if ((ifp->if_flags & IFF_BROADCAST) &&
1097 			    ifa->ifa_broadaddr != NULL &&
1098 			    /* IP6 doesn't have broadcast */
1099 			    ifa->ifa_broadaddr->sa_len != 0 &&
1100 			    sa_equal(ifa->ifa_broadaddr, addr)) {
1101 				result = ifa;
1102 				IFA_ADDREF_LOCKED(ifa); /* for caller */
1103 				IFA_UNLOCK(ifa);
1104 				break;
1105 			}
1106 			IFA_UNLOCK(ifa);
1107 		}
1108 		ifnet_lock_done(ifp);
1109 	}
1110 
1111 	return result;
1112 }
1113 
1114 struct ifaddr *
ifa_ifwithaddr_scoped(const struct sockaddr * addr,unsigned int ifscope)1115 ifa_ifwithaddr_scoped(const struct sockaddr *addr, unsigned int ifscope)
1116 {
1117 	struct ifaddr *result = NULL;
1118 
1119 	ifnet_head_lock_shared();
1120 
1121 	result = ifa_ifwithaddr_scoped_locked(addr, ifscope);
1122 
1123 	ifnet_head_done();
1124 
1125 	return result;
1126 }
1127 
1128 struct ifaddr *
ifa_ifwithnet(const struct sockaddr * addr)1129 ifa_ifwithnet(const struct sockaddr *addr)
1130 {
1131 	return ifa_ifwithnet_common(addr, IFSCOPE_NONE);
1132 }
1133 
1134 struct ifaddr *
ifa_ifwithnet_scoped(const struct sockaddr * addr,unsigned int ifscope)1135 ifa_ifwithnet_scoped(const struct sockaddr *addr, unsigned int ifscope)
1136 {
1137 	return ifa_ifwithnet_common(addr, ifscope);
1138 }
1139 
1140 /*
1141  * Find an interface on a specific network.  If many, choice
1142  * is most specific found.
1143  */
1144 static struct ifaddr *
ifa_ifwithnet_common(const struct sockaddr * addr,unsigned int ifscope)1145 ifa_ifwithnet_common(const struct sockaddr *addr, unsigned int ifscope)
1146 {
1147 	struct ifnet *ifp;
1148 	struct ifaddr *ifa = NULL;
1149 	struct ifaddr *ifa_maybe = NULL;
1150 	u_int af = addr->sa_family;
1151 	const char *addr_data = addr->sa_data, *cplim;
1152 	const struct sockaddr_in6 *sock_addr = (const struct sockaddr_in6*)(const void*)addr;
1153 
1154 	if (af != AF_INET && af != AF_INET6) {
1155 		ifscope = IFSCOPE_NONE;
1156 	}
1157 
1158 	ifnet_head_lock_shared();
1159 	/*
1160 	 * AF_LINK addresses can be looked up directly by their index number,
1161 	 * so do that if we can.
1162 	 */
1163 	if (af == AF_LINK) {
1164 		const struct sockaddr_dl *sdl =
1165 		    (const struct sockaddr_dl *)(uintptr_t)(size_t)addr;
1166 		if (sdl->sdl_index && sdl->sdl_index <= if_index) {
1167 			ifa = ifnet_addrs[sdl->sdl_index - 1];
1168 			if (ifa != NULL) {
1169 				IFA_ADDREF(ifa);
1170 			}
1171 
1172 			ifnet_head_done();
1173 			return ifa;
1174 		}
1175 	}
1176 
1177 	if (!in6_embedded_scope && af == AF_INET6 &&
1178 	    IN6_IS_SCOPE_EMBED(&sock_addr->sin6_addr)) {
1179 		VERIFY(ifscope != IFSCOPE_NONE);
1180 	}
1181 
1182 	/*
1183 	 * Scan though each interface, looking for ones that have
1184 	 * addresses in this address family.
1185 	 */
1186 	for (ifp = ifnet_head.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
1187 		ifnet_lock_shared(ifp);
1188 		for (ifa = ifp->if_addrhead.tqh_first; ifa;
1189 		    ifa = ifa->ifa_link.tqe_next) {
1190 			const char *cp, *cp2, *cp3;
1191 
1192 			IFA_LOCK(ifa);
1193 			if (ifa->ifa_addr == NULL ||
1194 			    ifa->ifa_addr->sa_family != af) {
1195 next:
1196 				IFA_UNLOCK(ifa);
1197 				continue;
1198 			}
1199 			/*
1200 			 * If we're looking up with a scope,
1201 			 * find using a matching interface.
1202 			 */
1203 			if (ifscope != IFSCOPE_NONE &&
1204 			    ifp->if_index != ifscope) {
1205 				IFA_UNLOCK(ifa);
1206 				continue;
1207 			}
1208 
1209 			/*
1210 			 * Scan all the bits in the ifa's address.
1211 			 * If a bit dissagrees with what we are
1212 			 * looking for, mask it with the netmask
1213 			 * to see if it really matters.
1214 			 * (A byte at a time)
1215 			 */
1216 			if (ifa->ifa_netmask == 0) {
1217 				IFA_UNLOCK(ifa);
1218 				continue;
1219 			}
1220 			cp = addr_data;
1221 			cp2 = ifa->ifa_addr->sa_data;
1222 			cp3 = ifa->ifa_netmask->sa_data;
1223 			cplim = ifa->ifa_netmask->sa_len +
1224 			    (char *)ifa->ifa_netmask;
1225 			while (cp3 < cplim) {
1226 				if ((*cp++ ^ *cp2++) & *cp3++) {
1227 					goto next; /* next address! */
1228 				}
1229 			}
1230 			/*
1231 			 * If the netmask of what we just found
1232 			 * is more specific than what we had before
1233 			 * (if we had one) then remember the new one
1234 			 * before continuing to search
1235 			 * for an even better one.
1236 			 */
1237 			if (ifa_maybe == NULL ||
1238 			    rn_refines((caddr_t)ifa->ifa_netmask,
1239 			    (caddr_t)ifa_maybe->ifa_netmask)) {
1240 				IFA_ADDREF_LOCKED(ifa); /* ifa_maybe */
1241 				IFA_UNLOCK(ifa);
1242 				if (ifa_maybe != NULL) {
1243 					IFA_REMREF(ifa_maybe);
1244 				}
1245 				ifa_maybe = ifa;
1246 			} else {
1247 				IFA_UNLOCK(ifa);
1248 			}
1249 			IFA_LOCK_ASSERT_NOTHELD(ifa);
1250 		}
1251 		ifnet_lock_done(ifp);
1252 
1253 		if (ifa != NULL) {
1254 			break;
1255 		}
1256 	}
1257 	ifnet_head_done();
1258 
1259 	if (ifa == NULL) {
1260 		ifa = ifa_maybe;
1261 	} else if (ifa_maybe != NULL) {
1262 		IFA_REMREF(ifa_maybe);
1263 	}
1264 
1265 	return ifa;
1266 }
1267 
1268 /*
1269  * Find an interface address specific to an interface best matching
1270  * a given address applying same source address selection rules
1271  * as done in the kernel for implicit source address binding
1272  */
1273 struct ifaddr *
ifaof_ifpforaddr_select(const struct sockaddr * addr,struct ifnet * ifp)1274 ifaof_ifpforaddr_select(const struct sockaddr *addr, struct ifnet *ifp)
1275 {
1276 	u_int af = addr->sa_family;
1277 
1278 	if (af == AF_INET6) {
1279 		return in6_selectsrc_core_ifa(__DECONST(struct sockaddr_in6 *, addr), ifp, 0);
1280 	}
1281 
1282 	return ifaof_ifpforaddr(addr, ifp);
1283 }
1284 
1285 /*
1286  * Find an interface address specific to an interface best matching
1287  * a given address without regards to source address selection.
1288  *
1289  * This is appropriate for use-cases where we just want to update/init
1290  * some data structure like routing table entries.
1291  */
1292 struct ifaddr *
ifaof_ifpforaddr(const struct sockaddr * addr,struct ifnet * ifp)1293 ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
1294 {
1295 	struct ifaddr *ifa = NULL;
1296 	const char *cp, *cp2, *cp3;
1297 	char *cplim;
1298 	struct ifaddr *ifa_maybe = NULL;
1299 	struct ifaddr *better_ifa_maybe = NULL;
1300 	u_int af = addr->sa_family;
1301 
1302 	if (af >= AF_MAX) {
1303 		return NULL;
1304 	}
1305 
1306 	ifnet_lock_shared(ifp);
1307 	for (ifa = ifp->if_addrhead.tqh_first; ifa;
1308 	    ifa = ifa->ifa_link.tqe_next) {
1309 		IFA_LOCK(ifa);
1310 		if (ifa->ifa_addr->sa_family != af) {
1311 			IFA_UNLOCK(ifa);
1312 			continue;
1313 		}
1314 		if (ifa_maybe == NULL) {
1315 			IFA_ADDREF_LOCKED(ifa); /* for ifa_maybe */
1316 			ifa_maybe = ifa;
1317 		}
1318 		if (ifa->ifa_netmask == 0) {
1319 			if (sa_equal(addr, ifa->ifa_addr) ||
1320 			    sa_equal(addr, ifa->ifa_dstaddr)) {
1321 				IFA_ADDREF_LOCKED(ifa); /* for caller */
1322 				IFA_UNLOCK(ifa);
1323 				break;
1324 			}
1325 			IFA_UNLOCK(ifa);
1326 			continue;
1327 		}
1328 		if (ifp->if_flags & IFF_POINTOPOINT) {
1329 			if (sa_equal(addr, ifa->ifa_dstaddr)) {
1330 				IFA_ADDREF_LOCKED(ifa); /* for caller */
1331 				IFA_UNLOCK(ifa);
1332 				break;
1333 			}
1334 		} else {
1335 			if (sa_equal(addr, ifa->ifa_addr)) {
1336 				/* exact match */
1337 				IFA_ADDREF_LOCKED(ifa); /* for caller */
1338 				IFA_UNLOCK(ifa);
1339 				break;
1340 			}
1341 			cp = addr->sa_data;
1342 			cp2 = ifa->ifa_addr->sa_data;
1343 			cp3 = ifa->ifa_netmask->sa_data;
1344 			cplim = ifa->ifa_netmask->sa_len +
1345 			    (char *)ifa->ifa_netmask;
1346 			for (; cp3 < cplim; cp3++) {
1347 				if ((*cp++ ^ *cp2++) & *cp3) {
1348 					break;
1349 				}
1350 			}
1351 			if (cp3 == cplim) {
1352 				/* subnet match */
1353 				if (better_ifa_maybe == NULL) {
1354 					/* for better_ifa_maybe */
1355 					IFA_ADDREF_LOCKED(ifa);
1356 					better_ifa_maybe = ifa;
1357 				}
1358 			}
1359 		}
1360 		IFA_UNLOCK(ifa);
1361 	}
1362 
1363 	if (ifa == NULL) {
1364 		if (better_ifa_maybe != NULL) {
1365 			ifa = better_ifa_maybe;
1366 			better_ifa_maybe = NULL;
1367 		} else {
1368 			ifa = ifa_maybe;
1369 			ifa_maybe = NULL;
1370 		}
1371 	}
1372 
1373 	ifnet_lock_done(ifp);
1374 
1375 	if (better_ifa_maybe != NULL) {
1376 		IFA_REMREF(better_ifa_maybe);
1377 	}
1378 	if (ifa_maybe != NULL) {
1379 		IFA_REMREF(ifa_maybe);
1380 	}
1381 
1382 	return ifa;
1383 }
1384 
1385 #include <net/route.h>
1386 
1387 /*
1388  * Default action when installing a route with a Link Level gateway.
1389  * Lookup an appropriate real ifa to point to.
1390  * This should be moved to /sys/net/link.c eventually.
1391  */
1392 void
link_rtrequest(int cmd,struct rtentry * rt,struct sockaddr * sa)1393 link_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
1394 {
1395 	struct ifaddr *ifa;
1396 	struct sockaddr *dst;
1397 	struct ifnet *ifp;
1398 	void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *);
1399 
1400 	LCK_MTX_ASSERT(rnh_lock, LCK_MTX_ASSERT_OWNED);
1401 	RT_LOCK_ASSERT_HELD(rt);
1402 
1403 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
1404 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) {
1405 		return;
1406 	}
1407 
1408 	/* Become a regular mutex, just in case */
1409 	RT_CONVERT_LOCK(rt);
1410 
1411 	ifa = ifaof_ifpforaddr(dst, ifp);
1412 	if (ifa) {
1413 		rtsetifa(rt, ifa);
1414 		IFA_LOCK_SPIN(ifa);
1415 		ifa_rtrequest = ifa->ifa_rtrequest;
1416 		IFA_UNLOCK(ifa);
1417 		if (ifa_rtrequest != NULL && ifa_rtrequest != link_rtrequest) {
1418 			ifa_rtrequest(cmd, rt, sa);
1419 		}
1420 		IFA_REMREF(ifa);
1421 	}
1422 }
1423 
1424 /*
1425  * if_updown will set the interface up or down. It will
1426  * prevent other up/down events from occurring until this
1427  * up/down event has completed.
1428  *
1429  * Caller must lock ifnet. This function will drop the
1430  * lock. This allows ifnet_set_flags to set the rest of
1431  * the flags after we change the up/down state without
1432  * dropping the interface lock between setting the
1433  * up/down state and updating the rest of the flags.
1434  */
1435 __private_extern__ void
if_updown(struct ifnet * ifp,int up)1436 if_updown(struct ifnet *ifp, int up)
1437 {
1438 	u_int32_t eflags;
1439 	int i;
1440 	struct ifaddr **ifa;
1441 	struct timespec tv;
1442 	struct ifclassq *ifq;
1443 
1444 	/* Wait until no one else is changing the up/down state */
1445 	while ((ifp->if_eflags & IFEF_UPDOWNCHANGE) != 0) {
1446 		tv.tv_sec = 0;
1447 		tv.tv_nsec = NSEC_PER_SEC / 10;
1448 		ifnet_lock_done(ifp);
1449 		msleep(&ifp->if_eflags, NULL, 0, "if_updown", &tv);
1450 		ifnet_lock_exclusive(ifp);
1451 	}
1452 
1453 	/* Verify that the interface isn't already in the right state */
1454 	if ((!up && (ifp->if_flags & IFF_UP) == 0) ||
1455 	    (up && (ifp->if_flags & IFF_UP) == IFF_UP)) {
1456 		return;
1457 	}
1458 
1459 	/* Indicate that the up/down state is changing */
1460 	eflags = if_set_eflags(ifp, IFEF_UPDOWNCHANGE);
1461 	ASSERT((eflags & IFEF_UPDOWNCHANGE) == 0);
1462 
1463 	/* Mark interface up or down */
1464 	if (up) {
1465 		ifp->if_flags |= IFF_UP;
1466 	} else {
1467 		ifp->if_flags &= ~IFF_UP;
1468 	}
1469 
1470 	if (!ifnet_is_attached(ifp, 1)) {
1471 		/*
1472 		 * The interface is not attached or is detaching, so
1473 		 * skip modifying any other state.
1474 		 */
1475 		os_log(OS_LOG_DEFAULT, "%s: %s is not attached",
1476 		    __func__, if_name(ifp));
1477 	} else {
1478 		/* Drop the lock to notify addresses and route */
1479 		ifnet_lock_done(ifp);
1480 
1481 		/* Inform all transmit queues about the new link state */
1482 		ifq = ifp->if_snd;
1483 		ASSERT(ifq != NULL);
1484 		IFCQ_LOCK(ifq);
1485 		if_qflush_snd(ifp, true);
1486 		ifnet_update_sndq(ifq,
1487 		    up ? CLASSQ_EV_LINK_UP : CLASSQ_EV_LINK_DOWN);
1488 		IFCQ_UNLOCK(ifq);
1489 
1490 		/* Inform protocols of changed interface state */
1491 		if (ifnet_get_address_list(ifp, &ifa) == 0) {
1492 			for (i = 0; ifa[i] != 0; i++) {
1493 				pfctlinput(up ? PRC_IFUP : PRC_IFDOWN,
1494 				    ifa[i]->ifa_addr);
1495 			}
1496 			ifnet_free_address_list(ifa);
1497 		}
1498 		rt_ifmsg(ifp);
1499 
1500 		ifnet_lock_exclusive(ifp);
1501 		ifnet_touch_lastchange(ifp);
1502 		ifnet_touch_lastupdown(ifp);
1503 		ifnet_decr_iorefcnt(ifp);
1504 	}
1505 	if_clear_eflags(ifp, IFEF_UPDOWNCHANGE);
1506 	wakeup(&ifp->if_eflags);
1507 }
1508 
1509 /*
1510  * Mark an interface down and notify protocols of
1511  * the transition.
1512  */
1513 void
if_down(struct ifnet * ifp)1514 if_down(
1515 	struct ifnet *ifp)
1516 {
1517 	ifnet_lock_exclusive(ifp);
1518 	if_updown(ifp, 0);
1519 	ifnet_lock_done(ifp);
1520 }
1521 
1522 /*
1523  * Mark an interface up and notify protocols of
1524  * the transition.
1525  */
1526 void
if_up(struct ifnet * ifp)1527 if_up(
1528 	struct ifnet *ifp)
1529 {
1530 	ifnet_lock_exclusive(ifp);
1531 	if_updown(ifp, 1);
1532 	ifnet_lock_done(ifp);
1533 }
1534 
1535 /*
1536  * Flush an interface queue.
1537  */
1538 void
if_qflush(struct ifnet * ifp,struct ifclassq * ifq,bool ifq_locked)1539 if_qflush(struct ifnet *ifp, struct ifclassq *ifq, bool ifq_locked)
1540 {
1541 	lck_mtx_lock(&ifp->if_ref_lock);
1542 	if ((ifp->if_refflags & IFRF_ATTACH_MASK) == 0) {
1543 		lck_mtx_unlock(&ifp->if_ref_lock);
1544 		return;
1545 	}
1546 	VERIFY(ifq != NULL);
1547 	ifclassq_retain(ifq);
1548 	lck_mtx_unlock(&ifp->if_ref_lock);
1549 
1550 	if (!ifq_locked) {
1551 		IFCQ_LOCK(ifq);
1552 	}
1553 
1554 	if (IFCQ_IS_ENABLED(ifq)) {
1555 		fq_if_request_classq(ifq, CLASSQRQ_PURGE, NULL);
1556 	}
1557 
1558 	VERIFY(IFCQ_IS_EMPTY(ifq));
1559 
1560 	if (!ifq_locked) {
1561 		IFCQ_UNLOCK(ifq);
1562 	}
1563 	ifclassq_release(&ifq);
1564 }
1565 
1566 void
if_qflush_snd(struct ifnet * ifp,bool ifq_locked)1567 if_qflush_snd(struct ifnet *ifp, bool ifq_locked)
1568 {
1569 	if_qflush(ifp, ifp->if_snd, ifq_locked);
1570 }
1571 
1572 void
if_qflush_sc(struct ifnet * ifp,mbuf_svc_class_t sc,u_int32_t flow,u_int32_t * packets,u_int32_t * bytes,int ifq_locked)1573 if_qflush_sc(struct ifnet *ifp, mbuf_svc_class_t sc, u_int32_t flow,
1574     u_int32_t *packets, u_int32_t *bytes, int ifq_locked)
1575 {
1576 	struct ifclassq *ifq;
1577 	u_int32_t cnt = 0, len = 0;
1578 
1579 	if ((ifp->if_refflags & IFRF_ATTACH_MASK) == 0) {
1580 		return;
1581 	}
1582 	ifq = ifp->if_snd;
1583 	VERIFY(ifq != NULL);
1584 	VERIFY(sc == MBUF_SC_UNSPEC || MBUF_VALID_SC(sc));
1585 	VERIFY(flow != 0);
1586 
1587 	if (!ifq_locked) {
1588 		IFCQ_LOCK(ifq);
1589 	}
1590 
1591 	if (IFCQ_IS_ENABLED(ifq)) {
1592 		cqrq_purge_sc_t req = { sc, flow, 0, 0 };
1593 
1594 		fq_if_request_classq(ifq, CLASSQRQ_PURGE_SC, &req);
1595 		cnt = req.packets;
1596 		len = req.bytes;
1597 	}
1598 
1599 	if (!ifq_locked) {
1600 		IFCQ_UNLOCK(ifq);
1601 	}
1602 
1603 	if (packets != NULL) {
1604 		*packets = cnt;
1605 	}
1606 	if (bytes != NULL) {
1607 		*bytes = len;
1608 	}
1609 }
1610 
1611 /*
1612  * Extracts interface unit number and name from string, returns -1 upon failure.
1613  * Upon success, returns extracted unit number, and interface name in dst.
1614  */
1615 int
ifunit_extract(const char * src,char * dst,size_t dstlen,int * unit)1616 ifunit_extract(const char *src, char *dst, size_t dstlen, int *unit)
1617 {
1618 	const char *cp;
1619 	size_t len, m;
1620 	char c;
1621 	int u;
1622 
1623 	if (src == NULL || dst == NULL || dstlen == 0 || unit == NULL) {
1624 		return -1;
1625 	}
1626 
1627 	len = strlen(src);
1628 	if (len < 2 || len > dstlen) {
1629 		return -1;
1630 	}
1631 	cp = src + len - 1;
1632 	c = *cp;
1633 	if (c < '0' || c > '9') {
1634 		return -1;            /* trailing garbage */
1635 	}
1636 	u = 0;
1637 	m = 1;
1638 	do {
1639 		if (cp == src) {
1640 			return -1;    /* no interface name */
1641 		}
1642 		u += (c - '0') * m;
1643 		if (u > 1000000) {
1644 			return -1;    /* number is unreasonable */
1645 		}
1646 		m *= 10;
1647 		c = *--cp;
1648 	} while (c >= '0' && c <= '9');
1649 	len = cp - src + 1;
1650 	bcopy(src, dst, len);
1651 	dst[len] = '\0';
1652 	*unit = u;
1653 
1654 	return 0;
1655 }
1656 
1657 /*
1658  * Map interface name to
1659  * interface structure pointer.
1660  */
1661 static struct ifnet *
ifunit_common(const char * name,boolean_t hold)1662 ifunit_common(const char *name, boolean_t hold)
1663 {
1664 	char namebuf[IFNAMSIZ + 1];
1665 	struct ifnet *ifp;
1666 	int unit;
1667 
1668 	if (ifunit_extract(name, namebuf, sizeof(namebuf), &unit) < 0) {
1669 		return NULL;
1670 	}
1671 
1672 	/* for safety, since we use strcmp() below */
1673 	namebuf[sizeof(namebuf) - 1] = '\0';
1674 
1675 	/*
1676 	 * Now search all the interfaces for this name/number
1677 	 */
1678 	ifnet_head_lock_shared();
1679 	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1680 		/*
1681 		 * Use strcmp() rather than strncmp() here,
1682 		 * since we want to match the entire string.
1683 		 */
1684 		if (strcmp(ifp->if_name, namebuf)) {
1685 			continue;
1686 		}
1687 		if (unit == ifp->if_unit) {
1688 			break;
1689 		}
1690 	}
1691 
1692 	/* if called from ifunit_ref() and ifnet is not attached, bail */
1693 	if (hold && ifp != NULL && !ifnet_is_attached(ifp, 1)) {
1694 		ifp = NULL;
1695 	}
1696 
1697 	ifnet_head_done();
1698 	return ifp;
1699 }
1700 
1701 struct ifnet *
ifunit(const char * name)1702 ifunit(const char *name)
1703 {
1704 	return ifunit_common(name, FALSE);
1705 }
1706 
1707 /*
1708  * Similar to ifunit(), except that we hold an I/O reference count on an
1709  * attached interface, which must later be released via ifnet_decr_iorefcnt().
1710  * Will return NULL unless interface exists and is fully attached.
1711  */
1712 struct ifnet *
ifunit_ref(const char * name)1713 ifunit_ref(const char *name)
1714 {
1715 	return ifunit_common(name, TRUE);
1716 }
1717 
1718 /*
1719  * Map interface name in a sockaddr_dl to
1720  * interface structure pointer.
1721  */
1722 struct ifnet *
if_withname(struct sockaddr * sa)1723 if_withname(struct sockaddr *sa)
1724 {
1725 	char ifname[IFNAMSIZ + 1];
1726 	struct sockaddr_dl *sdl = (struct sockaddr_dl *)(void *)sa;
1727 
1728 	if ((sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
1729 	    (sdl->sdl_nlen > IFNAMSIZ)) {
1730 		return NULL;
1731 	}
1732 
1733 	/*
1734 	 * ifunit wants a null-terminated name.  It may not be null-terminated
1735 	 * in the sockaddr.  We don't want to change the caller's sockaddr,
1736 	 * and there might not be room to put the trailing null anyway, so we
1737 	 * make a local copy that we know we can null terminate safely.
1738 	 */
1739 
1740 	bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1741 	ifname[sdl->sdl_nlen] = '\0';
1742 	return ifunit(ifname);
1743 }
1744 
1745 static __attribute__((noinline)) int
ifioctl_ifconf(u_long cmd,caddr_t data)1746 ifioctl_ifconf(u_long cmd, caddr_t data)
1747 {
1748 	int error = 0;
1749 
1750 	switch (cmd) {
1751 	case OSIOCGIFCONF32:                    /* struct ifconf32 */
1752 	case SIOCGIFCONF32: {                   /* struct ifconf32 */
1753 		struct ifconf32 ifc;
1754 		bcopy(data, &ifc, sizeof(ifc));
1755 		error = ifconf(cmd, CAST_USER_ADDR_T(ifc.ifc_req),
1756 		    &ifc.ifc_len);
1757 		bcopy(&ifc, data, sizeof(ifc));
1758 		break;
1759 	}
1760 
1761 	case SIOCGIFCONF64:                     /* struct ifconf64 */
1762 	case OSIOCGIFCONF64: {                  /* struct ifconf64 */
1763 		struct ifconf64 ifc;
1764 		bcopy(data, &ifc, sizeof(ifc));
1765 		error = ifconf(cmd, CAST_USER_ADDR_T(ifc.ifc_req), &ifc.ifc_len);
1766 		bcopy(&ifc, data, sizeof(ifc));
1767 		break;
1768 	}
1769 
1770 	default:
1771 		VERIFY(0);
1772 		/* NOTREACHED */
1773 	}
1774 
1775 	return error;
1776 }
1777 
1778 static __attribute__((noinline)) int
ifioctl_ifclone(u_long cmd,caddr_t data)1779 ifioctl_ifclone(u_long cmd, caddr_t data)
1780 {
1781 	int error = 0;
1782 
1783 	switch (cmd) {
1784 	case SIOCIFGCLONERS32: {                /* struct if_clonereq32 */
1785 		struct if_clonereq32 ifcr;
1786 		bcopy(data, &ifcr, sizeof(ifcr));
1787 		error = if_clone_list(ifcr.ifcr_count, &ifcr.ifcr_total,
1788 		    CAST_USER_ADDR_T(ifcr.ifcru_buffer));
1789 		bcopy(&ifcr, data, sizeof(ifcr));
1790 		break;
1791 	}
1792 
1793 	case SIOCIFGCLONERS64: {                /* struct if_clonereq64 */
1794 		struct if_clonereq64 ifcr;
1795 		bcopy(data, &ifcr, sizeof(ifcr));
1796 		error = if_clone_list(ifcr.ifcr_count, &ifcr.ifcr_total,
1797 		    CAST_USER_ADDR_T(ifcr.ifcru_buffer));
1798 		bcopy(&ifcr, data, sizeof(ifcr));
1799 		break;
1800 	}
1801 
1802 	default:
1803 		VERIFY(0);
1804 		/* NOTREACHED */
1805 	}
1806 
1807 	return error;
1808 }
1809 
1810 static __attribute__((noinline)) int
ifioctl_ifdesc(struct ifnet * ifp,u_long cmd,caddr_t data,struct proc * p)1811 ifioctl_ifdesc(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1812 {
1813 	struct if_descreq *ifdr = (struct if_descreq *)(void *)data;
1814 	u_int32_t ifdr_len;
1815 	int error = 0;
1816 
1817 	VERIFY(ifp != NULL);
1818 
1819 	switch (cmd) {
1820 	case SIOCSIFDESC: {                     /* struct if_descreq */
1821 		if ((error = proc_suser(p)) != 0) {
1822 			break;
1823 		}
1824 
1825 		ifnet_lock_exclusive(ifp);
1826 		bcopy(&ifdr->ifdr_len, &ifdr_len, sizeof(ifdr_len));
1827 		if (ifdr_len > sizeof(ifdr->ifdr_desc) ||
1828 		    ifdr_len > ifp->if_desc.ifd_maxlen) {
1829 			error = EINVAL;
1830 			ifnet_lock_done(ifp);
1831 			break;
1832 		}
1833 
1834 		bzero(ifp->if_desc.ifd_desc, ifp->if_desc.ifd_maxlen);
1835 		if ((ifp->if_desc.ifd_len = ifdr_len) > 0) {
1836 			bcopy(ifdr->ifdr_desc, ifp->if_desc.ifd_desc,
1837 			    MIN(ifdr_len, ifp->if_desc.ifd_maxlen));
1838 		}
1839 		ifnet_lock_done(ifp);
1840 		break;
1841 	}
1842 
1843 	case SIOCGIFDESC: {                     /* struct if_descreq */
1844 		ifnet_lock_shared(ifp);
1845 		ifdr_len = MIN(ifp->if_desc.ifd_len, sizeof(ifdr->ifdr_desc));
1846 		bcopy(&ifdr_len, &ifdr->ifdr_len, sizeof(ifdr_len));
1847 		bzero(&ifdr->ifdr_desc, sizeof(ifdr->ifdr_desc));
1848 		if (ifdr_len > 0) {
1849 			bcopy(ifp->if_desc.ifd_desc, ifdr->ifdr_desc, ifdr_len);
1850 		}
1851 		ifnet_lock_done(ifp);
1852 		break;
1853 	}
1854 
1855 	default:
1856 		VERIFY(0);
1857 		/* NOTREACHED */
1858 	}
1859 
1860 	return error;
1861 }
1862 
1863 static __attribute__((noinline)) int
ifioctl_linkparams(struct ifnet * ifp,u_long cmd,caddr_t data,struct proc * p)1864 ifioctl_linkparams(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1865 {
1866 	struct if_linkparamsreq *iflpr =
1867 	    (struct if_linkparamsreq *)(void *)data;
1868 	struct ifclassq *ifq;
1869 	int error = 0;
1870 
1871 	VERIFY(ifp != NULL);
1872 	ifq = ifp->if_snd;
1873 
1874 	ASSERT(ifq != NULL);
1875 	switch (cmd) {
1876 	case SIOCSIFLINKPARAMS: {               /* struct if_linkparamsreq */
1877 		struct tb_profile tb = { .rate = 0, .percent = 0, .depth = 0 };
1878 
1879 		if ((error = proc_suser(p)) != 0) {
1880 			break;
1881 		}
1882 
1883 #if SKYWALK
1884 		error = kern_nexus_set_netif_input_tbr_rate(ifp,
1885 		    iflpr->iflpr_input_tbr_rate);
1886 		if (error != 0) {
1887 			break;
1888 		}
1889 
1890 		/*
1891 		 * Input netem is done at flowswitch, which is the entry point
1892 		 * of all traffic, when skywalk is enabled.
1893 		 */
1894 		error = kern_nexus_set_if_netem_params(
1895 			kern_nexus_shared_controller(),
1896 			ifp->if_nx_flowswitch.if_fsw_instance,
1897 			&iflpr->iflpr_input_netem,
1898 			sizeof(iflpr->iflpr_input_netem));
1899 		if (error != 0) {
1900 			break;
1901 		}
1902 #endif /* SKYWALK */
1903 
1904 		char netem_name[32];
1905 		(void) snprintf(netem_name, sizeof(netem_name),
1906 		    "if_output_netem_%s", if_name(ifp));
1907 		error = netem_config(&ifp->if_output_netem, netem_name, ifp,
1908 		    &iflpr->iflpr_output_netem, (void *)ifp,
1909 		    ifnet_enqueue_netem, NETEM_MAX_BATCH_SIZE);
1910 		if (error != 0) {
1911 			break;
1912 		}
1913 
1914 		IFCQ_LOCK(ifq);
1915 		if (!IFCQ_IS_READY(ifq)) {
1916 			error = ENXIO;
1917 			IFCQ_UNLOCK(ifq);
1918 			break;
1919 		}
1920 		bcopy(&iflpr->iflpr_output_tbr_rate, &tb.rate,
1921 		    sizeof(tb.rate));
1922 		bcopy(&iflpr->iflpr_output_tbr_percent, &tb.percent,
1923 		    sizeof(tb.percent));
1924 		error = ifclassq_tbr_set(ifq, &tb, TRUE);
1925 		IFCQ_UNLOCK(ifq);
1926 		break;
1927 	}
1928 
1929 	case SIOCGIFLINKPARAMS: {               /* struct if_linkparamsreq */
1930 		u_int32_t sched_type = PKTSCHEDT_NONE, flags = 0;
1931 		u_int64_t tbr_bw = 0, tbr_pct = 0;
1932 
1933 		IFCQ_LOCK(ifq);
1934 
1935 		if (IFCQ_IS_ENABLED(ifq)) {
1936 			sched_type = ifq->ifcq_type;
1937 		}
1938 
1939 		bcopy(&sched_type, &iflpr->iflpr_output_sched,
1940 		    sizeof(iflpr->iflpr_output_sched));
1941 
1942 		if (IFCQ_TBR_IS_ENABLED(ifq)) {
1943 			tbr_bw = ifq->ifcq_tbr.tbr_rate_raw;
1944 			tbr_pct = ifq->ifcq_tbr.tbr_percent;
1945 		}
1946 		bcopy(&tbr_bw, &iflpr->iflpr_output_tbr_rate,
1947 		    sizeof(iflpr->iflpr_output_tbr_rate));
1948 		bcopy(&tbr_pct, &iflpr->iflpr_output_tbr_percent,
1949 		    sizeof(iflpr->iflpr_output_tbr_percent));
1950 		IFCQ_UNLOCK(ifq);
1951 
1952 		if (ifp->if_output_sched_model ==
1953 		    IFNET_SCHED_MODEL_DRIVER_MANAGED) {
1954 			flags |= IFLPRF_DRVMANAGED;
1955 		}
1956 		bcopy(&flags, &iflpr->iflpr_flags, sizeof(iflpr->iflpr_flags));
1957 		bcopy(&ifp->if_output_bw, &iflpr->iflpr_output_bw,
1958 		    sizeof(iflpr->iflpr_output_bw));
1959 		bcopy(&ifp->if_input_bw, &iflpr->iflpr_input_bw,
1960 		    sizeof(iflpr->iflpr_input_bw));
1961 		bcopy(&ifp->if_output_lt, &iflpr->iflpr_output_lt,
1962 		    sizeof(iflpr->iflpr_output_lt));
1963 		bcopy(&ifp->if_input_lt, &iflpr->iflpr_input_lt,
1964 		    sizeof(iflpr->iflpr_input_lt));
1965 
1966 #if SKYWALK
1967 		if (ifp->if_input_netem != NULL) {
1968 			netem_get_params(ifp->if_input_netem,
1969 			    &iflpr->iflpr_input_netem);
1970 		}
1971 #endif /* SKYWALK */
1972 		if (ifp->if_output_netem != NULL) {
1973 			netem_get_params(ifp->if_output_netem,
1974 			    &iflpr->iflpr_output_netem);
1975 		}
1976 
1977 		break;
1978 	}
1979 
1980 	default:
1981 		VERIFY(0);
1982 		/* NOTREACHED */
1983 	}
1984 
1985 	return error;
1986 }
1987 
1988 static __attribute__((noinline)) int
ifioctl_qstats(struct ifnet * ifp,u_long cmd,caddr_t data)1989 ifioctl_qstats(struct ifnet *ifp, u_long cmd, caddr_t data)
1990 {
1991 	struct if_qstatsreq *ifqr = (struct if_qstatsreq *)(void *)data;
1992 	u_int32_t ifqr_len, ifqr_slot;
1993 	uint32_t ifqr_grp_idx = 0;
1994 	int error = 0;
1995 
1996 	VERIFY(ifp != NULL);
1997 
1998 	switch (cmd) {
1999 	case SIOCGIFQUEUESTATS: {               /* struct if_qstatsreq */
2000 		bcopy(&ifqr->ifqr_slot, &ifqr_slot, sizeof(ifqr_slot));
2001 		bcopy(&ifqr->ifqr_grp_idx, &ifqr_grp_idx, sizeof(ifqr_grp_idx));
2002 		bcopy(&ifqr->ifqr_len, &ifqr_len, sizeof(ifqr_len));
2003 
2004 		if (ifqr_grp_idx > FQ_IF_MAX_GROUPS) {
2005 			return EINVAL;
2006 		}
2007 		error = ifclassq_getqstats(ifp->if_snd, (uint8_t)ifqr_grp_idx,
2008 		    ifqr_slot, ifqr->ifqr_buf, &ifqr_len);
2009 		if (error != 0) {
2010 			ifqr_len = 0;
2011 		}
2012 		bcopy(&ifqr_len, &ifqr->ifqr_len, sizeof(ifqr_len));
2013 		break;
2014 	}
2015 
2016 	default:
2017 		VERIFY(0);
2018 		/* NOTREACHED */
2019 	}
2020 
2021 	return error;
2022 }
2023 
2024 static __attribute__((noinline)) int
ifioctl_throttle(struct ifnet * ifp,u_long cmd,caddr_t data,struct proc * p)2025 ifioctl_throttle(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
2026 {
2027 	struct if_throttlereq *ifthr = (struct if_throttlereq *)(void *)data;
2028 	u_int32_t ifthr_level;
2029 	int error = 0;
2030 
2031 	VERIFY(ifp != NULL);
2032 
2033 	switch (cmd) {
2034 	case SIOCSIFTHROTTLE: {                 /* struct if_throttlereq */
2035 		/*
2036 		 * XXX: Use priv_check_cred() instead of root check?
2037 		 */
2038 		if ((error = proc_suser(p)) != 0) {
2039 			break;
2040 		}
2041 
2042 		bcopy(&ifthr->ifthr_level, &ifthr_level, sizeof(ifthr_level));
2043 		error = ifnet_set_throttle(ifp, ifthr_level);
2044 		if (error == EALREADY) {
2045 			error = 0;
2046 		}
2047 		break;
2048 	}
2049 
2050 	case SIOCGIFTHROTTLE: {                 /* struct if_throttlereq */
2051 		if ((error = ifnet_get_throttle(ifp, &ifthr_level)) == 0) {
2052 			bcopy(&ifthr_level, &ifthr->ifthr_level,
2053 			    sizeof(ifthr_level));
2054 		}
2055 		break;
2056 	}
2057 
2058 	default:
2059 		VERIFY(0);
2060 		/* NOTREACHED */
2061 	}
2062 
2063 	return error;
2064 }
2065 
2066 static int
ifioctl_getnetagents(struct ifnet * ifp,u_int32_t * count,user_addr_t uuid_p)2067 ifioctl_getnetagents(struct ifnet *ifp, u_int32_t *count, user_addr_t uuid_p)
2068 {
2069 	int error = 0;
2070 	u_int32_t index = 0;
2071 	u_int32_t valid_netagent_count = 0;
2072 	*count = 0;
2073 
2074 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_SHARED);
2075 
2076 	if (ifp->if_agentids != NULL) {
2077 		for (index = 0; index < ifp->if_agentcount; index++) {
2078 			uuid_t *netagent_uuid = &(ifp->if_agentids[index]);
2079 			if (!uuid_is_null(*netagent_uuid)) {
2080 				if (uuid_p != USER_ADDR_NULL) {
2081 					error = copyout(netagent_uuid,
2082 					    uuid_p + sizeof(uuid_t) * valid_netagent_count,
2083 					    sizeof(uuid_t));
2084 					if (error != 0) {
2085 						return error;
2086 					}
2087 				}
2088 				valid_netagent_count++;
2089 			}
2090 		}
2091 	}
2092 	*count = valid_netagent_count;
2093 
2094 	return 0;
2095 }
2096 
2097 #define IF_MAXAGENTS            64
2098 #define IF_AGENT_INCREMENT      8
2099 int
if_add_netagent_locked(struct ifnet * ifp,uuid_t new_agent_uuid)2100 if_add_netagent_locked(struct ifnet *ifp, uuid_t new_agent_uuid)
2101 {
2102 	VERIFY(ifp != NULL);
2103 
2104 	uuid_t *first_empty_slot = NULL;
2105 	u_int32_t index = 0;
2106 	bool already_added = FALSE;
2107 
2108 	if (ifp->if_agentids != NULL) {
2109 		for (index = 0; index < ifp->if_agentcount; index++) {
2110 			uuid_t *netagent_uuid = &(ifp->if_agentids[index]);
2111 			if (uuid_compare(*netagent_uuid, new_agent_uuid) == 0) {
2112 				/* Already present, ignore */
2113 				already_added = TRUE;
2114 				break;
2115 			}
2116 			if (first_empty_slot == NULL &&
2117 			    uuid_is_null(*netagent_uuid)) {
2118 				first_empty_slot = netagent_uuid;
2119 			}
2120 		}
2121 	}
2122 	if (already_added) {
2123 		/* Already added agent, don't return an error */
2124 		return 0;
2125 	}
2126 	if (first_empty_slot == NULL) {
2127 		if (ifp->if_agentcount >= IF_MAXAGENTS) {
2128 			/* No room for another netagent UUID, bail */
2129 			return ENOMEM;
2130 		} else {
2131 			/* Calculate new array size */
2132 			u_int32_t new_agent_count =
2133 			    MIN(ifp->if_agentcount + IF_AGENT_INCREMENT,
2134 			    IF_MAXAGENTS);
2135 
2136 			/* Reallocate array */
2137 			uuid_t *new_agent_array = krealloc_data(ifp->if_agentids,
2138 			    sizeof(uuid_t) * ifp->if_agentcount,
2139 			    sizeof(uuid_t) * new_agent_count,
2140 			    Z_WAITOK | Z_ZERO);
2141 			if (new_agent_array == NULL) {
2142 				return ENOMEM;
2143 			}
2144 
2145 			/* Save new array */
2146 			ifp->if_agentids = new_agent_array;
2147 
2148 			/* Set first empty slot */
2149 			first_empty_slot =
2150 			    &(ifp->if_agentids[ifp->if_agentcount]);
2151 
2152 			/* Save new array length */
2153 			ifp->if_agentcount = new_agent_count;
2154 		}
2155 	}
2156 	uuid_copy(*first_empty_slot, new_agent_uuid);
2157 	netagent_post_updated_interfaces(new_agent_uuid);
2158 	return 0;
2159 }
2160 
2161 int
if_add_netagent(struct ifnet * ifp,uuid_t new_agent_uuid)2162 if_add_netagent(struct ifnet *ifp, uuid_t new_agent_uuid)
2163 {
2164 	VERIFY(ifp != NULL);
2165 
2166 	ifnet_lock_exclusive(ifp);
2167 
2168 	int error = if_add_netagent_locked(ifp, new_agent_uuid);
2169 
2170 	ifnet_lock_done(ifp);
2171 
2172 	return error;
2173 }
2174 
2175 static int
if_delete_netagent_locked(struct ifnet * ifp,uuid_t remove_agent_uuid)2176 if_delete_netagent_locked(struct ifnet *ifp, uuid_t remove_agent_uuid)
2177 {
2178 	u_int32_t index = 0;
2179 	bool removed_agent_id = FALSE;
2180 
2181 	if (ifp->if_agentids != NULL) {
2182 		for (index = 0; index < ifp->if_agentcount; index++) {
2183 			uuid_t *netagent_uuid = &(ifp->if_agentids[index]);
2184 			if (uuid_compare(*netagent_uuid,
2185 			    remove_agent_uuid) == 0) {
2186 				uuid_clear(*netagent_uuid);
2187 				removed_agent_id = TRUE;
2188 				break;
2189 			}
2190 		}
2191 	}
2192 	if (removed_agent_id) {
2193 		netagent_post_updated_interfaces(remove_agent_uuid);
2194 	}
2195 
2196 	return 0;
2197 }
2198 
2199 int
if_delete_netagent(struct ifnet * ifp,uuid_t remove_agent_uuid)2200 if_delete_netagent(struct ifnet *ifp, uuid_t remove_agent_uuid)
2201 {
2202 	VERIFY(ifp != NULL);
2203 
2204 	ifnet_lock_exclusive(ifp);
2205 
2206 	int error = if_delete_netagent_locked(ifp, remove_agent_uuid);
2207 
2208 	ifnet_lock_done(ifp);
2209 
2210 	return error;
2211 }
2212 
2213 boolean_t
if_check_netagent(struct ifnet * ifp,uuid_t find_agent_uuid)2214 if_check_netagent(struct ifnet *ifp, uuid_t find_agent_uuid)
2215 {
2216 	boolean_t found = FALSE;
2217 
2218 	if (!ifp || uuid_is_null(find_agent_uuid)) {
2219 		return FALSE;
2220 	}
2221 
2222 	ifnet_lock_shared(ifp);
2223 
2224 	if (ifp->if_agentids != NULL) {
2225 		for (uint32_t index = 0; index < ifp->if_agentcount; index++) {
2226 			if (uuid_compare(ifp->if_agentids[index], find_agent_uuid) == 0) {
2227 				found = TRUE;
2228 				break;
2229 			}
2230 		}
2231 	}
2232 
2233 	ifnet_lock_done(ifp);
2234 
2235 	return found;
2236 }
2237 
2238 static __attribute__((noinline)) int
ifioctl_netagent(struct ifnet * ifp,u_long cmd,caddr_t data,struct proc * p)2239 ifioctl_netagent(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
2240 {
2241 	struct if_agentidreq *ifar = (struct if_agentidreq *)(void *)data;
2242 	union {
2243 		struct if_agentidsreq32 s32;
2244 		struct if_agentidsreq64 s64;
2245 	} u;
2246 	int error = 0;
2247 
2248 	VERIFY(ifp != NULL);
2249 
2250 	/* Get an io ref count if the interface is attached */
2251 	if (!ifnet_is_attached(ifp, 1)) {
2252 		return EOPNOTSUPP;
2253 	}
2254 
2255 	if (cmd == SIOCAIFAGENTID ||
2256 	    cmd == SIOCDIFAGENTID) {
2257 		ifnet_lock_exclusive(ifp);
2258 	} else {
2259 		ifnet_lock_shared(ifp);
2260 	}
2261 
2262 	switch (cmd) {
2263 	case SIOCAIFAGENTID: {                  /* struct if_agentidreq */
2264 		// TODO: Use priv_check_cred() instead of root check
2265 		if ((error = proc_suser(p)) != 0) {
2266 			break;
2267 		}
2268 		error = if_add_netagent_locked(ifp, ifar->ifar_uuid);
2269 		break;
2270 	}
2271 	case SIOCDIFAGENTID: {                          /* struct if_agentidreq */
2272 		// TODO: Use priv_check_cred() instead of root check
2273 		if ((error = proc_suser(p)) != 0) {
2274 			break;
2275 		}
2276 		error = if_delete_netagent_locked(ifp, ifar->ifar_uuid);
2277 		break;
2278 	}
2279 	case SIOCGIFAGENTIDS32: {               /* struct if_agentidsreq32 */
2280 		bcopy(data, &u.s32, sizeof(u.s32));
2281 		error = ifioctl_getnetagents(ifp, &u.s32.ifar_count,
2282 		    u.s32.ifar_uuids);
2283 		if (error == 0) {
2284 			bcopy(&u.s32, data, sizeof(u.s32));
2285 		}
2286 		break;
2287 	}
2288 	case SIOCGIFAGENTIDS64: {               /* struct if_agentidsreq64 */
2289 		bcopy(data, &u.s64, sizeof(u.s64));
2290 		error = ifioctl_getnetagents(ifp, &u.s64.ifar_count,
2291 		    CAST_USER_ADDR_T(u.s64.ifar_uuids));
2292 		if (error == 0) {
2293 			bcopy(&u.s64, data, sizeof(u.s64));
2294 		}
2295 		break;
2296 	}
2297 	default:
2298 		VERIFY(0);
2299 		/* NOTREACHED */
2300 	}
2301 
2302 	ifnet_lock_done(ifp);
2303 	ifnet_decr_iorefcnt(ifp);
2304 
2305 	return error;
2306 }
2307 
2308 void
ifnet_clear_netagent(uuid_t netagent_uuid)2309 ifnet_clear_netagent(uuid_t netagent_uuid)
2310 {
2311 	struct ifnet *ifp = NULL;
2312 	u_int32_t index = 0;
2313 
2314 	ifnet_head_lock_shared();
2315 
2316 	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
2317 		ifnet_lock_shared(ifp);
2318 		if (ifp->if_agentids != NULL) {
2319 			for (index = 0; index < ifp->if_agentcount; index++) {
2320 				uuid_t *ifp_netagent_uuid = &(ifp->if_agentids[index]);
2321 				if (uuid_compare(*ifp_netagent_uuid, netagent_uuid) == 0) {
2322 					uuid_clear(*ifp_netagent_uuid);
2323 				}
2324 			}
2325 		}
2326 		ifnet_lock_done(ifp);
2327 	}
2328 
2329 	ifnet_head_done();
2330 }
2331 
2332 void
ifnet_increment_generation(ifnet_t interface)2333 ifnet_increment_generation(ifnet_t interface)
2334 {
2335 	OSIncrementAtomic(&interface->if_generation);
2336 }
2337 
2338 u_int32_t
ifnet_get_generation(ifnet_t interface)2339 ifnet_get_generation(ifnet_t interface)
2340 {
2341 	return interface->if_generation;
2342 }
2343 
2344 void
ifnet_remove_from_ordered_list(struct ifnet * ifp)2345 ifnet_remove_from_ordered_list(struct ifnet *ifp)
2346 {
2347 	ifnet_head_assert_exclusive();
2348 
2349 	// Remove from list
2350 	TAILQ_REMOVE(&ifnet_ordered_head, ifp, if_ordered_link);
2351 	ifp->if_ordered_link.tqe_next = NULL;
2352 	ifp->if_ordered_link.tqe_prev = NULL;
2353 
2354 	// Update ordered count
2355 	VERIFY(if_ordered_count > 0);
2356 	if_ordered_count--;
2357 }
2358 
2359 static int
ifnet_reset_order(u_int32_t * ordered_indices,u_int32_t count)2360 ifnet_reset_order(u_int32_t *ordered_indices, u_int32_t count)
2361 {
2362 	struct ifnet *ifp = NULL;
2363 	int error = 0;
2364 
2365 	if (if_verbose != 0) {
2366 		os_log(OS_LOG_DEFAULT, "%s: count %u", __func__, count);
2367 	}
2368 
2369 	ifnet_head_lock_exclusive();
2370 	for (u_int32_t order_index = 0; order_index < count; order_index++) {
2371 		if (ordered_indices[order_index] == IFSCOPE_NONE ||
2372 		    ordered_indices[order_index] > (uint32_t)if_index) {
2373 			error = EINVAL;
2374 			ifnet_head_done();
2375 			return error;
2376 		}
2377 	}
2378 	// Flush current ordered list
2379 	for (ifp = TAILQ_FIRST(&ifnet_ordered_head); ifp != NULL;
2380 	    ifp = TAILQ_FIRST(&ifnet_ordered_head)) {
2381 		ifnet_lock_exclusive(ifp);
2382 		ifnet_remove_from_ordered_list(ifp);
2383 		ifnet_lock_done(ifp);
2384 	}
2385 
2386 	VERIFY(if_ordered_count == 0);
2387 
2388 	for (u_int32_t order_index = 0; order_index < count; order_index++) {
2389 		u_int32_t interface_index = ordered_indices[order_index];
2390 		ifp = ifindex2ifnet[interface_index];
2391 		if (ifp == NULL) {
2392 			continue;
2393 		}
2394 		ifnet_lock_exclusive(ifp);
2395 		TAILQ_INSERT_TAIL(&ifnet_ordered_head, ifp, if_ordered_link);
2396 		ifnet_lock_done(ifp);
2397 		if_ordered_count++;
2398 	}
2399 
2400 	ifnet_head_done();
2401 
2402 	necp_update_all_clients();
2403 
2404 	return error;
2405 }
2406 
2407 #if (DEBUG || DEVELOPMENT)
2408 static int
ifnet_get_ordered_indices(u_int32_t * ordered_indices,uint32_t * count)2409 ifnet_get_ordered_indices(u_int32_t *ordered_indices, uint32_t *count)
2410 {
2411 	struct ifnet *ifp = NULL;
2412 	int error = 0;
2413 	uint32_t order_index = 0;
2414 
2415 	ifnet_head_lock_exclusive();
2416 
2417 	if (*count < if_ordered_count) {
2418 		ifnet_head_done();
2419 		return ENOBUFS;
2420 	}
2421 
2422 	TAILQ_FOREACH(ifp, &ifnet_ordered_head, if_ordered_link) {
2423 		if (order_index >= if_ordered_count) {
2424 			break;
2425 		}
2426 		ordered_indices[order_index++] = ifp->if_index;
2427 	}
2428 	*count = order_index;
2429 	ifnet_head_done();
2430 
2431 	return error;
2432 }
2433 #endif /* (DEBUG || DEVELOPMENT) */
2434 
2435 int
if_set_qosmarking_mode(struct ifnet * ifp,u_int32_t mode)2436 if_set_qosmarking_mode(struct ifnet *ifp, u_int32_t mode)
2437 {
2438 	int error = 0;
2439 	u_int32_t old_mode = ifp->if_qosmarking_mode;
2440 
2441 	switch (mode) {
2442 	case IFRTYPE_QOSMARKING_MODE_NONE:
2443 		ifp->if_qosmarking_mode = IFRTYPE_QOSMARKING_MODE_NONE;
2444 		break;
2445 	case IFRTYPE_QOSMARKING_FASTLANE:
2446 	case IFRTYPE_QOSMARKING_RFC4594:
2447 		ifp->if_qosmarking_mode = mode;
2448 		break;
2449 #if (DEBUG || DEVELOPMENT)
2450 	case IFRTYPE_QOSMARKING_CUSTOM:
2451 		ifp->if_qosmarking_mode = mode;
2452 		break;
2453 #endif /* (DEBUG || DEVELOPMENT) */
2454 	default:
2455 		error = EINVAL;
2456 		break;
2457 	}
2458 	if (error == 0 && old_mode != ifp->if_qosmarking_mode) {
2459 		dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_QOS_MODE_CHANGED,
2460 		    NULL, 0, FALSE);
2461 	}
2462 	return error;
2463 }
2464 
2465 static __attribute__((noinline)) int
ifioctl_iforder(u_long cmd,caddr_t data)2466 ifioctl_iforder(u_long cmd, caddr_t data)
2467 {
2468 	int error = 0;
2469 	u_int32_t *ordered_indices = NULL;
2470 	size_t ordered_indices_length = 0;
2471 
2472 	if (data == NULL) {
2473 		return EINVAL;
2474 	}
2475 
2476 	switch (cmd) {
2477 	case SIOCSIFORDER: {            /* struct if_order */
2478 		struct if_order *ifo = (struct if_order *)(void *)data;
2479 
2480 		if (ifo->ifo_count > (u_int32_t)if_index) {
2481 			error = EINVAL;
2482 			break;
2483 		}
2484 
2485 		ordered_indices_length = ifo->ifo_count * sizeof(u_int32_t);
2486 		if (ordered_indices_length > 0) {
2487 			if (ifo->ifo_ordered_indices == USER_ADDR_NULL) {
2488 				error = EINVAL;
2489 				break;
2490 			}
2491 			ordered_indices = (u_int32_t *)kalloc_data(ordered_indices_length,
2492 			    Z_WAITOK);
2493 			if (ordered_indices == NULL) {
2494 				error = ENOMEM;
2495 				break;
2496 			}
2497 
2498 			error = copyin(CAST_USER_ADDR_T(ifo->ifo_ordered_indices),
2499 			    ordered_indices, ordered_indices_length);
2500 			if (error != 0) {
2501 				break;
2502 			}
2503 
2504 			/* ordered_indices should not contain duplicates */
2505 			bool found_duplicate = FALSE;
2506 			for (uint32_t i = 0; i < (ifo->ifo_count - 1) && !found_duplicate; i++) {
2507 				for (uint32_t j = i + 1; j < ifo->ifo_count && !found_duplicate; j++) {
2508 					if (ordered_indices[j] == ordered_indices[i]) {
2509 						error = EINVAL;
2510 						found_duplicate = TRUE;
2511 						break;
2512 					}
2513 				}
2514 			}
2515 			if (found_duplicate) {
2516 				break;
2517 			}
2518 
2519 			error = ifnet_reset_order(ordered_indices, ifo->ifo_count);
2520 		} else {
2521 			// Clear the list
2522 			error = ifnet_reset_order(NULL, 0);
2523 		}
2524 		break;
2525 	}
2526 
2527 	case SIOCGIFORDER: {
2528 #if (DEBUG || DEVELOPMENT)
2529 		struct if_order *ifo = (struct if_order *)(void *)data;
2530 		uint32_t count;
2531 
2532 		if (ifo->ifo_ordered_indices == 0) {
2533 			ifo->ifo_count = if_ordered_count;
2534 			break;
2535 		}
2536 
2537 		count = ifo->ifo_count;
2538 		if (count == 0) {
2539 			error = EINVAL;
2540 			break;
2541 		}
2542 
2543 		ordered_indices_length = count * sizeof(uint32_t);
2544 		ordered_indices = (uint32_t *)kalloc_data(ordered_indices_length,
2545 		    Z_WAITOK | Z_ZERO);
2546 		if (ordered_indices == NULL) {
2547 			error = ENOMEM;
2548 			break;
2549 		}
2550 
2551 		error = ifnet_get_ordered_indices(ordered_indices, &count);
2552 		if (error == 0) {
2553 			ifo->ifo_count = count;
2554 			error = copyout((caddr_t)ordered_indices,
2555 			    CAST_USER_ADDR_T(ifo->ifo_ordered_indices),
2556 			    count * sizeof(uint32_t));
2557 		}
2558 #else /* (DEBUG || DEVELOPMENT) */
2559 		error = EOPNOTSUPP;
2560 #endif /* (DEBUG || DEVELOPMENT) */
2561 
2562 		break;
2563 	}
2564 
2565 	default: {
2566 		VERIFY(0);
2567 		/* NOTREACHED */
2568 	}
2569 	}
2570 
2571 	if (ordered_indices != NULL) {
2572 		kfree_data(ordered_indices, ordered_indices_length);
2573 	}
2574 
2575 	return error;
2576 }
2577 
2578 static __attribute__((noinline)) int
ifioctl_networkid(struct ifnet * ifp,caddr_t data)2579 ifioctl_networkid(struct ifnet *ifp, caddr_t data)
2580 {
2581 	struct if_netidreq *ifnetidr = (struct if_netidreq *)(void *)data;
2582 	int error = 0;
2583 	int len = ifnetidr->ifnetid_len;
2584 
2585 	VERIFY(ifp != NULL);
2586 
2587 	if (len > sizeof(ifnetidr->ifnetid)) {
2588 		error = EINVAL;
2589 		goto end;
2590 	}
2591 
2592 	if (len == 0) {
2593 		bzero(&ifp->network_id, sizeof(ifp->network_id));
2594 	} else if (len > sizeof(ifp->network_id)) {
2595 		error = EINVAL;
2596 		goto end;
2597 	}
2598 
2599 	ifp->network_id_len = (uint8_t)len;
2600 	bcopy(data, ifp->network_id, len);
2601 end:
2602 	return error;
2603 }
2604 
2605 static __attribute__((noinline)) int
ifioctl_netsignature(struct ifnet * ifp,u_long cmd,caddr_t data)2606 ifioctl_netsignature(struct ifnet *ifp, u_long cmd, caddr_t data)
2607 {
2608 	struct if_nsreq *ifnsr = (struct if_nsreq *)(void *)data;
2609 	u_int16_t flags;
2610 	int error = 0;
2611 
2612 	VERIFY(ifp != NULL);
2613 
2614 	switch (cmd) {
2615 	case SIOCSIFNETSIGNATURE:               /* struct if_nsreq */
2616 		if (ifnsr->ifnsr_len > sizeof(ifnsr->ifnsr_data)) {
2617 			error = EINVAL;
2618 			break;
2619 		}
2620 		bcopy(&ifnsr->ifnsr_flags, &flags, sizeof(flags));
2621 		error = ifnet_set_netsignature(ifp, ifnsr->ifnsr_family,
2622 		    ifnsr->ifnsr_len, flags, ifnsr->ifnsr_data);
2623 		break;
2624 
2625 	case SIOCGIFNETSIGNATURE:               /* struct if_nsreq */
2626 		ifnsr->ifnsr_len = sizeof(ifnsr->ifnsr_data);
2627 		error = ifnet_get_netsignature(ifp, ifnsr->ifnsr_family,
2628 		    &ifnsr->ifnsr_len, &flags, ifnsr->ifnsr_data);
2629 		if (error == 0) {
2630 			bcopy(&flags, &ifnsr->ifnsr_flags, sizeof(flags));
2631 		} else {
2632 			ifnsr->ifnsr_len = 0;
2633 		}
2634 		break;
2635 
2636 	default:
2637 		VERIFY(0);
2638 		/* NOTREACHED */
2639 	}
2640 
2641 	return error;
2642 }
2643 
2644 static __attribute__((noinline)) int
ifioctl_nat64prefix(struct ifnet * ifp,u_long cmd,caddr_t data)2645 ifioctl_nat64prefix(struct ifnet *ifp, u_long cmd, caddr_t data)
2646 {
2647 	struct if_nat64req *ifnat64 = (struct if_nat64req *)(void *)data;
2648 	int error = 0;
2649 
2650 	VERIFY(ifp != NULL);
2651 
2652 	switch (cmd) {
2653 	case SIOCSIFNAT64PREFIX:                /* struct if_nat64req */
2654 		error = ifnet_set_nat64prefix(ifp, ifnat64->ifnat64_prefixes);
2655 		if (error != 0) {
2656 			ip6stat.ip6s_clat464_plat64_pfx_setfail++;
2657 		}
2658 		break;
2659 
2660 	case SIOCGIFNAT64PREFIX:                /* struct if_nat64req */
2661 		error = ifnet_get_nat64prefix(ifp, ifnat64->ifnat64_prefixes);
2662 		if (error != 0) {
2663 			ip6stat.ip6s_clat464_plat64_pfx_getfail++;
2664 		}
2665 		break;
2666 
2667 	default:
2668 		VERIFY(0);
2669 		/* NOTREACHED */
2670 	}
2671 
2672 	return error;
2673 }
2674 
2675 static __attribute__((noinline)) int
ifioctl_clat46addr(struct ifnet * ifp,u_long cmd,caddr_t data)2676 ifioctl_clat46addr(struct ifnet *ifp, u_long cmd, caddr_t data)
2677 {
2678 	struct if_clat46req *ifclat46 = (struct if_clat46req *)(void *)data;
2679 	struct in6_ifaddr *ia6_clat = NULL;
2680 	int error = 0;
2681 
2682 	VERIFY(ifp != NULL);
2683 
2684 	switch (cmd) {
2685 	case SIOCGIFCLAT46ADDR:
2686 		ia6_clat = in6ifa_ifpwithflag(ifp, IN6_IFF_CLAT46);
2687 		if (ia6_clat == NULL) {
2688 			error = ENOENT;
2689 			break;
2690 		}
2691 
2692 		bcopy(&ia6_clat->ia_addr.sin6_addr, &ifclat46->ifclat46_addr.v6_address,
2693 		    sizeof(ifclat46->ifclat46_addr.v6_address));
2694 		ifclat46->ifclat46_addr.v6_prefixlen = ia6_clat->ia_plen;
2695 		IFA_REMREF(&ia6_clat->ia_ifa);
2696 		break;
2697 	default:
2698 		VERIFY(0);
2699 		/* NOTREACHED */
2700 	}
2701 
2702 	return error;
2703 }
2704 
2705 #if SKYWALK
2706 static __attribute__((noinline)) int
ifioctl_nexus(struct ifnet * ifp,u_long cmd,caddr_t data)2707 ifioctl_nexus(struct ifnet *ifp, u_long cmd, caddr_t data)
2708 {
2709 	int error = 0;
2710 	struct if_nexusreq *ifnr = (struct if_nexusreq *)(void *)data;
2711 
2712 	switch (cmd) {
2713 	case SIOCGIFNEXUS:              /* struct if_nexusreq */
2714 		if (ifnr->ifnr_flags != 0) {
2715 			error = EINVAL;
2716 			break;
2717 		}
2718 		error = kern_nexus_get_netif_instance(ifp, ifnr->ifnr_netif);
2719 		if (error != 0) {
2720 			break;
2721 		}
2722 		kern_nexus_get_flowswitch_instance(ifp, ifnr->ifnr_flowswitch);
2723 		break;
2724 	default:
2725 		VERIFY(0);
2726 		/* NOTREACHED */
2727 	}
2728 
2729 	return error;
2730 }
2731 #endif /* SKYWALK */
2732 
2733 static int
ifioctl_get_protolist(struct ifnet * ifp,u_int32_t * ret_count,user_addr_t ifpl)2734 ifioctl_get_protolist(struct ifnet *ifp, u_int32_t * ret_count,
2735     user_addr_t ifpl)
2736 {
2737 	u_int32_t       actual_count;
2738 	u_int32_t       count;
2739 	int             error = 0;
2740 	u_int32_t       *list = NULL;
2741 
2742 	/* find out how many */
2743 	count = if_get_protolist(ifp, NULL, 0);
2744 	if (ifpl == USER_ADDR_NULL) {
2745 		goto done;
2746 	}
2747 
2748 	/* copy out how many there's space for */
2749 	if (*ret_count < count) {
2750 		count = *ret_count;
2751 	}
2752 	if (count == 0) {
2753 		goto done;
2754 	}
2755 	list = (u_int32_t *)kalloc_data(count * sizeof(*list), Z_WAITOK | Z_ZERO);
2756 	if (list == NULL) {
2757 		error = ENOMEM;
2758 		goto done;
2759 	}
2760 	actual_count = if_get_protolist(ifp, list, count);
2761 	if (actual_count < count) {
2762 		count = actual_count;
2763 	}
2764 	if (count != 0) {
2765 		error = copyout((caddr_t)list, ifpl, count * sizeof(*list));
2766 	}
2767 
2768 done:
2769 	if (list != NULL) {
2770 		if_free_protolist(list);
2771 	}
2772 	*ret_count = count;
2773 	return error;
2774 }
2775 
2776 static __attribute__((noinline)) int
ifioctl_protolist(struct ifnet * ifp,u_long cmd,caddr_t data)2777 ifioctl_protolist(struct ifnet *ifp, u_long cmd, caddr_t data)
2778 {
2779 	int error = 0;
2780 
2781 	switch (cmd) {
2782 	case SIOCGIFPROTOLIST32: {              /* struct if_protolistreq32 */
2783 		struct if_protolistreq32        ifpl;
2784 
2785 		bcopy(data, &ifpl, sizeof(ifpl));
2786 		if (ifpl.ifpl_reserved != 0) {
2787 			error = EINVAL;
2788 			break;
2789 		}
2790 		error = ifioctl_get_protolist(ifp, &ifpl.ifpl_count,
2791 		    CAST_USER_ADDR_T(ifpl.ifpl_list));
2792 		bcopy(&ifpl, data, sizeof(ifpl));
2793 		break;
2794 	}
2795 	case SIOCGIFPROTOLIST64: {              /* struct if_protolistreq64 */
2796 		struct if_protolistreq64        ifpl;
2797 
2798 		bcopy(data, &ifpl, sizeof(ifpl));
2799 		if (ifpl.ifpl_reserved != 0) {
2800 			error = EINVAL;
2801 			break;
2802 		}
2803 		error = ifioctl_get_protolist(ifp, &ifpl.ifpl_count,
2804 		    CAST_USER_ADDR_T(ifpl.ifpl_list));
2805 		bcopy(&ifpl, data, sizeof(ifpl));
2806 		break;
2807 	}
2808 	default:
2809 		VERIFY(0);
2810 		/* NOTREACHED */
2811 	}
2812 
2813 	return error;
2814 }
2815 
2816 /*
2817  * List the ioctl()s we can perform on restricted INTCOPROC interfaces.
2818  */
2819 static bool
ifioctl_restrict_intcoproc(unsigned long cmd,const char * ifname,struct ifnet * ifp,struct proc * p)2820 ifioctl_restrict_intcoproc(unsigned long cmd, const char *ifname,
2821     struct ifnet *ifp, struct proc *p)
2822 {
2823 	if (intcoproc_unrestricted) {
2824 		return false;
2825 	}
2826 	if (proc_pid(p) == 0) {
2827 		return false;
2828 	}
2829 	if (ifname) {
2830 		ifp = ifunit(ifname);
2831 	}
2832 	if (ifp == NULL) {
2833 		return false;
2834 	}
2835 	if (!IFNET_IS_INTCOPROC(ifp)) {
2836 		return false;
2837 	}
2838 	switch (cmd) {
2839 	case SIOCGIFBRDADDR:
2840 	case SIOCGIFCONF32:
2841 	case SIOCGIFCONF64:
2842 	case SIOCGIFFLAGS:
2843 	case SIOCGIFEFLAGS:
2844 	case SIOCGIFCAP:
2845 	case SIOCGIFMETRIC:
2846 	case SIOCGIFMTU:
2847 	case SIOCGIFPHYS:
2848 	case SIOCGIFTYPE:
2849 	case SIOCGIFFUNCTIONALTYPE:
2850 	case SIOCGIFPSRCADDR:
2851 	case SIOCGIFPDSTADDR:
2852 	case SIOCGIFGENERIC:
2853 	case SIOCGIFDEVMTU:
2854 	case SIOCGIFVLAN:
2855 	case SIOCGIFBOND:
2856 	case SIOCGIFWAKEFLAGS:
2857 	case SIOCGIFGETRTREFCNT:
2858 	case SIOCGIFOPPORTUNISTIC:
2859 	case SIOCGIFLINKQUALITYMETRIC:
2860 	case SIOCGIFLOG:
2861 	case SIOCGIFDELEGATE:
2862 	case SIOCGIFEXPENSIVE:
2863 	case SIOCGIFINTERFACESTATE:
2864 	case SIOCGIFPROBECONNECTIVITY:
2865 	case SIOCGIFTIMESTAMPENABLED:
2866 	case SIOCGECNMODE:
2867 	case SIOCGQOSMARKINGMODE:
2868 	case SIOCGQOSMARKINGENABLED:
2869 	case SIOCGIFLOWINTERNET:
2870 	case SIOCGIFSTATUS:
2871 	case SIOCGIFMEDIA32:
2872 	case SIOCGIFMEDIA64:
2873 	case SIOCGIFXMEDIA32:
2874 	case SIOCGIFXMEDIA64:
2875 	case SIOCGIFDESC:
2876 	case SIOCGIFLINKPARAMS:
2877 	case SIOCGIFQUEUESTATS:
2878 	case SIOCGIFTHROTTLE:
2879 	case SIOCGIFAGENTIDS32:
2880 	case SIOCGIFAGENTIDS64:
2881 	case SIOCGIFNETSIGNATURE:
2882 	case SIOCGIFINFO_IN6:
2883 	case SIOCGIFAFLAG_IN6:
2884 	case SIOCGNBRINFO_IN6:
2885 	case SIOCGIFALIFETIME_IN6:
2886 	case SIOCGIFNETMASK_IN6:
2887 #if SKYWALK
2888 	case SIOCGIFNEXUS:
2889 #endif /* SKYWALK */
2890 	case SIOCGIFPROTOLIST32:
2891 	case SIOCGIFPROTOLIST64:
2892 	case SIOCGIFXFLAGS:
2893 	case SIOCGIFNOTRAFFICSHAPING:
2894 		return false;
2895 	default:
2896 #if (DEBUG || DEVELOPMENT)
2897 		printf("%s: cmd 0x%lx not allowed (pid %u)\n",
2898 		    __func__, cmd, proc_pid(p));
2899 #endif
2900 		return true;
2901 	}
2902 	return false;
2903 }
2904 
2905 /*
2906  * Given a media word, return one suitable for an application
2907  * using the original encoding.
2908  */
2909 static int
compat_media(int media)2910 compat_media(int media)
2911 {
2912 	if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) {
2913 		media &= ~IFM_TMASK;
2914 		media |= IFM_OTHER;
2915 	}
2916 	return media;
2917 }
2918 
2919 static int
compat_ifmu_ulist(struct ifnet * ifp,u_long cmd,void * data)2920 compat_ifmu_ulist(struct ifnet *ifp, u_long cmd, void *data)
2921 {
2922 	struct ifmediareq *ifmr = (struct ifmediareq *)data;
2923 	user_addr_t user_addr;
2924 	int i;
2925 	int *media_list = NULL;
2926 	int error = 0;
2927 	bool list_modified = false;
2928 
2929 	user_addr = (cmd == SIOCGIFMEDIA64) ?
2930 	    CAST_USER_ADDR_T(((struct ifmediareq64 *)ifmr)->ifmu_ulist) :
2931 	    CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist);
2932 	if (user_addr == USER_ADDR_NULL || ifmr->ifm_count == 0) {
2933 		return 0;
2934 	}
2935 	media_list = (int *)kalloc_data(ifmr->ifm_count * sizeof(int),
2936 	    Z_WAITOK | Z_ZERO);
2937 	if (media_list == NULL) {
2938 		os_log_error(OS_LOG_DEFAULT,
2939 		    "%s: %s kalloc_data() failed",
2940 		    __func__, ifp->if_xname);
2941 		error = ENOMEM;
2942 		goto done;
2943 	}
2944 	error = copyin(user_addr, media_list, ifmr->ifm_count * sizeof(int));
2945 	if (error != 0) {
2946 		os_log_error(OS_LOG_DEFAULT,
2947 		    "%s: %s copyin() error %d",
2948 		    __func__, ifp->if_xname, error);
2949 		goto done;
2950 	}
2951 	for (i = 0; i < ifmr->ifm_count; i++) {
2952 		int old_media, new_media;
2953 
2954 		old_media = media_list[i];
2955 
2956 		new_media = compat_media(old_media);
2957 		if (new_media == old_media) {
2958 			continue;
2959 		}
2960 		if (if_verbose != 0) {
2961 			os_log_info(OS_LOG_DEFAULT,
2962 			    "%s: %s converted extended media %08x to compat media %08x",
2963 			    __func__, ifp->if_xname, old_media, new_media);
2964 		}
2965 		media_list[i] = new_media;
2966 		list_modified = true;
2967 	}
2968 	if (list_modified) {
2969 		error = copyout(media_list, user_addr, ifmr->ifm_count * sizeof(int));
2970 		if (error != 0) {
2971 			os_log_error(OS_LOG_DEFAULT,
2972 			    "%s: %s copyout() error %d",
2973 			    __func__, ifp->if_xname, error);
2974 			goto done;
2975 		}
2976 	}
2977 done:
2978 	if (media_list != NULL) {
2979 		kfree_data(media_list, ifmr->ifm_count * sizeof(int));
2980 	}
2981 	return error;
2982 }
2983 
2984 static int
compat_ifmediareq(struct ifnet * ifp,u_long cmd,void * data)2985 compat_ifmediareq(struct ifnet *ifp, u_long cmd, void *data)
2986 {
2987 	struct ifmediareq *ifmr = (struct ifmediareq *)data;
2988 	int error;
2989 
2990 	ifmr->ifm_active = compat_media(ifmr->ifm_active);
2991 	ifmr->ifm_current = compat_media(ifmr->ifm_current);
2992 
2993 	error = compat_ifmu_ulist(ifp, cmd, data);
2994 
2995 	return error;
2996 }
2997 
2998 static int
ifioctl_get_media(struct ifnet * ifp,struct socket * so,u_long cmd,caddr_t data)2999 ifioctl_get_media(struct ifnet *ifp, struct socket *so, u_long cmd, caddr_t data)
3000 {
3001 	int error = 0;
3002 
3003 	/*
3004 	 * An ifnet must not implement SIOCGIFXMEDIA as it gets the extended
3005 	 *  media subtypes macros from <net/if_media.h>
3006 	 */
3007 	switch (cmd) {
3008 	case SIOCGIFMEDIA32:
3009 	case SIOCGIFXMEDIA32:
3010 		error = ifnet_ioctl(ifp, SOCK_DOM(so), SIOCGIFMEDIA32, data);
3011 		break;
3012 	case SIOCGIFMEDIA64:
3013 	case SIOCGIFXMEDIA64:
3014 		error = ifnet_ioctl(ifp, SOCK_DOM(so), SIOCGIFMEDIA64, data);
3015 		break;
3016 	}
3017 	if (if_verbose != 0 && error != 0) {
3018 		os_log(OS_LOG_DEFAULT, "%s: first ifnet_ioctl(%s, %08lx) error %d",
3019 		    __func__, ifp->if_xname, cmd, error);
3020 	}
3021 	if (error == 0 && (cmd == SIOCGIFMEDIA32 || cmd == SIOCGIFMEDIA64)) {
3022 		error = compat_ifmediareq(ifp, cmd, data);
3023 	}
3024 	return error;
3025 }
3026 /*
3027  * Interface ioctls.
3028  *
3029  * Most of the routines called to handle the ioctls would end up being
3030  * tail-call optimized, which unfortunately causes this routine to
3031  * consume too much stack space; this is the reason for the "noinline"
3032  * attribute used on those routines.
3033  */
3034 int
ifioctl(struct socket * so,u_long cmd,caddr_t data,struct proc * p)3035 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
3036 {
3037 	char ifname[IFNAMSIZ + 1];
3038 	struct ifnet *ifp = NULL;
3039 	struct ifstat *ifs = NULL;
3040 	int error = 0;
3041 
3042 	bzero(ifname, sizeof(ifname));
3043 
3044 	/*
3045 	 * ioctls which don't require ifp, or ifreq ioctls
3046 	 */
3047 	switch (cmd) {
3048 	case OSIOCGIFCONF32:                    /* struct ifconf32 */
3049 	case SIOCGIFCONF32:                     /* struct ifconf32 */
3050 	case SIOCGIFCONF64:                     /* struct ifconf64 */
3051 	case OSIOCGIFCONF64:                    /* struct ifconf64 */
3052 		error = ifioctl_ifconf(cmd, data);
3053 		goto done;
3054 
3055 	case SIOCIFGCLONERS32:                  /* struct if_clonereq32 */
3056 	case SIOCIFGCLONERS64:                  /* struct if_clonereq64 */
3057 		error = ifioctl_ifclone(cmd, data);
3058 		goto done;
3059 
3060 	case SIOCGIFAGENTDATA32:                /* struct netagent_req32 */
3061 	case SIOCGIFAGENTDATA64:                /* struct netagent_req64 */
3062 	case SIOCGIFAGENTLIST32:                /* struct netagentlist_req32 */
3063 	case SIOCGIFAGENTLIST64:                /* struct netagentlist_req64 */
3064 		error = netagent_ioctl(cmd, data);
3065 		goto done;
3066 
3067 	case SIOCSIFORDER:                      /* struct if_order */
3068 	case SIOCGIFORDER:                      /* struct if_order */
3069 		error = ifioctl_iforder(cmd, data);
3070 		goto done;
3071 
3072 	case SIOCSIFDSTADDR:                    /* struct ifreq */
3073 	case SIOCSIFADDR:                       /* struct ifreq */
3074 	case SIOCSIFBRDADDR:                    /* struct ifreq */
3075 	case SIOCSIFNETMASK:                    /* struct ifreq */
3076 	case OSIOCGIFADDR:                      /* struct ifreq */
3077 	case OSIOCGIFDSTADDR:                   /* struct ifreq */
3078 	case OSIOCGIFBRDADDR:                   /* struct ifreq */
3079 	case OSIOCGIFNETMASK:                   /* struct ifreq */
3080 	case SIOCSIFKPI:                        /* struct ifreq */
3081 		if (so->so_proto == NULL) {
3082 			error = EOPNOTSUPP;
3083 			goto done;
3084 		}
3085 		OS_FALLTHROUGH;
3086 	case SIOCIFCREATE:                      /* struct ifreq */
3087 	case SIOCIFCREATE2:                     /* struct ifreq */
3088 	case SIOCIFDESTROY:                     /* struct ifreq */
3089 	case SIOCGIFFLAGS:                      /* struct ifreq */
3090 	case SIOCGIFEFLAGS:                     /* struct ifreq */
3091 	case SIOCGIFCAP:                        /* struct ifreq */
3092 	case SIOCGIFMETRIC:                     /* struct ifreq */
3093 	case SIOCGIFMTU:                        /* struct ifreq */
3094 	case SIOCGIFPHYS:                       /* struct ifreq */
3095 	case SIOCSIFFLAGS:                      /* struct ifreq */
3096 	case SIOCSIFCAP:                        /* struct ifreq */
3097 	case SIOCSIFMETRIC:                     /* struct ifreq */
3098 	case SIOCSIFPHYS:                       /* struct ifreq */
3099 	case SIOCSIFMTU:                        /* struct ifreq */
3100 	case SIOCADDMULTI:                      /* struct ifreq */
3101 	case SIOCDELMULTI:                      /* struct ifreq */
3102 	case SIOCDIFPHYADDR:                    /* struct ifreq */
3103 	case SIOCSIFMEDIA:                      /* struct ifreq */
3104 	case SIOCSIFGENERIC:                    /* struct ifreq */
3105 	case SIOCSIFLLADDR:                     /* struct ifreq */
3106 	case SIOCSIFALTMTU:                     /* struct ifreq */
3107 	case SIOCSIFVLAN:                       /* struct ifreq */
3108 	case SIOCSIFBOND:                       /* struct ifreq */
3109 	case SIOCGIFLLADDR:                     /* struct ifreq */
3110 	case SIOCGIFTYPE:                       /* struct ifreq */
3111 	case SIOCGIFFUNCTIONALTYPE:             /* struct ifreq */
3112 	case SIOCGIFPSRCADDR:                   /* struct ifreq */
3113 	case SIOCGIFPDSTADDR:                   /* struct ifreq */
3114 	case SIOCGIFGENERIC:                    /* struct ifreq */
3115 	case SIOCGIFDEVMTU:                     /* struct ifreq */
3116 	case SIOCGIFVLAN:                       /* struct ifreq */
3117 	case SIOCGIFBOND:                       /* struct ifreq */
3118 	case SIOCGIFWAKEFLAGS:                  /* struct ifreq */
3119 	case SIOCGIFGETRTREFCNT:                /* struct ifreq */
3120 	case SIOCSIFOPPORTUNISTIC:              /* struct ifreq */
3121 	case SIOCGIFOPPORTUNISTIC:              /* struct ifreq */
3122 	case SIOCGIFLINKQUALITYMETRIC:          /* struct ifreq */
3123 	case SIOCSIFLINKQUALITYMETRIC:          /* struct ifreq */
3124 	case SIOCSIFLOG:                        /* struct ifreq */
3125 	case SIOCGIFLOG:                        /* struct ifreq */
3126 	case SIOCGIFDELEGATE:                   /* struct ifreq */
3127 	case SIOCGIFEXPENSIVE:                  /* struct ifreq */
3128 	case SIOCSIFEXPENSIVE:                  /* struct ifreq */
3129 	case SIOCSIF2KCL:                       /* struct ifreq */
3130 	case SIOCGIF2KCL:                       /* struct ifreq */
3131 	case SIOCSIFINTERFACESTATE:             /* struct ifreq */
3132 	case SIOCGIFINTERFACESTATE:             /* struct ifreq */
3133 	case SIOCSIFPROBECONNECTIVITY:          /* struct ifreq */
3134 	case SIOCGIFPROBECONNECTIVITY:          /* struct ifreq */
3135 	case SIOCGSTARTDELAY:                   /* struct ifreq */
3136 	case SIOCSIFTIMESTAMPENABLE:            /* struct ifreq */
3137 	case SIOCSIFTIMESTAMPDISABLE:           /* struct ifreq */
3138 	case SIOCGIFTIMESTAMPENABLED:           /* struct ifreq */
3139 #if (DEBUG || DEVELOPMENT)
3140 	case SIOCSIFDISABLEOUTPUT:              /* struct ifreq */
3141 #endif /* (DEBUG || DEVELOPMENT) */
3142 	case SIOCGECNMODE:                      /* struct ifreq */
3143 	case SIOCSECNMODE:
3144 	case SIOCSQOSMARKINGMODE:               /* struct ifreq */
3145 	case SIOCSQOSMARKINGENABLED:            /* struct ifreq */
3146 	case SIOCGQOSMARKINGMODE:               /* struct ifreq */
3147 	case SIOCGQOSMARKINGENABLED:            /* struct ifreq */
3148 	case SIOCSIFLOWINTERNET:                /* struct ifreq */
3149 	case SIOCGIFLOWINTERNET:                /* struct ifreq */
3150 	case SIOCGIFLOWPOWER:                   /* struct ifreq */
3151 	case SIOCSIFLOWPOWER:                   /* struct ifreq */
3152 	case SIOCGIFMPKLOG:                     /* struct ifreq */
3153 	case SIOCSIFMPKLOG:                     /* struct ifreq */
3154 	case SIOCGIFCONSTRAINED:                /* struct ifreq */
3155 	case SIOCSIFCONSTRAINED:                /* struct ifreq */
3156 	case SIOCSIFESTTHROUGHPUT:              /* struct ifreq */
3157 	case SIOCSIFRADIODETAILS:               /* struct ifreq */
3158 	case SIOCGIFXFLAGS:                     /* struct ifreq */
3159 	case SIOCGIFNOACKPRIO:                  /* struct ifreq */
3160 	case SIOCSIFNOACKPRIO:                  /* struct ifreq */
3161 	case SIOCSIFMARKWAKEPKT:                /* struct ifreq */
3162 	case SIOCSIFNOTRAFFICSHAPING:           /* struct ifreq */
3163 	case SIOCGIFNOTRAFFICSHAPING:           /* struct ifreq */
3164 	{                       /* struct ifreq */
3165 		struct ifreq ifr;
3166 		bcopy(data, &ifr, sizeof(ifr));
3167 		ifr.ifr_name[IFNAMSIZ - 1] = '\0';
3168 		bcopy(&ifr.ifr_name, ifname, IFNAMSIZ);
3169 		if (ifioctl_restrict_intcoproc(cmd, ifname, NULL, p) == true) {
3170 			error = EPERM;
3171 			goto done;
3172 		}
3173 		error = ifioctl_ifreq(so, cmd, &ifr, p);
3174 		bcopy(&ifr, data, sizeof(ifr));
3175 		goto done;
3176 	}
3177 	}
3178 
3179 	/*
3180 	 * ioctls which require ifp.  Note that we acquire dlil_ifnet_lock
3181 	 * here to ensure that the ifnet, if found, has been fully attached.
3182 	 */
3183 	dlil_if_lock();
3184 	switch (cmd) {
3185 	case SIOCSIFPHYADDR:                    /* struct {if,in_}aliasreq */
3186 		bcopy(((struct in_aliasreq *)(void *)data)->ifra_name,
3187 		    ifname, IFNAMSIZ);
3188 		ifp = ifunit_ref(ifname);
3189 		break;
3190 
3191 	case SIOCSIFPHYADDR_IN6_32:             /* struct in6_aliasreq_32 */
3192 		bcopy(((struct in6_aliasreq_32 *)(void *)data)->ifra_name,
3193 		    ifname, IFNAMSIZ);
3194 		ifp = ifunit_ref(ifname);
3195 		break;
3196 
3197 	case SIOCSIFPHYADDR_IN6_64:             /* struct in6_aliasreq_64 */
3198 		bcopy(((struct in6_aliasreq_64 *)(void *)data)->ifra_name,
3199 		    ifname, IFNAMSIZ);
3200 		ifp = ifunit_ref(ifname);
3201 		break;
3202 
3203 	case SIOCGIFSTATUS:                     /* struct ifstat */
3204 		ifs = kalloc_type(struct ifstat, Z_WAITOK | Z_NOFAIL);
3205 		bcopy(data, ifs, sizeof(*ifs));
3206 		ifs->ifs_name[IFNAMSIZ - 1] = '\0';
3207 		bcopy(ifs->ifs_name, ifname, IFNAMSIZ);
3208 		ifp = ifunit_ref(ifname);
3209 		break;
3210 
3211 	case SIOCGIFMEDIA32:                    /* struct ifmediareq32 */
3212 	case SIOCGIFXMEDIA32:                    /* struct ifmediareq32 */
3213 		bcopy(((struct ifmediareq32 *)(void *)data)->ifm_name,
3214 		    ifname, IFNAMSIZ);
3215 		ifp = ifunit_ref(ifname);
3216 		break;
3217 
3218 	case SIOCGIFMEDIA64:                    /* struct ifmediareq64 */
3219 	case SIOCGIFXMEDIA64:                    /* struct ifmediareq64 */
3220 		bcopy(((struct ifmediareq64 *)(void *)data)->ifm_name,
3221 		    ifname, IFNAMSIZ);
3222 		ifp = ifunit_ref(ifname);
3223 		break;
3224 
3225 	case SIOCSIFDESC:                       /* struct if_descreq */
3226 	case SIOCGIFDESC:                       /* struct if_descreq */
3227 		bcopy(((struct if_descreq *)(void *)data)->ifdr_name,
3228 		    ifname, IFNAMSIZ);
3229 		ifp = ifunit_ref(ifname);
3230 		break;
3231 
3232 	case SIOCSIFLINKPARAMS:                 /* struct if_linkparamsreq */
3233 	case SIOCGIFLINKPARAMS:                 /* struct if_linkparamsreq */
3234 		bcopy(((struct if_linkparamsreq *)(void *)data)->iflpr_name,
3235 		    ifname, IFNAMSIZ);
3236 		ifp = ifunit_ref(ifname);
3237 		break;
3238 
3239 	case SIOCGIFQUEUESTATS:                 /* struct if_qstatsreq */
3240 		bcopy(((struct if_qstatsreq *)(void *)data)->ifqr_name,
3241 		    ifname, IFNAMSIZ);
3242 		ifp = ifunit_ref(ifname);
3243 		break;
3244 
3245 	case SIOCSIFTHROTTLE:                   /* struct if_throttlereq */
3246 	case SIOCGIFTHROTTLE:                   /* struct if_throttlereq */
3247 		bcopy(((struct if_throttlereq *)(void *)data)->ifthr_name,
3248 		    ifname, IFNAMSIZ);
3249 		ifp = ifunit_ref(ifname);
3250 		break;
3251 
3252 	case SIOCAIFAGENTID:                    /* struct if_agentidreq */
3253 	case SIOCDIFAGENTID:                    /* struct if_agentidreq */
3254 	case SIOCGIFAGENTIDS32:         /* struct if_agentidsreq32 */
3255 	case SIOCGIFAGENTIDS64:         /* struct if_agentidsreq64 */
3256 		bcopy(((struct if_agentidreq *)(void *)data)->ifar_name,
3257 		    ifname, IFNAMSIZ);
3258 		ifp = ifunit_ref(ifname);
3259 		break;
3260 
3261 	case SIOCSIFNETSIGNATURE:               /* struct if_nsreq */
3262 	case SIOCGIFNETSIGNATURE:               /* struct if_nsreq */
3263 		bcopy(((struct if_nsreq *)(void *)data)->ifnsr_name,
3264 		    ifname, IFNAMSIZ);
3265 		ifp = ifunit_ref(ifname);
3266 		break;
3267 
3268 	case SIOCSIFNETWORKID:                  /* struct if_netidreq */
3269 		bcopy(((struct if_netidreq *)(void *)data)->ifnetid_name,
3270 		    ifname, IFNAMSIZ);
3271 		ifp = ifunit_ref(ifname);
3272 		break;
3273 #if SKYWALK
3274 	case SIOCGIFNEXUS:                      /* struct if_nexusreq */
3275 		bcopy(((struct if_nexusreq *)(void *)data)->ifnr_name,
3276 		    ifname, IFNAMSIZ);
3277 		ifp = ifunit_ref(ifname);
3278 		break;
3279 #endif /* SKYWALK */
3280 	case SIOCGIFPROTOLIST32:                /* struct if_protolistreq32 */
3281 	case SIOCGIFPROTOLIST64:                /* struct if_protolistreq64 */
3282 		bcopy(((struct if_protolistreq *)(void *)data)->ifpl_name,
3283 		    ifname, IFNAMSIZ);
3284 		ifp = ifunit_ref(ifname);
3285 		break;
3286 	default:
3287 		/*
3288 		 * This is a bad assumption, but the code seems to
3289 		 * have been doing this in the past; caveat emptor.
3290 		 */
3291 		bcopy(((struct ifreq *)(void *)data)->ifr_name,
3292 		    ifname, IFNAMSIZ);
3293 		ifp = ifunit_ref(ifname);
3294 		break;
3295 	}
3296 	dlil_if_unlock();
3297 
3298 	if (ifp == NULL) {
3299 		error = ENXIO;
3300 		goto done;
3301 	}
3302 
3303 	if (ifioctl_restrict_intcoproc(cmd, NULL, ifp, p) == true) {
3304 		error = EPERM;
3305 		goto done;
3306 	}
3307 	switch (cmd) {
3308 	case SIOCSIFPHYADDR:                    /* struct {if,in_}aliasreq */
3309 	case SIOCSIFPHYADDR_IN6_32:             /* struct in6_aliasreq_32 */
3310 	case SIOCSIFPHYADDR_IN6_64:             /* struct in6_aliasreq_64 */
3311 		error = proc_suser(p);
3312 		if (error != 0) {
3313 			break;
3314 		}
3315 
3316 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
3317 		if (error != 0) {
3318 			break;
3319 		}
3320 
3321 		ifnet_touch_lastchange(ifp);
3322 		break;
3323 
3324 	case SIOCGIFSTATUS:                     /* struct ifstat */
3325 		VERIFY(ifs != NULL);
3326 		ifs->ascii[0] = '\0';
3327 
3328 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifs);
3329 
3330 		bcopy(ifs, data, sizeof(*ifs));
3331 		break;
3332 
3333 	case SIOCGIFMEDIA32:                    /* struct ifmediareq32 */
3334 	case SIOCGIFMEDIA64:                    /* struct ifmediareq64 */
3335 	case SIOCGIFXMEDIA32:                    /* struct ifmediareq32 */
3336 	case SIOCGIFXMEDIA64:                    /* struct ifmediareq64 */
3337 		error = ifioctl_get_media(ifp, so, cmd, data);
3338 		break;
3339 
3340 	case SIOCSIFDESC:                       /* struct if_descreq */
3341 	case SIOCGIFDESC:                       /* struct if_descreq */
3342 		error = ifioctl_ifdesc(ifp, cmd, data, p);
3343 		break;
3344 
3345 	case SIOCSIFLINKPARAMS:                 /* struct if_linkparamsreq */
3346 	case SIOCGIFLINKPARAMS:                 /* struct if_linkparamsreq */
3347 		error = ifioctl_linkparams(ifp, cmd, data, p);
3348 		break;
3349 
3350 	case SIOCGIFQUEUESTATS:                 /* struct if_qstatsreq */
3351 		error = ifioctl_qstats(ifp, cmd, data);
3352 		break;
3353 
3354 	case SIOCSIFTHROTTLE:                   /* struct if_throttlereq */
3355 	case SIOCGIFTHROTTLE:                   /* struct if_throttlereq */
3356 		error = ifioctl_throttle(ifp, cmd, data, p);
3357 		break;
3358 
3359 	case SIOCAIFAGENTID:                    /* struct if_agentidreq */
3360 	case SIOCDIFAGENTID:                    /* struct if_agentidreq */
3361 	case SIOCGIFAGENTIDS32:         /* struct if_agentidsreq32 */
3362 	case SIOCGIFAGENTIDS64:         /* struct if_agentidsreq64 */
3363 		error = ifioctl_netagent(ifp, cmd, data, p);
3364 		break;
3365 
3366 	case SIOCSIFNETSIGNATURE:               /* struct if_nsreq */
3367 	case SIOCGIFNETSIGNATURE:               /* struct if_nsreq */
3368 		error = ifioctl_netsignature(ifp, cmd, data);
3369 		break;
3370 
3371 	case SIOCSIFNETWORKID:                  /* struct if_netidreq */
3372 		error = ifioctl_networkid(ifp, data);
3373 		break;
3374 	case SIOCSIFNAT64PREFIX:                /* struct if_nat64req */
3375 	case SIOCGIFNAT64PREFIX:                /* struct if_nat64req */
3376 		error = ifioctl_nat64prefix(ifp, cmd, data);
3377 		break;
3378 
3379 	case SIOCGIFCLAT46ADDR:                 /* struct if_clat46req */
3380 		error = ifioctl_clat46addr(ifp, cmd, data);
3381 		break;
3382 #if SKYWALK
3383 	case SIOCGIFNEXUS:
3384 		error = ifioctl_nexus(ifp, cmd, data);
3385 		break;
3386 #endif /* SKYWALK */
3387 
3388 	case SIOCGIFPROTOLIST32:                /* struct if_protolistreq32 */
3389 	case SIOCGIFPROTOLIST64:                /* struct if_protolistreq64 */
3390 		error = ifioctl_protolist(ifp, cmd, data);
3391 		break;
3392 
3393 	default:
3394 		if (so->so_proto == NULL) {
3395 			error = EOPNOTSUPP;
3396 			break;
3397 		}
3398 
3399 		socket_lock(so, 1);
3400 		error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
3401 		    data, ifp, p));
3402 		socket_unlock(so, 1);
3403 
3404 		// Don't allow to call SIOCAIFADDR and SIOCDIFADDR with
3405 		// ifreq as the code expects ifaddr
3406 		if ((error == EOPNOTSUPP || error == ENOTSUP) &&
3407 		    !(cmd == SIOCAIFADDR || cmd == SIOCDIFADDR)) {
3408 			error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
3409 		}
3410 		break;
3411 	}
3412 
3413 done:
3414 	if (ifs != NULL) {
3415 		kfree_type(struct ifstat, ifs);
3416 	}
3417 
3418 	if (if_verbose) {
3419 		if (ifname[0] == '\0') {
3420 			(void) snprintf(ifname, sizeof(ifname), "%s",
3421 			    "NULL");
3422 		} else if (ifp != NULL) {
3423 			(void) snprintf(ifname, sizeof(ifname), "%s",
3424 			    if_name(ifp));
3425 		}
3426 
3427 		if (error != 0) {
3428 			printf("%s[%s,%d]: ifp %s cmd 0x%08lx (%c%c [%lu] "
3429 			    "%c %lu) error %d\n", __func__,
3430 			    proc_name_address(p), proc_pid(p),
3431 			    ifname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
3432 			    (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
3433 			    (char)IOCGROUP(cmd), cmd & 0xff, error);
3434 		} else if (if_verbose > 1) {
3435 			printf("%s[%s,%d]: ifp %s cmd 0x%08lx (%c%c [%lu] "
3436 			    "%c %lu) OK\n", __func__,
3437 			    proc_name_address(p), proc_pid(p),
3438 			    ifname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
3439 			    (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
3440 			    (char)IOCGROUP(cmd), cmd & 0xff);
3441 		}
3442 	}
3443 
3444 	if (ifp != NULL) {
3445 		ifnet_decr_iorefcnt(ifp);
3446 	}
3447 	return error;
3448 }
3449 
3450 static __attribute__((noinline)) int
ifioctl_ifreq(struct socket * so,u_long cmd,struct ifreq * ifr,struct proc * p)3451 ifioctl_ifreq(struct socket *so, u_long cmd, struct ifreq *ifr, struct proc *p)
3452 {
3453 	struct ifnet *ifp;
3454 	u_long ocmd = cmd;
3455 	int error = 0;
3456 	struct kev_msg ev_msg;
3457 	struct net_event_data ev_data;
3458 
3459 	bzero(&ev_data, sizeof(struct net_event_data));
3460 	bzero(&ev_msg, sizeof(struct kev_msg));
3461 
3462 	switch (cmd) {
3463 	case SIOCIFCREATE:
3464 	case SIOCIFCREATE2:
3465 		error = proc_suser(p);
3466 		if (error) {
3467 			return error;
3468 		}
3469 		return if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name),
3470 		           cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL);
3471 	case SIOCIFDESTROY:
3472 		error = proc_suser(p);
3473 		if (error) {
3474 			return error;
3475 		}
3476 		return if_clone_destroy(ifr->ifr_name);
3477 	}
3478 
3479 	/*
3480 	 * ioctls which require ifp.  Note that we acquire dlil_ifnet_lock
3481 	 * here to ensure that the ifnet, if found, has been fully attached.
3482 	 */
3483 	dlil_if_lock();
3484 	ifp = ifunit(ifr->ifr_name);
3485 	dlil_if_unlock();
3486 
3487 	if (ifp == NULL) {
3488 		return ENXIO;
3489 	}
3490 
3491 	switch (cmd) {
3492 	case SIOCGIFFLAGS:
3493 		ifnet_lock_shared(ifp);
3494 		ifr->ifr_flags = ifp->if_flags;
3495 		ifnet_lock_done(ifp);
3496 		break;
3497 
3498 	case SIOCGIFEFLAGS:
3499 		ifnet_lock_shared(ifp);
3500 		ifr->ifr_eflags = ifp->if_eflags;
3501 		ifnet_lock_done(ifp);
3502 		break;
3503 
3504 	case SIOCGIFXFLAGS:
3505 		ifnet_lock_shared(ifp);
3506 		ifr->ifr_xflags = ifp->if_xflags;
3507 		ifnet_lock_done(ifp);
3508 		break;
3509 
3510 	case SIOCGIFCAP:
3511 		ifnet_lock_shared(ifp);
3512 		ifr->ifr_reqcap = ifp->if_capabilities;
3513 		ifr->ifr_curcap = ifp->if_capenable;
3514 		ifnet_lock_done(ifp);
3515 		break;
3516 
3517 	case SIOCGIFMETRIC:
3518 		ifnet_lock_shared(ifp);
3519 		ifr->ifr_metric = ifp->if_metric;
3520 		ifnet_lock_done(ifp);
3521 		break;
3522 
3523 	case SIOCGIFMTU:
3524 		ifnet_lock_shared(ifp);
3525 		ifr->ifr_mtu = ifp->if_mtu;
3526 		ifnet_lock_done(ifp);
3527 		break;
3528 
3529 	case SIOCGIFPHYS:
3530 		ifnet_lock_shared(ifp);
3531 		ifr->ifr_phys = ifp->if_physical;
3532 		ifnet_lock_done(ifp);
3533 		break;
3534 
3535 	case SIOCSIFFLAGS:
3536 		error = proc_suser(p);
3537 		if (error != 0) {
3538 			break;
3539 		}
3540 
3541 		(void) ifnet_set_flags(ifp, ifr->ifr_flags,
3542 		    (u_int16_t)~IFF_CANTCHANGE);
3543 
3544 		/*
3545 		 * Note that we intentionally ignore any error from below
3546 		 * for the SIOCSIFFLAGS case.
3547 		 */
3548 		(void) ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3549 
3550 		/*
3551 		 * Send the event even upon error from the driver because
3552 		 * we changed the flags.
3553 		 */
3554 		dlil_post_sifflags_msg(ifp);
3555 
3556 		ifnet_touch_lastchange(ifp);
3557 		break;
3558 
3559 	case SIOCSIFCAP:
3560 		error = proc_suser(p);
3561 		if (error != 0) {
3562 			break;
3563 		}
3564 
3565 		if ((ifr->ifr_reqcap & ~ifp->if_capabilities)) {
3566 			error = EINVAL;
3567 			break;
3568 		}
3569 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3570 
3571 		ifnet_touch_lastchange(ifp);
3572 		break;
3573 
3574 	case SIOCSIFMETRIC:
3575 		error = proc_suser(p);
3576 		if (error != 0) {
3577 			break;
3578 		}
3579 
3580 		ifp->if_metric = ifr->ifr_metric;
3581 
3582 		ev_msg.vendor_code    = KEV_VENDOR_APPLE;
3583 		ev_msg.kev_class      = KEV_NETWORK_CLASS;
3584 		ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
3585 
3586 		ev_msg.event_code = KEV_DL_SIFMETRICS;
3587 		strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3588 		ev_data.if_family = ifp->if_family;
3589 		ev_data.if_unit   = (u_int32_t) ifp->if_unit;
3590 		ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3591 		ev_msg.dv[0].data_ptr    = &ev_data;
3592 
3593 		ev_msg.dv[1].data_length = 0;
3594 		dlil_post_complete_msg(ifp, &ev_msg);
3595 
3596 		ifnet_touch_lastchange(ifp);
3597 		break;
3598 
3599 	case SIOCSIFPHYS:
3600 		error = proc_suser(p);
3601 		if (error != 0) {
3602 			break;
3603 		}
3604 
3605 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3606 		if (error != 0) {
3607 			break;
3608 		}
3609 
3610 		ev_msg.vendor_code    = KEV_VENDOR_APPLE;
3611 		ev_msg.kev_class      = KEV_NETWORK_CLASS;
3612 		ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
3613 
3614 		ev_msg.event_code = KEV_DL_SIFPHYS;
3615 		strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3616 		ev_data.if_family = ifp->if_family;
3617 		ev_data.if_unit   = (u_int32_t) ifp->if_unit;
3618 		ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3619 		ev_msg.dv[0].data_ptr    = &ev_data;
3620 		ev_msg.dv[1].data_length = 0;
3621 		dlil_post_complete_msg(ifp, &ev_msg);
3622 
3623 		ifnet_touch_lastchange(ifp);
3624 		break;
3625 
3626 	case SIOCSIFMTU: {
3627 		u_int32_t oldmtu = ifp->if_mtu;
3628 		struct ifclassq *ifq = ifp->if_snd;
3629 
3630 		ASSERT(ifq != NULL);
3631 		error = proc_suser(p);
3632 		if (error != 0) {
3633 			break;
3634 		}
3635 
3636 		if (ifp->if_ioctl == NULL) {
3637 			error = EOPNOTSUPP;
3638 			break;
3639 		}
3640 		if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) {
3641 			error = EINVAL;
3642 			break;
3643 		}
3644 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3645 		if (error != 0) {
3646 			break;
3647 		}
3648 
3649 		ev_msg.vendor_code    = KEV_VENDOR_APPLE;
3650 		ev_msg.kev_class      = KEV_NETWORK_CLASS;
3651 		ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
3652 
3653 		ev_msg.event_code = KEV_DL_SIFMTU;
3654 		strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3655 		ev_data.if_family = ifp->if_family;
3656 		ev_data.if_unit   = (u_int32_t) ifp->if_unit;
3657 		ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3658 		ev_msg.dv[0].data_ptr    = &ev_data;
3659 		ev_msg.dv[1].data_length = 0;
3660 		dlil_post_complete_msg(ifp, &ev_msg);
3661 
3662 		ifnet_touch_lastchange(ifp);
3663 		rt_ifmsg(ifp);
3664 
3665 		/*
3666 		 * If the link MTU changed, do network layer specific procedure
3667 		 * and update all route entries associated with the interface,
3668 		 * so that their MTU metric gets updated.
3669 		 */
3670 		if (ifp->if_mtu != oldmtu) {
3671 			if_rtmtu_update(ifp);
3672 			nd6_setmtu(ifp);
3673 			/* Inform all transmit queues about the new MTU */
3674 			IFCQ_LOCK(ifq);
3675 			ifnet_update_sndq(ifq, CLASSQ_EV_LINK_MTU);
3676 			IFCQ_UNLOCK(ifq);
3677 		}
3678 		break;
3679 	}
3680 
3681 	case SIOCADDMULTI:
3682 	case SIOCDELMULTI:
3683 		error = proc_suser(p);
3684 		if (error != 0) {
3685 			break;
3686 		}
3687 
3688 		/* Don't allow group membership on non-multicast interfaces. */
3689 		if ((ifp->if_flags & IFF_MULTICAST) == 0) {
3690 			error = EOPNOTSUPP;
3691 			break;
3692 		}
3693 
3694 		/* Don't let users screw up protocols' entries. */
3695 		if (ifr->ifr_addr.sa_family != AF_UNSPEC &&
3696 		    ifr->ifr_addr.sa_family != AF_LINK) {
3697 			error = EINVAL;
3698 			break;
3699 		}
3700 		if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
3701 			ifr->ifr_addr.sa_len = sizeof(struct sockaddr);
3702 		}
3703 
3704 		/*
3705 		 * User is permitted to anonymously join a particular link
3706 		 * multicast group via SIOCADDMULTI.  Subsequent join requested
3707 		 * for the same record which has an outstanding refcnt from a
3708 		 * past if_addmulti_anon() will not result in EADDRINUSE error
3709 		 * (unlike other BSDs.)  Anonymously leaving a group is also
3710 		 * allowed only as long as there is an outstanding refcnt held
3711 		 * by a previous anonymous request, or else ENOENT (even if the
3712 		 * link-layer multicast membership exists for a network-layer
3713 		 * membership.)
3714 		 */
3715 		if (cmd == SIOCADDMULTI) {
3716 			error = if_addmulti_anon(ifp, &ifr->ifr_addr, NULL);
3717 			ev_msg.event_code = KEV_DL_ADDMULTI;
3718 		} else {
3719 			error = if_delmulti_anon(ifp, &ifr->ifr_addr);
3720 			ev_msg.event_code = KEV_DL_DELMULTI;
3721 		}
3722 		if (error != 0) {
3723 			break;
3724 		}
3725 
3726 		ev_msg.vendor_code    = KEV_VENDOR_APPLE;
3727 		ev_msg.kev_class      = KEV_NETWORK_CLASS;
3728 		ev_msg.kev_subclass   = KEV_DL_SUBCLASS;
3729 		strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3730 
3731 		ev_data.if_family = ifp->if_family;
3732 		ev_data.if_unit   = (u_int32_t) ifp->if_unit;
3733 		ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3734 		ev_msg.dv[0].data_ptr    = &ev_data;
3735 		ev_msg.dv[1].data_length = 0;
3736 		dlil_post_complete_msg(ifp, &ev_msg);
3737 
3738 		ifnet_touch_lastchange(ifp);
3739 		break;
3740 
3741 	case SIOCSIFMEDIA:
3742 		error = proc_suser(p);
3743 		if (error != 0) {
3744 			break;
3745 		}
3746 		/*
3747 		 * Silently ignore setting IFM_OTHER
3748 		 */
3749 		if (ifr->ifr_media == IFM_OTHER) {
3750 			os_log_info(OS_LOG_DEFAULT,
3751 			    "%s: %s SIOCSIFMEDIA ignore IFM_OTHER",
3752 			    __func__, ifp->if_xname);
3753 			error = 0;
3754 			break;
3755 		}
3756 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3757 		if (error != 0) {
3758 			break;
3759 		}
3760 		ifnet_touch_lastchange(ifp);
3761 		break;
3762 
3763 	case SIOCDIFPHYADDR:
3764 	case SIOCSIFGENERIC:
3765 	case SIOCSIFLLADDR:
3766 	case SIOCSIFALTMTU:
3767 	case SIOCSIFVLAN:
3768 	case SIOCSIFBOND:
3769 		error = proc_suser(p);
3770 		if (error != 0) {
3771 			break;
3772 		}
3773 
3774 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3775 		if (error != 0) {
3776 			break;
3777 		}
3778 
3779 		ifnet_touch_lastchange(ifp);
3780 		break;
3781 
3782 	case SIOCGIFLLADDR: {
3783 		struct sockaddr_dl *sdl = SDL(ifp->if_lladdr->ifa_addr);
3784 
3785 		if (sdl->sdl_alen == 0) {
3786 			error = EADDRNOTAVAIL;
3787 			break;
3788 		}
3789 		/* If larger than 14-bytes we'll need another mechanism */
3790 		if (sdl->sdl_alen > sizeof(ifr->ifr_addr.sa_data)) {
3791 			error = EMSGSIZE;
3792 			break;
3793 		}
3794 		/* Follow the same convention used by SIOCSIFLLADDR */
3795 		bzero(&ifr->ifr_addr, sizeof(ifr->ifr_addr));
3796 		ifr->ifr_addr.sa_family = AF_LINK;
3797 		ifr->ifr_addr.sa_len = sdl->sdl_alen;
3798 		error = ifnet_guarded_lladdr_copy_bytes(ifp,
3799 		    &ifr->ifr_addr.sa_data, sdl->sdl_alen);
3800 		break;
3801 	}
3802 
3803 	case SIOCGIFTYPE:
3804 		ifr->ifr_type.ift_type = ifp->if_type;
3805 		ifr->ifr_type.ift_family = ifp->if_family;
3806 		ifr->ifr_type.ift_subfamily = ifp->if_subfamily;
3807 		break;
3808 
3809 	case SIOCGIFFUNCTIONALTYPE:
3810 		ifr->ifr_functional_type = if_functional_type(ifp, FALSE);
3811 		break;
3812 
3813 	case SIOCGIFPSRCADDR:
3814 	case SIOCGIFPDSTADDR:
3815 	case SIOCGIFGENERIC:
3816 	case SIOCGIFDEVMTU:
3817 	case SIOCGIFVLAN:
3818 	case SIOCGIFBOND:
3819 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3820 		break;
3821 
3822 	case SIOCGIFWAKEFLAGS:
3823 		ifnet_lock_shared(ifp);
3824 		ifr->ifr_wake_flags = ifnet_get_wake_flags(ifp);
3825 		ifnet_lock_done(ifp);
3826 		break;
3827 
3828 	case SIOCGIFGETRTREFCNT:
3829 		ifnet_lock_shared(ifp);
3830 		ifr->ifr_route_refcnt = ifp->if_route_refcnt;
3831 		ifnet_lock_done(ifp);
3832 		break;
3833 
3834 	case SIOCSIFOPPORTUNISTIC:
3835 	case SIOCGIFOPPORTUNISTIC:
3836 		error = ifnet_getset_opportunistic(ifp, cmd, ifr, p);
3837 		break;
3838 
3839 	case SIOCGIFLINKQUALITYMETRIC:
3840 		ifnet_lock_shared(ifp);
3841 		if ((ifp->if_interface_state.valid_bitmask &
3842 		    IF_INTERFACE_STATE_LQM_STATE_VALID)) {
3843 			ifr->ifr_link_quality_metric =
3844 			    ifp->if_interface_state.lqm_state;
3845 		} else if (IF_FULLY_ATTACHED(ifp)) {
3846 			ifr->ifr_link_quality_metric =
3847 			    IFNET_LQM_THRESH_UNKNOWN;
3848 		} else {
3849 			ifr->ifr_link_quality_metric =
3850 			    IFNET_LQM_THRESH_OFF;
3851 		}
3852 		ifnet_lock_done(ifp);
3853 		break;
3854 
3855 	case SIOCSIFLINKQUALITYMETRIC:
3856 		if ((error = priv_check_cred(kauth_cred_get(),
3857 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
3858 			return error;
3859 		}
3860 		error = ifnet_set_link_quality(ifp, ifr->ifr_link_quality_metric);
3861 		break;
3862 
3863 	case SIOCSIFLOG:
3864 	case SIOCGIFLOG:
3865 		error = ifnet_getset_log(ifp, cmd, ifr, p);
3866 		break;
3867 
3868 	case SIOCGIFDELEGATE:
3869 		ifnet_lock_shared(ifp);
3870 		ifr->ifr_delegated = ((ifp->if_delegated.ifp != NULL) ?
3871 		    ifp->if_delegated.ifp->if_index : 0);
3872 		ifnet_lock_done(ifp);
3873 		break;
3874 
3875 	case SIOCGIFEXPENSIVE:
3876 		ifnet_lock_shared(ifp);
3877 		if (ifp->if_eflags & IFEF_EXPENSIVE) {
3878 			ifr->ifr_expensive = 1;
3879 		} else {
3880 			ifr->ifr_expensive = 0;
3881 		}
3882 		ifnet_lock_done(ifp);
3883 		break;
3884 
3885 	case SIOCSIFEXPENSIVE:
3886 	{
3887 		struct ifnet *difp;
3888 
3889 		if ((error = priv_check_cred(kauth_cred_get(),
3890 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
3891 			return error;
3892 		}
3893 		if (ifr->ifr_expensive) {
3894 			if_set_eflags(ifp, IFEF_EXPENSIVE);
3895 		} else {
3896 			if_clear_eflags(ifp, IFEF_EXPENSIVE);
3897 		}
3898 		ifnet_increment_generation(ifp);
3899 
3900 		/*
3901 		 * Update the expensive bit in the delegated interface
3902 		 * structure.
3903 		 */
3904 		ifnet_head_lock_shared();
3905 		TAILQ_FOREACH(difp, &ifnet_head, if_link) {
3906 			ifnet_lock_exclusive(difp);
3907 			if (difp->if_delegated.ifp == ifp) {
3908 				difp->if_delegated.expensive =
3909 				    ifp->if_eflags & IFEF_EXPENSIVE ? 1 : 0;
3910 				ifnet_increment_generation(difp);
3911 			}
3912 			ifnet_lock_done(difp);
3913 		}
3914 		ifnet_head_done();
3915 		necp_update_all_clients();
3916 		break;
3917 	}
3918 
3919 	case SIOCGIFCONSTRAINED:
3920 		if ((ifp->if_xflags & IFXF_CONSTRAINED) != 0) {
3921 			ifr->ifr_constrained = 1;
3922 		} else {
3923 			ifr->ifr_constrained = 0;
3924 		}
3925 		break;
3926 
3927 	case SIOCSIFCONSTRAINED:
3928 	{
3929 		struct ifnet *difp;
3930 
3931 		if ((error = priv_check_cred(kauth_cred_get(),
3932 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
3933 			return error;
3934 		}
3935 		if (ifr->ifr_constrained) {
3936 			if_set_xflags(ifp, IFXF_CONSTRAINED);
3937 		} else {
3938 			if_clear_xflags(ifp, IFXF_CONSTRAINED);
3939 		}
3940 		ifnet_increment_generation(ifp);
3941 		/*
3942 		 * Update the constrained bit in the delegated interface
3943 		 * structure.
3944 		 */
3945 		ifnet_head_lock_shared();
3946 		TAILQ_FOREACH(difp, &ifnet_head, if_link) {
3947 			ifnet_lock_exclusive(difp);
3948 			if (difp->if_delegated.ifp == ifp) {
3949 				difp->if_delegated.constrained =
3950 				    ((ifp->if_xflags & IFXF_CONSTRAINED) != 0) ? 1 : 0;
3951 				ifnet_increment_generation(difp);
3952 			}
3953 			ifnet_lock_done(difp);
3954 		}
3955 		ifnet_head_done();
3956 		necp_update_all_clients();
3957 		break;
3958 	}
3959 
3960 	case SIOCSIFESTTHROUGHPUT:
3961 	{
3962 		bool changed = false;
3963 		struct ifnet *difp;
3964 
3965 		if ((error = priv_check_cred(kauth_cred_get(),
3966 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
3967 			return error;
3968 		}
3969 		ifnet_lock_exclusive(ifp);
3970 		changed = (ifp->if_estimated_up_bucket != ifr->ifr_estimated_throughput.up_bucket) ||
3971 		    (ifp->if_estimated_down_bucket != ifr->ifr_estimated_throughput.down_bucket);
3972 		ifp->if_estimated_up_bucket = ifr->ifr_estimated_throughput.up_bucket;
3973 		ifp->if_estimated_down_bucket = ifr->ifr_estimated_throughput.down_bucket;
3974 		if (changed) {
3975 			ifnet_increment_generation(ifp);
3976 		}
3977 		ifnet_lock_done(ifp);
3978 		os_log_info(OS_LOG_DEFAULT,
3979 		    "SIOCSIFESTTHROUGHPUT %s%s up: %u, down: %u",
3980 		    ifp->if_name, changed ? " changed" : "",
3981 		    ifp->if_estimated_up_bucket,
3982 		    ifp->if_estimated_down_bucket);
3983 		if (changed) {
3984 			/*
3985 			 * Update the generation on delegated interfaces.
3986 			 */
3987 			ifnet_head_lock_shared();
3988 			TAILQ_FOREACH(difp, &ifnet_head, if_link) {
3989 				ifnet_lock_exclusive(difp);
3990 				if (difp->if_delegated.ifp == ifp) {
3991 					ifnet_increment_generation(difp);
3992 				}
3993 				ifnet_lock_done(difp);
3994 			}
3995 			ifnet_head_done();
3996 			necp_update_all_clients();
3997 		}
3998 		break;
3999 	}
4000 
4001 	case SIOCSIFRADIODETAILS:
4002 	{
4003 		bool changed = false;
4004 		struct ifnet *difp;
4005 
4006 		if ((error = priv_check_cred(kauth_cred_get(),
4007 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4008 			return error;
4009 		}
4010 		ifnet_lock_exclusive(ifp);
4011 		changed = ifp->if_radio_type != ifr->ifr_radio_details.technology ||
4012 		    ifp->if_radio_channel != ifr->ifr_radio_details.channel;
4013 		ifp->if_radio_type = ifr->ifr_radio_details.technology;
4014 		ifp->if_radio_channel = ifr->ifr_radio_details.channel;
4015 		ifnet_lock_done(ifp);
4016 		os_log_info(OS_LOG_DEFAULT,
4017 		    "SIOCSIFRADIODETAILS %s%s technology: %u, channel: %u",
4018 		    ifp->if_name, changed ? " changed" : "",
4019 		    ifr->ifr_radio_details.technology,
4020 		    ifr->ifr_radio_details.channel);
4021 		if (changed) {
4022 			ifnet_increment_generation(ifp);
4023 			/*
4024 			 * Update the generation on delegated interfaces.
4025 			 */
4026 			ifnet_head_lock_shared();
4027 			TAILQ_FOREACH(difp, &ifnet_head, if_link) {
4028 				ifnet_lock_exclusive(difp);
4029 				if (difp->if_delegated.ifp == ifp) {
4030 					ifnet_increment_generation(difp);
4031 				}
4032 				ifnet_lock_done(difp);
4033 			}
4034 			ifnet_head_done();
4035 			necp_update_all_clients();
4036 		}
4037 		break;
4038 	}
4039 
4040 	case SIOCGIF2KCL:
4041 		ifnet_lock_shared(ifp);
4042 		if (ifp->if_eflags & IFEF_2KCL) {
4043 			ifr->ifr_2kcl = 1;
4044 		} else {
4045 			ifr->ifr_2kcl = 0;
4046 		}
4047 		ifnet_lock_done(ifp);
4048 		break;
4049 
4050 	case SIOCSIF2KCL:
4051 		if ((error = priv_check_cred(kauth_cred_get(),
4052 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4053 			return error;
4054 		}
4055 		if (ifr->ifr_2kcl) {
4056 			if_set_eflags(ifp, IFEF_2KCL);
4057 		} else {
4058 			if_clear_eflags(ifp, IFEF_2KCL);
4059 		}
4060 		break;
4061 	case SIOCGSTARTDELAY:
4062 		ifnet_lock_shared(ifp);
4063 		if (ifp->if_eflags & IFEF_ENQUEUE_MULTI) {
4064 			ifr->ifr_start_delay_qlen =
4065 			    ifp->if_start_delay_qlen;
4066 			ifr->ifr_start_delay_timeout =
4067 			    ifp->if_start_delay_timeout;
4068 		} else {
4069 			ifr->ifr_start_delay_qlen = 0;
4070 			ifr->ifr_start_delay_timeout = 0;
4071 		}
4072 		ifnet_lock_done(ifp);
4073 		break;
4074 	case SIOCSIFDSTADDR:
4075 	case SIOCSIFADDR:
4076 	case SIOCSIFBRDADDR:
4077 	case SIOCSIFNETMASK:
4078 	case OSIOCGIFADDR:
4079 	case OSIOCGIFDSTADDR:
4080 	case OSIOCGIFBRDADDR:
4081 	case OSIOCGIFNETMASK:
4082 	case SIOCSIFKPI:
4083 		VERIFY(so->so_proto != NULL);
4084 
4085 		if (cmd == SIOCSIFDSTADDR || cmd == SIOCSIFADDR ||
4086 		    cmd == SIOCSIFBRDADDR || cmd == SIOCSIFNETMASK) {
4087 #if BYTE_ORDER != BIG_ENDIAN
4088 			if (ifr->ifr_addr.sa_family == 0 &&
4089 			    ifr->ifr_addr.sa_len < 16) {
4090 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
4091 				ifr->ifr_addr.sa_len = 16;
4092 			}
4093 #else
4094 			if (ifr->ifr_addr.sa_len == 0) {
4095 				ifr->ifr_addr.sa_len = 16;
4096 			}
4097 #endif
4098 		} else if (cmd == OSIOCGIFADDR) {
4099 			cmd = SIOCGIFADDR;      /* struct ifreq */
4100 		} else if (cmd == OSIOCGIFDSTADDR) {
4101 			cmd = SIOCGIFDSTADDR;   /* struct ifreq */
4102 		} else if (cmd == OSIOCGIFBRDADDR) {
4103 			cmd = SIOCGIFBRDADDR;   /* struct ifreq */
4104 		} else if (cmd == OSIOCGIFNETMASK) {
4105 			cmd = SIOCGIFNETMASK;   /* struct ifreq */
4106 		}
4107 
4108 		socket_lock(so, 1);
4109 		error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
4110 		    (caddr_t)ifr, ifp, p));
4111 		socket_unlock(so, 1);
4112 
4113 		switch (ocmd) {
4114 		case OSIOCGIFADDR:
4115 		case OSIOCGIFDSTADDR:
4116 		case OSIOCGIFBRDADDR:
4117 		case OSIOCGIFNETMASK:
4118 			bcopy(&ifr->ifr_addr.sa_family, &ifr->ifr_addr,
4119 			    sizeof(u_short));
4120 		}
4121 
4122 		if (cmd == SIOCSIFKPI) {
4123 			int temperr = proc_suser(p);
4124 			if (temperr != 0) {
4125 				error = temperr;
4126 			}
4127 		}
4128 		// Don't allow to call SIOCSIFADDR and SIOCSIFDSTADDR
4129 		// with ifreq as the code expects ifaddr
4130 		if ((error == EOPNOTSUPP || error == ENOTSUP) &&
4131 		    !(cmd == SIOCSIFADDR || cmd == SIOCSIFDSTADDR)) {
4132 			error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd,
4133 			    (caddr_t)ifr);
4134 		}
4135 		break;
4136 
4137 	case SIOCGIFINTERFACESTATE:
4138 		if_get_state(ifp, &ifr->ifr_interface_state);
4139 		break;
4140 
4141 	case SIOCSIFINTERFACESTATE:
4142 		if ((error = priv_check_cred(kauth_cred_get(),
4143 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4144 			return error;
4145 		}
4146 
4147 		error = if_state_update(ifp, &ifr->ifr_interface_state);
4148 
4149 		break;
4150 	case SIOCSIFPROBECONNECTIVITY:
4151 		if ((error = priv_check_cred(kauth_cred_get(),
4152 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4153 			return error;
4154 		}
4155 		error = if_probe_connectivity(ifp,
4156 		    ifr->ifr_probe_connectivity);
4157 		break;
4158 	case SIOCGIFPROBECONNECTIVITY:
4159 		if ((error = priv_check_cred(kauth_cred_get(),
4160 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4161 			return error;
4162 		}
4163 		if (ifp->if_eflags & IFEF_PROBE_CONNECTIVITY) {
4164 			ifr->ifr_probe_connectivity = 1;
4165 		} else {
4166 			ifr->ifr_probe_connectivity = 0;
4167 		}
4168 		break;
4169 	case SIOCGECNMODE:
4170 		if ((ifp->if_eflags & (IFEF_ECN_ENABLE | IFEF_ECN_DISABLE)) ==
4171 		    IFEF_ECN_ENABLE) {
4172 			ifr->ifr_ecn_mode = IFRTYPE_ECN_ENABLE;
4173 		} else if ((ifp->if_eflags & (IFEF_ECN_ENABLE | IFEF_ECN_DISABLE)) ==
4174 		    IFEF_ECN_DISABLE) {
4175 			ifr->ifr_ecn_mode = IFRTYPE_ECN_DISABLE;
4176 		} else {
4177 			ifr->ifr_ecn_mode = IFRTYPE_ECN_DEFAULT;
4178 		}
4179 		break;
4180 	case SIOCSECNMODE:
4181 		if ((error = priv_check_cred(kauth_cred_get(),
4182 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4183 			return error;
4184 		}
4185 		if (ifr->ifr_ecn_mode == IFRTYPE_ECN_DEFAULT) {
4186 			if_clear_eflags(ifp, IFEF_ECN_ENABLE | IFEF_ECN_DISABLE);
4187 		} else if (ifr->ifr_ecn_mode == IFRTYPE_ECN_ENABLE) {
4188 			if_set_eflags(ifp, IFEF_ECN_ENABLE);
4189 			if_clear_eflags(ifp, IFEF_ECN_DISABLE);
4190 		} else if (ifr->ifr_ecn_mode == IFRTYPE_ECN_DISABLE) {
4191 			if_set_eflags(ifp, IFEF_ECN_DISABLE);
4192 			if_clear_eflags(ifp, IFEF_ECN_ENABLE);
4193 		} else {
4194 			error = EINVAL;
4195 		}
4196 		break;
4197 
4198 	case SIOCSIFTIMESTAMPENABLE:
4199 	case SIOCSIFTIMESTAMPDISABLE:
4200 		error = proc_suser(p);
4201 		if (error != 0) {
4202 			break;
4203 		}
4204 
4205 		if ((cmd == SIOCSIFTIMESTAMPENABLE &&
4206 		    (ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) != 0) ||
4207 		    (cmd == SIOCSIFTIMESTAMPDISABLE &&
4208 		    (ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) == 0)) {
4209 			break;
4210 		}
4211 		if (cmd == SIOCSIFTIMESTAMPENABLE) {
4212 			if_set_xflags(ifp, IFXF_TIMESTAMP_ENABLED);
4213 		} else {
4214 			if_clear_xflags(ifp, IFXF_TIMESTAMP_ENABLED);
4215 		}
4216 		/*
4217 		 * Pass the setting to the interface if it supports either
4218 		 * software or hardware time stamping
4219 		 */
4220 		if (ifp->if_capabilities & (IFCAP_HW_TIMESTAMP |
4221 		    IFCAP_SW_TIMESTAMP)) {
4222 			error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd,
4223 			    (caddr_t)ifr);
4224 		}
4225 		break;
4226 	case SIOCGIFTIMESTAMPENABLED: {
4227 		if ((ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) != 0) {
4228 			ifr->ifr_intval = 1;
4229 		} else {
4230 			ifr->ifr_intval = 0;
4231 		}
4232 		break;
4233 	}
4234 	case SIOCSQOSMARKINGMODE:
4235 		if ((error = priv_check_cred(kauth_cred_get(),
4236 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4237 			return error;
4238 		}
4239 		error = if_set_qosmarking_mode(ifp, ifr->ifr_qosmarking_mode);
4240 		break;
4241 
4242 	case SIOCGQOSMARKINGMODE:
4243 		ifr->ifr_qosmarking_mode = ifp->if_qosmarking_mode;
4244 		break;
4245 
4246 	case SIOCSQOSMARKINGENABLED:
4247 		if ((error = priv_check_cred(kauth_cred_get(),
4248 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4249 			return error;
4250 		}
4251 		if (ifr->ifr_qosmarking_enabled != 0) {
4252 			if_set_eflags(ifp, IFEF_QOSMARKING_ENABLED);
4253 		} else {
4254 			if_clear_eflags(ifp, IFEF_QOSMARKING_ENABLED);
4255 		}
4256 		break;
4257 
4258 	case SIOCGQOSMARKINGENABLED:
4259 		ifr->ifr_qosmarking_enabled =
4260 		    ((ifp->if_eflags & IFEF_QOSMARKING_ENABLED) != 0) ? 1 : 0;
4261 		break;
4262 
4263 	case SIOCSIFDISABLEOUTPUT:
4264 #if (DEBUG || DEVELOPMENT)
4265 		if (ifr->ifr_disable_output == 1) {
4266 			error = ifnet_disable_output(ifp);
4267 		} else if (ifr->ifr_disable_output == 0) {
4268 			error = ifnet_enable_output(ifp);
4269 		} else {
4270 			error = EINVAL;
4271 		}
4272 #else
4273 		error = EINVAL;
4274 #endif /* (DEBUG || DEVELOPMENT) */
4275 		break;
4276 
4277 	case SIOCSIFSUBFAMILY:
4278 		if ((error = priv_check_cred(kauth_cred_get(),
4279 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4280 			return error;
4281 		}
4282 		error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
4283 		break;
4284 
4285 	case SIOCSIFLOWINTERNET:
4286 		if ((error = priv_check_cred(kauth_cred_get(),
4287 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4288 			return error;
4289 		}
4290 
4291 		if (ifr->ifr_low_internet & IFRTYPE_LOW_INTERNET_ENABLE_UL) {
4292 			if_set_xflags(ifp, IFXF_LOW_INTERNET_UL);
4293 		} else {
4294 			if_clear_xflags(ifp, IFXF_LOW_INTERNET_UL);
4295 		}
4296 		if (ifr->ifr_low_internet & IFRTYPE_LOW_INTERNET_ENABLE_DL) {
4297 			if_set_xflags(ifp, IFXF_LOW_INTERNET_DL);
4298 		} else {
4299 			if_clear_xflags(ifp, IFXF_LOW_INTERNET_DL);
4300 		}
4301 		break;
4302 	case SIOCGIFLOWINTERNET:
4303 		ifnet_lock_shared(ifp);
4304 		ifr->ifr_low_internet = 0;
4305 		if ((ifp->if_xflags & IFXF_LOW_INTERNET_UL) != 0) {
4306 			ifr->ifr_low_internet |=
4307 			    IFRTYPE_LOW_INTERNET_ENABLE_UL;
4308 		}
4309 		if ((ifp->if_xflags & IFXF_LOW_INTERNET_DL) != 0) {
4310 			ifr->ifr_low_internet |=
4311 			    IFRTYPE_LOW_INTERNET_ENABLE_DL;
4312 		}
4313 		ifnet_lock_done(ifp);
4314 		break;
4315 	case SIOCGIFLOWPOWER:
4316 		ifr->ifr_low_power_mode =
4317 		    ((ifp->if_xflags & IFXF_LOW_POWER) != 0);
4318 		break;
4319 	case SIOCSIFLOWPOWER:
4320 #if (DEVELOPMENT || DEBUG)
4321 		error = if_set_low_power(ifp, (ifr->ifr_low_power_mode != 0));
4322 #else /* DEVELOPMENT || DEBUG */
4323 		error = EOPNOTSUPP;
4324 #endif /* DEVELOPMENT || DEBUG */
4325 		break;
4326 
4327 	case SIOCGIFMPKLOG:
4328 		ifr->ifr_mpk_log = ((ifp->if_xflags & IFXF_MPK_LOG) != 0);
4329 		break;
4330 	case SIOCSIFMPKLOG:
4331 		if (ifr->ifr_mpk_log) {
4332 			if_set_xflags(ifp, IFXF_MPK_LOG);
4333 		} else {
4334 			if_clear_xflags(ifp, IFXF_MPK_LOG);
4335 		}
4336 		break;
4337 	case SIOCGIFNOACKPRIO:
4338 		if ((ifp->if_eflags & IFEF_NOACKPRI) != 0) {
4339 			ifr->ifr_noack_prio = 1;
4340 		} else {
4341 			ifr->ifr_noack_prio = 0;
4342 		}
4343 		break;
4344 
4345 	case SIOCSIFNOACKPRIO:
4346 		if ((error = priv_check_cred(kauth_cred_get(),
4347 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4348 			return error;
4349 		}
4350 		if (ifr->ifr_noack_prio) {
4351 			if_set_eflags(ifp, IFEF_NOACKPRI);
4352 		} else {
4353 			if_clear_eflags(ifp, IFEF_NOACKPRI);
4354 		}
4355 		break;
4356 
4357 	case SIOCSIFMARKWAKEPKT:
4358 #if (DEVELOPMENT || DEBUG)
4359 		if ((error = priv_check_cred(kauth_cred_get(),
4360 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4361 			return error;
4362 		}
4363 		if (net_wake_pkt_debug) {
4364 			os_log(OS_LOG_DEFAULT,
4365 			    "SIOCSIFMARKWAKEPKT %s", ifp->if_xname);
4366 		}
4367 		if (ifr->ifr_intval != 0) {
4368 			ifp->if_xflags |= IFXF_MARK_WAKE_PKT;
4369 		} else {
4370 			ifp->if_xflags &= ~IFXF_MARK_WAKE_PKT;
4371 		}
4372 #else /* DEVELOPMENT || DEBUG */
4373 		error = EOPNOTSUPP;
4374 #endif /* DEVELOPMENT || DEBUG */
4375 		break;
4376 
4377 	case SIOCSIFNOTRAFFICSHAPING:
4378 		if ((error = priv_check_cred(kauth_cred_get(),
4379 		    PRIV_NET_INTERFACE_CONTROL, 0)) != 0) {
4380 			return error;
4381 		}
4382 		os_log_info(OS_LOG_DEFAULT, "SIOCSIFNOTRAFFICSHAPING %s %d",
4383 		    ifp->if_xname, ifr->ifr_intval);
4384 		if (ifr->ifr_intval != 0) {
4385 			ifp->if_xflags |= IFXF_NO_TRAFFIC_SHAPING;
4386 		} else {
4387 			ifp->if_xflags &= ~IFXF_NO_TRAFFIC_SHAPING;
4388 		}
4389 		break;
4390 
4391 	case SIOCGIFNOTRAFFICSHAPING:
4392 		if ((ifp->if_xflags & IFXF_NO_TRAFFIC_SHAPING) != 0) {
4393 			ifr->ifr_intval = 1;
4394 		} else {
4395 			ifr->ifr_intval = 0;
4396 		}
4397 		break;
4398 
4399 	default:
4400 		VERIFY(0);
4401 		/* NOTREACHED */
4402 	}
4403 
4404 	return error;
4405 }
4406 
4407 int
ifioctllocked(struct socket * so,u_long cmd,caddr_t data,struct proc * p)4408 ifioctllocked(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
4409 {
4410 	int error;
4411 
4412 	socket_unlock(so, 0);
4413 	error = ifioctl(so, cmd, data, p);
4414 	socket_lock(so, 0);
4415 	return error;
4416 }
4417 
4418 /*
4419  * Set/clear promiscuous mode on interface ifp based on the truth value
4420  * of pswitch.  The calls are reference counted so that only the first
4421  * "on" request actually has an effect, as does the final "off" request.
4422  * Results are undefined if the "off" and "on" requests are not matched.
4423  */
4424 errno_t
ifnet_set_promiscuous(ifnet_t ifp,int pswitch)4425 ifnet_set_promiscuous(
4426 	ifnet_t ifp,
4427 	int pswitch)
4428 {
4429 	int error = 0;
4430 	int oldflags = 0;
4431 	int newflags = 0;
4432 
4433 	ifnet_lock_exclusive(ifp);
4434 	oldflags = ifp->if_flags;
4435 	ifp->if_pcount += pswitch ? 1 : -1;
4436 
4437 	if (ifp->if_pcount > 0) {
4438 		ifp->if_flags |= IFF_PROMISC;
4439 	} else {
4440 		ifp->if_flags &= ~IFF_PROMISC;
4441 	}
4442 
4443 	newflags = ifp->if_flags;
4444 	ifnet_lock_done(ifp);
4445 
4446 	if (newflags != oldflags && (newflags & IFF_UP) != 0) {
4447 		error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
4448 		if (error == 0) {
4449 			rt_ifmsg(ifp);
4450 		} else {
4451 			ifnet_lock_exclusive(ifp);
4452 			// revert the flags
4453 			ifp->if_pcount -= pswitch ? 1 : -1;
4454 			if (ifp->if_pcount > 0) {
4455 				ifp->if_flags |= IFF_PROMISC;
4456 			} else {
4457 				ifp->if_flags &= ~IFF_PROMISC;
4458 			}
4459 			ifnet_lock_done(ifp);
4460 		}
4461 	}
4462 
4463 	if (newflags != oldflags) {
4464 		log(LOG_INFO, "%s: promiscuous mode %s%s\n",
4465 		    if_name(ifp),
4466 		    (newflags & IFF_PROMISC) != 0 ? "enable" : "disable",
4467 		    error != 0 ? " failed" : " succeeded");
4468 	}
4469 	return error;
4470 }
4471 
4472 /*
4473  * Return interface configuration
4474  * of system.  List may be used
4475  * in later ioctl's (above) to get
4476  * other information.
4477  */
4478 /*ARGSUSED*/
4479 static int
ifconf(u_long cmd,user_addr_t ifrp,int * ret_space)4480 ifconf(u_long cmd, user_addr_t ifrp, int *ret_space)
4481 {
4482 	struct ifnet *ifp = NULL;
4483 	struct ifaddr *ifa;
4484 	struct ifreq ifr;
4485 	int error = 0;
4486 	size_t space;
4487 	net_thread_marks_t marks;
4488 
4489 	marks = net_thread_marks_push(NET_THREAD_CKREQ_LLADDR);
4490 
4491 	/*
4492 	 * Zero the ifr buffer to make sure we don't
4493 	 * disclose the contents of the stack.
4494 	 */
4495 	bzero(&ifr, sizeof(struct ifreq));
4496 
4497 	space = *ret_space;
4498 	ifnet_head_lock_shared();
4499 	for (ifp = ifnet_head.tqh_first; space > sizeof(ifr) &&
4500 	    ifp; ifp = ifp->if_link.tqe_next) {
4501 		char workbuf[64];
4502 		size_t ifnlen, addrs;
4503 
4504 		ifnlen = snprintf(workbuf, sizeof(workbuf),
4505 		    "%s", if_name(ifp));
4506 		if (ifnlen + 1 > sizeof(ifr.ifr_name)) {
4507 			error = ENAMETOOLONG;
4508 			break;
4509 		} else {
4510 			strlcpy(ifr.ifr_name, workbuf, IFNAMSIZ);
4511 		}
4512 
4513 		ifnet_lock_shared(ifp);
4514 
4515 		addrs = 0;
4516 		ifa = ifp->if_addrhead.tqh_first;
4517 		for (; space > sizeof(ifr) && ifa;
4518 		    ifa = ifa->ifa_link.tqe_next) {
4519 			struct sockaddr *sa;
4520 			union {
4521 				struct sockaddr sa;
4522 				struct sockaddr_dl sdl;
4523 				uint8_t buf[SOCK_MAXADDRLEN + 1];
4524 			} u;
4525 
4526 			/*
4527 			 * Make sure to accomodate the largest possible
4528 			 * size of SA(if_lladdr)->sa_len.
4529 			 */
4530 			_CASSERT(sizeof(u) == (SOCK_MAXADDRLEN + 1));
4531 
4532 			IFA_LOCK(ifa);
4533 			sa = ifa->ifa_addr;
4534 			addrs++;
4535 
4536 			if (ifa == ifp->if_lladdr) {
4537 				VERIFY(sa->sa_family == AF_LINK);
4538 				bcopy(sa, &u, sa->sa_len);
4539 				IFA_UNLOCK(ifa);
4540 				ifnet_guarded_lladdr_copy_bytes(ifp,
4541 				    LLADDR(&u.sdl), u.sdl.sdl_alen);
4542 				IFA_LOCK(ifa);
4543 				sa = &u.sa;
4544 			}
4545 
4546 			if (cmd == OSIOCGIFCONF32 || cmd == OSIOCGIFCONF64) {
4547 				struct osockaddr *osa =
4548 				    (struct osockaddr *)(void *)&ifr.ifr_addr;
4549 				ifr.ifr_addr = *sa;
4550 				osa->sa_family = sa->sa_family;
4551 				error = copyout((caddr_t)&ifr, ifrp,
4552 				    sizeof(ifr));
4553 				ifrp += sizeof(struct ifreq);
4554 			} else if (sa->sa_len <= sizeof(*sa)) {
4555 				ifr.ifr_addr = *sa;
4556 				error = copyout((caddr_t)&ifr, ifrp,
4557 				    sizeof(ifr));
4558 				ifrp += sizeof(struct ifreq);
4559 			} else {
4560 				if (space <
4561 				    sizeof(ifr) + sa->sa_len - sizeof(*sa)) {
4562 					IFA_UNLOCK(ifa);
4563 					break;
4564 				}
4565 				space -= sa->sa_len - sizeof(*sa);
4566 				error = copyout((caddr_t)&ifr, ifrp,
4567 				    sizeof(ifr.ifr_name));
4568 				if (error == 0) {
4569 					error = copyout((caddr_t)sa, (ifrp +
4570 					    offsetof(struct ifreq, ifr_addr)),
4571 					    sa->sa_len);
4572 				}
4573 				ifrp += (sa->sa_len + offsetof(struct ifreq,
4574 				    ifr_addr));
4575 			}
4576 			IFA_UNLOCK(ifa);
4577 			if (error) {
4578 				break;
4579 			}
4580 			space -= sizeof(ifr);
4581 		}
4582 		ifnet_lock_done(ifp);
4583 
4584 		if (error) {
4585 			break;
4586 		}
4587 		if (!addrs) {
4588 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
4589 			error = copyout((caddr_t)&ifr, ifrp, sizeof(ifr));
4590 			if (error) {
4591 				break;
4592 			}
4593 			space -= sizeof(ifr);
4594 			ifrp += sizeof(struct ifreq);
4595 		}
4596 	}
4597 	ifnet_head_done();
4598 	*ret_space -= space;
4599 	net_thread_marks_pop(marks);
4600 	return error;
4601 }
4602 
4603 /*
4604  * Just like if_promisc(), but for all-multicast-reception mode.
4605  */
4606 int
if_allmulti(struct ifnet * ifp,int onswitch)4607 if_allmulti(struct ifnet *ifp, int onswitch)
4608 {
4609 	int error = 0;
4610 	int     modified = 0;
4611 
4612 	ifnet_lock_exclusive(ifp);
4613 
4614 	if (onswitch) {
4615 		if (ifp->if_amcount++ == 0) {
4616 			ifp->if_flags |= IFF_ALLMULTI;
4617 			modified = 1;
4618 		}
4619 	} else {
4620 		if (ifp->if_amcount > 1) {
4621 			ifp->if_amcount--;
4622 		} else {
4623 			ifp->if_amcount = 0;
4624 			ifp->if_flags &= ~IFF_ALLMULTI;
4625 			modified = 1;
4626 		}
4627 	}
4628 	ifnet_lock_done(ifp);
4629 
4630 	if (modified) {
4631 		error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
4632 	}
4633 
4634 	if (error == 0) {
4635 		rt_ifmsg(ifp);
4636 	}
4637 	return error;
4638 }
4639 
4640 static struct ifmultiaddr *
ifma_alloc(zalloc_flags_t how)4641 ifma_alloc(zalloc_flags_t how)
4642 {
4643 	struct ifmultiaddr *ifma;
4644 
4645 	ifma = zalloc_flags(ifma_zone, how | Z_ZERO);
4646 
4647 	if (ifma != NULL) {
4648 		lck_mtx_init(&ifma->ifma_lock, &ifa_mtx_grp, &ifa_mtx_attr);
4649 		ifma->ifma_debug |= IFD_ALLOC;
4650 		if (ifma_debug != 0) {
4651 			ifma->ifma_debug |= IFD_DEBUG;
4652 			ifma->ifma_trace = ifma_trace;
4653 		}
4654 	}
4655 	return ifma;
4656 }
4657 
4658 static void
ifma_free(struct ifmultiaddr * ifma)4659 ifma_free(struct ifmultiaddr *ifma)
4660 {
4661 	IFMA_LOCK(ifma);
4662 
4663 	if (ifma->ifma_protospec != NULL) {
4664 		panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
4665 		/* NOTREACHED */
4666 	} else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4667 	    ifma->ifma_anoncnt != 0) {
4668 		panic("%s: Freeing ifma=%p with outstanding anon req",
4669 		    __func__, ifma);
4670 		/* NOTREACHED */
4671 	} else if (ifma->ifma_debug & IFD_ATTACHED) {
4672 		panic("%s: ifma=%p attached to ifma_ifp=%p is being freed",
4673 		    __func__, ifma, ifma->ifma_ifp);
4674 		/* NOTREACHED */
4675 	} else if (!(ifma->ifma_debug & IFD_ALLOC)) {
4676 		panic("%s: ifma %p cannot be freed", __func__, ifma);
4677 		/* NOTREACHED */
4678 	} else if (ifma->ifma_refcount != 0) {
4679 		panic("%s: non-zero refcount ifma=%p", __func__, ifma);
4680 		/* NOTREACHED */
4681 	} else if (ifma->ifma_reqcnt != 0) {
4682 		panic("%s: non-zero reqcnt ifma=%p", __func__, ifma);
4683 		/* NOTREACHED */
4684 	} else if (ifma->ifma_ifp != NULL) {
4685 		panic("%s: non-NULL ifma_ifp=%p for ifma=%p", __func__,
4686 		    ifma->ifma_ifp, ifma);
4687 		/* NOTREACHED */
4688 	} else if (ifma->ifma_ll != NULL) {
4689 		panic("%s: non-NULL ifma_ll=%p for ifma=%p", __func__,
4690 		    ifma->ifma_ll, ifma);
4691 		/* NOTREACHED */
4692 	}
4693 	ifma->ifma_debug &= ~IFD_ALLOC;
4694 	if ((ifma->ifma_debug & (IFD_DEBUG | IFD_TRASHED)) ==
4695 	    (IFD_DEBUG | IFD_TRASHED)) {
4696 		lck_mtx_lock(&ifma_trash_lock);
4697 		TAILQ_REMOVE(&ifma_trash_head, (struct ifmultiaddr_dbg *)ifma,
4698 		    ifma_trash_link);
4699 		lck_mtx_unlock(&ifma_trash_lock);
4700 		ifma->ifma_debug &= ~IFD_TRASHED;
4701 	}
4702 	IFMA_UNLOCK(ifma);
4703 
4704 	if (ifma->ifma_addr != NULL) {
4705 		kfree_data(ifma->ifma_addr, ifma->ifma_addr->sa_len);
4706 		ifma->ifma_addr = NULL;
4707 	}
4708 	lck_mtx_destroy(&ifma->ifma_lock, &ifa_mtx_grp);
4709 	zfree(ifma_zone, ifma);
4710 }
4711 
4712 static void
ifma_trace(struct ifmultiaddr * ifma,int refhold)4713 ifma_trace(struct ifmultiaddr *ifma, int refhold)
4714 {
4715 	struct ifmultiaddr_dbg *ifma_dbg = (struct ifmultiaddr_dbg *)ifma;
4716 	ctrace_t *tr;
4717 	u_int32_t idx;
4718 	u_int16_t *cnt;
4719 
4720 	if (!(ifma->ifma_debug & IFD_DEBUG)) {
4721 		panic("%s: ifma %p has no debug structure", __func__, ifma);
4722 		/* NOTREACHED */
4723 	}
4724 	if (refhold) {
4725 		cnt = &ifma_dbg->ifma_refhold_cnt;
4726 		tr = ifma_dbg->ifma_refhold;
4727 	} else {
4728 		cnt = &ifma_dbg->ifma_refrele_cnt;
4729 		tr = ifma_dbg->ifma_refrele;
4730 	}
4731 
4732 	idx = atomic_add_16_ov(cnt, 1) % IFMA_TRACE_HIST_SIZE;
4733 	ctrace_record(&tr[idx]);
4734 }
4735 
4736 void
ifma_addref(struct ifmultiaddr * ifma,int locked)4737 ifma_addref(struct ifmultiaddr *ifma, int locked)
4738 {
4739 	if (!locked) {
4740 		IFMA_LOCK(ifma);
4741 	} else {
4742 		IFMA_LOCK_ASSERT_HELD(ifma);
4743 	}
4744 
4745 	if (++ifma->ifma_refcount == 0) {
4746 		panic("%s: ifma=%p wraparound refcnt", __func__, ifma);
4747 		/* NOTREACHED */
4748 	} else if (ifma->ifma_trace != NULL) {
4749 		(*ifma->ifma_trace)(ifma, TRUE);
4750 	}
4751 	if (!locked) {
4752 		IFMA_UNLOCK(ifma);
4753 	}
4754 }
4755 
4756 void
ifma_remref(struct ifmultiaddr * ifma)4757 ifma_remref(struct ifmultiaddr *ifma)
4758 {
4759 	struct ifmultiaddr *ll;
4760 
4761 	IFMA_LOCK(ifma);
4762 
4763 	if (ifma->ifma_refcount == 0) {
4764 		panic("%s: ifma=%p negative refcnt", __func__, ifma);
4765 		/* NOTREACHED */
4766 	} else if (ifma->ifma_trace != NULL) {
4767 		(*ifma->ifma_trace)(ifma, FALSE);
4768 	}
4769 
4770 	--ifma->ifma_refcount;
4771 	if (ifma->ifma_refcount > 0) {
4772 		IFMA_UNLOCK(ifma);
4773 		return;
4774 	}
4775 
4776 	ll = ifma->ifma_ll;
4777 	ifma->ifma_ifp = NULL;
4778 	ifma->ifma_ll = NULL;
4779 	IFMA_UNLOCK(ifma);
4780 	ifma_free(ifma);        /* deallocate it */
4781 
4782 	if (ll != NULL) {
4783 		IFMA_REMREF(ll);
4784 	}
4785 }
4786 
4787 static void
if_attach_ifma(struct ifnet * ifp,struct ifmultiaddr * ifma,int anon)4788 if_attach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
4789 {
4790 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
4791 	IFMA_LOCK_ASSERT_HELD(ifma);
4792 
4793 	if (ifma->ifma_ifp != ifp) {
4794 		panic("%s: Mismatch ifma_ifp=%p != ifp=%p", __func__,
4795 		    ifma->ifma_ifp, ifp);
4796 		/* NOTREACHED */
4797 	} else if (ifma->ifma_debug & IFD_ATTACHED) {
4798 		panic("%s: Attempt to attach an already attached ifma=%p",
4799 		    __func__, ifma);
4800 		/* NOTREACHED */
4801 	} else if (anon && (ifma->ifma_flags & IFMAF_ANONYMOUS)) {
4802 		panic("%s: ifma=%p unexpected IFMAF_ANONYMOUS", __func__, ifma);
4803 		/* NOTREACHED */
4804 	} else if (ifma->ifma_debug & IFD_TRASHED) {
4805 		panic("%s: Attempt to reattach a detached ifma=%p",
4806 		    __func__, ifma);
4807 		/* NOTREACHED */
4808 	}
4809 
4810 	ifma->ifma_reqcnt++;
4811 	VERIFY(ifma->ifma_reqcnt == 1);
4812 	IFMA_ADDREF_LOCKED(ifma);
4813 	ifma->ifma_debug |= IFD_ATTACHED;
4814 	if (anon) {
4815 		ifma->ifma_anoncnt++;
4816 		VERIFY(ifma->ifma_anoncnt == 1);
4817 		ifma->ifma_flags |= IFMAF_ANONYMOUS;
4818 	}
4819 
4820 	LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
4821 }
4822 
4823 static int
if_detach_ifma(struct ifnet * ifp,struct ifmultiaddr * ifma,int anon)4824 if_detach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
4825 {
4826 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
4827 	IFMA_LOCK_ASSERT_HELD(ifma);
4828 
4829 	if (ifma->ifma_reqcnt == 0) {
4830 		panic("%s: ifma=%p negative reqcnt", __func__, ifma);
4831 		/* NOTREACHED */
4832 	} else if (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
4833 		panic("%s: ifma=%p missing IFMAF_ANONYMOUS", __func__, ifma);
4834 		/* NOTREACHED */
4835 	} else if (anon && ifma->ifma_anoncnt == 0) {
4836 		panic("%s: ifma=%p negative anonreqcnt", __func__, ifma);
4837 		/* NOTREACHED */
4838 	} else if (ifma->ifma_ifp != ifp) {
4839 		panic("%s: Mismatch ifma_ifp=%p, ifp=%p", __func__,
4840 		    ifma->ifma_ifp, ifp);
4841 		/* NOTREACHED */
4842 	}
4843 
4844 	if (anon) {
4845 		--ifma->ifma_anoncnt;
4846 		if (ifma->ifma_anoncnt > 0) {
4847 			return 0;
4848 		}
4849 		ifma->ifma_flags &= ~IFMAF_ANONYMOUS;
4850 	}
4851 
4852 	--ifma->ifma_reqcnt;
4853 	if (ifma->ifma_reqcnt > 0) {
4854 		return 0;
4855 	}
4856 
4857 	if (ifma->ifma_protospec != NULL) {
4858 		panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
4859 		/* NOTREACHED */
4860 	} else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4861 	    ifma->ifma_anoncnt != 0) {
4862 		panic("%s: Detaching ifma=%p with outstanding anon req",
4863 		    __func__, ifma);
4864 		/* NOTREACHED */
4865 	} else if (!(ifma->ifma_debug & IFD_ATTACHED)) {
4866 		panic("%s: Attempt to detach an unattached address ifma=%p",
4867 		    __func__, ifma);
4868 		/* NOTREACHED */
4869 	} else if (ifma->ifma_debug & IFD_TRASHED) {
4870 		panic("%s: ifma %p is already in trash list", __func__, ifma);
4871 		/* NOTREACHED */
4872 	}
4873 
4874 	/*
4875 	 * NOTE: Caller calls IFMA_REMREF
4876 	 */
4877 	ifma->ifma_debug &= ~IFD_ATTACHED;
4878 	LIST_REMOVE(ifma, ifma_link);
4879 	if (LIST_EMPTY(&ifp->if_multiaddrs)) {
4880 		ifp->if_updatemcasts = 0;
4881 	}
4882 
4883 	if (ifma->ifma_debug & IFD_DEBUG) {
4884 		/* Become a regular mutex, just in case */
4885 		IFMA_CONVERT_LOCK(ifma);
4886 		lck_mtx_lock(&ifma_trash_lock);
4887 		TAILQ_INSERT_TAIL(&ifma_trash_head,
4888 		    (struct ifmultiaddr_dbg *)ifma, ifma_trash_link);
4889 		lck_mtx_unlock(&ifma_trash_lock);
4890 		ifma->ifma_debug |= IFD_TRASHED;
4891 	}
4892 
4893 	return 1;
4894 }
4895 
4896 /*
4897  * Find an ifmultiaddr that matches a socket address on an interface.
4898  *
4899  * Caller is responsible for holding the ifnet_lock while calling
4900  * this function.
4901  */
4902 static int
if_addmulti_doesexist(struct ifnet * ifp,const struct sockaddr * sa,struct ifmultiaddr ** retifma,int anon)4903 if_addmulti_doesexist(struct ifnet *ifp, const struct sockaddr *sa,
4904     struct ifmultiaddr **retifma, int anon)
4905 {
4906 	struct ifmultiaddr *ifma;
4907 
4908 	for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
4909 	    ifma = LIST_NEXT(ifma, ifma_link)) {
4910 		IFMA_LOCK_SPIN(ifma);
4911 		if (!sa_equal(sa, ifma->ifma_addr)) {
4912 			IFMA_UNLOCK(ifma);
4913 			continue;
4914 		}
4915 		if (anon) {
4916 			VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4917 			    ifma->ifma_anoncnt != 0);
4918 			VERIFY((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4919 			    ifma->ifma_anoncnt == 0);
4920 			ifma->ifma_anoncnt++;
4921 			if (!(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
4922 				VERIFY(ifma->ifma_anoncnt == 1);
4923 				ifma->ifma_flags |= IFMAF_ANONYMOUS;
4924 			}
4925 		}
4926 		if (!anon || ifma->ifma_anoncnt == 1) {
4927 			ifma->ifma_reqcnt++;
4928 			VERIFY(ifma->ifma_reqcnt > 1);
4929 		}
4930 		if (retifma != NULL) {
4931 			*retifma = ifma;
4932 			IFMA_ADDREF_LOCKED(ifma);
4933 		}
4934 		IFMA_UNLOCK(ifma);
4935 		return 0;
4936 	}
4937 	return ENOENT;
4938 }
4939 
4940 /*
4941  * Radar 3642395, make sure all multicasts are in a standard format.
4942  */
4943 static struct sockaddr *
copy_and_normalize(const struct sockaddr * original)4944 copy_and_normalize(const struct sockaddr *original)
4945 {
4946 	int                     alen = 0;
4947 	const u_char            *aptr = NULL;
4948 	struct sockaddr         *copy = NULL;
4949 	struct sockaddr_dl      *sdl_new = NULL;
4950 	int                     len = 0;
4951 
4952 	if (original->sa_family != AF_LINK &&
4953 	    original->sa_family != AF_UNSPEC) {
4954 		/* Just make a copy */
4955 		copy = (struct sockaddr *)kalloc_data(original->sa_len, Z_WAITOK);
4956 		if (copy != NULL) {
4957 			bcopy(original, copy, original->sa_len);
4958 		}
4959 		return copy;
4960 	}
4961 
4962 	switch (original->sa_family) {
4963 	case AF_LINK: {
4964 		const struct sockaddr_dl *sdl_original =
4965 		    (struct sockaddr_dl *)(uintptr_t)(size_t)original;
4966 
4967 		if (sdl_original->sdl_len < offsetof(struct sockaddr_dl, sdl_data)) {
4968 			return NULL;
4969 		}
4970 		if (sdl_original->sdl_nlen + sdl_original->sdl_alen +
4971 		    sdl_original->sdl_slen +
4972 		    offsetof(struct sockaddr_dl, sdl_data) >
4973 		    sdl_original->sdl_len) {
4974 			return NULL;
4975 		}
4976 
4977 		alen = sdl_original->sdl_alen;
4978 		aptr = CONST_LLADDR(sdl_original);
4979 	}
4980 	break;
4981 
4982 	case AF_UNSPEC: {
4983 		if (original->sa_len < ETHER_ADDR_LEN +
4984 		    offsetof(struct sockaddr, sa_data)) {
4985 			return NULL;
4986 		}
4987 
4988 		alen = ETHER_ADDR_LEN;
4989 		aptr = (const u_char *)original->sa_data;
4990 	}
4991 	break;
4992 	}
4993 
4994 	if (alen == 0 || aptr == NULL) {
4995 		return NULL;
4996 	}
4997 
4998 	len = alen + offsetof(struct sockaddr_dl, sdl_data);
4999 	sdl_new = (struct sockaddr_dl *)kalloc_data(len, Z_WAITOK | Z_ZERO);
5000 
5001 	if (sdl_new != NULL) {
5002 		sdl_new->sdl_len = (u_char)len;
5003 		sdl_new->sdl_family = AF_LINK;
5004 		sdl_new->sdl_alen = (u_char)alen;
5005 		bcopy(aptr, LLADDR(sdl_new), alen);
5006 	}
5007 
5008 	return (struct sockaddr *)sdl_new;
5009 }
5010 
5011 /*
5012  * Network-layer protocol domains which hold references to the underlying
5013  * link-layer record must use this routine.
5014  */
5015 int
if_addmulti(struct ifnet * ifp,const struct sockaddr * sa,struct ifmultiaddr ** retifma)5016 if_addmulti(struct ifnet *ifp, const struct sockaddr *sa,
5017     struct ifmultiaddr **retifma)
5018 {
5019 	return if_addmulti_common(ifp, sa, retifma, 0);
5020 }
5021 
5022 /*
5023  * Anything other than network-layer protocol domains which hold references
5024  * to the underlying link-layer record must use this routine: SIOCADDMULTI
5025  * ioctl, ifnet_add_multicast(), if_bond.
5026  */
5027 int
if_addmulti_anon(struct ifnet * ifp,const struct sockaddr * sa,struct ifmultiaddr ** retifma)5028 if_addmulti_anon(struct ifnet *ifp, const struct sockaddr *sa,
5029     struct ifmultiaddr **retifma)
5030 {
5031 	return if_addmulti_common(ifp, sa, retifma, 1);
5032 }
5033 
5034 /*
5035  * Register an additional multicast address with a network interface.
5036  *
5037  * - If the address is already present, bump the reference count on the
5038  *   address and return.
5039  * - If the address is not link-layer, look up a link layer address.
5040  * - Allocate address structures for one or both addresses, and attach to the
5041  *   multicast address list on the interface.  If automatically adding a link
5042  *   layer address, the protocol address will own a reference to the link
5043  *   layer address, to be freed when it is freed.
5044  * - Notify the network device driver of an addition to the multicast address
5045  *   list.
5046  *
5047  * 'sa' points to caller-owned memory with the desired multicast address.
5048  *
5049  * 'retifma' will be used to return a pointer to the resulting multicast
5050  * address reference, if desired.
5051  *
5052  * 'anon' indicates a link-layer address with no protocol address reference
5053  * made to it.  Anything other than network-layer protocol domain requests
5054  * are considered as anonymous.
5055  */
5056 static int
if_addmulti_common(struct ifnet * ifp,const struct sockaddr * sa,struct ifmultiaddr ** retifma,int anon)5057 if_addmulti_common(struct ifnet *ifp, const struct sockaddr *sa,
5058     struct ifmultiaddr **retifma, int anon)
5059 {
5060 	struct sockaddr_storage storage;
5061 	struct sockaddr *llsa = NULL;
5062 	struct sockaddr *dupsa = NULL;
5063 	int error = 0, ll_firstref = 0, lladdr;
5064 	struct ifmultiaddr *ifma = NULL;
5065 	struct ifmultiaddr *llifma = NULL;
5066 
5067 	/* Only AF_UNSPEC/AF_LINK is allowed for an "anonymous" address */
5068 	VERIFY(!anon || sa->sa_family == AF_UNSPEC ||
5069 	    sa->sa_family == AF_LINK);
5070 
5071 	/* If sa is a AF_LINK or AF_UNSPEC, duplicate and normalize it */
5072 	if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
5073 		dupsa = copy_and_normalize(sa);
5074 		if (dupsa == NULL) {
5075 			error = ENOMEM;
5076 			goto cleanup;
5077 		}
5078 		sa = dupsa;
5079 	}
5080 
5081 	ifnet_lock_exclusive(ifp);
5082 	if (!(ifp->if_flags & IFF_MULTICAST)) {
5083 		error = EADDRNOTAVAIL;
5084 		ifnet_lock_done(ifp);
5085 		goto cleanup;
5086 	}
5087 
5088 	/* If the address is already present, return a new reference to it */
5089 	error = if_addmulti_doesexist(ifp, sa, retifma, anon);
5090 	ifnet_lock_done(ifp);
5091 	if (error == 0) {
5092 		goto cleanup;
5093 	}
5094 
5095 	/*
5096 	 * The address isn't already present; give the link layer a chance
5097 	 * to accept/reject it, and also find out which AF_LINK address this
5098 	 * maps to, if it isn't one already.
5099 	 */
5100 	error = dlil_resolve_multi(ifp, sa, (struct sockaddr *)&storage,
5101 	    sizeof(storage));
5102 	if (error == 0 && storage.ss_len != 0) {
5103 		llsa = copy_and_normalize((struct sockaddr *)&storage);
5104 		if (llsa == NULL) {
5105 			error = ENOMEM;
5106 			goto cleanup;
5107 		}
5108 
5109 		llifma = ifma_alloc(Z_WAITOK);
5110 		if (llifma == NULL) {
5111 			error = ENOMEM;
5112 			goto cleanup;
5113 		}
5114 	}
5115 
5116 	/* to be similar to FreeBSD */
5117 	if (error == EOPNOTSUPP) {
5118 		error = 0;
5119 	} else if (error != 0) {
5120 		goto cleanup;
5121 	}
5122 
5123 	/* Allocate while we aren't holding any locks */
5124 	if (dupsa == NULL) {
5125 		dupsa = copy_and_normalize(sa);
5126 		if (dupsa == NULL) {
5127 			error = ENOMEM;
5128 			goto cleanup;
5129 		}
5130 	}
5131 	ifma = ifma_alloc(Z_WAITOK);
5132 	if (ifma == NULL) {
5133 		error = ENOMEM;
5134 		goto cleanup;
5135 	}
5136 
5137 	ifnet_lock_exclusive(ifp);
5138 	/*
5139 	 * Check again for the matching multicast.
5140 	 */
5141 	error = if_addmulti_doesexist(ifp, sa, retifma, anon);
5142 	if (error == 0) {
5143 		ifnet_lock_done(ifp);
5144 		goto cleanup;
5145 	}
5146 
5147 	if (llifma != NULL) {
5148 		VERIFY(!anon);  /* must not get here if "anonymous" */
5149 		if (if_addmulti_doesexist(ifp, llsa, &ifma->ifma_ll, 0) == 0) {
5150 			kfree_data(llsa, llsa->sa_len);
5151 			llsa = NULL;
5152 			ifma_free(llifma);
5153 			llifma = NULL;
5154 			VERIFY(ifma->ifma_ll->ifma_ifp == ifp);
5155 		} else {
5156 			ll_firstref = 1;
5157 			llifma->ifma_addr = llsa;
5158 			llifma->ifma_ifp = ifp;
5159 			IFMA_LOCK(llifma);
5160 			if_attach_ifma(ifp, llifma, 0);
5161 			/* add extra refcnt for ifma */
5162 			IFMA_ADDREF_LOCKED(llifma);
5163 			IFMA_UNLOCK(llifma);
5164 			ifma->ifma_ll = llifma;
5165 		}
5166 	}
5167 
5168 	/* "anonymous" request should not result in network address */
5169 	VERIFY(!anon || ifma->ifma_ll == NULL);
5170 
5171 	ifma->ifma_addr = dupsa;
5172 	ifma->ifma_ifp = ifp;
5173 	IFMA_LOCK(ifma);
5174 	if_attach_ifma(ifp, ifma, anon);
5175 	IFMA_ADDREF_LOCKED(ifma);               /* for this routine */
5176 	if (retifma != NULL) {
5177 		*retifma = ifma;
5178 		IFMA_ADDREF_LOCKED(*retifma);   /* for caller */
5179 	}
5180 	lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
5181 	    ifma->ifma_addr->sa_family == AF_LINK);
5182 	IFMA_UNLOCK(ifma);
5183 	ifnet_lock_done(ifp);
5184 
5185 	rt_newmaddrmsg(RTM_NEWMADDR, ifma);
5186 	IFMA_REMREF(ifma);                      /* for this routine */
5187 
5188 	/*
5189 	 * We are certain we have added something, so call down to the
5190 	 * interface to let them know about it.  Do this only for newly-
5191 	 * added AF_LINK/AF_UNSPEC address in the if_multiaddrs set.
5192 	 * Note that the notification is deferred to avoid
5193 	 * locking reodering issues in certain paths.
5194 	 */
5195 	if (lladdr || ll_firstref) {
5196 		ifnet_ioctl_async(ifp, SIOCADDMULTI);
5197 	}
5198 
5199 	if (ifp->if_updatemcasts > 0) {
5200 		ifp->if_updatemcasts = 0;
5201 	}
5202 
5203 	return 0;
5204 
5205 cleanup:
5206 	if (ifma != NULL) {
5207 		ifma_free(ifma);
5208 	}
5209 	if (dupsa != NULL) {
5210 		kfree_data(dupsa, dupsa->sa_len);
5211 	}
5212 	if (llifma != NULL) {
5213 		ifma_free(llifma);
5214 	}
5215 	if (llsa != NULL) {
5216 		kfree_data(llsa, llsa->sa_len);
5217 	}
5218 
5219 	return error;
5220 }
5221 
5222 /*
5223  * Delete a multicast group membership by network-layer group address.
5224  * This routine is deprecated.
5225  */
5226 int
if_delmulti(struct ifnet * ifp,const struct sockaddr * sa)5227 if_delmulti(struct ifnet *ifp, const struct sockaddr *sa)
5228 {
5229 	return if_delmulti_common(NULL, ifp, sa, 0);
5230 }
5231 
5232 /*
5233  * Delete a multicast group membership by group membership pointer.
5234  * Network-layer protocol domains must use this routine.
5235  */
5236 int
if_delmulti_ifma(struct ifmultiaddr * ifma)5237 if_delmulti_ifma(struct ifmultiaddr *ifma)
5238 {
5239 	return if_delmulti_common(ifma, NULL, NULL, 0);
5240 }
5241 
5242 /*
5243  * Anything other than network-layer protocol domains which hold references
5244  * to the underlying link-layer record must use this routine: SIOCDELMULTI
5245  * ioctl, ifnet_remove_multicast(), if_bond.
5246  */
5247 int
if_delmulti_anon(struct ifnet * ifp,const struct sockaddr * sa)5248 if_delmulti_anon(struct ifnet *ifp, const struct sockaddr *sa)
5249 {
5250 	return if_delmulti_common(NULL, ifp, sa, 1);
5251 }
5252 
5253 /*
5254  * Delete a multicast group membership by network-layer group address.
5255  *
5256  * Returns ENOENT if the entry could not be found.
5257  */
5258 static int
if_delmulti_common(struct ifmultiaddr * ifma,struct ifnet * ifp,const struct sockaddr * sa,int anon)5259 if_delmulti_common(struct ifmultiaddr *ifma, struct ifnet *ifp,
5260     const struct sockaddr *sa, int anon)
5261 {
5262 	struct sockaddr         *dupsa = NULL;
5263 	int                     lastref, ll_lastref = 0, lladdr;
5264 	struct ifmultiaddr      *ll = NULL;
5265 
5266 	/* sanity check for callers */
5267 	VERIFY(ifma != NULL || (ifp != NULL && sa != NULL));
5268 
5269 	if (ifma != NULL) {
5270 		ifp = ifma->ifma_ifp;
5271 	}
5272 
5273 	if (sa != NULL &&
5274 	    (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC)) {
5275 		dupsa = copy_and_normalize(sa);
5276 		if (dupsa == NULL) {
5277 			return ENOMEM;
5278 		}
5279 		sa = dupsa;
5280 	}
5281 
5282 	ifnet_lock_exclusive(ifp);
5283 	if (ifma == NULL) {
5284 		for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
5285 		    ifma = LIST_NEXT(ifma, ifma_link)) {
5286 			IFMA_LOCK(ifma);
5287 			if (!sa_equal(sa, ifma->ifma_addr) ||
5288 			    (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS))) {
5289 				VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
5290 				    ifma->ifma_anoncnt != 0);
5291 				IFMA_UNLOCK(ifma);
5292 				continue;
5293 			}
5294 			/* found; keep it locked */
5295 			break;
5296 		}
5297 		if (ifma == NULL) {
5298 			if (dupsa != NULL) {
5299 				kfree_data(dupsa, dupsa->sa_len);
5300 			}
5301 			ifnet_lock_done(ifp);
5302 			return ENOENT;
5303 		}
5304 	} else {
5305 		IFMA_LOCK(ifma);
5306 	}
5307 	IFMA_LOCK_ASSERT_HELD(ifma);
5308 	IFMA_ADDREF_LOCKED(ifma);       /* for this routine */
5309 	lastref = if_detach_ifma(ifp, ifma, anon);
5310 	VERIFY(!lastref || (!(ifma->ifma_debug & IFD_ATTACHED) &&
5311 	    ifma->ifma_reqcnt == 0));
5312 	VERIFY(!anon || ifma->ifma_ll == NULL);
5313 	ll = ifma->ifma_ll;
5314 	lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
5315 	    ifma->ifma_addr->sa_family == AF_LINK);
5316 	IFMA_UNLOCK(ifma);
5317 	if (lastref && ll != NULL) {
5318 		IFMA_LOCK(ll);
5319 		ll_lastref = if_detach_ifma(ifp, ll, 0);
5320 		IFMA_UNLOCK(ll);
5321 	}
5322 	ifnet_lock_done(ifp);
5323 
5324 	if (lastref) {
5325 		rt_newmaddrmsg(RTM_DELMADDR, ifma);
5326 	}
5327 
5328 	if ((ll == NULL && lastref && lladdr) || ll_lastref) {
5329 		/*
5330 		 * Make sure the interface driver is notified in the
5331 		 * case of a link layer mcast group being left.  Do
5332 		 * this only for a AF_LINK/AF_UNSPEC address that has
5333 		 * been removed from the if_multiaddrs set.
5334 		 * Note that the notification is deferred to avoid
5335 		 * locking reodering issues in certain paths.
5336 		 */
5337 		ifnet_ioctl_async(ifp, SIOCDELMULTI);
5338 	}
5339 
5340 	if (lastref) {
5341 		IFMA_REMREF(ifma);      /* for if_multiaddrs list */
5342 	}
5343 	if (ll_lastref) {
5344 		IFMA_REMREF(ll);        /* for if_multiaddrs list */
5345 	}
5346 	IFMA_REMREF(ifma);              /* for this routine */
5347 	if (dupsa != NULL) {
5348 		kfree_data(dupsa, dupsa->sa_len);
5349 	}
5350 
5351 	return 0;
5352 }
5353 
5354 /*
5355  * Shutdown all network activity.  Used boot() when halting
5356  * system.
5357  */
5358 int
if_down_all(void)5359 if_down_all(void)
5360 {
5361 	struct ifnet **ifp;
5362 	u_int32_t       count;
5363 	u_int32_t       i;
5364 
5365 	if (ifnet_list_get_all(IFNET_FAMILY_ANY, &ifp, &count) == 0) {
5366 		for (i = 0; i < count; i++) {
5367 			if_down(ifp[i]);
5368 			dlil_proto_unplumb_all(ifp[i]);
5369 		}
5370 		ifnet_list_free(ifp);
5371 	}
5372 
5373 	return 0;
5374 }
5375 
5376 /*
5377  * Delete Routes for a Network Interface
5378  *
5379  * Called for each routing entry via the rnh->rnh_walktree() call above
5380  * to delete all route entries referencing a detaching network interface.
5381  *
5382  * Arguments:
5383  *	rn	pointer to node in the routing table
5384  *	arg	argument passed to rnh->rnh_walktree() - detaching interface
5385  *
5386  * Returns:
5387  *	0	successful
5388  *	errno	failed - reason indicated
5389  *
5390  */
5391 static int
if_rtdel(struct radix_node * rn,void * arg)5392 if_rtdel(struct radix_node *rn, void *arg)
5393 {
5394 	struct rtentry  *rt = (struct rtentry *)rn;
5395 	struct ifnet    *ifp = arg;
5396 	int             err;
5397 
5398 	if (rt == NULL) {
5399 		return 0;
5400 	}
5401 	/*
5402 	 * Checking against RTF_UP protects against walktree
5403 	 * recursion problems with cloned routes.
5404 	 */
5405 	RT_LOCK(rt);
5406 	if (rt->rt_ifp == ifp && (rt->rt_flags & RTF_UP)) {
5407 		/*
5408 		 * Safe to drop rt_lock and use rt_key, rt_gateway,
5409 		 * since holding rnh_lock here prevents another thread
5410 		 * from calling rt_setgate() on this route.
5411 		 */
5412 		RT_UNLOCK(rt);
5413 		err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
5414 		    rt_mask(rt), rt->rt_flags, NULL);
5415 		if (err) {
5416 			log(LOG_WARNING, "if_rtdel: error %d\n", err);
5417 		}
5418 	} else {
5419 		RT_UNLOCK(rt);
5420 	}
5421 	return 0;
5422 }
5423 
5424 /*
5425  * Removes routing table reference to a given interface
5426  * for a given protocol family
5427  */
5428 void
if_rtproto_del(struct ifnet * ifp,int protocol)5429 if_rtproto_del(struct ifnet *ifp, int protocol)
5430 {
5431 	struct radix_node_head  *rnh;
5432 
5433 	if ((protocol <= AF_MAX) && (protocol >= 0) &&
5434 	    ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL)) {
5435 		lck_mtx_lock(rnh_lock);
5436 		(void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
5437 		lck_mtx_unlock(rnh_lock);
5438 	}
5439 }
5440 
5441 static int
if_rtmtu(struct radix_node * rn,void * arg)5442 if_rtmtu(struct radix_node *rn, void *arg)
5443 {
5444 	struct rtentry *rt = (struct rtentry *)rn;
5445 	struct ifnet *ifp = arg;
5446 
5447 	RT_LOCK(rt);
5448 	if (rt->rt_ifp == ifp) {
5449 		/*
5450 		 * Update the MTU of this entry only if the MTU
5451 		 * has not been locked (RTV_MTU is not set) and
5452 		 * if it was non-zero to begin with.
5453 		 */
5454 		if (!(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_rmx.rmx_mtu) {
5455 			rt->rt_rmx.rmx_mtu = ifp->if_mtu;
5456 			if (rt_key(rt)->sa_family == AF_INET &&
5457 			    INTF_ADJUST_MTU_FOR_CLAT46(ifp)) {
5458 				rt->rt_rmx.rmx_mtu = IN6_LINKMTU(ifp);
5459 				/* Further adjust the size for CLAT46 expansion */
5460 				rt->rt_rmx.rmx_mtu -= CLAT46_HDR_EXPANSION_OVERHD;
5461 			}
5462 		}
5463 	}
5464 	RT_UNLOCK(rt);
5465 
5466 	return 0;
5467 }
5468 
5469 /*
5470  * Update the MTU metric of all route entries in all protocol tables
5471  * associated with a particular interface; this is called when the
5472  * MTU of that interface has changed.
5473  */
5474 static void
if_rtmtu_update(struct ifnet * ifp)5475 if_rtmtu_update(struct ifnet *ifp)
5476 {
5477 	struct radix_node_head *rnh;
5478 	int p;
5479 
5480 	for (p = 0; p < AF_MAX + 1; p++) {
5481 		if ((rnh = rt_tables[p]) == NULL) {
5482 			continue;
5483 		}
5484 
5485 		lck_mtx_lock(rnh_lock);
5486 		(void) rnh->rnh_walktree(rnh, if_rtmtu, ifp);
5487 		lck_mtx_unlock(rnh_lock);
5488 	}
5489 	routegenid_update();
5490 }
5491 
5492 __private_extern__ void
if_data_internal_to_if_data(struct ifnet * ifp,const struct if_data_internal * if_data_int,struct if_data * if_data)5493 if_data_internal_to_if_data(struct ifnet *ifp,
5494     const struct if_data_internal *if_data_int, struct if_data *if_data)
5495 {
5496 #pragma unused(ifp)
5497 #define COPYFIELD(fld)          if_data->fld = if_data_int->fld
5498 #define COPYFIELD32(fld)        if_data->fld = (u_int32_t)(if_data_int->fld)
5499 /* compiler will cast down to 32-bit */
5500 #define COPYFIELD32_ATOMIC(fld) do {                                    \
5501 	u_int64_t _val = 0;                                             \
5502 	atomic_get_64(_val,                                             \
5503 	        (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld);     \
5504 	if_data->fld = (uint32_t) _val;                                 \
5505 } while (0)
5506 
5507 	COPYFIELD(ifi_type);
5508 	COPYFIELD(ifi_typelen);
5509 	COPYFIELD(ifi_physical);
5510 	COPYFIELD(ifi_addrlen);
5511 	COPYFIELD(ifi_hdrlen);
5512 	COPYFIELD(ifi_recvquota);
5513 	COPYFIELD(ifi_xmitquota);
5514 	if_data->ifi_unused1 = 0;
5515 	COPYFIELD(ifi_mtu);
5516 	COPYFIELD(ifi_metric);
5517 	if (if_data_int->ifi_baudrate & 0xFFFFFFFF00000000LL) {
5518 		if_data->ifi_baudrate = 0xFFFFFFFF;
5519 	} else {
5520 		COPYFIELD32(ifi_baudrate);
5521 	}
5522 
5523 	COPYFIELD32_ATOMIC(ifi_ipackets);
5524 	COPYFIELD32_ATOMIC(ifi_ierrors);
5525 	COPYFIELD32_ATOMIC(ifi_opackets);
5526 	COPYFIELD32_ATOMIC(ifi_oerrors);
5527 	COPYFIELD32_ATOMIC(ifi_collisions);
5528 	COPYFIELD32_ATOMIC(ifi_ibytes);
5529 	COPYFIELD32_ATOMIC(ifi_obytes);
5530 	COPYFIELD32_ATOMIC(ifi_imcasts);
5531 	COPYFIELD32_ATOMIC(ifi_omcasts);
5532 	COPYFIELD32_ATOMIC(ifi_iqdrops);
5533 	COPYFIELD32_ATOMIC(ifi_noproto);
5534 
5535 	COPYFIELD(ifi_recvtiming);
5536 	COPYFIELD(ifi_xmittiming);
5537 
5538 	if_data->ifi_lastchange.tv_sec = (uint32_t)if_data_int->ifi_lastchange.tv_sec;
5539 	if_data->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
5540 
5541 	if_data->ifi_lastchange.tv_sec += (uint32_t)boottime_sec();
5542 
5543 	if_data->ifi_unused2 = 0;
5544 	COPYFIELD(ifi_hwassist);
5545 	if_data->ifi_reserved1 = 0;
5546 	if_data->ifi_reserved2 = 0;
5547 #undef COPYFIELD32_ATOMIC
5548 #undef COPYFIELD32
5549 #undef COPYFIELD
5550 }
5551 
5552 __private_extern__ void
if_data_internal_to_if_data64(struct ifnet * ifp,const struct if_data_internal * if_data_int,struct if_data64 * if_data64)5553 if_data_internal_to_if_data64(struct ifnet *ifp,
5554     const struct if_data_internal *if_data_int,
5555     struct if_data64 *if_data64)
5556 {
5557 #pragma unused(ifp)
5558 #define COPYFIELD64(fld)        if_data64->fld = if_data_int->fld
5559 #define COPYFIELD64_ATOMIC(fld) do {                                    \
5560 	atomic_get_64(if_data64->fld,                                   \
5561 	    (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld);         \
5562 } while (0)
5563 
5564 	COPYFIELD64(ifi_type);
5565 	COPYFIELD64(ifi_typelen);
5566 	COPYFIELD64(ifi_physical);
5567 	COPYFIELD64(ifi_addrlen);
5568 	COPYFIELD64(ifi_hdrlen);
5569 	COPYFIELD64(ifi_recvquota);
5570 	COPYFIELD64(ifi_xmitquota);
5571 	if_data64->ifi_unused1 = 0;
5572 	COPYFIELD64(ifi_mtu);
5573 	COPYFIELD64(ifi_metric);
5574 	COPYFIELD64(ifi_baudrate);
5575 
5576 	COPYFIELD64_ATOMIC(ifi_ipackets);
5577 	COPYFIELD64_ATOMIC(ifi_ierrors);
5578 	COPYFIELD64_ATOMIC(ifi_opackets);
5579 	COPYFIELD64_ATOMIC(ifi_oerrors);
5580 	COPYFIELD64_ATOMIC(ifi_collisions);
5581 	COPYFIELD64_ATOMIC(ifi_ibytes);
5582 	COPYFIELD64_ATOMIC(ifi_obytes);
5583 	COPYFIELD64_ATOMIC(ifi_imcasts);
5584 	COPYFIELD64_ATOMIC(ifi_omcasts);
5585 	COPYFIELD64_ATOMIC(ifi_iqdrops);
5586 	COPYFIELD64_ATOMIC(ifi_noproto);
5587 
5588 	/*
5589 	 * Note these two fields are actually 32 bit, so doing
5590 	 * COPYFIELD64_ATOMIC will cause them to be misaligned
5591 	 */
5592 	COPYFIELD64(ifi_recvtiming);
5593 	COPYFIELD64(ifi_xmittiming);
5594 
5595 	if_data64->ifi_lastchange.tv_sec = (uint32_t)if_data_int->ifi_lastchange.tv_sec;
5596 	if_data64->ifi_lastchange.tv_usec = (uint32_t)if_data_int->ifi_lastchange.tv_usec;
5597 
5598 	if_data64->ifi_lastchange.tv_sec += (uint32_t)boottime_sec();
5599 
5600 #undef COPYFIELD64
5601 }
5602 
5603 __private_extern__ void
if_copy_traffic_class(struct ifnet * ifp,struct if_traffic_class * if_tc)5604 if_copy_traffic_class(struct ifnet *ifp,
5605     struct if_traffic_class *if_tc)
5606 {
5607 #define COPY_IF_TC_FIELD64_ATOMIC(fld) do {                     \
5608 	atomic_get_64(if_tc->fld,                               \
5609 	    (u_int64_t *)(void *)(uintptr_t)&ifp->if_tc.fld);   \
5610 } while (0)
5611 
5612 	bzero(if_tc, sizeof(*if_tc));
5613 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ibepackets);
5614 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ibebytes);
5615 	COPY_IF_TC_FIELD64_ATOMIC(ifi_obepackets);
5616 	COPY_IF_TC_FIELD64_ATOMIC(ifi_obebytes);
5617 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkpackets);
5618 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkbytes);
5619 	COPY_IF_TC_FIELD64_ATOMIC(ifi_obkpackets);
5620 	COPY_IF_TC_FIELD64_ATOMIC(ifi_obkbytes);
5621 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ivipackets);
5622 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ivibytes);
5623 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ovipackets);
5624 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ovibytes);
5625 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ivopackets);
5626 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ivobytes);
5627 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ovopackets);
5628 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ovobytes);
5629 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ipvpackets);
5630 	COPY_IF_TC_FIELD64_ATOMIC(ifi_ipvbytes);
5631 	COPY_IF_TC_FIELD64_ATOMIC(ifi_opvpackets);
5632 	COPY_IF_TC_FIELD64_ATOMIC(ifi_opvbytes);
5633 
5634 #undef COPY_IF_TC_FIELD64_ATOMIC
5635 }
5636 
5637 void
if_copy_data_extended(struct ifnet * ifp,struct if_data_extended * if_de)5638 if_copy_data_extended(struct ifnet *ifp, struct if_data_extended *if_de)
5639 {
5640 #define COPY_IF_DE_FIELD64_ATOMIC(fld) do {                     \
5641 	atomic_get_64(if_de->fld,                               \
5642 	    (u_int64_t *)(void *)(uintptr_t)&ifp->if_data.fld); \
5643 } while (0)
5644 
5645 	bzero(if_de, sizeof(*if_de));
5646 	COPY_IF_DE_FIELD64_ATOMIC(ifi_alignerrs);
5647 	COPY_IF_DE_FIELD64_ATOMIC(ifi_dt_bytes);
5648 	COPY_IF_DE_FIELD64_ATOMIC(ifi_fpackets);
5649 	COPY_IF_DE_FIELD64_ATOMIC(ifi_fbytes);
5650 
5651 #undef COPY_IF_DE_FIELD64_ATOMIC
5652 }
5653 
5654 void
if_copy_packet_stats(struct ifnet * ifp,struct if_packet_stats * if_ps)5655 if_copy_packet_stats(struct ifnet *ifp, struct if_packet_stats *if_ps)
5656 {
5657 #define COPY_IF_PS_TCP_FIELD64_ATOMIC(fld) do {                         \
5658 	atomic_get_64(if_ps->ifi_tcp_##fld,                             \
5659 	    (u_int64_t *)(void *)(uintptr_t)&ifp->if_tcp_stat->fld);    \
5660 } while (0)
5661 
5662 #define COPY_IF_PS_UDP_FIELD64_ATOMIC(fld) do {                         \
5663 	atomic_get_64(if_ps->ifi_udp_##fld,                             \
5664 	    (u_int64_t *)(void *)(uintptr_t)&ifp->if_udp_stat->fld);    \
5665 } while (0)
5666 
5667 	COPY_IF_PS_TCP_FIELD64_ATOMIC(badformat);
5668 	COPY_IF_PS_TCP_FIELD64_ATOMIC(unspecv6);
5669 	COPY_IF_PS_TCP_FIELD64_ATOMIC(synfin);
5670 	COPY_IF_PS_TCP_FIELD64_ATOMIC(badformatipsec);
5671 	COPY_IF_PS_TCP_FIELD64_ATOMIC(noconnnolist);
5672 	COPY_IF_PS_TCP_FIELD64_ATOMIC(noconnlist);
5673 	COPY_IF_PS_TCP_FIELD64_ATOMIC(listbadsyn);
5674 	COPY_IF_PS_TCP_FIELD64_ATOMIC(icmp6unreach);
5675 	COPY_IF_PS_TCP_FIELD64_ATOMIC(deprecate6);
5676 	COPY_IF_PS_TCP_FIELD64_ATOMIC(ooopacket);
5677 	COPY_IF_PS_TCP_FIELD64_ATOMIC(rstinsynrcv);
5678 	COPY_IF_PS_TCP_FIELD64_ATOMIC(dospacket);
5679 	COPY_IF_PS_TCP_FIELD64_ATOMIC(cleanup);
5680 	COPY_IF_PS_TCP_FIELD64_ATOMIC(synwindow);
5681 
5682 	COPY_IF_PS_UDP_FIELD64_ATOMIC(port_unreach);
5683 	COPY_IF_PS_UDP_FIELD64_ATOMIC(faithprefix);
5684 	COPY_IF_PS_UDP_FIELD64_ATOMIC(port0);
5685 	COPY_IF_PS_UDP_FIELD64_ATOMIC(badlength);
5686 	COPY_IF_PS_UDP_FIELD64_ATOMIC(badchksum);
5687 	COPY_IF_PS_UDP_FIELD64_ATOMIC(badmcast);
5688 	COPY_IF_PS_UDP_FIELD64_ATOMIC(cleanup);
5689 	COPY_IF_PS_UDP_FIELD64_ATOMIC(badipsec);
5690 
5691 #undef COPY_IF_PS_TCP_FIELD64_ATOMIC
5692 #undef COPY_IF_PS_UDP_FIELD64_ATOMIC
5693 }
5694 
5695 void
if_copy_rxpoll_stats(struct ifnet * ifp,struct if_rxpoll_stats * if_rs)5696 if_copy_rxpoll_stats(struct ifnet *ifp, struct if_rxpoll_stats *if_rs)
5697 {
5698 	bzero(if_rs, sizeof(*if_rs));
5699 	if (!(ifp->if_eflags & IFEF_RXPOLL) || !ifnet_is_attached(ifp, 1)) {
5700 		return;
5701 	}
5702 	bcopy(&ifp->if_poll_pstats, if_rs, sizeof(*if_rs));
5703 	/* Release the IO refcnt */
5704 	ifnet_decr_iorefcnt(ifp);
5705 }
5706 
5707 void
if_copy_netif_stats(struct ifnet * ifp,struct if_netif_stats * if_ns)5708 if_copy_netif_stats(struct ifnet *ifp, struct if_netif_stats *if_ns)
5709 {
5710 	bzero(if_ns, sizeof(*if_ns));
5711 #if SKYWALK
5712 	if (!(ifp->if_capabilities & IFCAP_SKYWALK) ||
5713 	    !ifnet_is_attached(ifp, 1)) {
5714 		return;
5715 	}
5716 
5717 	if (ifp->if_na != NULL) {
5718 		nx_netif_copy_stats(ifp->if_na, if_ns);
5719 	}
5720 
5721 	/* Release the IO refcnt */
5722 	ifnet_decr_iorefcnt(ifp);
5723 #else /* SKYWALK */
5724 #pragma unused(ifp)
5725 #endif /* SKYWALK */
5726 }
5727 
5728 struct ifaddr *
ifa_remref(struct ifaddr * ifa,int locked)5729 ifa_remref(struct ifaddr *ifa, int locked)
5730 {
5731 	if (!locked) {
5732 		IFA_LOCK_SPIN(ifa);
5733 	} else {
5734 		IFA_LOCK_ASSERT_HELD(ifa);
5735 	}
5736 
5737 	if (ifa->ifa_refcnt == 0) {
5738 		panic("%s: ifa %p negative refcnt", __func__, ifa);
5739 	} else if (ifa->ifa_trace != NULL) {
5740 		(*ifa->ifa_trace)(ifa, FALSE);
5741 	}
5742 	if (--ifa->ifa_refcnt == 0) {
5743 		if (ifa->ifa_debug & IFD_ATTACHED) {
5744 			panic("ifa %p attached to ifp is being freed", ifa);
5745 		}
5746 		/*
5747 		 * Some interface addresses are allocated either statically
5748 		 * or carved out of a larger block.  Only free it if it was
5749 		 * allocated via MALLOC or via the corresponding per-address
5750 		 * family allocator.  Otherwise, leave it alone.
5751 		 */
5752 		if (ifa->ifa_debug & IFD_ALLOC) {
5753 #if XNU_PLATFORM_MacOSX
5754 			if (ifa->ifa_free == NULL) {
5755 				IFA_UNLOCK(ifa);
5756 				/*
5757 				 * support for 3rd party kexts,
5758 				 * old ABI was that this had to be allocated
5759 				 * with MALLOC(M_IFADDR).
5760 				 */
5761 				__typed_allocators_ignore(kheap_free_addr(KHEAP_DEFAULT, ifa));
5762 			} else
5763 #endif /* XNU_PLATFORM_MacOSX */
5764 			{
5765 				/* Become a regular mutex */
5766 				IFA_CONVERT_LOCK(ifa);
5767 				/* callee will unlock */
5768 				(*ifa->ifa_free)(ifa);
5769 			}
5770 		} else {
5771 			IFA_UNLOCK(ifa);
5772 		}
5773 		ifa = NULL;
5774 	}
5775 
5776 	if (!locked && ifa != NULL) {
5777 		IFA_UNLOCK(ifa);
5778 	}
5779 
5780 	return ifa;
5781 }
5782 
5783 void
ifa_addref(struct ifaddr * ifa,int locked)5784 ifa_addref(struct ifaddr *ifa, int locked)
5785 {
5786 	if (!locked) {
5787 		IFA_LOCK_SPIN(ifa);
5788 	} else {
5789 		IFA_LOCK_ASSERT_HELD(ifa);
5790 	}
5791 
5792 	if (++ifa->ifa_refcnt == 0) {
5793 		panic("%s: ifa %p wraparound refcnt", __func__, ifa);
5794 		/* NOTREACHED */
5795 	} else if (ifa->ifa_trace != NULL) {
5796 		(*ifa->ifa_trace)(ifa, TRUE);
5797 	}
5798 	if (!locked) {
5799 		IFA_UNLOCK(ifa);
5800 	}
5801 }
5802 
5803 void
ifa_lock_init(struct ifaddr * ifa)5804 ifa_lock_init(struct ifaddr *ifa)
5805 {
5806 	lck_mtx_init(&ifa->ifa_lock, &ifa_mtx_grp, &ifa_mtx_attr);
5807 }
5808 
5809 void
ifa_lock_destroy(struct ifaddr * ifa)5810 ifa_lock_destroy(struct ifaddr *ifa)
5811 {
5812 	IFA_LOCK_ASSERT_NOTHELD(ifa);
5813 	lck_mtx_destroy(&ifa->ifa_lock, &ifa_mtx_grp);
5814 }
5815 
5816 /*
5817  * 'i' group ioctls.
5818  *
5819  * The switch statement below does nothing at runtime, as it serves as a
5820  * compile time check to ensure that all of the socket 'i' ioctls (those
5821  * in the 'i' group going thru soo_ioctl) that are made available by the
5822  * networking stack is unique.  This works as long as this routine gets
5823  * updated each time a new interface ioctl gets added.
5824  *
5825  * Any failures at compile time indicates duplicated ioctl values.
5826  */
5827 static __attribute__((unused)) void
ifioctl_cassert(void)5828 ifioctl_cassert(void)
5829 {
5830 	/*
5831 	 * This is equivalent to _CASSERT() and the compiler wouldn't
5832 	 * generate any instructions, thus for compile time only.
5833 	 */
5834 	switch ((u_long)0) {
5835 	case 0:
5836 
5837 	/* bsd/net/if_ppp.h */
5838 	case SIOCGPPPSTATS:
5839 	case SIOCGPPPCSTATS:
5840 
5841 	/* bsd/netinet6/in6_var.h */
5842 	case SIOCSIFADDR_IN6:
5843 	case SIOCGIFADDR_IN6:
5844 	case SIOCSIFDSTADDR_IN6:
5845 	case SIOCSIFNETMASK_IN6:
5846 	case SIOCGIFDSTADDR_IN6:
5847 	case SIOCGIFNETMASK_IN6:
5848 	case SIOCDIFADDR_IN6:
5849 	case SIOCAIFADDR_IN6_32:
5850 	case SIOCAIFADDR_IN6_64:
5851 	case SIOCSIFPHYADDR_IN6_32:
5852 	case SIOCSIFPHYADDR_IN6_64:
5853 	case SIOCGIFPSRCADDR_IN6:
5854 	case SIOCGIFPDSTADDR_IN6:
5855 	case SIOCGIFAFLAG_IN6:
5856 	case SIOCGDRLST_IN6_32:
5857 	case SIOCGDRLST_IN6_64:
5858 	case SIOCGPRLST_IN6_32:
5859 	case SIOCGPRLST_IN6_64:
5860 	case OSIOCGIFINFO_IN6:
5861 	case SIOCGIFINFO_IN6:
5862 	case SIOCSNDFLUSH_IN6:
5863 	case SIOCGNBRINFO_IN6_32:
5864 	case SIOCGNBRINFO_IN6_64:
5865 	case SIOCSPFXFLUSH_IN6:
5866 	case SIOCSRTRFLUSH_IN6:
5867 	case SIOCGIFALIFETIME_IN6:
5868 	case SIOCSIFALIFETIME_IN6:
5869 	case SIOCGIFSTAT_IN6:
5870 	case SIOCGIFSTAT_ICMP6:
5871 	case SIOCSDEFIFACE_IN6_32:
5872 	case SIOCSDEFIFACE_IN6_64:
5873 	case SIOCGDEFIFACE_IN6_32:
5874 	case SIOCGDEFIFACE_IN6_64:
5875 	case SIOCSIFINFO_FLAGS:
5876 	case SIOCSSCOPE6:
5877 	case SIOCGSCOPE6:
5878 	case SIOCGSCOPE6DEF:
5879 	case SIOCSIFPREFIX_IN6:
5880 	case SIOCGIFPREFIX_IN6:
5881 	case SIOCDIFPREFIX_IN6:
5882 	case SIOCAIFPREFIX_IN6:
5883 	case SIOCCIFPREFIX_IN6:
5884 	case SIOCSGIFPREFIX_IN6:
5885 	case SIOCPROTOATTACH_IN6_32:
5886 	case SIOCPROTOATTACH_IN6_64:
5887 	case SIOCPROTODETACH_IN6:
5888 	case SIOCLL_START_32:
5889 	case SIOCLL_START_64:
5890 	case SIOCLL_STOP:
5891 	case SIOCAUTOCONF_START:
5892 	case SIOCAUTOCONF_STOP:
5893 	case SIOCSETROUTERMODE_IN6:
5894 	case SIOCGETROUTERMODE_IN6:
5895 	case SIOCLL_CGASTART_32:
5896 	case SIOCLL_CGASTART_64:
5897 	case SIOCGIFCGAPREP_IN6:
5898 	case SIOCSIFCGAPREP_IN6:
5899 
5900 	/* bsd/sys/sockio.h */
5901 	case SIOCSIFADDR:
5902 	case OSIOCGIFADDR:
5903 	case SIOCSIFDSTADDR:
5904 	case OSIOCGIFDSTADDR:
5905 	case SIOCSIFFLAGS:
5906 	case SIOCGIFFLAGS:
5907 	case OSIOCGIFBRDADDR:
5908 	case SIOCSIFBRDADDR:
5909 	case OSIOCGIFCONF32:
5910 	case OSIOCGIFCONF64:
5911 	case OSIOCGIFNETMASK:
5912 	case SIOCSIFNETMASK:
5913 	case SIOCGIFMETRIC:
5914 	case SIOCSIFMETRIC:
5915 	case SIOCDIFADDR:
5916 	case SIOCAIFADDR:
5917 
5918 	case SIOCGIFADDR:
5919 	case SIOCGIFDSTADDR:
5920 	case SIOCGIFBRDADDR:
5921 	case SIOCGIFCONF32:
5922 	case SIOCGIFCONF64:
5923 	case SIOCGIFNETMASK:
5924 	case SIOCAUTOADDR:
5925 	case SIOCAUTONETMASK:
5926 	case SIOCARPIPLL:
5927 
5928 	case SIOCADDMULTI:
5929 	case SIOCDELMULTI:
5930 	case SIOCGIFMTU:
5931 	case SIOCSIFMTU:
5932 	case SIOCGIFPHYS:
5933 	case SIOCSIFPHYS:
5934 	case SIOCSIFMEDIA:
5935 	case SIOCGIFMEDIA32:
5936 	case SIOCGIFMEDIA64:
5937 	case SIOCGIFXMEDIA32:
5938 	case SIOCGIFXMEDIA64:
5939 	case SIOCSIFGENERIC:
5940 	case SIOCGIFGENERIC:
5941 	case SIOCRSLVMULTI:
5942 
5943 	case SIOCSIFLLADDR:
5944 	case SIOCGIFSTATUS:
5945 	case SIOCSIFPHYADDR:
5946 	case SIOCGIFPSRCADDR:
5947 	case SIOCGIFPDSTADDR:
5948 	case SIOCDIFPHYADDR:
5949 
5950 	case SIOCGIFDEVMTU:
5951 	case SIOCSIFALTMTU:
5952 	case SIOCGIFALTMTU:
5953 	case SIOCSIFBOND:
5954 	case SIOCGIFBOND:
5955 
5956 	case SIOCPROTOATTACH:
5957 	case SIOCPROTODETACH:
5958 
5959 	case SIOCSIFCAP:
5960 	case SIOCGIFCAP:
5961 
5962 	case SIOCIFCREATE:
5963 	case SIOCIFDESTROY:
5964 	case SIOCIFCREATE2:
5965 
5966 	case SIOCSDRVSPEC32:
5967 	case SIOCGDRVSPEC32:
5968 	case SIOCSDRVSPEC64:
5969 	case SIOCGDRVSPEC64:
5970 
5971 	case SIOCSIFVLAN:
5972 	case SIOCGIFVLAN:
5973 
5974 	case SIOCIFGCLONERS32:
5975 	case SIOCIFGCLONERS64:
5976 
5977 	case SIOCGIFASYNCMAP:
5978 	case SIOCSIFASYNCMAP:
5979 	case SIOCSIFKPI:
5980 	case SIOCGIFKPI:
5981 
5982 	case SIOCGIFWAKEFLAGS:
5983 
5984 	case SIOCGIFGETRTREFCNT:
5985 	case SIOCGIFLINKQUALITYMETRIC:
5986 	case SIOCSIFLINKQUALITYMETRIC:
5987 	case SIOCSIFOPPORTUNISTIC:
5988 	case SIOCGIFOPPORTUNISTIC:
5989 	case SIOCGETROUTERMODE:
5990 	case SIOCSETROUTERMODE:
5991 	case SIOCGIFEFLAGS:
5992 	case SIOCSIFDESC:
5993 	case SIOCGIFDESC:
5994 	case SIOCSIFLINKPARAMS:
5995 	case SIOCGIFLINKPARAMS:
5996 	case SIOCGIFQUEUESTATS:
5997 	case SIOCSIFTHROTTLE:
5998 	case SIOCGIFTHROTTLE:
5999 
6000 	case SIOCGASSOCIDS32:
6001 	case SIOCGASSOCIDS64:
6002 	case SIOCGCONNIDS32:
6003 	case SIOCGCONNIDS64:
6004 	case SIOCGCONNINFO32:
6005 	case SIOCGCONNINFO64:
6006 	case SIOCSCONNORDER:
6007 	case SIOCGCONNORDER:
6008 
6009 	case SIOCSIFLOG:
6010 	case SIOCGIFLOG:
6011 	case SIOCGIFDELEGATE:
6012 	case SIOCGIFLLADDR:
6013 	case SIOCGIFTYPE:
6014 	case SIOCGIFEXPENSIVE:
6015 	case SIOCSIFEXPENSIVE:
6016 	case SIOCGIF2KCL:
6017 	case SIOCSIF2KCL:
6018 	case SIOCGSTARTDELAY:
6019 
6020 	case SIOCAIFAGENTID:
6021 	case SIOCDIFAGENTID:
6022 	case SIOCGIFAGENTIDS32:
6023 	case SIOCGIFAGENTIDS64:
6024 	case SIOCGIFAGENTDATA32:
6025 	case SIOCGIFAGENTDATA64:
6026 
6027 	case SIOCSIFINTERFACESTATE:
6028 	case SIOCGIFINTERFACESTATE:
6029 	case SIOCSIFPROBECONNECTIVITY:
6030 	case SIOCGIFPROBECONNECTIVITY:
6031 
6032 	case SIOCGIFFUNCTIONALTYPE:
6033 	case SIOCSIFNETSIGNATURE:
6034 	case SIOCGIFNETSIGNATURE:
6035 
6036 	case SIOCSIFNETWORKID:
6037 	case SIOCGECNMODE:
6038 	case SIOCSECNMODE:
6039 
6040 	case SIOCSIFORDER:
6041 	case SIOCGIFORDER:
6042 
6043 	case SIOCSQOSMARKINGMODE:
6044 	case SIOCSQOSMARKINGENABLED:
6045 	case SIOCGQOSMARKINGMODE:
6046 	case SIOCGQOSMARKINGENABLED:
6047 
6048 	case SIOCSIFTIMESTAMPENABLE:
6049 	case SIOCSIFTIMESTAMPDISABLE:
6050 	case SIOCGIFTIMESTAMPENABLED:
6051 
6052 	case SIOCSIFDISABLEOUTPUT:
6053 
6054 	case SIOCSIFSUBFAMILY:
6055 
6056 	case SIOCGIFAGENTLIST32:
6057 	case SIOCGIFAGENTLIST64:
6058 
6059 	case SIOCSIFLOWINTERNET:
6060 	case SIOCGIFLOWINTERNET:
6061 
6062 	case SIOCGIFNAT64PREFIX:
6063 	case SIOCSIFNAT64PREFIX:
6064 
6065 	case SIOCGIFCLAT46ADDR:
6066 #if SKYWALK
6067 	case SIOCGIFNEXUS:
6068 #endif /* SKYWALK */
6069 
6070 	case SIOCGIFPROTOLIST32:
6071 	case SIOCGIFPROTOLIST64:
6072 
6073 	case SIOCGIFLOWPOWER:
6074 	case SIOCSIFLOWPOWER:
6075 
6076 	case SIOCGIFMPKLOG:
6077 	case SIOCSIFMPKLOG:
6078 
6079 	case SIOCGIFCONSTRAINED:
6080 	case SIOCSIFCONSTRAINED:
6081 
6082 	case SIOCGIFXFLAGS:
6083 
6084 	case SIOCGIFNOACKPRIO:
6085 	case SIOCSIFNOACKPRIO:
6086 
6087 	case SIOCSIFMARKWAKEPKT:
6088 
6089 	case SIOCSIFNOTRAFFICSHAPING:
6090 	case SIOCGIFNOTRAFFICSHAPING:
6091 		;
6092 	}
6093 }
6094 
6095 #if SKYWALK
6096 /*
6097  * XXX: This API is only used by BSD stack and for now will always return 0.
6098  * For Skywalk native drivers, preamble space need not be allocated in mbuf
6099  * as the preamble will be reserved in the translated skywalk packet
6100  * which is transmitted to the driver.
6101  * For Skywalk compat drivers currently headroom is always set to zero.
6102  */
6103 #endif /* SKYWALK */
6104 uint32_t
ifnet_mbuf_packetpreamblelen(struct ifnet * ifp)6105 ifnet_mbuf_packetpreamblelen(struct ifnet *ifp)
6106 {
6107 #pragma unused(ifp)
6108 	return 0;
6109 }
6110 
6111 /* The following is used to enqueue work items for interface events */
6112 struct intf_event {
6113 	struct ifnet *ifp;
6114 	union sockaddr_in_4_6 addr;
6115 	uint32_t intf_event_code;
6116 };
6117 
6118 struct intf_event_nwk_wq_entry {
6119 	struct nwk_wq_entry nwk_wqe;
6120 	struct intf_event intf_ev_arg;
6121 };
6122 
6123 static void
intf_event_callback(struct nwk_wq_entry * nwk_item)6124 intf_event_callback(struct nwk_wq_entry *nwk_item)
6125 {
6126 	struct intf_event_nwk_wq_entry *p_ev;
6127 
6128 	p_ev = __container_of(nwk_item, struct intf_event_nwk_wq_entry, nwk_wqe);
6129 
6130 	/* Call this before we walk the tree */
6131 	EVENTHANDLER_INVOKE(&ifnet_evhdlr_ctxt, ifnet_event,
6132 	    p_ev->intf_ev_arg.ifp,
6133 	    (struct sockaddr *)&(p_ev->intf_ev_arg.addr),
6134 	    p_ev->intf_ev_arg.intf_event_code);
6135 
6136 	kfree_type(struct intf_event_nwk_wq_entry, p_ev);
6137 }
6138 
6139 void
intf_event_enqueue_nwk_wq_entry(struct ifnet * ifp,struct sockaddr * addrp,uint32_t intf_event_code)6140 intf_event_enqueue_nwk_wq_entry(struct ifnet *ifp, struct sockaddr *addrp,
6141     uint32_t intf_event_code)
6142 {
6143 #pragma unused(addrp)
6144 	struct intf_event_nwk_wq_entry *p_intf_ev = NULL;
6145 
6146 	p_intf_ev = kalloc_type(struct intf_event_nwk_wq_entry,
6147 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
6148 
6149 	p_intf_ev->intf_ev_arg.ifp = ifp;
6150 	/*
6151 	 * XXX Not using addr in the arg. This will be used
6152 	 * once we need IP address add/delete events
6153 	 */
6154 	p_intf_ev->intf_ev_arg.intf_event_code = intf_event_code;
6155 	p_intf_ev->nwk_wqe.func = intf_event_callback;
6156 	nwk_wq_enqueue(&p_intf_ev->nwk_wqe);
6157 }
6158 
6159 int
if_get_tcp_kao_max(struct ifnet * ifp)6160 if_get_tcp_kao_max(struct ifnet *ifp)
6161 {
6162 	int error = 0;
6163 
6164 	if (ifp->if_tcp_kao_max == 0) {
6165 		struct ifreq ifr;
6166 
6167 		memset(&ifr, 0, sizeof(struct ifreq));
6168 		error = ifnet_ioctl(ifp, 0, SIOCGIFTCPKAOMAX, &ifr);
6169 
6170 		ifnet_lock_exclusive(ifp);
6171 		if (error == 0) {
6172 			ifp->if_tcp_kao_max = ifr.ifr_tcp_kao_max;
6173 		} else if (error == EOPNOTSUPP) {
6174 			ifp->if_tcp_kao_max = default_tcp_kao_max;
6175 		}
6176 		ifnet_lock_done(ifp);
6177 	}
6178 	return error;
6179 }
6180