xref: /xnu-10002.81.5/bsd/net/kpi_interface.c (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /*
2  * Copyright (c) 2004-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 #include "kpi_interface.h"
30 
31 #include <sys/queue.h>
32 #include <sys/param.h>  /* for definition of NULL */
33 #include <kern/debug.h> /* for panic */
34 #include <sys/errno.h>
35 #include <sys/socket.h>
36 #include <sys/kern_event.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/kpi_mbuf.h>
40 #include <sys/mcache.h>
41 #include <sys/protosw.h>
42 #include <sys/syslog.h>
43 #include <net/if_var.h>
44 #include <net/if_dl.h>
45 #include <net/dlil.h>
46 #include <net/if_types.h>
47 #include <net/if_dl.h>
48 #include <net/if_arp.h>
49 #include <net/if_llreach.h>
50 #include <net/if_ether.h>
51 #include <net/net_api_stats.h>
52 #include <net/route.h>
53 #include <net/if_ports_used.h>
54 #include <libkern/libkern.h>
55 #include <libkern/OSAtomic.h>
56 #include <kern/locks.h>
57 #include <kern/clock.h>
58 #include <sys/sockio.h>
59 #include <sys/proc.h>
60 #include <sys/sysctl.h>
61 #include <sys/mbuf.h>
62 #include <netinet/ip_var.h>
63 #include <netinet/udp.h>
64 #include <netinet/udp_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/tcp_var.h>
67 #include <netinet/in_pcb.h>
68 #ifdef INET
69 #include <netinet/igmp_var.h>
70 #endif
71 #include <netinet6/mld6_var.h>
72 #include <netkey/key.h>
73 #include <stdbool.h>
74 
75 #include "net/net_str_id.h"
76 
77 #if CONFIG_MACF
78 #include <sys/kauth.h>
79 #include <security/mac_framework.h>
80 #endif
81 
82 #if SKYWALK
83 #include <skywalk/os_skywalk_private.h>
84 #include <skywalk/nexus/netif/nx_netif.h>
85 #endif /* SKYWALK */
86 
87 extern uint64_t if_creation_generation_count;
88 
89 #undef ifnet_allocate
90 errno_t ifnet_allocate(const struct ifnet_init_params *init,
91     ifnet_t *ifp);
92 
93 static errno_t ifnet_allocate_common(const struct ifnet_init_params *init,
94     ifnet_t *ifp, bool is_internal);
95 
96 
97 #define TOUCHLASTCHANGE(__if_lastchange) {                              \
98 	(__if_lastchange)->tv_sec = (time_t)net_uptime();               \
99 	(__if_lastchange)->tv_usec = 0;                                 \
100 }
101 
102 static errno_t ifnet_defrouter_llreachinfo(ifnet_t, sa_family_t,
103     struct ifnet_llreach_info *);
104 static void ifnet_kpi_free(ifnet_t);
105 static errno_t ifnet_list_get_common(ifnet_family_t, boolean_t, ifnet_t **,
106     u_int32_t *);
107 static errno_t ifnet_set_lladdr_internal(ifnet_t, const void *, size_t,
108     u_char, int);
109 static errno_t ifnet_awdl_check_eflags(ifnet_t, u_int32_t *, u_int32_t *);
110 
111 
112 /*
113  * Temporary work around until we have real reference counting
114  *
115  * We keep the bits about calling dlil_if_release (which should be
116  * called recycle) transparent by calling it from our if_free function
117  * pointer. We have to keep the client's original detach function
118  * somewhere so we can call it.
119  */
120 static void
ifnet_kpi_free(ifnet_t ifp)121 ifnet_kpi_free(ifnet_t ifp)
122 {
123 	if ((ifp->if_refflags & IFRF_EMBRYONIC) == 0) {
124 		ifnet_detached_func detach_func;
125 
126 		detach_func = ifp->if_detach;
127 		if (detach_func != NULL) {
128 			(*detach_func)(ifp);
129 		}
130 	}
131 
132 	ifnet_dispose(ifp);
133 }
134 
135 errno_t
ifnet_allocate_common(const struct ifnet_init_params * init,ifnet_t * ifp,bool is_internal)136 ifnet_allocate_common(const struct ifnet_init_params *init,
137     ifnet_t *ifp, bool is_internal)
138 {
139 	struct ifnet_init_eparams einit;
140 
141 	bzero(&einit, sizeof(einit));
142 
143 	einit.ver               = IFNET_INIT_CURRENT_VERSION;
144 	einit.len               = sizeof(einit);
145 	einit.flags             = IFNET_INIT_LEGACY | IFNET_INIT_NX_NOAUTO;
146 	if (!is_internal) {
147 		einit.flags |= IFNET_INIT_ALLOC_KPI;
148 	}
149 	einit.uniqueid          = init->uniqueid;
150 	einit.uniqueid_len      = init->uniqueid_len;
151 	einit.name              = init->name;
152 	einit.unit              = init->unit;
153 	einit.family            = init->family;
154 	einit.type              = init->type;
155 	einit.output            = init->output;
156 	einit.demux             = init->demux;
157 	einit.add_proto         = init->add_proto;
158 	einit.del_proto         = init->del_proto;
159 	einit.check_multi       = init->check_multi;
160 	einit.framer            = init->framer;
161 	einit.softc             = init->softc;
162 	einit.ioctl             = init->ioctl;
163 	einit.set_bpf_tap       = init->set_bpf_tap;
164 	einit.detach            = init->detach;
165 	einit.event             = init->event;
166 	einit.broadcast_addr    = init->broadcast_addr;
167 	einit.broadcast_len     = init->broadcast_len;
168 
169 	return ifnet_allocate_extended(&einit, ifp);
170 }
171 
172 errno_t
ifnet_allocate_internal(const struct ifnet_init_params * init,ifnet_t * ifp)173 ifnet_allocate_internal(const struct ifnet_init_params *init, ifnet_t *ifp)
174 {
175 	return ifnet_allocate_common(init, ifp, true);
176 }
177 
178 errno_t
ifnet_allocate(const struct ifnet_init_params * init,ifnet_t * ifp)179 ifnet_allocate(const struct ifnet_init_params *init, ifnet_t *ifp)
180 {
181 	return ifnet_allocate_common(init, ifp, false);
182 }
183 
184 static void
ifnet_set_broadcast_addr(ifnet_t ifp,const void * broadcast_addr,u_int32_t broadcast_len)185 ifnet_set_broadcast_addr(ifnet_t ifp, const void * broadcast_addr,
186     u_int32_t broadcast_len)
187 {
188 	if (broadcast_len == 0 || broadcast_addr == NULL) {
189 		/* no broadcast address */
190 		bzero(&ifp->if_broadcast, sizeof(ifp->if_broadcast));
191 	} else if (broadcast_len > sizeof(ifp->if_broadcast.u.buffer)) {
192 		ifp->if_broadcast.u.ptr
193 		        = (u_char *)kalloc_data(broadcast_len,
194 		    Z_WAITOK | Z_NOFAIL);
195 		bcopy(broadcast_addr,
196 		    ifp->if_broadcast.u.ptr,
197 		    broadcast_len);
198 	} else {
199 		bcopy(broadcast_addr,
200 		    ifp->if_broadcast.u.buffer,
201 		    broadcast_len);
202 	}
203 	ifp->if_broadcast.length = broadcast_len;
204 }
205 
206 errno_t
ifnet_allocate_extended(const struct ifnet_init_eparams * einit0,ifnet_t * interface)207 ifnet_allocate_extended(const struct ifnet_init_eparams *einit0,
208     ifnet_t *interface)
209 {
210 #if SKYWALK
211 	ifnet_start_func ostart = NULL;
212 #endif /* SKYWALK */
213 	struct ifnet_init_eparams einit;
214 	struct ifnet *ifp = NULL;
215 	char if_xname[IFXNAMSIZ] = {0};
216 	int error;
217 
218 	einit = *einit0;
219 
220 	if (einit.ver != IFNET_INIT_CURRENT_VERSION ||
221 	    einit.len < sizeof(einit)) {
222 		return EINVAL;
223 	}
224 
225 	if (einit.family == 0 || einit.name == NULL ||
226 	    strlen(einit.name) >= IFNAMSIZ ||
227 	    (einit.type & 0xFFFFFF00) != 0 || einit.type == 0) {
228 		return EINVAL;
229 	}
230 
231 #if SKYWALK
232 	/* headroom must be a multiple of 8 bytes */
233 	if ((einit.tx_headroom & 0x7) != 0) {
234 		return EINVAL;
235 	}
236 	if ((einit.flags & IFNET_INIT_SKYWALK_NATIVE) == 0) {
237 		/*
238 		 * Currently Interface advisory reporting is supported only
239 		 * for skywalk interface.
240 		 */
241 		if ((einit.flags & IFNET_INIT_IF_ADV) != 0) {
242 			return EINVAL;
243 		}
244 	}
245 #endif /* SKYWALK */
246 
247 	if (einit.flags & IFNET_INIT_LEGACY) {
248 #if SKYWALK
249 		if (einit.flags & IFNET_INIT_SKYWALK_NATIVE) {
250 			return EINVAL;
251 		}
252 #endif /* SKYWALK */
253 		if (einit.output == NULL ||
254 		    (einit.flags & IFNET_INIT_INPUT_POLL)) {
255 			return EINVAL;
256 		}
257 		einit.pre_enqueue = NULL;
258 		einit.start = NULL;
259 		einit.output_ctl = NULL;
260 		einit.output_sched_model = IFNET_SCHED_MODEL_NORMAL;
261 		einit.input_poll = NULL;
262 		einit.input_ctl = NULL;
263 	} else {
264 #if SKYWALK
265 		/*
266 		 * For native Skywalk drivers, steer all start requests
267 		 * to ifp_if_start() until the netif device adapter is
268 		 * fully activated, at which point we will point it to
269 		 * nx_netif_doorbell().
270 		 */
271 		if (einit.flags & IFNET_INIT_SKYWALK_NATIVE) {
272 			if (einit.start != NULL) {
273 				return EINVAL;
274 			}
275 			/* override output start callback */
276 			ostart = einit.start = ifp_if_start;
277 		} else {
278 			ostart = einit.start;
279 		}
280 #endif /* SKYWALK */
281 		if (einit.start == NULL) {
282 			return EINVAL;
283 		}
284 
285 		einit.output = NULL;
286 		if (einit.output_sched_model >= IFNET_SCHED_MODEL_MAX) {
287 			return EINVAL;
288 		}
289 
290 		if (einit.flags & IFNET_INIT_INPUT_POLL) {
291 			if (einit.input_poll == NULL || einit.input_ctl == NULL) {
292 				return EINVAL;
293 			}
294 		} else {
295 			einit.input_poll = NULL;
296 			einit.input_ctl = NULL;
297 		}
298 	}
299 
300 	if (einit.type > UCHAR_MAX) {
301 		return EINVAL;
302 	}
303 
304 	if (einit.unit > SHRT_MAX) {
305 		return EINVAL;
306 	}
307 
308 	/* Initialize external name (name + unit) */
309 	(void) snprintf(if_xname, sizeof(if_xname), "%s%d",
310 	    einit.name, einit.unit);
311 
312 	if (einit.uniqueid == NULL) {
313 		einit.uniqueid = if_xname;
314 		einit.uniqueid_len = (uint32_t)strlen(if_xname);
315 	}
316 
317 	error = dlil_if_acquire(einit.family, einit.uniqueid,
318 	    einit.uniqueid_len, if_xname, &ifp);
319 
320 	if (error == 0) {
321 		uint64_t br;
322 
323 		/*
324 		 * Cast ifp->if_name as non const. dlil_if_acquire sets it up
325 		 * to point to storage of at least IFNAMSIZ bytes. It is safe
326 		 * to write to this.
327 		 */
328 		strlcpy(__DECONST(char *, ifp->if_name), einit.name, IFNAMSIZ);
329 		ifp->if_type            = (u_char)einit.type;
330 		ifp->if_family          = einit.family;
331 		ifp->if_subfamily       = einit.subfamily;
332 		ifp->if_unit            = (short)einit.unit;
333 		ifp->if_output          = einit.output;
334 		ifp->if_pre_enqueue     = einit.pre_enqueue;
335 		ifp->if_start           = einit.start;
336 		ifp->if_output_ctl      = einit.output_ctl;
337 		ifp->if_output_sched_model = einit.output_sched_model;
338 		ifp->if_output_bw.eff_bw = einit.output_bw;
339 		ifp->if_output_bw.max_bw = einit.output_bw_max;
340 		ifp->if_output_lt.eff_lt = einit.output_lt;
341 		ifp->if_output_lt.max_lt = einit.output_lt_max;
342 		ifp->if_input_poll      = einit.input_poll;
343 		ifp->if_input_ctl       = einit.input_ctl;
344 		ifp->if_input_bw.eff_bw = einit.input_bw;
345 		ifp->if_input_bw.max_bw = einit.input_bw_max;
346 		ifp->if_input_lt.eff_lt = einit.input_lt;
347 		ifp->if_input_lt.max_lt = einit.input_lt_max;
348 		ifp->if_demux           = einit.demux;
349 		ifp->if_add_proto       = einit.add_proto;
350 		ifp->if_del_proto       = einit.del_proto;
351 		ifp->if_check_multi     = einit.check_multi;
352 		ifp->if_framer_legacy   = einit.framer;
353 		ifp->if_framer          = einit.framer_extended;
354 		ifp->if_softc           = einit.softc;
355 		ifp->if_ioctl           = einit.ioctl;
356 		ifp->if_set_bpf_tap     = einit.set_bpf_tap;
357 		ifp->if_free            = (einit.free != NULL) ? einit.free : ifnet_kpi_free;
358 		ifp->if_event           = einit.event;
359 		ifp->if_detach          = einit.detach;
360 
361 		/* Initialize Network ID */
362 		ifp->network_id_len     = 0;
363 		bzero(&ifp->network_id, sizeof(ifp->network_id));
364 
365 		/* Initialize external name (name + unit) */
366 		snprintf(__DECONST(char *, ifp->if_xname), IFXNAMSIZ,
367 		    "%s", if_xname);
368 
369 		/*
370 		 * On embedded, framer() is already in the extended form;
371 		 * we simply use it as is, unless the caller specifies
372 		 * framer_extended() which will then override it.
373 		 *
374 		 * On non-embedded, framer() has long been exposed as part
375 		 * of the public KPI, and therefore its signature must
376 		 * remain the same (without the pre- and postpend length
377 		 * parameters.)  We special case ether_frameout, such that
378 		 * it gets mapped to its extended variant.  All other cases
379 		 * utilize the stub routine which will simply return zeroes
380 		 * for those new parameters.
381 		 *
382 		 * Internally, DLIL will only use the extended callback
383 		 * variant which is represented by if_framer.
384 		 */
385 #if !XNU_TARGET_OS_OSX
386 		if (ifp->if_framer == NULL && ifp->if_framer_legacy != NULL) {
387 			ifp->if_framer = ifp->if_framer_legacy;
388 		}
389 #else /* XNU_TARGET_OS_OSX */
390 		if (ifp->if_framer == NULL && ifp->if_framer_legacy != NULL) {
391 			if (ifp->if_framer_legacy == ether_frameout) {
392 				ifp->if_framer = ether_frameout_extended;
393 			} else {
394 				ifp->if_framer = ifnet_framer_stub;
395 			}
396 		}
397 #endif /* XNU_TARGET_OS_OSX */
398 
399 		if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw) {
400 			ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw;
401 		} else if (ifp->if_output_bw.eff_bw == 0) {
402 			ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw;
403 		}
404 
405 		if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw) {
406 			ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw;
407 		} else if (ifp->if_input_bw.eff_bw == 0) {
408 			ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw;
409 		}
410 
411 		if (ifp->if_output_bw.max_bw == 0) {
412 			ifp->if_output_bw = ifp->if_input_bw;
413 		} else if (ifp->if_input_bw.max_bw == 0) {
414 			ifp->if_input_bw = ifp->if_output_bw;
415 		}
416 
417 		/* Pin if_baudrate to 32 bits */
418 		br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw);
419 		if (br != 0) {
420 			ifp->if_baudrate = (br > UINT32_MAX) ? UINT32_MAX : (uint32_t)br;
421 		}
422 
423 		if (ifp->if_output_lt.eff_lt > ifp->if_output_lt.max_lt) {
424 			ifp->if_output_lt.max_lt = ifp->if_output_lt.eff_lt;
425 		} else if (ifp->if_output_lt.eff_lt == 0) {
426 			ifp->if_output_lt.eff_lt = ifp->if_output_lt.max_lt;
427 		}
428 
429 		if (ifp->if_input_lt.eff_lt > ifp->if_input_lt.max_lt) {
430 			ifp->if_input_lt.max_lt = ifp->if_input_lt.eff_lt;
431 		} else if (ifp->if_input_lt.eff_lt == 0) {
432 			ifp->if_input_lt.eff_lt = ifp->if_input_lt.max_lt;
433 		}
434 
435 		if (ifp->if_output_lt.max_lt == 0) {
436 			ifp->if_output_lt = ifp->if_input_lt;
437 		} else if (ifp->if_input_lt.max_lt == 0) {
438 			ifp->if_input_lt = ifp->if_output_lt;
439 		}
440 
441 		if (ifp->if_ioctl == NULL) {
442 			ifp->if_ioctl = ifp_if_ioctl;
443 		}
444 
445 		if_clear_eflags(ifp, -1);
446 		if (ifp->if_start != NULL) {
447 			if_set_eflags(ifp, IFEF_TXSTART);
448 			if (ifp->if_pre_enqueue == NULL) {
449 				ifp->if_pre_enqueue = ifnet_enqueue;
450 			}
451 			ifp->if_output = ifp->if_pre_enqueue;
452 		}
453 
454 		if (ifp->if_input_poll != NULL) {
455 			if_set_eflags(ifp, IFEF_RXPOLL);
456 		}
457 
458 		ifp->if_output_dlil = dlil_output_handler;
459 		ifp->if_input_dlil = dlil_input_handler;
460 
461 		VERIFY(!(einit.flags & IFNET_INIT_LEGACY) ||
462 		    (ifp->if_pre_enqueue == NULL && ifp->if_start == NULL &&
463 		    ifp->if_output_ctl == NULL && ifp->if_input_poll == NULL &&
464 		    ifp->if_input_ctl == NULL));
465 		VERIFY(!(einit.flags & IFNET_INIT_INPUT_POLL) ||
466 		    (ifp->if_input_poll != NULL && ifp->if_input_ctl != NULL));
467 
468 		ifnet_set_broadcast_addr(ifp, einit.broadcast_addr,
469 		    einit.broadcast_len);
470 
471 		if_clear_xflags(ifp, -1);
472 #if SKYWALK
473 		ifp->if_tx_headroom = 0;
474 		ifp->if_tx_trailer = 0;
475 		ifp->if_rx_mit_ival = 0;
476 		ifp->if_save_start = ostart;
477 		if (einit.flags & IFNET_INIT_SKYWALK_NATIVE) {
478 			VERIFY(ifp->if_eflags & IFEF_TXSTART);
479 			VERIFY(!(einit.flags & IFNET_INIT_LEGACY));
480 			if_set_eflags(ifp, IFEF_SKYWALK_NATIVE);
481 			ifp->if_tx_headroom = einit.tx_headroom;
482 			ifp->if_tx_trailer = einit.tx_trailer;
483 			ifp->if_rx_mit_ival = einit.rx_mit_ival;
484 			/*
485 			 * For native Skywalk drivers, make sure packets
486 			 * emitted by the BSD stack get dropped until the
487 			 * interface is in service.  When the netif host
488 			 * adapter is fully activated, we'll point it to
489 			 * nx_netif_output().
490 			 */
491 			ifp->if_output = ifp_if_output;
492 			/*
493 			 * Override driver-supplied parameters
494 			 * and force IFEF_ENQUEUE_MULTI?
495 			 */
496 			if (sk_netif_native_txmodel ==
497 			    NETIF_NATIVE_TXMODEL_ENQUEUE_MULTI) {
498 				einit.start_delay_qlen = sk_tx_delay_qlen;
499 				einit.start_delay_timeout = sk_tx_delay_timeout;
500 			}
501 			/* netif comes with native interfaces */
502 			VERIFY((ifp->if_xflags & IFXF_LEGACY) == 0);
503 		} else if (!ifnet_needs_compat(ifp)) {
504 			/*
505 			 * If we're told not to plumb in netif compat
506 			 * for this interface, set IFXF_NX_NOAUTO to
507 			 * prevent DLIL from auto-attaching the nexus.
508 			 */
509 			einit.flags |= IFNET_INIT_NX_NOAUTO;
510 			/* legacy (non-netif) interface */
511 			if_set_xflags(ifp, IFXF_LEGACY);
512 		}
513 
514 		ifp->if_save_output = ifp->if_output;
515 		if ((einit.flags & IFNET_INIT_NX_NOAUTO) != 0) {
516 			if_set_xflags(ifp, IFXF_NX_NOAUTO);
517 		}
518 		if ((einit.flags & IFNET_INIT_IF_ADV) != 0) {
519 			if_set_eflags(ifp, IFEF_ADV_REPORT);
520 		}
521 #else /* !SKYWALK */
522 		/* legacy interface */
523 		if_set_xflags(ifp, IFXF_LEGACY);
524 #endif /* !SKYWALK */
525 
526 		if ((ifp->if_snd = ifclassq_alloc()) == NULL) {
527 			panic_plain("%s: ifp=%p couldn't allocate class queues",
528 			    __func__, ifp);
529 			/* NOTREACHED */
530 		}
531 
532 		/*
533 		 * output target queue delay is specified in millisecond
534 		 * convert it to nanoseconds
535 		 */
536 		IFCQ_TARGET_QDELAY(ifp->if_snd) =
537 		    einit.output_target_qdelay * 1000 * 1000;
538 		IFCQ_MAXLEN(ifp->if_snd) = einit.sndq_maxlen;
539 
540 		ifnet_enqueue_multi_setup(ifp, einit.start_delay_qlen,
541 		    einit.start_delay_timeout);
542 
543 		IFCQ_PKT_DROP_LIMIT(ifp->if_snd) = IFCQ_DEFAULT_PKT_DROP_LIMIT;
544 
545 		/*
546 		 * Set embryonic flag; this will be cleared
547 		 * later when it is fully attached.
548 		 */
549 		ifp->if_refflags = IFRF_EMBRYONIC;
550 
551 		/*
552 		 * Count the newly allocated ifnet
553 		 */
554 		OSIncrementAtomic64(&net_api_stats.nas_ifnet_alloc_count);
555 		INC_ATOMIC_INT64_LIM(net_api_stats.nas_ifnet_alloc_total);
556 		if ((einit.flags & IFNET_INIT_ALLOC_KPI) != 0) {
557 			if_set_xflags(ifp, IFXF_ALLOC_KPI);
558 		} else {
559 			OSIncrementAtomic64(
560 				&net_api_stats.nas_ifnet_alloc_os_count);
561 			INC_ATOMIC_INT64_LIM(
562 				net_api_stats.nas_ifnet_alloc_os_total);
563 		}
564 
565 		if (ifp->if_subfamily == IFNET_SUBFAMILY_MANAGEMENT) {
566 			if_set_xflags(ifp, IFXF_MANAGEMENT);
567 			if_management_interface_check_needed = true;
568 		}
569 
570 		/*
571 		 * Increment the generation count on interface creation
572 		 */
573 		ifp->if_creation_generation_id = os_atomic_inc(&if_creation_generation_count, relaxed);
574 
575 		*interface = ifp;
576 	}
577 	return error;
578 }
579 
580 errno_t
ifnet_reference(ifnet_t ifp)581 ifnet_reference(ifnet_t ifp)
582 {
583 	return dlil_if_ref(ifp);
584 }
585 
586 void
ifnet_dispose(ifnet_t ifp)587 ifnet_dispose(ifnet_t ifp)
588 {
589 	dlil_if_release(ifp);
590 }
591 
592 errno_t
ifnet_release(ifnet_t ifp)593 ifnet_release(ifnet_t ifp)
594 {
595 	return dlil_if_free(ifp);
596 }
597 
598 errno_t
ifnet_interface_family_find(const char * module_string,ifnet_family_t * family_id)599 ifnet_interface_family_find(const char *module_string,
600     ifnet_family_t *family_id)
601 {
602 	if (module_string == NULL || family_id == NULL) {
603 		return EINVAL;
604 	}
605 
606 	return net_str_id_find_internal(module_string, family_id,
607 	           NSI_IF_FAM_ID, 1);
608 }
609 
610 void *
ifnet_softc(ifnet_t interface)611 ifnet_softc(ifnet_t interface)
612 {
613 	return (interface == NULL) ? NULL : interface->if_softc;
614 }
615 
616 const char *
ifnet_name(ifnet_t interface)617 ifnet_name(ifnet_t interface)
618 {
619 	return (interface == NULL) ? NULL : interface->if_name;
620 }
621 
622 ifnet_family_t
ifnet_family(ifnet_t interface)623 ifnet_family(ifnet_t interface)
624 {
625 	return (interface == NULL) ? 0 : interface->if_family;
626 }
627 
628 ifnet_subfamily_t
ifnet_subfamily(ifnet_t interface)629 ifnet_subfamily(ifnet_t interface)
630 {
631 	return (interface == NULL) ? 0 : interface->if_subfamily;
632 }
633 
634 u_int32_t
ifnet_unit(ifnet_t interface)635 ifnet_unit(ifnet_t interface)
636 {
637 	return (interface == NULL) ? (u_int32_t)0xffffffff :
638 	       (u_int32_t)interface->if_unit;
639 }
640 
641 u_int32_t
ifnet_index(ifnet_t interface)642 ifnet_index(ifnet_t interface)
643 {
644 	return (interface == NULL) ? (u_int32_t)0xffffffff :
645 	       interface->if_index;
646 }
647 
648 errno_t
ifnet_set_flags(ifnet_t interface,u_int16_t new_flags,u_int16_t mask)649 ifnet_set_flags(ifnet_t interface, u_int16_t new_flags, u_int16_t mask)
650 {
651 	bool set_IFF_UP;
652 	bool change_IFF_UP;
653 	uint16_t old_flags;
654 
655 	if (interface == NULL) {
656 		return EINVAL;
657 	}
658 	set_IFF_UP = (new_flags & IFF_UP) != 0;
659 	change_IFF_UP = (mask & IFF_UP) != 0;
660 #if SKYWALK
661 	if (set_IFF_UP && change_IFF_UP) {
662 		/*
663 		 * When a native skywalk interface is marked IFF_UP, ensure
664 		 * the flowswitch is attached.
665 		 */
666 		ifnet_attach_native_flowswitch(interface);
667 	}
668 #endif /* SKYWALK */
669 
670 	ifnet_lock_exclusive(interface);
671 
672 	/* If we are modifying the up/down state, call if_updown */
673 	if (change_IFF_UP) {
674 		if_updown(interface, set_IFF_UP);
675 	}
676 
677 	old_flags = interface->if_flags;
678 	interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask);
679 	/* If we are modifying the multicast flag, set/unset the silent flag */
680 	if ((old_flags & IFF_MULTICAST) !=
681 	    (interface->if_flags & IFF_MULTICAST)) {
682 #if INET
683 		if (IGMP_IFINFO(interface) != NULL) {
684 			igmp_initsilent(interface, IGMP_IFINFO(interface));
685 		}
686 #endif /* INET */
687 		if (MLD_IFINFO(interface) != NULL) {
688 			mld6_initsilent(interface, MLD_IFINFO(interface));
689 		}
690 	}
691 
692 	ifnet_lock_done(interface);
693 
694 	return 0;
695 }
696 
697 u_int16_t
ifnet_flags(ifnet_t interface)698 ifnet_flags(ifnet_t interface)
699 {
700 	return (interface == NULL) ? 0 : interface->if_flags;
701 }
702 
703 /*
704  * This routine ensures the following:
705  *
706  * If IFEF_AWDL is set by the caller, also set the rest of flags as
707  * defined in IFEF_AWDL_MASK.
708  *
709  * If IFEF_AWDL has been set on the interface and the caller attempts
710  * to clear one or more of the associated flags in IFEF_AWDL_MASK,
711  * return failure.
712  *
713  * If IFEF_AWDL_RESTRICTED is set by the caller, make sure IFEF_AWDL is set
714  * on the interface.
715  *
716  * All other flags not associated with AWDL are not affected.
717  *
718  * See <net/if.h> for current definition of IFEF_AWDL_MASK.
719  */
720 static errno_t
ifnet_awdl_check_eflags(ifnet_t ifp,u_int32_t * new_eflags,u_int32_t * mask)721 ifnet_awdl_check_eflags(ifnet_t ifp, u_int32_t *new_eflags, u_int32_t *mask)
722 {
723 	u_int32_t eflags;
724 
725 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
726 
727 	eflags = (*new_eflags & *mask) | (ifp->if_eflags & ~(*mask));
728 
729 	if (ifp->if_eflags & IFEF_AWDL) {
730 		if (eflags & IFEF_AWDL) {
731 			if ((eflags & IFEF_AWDL_MASK) != IFEF_AWDL_MASK) {
732 				return EINVAL;
733 			}
734 		} else {
735 			*new_eflags &= ~IFEF_AWDL_MASK;
736 			*mask |= IFEF_AWDL_MASK;
737 		}
738 	} else if (eflags & IFEF_AWDL) {
739 		*new_eflags |= IFEF_AWDL_MASK;
740 		*mask |= IFEF_AWDL_MASK;
741 	} else if (eflags & IFEF_AWDL_RESTRICTED &&
742 	    !(ifp->if_eflags & IFEF_AWDL)) {
743 		return EINVAL;
744 	}
745 
746 	return 0;
747 }
748 
749 errno_t
ifnet_set_eflags(ifnet_t interface,u_int32_t new_flags,u_int32_t mask)750 ifnet_set_eflags(ifnet_t interface, u_int32_t new_flags, u_int32_t mask)
751 {
752 	uint32_t oeflags;
753 	struct kev_msg ev_msg;
754 	struct net_event_data ev_data;
755 
756 	if (interface == NULL) {
757 		return EINVAL;
758 	}
759 
760 	bzero(&ev_msg, sizeof(ev_msg));
761 	ifnet_lock_exclusive(interface);
762 	/*
763 	 * Sanity checks for IFEF_AWDL and its related flags.
764 	 */
765 	if (ifnet_awdl_check_eflags(interface, &new_flags, &mask) != 0) {
766 		ifnet_lock_done(interface);
767 		return EINVAL;
768 	}
769 	/*
770 	 * Currently Interface advisory reporting is supported only for
771 	 * skywalk interface.
772 	 */
773 	if ((((new_flags & mask) & IFEF_ADV_REPORT) != 0) &&
774 	    ((interface->if_eflags & IFEF_SKYWALK_NATIVE) == 0)) {
775 		ifnet_lock_done(interface);
776 		return EINVAL;
777 	}
778 	oeflags = interface->if_eflags;
779 	if_clear_eflags(interface, mask);
780 	if (new_flags != 0) {
781 		if_set_eflags(interface, (new_flags & mask));
782 	}
783 	ifnet_lock_done(interface);
784 	if (interface->if_eflags & IFEF_AWDL_RESTRICTED &&
785 	    !(oeflags & IFEF_AWDL_RESTRICTED)) {
786 		ev_msg.event_code = KEV_DL_AWDL_RESTRICTED;
787 		/*
788 		 * The interface is now restricted to applications that have
789 		 * the entitlement.
790 		 * The check for the entitlement will be done in the data
791 		 * path, so we don't have to do anything here.
792 		 */
793 	} else if (oeflags & IFEF_AWDL_RESTRICTED &&
794 	    !(interface->if_eflags & IFEF_AWDL_RESTRICTED)) {
795 		ev_msg.event_code = KEV_DL_AWDL_UNRESTRICTED;
796 	}
797 	/*
798 	 * Notify configd so that it has a chance to perform better
799 	 * reachability detection.
800 	 */
801 	if (ev_msg.event_code) {
802 		bzero(&ev_data, sizeof(ev_data));
803 		ev_msg.vendor_code = KEV_VENDOR_APPLE;
804 		ev_msg.kev_class = KEV_NETWORK_CLASS;
805 		ev_msg.kev_subclass = KEV_DL_SUBCLASS;
806 		strlcpy(ev_data.if_name, interface->if_name, IFNAMSIZ);
807 		ev_data.if_family = interface->if_family;
808 		ev_data.if_unit = interface->if_unit;
809 		ev_msg.dv[0].data_length = sizeof(struct net_event_data);
810 		ev_msg.dv[0].data_ptr = &ev_data;
811 		ev_msg.dv[1].data_length = 0;
812 		dlil_post_complete_msg(interface, &ev_msg);
813 	}
814 
815 	return 0;
816 }
817 
818 u_int32_t
ifnet_eflags(ifnet_t interface)819 ifnet_eflags(ifnet_t interface)
820 {
821 	return (interface == NULL) ? 0 : interface->if_eflags;
822 }
823 
824 errno_t
ifnet_set_idle_flags_locked(ifnet_t ifp,u_int32_t new_flags,u_int32_t mask)825 ifnet_set_idle_flags_locked(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
826 {
827 	if (ifp == NULL) {
828 		return EINVAL;
829 	}
830 	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
831 
832 	/*
833 	 * If this is called prior to ifnet attach, the actual work will
834 	 * be done at attach time.  Otherwise, if it is called after
835 	 * ifnet detach, then it is a no-op.
836 	 */
837 	if (!ifnet_is_attached(ifp, 0)) {
838 		ifp->if_idle_new_flags = new_flags;
839 		ifp->if_idle_new_flags_mask = mask;
840 		return 0;
841 	} else {
842 		ifp->if_idle_new_flags = ifp->if_idle_new_flags_mask = 0;
843 	}
844 
845 	ifp->if_idle_flags = (new_flags & mask) | (ifp->if_idle_flags & ~mask);
846 	return 0;
847 }
848 
849 errno_t
ifnet_set_idle_flags(ifnet_t ifp,u_int32_t new_flags,u_int32_t mask)850 ifnet_set_idle_flags(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
851 {
852 	errno_t err;
853 
854 	ifnet_lock_exclusive(ifp);
855 	err = ifnet_set_idle_flags_locked(ifp, new_flags, mask);
856 	ifnet_lock_done(ifp);
857 
858 	return err;
859 }
860 
861 u_int32_t
ifnet_idle_flags(ifnet_t ifp)862 ifnet_idle_flags(ifnet_t ifp)
863 {
864 	return (ifp == NULL) ? 0 : ifp->if_idle_flags;
865 }
866 
867 errno_t
ifnet_set_link_quality(ifnet_t ifp,int quality)868 ifnet_set_link_quality(ifnet_t ifp, int quality)
869 {
870 	errno_t err = 0;
871 
872 	if (ifp == NULL || quality < IFNET_LQM_MIN || quality > IFNET_LQM_MAX) {
873 		err = EINVAL;
874 		goto done;
875 	}
876 
877 	if (!ifnet_is_attached(ifp, 0)) {
878 		err = ENXIO;
879 		goto done;
880 	}
881 
882 	if_lqm_update(ifp, quality, 0);
883 
884 done:
885 	return err;
886 }
887 
888 int
ifnet_link_quality(ifnet_t ifp)889 ifnet_link_quality(ifnet_t ifp)
890 {
891 	int lqm;
892 
893 	if (ifp == NULL) {
894 		return IFNET_LQM_THRESH_OFF;
895 	}
896 
897 	ifnet_lock_shared(ifp);
898 	lqm = ifp->if_interface_state.lqm_state;
899 	ifnet_lock_done(ifp);
900 
901 	return lqm;
902 }
903 
904 errno_t
ifnet_set_interface_state(ifnet_t ifp,struct if_interface_state * if_interface_state)905 ifnet_set_interface_state(ifnet_t ifp,
906     struct if_interface_state *if_interface_state)
907 {
908 	errno_t err = 0;
909 
910 	if (ifp == NULL || if_interface_state == NULL) {
911 		err = EINVAL;
912 		goto done;
913 	}
914 
915 	if (!ifnet_is_attached(ifp, 0)) {
916 		err = ENXIO;
917 		goto done;
918 	}
919 
920 	if_state_update(ifp, if_interface_state);
921 
922 done:
923 	return err;
924 }
925 
926 errno_t
ifnet_get_interface_state(ifnet_t ifp,struct if_interface_state * if_interface_state)927 ifnet_get_interface_state(ifnet_t ifp,
928     struct if_interface_state *if_interface_state)
929 {
930 	errno_t err = 0;
931 
932 	if (ifp == NULL || if_interface_state == NULL) {
933 		err = EINVAL;
934 		goto done;
935 	}
936 
937 	if (!ifnet_is_attached(ifp, 0)) {
938 		err = ENXIO;
939 		goto done;
940 	}
941 
942 	if_get_state(ifp, if_interface_state);
943 
944 done:
945 	return err;
946 }
947 
948 
949 static errno_t
ifnet_defrouter_llreachinfo(ifnet_t ifp,sa_family_t af,struct ifnet_llreach_info * iflri)950 ifnet_defrouter_llreachinfo(ifnet_t ifp, sa_family_t af,
951     struct ifnet_llreach_info *iflri)
952 {
953 	if (ifp == NULL || iflri == NULL) {
954 		return EINVAL;
955 	}
956 
957 	VERIFY(af == AF_INET || af == AF_INET6);
958 
959 	return ifnet_llreach_get_defrouter(ifp, af, iflri);
960 }
961 
962 errno_t
ifnet_inet_defrouter_llreachinfo(ifnet_t ifp,struct ifnet_llreach_info * iflri)963 ifnet_inet_defrouter_llreachinfo(ifnet_t ifp, struct ifnet_llreach_info *iflri)
964 {
965 	return ifnet_defrouter_llreachinfo(ifp, AF_INET, iflri);
966 }
967 
968 errno_t
ifnet_inet6_defrouter_llreachinfo(ifnet_t ifp,struct ifnet_llreach_info * iflri)969 ifnet_inet6_defrouter_llreachinfo(ifnet_t ifp, struct ifnet_llreach_info *iflri)
970 {
971 	return ifnet_defrouter_llreachinfo(ifp, AF_INET6, iflri);
972 }
973 
974 errno_t
ifnet_set_capabilities_supported(ifnet_t ifp,u_int32_t new_caps,u_int32_t mask)975 ifnet_set_capabilities_supported(ifnet_t ifp, u_int32_t new_caps,
976     u_int32_t mask)
977 {
978 	errno_t error = 0;
979 	int tmp;
980 
981 	if (ifp == NULL) {
982 		return EINVAL;
983 	}
984 
985 	ifnet_lock_exclusive(ifp);
986 	tmp = (new_caps & mask) | (ifp->if_capabilities & ~mask);
987 	if ((tmp & ~IFCAP_VALID)) {
988 		error = EINVAL;
989 	} else {
990 		ifp->if_capabilities = tmp;
991 	}
992 	ifnet_lock_done(ifp);
993 
994 	return error;
995 }
996 
997 u_int32_t
ifnet_capabilities_supported(ifnet_t ifp)998 ifnet_capabilities_supported(ifnet_t ifp)
999 {
1000 	return (ifp == NULL) ? 0 : ifp->if_capabilities;
1001 }
1002 
1003 
1004 errno_t
ifnet_set_capabilities_enabled(ifnet_t ifp,u_int32_t new_caps,u_int32_t mask)1005 ifnet_set_capabilities_enabled(ifnet_t ifp, u_int32_t new_caps,
1006     u_int32_t mask)
1007 {
1008 	errno_t error = 0;
1009 	int tmp;
1010 	struct kev_msg ev_msg;
1011 	struct net_event_data ev_data;
1012 
1013 	if (ifp == NULL) {
1014 		return EINVAL;
1015 	}
1016 
1017 	ifnet_lock_exclusive(ifp);
1018 	tmp = (new_caps & mask) | (ifp->if_capenable & ~mask);
1019 	if ((tmp & ~IFCAP_VALID) || (tmp & ~ifp->if_capabilities)) {
1020 		error = EINVAL;
1021 	} else {
1022 		ifp->if_capenable = tmp;
1023 	}
1024 	ifnet_lock_done(ifp);
1025 
1026 	/* Notify application of the change */
1027 	bzero(&ev_data, sizeof(struct net_event_data));
1028 	bzero(&ev_msg, sizeof(struct kev_msg));
1029 	ev_msg.vendor_code      = KEV_VENDOR_APPLE;
1030 	ev_msg.kev_class        = KEV_NETWORK_CLASS;
1031 	ev_msg.kev_subclass     = KEV_DL_SUBCLASS;
1032 
1033 	ev_msg.event_code       = KEV_DL_IFCAP_CHANGED;
1034 	strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1035 	ev_data.if_family       = ifp->if_family;
1036 	ev_data.if_unit         = (u_int32_t)ifp->if_unit;
1037 	ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1038 	ev_msg.dv[0].data_ptr = &ev_data;
1039 	ev_msg.dv[1].data_length = 0;
1040 	dlil_post_complete_msg(ifp, &ev_msg);
1041 
1042 	return error;
1043 }
1044 
1045 u_int32_t
ifnet_capabilities_enabled(ifnet_t ifp)1046 ifnet_capabilities_enabled(ifnet_t ifp)
1047 {
1048 	return (ifp == NULL) ? 0 : ifp->if_capenable;
1049 }
1050 
1051 static const ifnet_offload_t offload_mask =
1052     (IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT |
1053     IFNET_IP_FRAGMENT | IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 |
1054     IFNET_IPV6_FRAGMENT | IFNET_CSUM_PARTIAL | IFNET_CSUM_ZERO_INVERT |
1055     IFNET_VLAN_TAGGING | IFNET_VLAN_MTU | IFNET_MULTIPAGES |
1056     IFNET_TSO_IPV4 | IFNET_TSO_IPV6 | IFNET_TX_STATUS | IFNET_HW_TIMESTAMP |
1057     IFNET_SW_TIMESTAMP);
1058 
1059 static const ifnet_offload_t any_offload_csum = IFNET_CHECKSUMF;
1060 
1061 static errno_t
ifnet_set_offload_common(ifnet_t interface,ifnet_offload_t offload,boolean_t set_both)1062 ifnet_set_offload_common(ifnet_t interface, ifnet_offload_t offload, boolean_t set_both)
1063 {
1064 	u_int32_t ifcaps = 0;
1065 
1066 	if (interface == NULL) {
1067 		return EINVAL;
1068 	}
1069 
1070 	ifnet_lock_exclusive(interface);
1071 	interface->if_hwassist = (offload & offload_mask);
1072 
1073 #if SKYWALK
1074 	/* preserve skywalk capability */
1075 	if ((interface->if_capabilities & IFCAP_SKYWALK) != 0) {
1076 		ifcaps |= IFCAP_SKYWALK;
1077 	}
1078 #endif /* SKYWALK */
1079 	if (dlil_verbose) {
1080 		log(LOG_DEBUG, "%s: set offload flags=%b\n",
1081 		    if_name(interface),
1082 		    interface->if_hwassist, IFNET_OFFLOADF_BITS);
1083 	}
1084 	ifnet_lock_done(interface);
1085 
1086 	if ((offload & any_offload_csum)) {
1087 		ifcaps |= IFCAP_HWCSUM;
1088 	}
1089 	if ((offload & IFNET_TSO_IPV4)) {
1090 		ifcaps |= IFCAP_TSO4;
1091 	}
1092 	if ((offload & IFNET_TSO_IPV6)) {
1093 		ifcaps |= IFCAP_TSO6;
1094 	}
1095 	if ((offload & IFNET_LRO)) {
1096 		ifcaps |= IFCAP_LRO;
1097 	}
1098 	if ((offload & IFNET_VLAN_MTU)) {
1099 		ifcaps |= IFCAP_VLAN_MTU;
1100 	}
1101 	if ((offload & IFNET_VLAN_TAGGING)) {
1102 		ifcaps |= IFCAP_VLAN_HWTAGGING;
1103 	}
1104 	if ((offload & IFNET_TX_STATUS)) {
1105 		ifcaps |= IFCAP_TXSTATUS;
1106 	}
1107 	if ((offload & IFNET_HW_TIMESTAMP)) {
1108 		ifcaps |= IFCAP_HW_TIMESTAMP;
1109 	}
1110 	if ((offload & IFNET_SW_TIMESTAMP)) {
1111 		ifcaps |= IFCAP_SW_TIMESTAMP;
1112 	}
1113 	if ((offload & IFNET_CSUM_PARTIAL)) {
1114 		ifcaps |= IFCAP_CSUM_PARTIAL;
1115 	}
1116 	if ((offload & IFNET_CSUM_ZERO_INVERT)) {
1117 		ifcaps |= IFCAP_CSUM_ZERO_INVERT;
1118 	}
1119 	if (ifcaps != 0) {
1120 		if (set_both) {
1121 			(void) ifnet_set_capabilities_supported(interface,
1122 			    ifcaps, IFCAP_VALID);
1123 		}
1124 		(void) ifnet_set_capabilities_enabled(interface, ifcaps,
1125 		    IFCAP_VALID);
1126 	}
1127 
1128 	return 0;
1129 }
1130 
1131 errno_t
ifnet_set_offload(ifnet_t interface,ifnet_offload_t offload)1132 ifnet_set_offload(ifnet_t interface, ifnet_offload_t offload)
1133 {
1134 	return ifnet_set_offload_common(interface, offload, TRUE);
1135 }
1136 
1137 errno_t
ifnet_set_offload_enabled(ifnet_t interface,ifnet_offload_t offload)1138 ifnet_set_offload_enabled(ifnet_t interface, ifnet_offload_t offload)
1139 {
1140 	return ifnet_set_offload_common(interface, offload, FALSE);
1141 }
1142 
1143 ifnet_offload_t
ifnet_offload(ifnet_t interface)1144 ifnet_offload(ifnet_t interface)
1145 {
1146 	return (interface == NULL) ?
1147 	       0 : (interface->if_hwassist & offload_mask);
1148 }
1149 
1150 errno_t
ifnet_set_tso_mtu(ifnet_t interface,sa_family_t family,u_int32_t mtuLen)1151 ifnet_set_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t mtuLen)
1152 {
1153 	errno_t error = 0;
1154 
1155 	if (interface == NULL || mtuLen < interface->if_mtu) {
1156 		return EINVAL;
1157 	}
1158 	if (mtuLen > IP_MAXPACKET) {
1159 		return EINVAL;
1160 	}
1161 
1162 	switch (family) {
1163 	case AF_INET:
1164 		if (interface->if_hwassist & IFNET_TSO_IPV4) {
1165 			interface->if_tso_v4_mtu = mtuLen;
1166 		} else {
1167 			error = EINVAL;
1168 		}
1169 		break;
1170 
1171 	case AF_INET6:
1172 		if (interface->if_hwassist & IFNET_TSO_IPV6) {
1173 			interface->if_tso_v6_mtu = mtuLen;
1174 		} else {
1175 			error = EINVAL;
1176 		}
1177 		break;
1178 
1179 	default:
1180 		error = EPROTONOSUPPORT;
1181 		break;
1182 	}
1183 
1184 	if (error == 0) {
1185 		struct ifclassq *ifq = interface->if_snd;
1186 		ASSERT(ifq != NULL);
1187 		/* Inform all transmit queues about the new TSO MTU */
1188 		IFCQ_LOCK(ifq);
1189 		ifnet_update_sndq(ifq, CLASSQ_EV_LINK_MTU);
1190 		IFCQ_UNLOCK(ifq);
1191 	}
1192 
1193 	return error;
1194 }
1195 
1196 errno_t
ifnet_get_tso_mtu(ifnet_t interface,sa_family_t family,u_int32_t * mtuLen)1197 ifnet_get_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t *mtuLen)
1198 {
1199 	errno_t error = 0;
1200 
1201 	if (interface == NULL || mtuLen == NULL) {
1202 		return EINVAL;
1203 	}
1204 
1205 	switch (family) {
1206 	case AF_INET:
1207 		if (interface->if_hwassist & IFNET_TSO_IPV4) {
1208 			*mtuLen = interface->if_tso_v4_mtu;
1209 		} else {
1210 			error = EINVAL;
1211 		}
1212 		break;
1213 
1214 	case AF_INET6:
1215 		if (interface->if_hwassist & IFNET_TSO_IPV6) {
1216 			*mtuLen = interface->if_tso_v6_mtu;
1217 		} else {
1218 			error = EINVAL;
1219 		}
1220 		break;
1221 
1222 	default:
1223 		error = EPROTONOSUPPORT;
1224 		break;
1225 	}
1226 
1227 	return error;
1228 }
1229 
1230 errno_t
ifnet_set_wake_flags(ifnet_t interface,u_int32_t properties,u_int32_t mask)1231 ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask)
1232 {
1233 	struct kev_msg ev_msg;
1234 	struct net_event_data ev_data;
1235 
1236 	bzero(&ev_data, sizeof(struct net_event_data));
1237 	bzero(&ev_msg, sizeof(struct kev_msg));
1238 
1239 	if (interface == NULL) {
1240 		return EINVAL;
1241 	}
1242 
1243 	/* Do not accept wacky values */
1244 	if ((properties & mask) & ~IF_WAKE_VALID_FLAGS) {
1245 		return EINVAL;
1246 	}
1247 
1248 	if ((mask & IF_WAKE_ON_MAGIC_PACKET) != 0) {
1249 		if ((properties & IF_WAKE_ON_MAGIC_PACKET) != 0) {
1250 			if_set_xflags(interface, IFXF_WAKE_ON_MAGIC_PACKET);
1251 		} else {
1252 			if_clear_xflags(interface, IFXF_WAKE_ON_MAGIC_PACKET);
1253 		}
1254 	}
1255 
1256 	(void) ifnet_touch_lastchange(interface);
1257 
1258 	/* Notify application of the change */
1259 	ev_msg.vendor_code      = KEV_VENDOR_APPLE;
1260 	ev_msg.kev_class        = KEV_NETWORK_CLASS;
1261 	ev_msg.kev_subclass     = KEV_DL_SUBCLASS;
1262 
1263 	ev_msg.event_code       = KEV_DL_WAKEFLAGS_CHANGED;
1264 	strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ);
1265 	ev_data.if_family       = interface->if_family;
1266 	ev_data.if_unit         = (u_int32_t)interface->if_unit;
1267 	ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1268 	ev_msg.dv[0].data_ptr   = &ev_data;
1269 	ev_msg.dv[1].data_length = 0;
1270 	dlil_post_complete_msg(interface, &ev_msg);
1271 
1272 	return 0;
1273 }
1274 
1275 u_int32_t
ifnet_get_wake_flags(ifnet_t interface)1276 ifnet_get_wake_flags(ifnet_t interface)
1277 {
1278 	u_int32_t flags = 0;
1279 
1280 	if (interface == NULL) {
1281 		return 0;
1282 	}
1283 
1284 	if ((interface->if_xflags & IFXF_WAKE_ON_MAGIC_PACKET) != 0) {
1285 		flags |= IF_WAKE_ON_MAGIC_PACKET;
1286 	}
1287 
1288 	return flags;
1289 }
1290 
1291 /*
1292  * Should MIB data store a copy?
1293  */
1294 errno_t
ifnet_set_link_mib_data(ifnet_t interface,void * mibData,uint32_t mibLen)1295 ifnet_set_link_mib_data(ifnet_t interface, void *mibData, uint32_t mibLen)
1296 {
1297 	if (interface == NULL) {
1298 		return EINVAL;
1299 	}
1300 
1301 	ifnet_lock_exclusive(interface);
1302 	interface->if_linkmib = (void*)mibData;
1303 	interface->if_linkmiblen = mibLen;
1304 	ifnet_lock_done(interface);
1305 	return 0;
1306 }
1307 
1308 errno_t
ifnet_get_link_mib_data(ifnet_t interface,void * mibData,uint32_t * mibLen)1309 ifnet_get_link_mib_data(ifnet_t interface, void *mibData, uint32_t *mibLen)
1310 {
1311 	errno_t result = 0;
1312 
1313 	if (interface == NULL) {
1314 		return EINVAL;
1315 	}
1316 
1317 	ifnet_lock_shared(interface);
1318 	if (*mibLen < interface->if_linkmiblen) {
1319 		result = EMSGSIZE;
1320 	}
1321 	if (result == 0 && interface->if_linkmib == NULL) {
1322 		result = ENOTSUP;
1323 	}
1324 
1325 	if (result == 0) {
1326 		*mibLen = interface->if_linkmiblen;
1327 		bcopy(interface->if_linkmib, mibData, *mibLen);
1328 	}
1329 	ifnet_lock_done(interface);
1330 
1331 	return result;
1332 }
1333 
1334 uint32_t
ifnet_get_link_mib_data_length(ifnet_t interface)1335 ifnet_get_link_mib_data_length(ifnet_t interface)
1336 {
1337 	return (interface == NULL) ? 0 : interface->if_linkmiblen;
1338 }
1339 
1340 errno_t
ifnet_output(ifnet_t interface,protocol_family_t protocol_family,mbuf_t m,void * route,const struct sockaddr * dest)1341 ifnet_output(ifnet_t interface, protocol_family_t protocol_family,
1342     mbuf_t m, void *route, const struct sockaddr *dest)
1343 {
1344 	if (interface == NULL || protocol_family == 0 || m == NULL) {
1345 		if (m != NULL) {
1346 			mbuf_freem_list(m);
1347 		}
1348 		return EINVAL;
1349 	}
1350 	return dlil_output(interface, protocol_family, m, route, dest, 0, NULL);
1351 }
1352 
1353 errno_t
ifnet_output_raw(ifnet_t interface,protocol_family_t protocol_family,mbuf_t m)1354 ifnet_output_raw(ifnet_t interface, protocol_family_t protocol_family, mbuf_t m)
1355 {
1356 	if (interface == NULL || m == NULL) {
1357 		if (m != NULL) {
1358 			mbuf_freem_list(m);
1359 		}
1360 		return EINVAL;
1361 	}
1362 	return dlil_output(interface, protocol_family, m, NULL, NULL, 1, NULL);
1363 }
1364 
1365 errno_t
ifnet_set_mtu(ifnet_t interface,u_int32_t mtu)1366 ifnet_set_mtu(ifnet_t interface, u_int32_t mtu)
1367 {
1368 	if (interface == NULL) {
1369 		return EINVAL;
1370 	}
1371 
1372 	interface->if_mtu = mtu;
1373 	return 0;
1374 }
1375 
1376 u_int32_t
ifnet_mtu(ifnet_t interface)1377 ifnet_mtu(ifnet_t interface)
1378 {
1379 	return (interface == NULL) ? 0 : interface->if_mtu;
1380 }
1381 
1382 u_char
ifnet_type(ifnet_t interface)1383 ifnet_type(ifnet_t interface)
1384 {
1385 	return (interface == NULL) ? 0 : interface->if_data.ifi_type;
1386 }
1387 
1388 errno_t
ifnet_set_addrlen(ifnet_t interface,u_char addrlen)1389 ifnet_set_addrlen(ifnet_t interface, u_char addrlen)
1390 {
1391 	if (interface == NULL) {
1392 		return EINVAL;
1393 	}
1394 
1395 	interface->if_data.ifi_addrlen = addrlen;
1396 	return 0;
1397 }
1398 
1399 u_char
ifnet_addrlen(ifnet_t interface)1400 ifnet_addrlen(ifnet_t interface)
1401 {
1402 	return (interface == NULL) ? 0 : interface->if_data.ifi_addrlen;
1403 }
1404 
1405 errno_t
ifnet_set_hdrlen(ifnet_t interface,u_char hdrlen)1406 ifnet_set_hdrlen(ifnet_t interface, u_char hdrlen)
1407 {
1408 	if (interface == NULL) {
1409 		return EINVAL;
1410 	}
1411 
1412 	interface->if_data.ifi_hdrlen = hdrlen;
1413 	return 0;
1414 }
1415 
1416 u_char
ifnet_hdrlen(ifnet_t interface)1417 ifnet_hdrlen(ifnet_t interface)
1418 {
1419 	return (interface == NULL) ? 0 : interface->if_data.ifi_hdrlen;
1420 }
1421 
1422 errno_t
ifnet_set_metric(ifnet_t interface,u_int32_t metric)1423 ifnet_set_metric(ifnet_t interface, u_int32_t metric)
1424 {
1425 	if (interface == NULL) {
1426 		return EINVAL;
1427 	}
1428 
1429 	interface->if_data.ifi_metric = metric;
1430 	return 0;
1431 }
1432 
1433 u_int32_t
ifnet_metric(ifnet_t interface)1434 ifnet_metric(ifnet_t interface)
1435 {
1436 	return (interface == NULL) ? 0 : interface->if_data.ifi_metric;
1437 }
1438 
1439 errno_t
ifnet_set_baudrate(struct ifnet * ifp,uint64_t baudrate)1440 ifnet_set_baudrate(struct ifnet *ifp, uint64_t baudrate)
1441 {
1442 	if (ifp == NULL) {
1443 		return EINVAL;
1444 	}
1445 
1446 	ifp->if_output_bw.max_bw = ifp->if_input_bw.max_bw =
1447 	    ifp->if_output_bw.eff_bw = ifp->if_input_bw.eff_bw = baudrate;
1448 
1449 	/* Pin if_baudrate to 32 bits until we can change the storage size */
1450 	ifp->if_baudrate = (baudrate > UINT32_MAX) ? UINT32_MAX : (uint32_t)baudrate;
1451 
1452 	return 0;
1453 }
1454 
1455 u_int64_t
ifnet_baudrate(struct ifnet * ifp)1456 ifnet_baudrate(struct ifnet *ifp)
1457 {
1458 	return (ifp == NULL) ? 0 : ifp->if_baudrate;
1459 }
1460 
1461 errno_t
ifnet_set_bandwidths(struct ifnet * ifp,struct if_bandwidths * output_bw,struct if_bandwidths * input_bw)1462 ifnet_set_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw,
1463     struct if_bandwidths *input_bw)
1464 {
1465 	if (ifp == NULL) {
1466 		return EINVAL;
1467 	}
1468 
1469 	/* set input values first (if any), as output values depend on them */
1470 	if (input_bw != NULL) {
1471 		(void) ifnet_set_input_bandwidths(ifp, input_bw);
1472 	}
1473 
1474 	if (output_bw != NULL) {
1475 		(void) ifnet_set_output_bandwidths(ifp, output_bw, FALSE);
1476 	}
1477 
1478 	return 0;
1479 }
1480 
1481 static void
ifnet_set_link_status_outbw(struct ifnet * ifp)1482 ifnet_set_link_status_outbw(struct ifnet *ifp)
1483 {
1484 	struct if_wifi_status_v1 *sr;
1485 	sr = &ifp->if_link_status->ifsr_u.ifsr_wifi.if_wifi_u.if_status_v1;
1486 	if (ifp->if_output_bw.eff_bw != 0) {
1487 		sr->valid_bitmask |=
1488 		    IF_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID;
1489 		sr->ul_effective_bandwidth =
1490 		    ifp->if_output_bw.eff_bw > UINT32_MAX ?
1491 		    UINT32_MAX :
1492 		    (uint32_t)ifp->if_output_bw.eff_bw;
1493 	}
1494 	if (ifp->if_output_bw.max_bw != 0) {
1495 		sr->valid_bitmask |=
1496 		    IF_WIFI_UL_MAX_BANDWIDTH_VALID;
1497 		sr->ul_max_bandwidth =
1498 		    ifp->if_output_bw.max_bw > UINT32_MAX ?
1499 		    UINT32_MAX :
1500 		    (uint32_t)ifp->if_output_bw.max_bw;
1501 	}
1502 }
1503 
1504 errno_t
ifnet_set_output_bandwidths(struct ifnet * ifp,struct if_bandwidths * bw,boolean_t locked)1505 ifnet_set_output_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw,
1506     boolean_t locked)
1507 {
1508 	struct if_bandwidths old_bw;
1509 	struct ifclassq *ifq;
1510 	u_int64_t br;
1511 
1512 	VERIFY(ifp != NULL && bw != NULL);
1513 
1514 	ifq = ifp->if_snd;
1515 	if (!locked) {
1516 		IFCQ_LOCK(ifq);
1517 	}
1518 	IFCQ_LOCK_ASSERT_HELD(ifq);
1519 
1520 	old_bw = ifp->if_output_bw;
1521 	if (bw->eff_bw != 0) {
1522 		ifp->if_output_bw.eff_bw = bw->eff_bw;
1523 	}
1524 	if (bw->max_bw != 0) {
1525 		ifp->if_output_bw.max_bw = bw->max_bw;
1526 	}
1527 	if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw) {
1528 		ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw;
1529 	} else if (ifp->if_output_bw.eff_bw == 0) {
1530 		ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw;
1531 	}
1532 
1533 	/* Pin if_baudrate to 32 bits */
1534 	br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw);
1535 	if (br != 0) {
1536 		ifp->if_baudrate = (br > UINT32_MAX) ? UINT32_MAX : (uint32_t)br;
1537 	}
1538 
1539 	/* Adjust queue parameters if needed */
1540 	if (old_bw.eff_bw != ifp->if_output_bw.eff_bw ||
1541 	    old_bw.max_bw != ifp->if_output_bw.max_bw) {
1542 		ifnet_update_sndq(ifq, CLASSQ_EV_LINK_BANDWIDTH);
1543 	}
1544 
1545 	if (!locked) {
1546 		IFCQ_UNLOCK(ifq);
1547 	}
1548 
1549 	/*
1550 	 * If this is a Wifi interface, update the values in
1551 	 * if_link_status structure also.
1552 	 */
1553 	if (IFNET_IS_WIFI(ifp) && ifp->if_link_status != NULL) {
1554 		lck_rw_lock_exclusive(&ifp->if_link_status_lock);
1555 		ifnet_set_link_status_outbw(ifp);
1556 		lck_rw_done(&ifp->if_link_status_lock);
1557 	}
1558 
1559 	return 0;
1560 }
1561 
1562 static void
ifnet_set_link_status_inbw(struct ifnet * ifp)1563 ifnet_set_link_status_inbw(struct ifnet *ifp)
1564 {
1565 	struct if_wifi_status_v1 *sr;
1566 
1567 	sr = &ifp->if_link_status->ifsr_u.ifsr_wifi.if_wifi_u.if_status_v1;
1568 	if (ifp->if_input_bw.eff_bw != 0) {
1569 		sr->valid_bitmask |=
1570 		    IF_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID;
1571 		sr->dl_effective_bandwidth =
1572 		    ifp->if_input_bw.eff_bw > UINT32_MAX ?
1573 		    UINT32_MAX :
1574 		    (uint32_t)ifp->if_input_bw.eff_bw;
1575 	}
1576 	if (ifp->if_input_bw.max_bw != 0) {
1577 		sr->valid_bitmask |=
1578 		    IF_WIFI_DL_MAX_BANDWIDTH_VALID;
1579 		sr->dl_max_bandwidth = ifp->if_input_bw.max_bw > UINT32_MAX ?
1580 		    UINT32_MAX :
1581 		    (uint32_t)ifp->if_input_bw.max_bw;
1582 	}
1583 }
1584 
1585 errno_t
ifnet_set_input_bandwidths(struct ifnet * ifp,struct if_bandwidths * bw)1586 ifnet_set_input_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw)
1587 {
1588 	struct if_bandwidths old_bw;
1589 
1590 	VERIFY(ifp != NULL && bw != NULL);
1591 
1592 	old_bw = ifp->if_input_bw;
1593 	if (bw->eff_bw != 0) {
1594 		ifp->if_input_bw.eff_bw = bw->eff_bw;
1595 	}
1596 	if (bw->max_bw != 0) {
1597 		ifp->if_input_bw.max_bw = bw->max_bw;
1598 	}
1599 	if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw) {
1600 		ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw;
1601 	} else if (ifp->if_input_bw.eff_bw == 0) {
1602 		ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw;
1603 	}
1604 
1605 	if (IFNET_IS_WIFI(ifp) && ifp->if_link_status != NULL) {
1606 		lck_rw_lock_exclusive(&ifp->if_link_status_lock);
1607 		ifnet_set_link_status_inbw(ifp);
1608 		lck_rw_done(&ifp->if_link_status_lock);
1609 	}
1610 
1611 	if (old_bw.eff_bw != ifp->if_input_bw.eff_bw ||
1612 	    old_bw.max_bw != ifp->if_input_bw.max_bw) {
1613 		ifnet_update_rcv(ifp, CLASSQ_EV_LINK_BANDWIDTH);
1614 	}
1615 
1616 	return 0;
1617 }
1618 
1619 u_int64_t
ifnet_output_linkrate(struct ifnet * ifp)1620 ifnet_output_linkrate(struct ifnet *ifp)
1621 {
1622 	struct ifclassq *ifq = ifp->if_snd;
1623 	u_int64_t rate;
1624 
1625 	IFCQ_LOCK_ASSERT_HELD(ifq);
1626 
1627 	rate = ifp->if_output_bw.eff_bw;
1628 	if (IFCQ_TBR_IS_ENABLED(ifq)) {
1629 		u_int64_t tbr_rate = ifq->ifcq_tbr.tbr_rate_raw;
1630 		VERIFY(tbr_rate > 0);
1631 		rate = MIN(rate, ifq->ifcq_tbr.tbr_rate_raw);
1632 	}
1633 
1634 	return rate;
1635 }
1636 
1637 u_int64_t
ifnet_input_linkrate(struct ifnet * ifp)1638 ifnet_input_linkrate(struct ifnet *ifp)
1639 {
1640 	return ifp->if_input_bw.eff_bw;
1641 }
1642 
1643 errno_t
ifnet_bandwidths(struct ifnet * ifp,struct if_bandwidths * output_bw,struct if_bandwidths * input_bw)1644 ifnet_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw,
1645     struct if_bandwidths *input_bw)
1646 {
1647 	if (ifp == NULL) {
1648 		return EINVAL;
1649 	}
1650 
1651 	if (output_bw != NULL) {
1652 		*output_bw = ifp->if_output_bw;
1653 	}
1654 	if (input_bw != NULL) {
1655 		*input_bw = ifp->if_input_bw;
1656 	}
1657 
1658 	return 0;
1659 }
1660 
1661 errno_t
ifnet_set_latencies(struct ifnet * ifp,struct if_latencies * output_lt,struct if_latencies * input_lt)1662 ifnet_set_latencies(struct ifnet *ifp, struct if_latencies *output_lt,
1663     struct if_latencies *input_lt)
1664 {
1665 	if (ifp == NULL) {
1666 		return EINVAL;
1667 	}
1668 
1669 	if (output_lt != NULL) {
1670 		(void) ifnet_set_output_latencies(ifp, output_lt, FALSE);
1671 	}
1672 
1673 	if (input_lt != NULL) {
1674 		(void) ifnet_set_input_latencies(ifp, input_lt);
1675 	}
1676 
1677 	return 0;
1678 }
1679 
1680 errno_t
ifnet_set_output_latencies(struct ifnet * ifp,struct if_latencies * lt,boolean_t locked)1681 ifnet_set_output_latencies(struct ifnet *ifp, struct if_latencies *lt,
1682     boolean_t locked)
1683 {
1684 	struct if_latencies old_lt;
1685 	struct ifclassq *ifq;
1686 
1687 	VERIFY(ifp != NULL && lt != NULL);
1688 
1689 	ifq = ifp->if_snd;
1690 	if (!locked) {
1691 		IFCQ_LOCK(ifq);
1692 	}
1693 	IFCQ_LOCK_ASSERT_HELD(ifq);
1694 
1695 	old_lt = ifp->if_output_lt;
1696 	if (lt->eff_lt != 0) {
1697 		ifp->if_output_lt.eff_lt = lt->eff_lt;
1698 	}
1699 	if (lt->max_lt != 0) {
1700 		ifp->if_output_lt.max_lt = lt->max_lt;
1701 	}
1702 	if (ifp->if_output_lt.eff_lt > ifp->if_output_lt.max_lt) {
1703 		ifp->if_output_lt.max_lt = ifp->if_output_lt.eff_lt;
1704 	} else if (ifp->if_output_lt.eff_lt == 0) {
1705 		ifp->if_output_lt.eff_lt = ifp->if_output_lt.max_lt;
1706 	}
1707 
1708 	/* Adjust queue parameters if needed */
1709 	if (old_lt.eff_lt != ifp->if_output_lt.eff_lt ||
1710 	    old_lt.max_lt != ifp->if_output_lt.max_lt) {
1711 		ifnet_update_sndq(ifq, CLASSQ_EV_LINK_LATENCY);
1712 	}
1713 
1714 	if (!locked) {
1715 		IFCQ_UNLOCK(ifq);
1716 	}
1717 
1718 	return 0;
1719 }
1720 
1721 errno_t
ifnet_set_input_latencies(struct ifnet * ifp,struct if_latencies * lt)1722 ifnet_set_input_latencies(struct ifnet *ifp, struct if_latencies *lt)
1723 {
1724 	struct if_latencies old_lt;
1725 
1726 	VERIFY(ifp != NULL && lt != NULL);
1727 
1728 	old_lt = ifp->if_input_lt;
1729 	if (lt->eff_lt != 0) {
1730 		ifp->if_input_lt.eff_lt = lt->eff_lt;
1731 	}
1732 	if (lt->max_lt != 0) {
1733 		ifp->if_input_lt.max_lt = lt->max_lt;
1734 	}
1735 	if (ifp->if_input_lt.eff_lt > ifp->if_input_lt.max_lt) {
1736 		ifp->if_input_lt.max_lt = ifp->if_input_lt.eff_lt;
1737 	} else if (ifp->if_input_lt.eff_lt == 0) {
1738 		ifp->if_input_lt.eff_lt = ifp->if_input_lt.max_lt;
1739 	}
1740 
1741 	if (old_lt.eff_lt != ifp->if_input_lt.eff_lt ||
1742 	    old_lt.max_lt != ifp->if_input_lt.max_lt) {
1743 		ifnet_update_rcv(ifp, CLASSQ_EV_LINK_LATENCY);
1744 	}
1745 
1746 	return 0;
1747 }
1748 
1749 errno_t
ifnet_latencies(struct ifnet * ifp,struct if_latencies * output_lt,struct if_latencies * input_lt)1750 ifnet_latencies(struct ifnet *ifp, struct if_latencies *output_lt,
1751     struct if_latencies *input_lt)
1752 {
1753 	if (ifp == NULL) {
1754 		return EINVAL;
1755 	}
1756 
1757 	if (output_lt != NULL) {
1758 		*output_lt = ifp->if_output_lt;
1759 	}
1760 	if (input_lt != NULL) {
1761 		*input_lt = ifp->if_input_lt;
1762 	}
1763 
1764 	return 0;
1765 }
1766 
1767 errno_t
ifnet_set_poll_params(struct ifnet * ifp,struct ifnet_poll_params * p)1768 ifnet_set_poll_params(struct ifnet *ifp, struct ifnet_poll_params *p)
1769 {
1770 	errno_t err;
1771 
1772 	if (ifp == NULL) {
1773 		return EINVAL;
1774 	} else if (!ifnet_is_attached(ifp, 1)) {
1775 		return ENXIO;
1776 	}
1777 
1778 #if SKYWALK
1779 	if (SKYWALK_CAPABLE(ifp)) {
1780 		err = netif_rxpoll_set_params(ifp, p, FALSE);
1781 		ifnet_decr_iorefcnt(ifp);
1782 		return err;
1783 	}
1784 #endif /* SKYWALK */
1785 	err = dlil_rxpoll_set_params(ifp, p, FALSE);
1786 
1787 	/* Release the io ref count */
1788 	ifnet_decr_iorefcnt(ifp);
1789 
1790 	return err;
1791 }
1792 
1793 errno_t
ifnet_poll_params(struct ifnet * ifp,struct ifnet_poll_params * p)1794 ifnet_poll_params(struct ifnet *ifp, struct ifnet_poll_params *p)
1795 {
1796 	errno_t err;
1797 
1798 	if (ifp == NULL || p == NULL) {
1799 		return EINVAL;
1800 	} else if (!ifnet_is_attached(ifp, 1)) {
1801 		return ENXIO;
1802 	}
1803 
1804 	err = dlil_rxpoll_get_params(ifp, p);
1805 
1806 	/* Release the io ref count */
1807 	ifnet_decr_iorefcnt(ifp);
1808 
1809 	return err;
1810 }
1811 
1812 errno_t
ifnet_stat_increment(struct ifnet * ifp,const struct ifnet_stat_increment_param * s)1813 ifnet_stat_increment(struct ifnet *ifp,
1814     const struct ifnet_stat_increment_param *s)
1815 {
1816 	if (ifp == NULL) {
1817 		return EINVAL;
1818 	}
1819 
1820 	if (s->packets_in != 0) {
1821 		os_atomic_add(&ifp->if_data.ifi_ipackets, s->packets_in, relaxed);
1822 	}
1823 	if (s->bytes_in != 0) {
1824 		os_atomic_add(&ifp->if_data.ifi_ibytes, s->bytes_in, relaxed);
1825 	}
1826 	if (s->errors_in != 0) {
1827 		os_atomic_add(&ifp->if_data.ifi_ierrors, s->errors_in, relaxed);
1828 	}
1829 
1830 	if (s->packets_out != 0) {
1831 		os_atomic_add(&ifp->if_data.ifi_opackets, s->packets_out, relaxed);
1832 	}
1833 	if (s->bytes_out != 0) {
1834 		os_atomic_add(&ifp->if_data.ifi_obytes, s->bytes_out, relaxed);
1835 	}
1836 	if (s->errors_out != 0) {
1837 		os_atomic_add(&ifp->if_data.ifi_oerrors, s->errors_out, relaxed);
1838 	}
1839 
1840 	if (s->collisions != 0) {
1841 		os_atomic_add(&ifp->if_data.ifi_collisions, s->collisions, relaxed);
1842 	}
1843 	if (s->dropped != 0) {
1844 		os_atomic_add(&ifp->if_data.ifi_iqdrops, s->dropped, relaxed);
1845 	}
1846 
1847 	/* Touch the last change time. */
1848 	TOUCHLASTCHANGE(&ifp->if_lastchange);
1849 
1850 	if (ifp->if_data_threshold != 0) {
1851 		ifnet_notify_data_threshold(ifp);
1852 	}
1853 
1854 	return 0;
1855 }
1856 
1857 errno_t
ifnet_stat_increment_in(struct ifnet * ifp,u_int32_t packets_in,u_int32_t bytes_in,u_int32_t errors_in)1858 ifnet_stat_increment_in(struct ifnet *ifp, u_int32_t packets_in,
1859     u_int32_t bytes_in, u_int32_t errors_in)
1860 {
1861 	if (ifp == NULL) {
1862 		return EINVAL;
1863 	}
1864 
1865 	if (packets_in != 0) {
1866 		os_atomic_add(&ifp->if_data.ifi_ipackets, packets_in, relaxed);
1867 	}
1868 	if (bytes_in != 0) {
1869 		os_atomic_add(&ifp->if_data.ifi_ibytes, bytes_in, relaxed);
1870 	}
1871 	if (errors_in != 0) {
1872 		os_atomic_add(&ifp->if_data.ifi_ierrors, errors_in, relaxed);
1873 	}
1874 
1875 	TOUCHLASTCHANGE(&ifp->if_lastchange);
1876 
1877 	if (ifp->if_data_threshold != 0) {
1878 		ifnet_notify_data_threshold(ifp);
1879 	}
1880 
1881 	return 0;
1882 }
1883 
1884 errno_t
ifnet_stat_increment_out(struct ifnet * ifp,u_int32_t packets_out,u_int32_t bytes_out,u_int32_t errors_out)1885 ifnet_stat_increment_out(struct ifnet *ifp, u_int32_t packets_out,
1886     u_int32_t bytes_out, u_int32_t errors_out)
1887 {
1888 	if (ifp == NULL) {
1889 		return EINVAL;
1890 	}
1891 
1892 	if (packets_out != 0) {
1893 		os_atomic_add(&ifp->if_data.ifi_opackets, packets_out, relaxed);
1894 	}
1895 	if (bytes_out != 0) {
1896 		os_atomic_add(&ifp->if_data.ifi_obytes, bytes_out, relaxed);
1897 	}
1898 	if (errors_out != 0) {
1899 		os_atomic_add(&ifp->if_data.ifi_oerrors, errors_out, relaxed);
1900 	}
1901 
1902 	TOUCHLASTCHANGE(&ifp->if_lastchange);
1903 
1904 	if (ifp->if_data_threshold != 0) {
1905 		ifnet_notify_data_threshold(ifp);
1906 	}
1907 
1908 	return 0;
1909 }
1910 
1911 errno_t
ifnet_set_stat(struct ifnet * ifp,const struct ifnet_stats_param * s)1912 ifnet_set_stat(struct ifnet *ifp, const struct ifnet_stats_param *s)
1913 {
1914 	if (ifp == NULL) {
1915 		return EINVAL;
1916 	}
1917 
1918 	os_atomic_store(&ifp->if_data.ifi_ipackets, s->packets_in, release);
1919 	os_atomic_store(&ifp->if_data.ifi_ibytes, s->bytes_in, release);
1920 	os_atomic_store(&ifp->if_data.ifi_imcasts, s->multicasts_in, release);
1921 	os_atomic_store(&ifp->if_data.ifi_ierrors, s->errors_in, release);
1922 
1923 	os_atomic_store(&ifp->if_data.ifi_opackets, s->packets_out, release);
1924 	os_atomic_store(&ifp->if_data.ifi_obytes, s->bytes_out, release);
1925 	os_atomic_store(&ifp->if_data.ifi_omcasts, s->multicasts_out, release);
1926 	os_atomic_store(&ifp->if_data.ifi_oerrors, s->errors_out, release);
1927 
1928 	os_atomic_store(&ifp->if_data.ifi_collisions, s->collisions, release);
1929 	os_atomic_store(&ifp->if_data.ifi_iqdrops, s->dropped, release);
1930 	os_atomic_store(&ifp->if_data.ifi_noproto, s->no_protocol, release);
1931 
1932 	/* Touch the last change time. */
1933 	TOUCHLASTCHANGE(&ifp->if_lastchange);
1934 
1935 	if (ifp->if_data_threshold != 0) {
1936 		ifnet_notify_data_threshold(ifp);
1937 	}
1938 
1939 	return 0;
1940 }
1941 
1942 errno_t
ifnet_stat(struct ifnet * ifp,struct ifnet_stats_param * s)1943 ifnet_stat(struct ifnet *ifp, struct ifnet_stats_param *s)
1944 {
1945 	if (ifp == NULL) {
1946 		return EINVAL;
1947 	}
1948 
1949 	s->packets_in = os_atomic_load(&ifp->if_data.ifi_ipackets, relaxed);
1950 	s->bytes_in = os_atomic_load(&ifp->if_data.ifi_ibytes, relaxed);
1951 	s->multicasts_in = os_atomic_load(&ifp->if_data.ifi_imcasts, relaxed);
1952 	s->errors_in = os_atomic_load(&ifp->if_data.ifi_ierrors, relaxed);
1953 
1954 	s->packets_out = os_atomic_load(&ifp->if_data.ifi_opackets, relaxed);
1955 	s->bytes_out = os_atomic_load(&ifp->if_data.ifi_obytes, relaxed);
1956 	s->multicasts_out = os_atomic_load(&ifp->if_data.ifi_omcasts, relaxed);
1957 	s->errors_out = os_atomic_load(&ifp->if_data.ifi_oerrors, relaxed);
1958 
1959 	s->collisions = os_atomic_load(&ifp->if_data.ifi_collisions, relaxed);
1960 	s->dropped = os_atomic_load(&ifp->if_data.ifi_iqdrops, relaxed);
1961 	s->no_protocol = os_atomic_load(&ifp->if_data.ifi_noproto, relaxed);
1962 
1963 	if (ifp->if_data_threshold != 0) {
1964 		ifnet_notify_data_threshold(ifp);
1965 	}
1966 
1967 	return 0;
1968 }
1969 
1970 errno_t
ifnet_touch_lastchange(ifnet_t interface)1971 ifnet_touch_lastchange(ifnet_t interface)
1972 {
1973 	if (interface == NULL) {
1974 		return EINVAL;
1975 	}
1976 
1977 	TOUCHLASTCHANGE(&interface->if_lastchange);
1978 
1979 	return 0;
1980 }
1981 
1982 errno_t
ifnet_lastchange(ifnet_t interface,struct timeval * last_change)1983 ifnet_lastchange(ifnet_t interface, struct timeval *last_change)
1984 {
1985 	if (interface == NULL) {
1986 		return EINVAL;
1987 	}
1988 
1989 	*last_change = interface->if_data.ifi_lastchange;
1990 	/* Crude conversion from uptime to calendar time */
1991 	last_change->tv_sec += boottime_sec();
1992 
1993 	return 0;
1994 }
1995 
1996 errno_t
ifnet_touch_lastupdown(ifnet_t interface)1997 ifnet_touch_lastupdown(ifnet_t interface)
1998 {
1999 	if (interface == NULL) {
2000 		return EINVAL;
2001 	}
2002 
2003 	TOUCHLASTCHANGE(&interface->if_lastupdown);
2004 
2005 	return 0;
2006 }
2007 
2008 errno_t
ifnet_updown_delta(ifnet_t interface,struct timeval * updown_delta)2009 ifnet_updown_delta(ifnet_t interface, struct timeval *updown_delta)
2010 {
2011 	if (interface == NULL) {
2012 		return EINVAL;
2013 	}
2014 
2015 	/* Calculate the delta */
2016 	updown_delta->tv_sec = (time_t)net_uptime();
2017 	if (updown_delta->tv_sec > interface->if_data.ifi_lastupdown.tv_sec) {
2018 		updown_delta->tv_sec -= interface->if_data.ifi_lastupdown.tv_sec;
2019 	} else {
2020 		updown_delta->tv_sec = 0;
2021 	}
2022 	updown_delta->tv_usec = 0;
2023 
2024 	return 0;
2025 }
2026 
2027 errno_t
ifnet_get_address_list(ifnet_t interface,ifaddr_t ** addresses)2028 ifnet_get_address_list(ifnet_t interface, ifaddr_t **addresses)
2029 {
2030 	return addresses == NULL ? EINVAL :
2031 	       ifnet_get_address_list_family(interface, addresses, 0);
2032 }
2033 
2034 struct ifnet_addr_list {
2035 	SLIST_ENTRY(ifnet_addr_list)    ifal_le;
2036 	struct ifaddr                   *ifal_ifa;
2037 };
2038 
2039 errno_t
ifnet_get_address_list_family(ifnet_t interface,ifaddr_t ** addresses,sa_family_t family)2040 ifnet_get_address_list_family(ifnet_t interface, ifaddr_t **addresses,
2041     sa_family_t family)
2042 {
2043 	return ifnet_get_address_list_family_internal(interface, addresses,
2044 	           family, 0, Z_WAITOK, 0);
2045 }
2046 
2047 errno_t
ifnet_get_inuse_address_list(ifnet_t interface,ifaddr_t ** addresses)2048 ifnet_get_inuse_address_list(ifnet_t interface, ifaddr_t **addresses)
2049 {
2050 	return addresses == NULL ? EINVAL :
2051 	       ifnet_get_address_list_family_internal(interface, addresses,
2052 	           0, 0, Z_WAITOK, 1);
2053 }
2054 
2055 extern uint32_t tcp_find_anypcb_byaddr(struct ifaddr *ifa);
2056 
2057 extern uint32_t udp_find_anypcb_byaddr(struct ifaddr *ifa);
2058 
2059 __private_extern__ errno_t
ifnet_get_address_list_family_internal(ifnet_t interface,ifaddr_t ** addresses,sa_family_t family,int detached,int how,int return_inuse_addrs)2060 ifnet_get_address_list_family_internal(ifnet_t interface, ifaddr_t **addresses,
2061     sa_family_t family, int detached, int how, int return_inuse_addrs)
2062 {
2063 	SLIST_HEAD(, ifnet_addr_list) ifal_head;
2064 	struct ifnet_addr_list *ifal, *ifal_tmp;
2065 	struct ifnet *ifp;
2066 	int count = 0;
2067 	errno_t err = 0;
2068 	int usecount = 0;
2069 	int index = 0;
2070 
2071 	SLIST_INIT(&ifal_head);
2072 
2073 	if (addresses == NULL) {
2074 		err = EINVAL;
2075 		goto done;
2076 	}
2077 	*addresses = NULL;
2078 
2079 	if (detached) {
2080 		/*
2081 		 * Interface has been detached, so skip the lookup
2082 		 * at ifnet_head and go directly to inner loop.
2083 		 */
2084 		ifp = interface;
2085 		if (ifp == NULL) {
2086 			err = EINVAL;
2087 			goto done;
2088 		}
2089 		goto one;
2090 	}
2091 
2092 	ifnet_head_lock_shared();
2093 	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
2094 		if (interface != NULL && ifp != interface) {
2095 			continue;
2096 		}
2097 one:
2098 		ifnet_lock_shared(ifp);
2099 		if (interface == NULL || interface == ifp) {
2100 			struct ifaddr *ifa;
2101 			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
2102 				IFA_LOCK(ifa);
2103 				if (family != 0 &&
2104 				    ifa->ifa_addr->sa_family != family) {
2105 					IFA_UNLOCK(ifa);
2106 					continue;
2107 				}
2108 				ifal = kalloc_type(struct ifnet_addr_list, how);
2109 				if (ifal == NULL) {
2110 					IFA_UNLOCK(ifa);
2111 					ifnet_lock_done(ifp);
2112 					if (!detached) {
2113 						ifnet_head_done();
2114 					}
2115 					err = ENOMEM;
2116 					goto done;
2117 				}
2118 				ifal->ifal_ifa = ifa;
2119 				IFA_ADDREF_LOCKED(ifa);
2120 				SLIST_INSERT_HEAD(&ifal_head, ifal, ifal_le);
2121 				++count;
2122 				IFA_UNLOCK(ifa);
2123 			}
2124 		}
2125 		ifnet_lock_done(ifp);
2126 		if (detached) {
2127 			break;
2128 		}
2129 	}
2130 	if (!detached) {
2131 		ifnet_head_done();
2132 	}
2133 
2134 	if (count == 0) {
2135 		err = ENXIO;
2136 		goto done;
2137 	}
2138 
2139 	*addresses = kalloc_type(ifaddr_t, count + 1, how | Z_ZERO);
2140 	if (*addresses == NULL) {
2141 		err = ENOMEM;
2142 		goto done;
2143 	}
2144 
2145 done:
2146 	SLIST_FOREACH_SAFE(ifal, &ifal_head, ifal_le, ifal_tmp) {
2147 		SLIST_REMOVE(&ifal_head, ifal, ifnet_addr_list, ifal_le);
2148 		if (err == 0) {
2149 			if (return_inuse_addrs) {
2150 				usecount = tcp_find_anypcb_byaddr(ifal->ifal_ifa);
2151 				usecount += udp_find_anypcb_byaddr(ifal->ifal_ifa);
2152 				if (usecount) {
2153 					(*addresses)[index] = ifal->ifal_ifa;
2154 					index++;
2155 				} else {
2156 					IFA_REMREF(ifal->ifal_ifa);
2157 				}
2158 			} else {
2159 				(*addresses)[--count] = ifal->ifal_ifa;
2160 			}
2161 		} else {
2162 			IFA_REMREF(ifal->ifal_ifa);
2163 		}
2164 		kfree_type(struct ifnet_addr_list, ifal);
2165 	}
2166 
2167 	VERIFY(err == 0 || *addresses == NULL);
2168 	if ((err == 0) && (count) && ((*addresses)[0] == NULL)) {
2169 		VERIFY(return_inuse_addrs == 1);
2170 		kfree_type(ifaddr_t, count + 1, *addresses);
2171 		err = ENXIO;
2172 	}
2173 	return err;
2174 }
2175 
2176 void
ifnet_free_address_list(ifaddr_t * addresses)2177 ifnet_free_address_list(ifaddr_t *addresses)
2178 {
2179 	int i;
2180 
2181 	if (addresses == NULL) {
2182 		return;
2183 	}
2184 
2185 	for (i = 0; addresses[i] != NULL; i++) {
2186 		IFA_REMREF(addresses[i]);
2187 	}
2188 
2189 	kfree_type(ifaddr_t, i + 1, addresses);
2190 }
2191 
2192 void *
ifnet_lladdr(ifnet_t interface)2193 ifnet_lladdr(ifnet_t interface)
2194 {
2195 	struct ifaddr *ifa;
2196 	void *lladdr;
2197 
2198 	if (interface == NULL) {
2199 		return NULL;
2200 	}
2201 
2202 	/*
2203 	 * if_lladdr points to the permanent link address of
2204 	 * the interface and it never gets deallocated; internal
2205 	 * code should simply use IF_LLADDR() for performance.
2206 	 */
2207 	ifa = interface->if_lladdr;
2208 	IFA_LOCK_SPIN(ifa);
2209 	lladdr = LLADDR(SDL((void *)ifa->ifa_addr));
2210 	IFA_UNLOCK(ifa);
2211 
2212 	return lladdr;
2213 }
2214 
2215 errno_t
ifnet_llbroadcast_copy_bytes(ifnet_t interface,void * addr,size_t buffer_len,size_t * out_len)2216 ifnet_llbroadcast_copy_bytes(ifnet_t interface, void *addr, size_t buffer_len,
2217     size_t *out_len)
2218 {
2219 	if (interface == NULL || addr == NULL || out_len == NULL) {
2220 		return EINVAL;
2221 	}
2222 
2223 	*out_len = interface->if_broadcast.length;
2224 
2225 	if (buffer_len < interface->if_broadcast.length) {
2226 		return EMSGSIZE;
2227 	}
2228 
2229 	if (interface->if_broadcast.length == 0) {
2230 		return ENXIO;
2231 	}
2232 
2233 	if (interface->if_broadcast.length <=
2234 	    sizeof(interface->if_broadcast.u.buffer)) {
2235 		bcopy(interface->if_broadcast.u.buffer, addr,
2236 		    interface->if_broadcast.length);
2237 	} else {
2238 		bcopy(interface->if_broadcast.u.ptr, addr,
2239 		    interface->if_broadcast.length);
2240 	}
2241 
2242 	return 0;
2243 }
2244 
2245 static errno_t
ifnet_lladdr_copy_bytes_internal(ifnet_t interface,void * lladdr,size_t lladdr_len,kauth_cred_t * credp)2246 ifnet_lladdr_copy_bytes_internal(ifnet_t interface, void *lladdr,
2247     size_t lladdr_len, kauth_cred_t *credp)
2248 {
2249 	const u_int8_t *bytes;
2250 	size_t bytes_len;
2251 	struct ifaddr *ifa;
2252 	uint8_t sdlbuf[SOCK_MAXADDRLEN + 1];
2253 	errno_t error = 0;
2254 
2255 	/*
2256 	 * Make sure to accomodate the largest possible
2257 	 * size of SA(if_lladdr)->sa_len.
2258 	 */
2259 	_CASSERT(sizeof(sdlbuf) == (SOCK_MAXADDRLEN + 1));
2260 
2261 	if (interface == NULL || lladdr == NULL) {
2262 		return EINVAL;
2263 	}
2264 
2265 	ifa = interface->if_lladdr;
2266 	IFA_LOCK_SPIN(ifa);
2267 	bcopy(ifa->ifa_addr, &sdlbuf, SDL(ifa->ifa_addr)->sdl_len);
2268 	IFA_UNLOCK(ifa);
2269 
2270 	bytes = dlil_ifaddr_bytes(SDL(&sdlbuf), &bytes_len, credp);
2271 	if (bytes_len != lladdr_len) {
2272 		bzero(lladdr, lladdr_len);
2273 		error = EMSGSIZE;
2274 	} else {
2275 		bcopy(bytes, lladdr, bytes_len);
2276 	}
2277 
2278 	return error;
2279 }
2280 
2281 errno_t
ifnet_lladdr_copy_bytes(ifnet_t interface,void * lladdr,size_t length)2282 ifnet_lladdr_copy_bytes(ifnet_t interface, void *lladdr, size_t length)
2283 {
2284 	return ifnet_lladdr_copy_bytes_internal(interface, lladdr, length,
2285 	           NULL);
2286 }
2287 
2288 errno_t
ifnet_guarded_lladdr_copy_bytes(ifnet_t interface,void * lladdr,size_t length)2289 ifnet_guarded_lladdr_copy_bytes(ifnet_t interface, void *lladdr, size_t length)
2290 {
2291 #if CONFIG_MACF
2292 	kauth_cred_t cred;
2293 	net_thread_marks_t marks;
2294 #endif
2295 	kauth_cred_t *credp;
2296 	errno_t error;
2297 
2298 	credp = NULL;
2299 #if CONFIG_MACF
2300 	marks = net_thread_marks_push(NET_THREAD_CKREQ_LLADDR);
2301 	cred = kauth_cred_proc_ref(current_proc());
2302 	credp = &cred;
2303 #else
2304 	credp = NULL;
2305 #endif
2306 
2307 	error = ifnet_lladdr_copy_bytes_internal(interface, lladdr, length,
2308 	    credp);
2309 
2310 #if CONFIG_MACF
2311 	kauth_cred_unref(credp);
2312 	net_thread_marks_pop(marks);
2313 #endif
2314 
2315 	return error;
2316 }
2317 
2318 static errno_t
ifnet_set_lladdr_internal(ifnet_t interface,const void * lladdr,size_t lladdr_len,u_char new_type,int apply_type)2319 ifnet_set_lladdr_internal(ifnet_t interface, const void *lladdr,
2320     size_t lladdr_len, u_char new_type, int apply_type)
2321 {
2322 	struct ifaddr *ifa;
2323 	errno_t error = 0;
2324 
2325 	if (interface == NULL) {
2326 		return EINVAL;
2327 	}
2328 
2329 	ifnet_head_lock_shared();
2330 	ifnet_lock_exclusive(interface);
2331 	if (lladdr_len != 0 &&
2332 	    (lladdr_len != interface->if_addrlen || lladdr == 0)) {
2333 		ifnet_lock_done(interface);
2334 		ifnet_head_done();
2335 		return EINVAL;
2336 	}
2337 	ifa = ifnet_addrs[interface->if_index - 1];
2338 	if (ifa != NULL) {
2339 		struct sockaddr_dl *sdl;
2340 
2341 		IFA_LOCK_SPIN(ifa);
2342 		sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
2343 		if (lladdr_len != 0) {
2344 			bcopy(lladdr, LLADDR(sdl), lladdr_len);
2345 		} else {
2346 			bzero(LLADDR(sdl), interface->if_addrlen);
2347 		}
2348 		/* lladdr_len-check with if_addrlen makes sure it fits in u_char */
2349 		sdl->sdl_alen = (u_char)lladdr_len;
2350 
2351 		if (apply_type) {
2352 			sdl->sdl_type = new_type;
2353 		}
2354 		IFA_UNLOCK(ifa);
2355 	} else {
2356 		error = ENXIO;
2357 	}
2358 	ifnet_lock_done(interface);
2359 	ifnet_head_done();
2360 
2361 	/* Generate a kernel event */
2362 	if (error == 0) {
2363 		intf_event_enqueue_nwk_wq_entry(interface, NULL,
2364 		    INTF_EVENT_CODE_LLADDR_UPDATE);
2365 		dlil_post_msg(interface, KEV_DL_SUBCLASS,
2366 		    KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0, FALSE);
2367 	}
2368 
2369 	return error;
2370 }
2371 
2372 errno_t
ifnet_set_lladdr(ifnet_t interface,const void * lladdr,size_t lladdr_len)2373 ifnet_set_lladdr(ifnet_t interface, const void* lladdr, size_t lladdr_len)
2374 {
2375 	return ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0);
2376 }
2377 
2378 errno_t
ifnet_set_lladdr_and_type(ifnet_t interface,const void * lladdr,size_t lladdr_len,u_char type)2379 ifnet_set_lladdr_and_type(ifnet_t interface, const void* lladdr,
2380     size_t lladdr_len, u_char type)
2381 {
2382 	return ifnet_set_lladdr_internal(interface, lladdr,
2383 	           lladdr_len, type, 1);
2384 }
2385 
2386 errno_t
ifnet_add_multicast(ifnet_t interface,const struct sockaddr * maddr,ifmultiaddr_t * ifmap)2387 ifnet_add_multicast(ifnet_t interface, const struct sockaddr *maddr,
2388     ifmultiaddr_t *ifmap)
2389 {
2390 	if (interface == NULL || maddr == NULL) {
2391 		return EINVAL;
2392 	}
2393 
2394 	/* Don't let users screw up protocols' entries. */
2395 	switch (maddr->sa_family) {
2396 	case AF_LINK: {
2397 		const struct sockaddr_dl *sdl =
2398 		    (const struct sockaddr_dl *)(uintptr_t)maddr;
2399 		if (sdl->sdl_len < sizeof(struct sockaddr_dl) ||
2400 		    (sdl->sdl_nlen + sdl->sdl_alen + sdl->sdl_slen +
2401 		    offsetof(struct sockaddr_dl, sdl_data) > sdl->sdl_len)) {
2402 			return EINVAL;
2403 		}
2404 		break;
2405 	}
2406 	case AF_UNSPEC:
2407 		if (maddr->sa_len < ETHER_ADDR_LEN +
2408 		    offsetof(struct sockaddr, sa_data)) {
2409 			return EINVAL;
2410 		}
2411 		break;
2412 	default:
2413 		return EINVAL;
2414 	}
2415 
2416 	return if_addmulti_anon(interface, maddr, ifmap);
2417 }
2418 
2419 errno_t
ifnet_remove_multicast(ifmultiaddr_t ifma)2420 ifnet_remove_multicast(ifmultiaddr_t ifma)
2421 {
2422 	struct sockaddr *maddr;
2423 
2424 	if (ifma == NULL) {
2425 		return EINVAL;
2426 	}
2427 
2428 	maddr = ifma->ifma_addr;
2429 	/* Don't let users screw up protocols' entries. */
2430 	if (maddr->sa_family != AF_UNSPEC && maddr->sa_family != AF_LINK) {
2431 		return EINVAL;
2432 	}
2433 
2434 	return if_delmulti_anon(ifma->ifma_ifp, maddr);
2435 }
2436 
2437 errno_t
ifnet_get_multicast_list(ifnet_t ifp,ifmultiaddr_t ** addresses)2438 ifnet_get_multicast_list(ifnet_t ifp, ifmultiaddr_t **addresses)
2439 {
2440 	int count = 0;
2441 	int cmax = 0;
2442 	struct ifmultiaddr *addr;
2443 
2444 	if (ifp == NULL || addresses == NULL) {
2445 		return EINVAL;
2446 	}
2447 
2448 	ifnet_lock_shared(ifp);
2449 	LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) {
2450 		cmax++;
2451 	}
2452 
2453 	*addresses = kalloc_type(ifmultiaddr_t, cmax + 1, Z_WAITOK);
2454 	if (*addresses == NULL) {
2455 		ifnet_lock_done(ifp);
2456 		return ENOMEM;
2457 	}
2458 
2459 	LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) {
2460 		if (count + 1 > cmax) {
2461 			break;
2462 		}
2463 		(*addresses)[count] = (ifmultiaddr_t)addr;
2464 		ifmaddr_reference((*addresses)[count]);
2465 		count++;
2466 	}
2467 	(*addresses)[cmax] = NULL;
2468 	ifnet_lock_done(ifp);
2469 
2470 	return 0;
2471 }
2472 
2473 void
ifnet_free_multicast_list(ifmultiaddr_t * addresses)2474 ifnet_free_multicast_list(ifmultiaddr_t *addresses)
2475 {
2476 	int i;
2477 
2478 	if (addresses == NULL) {
2479 		return;
2480 	}
2481 
2482 	for (i = 0; addresses[i] != NULL; i++) {
2483 		ifmaddr_release(addresses[i]);
2484 	}
2485 
2486 	kfree_type(ifmultiaddr_t, i + 1, addresses);
2487 }
2488 
2489 errno_t
ifnet_find_by_name(const char * ifname,ifnet_t * ifpp)2490 ifnet_find_by_name(const char *ifname, ifnet_t *ifpp)
2491 {
2492 	struct ifnet *ifp;
2493 	size_t namelen;
2494 
2495 	if (ifname == NULL) {
2496 		return EINVAL;
2497 	}
2498 
2499 	namelen = strlen(ifname);
2500 
2501 	*ifpp = NULL;
2502 
2503 	ifnet_head_lock_shared();
2504 	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
2505 		struct ifaddr *ifa;
2506 		struct sockaddr_dl *ll_addr;
2507 
2508 		ifa = ifnet_addrs[ifp->if_index - 1];
2509 		if (ifa == NULL) {
2510 			continue;
2511 		}
2512 
2513 		IFA_LOCK(ifa);
2514 		ll_addr = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
2515 
2516 		if (namelen == ll_addr->sdl_nlen && strncmp(ll_addr->sdl_data,
2517 		    ifname, ll_addr->sdl_nlen) == 0) {
2518 			IFA_UNLOCK(ifa);
2519 			*ifpp = ifp;
2520 			ifnet_reference(*ifpp);
2521 			break;
2522 		}
2523 		IFA_UNLOCK(ifa);
2524 	}
2525 	ifnet_head_done();
2526 
2527 	return (ifp == NULL) ? ENXIO : 0;
2528 }
2529 
2530 errno_t
ifnet_list_get(ifnet_family_t family,ifnet_t ** list,u_int32_t * count)2531 ifnet_list_get(ifnet_family_t family, ifnet_t **list, u_int32_t *count)
2532 {
2533 	return ifnet_list_get_common(family, FALSE, list, count);
2534 }
2535 
2536 __private_extern__ errno_t
ifnet_list_get_all(ifnet_family_t family,ifnet_t ** list,u_int32_t * count)2537 ifnet_list_get_all(ifnet_family_t family, ifnet_t **list, u_int32_t *count)
2538 {
2539 	return ifnet_list_get_common(family, TRUE, list, count);
2540 }
2541 
2542 struct ifnet_list {
2543 	SLIST_ENTRY(ifnet_list) ifl_le;
2544 	struct ifnet            *ifl_ifp;
2545 };
2546 
2547 static errno_t
ifnet_list_get_common(ifnet_family_t family,boolean_t get_all,ifnet_t ** list,u_int32_t * count)2548 ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list,
2549     u_int32_t *count)
2550 {
2551 #pragma unused(get_all)
2552 	SLIST_HEAD(, ifnet_list) ifl_head;
2553 	struct ifnet_list *ifl, *ifl_tmp;
2554 	struct ifnet *ifp;
2555 	int cnt = 0;
2556 	errno_t err = 0;
2557 
2558 	SLIST_INIT(&ifl_head);
2559 
2560 	if (list == NULL || count == NULL) {
2561 		err = EINVAL;
2562 		goto done;
2563 	}
2564 	*count = 0;
2565 	*list = NULL;
2566 
2567 	ifnet_head_lock_shared();
2568 	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
2569 		if (family == IFNET_FAMILY_ANY || ifp->if_family == family) {
2570 			ifl = kalloc_type(struct ifnet_list, Z_NOWAIT);
2571 			if (ifl == NULL) {
2572 				ifnet_head_done();
2573 				err = ENOMEM;
2574 				goto done;
2575 			}
2576 			ifl->ifl_ifp = ifp;
2577 			ifnet_reference(ifp);
2578 			SLIST_INSERT_HEAD(&ifl_head, ifl, ifl_le);
2579 			++cnt;
2580 		}
2581 	}
2582 	ifnet_head_done();
2583 
2584 	if (cnt == 0) {
2585 		err = ENXIO;
2586 		goto done;
2587 	}
2588 
2589 	*list = kalloc_type(ifnet_t, cnt + 1, Z_WAITOK | Z_ZERO);
2590 	if (*list == NULL) {
2591 		err = ENOMEM;
2592 		goto done;
2593 	}
2594 	*count = cnt;
2595 
2596 done:
2597 	SLIST_FOREACH_SAFE(ifl, &ifl_head, ifl_le, ifl_tmp) {
2598 		SLIST_REMOVE(&ifl_head, ifl, ifnet_list, ifl_le);
2599 		if (err == 0) {
2600 			(*list)[--cnt] = ifl->ifl_ifp;
2601 		} else {
2602 			ifnet_release(ifl->ifl_ifp);
2603 		}
2604 		kfree_type(struct ifnet_list, ifl);
2605 	}
2606 
2607 	return err;
2608 }
2609 
2610 void
ifnet_list_free(ifnet_t * interfaces)2611 ifnet_list_free(ifnet_t *interfaces)
2612 {
2613 	int i;
2614 
2615 	if (interfaces == NULL) {
2616 		return;
2617 	}
2618 
2619 	for (i = 0; interfaces[i]; i++) {
2620 		ifnet_release(interfaces[i]);
2621 	}
2622 
2623 	kfree_type(ifnet_t, i + 1, interfaces);
2624 }
2625 
2626 /*************************************************************************/
2627 /* ifaddr_t accessors						*/
2628 /*************************************************************************/
2629 
2630 errno_t
ifaddr_reference(ifaddr_t ifa)2631 ifaddr_reference(ifaddr_t ifa)
2632 {
2633 	if (ifa == NULL) {
2634 		return EINVAL;
2635 	}
2636 
2637 	IFA_ADDREF(ifa);
2638 	return 0;
2639 }
2640 
2641 errno_t
ifaddr_release(ifaddr_t ifa)2642 ifaddr_release(ifaddr_t ifa)
2643 {
2644 	if (ifa == NULL) {
2645 		return EINVAL;
2646 	}
2647 
2648 	IFA_REMREF(ifa);
2649 	return 0;
2650 }
2651 
2652 sa_family_t
ifaddr_address_family(ifaddr_t ifa)2653 ifaddr_address_family(ifaddr_t ifa)
2654 {
2655 	sa_family_t family = 0;
2656 
2657 	if (ifa != NULL) {
2658 		IFA_LOCK_SPIN(ifa);
2659 		if (ifa->ifa_addr != NULL) {
2660 			family = ifa->ifa_addr->sa_family;
2661 		}
2662 		IFA_UNLOCK(ifa);
2663 	}
2664 	return family;
2665 }
2666 
2667 errno_t
ifaddr_address(ifaddr_t ifa,struct sockaddr * out_addr,u_int32_t addr_size)2668 ifaddr_address(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
2669 {
2670 	u_int32_t copylen;
2671 
2672 	if (ifa == NULL || out_addr == NULL) {
2673 		return EINVAL;
2674 	}
2675 
2676 	IFA_LOCK_SPIN(ifa);
2677 	if (ifa->ifa_addr == NULL) {
2678 		IFA_UNLOCK(ifa);
2679 		return ENOTSUP;
2680 	}
2681 
2682 	copylen = (addr_size >= ifa->ifa_addr->sa_len) ?
2683 	    ifa->ifa_addr->sa_len : addr_size;
2684 	bcopy(ifa->ifa_addr, out_addr, copylen);
2685 
2686 	if (ifa->ifa_addr->sa_len > addr_size) {
2687 		IFA_UNLOCK(ifa);
2688 		return EMSGSIZE;
2689 	}
2690 
2691 	IFA_UNLOCK(ifa);
2692 	return 0;
2693 }
2694 
2695 errno_t
ifaddr_dstaddress(ifaddr_t ifa,struct sockaddr * out_addr,u_int32_t addr_size)2696 ifaddr_dstaddress(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
2697 {
2698 	u_int32_t copylen;
2699 
2700 	if (ifa == NULL || out_addr == NULL) {
2701 		return EINVAL;
2702 	}
2703 
2704 	IFA_LOCK_SPIN(ifa);
2705 	if (ifa->ifa_dstaddr == NULL) {
2706 		IFA_UNLOCK(ifa);
2707 		return ENOTSUP;
2708 	}
2709 
2710 	copylen = (addr_size >= ifa->ifa_dstaddr->sa_len) ?
2711 	    ifa->ifa_dstaddr->sa_len : addr_size;
2712 	bcopy(ifa->ifa_dstaddr, out_addr, copylen);
2713 
2714 	if (ifa->ifa_dstaddr->sa_len > addr_size) {
2715 		IFA_UNLOCK(ifa);
2716 		return EMSGSIZE;
2717 	}
2718 
2719 	IFA_UNLOCK(ifa);
2720 	return 0;
2721 }
2722 
2723 errno_t
ifaddr_netmask(ifaddr_t ifa,struct sockaddr * out_addr,u_int32_t addr_size)2724 ifaddr_netmask(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
2725 {
2726 	u_int32_t copylen;
2727 
2728 	if (ifa == NULL || out_addr == NULL) {
2729 		return EINVAL;
2730 	}
2731 
2732 	IFA_LOCK_SPIN(ifa);
2733 	if (ifa->ifa_netmask == NULL) {
2734 		IFA_UNLOCK(ifa);
2735 		return ENOTSUP;
2736 	}
2737 
2738 	copylen = addr_size >= ifa->ifa_netmask->sa_len ?
2739 	    ifa->ifa_netmask->sa_len : addr_size;
2740 	bcopy(ifa->ifa_netmask, out_addr, copylen);
2741 
2742 	if (ifa->ifa_netmask->sa_len > addr_size) {
2743 		IFA_UNLOCK(ifa);
2744 		return EMSGSIZE;
2745 	}
2746 
2747 	IFA_UNLOCK(ifa);
2748 	return 0;
2749 }
2750 
2751 ifnet_t
ifaddr_ifnet(ifaddr_t ifa)2752 ifaddr_ifnet(ifaddr_t ifa)
2753 {
2754 	struct ifnet *ifp;
2755 
2756 	if (ifa == NULL) {
2757 		return NULL;
2758 	}
2759 
2760 	/* ifa_ifp is set once at creation time; it is never changed */
2761 	ifp = ifa->ifa_ifp;
2762 
2763 	return ifp;
2764 }
2765 
2766 ifaddr_t
ifaddr_withaddr(const struct sockaddr * address)2767 ifaddr_withaddr(const struct sockaddr *address)
2768 {
2769 	if (address == NULL) {
2770 		return NULL;
2771 	}
2772 
2773 	return ifa_ifwithaddr(address);
2774 }
2775 
2776 ifaddr_t
ifaddr_withdstaddr(const struct sockaddr * address)2777 ifaddr_withdstaddr(const struct sockaddr *address)
2778 {
2779 	if (address == NULL) {
2780 		return NULL;
2781 	}
2782 
2783 	return ifa_ifwithdstaddr(address);
2784 }
2785 
2786 ifaddr_t
ifaddr_withnet(const struct sockaddr * net)2787 ifaddr_withnet(const struct sockaddr *net)
2788 {
2789 	if (net == NULL) {
2790 		return NULL;
2791 	}
2792 
2793 	return ifa_ifwithnet(net);
2794 }
2795 
2796 ifaddr_t
ifaddr_withroute(int flags,const struct sockaddr * destination,const struct sockaddr * gateway)2797 ifaddr_withroute(int flags, const struct sockaddr *destination,
2798     const struct sockaddr *gateway)
2799 {
2800 	if (destination == NULL || gateway == NULL) {
2801 		return NULL;
2802 	}
2803 
2804 	return ifa_ifwithroute(flags, destination, gateway);
2805 }
2806 
2807 ifaddr_t
ifaddr_findbestforaddr(const struct sockaddr * addr,ifnet_t interface)2808 ifaddr_findbestforaddr(const struct sockaddr *addr, ifnet_t interface)
2809 {
2810 	if (addr == NULL || interface == NULL) {
2811 		return NULL;
2812 	}
2813 
2814 	return ifaof_ifpforaddr_select(addr, interface);
2815 }
2816 
2817 errno_t
ifmaddr_reference(ifmultiaddr_t ifmaddr)2818 ifmaddr_reference(ifmultiaddr_t ifmaddr)
2819 {
2820 	if (ifmaddr == NULL) {
2821 		return EINVAL;
2822 	}
2823 
2824 	IFMA_ADDREF(ifmaddr);
2825 	return 0;
2826 }
2827 
2828 errno_t
ifmaddr_release(ifmultiaddr_t ifmaddr)2829 ifmaddr_release(ifmultiaddr_t ifmaddr)
2830 {
2831 	if (ifmaddr == NULL) {
2832 		return EINVAL;
2833 	}
2834 
2835 	IFMA_REMREF(ifmaddr);
2836 	return 0;
2837 }
2838 
2839 errno_t
ifmaddr_address(ifmultiaddr_t ifma,struct sockaddr * out_addr,u_int32_t addr_size)2840 ifmaddr_address(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2841     u_int32_t addr_size)
2842 {
2843 	u_int32_t copylen;
2844 
2845 	if (ifma == NULL || out_addr == NULL) {
2846 		return EINVAL;
2847 	}
2848 
2849 	IFMA_LOCK(ifma);
2850 	if (ifma->ifma_addr == NULL) {
2851 		IFMA_UNLOCK(ifma);
2852 		return ENOTSUP;
2853 	}
2854 
2855 	copylen = (addr_size >= ifma->ifma_addr->sa_len ?
2856 	    ifma->ifma_addr->sa_len : addr_size);
2857 	bcopy(ifma->ifma_addr, out_addr, copylen);
2858 
2859 	if (ifma->ifma_addr->sa_len > addr_size) {
2860 		IFMA_UNLOCK(ifma);
2861 		return EMSGSIZE;
2862 	}
2863 	IFMA_UNLOCK(ifma);
2864 	return 0;
2865 }
2866 
2867 errno_t
ifmaddr_lladdress(ifmultiaddr_t ifma,struct sockaddr * out_addr,u_int32_t addr_size)2868 ifmaddr_lladdress(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2869     u_int32_t addr_size)
2870 {
2871 	struct ifmultiaddr *ifma_ll;
2872 
2873 	if (ifma == NULL || out_addr == NULL) {
2874 		return EINVAL;
2875 	}
2876 	if ((ifma_ll = ifma->ifma_ll) == NULL) {
2877 		return ENOTSUP;
2878 	}
2879 
2880 	return ifmaddr_address(ifma_ll, out_addr, addr_size);
2881 }
2882 
2883 ifnet_t
ifmaddr_ifnet(ifmultiaddr_t ifma)2884 ifmaddr_ifnet(ifmultiaddr_t ifma)
2885 {
2886 	return (ifma == NULL) ? NULL : ifma->ifma_ifp;
2887 }
2888 
2889 /**************************************************************************/
2890 /* interface cloner						*/
2891 /**************************************************************************/
2892 
2893 errno_t
ifnet_clone_attach(struct ifnet_clone_params * cloner_params,if_clone_t * ifcloner)2894 ifnet_clone_attach(struct ifnet_clone_params *cloner_params,
2895     if_clone_t *ifcloner)
2896 {
2897 	errno_t error = 0;
2898 	struct if_clone *ifc = NULL;
2899 	size_t namelen;
2900 
2901 	if (cloner_params == NULL || ifcloner == NULL ||
2902 	    cloner_params->ifc_name == NULL ||
2903 	    cloner_params->ifc_create == NULL ||
2904 	    cloner_params->ifc_destroy == NULL ||
2905 	    (namelen = strlen(cloner_params->ifc_name)) >= IFNAMSIZ) {
2906 		error = EINVAL;
2907 		goto fail;
2908 	}
2909 
2910 	if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) {
2911 		printf("%s: already a cloner for %s\n", __func__,
2912 		    cloner_params->ifc_name);
2913 		error = EEXIST;
2914 		goto fail;
2915 	}
2916 
2917 	ifc = kalloc_type(struct if_clone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2918 	strlcpy(ifc->ifc_name, cloner_params->ifc_name, IFNAMSIZ + 1);
2919 	ifc->ifc_namelen = (uint8_t)namelen;
2920 	ifc->ifc_maxunit = IF_MAXUNIT;
2921 	ifc->ifc_create = cloner_params->ifc_create;
2922 	ifc->ifc_destroy = cloner_params->ifc_destroy;
2923 
2924 	error = if_clone_attach(ifc);
2925 	if (error != 0) {
2926 		printf("%s: if_clone_attach failed %d\n", __func__, error);
2927 		goto fail;
2928 	}
2929 	*ifcloner = ifc;
2930 
2931 	return 0;
2932 fail:
2933 	if (ifc != NULL) {
2934 		kfree_type(struct if_clone, ifc);
2935 	}
2936 	return error;
2937 }
2938 
2939 errno_t
ifnet_clone_detach(if_clone_t ifcloner)2940 ifnet_clone_detach(if_clone_t ifcloner)
2941 {
2942 	errno_t error = 0;
2943 	struct if_clone *ifc = ifcloner;
2944 
2945 	if (ifc == NULL) {
2946 		return EINVAL;
2947 	}
2948 
2949 	if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) {
2950 		printf("%s: no cloner for %s\n", __func__, ifc->ifc_name);
2951 		error = EINVAL;
2952 		goto fail;
2953 	}
2954 
2955 	if_clone_detach(ifc);
2956 
2957 	kfree_type(struct if_clone, ifc);
2958 
2959 fail:
2960 	return error;
2961 }
2962 
2963 /**************************************************************************/
2964 /* misc							*/
2965 /**************************************************************************/
2966 
2967 static errno_t
ifnet_get_local_ports_extended_inner(ifnet_t ifp,protocol_family_t protocol,u_int32_t flags,u_int8_t * bitfield)2968 ifnet_get_local_ports_extended_inner(ifnet_t ifp, protocol_family_t protocol,
2969     u_int32_t flags, u_int8_t *bitfield)
2970 {
2971 	u_int32_t ifindex;
2972 
2973 	/* no point in continuing if no address is assigned */
2974 	if (ifp != NULL && TAILQ_EMPTY(&ifp->if_addrhead)) {
2975 		return 0;
2976 	}
2977 
2978 	if_ports_used_update_wakeuuid(ifp);
2979 
2980 #if SKYWALK
2981 	if (netns_is_enabled()) {
2982 		netns_get_local_ports(ifp, protocol, flags, bitfield);
2983 	}
2984 #endif /* SKYWALK */
2985 
2986 	ifindex = (ifp != NULL) ? ifp->if_index : 0;
2987 
2988 	if (!(flags & IFNET_GET_LOCAL_PORTS_TCPONLY)) {
2989 		udp_get_ports_used(ifp, protocol, flags,
2990 		    bitfield);
2991 	}
2992 
2993 	if (!(flags & IFNET_GET_LOCAL_PORTS_UDPONLY)) {
2994 		tcp_get_ports_used(ifp, protocol, flags,
2995 		    bitfield);
2996 	}
2997 
2998 	return 0;
2999 }
3000 
3001 errno_t
ifnet_get_local_ports_extended(ifnet_t ifp,protocol_family_t protocol,u_int32_t flags,u_int8_t * bitfield)3002 ifnet_get_local_ports_extended(ifnet_t ifp, protocol_family_t protocol,
3003     u_int32_t flags, u_int8_t *bitfield)
3004 {
3005 	ifnet_t parent_ifp = NULL;
3006 
3007 	if (bitfield == NULL) {
3008 		return EINVAL;
3009 	}
3010 
3011 	switch (protocol) {
3012 	case PF_UNSPEC:
3013 	case PF_INET:
3014 	case PF_INET6:
3015 		break;
3016 	default:
3017 		return EINVAL;
3018 	}
3019 
3020 	/* bit string is long enough to hold 16-bit port values */
3021 	bzero(bitfield, bitstr_size(IP_PORTRANGE_SIZE));
3022 
3023 	ifnet_get_local_ports_extended_inner(ifp, protocol, flags, bitfield);
3024 
3025 	/* get local ports for parent interface */
3026 	if (ifp != NULL && ifnet_get_delegate_parent(ifp, &parent_ifp) == 0) {
3027 		ifnet_get_local_ports_extended_inner(parent_ifp, protocol,
3028 		    flags, bitfield);
3029 		ifnet_release_delegate_parent(ifp);
3030 	}
3031 
3032 	return 0;
3033 }
3034 
3035 errno_t
ifnet_get_local_ports(ifnet_t ifp,u_int8_t * bitfield)3036 ifnet_get_local_ports(ifnet_t ifp, u_int8_t *bitfield)
3037 {
3038 	u_int32_t flags = IFNET_GET_LOCAL_PORTS_WILDCARDOK;
3039 	return ifnet_get_local_ports_extended(ifp, PF_UNSPEC, flags,
3040 	           bitfield);
3041 }
3042 
3043 errno_t
ifnet_notice_node_presence(ifnet_t ifp,struct sockaddr * sa,int32_t rssi,int lqm,int npm,u_int8_t srvinfo[48])3044 ifnet_notice_node_presence(ifnet_t ifp, struct sockaddr *sa, int32_t rssi,
3045     int lqm, int npm, u_int8_t srvinfo[48])
3046 {
3047 	if (ifp == NULL || sa == NULL || srvinfo == NULL) {
3048 		return EINVAL;
3049 	}
3050 	if (sa->sa_len > sizeof(struct sockaddr_storage)) {
3051 		return EINVAL;
3052 	}
3053 	if (sa->sa_family != AF_LINK && sa->sa_family != AF_INET6) {
3054 		return EINVAL;
3055 	}
3056 
3057 	return dlil_node_present(ifp, sa, rssi, lqm, npm, srvinfo);
3058 }
3059 
3060 errno_t
ifnet_notice_node_presence_v2(ifnet_t ifp,struct sockaddr * sa,struct sockaddr_dl * sdl,int32_t rssi,int lqm,int npm,u_int8_t srvinfo[48])3061 ifnet_notice_node_presence_v2(ifnet_t ifp, struct sockaddr *sa, struct sockaddr_dl *sdl,
3062     int32_t rssi, int lqm, int npm, u_int8_t srvinfo[48])
3063 {
3064 	/* Support older version if sdl is NULL */
3065 	if (sdl == NULL) {
3066 		return ifnet_notice_node_presence(ifp, sa, rssi, lqm, npm, srvinfo);
3067 	}
3068 
3069 	if (ifp == NULL || sa == NULL || srvinfo == NULL) {
3070 		return EINVAL;
3071 	}
3072 	if (sa->sa_len > sizeof(struct sockaddr_storage)) {
3073 		return EINVAL;
3074 	}
3075 
3076 	if (sa->sa_family != AF_INET6) {
3077 		return EINVAL;
3078 	}
3079 
3080 	if (sdl->sdl_family != AF_LINK) {
3081 		return EINVAL;
3082 	}
3083 
3084 	return dlil_node_present_v2(ifp, sa, sdl, rssi, lqm, npm, srvinfo);
3085 }
3086 
3087 errno_t
ifnet_notice_node_absence(ifnet_t ifp,struct sockaddr * sa)3088 ifnet_notice_node_absence(ifnet_t ifp, struct sockaddr *sa)
3089 {
3090 	if (ifp == NULL || sa == NULL) {
3091 		return EINVAL;
3092 	}
3093 	if (sa->sa_len > sizeof(struct sockaddr_storage)) {
3094 		return EINVAL;
3095 	}
3096 	if (sa->sa_family != AF_LINK && sa->sa_family != AF_INET6) {
3097 		return EINVAL;
3098 	}
3099 
3100 	dlil_node_absent(ifp, sa);
3101 	return 0;
3102 }
3103 
3104 errno_t
ifnet_notice_primary_elected(ifnet_t ifp)3105 ifnet_notice_primary_elected(ifnet_t ifp)
3106 {
3107 	if (ifp == NULL) {
3108 		return EINVAL;
3109 	}
3110 
3111 	dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_PRIMARY_ELECTED, NULL, 0, FALSE);
3112 	return 0;
3113 }
3114 
3115 errno_t
ifnet_tx_compl_status(ifnet_t ifp,mbuf_t m,tx_compl_val_t val)3116 ifnet_tx_compl_status(ifnet_t ifp, mbuf_t m, tx_compl_val_t val)
3117 {
3118 #pragma unused(val)
3119 
3120 	m_do_tx_compl_callback(m, ifp);
3121 
3122 	return 0;
3123 }
3124 
3125 errno_t
ifnet_tx_compl(ifnet_t ifp,mbuf_t m)3126 ifnet_tx_compl(ifnet_t ifp, mbuf_t m)
3127 {
3128 	m_do_tx_compl_callback(m, ifp);
3129 
3130 	return 0;
3131 }
3132 
3133 errno_t
ifnet_report_issues(ifnet_t ifp,u_int8_t modid[IFNET_MODIDLEN],u_int8_t info[IFNET_MODARGLEN])3134 ifnet_report_issues(ifnet_t ifp, u_int8_t modid[IFNET_MODIDLEN],
3135     u_int8_t info[IFNET_MODARGLEN])
3136 {
3137 	if (ifp == NULL || modid == NULL) {
3138 		return EINVAL;
3139 	}
3140 
3141 	dlil_report_issues(ifp, modid, info);
3142 	return 0;
3143 }
3144 
3145 errno_t
ifnet_set_delegate(ifnet_t ifp,ifnet_t delegated_ifp)3146 ifnet_set_delegate(ifnet_t ifp, ifnet_t delegated_ifp)
3147 {
3148 	ifnet_t odifp = NULL;
3149 
3150 	if (ifp == NULL) {
3151 		return EINVAL;
3152 	} else if (!ifnet_is_attached(ifp, 1)) {
3153 		return ENXIO;
3154 	}
3155 
3156 	ifnet_lock_exclusive(ifp);
3157 	odifp = ifp->if_delegated.ifp;
3158 	if (odifp != NULL && odifp == delegated_ifp) {
3159 		/* delegate info is unchanged; nothing more to do */
3160 		ifnet_lock_done(ifp);
3161 		goto done;
3162 	}
3163 	// Test if this delegate interface would cause a loop
3164 	ifnet_t delegate_check_ifp = delegated_ifp;
3165 	while (delegate_check_ifp != NULL) {
3166 		if (delegate_check_ifp == ifp) {
3167 			printf("%s: delegating to %s would cause a loop\n",
3168 			    ifp->if_xname, delegated_ifp->if_xname);
3169 			ifnet_lock_done(ifp);
3170 			goto done;
3171 		}
3172 		delegate_check_ifp = delegate_check_ifp->if_delegated.ifp;
3173 	}
3174 	bzero(&ifp->if_delegated, sizeof(ifp->if_delegated));
3175 	if (delegated_ifp != NULL && ifp != delegated_ifp) {
3176 		uint32_t        set_eflags;
3177 
3178 		ifp->if_delegated.ifp = delegated_ifp;
3179 		ifnet_reference(delegated_ifp);
3180 		ifp->if_delegated.type = delegated_ifp->if_type;
3181 		ifp->if_delegated.family = delegated_ifp->if_family;
3182 		ifp->if_delegated.subfamily = delegated_ifp->if_subfamily;
3183 		ifp->if_delegated.expensive =
3184 		    delegated_ifp->if_eflags & IFEF_EXPENSIVE ? 1 : 0;
3185 		ifp->if_delegated.constrained =
3186 		    delegated_ifp->if_xflags & IFXF_CONSTRAINED ? 1 : 0;
3187 
3188 		/*
3189 		 * Propogate flags related to ECN from delegated interface
3190 		 */
3191 		if_clear_eflags(ifp, IFEF_ECN_ENABLE | IFEF_ECN_DISABLE);
3192 		set_eflags = (delegated_ifp->if_eflags &
3193 		    (IFEF_ECN_ENABLE | IFEF_ECN_DISABLE));
3194 		if_set_eflags(ifp, set_eflags);
3195 		printf("%s: is now delegating %s (type 0x%x, family %u, "
3196 		    "sub-family %u)\n", ifp->if_xname, delegated_ifp->if_xname,
3197 		    delegated_ifp->if_type, delegated_ifp->if_family,
3198 		    delegated_ifp->if_subfamily);
3199 	}
3200 
3201 	ifnet_lock_done(ifp);
3202 
3203 	if (odifp != NULL) {
3204 		if (odifp != delegated_ifp) {
3205 			printf("%s: is no longer delegating %s\n",
3206 			    ifp->if_xname, odifp->if_xname);
3207 		}
3208 		ifnet_release(odifp);
3209 	}
3210 
3211 	/* Generate a kernel event */
3212 	dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_IFDELEGATE_CHANGED, NULL, 0, FALSE);
3213 
3214 done:
3215 	/* Release the io ref count */
3216 	ifnet_decr_iorefcnt(ifp);
3217 
3218 	return 0;
3219 }
3220 
3221 errno_t
ifnet_get_delegate(ifnet_t ifp,ifnet_t * pdelegated_ifp)3222 ifnet_get_delegate(ifnet_t ifp, ifnet_t *pdelegated_ifp)
3223 {
3224 	if (ifp == NULL || pdelegated_ifp == NULL) {
3225 		return EINVAL;
3226 	} else if (!ifnet_is_attached(ifp, 1)) {
3227 		return ENXIO;
3228 	}
3229 
3230 	ifnet_lock_shared(ifp);
3231 	if (ifp->if_delegated.ifp != NULL) {
3232 		ifnet_reference(ifp->if_delegated.ifp);
3233 	}
3234 	*pdelegated_ifp = ifp->if_delegated.ifp;
3235 	ifnet_lock_done(ifp);
3236 
3237 	/* Release the io ref count */
3238 	ifnet_decr_iorefcnt(ifp);
3239 
3240 	return 0;
3241 }
3242 
3243 errno_t
ifnet_get_keepalive_offload_frames(ifnet_t ifp,struct ifnet_keepalive_offload_frame * frames_array,u_int32_t frames_array_count,size_t frame_data_offset,u_int32_t * used_frames_count)3244 ifnet_get_keepalive_offload_frames(ifnet_t ifp,
3245     struct ifnet_keepalive_offload_frame *frames_array,
3246     u_int32_t frames_array_count, size_t frame_data_offset,
3247     u_int32_t *used_frames_count)
3248 {
3249 	u_int32_t i;
3250 
3251 	if (frames_array == NULL || used_frames_count == NULL ||
3252 	    frame_data_offset >= IFNET_KEEPALIVE_OFFLOAD_FRAME_DATA_SIZE) {
3253 		return EINVAL;
3254 	}
3255 
3256 	/* frame_data_offset should be 32-bit aligned */
3257 	if (P2ROUNDUP(frame_data_offset, sizeof(u_int32_t)) !=
3258 	    frame_data_offset) {
3259 		return EINVAL;
3260 	}
3261 
3262 	*used_frames_count = 0;
3263 	if (frames_array_count == 0) {
3264 		return 0;
3265 	}
3266 
3267 	/* Keep-alive offload not required for CLAT interface */
3268 	if (IS_INTF_CLAT46(ifp)) {
3269 		return 0;
3270 	}
3271 
3272 	for (i = 0; i < frames_array_count; i++) {
3273 		struct ifnet_keepalive_offload_frame *frame = frames_array + i;
3274 
3275 		bzero(frame, sizeof(struct ifnet_keepalive_offload_frame));
3276 	}
3277 
3278 	/* First collect IPsec related keep-alive frames */
3279 	*used_frames_count = key_fill_offload_frames_for_savs(ifp,
3280 	    frames_array, frames_array_count, frame_data_offset);
3281 
3282 	/* If there is more room, collect other UDP keep-alive frames */
3283 	if (*used_frames_count < frames_array_count) {
3284 		udp_fill_keepalive_offload_frames(ifp, frames_array,
3285 		    frames_array_count, frame_data_offset,
3286 		    used_frames_count);
3287 	}
3288 
3289 	/* If there is more room, collect other TCP keep-alive frames */
3290 	if (*used_frames_count < frames_array_count) {
3291 		tcp_fill_keepalive_offload_frames(ifp, frames_array,
3292 		    frames_array_count, frame_data_offset,
3293 		    used_frames_count);
3294 	}
3295 
3296 	VERIFY(*used_frames_count <= frames_array_count);
3297 
3298 	return 0;
3299 }
3300 
3301 errno_t
ifnet_notify_tcp_keepalive_offload_timeout(ifnet_t ifp,struct ifnet_keepalive_offload_frame * frame)3302 ifnet_notify_tcp_keepalive_offload_timeout(ifnet_t ifp,
3303     struct ifnet_keepalive_offload_frame *frame)
3304 {
3305 	errno_t error = 0;
3306 
3307 	if (ifp == NULL || frame == NULL) {
3308 		return EINVAL;
3309 	}
3310 
3311 	if (frame->type != IFNET_KEEPALIVE_OFFLOAD_FRAME_TCP) {
3312 		return EINVAL;
3313 	}
3314 	if (frame->ether_type != IFNET_KEEPALIVE_OFFLOAD_FRAME_ETHERTYPE_IPV4 &&
3315 	    frame->ether_type != IFNET_KEEPALIVE_OFFLOAD_FRAME_ETHERTYPE_IPV6) {
3316 		return EINVAL;
3317 	}
3318 	if (frame->local_port == 0 || frame->remote_port == 0) {
3319 		return EINVAL;
3320 	}
3321 
3322 	error = tcp_notify_kao_timeout(ifp, frame);
3323 
3324 	return error;
3325 }
3326 
3327 errno_t
ifnet_link_status_report(ifnet_t ifp,const void * buffer,size_t buffer_len)3328 ifnet_link_status_report(ifnet_t ifp, const void *buffer,
3329     size_t buffer_len)
3330 {
3331 	struct if_link_status *ifsr;
3332 	errno_t err = 0;
3333 
3334 	if (ifp == NULL || buffer == NULL || buffer_len == 0) {
3335 		return EINVAL;
3336 	}
3337 
3338 	ifnet_lock_shared(ifp);
3339 
3340 	/*
3341 	 * Make sure that the interface is attached but there is no need
3342 	 * to take a reference because this call is coming from the driver.
3343 	 */
3344 	if (!ifnet_is_attached(ifp, 0)) {
3345 		ifnet_lock_done(ifp);
3346 		return ENXIO;
3347 	}
3348 
3349 	lck_rw_lock_exclusive(&ifp->if_link_status_lock);
3350 
3351 	/*
3352 	 * If this is the first status report then allocate memory
3353 	 * to store it.
3354 	 */
3355 	if (ifp->if_link_status == NULL) {
3356 		ifp->if_link_status = kalloc_type(struct if_link_status, Z_ZERO);
3357 		if (ifp->if_link_status == NULL) {
3358 			err = ENOMEM;
3359 			goto done;
3360 		}
3361 	}
3362 
3363 	ifsr = __DECONST(struct if_link_status *, buffer);
3364 
3365 	if (ifp->if_type == IFT_CELLULAR) {
3366 		struct if_cellular_status_v1 *if_cell_sr, *new_cell_sr;
3367 		/*
3368 		 * Currently we have a single version -- if it does
3369 		 * not match, just return.
3370 		 */
3371 		if (ifsr->ifsr_version !=
3372 		    IF_CELLULAR_STATUS_REPORT_CURRENT_VERSION) {
3373 			err = ENOTSUP;
3374 			goto done;
3375 		}
3376 
3377 		if (ifsr->ifsr_len != sizeof(*if_cell_sr)) {
3378 			err = EINVAL;
3379 			goto done;
3380 		}
3381 
3382 		if_cell_sr =
3383 		    &ifp->if_link_status->ifsr_u.ifsr_cell.if_cell_u.if_status_v1;
3384 		new_cell_sr = &ifsr->ifsr_u.ifsr_cell.if_cell_u.if_status_v1;
3385 		/* Check if we need to act on any new notifications */
3386 		if ((new_cell_sr->valid_bitmask &
3387 		    IF_CELL_UL_MSS_RECOMMENDED_VALID) &&
3388 		    new_cell_sr->mss_recommended !=
3389 		    if_cell_sr->mss_recommended) {
3390 			os_atomic_or(&tcbinfo.ipi_flags, INPCBINFO_UPDATE_MSS, relaxed);
3391 			inpcb_timer_sched(&tcbinfo, INPCB_TIMER_FAST);
3392 #if NECP
3393 			necp_update_all_clients();
3394 #endif
3395 		}
3396 
3397 		/* Finally copy the new information */
3398 		ifp->if_link_status->ifsr_version = ifsr->ifsr_version;
3399 		ifp->if_link_status->ifsr_len = ifsr->ifsr_len;
3400 		if_cell_sr->valid_bitmask = 0;
3401 		bcopy(new_cell_sr, if_cell_sr, sizeof(*if_cell_sr));
3402 	} else if (IFNET_IS_WIFI(ifp)) {
3403 		struct if_wifi_status_v1 *if_wifi_sr, *new_wifi_sr;
3404 
3405 		/* Check version */
3406 		if (ifsr->ifsr_version !=
3407 		    IF_WIFI_STATUS_REPORT_CURRENT_VERSION) {
3408 			err = ENOTSUP;
3409 			goto done;
3410 		}
3411 
3412 		if (ifsr->ifsr_len != sizeof(*if_wifi_sr)) {
3413 			err = EINVAL;
3414 			goto done;
3415 		}
3416 
3417 		if_wifi_sr =
3418 		    &ifp->if_link_status->ifsr_u.ifsr_wifi.if_wifi_u.if_status_v1;
3419 		new_wifi_sr =
3420 		    &ifsr->ifsr_u.ifsr_wifi.if_wifi_u.if_status_v1;
3421 		ifp->if_link_status->ifsr_version = ifsr->ifsr_version;
3422 		ifp->if_link_status->ifsr_len = ifsr->ifsr_len;
3423 		if_wifi_sr->valid_bitmask = 0;
3424 		bcopy(new_wifi_sr, if_wifi_sr, sizeof(*if_wifi_sr));
3425 
3426 		/*
3427 		 * Update the bandwidth values if we got recent values
3428 		 * reported through the other KPI.
3429 		 */
3430 		if (!(new_wifi_sr->valid_bitmask &
3431 		    IF_WIFI_UL_MAX_BANDWIDTH_VALID) &&
3432 		    ifp->if_output_bw.max_bw > 0) {
3433 			if_wifi_sr->valid_bitmask |=
3434 			    IF_WIFI_UL_MAX_BANDWIDTH_VALID;
3435 			if_wifi_sr->ul_max_bandwidth =
3436 			    ifp->if_output_bw.max_bw > UINT32_MAX ?
3437 			    UINT32_MAX :
3438 			    (uint32_t)ifp->if_output_bw.max_bw;
3439 		}
3440 		if (!(new_wifi_sr->valid_bitmask &
3441 		    IF_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID) &&
3442 		    ifp->if_output_bw.eff_bw > 0) {
3443 			if_wifi_sr->valid_bitmask |=
3444 			    IF_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID;
3445 			if_wifi_sr->ul_effective_bandwidth =
3446 			    ifp->if_output_bw.eff_bw > UINT32_MAX ?
3447 			    UINT32_MAX :
3448 			    (uint32_t)ifp->if_output_bw.eff_bw;
3449 		}
3450 		if (!(new_wifi_sr->valid_bitmask &
3451 		    IF_WIFI_DL_MAX_BANDWIDTH_VALID) &&
3452 		    ifp->if_input_bw.max_bw > 0) {
3453 			if_wifi_sr->valid_bitmask |=
3454 			    IF_WIFI_DL_MAX_BANDWIDTH_VALID;
3455 			if_wifi_sr->dl_max_bandwidth =
3456 			    ifp->if_input_bw.max_bw > UINT32_MAX ?
3457 			    UINT32_MAX :
3458 			    (uint32_t)ifp->if_input_bw.max_bw;
3459 		}
3460 		if (!(new_wifi_sr->valid_bitmask &
3461 		    IF_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID) &&
3462 		    ifp->if_input_bw.eff_bw > 0) {
3463 			if_wifi_sr->valid_bitmask |=
3464 			    IF_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID;
3465 			if_wifi_sr->dl_effective_bandwidth =
3466 			    ifp->if_input_bw.eff_bw > UINT32_MAX ?
3467 			    UINT32_MAX :
3468 			    (uint32_t)ifp->if_input_bw.eff_bw;
3469 		}
3470 	}
3471 
3472 done:
3473 	lck_rw_done(&ifp->if_link_status_lock);
3474 	ifnet_lock_done(ifp);
3475 	return err;
3476 }
3477 
3478 /*************************************************************************/
3479 /* Fastlane QoS Ca						*/
3480 /*************************************************************************/
3481 
3482 errno_t
ifnet_set_fastlane_capable(ifnet_t interface,boolean_t capable)3483 ifnet_set_fastlane_capable(ifnet_t interface, boolean_t capable)
3484 {
3485 	if (interface == NULL) {
3486 		return EINVAL;
3487 	}
3488 
3489 	if_set_qosmarking_mode(interface,
3490 	    capable ? IFRTYPE_QOSMARKING_FASTLANE : IFRTYPE_QOSMARKING_MODE_NONE);
3491 
3492 	return 0;
3493 }
3494 
3495 errno_t
ifnet_get_fastlane_capable(ifnet_t interface,boolean_t * capable)3496 ifnet_get_fastlane_capable(ifnet_t interface, boolean_t *capable)
3497 {
3498 	if (interface == NULL || capable == NULL) {
3499 		return EINVAL;
3500 	}
3501 	if (interface->if_qosmarking_mode == IFRTYPE_QOSMARKING_FASTLANE) {
3502 		*capable = true;
3503 	} else {
3504 		*capable = false;
3505 	}
3506 	return 0;
3507 }
3508 
3509 errno_t
ifnet_get_unsent_bytes(ifnet_t interface,int64_t * unsent_bytes)3510 ifnet_get_unsent_bytes(ifnet_t interface, int64_t *unsent_bytes)
3511 {
3512 	int64_t bytes;
3513 
3514 	if (interface == NULL || unsent_bytes == NULL) {
3515 		return EINVAL;
3516 	}
3517 
3518 	bytes = *unsent_bytes = 0;
3519 
3520 	if (!IF_FULLY_ATTACHED(interface)) {
3521 		return ENXIO;
3522 	}
3523 
3524 	bytes = interface->if_sndbyte_unsent;
3525 
3526 	if (interface->if_eflags & IFEF_TXSTART) {
3527 		bytes += IFCQ_BYTES(interface->if_snd);
3528 	}
3529 	*unsent_bytes = bytes;
3530 
3531 	return 0;
3532 }
3533 
3534 errno_t
ifnet_get_buffer_status(const ifnet_t ifp,ifnet_buffer_status_t * buf_status)3535 ifnet_get_buffer_status(const ifnet_t ifp, ifnet_buffer_status_t *buf_status)
3536 {
3537 	if (ifp == NULL || buf_status == NULL) {
3538 		return EINVAL;
3539 	}
3540 
3541 	bzero(buf_status, sizeof(*buf_status));
3542 
3543 	if (!IF_FULLY_ATTACHED(ifp)) {
3544 		return ENXIO;
3545 	}
3546 
3547 	if (ifp->if_eflags & IFEF_TXSTART) {
3548 		buf_status->buf_interface = IFCQ_BYTES(ifp->if_snd);
3549 	}
3550 
3551 	buf_status->buf_sndbuf = ((buf_status->buf_interface != 0) ||
3552 	    (ifp->if_sndbyte_unsent != 0)) ? 1 : 0;
3553 
3554 	return 0;
3555 }
3556 
3557 void
ifnet_normalise_unsent_data(void)3558 ifnet_normalise_unsent_data(void)
3559 {
3560 	struct ifnet *ifp;
3561 
3562 	ifnet_head_lock_shared();
3563 	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
3564 		ifnet_lock_exclusive(ifp);
3565 		if (!IF_FULLY_ATTACHED(ifp)) {
3566 			ifnet_lock_done(ifp);
3567 			continue;
3568 		}
3569 		if (!(ifp->if_eflags & IFEF_TXSTART)) {
3570 			ifnet_lock_done(ifp);
3571 			continue;
3572 		}
3573 
3574 		if (ifp->if_sndbyte_total > 0 ||
3575 		    IFCQ_BYTES(ifp->if_snd) > 0) {
3576 			ifp->if_unsent_data_cnt++;
3577 		}
3578 
3579 		ifnet_lock_done(ifp);
3580 	}
3581 	ifnet_head_done();
3582 }
3583 
3584 errno_t
ifnet_set_low_power_mode(ifnet_t ifp,boolean_t on)3585 ifnet_set_low_power_mode(ifnet_t ifp, boolean_t on)
3586 {
3587 	errno_t error;
3588 
3589 	error = if_set_low_power(ifp, on);
3590 
3591 	return error;
3592 }
3593 
3594 errno_t
ifnet_get_low_power_mode(ifnet_t ifp,boolean_t * on)3595 ifnet_get_low_power_mode(ifnet_t ifp, boolean_t *on)
3596 {
3597 	if (ifp == NULL || on == NULL) {
3598 		return EINVAL;
3599 	}
3600 
3601 	*on = ((ifp->if_xflags & IFXF_LOW_POWER) != 0);
3602 	return 0;
3603 }
3604