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