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