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