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