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