2 * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include "kpi_interface.h"
31 #include <sys/queue.h>
32 #include <sys/param.h> /* for definition of NULL */
33 #include <kern/debug.h> /* for panic */
34 #include <sys/errno.h>
35 #include <sys/socket.h>
36 #include <sys/kern_event.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/kpi_mbuf.h>
40 #include <sys/mcache.h>
41 #include <sys/protosw.h>
42 #include <sys/syslog.h>
43 #include <net/if_var.h>
44 #include <net/if_dl.h>
46 #include <net/if_types.h>
47 #include <net/if_dl.h>
48 #include <net/if_arp.h>
49 #include <net/if_llreach.h>
50 #include <net/if_ether.h>
51 #include <net/route.h>
52 #include <libkern/libkern.h>
53 #include <libkern/OSAtomic.h>
54 #include <kern/locks.h>
55 #include <kern/clock.h>
56 #include <sys/sockio.h>
58 #include <sys/sysctl.h>
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>
65 #include <netinet/in_pcb.h>
67 #include <netinet/igmp_var.h>
70 #include <netinet6/mld6_var.h>
72 #include <netkey/key.h>
74 #include "net/net_str_id.h"
77 #include <sys/kauth.h>
78 #include <security/mac_framework.h>
81 #define TOUCHLASTCHANGE(__if_lastchange) { \
82 (__if_lastchange)->tv_sec = net_uptime(); \
83 (__if_lastchange)->tv_usec = 0; \
86 static errno_t
ifnet_defrouter_llreachinfo(ifnet_t
, int,
87 struct ifnet_llreach_info
*);
88 static void ifnet_kpi_free(ifnet_t
);
89 static errno_t
ifnet_list_get_common(ifnet_family_t
, boolean_t
, ifnet_t
**,
91 static errno_t
ifnet_set_lladdr_internal(ifnet_t
, const void *, size_t,
93 static errno_t
ifnet_awdl_check_eflags(ifnet_t
, u_int32_t
*, u_int32_t
*);
96 * Temporary work around until we have real reference counting
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.
104 ifnet_kpi_free(ifnet_t ifp
)
106 ifnet_detached_func detach_func
= ifp
->if_kpi_storage
;
108 if (detach_func
!= NULL
)
111 if (ifp
->if_broadcast
.length
> sizeof (ifp
->if_broadcast
.u
.buffer
)) {
112 FREE(ifp
->if_broadcast
.u
.ptr
, M_IFADDR
);
113 ifp
->if_broadcast
.u
.ptr
= NULL
;
116 dlil_if_release(ifp
);
120 ifnet_allocate(const struct ifnet_init_params
*init
, ifnet_t
*interface
)
122 struct ifnet_init_eparams einit
;
124 bzero(&einit
, sizeof (einit
));
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
;
149 return (ifnet_allocate_extended(&einit
, interface
));
153 ifnet_allocate_extended(const struct ifnet_init_eparams
*einit0
,
156 struct ifnet_init_eparams einit
;
157 struct ifnet
*ifp
= NULL
;
158 char if_xname
[IFXNAMSIZ
] = {0};
163 if (einit
.ver
!= IFNET_INIT_CURRENT_VERSION
||
164 einit
.len
< sizeof (einit
))
167 if (einit
.family
== 0 || einit
.name
== NULL
||
168 strlen(einit
.name
) >= IFNAMSIZ
||
169 (einit
.type
& 0xFFFFFF00) != 0 || einit
.type
== 0)
172 if (einit
.flags
& IFNET_INIT_LEGACY
) {
173 if (einit
.output
== NULL
|| einit
.flags
!= IFNET_INIT_LEGACY
)
176 einit
.pre_enqueue
= 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
;
183 if (einit
.start
== NULL
)
187 if (einit
.output_sched_model
>= IFNET_SCHED_MODEL_MAX
)
190 if (einit
.flags
& IFNET_INIT_INPUT_POLL
) {
191 if (einit
.input_poll
== NULL
|| einit
.input_ctl
== NULL
)
194 einit
.input_poll
= NULL
;
195 einit
.input_ctl
= NULL
;
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
);
207 error
= dlil_if_acquire(einit
.family
, einit
.uniqueid
,
208 einit
.uniqueid_len
, &ifp
);
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
218 strlcpy(__DECONST(char *, ifp
->if_name
), einit
.name
, IFNAMSIZ
);
219 ifp
->if_type
= einit
.type
;
220 ifp
->if_family
= einit
.family
;
221 ifp
->if_subfamily
= einit
.subfamily
;
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
;
230 ifp
->if_output_lt
.eff_lt
= einit
.output_lt
;
231 ifp
->if_output_lt
.max_lt
= einit
.output_lt_max
;
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
;
236 ifp
->if_input_lt
.eff_lt
= einit
.input_lt
;
237 ifp
->if_input_lt
.max_lt
= einit
.input_lt_max
;
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
;
242 ifp
->if_framer_legacy
= einit
.framer
;
243 ifp
->if_framer
= einit
.framer_extended
;
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
;
251 /* Initialize external name (name + unit) */
252 snprintf(__DECONST(char *, ifp
->if_xname
), IFXNAMSIZ
,
253 "%s%d", ifp
->if_name
, ifp
->if_unit
);
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.
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.
268 * Internally, DLIL will only use the extended callback
269 * variant which is represented by if_framer.
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
;
275 ifp
->if_framer
= ifnet_framer_stub
;
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
;
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
;
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
;
293 /* Pin if_baudrate to 32 bits */
294 br
= MAX(ifp
->if_output_bw
.max_bw
, ifp
->if_input_bw
.max_bw
);
296 ifp
->if_baudrate
= (br
> 0xFFFFFFFF) ? 0xFFFFFFFF : br
;
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
;
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
;
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
;
313 if (ifp
->if_ioctl
== NULL
)
314 ifp
->if_ioctl
= ifp_if_ioctl
;
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
;
322 ifp
->if_eflags
&= ~IFEF_TXSTART
;
325 if (ifp
->if_input_poll
!= NULL
)
326 ifp
->if_eflags
|= IFEF_RXPOLL
;
328 ifp
->if_eflags
&= ~IFEF_RXPOLL
;
330 ifp
->if_output_handler
= dlil_output_handler
;
331 ifp
->if_input_handler
= dlil_input_handler
;
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
));
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
);
345 if (ifp
->if_broadcast
.u
.ptr
== NULL
) {
348 bcopy(einit
.broadcast_addr
,
349 ifp
->if_broadcast
.u
.ptr
,
350 einit
.broadcast_len
);
353 bcopy(einit
.broadcast_addr
,
354 ifp
->if_broadcast
.u
.buffer
,
355 einit
.broadcast_len
);
357 ifp
->if_broadcast
.length
= einit
.broadcast_len
;
359 bzero(&ifp
->if_broadcast
, sizeof (ifp
->if_broadcast
));
363 * output target queue delay is specified in millisecond
364 * convert it to nanoseconds
366 IFCQ_TARGET_QDELAY(&ifp
->if_snd
) =
367 einit
.output_target_qdelay
* 1000 * 1000;
368 IFCQ_MAXLEN(&ifp
->if_snd
) = einit
.sndq_maxlen
;
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;
383 // temporary - this should be done in dlil_if_acquire
384 ifnet_reference(ifp
);
386 dlil_if_release(ifp
);
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.
405 ifnet_reference(ifnet_t ifp
)
407 return (dlil_if_ref(ifp
));
411 ifnet_release(ifnet_t ifp
)
413 return (dlil_if_free(ifp
));
417 ifnet_interface_family_find(const char *module_string
,
418 ifnet_family_t
*family_id
)
420 if (module_string
== NULL
|| family_id
== NULL
)
423 return (net_str_id_find_internal(module_string
, family_id
,
428 ifnet_softc(ifnet_t interface
)
430 return ((interface
== NULL
) ? NULL
: interface
->if_softc
);
434 ifnet_name(ifnet_t interface
)
436 return ((interface
== NULL
) ? NULL
: interface
->if_name
);
440 ifnet_family(ifnet_t interface
)
442 return ((interface
== NULL
) ? 0 : interface
->if_family
);
446 ifnet_subfamily(ifnet_t interface
)
448 return ((interface
== NULL
) ? 0 : interface
->if_subfamily
);
452 ifnet_unit(ifnet_t interface
)
454 return ((interface
== NULL
) ? (u_int32_t
)0xffffffff :
455 (u_int32_t
)interface
->if_unit
);
459 ifnet_index(ifnet_t interface
)
461 return ((interface
== NULL
) ? (u_int32_t
)0xffffffff :
462 interface
->if_index
);
466 ifnet_set_flags(ifnet_t interface
, u_int16_t new_flags
, u_int16_t mask
)
470 if (interface
== NULL
)
473 ifnet_lock_exclusive(interface
);
475 /* If we are modifying the up/down state, call if_updown */
476 if ((mask
& IFF_UP
) != 0) {
477 if_updown(interface
, (new_flags
& IFF_UP
) == IFF_UP
);
480 old_flags
= interface
->if_flags
;
481 interface
->if_flags
= (new_flags
& mask
) | (interface
->if_flags
& ~mask
);
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
)) {
486 if (IGMP_IFINFO(interface
) != NULL
)
487 igmp_initsilent(interface
, IGMP_IFINFO(interface
));
490 if (MLD_IFINFO(interface
) != NULL
)
491 mld6_initsilent(interface
, MLD_IFINFO(interface
));
495 ifnet_lock_done(interface
);
501 ifnet_flags(ifnet_t interface
)
503 return ((interface
== NULL
) ? 0 : interface
->if_flags
);
507 * This routine ensures the following:
509 * If IFEF_AWDL is set by the caller, also set the rest of flags as
510 * defined in IFEF_AWDL_MASK.
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,
516 * If IFEF_AWDL_RESTRICTED is set by the caller, make sure IFEF_AWDL is set
519 * All other flags not associated with AWDL are not affected.
521 * See <net/if.h> for current definition of IFEF_AWDL_MASK.
524 ifnet_awdl_check_eflags(ifnet_t ifp
, u_int32_t
*new_eflags
, u_int32_t
*mask
)
528 ifnet_lock_assert(ifp
, IFNET_LCK_ASSERT_EXCLUSIVE
);
530 eflags
= (*new_eflags
& *mask
) | (ifp
->if_eflags
& ~(*mask
));
532 if (ifp
->if_eflags
& IFEF_AWDL
) {
533 if (eflags
& IFEF_AWDL
) {
534 if ((eflags
& IFEF_AWDL_MASK
) != IFEF_AWDL_MASK
)
537 *new_eflags
&= ~IFEF_AWDL_MASK
;
538 *mask
|= IFEF_AWDL_MASK
;
540 } else if (eflags
& IFEF_AWDL
) {
541 *new_eflags
|= IFEF_AWDL_MASK
;
542 *mask
|= IFEF_AWDL_MASK
;
543 } else if (eflags
& IFEF_AWDL_RESTRICTED
&&
544 !(ifp
->if_eflags
& IFEF_AWDL
))
551 ifnet_set_eflags(ifnet_t interface
, u_int32_t new_flags
, u_int32_t mask
)
554 struct kev_msg ev_msg
;
555 struct net_event_data ev_data
;
557 if (interface
== NULL
)
560 bzero(&ev_msg
, sizeof(ev_msg
));
561 ifnet_lock_exclusive(interface
);
563 * Sanity checks for IFEF_AWDL and its related flags.
565 if (ifnet_awdl_check_eflags(interface
, &new_flags
, &mask
) != 0) {
566 ifnet_lock_done(interface
);
569 oeflags
= interface
->if_eflags
;
570 interface
->if_eflags
=
571 (new_flags
& mask
) | (interface
->if_eflags
& ~mask
);
572 ifnet_lock_done(interface
);
573 if (interface
->if_eflags
& IFEF_AWDL_RESTRICTED
&&
574 !(oeflags
& IFEF_AWDL_RESTRICTED
)) {
575 ev_msg
.event_code
= KEV_DL_AWDL_RESTRICTED
;
577 * The interface is now restricted to applications that have
579 * The check for the entitlement will be done in the data
580 * path, so we don't have to do anything here.
582 } else if (oeflags
& IFEF_AWDL_RESTRICTED
&&
583 !(interface
->if_eflags
& IFEF_AWDL_RESTRICTED
))
584 ev_msg
.event_code
= KEV_DL_AWDL_UNRESTRICTED
;
586 * Notify configd so that it has a chance to perform better
587 * reachability detection.
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
;
599 ev_msg
.dv
[1].data_length
= 0;
600 dlil_post_complete_msg(interface
, &ev_msg
);
607 ifnet_eflags(ifnet_t interface
)
609 return ((interface
== NULL
) ? 0 : interface
->if_eflags
);
613 ifnet_set_idle_flags_locked(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
620 lck_mtx_assert(rnh_lock
, LCK_MTX_ASSERT_OWNED
);
621 ifnet_lock_assert(ifp
, IFNET_LCK_ASSERT_EXCLUSIVE
);
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.
628 if (!ifnet_is_attached(ifp
, 0)) {
629 ifp
->if_idle_new_flags
= new_flags
;
630 ifp
->if_idle_new_flags_mask
= mask
;
633 ifp
->if_idle_new_flags
= ifp
->if_idle_new_flags_mask
= 0;
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
;
640 if ((after
- before
) < 0 && ifp
->if_idle_flags
== 0 &&
641 ifp
->if_want_aggressive_drain
!= 0) {
642 ifp
->if_want_aggressive_drain
= 0;
643 } else if ((after
- before
) > 0 && ifp
->if_want_aggressive_drain
== 0) {
644 ifp
->if_want_aggressive_drain
++;
651 ifnet_set_idle_flags(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
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
);
659 lck_mtx_unlock(rnh_lock
);
665 ifnet_idle_flags(ifnet_t ifp
)
667 return ((ifp
== NULL
) ? 0 : ifp
->if_idle_flags
);
671 ifnet_set_link_quality(ifnet_t ifp
, int quality
)
675 if (ifp
== NULL
|| quality
< IFNET_LQM_MIN
|| quality
> IFNET_LQM_MAX
) {
680 if (!ifnet_is_attached(ifp
, 0)) {
685 if_lqm_update(ifp
, quality
, 0);
692 ifnet_link_quality(ifnet_t ifp
)
697 return (IFNET_LQM_THRESH_OFF
);
699 ifnet_lock_shared(ifp
);
700 lqm
= ifp
->if_interface_state
.lqm_state
;
701 ifnet_lock_done(ifp
);
707 ifnet_set_interface_state(ifnet_t ifp
,
708 struct if_interface_state
*if_interface_state
)
712 if (ifp
== NULL
|| if_interface_state
== NULL
) {
717 if (!ifnet_is_attached(ifp
, 0)) {
722 if_state_update(ifp
, if_interface_state
);
729 ifnet_get_interface_state(ifnet_t ifp
,
730 struct if_interface_state
*if_interface_state
)
734 if (ifp
== NULL
|| if_interface_state
== NULL
) {
739 if (!ifnet_is_attached(ifp
, 0)) {
744 if_get_state(ifp
, if_interface_state
);
752 ifnet_defrouter_llreachinfo(ifnet_t ifp
, int af
,
753 struct ifnet_llreach_info
*iflri
)
755 if (ifp
== NULL
|| iflri
== NULL
)
758 VERIFY(af
== AF_INET
|| af
== AF_INET6
);
760 return (ifnet_llreach_get_defrouter(ifp
, af
, iflri
));
764 ifnet_inet_defrouter_llreachinfo(ifnet_t ifp
, struct ifnet_llreach_info
*iflri
)
766 return (ifnet_defrouter_llreachinfo(ifp
, AF_INET
, iflri
));
770 ifnet_inet6_defrouter_llreachinfo(ifnet_t ifp
, struct ifnet_llreach_info
*iflri
)
772 return (ifnet_defrouter_llreachinfo(ifp
, AF_INET6
, iflri
));
776 ifnet_set_capabilities_supported(ifnet_t ifp
, u_int32_t new_caps
,
785 ifnet_lock_exclusive(ifp
);
786 tmp
= (new_caps
& mask
) | (ifp
->if_capabilities
& ~mask
);
787 if ((tmp
& ~IFCAP_VALID
))
790 ifp
->if_capabilities
= tmp
;
791 ifnet_lock_done(ifp
);
797 ifnet_capabilities_supported(ifnet_t ifp
)
799 return ((ifp
== NULL
) ? 0 : ifp
->if_capabilities
);
804 ifnet_set_capabilities_enabled(ifnet_t ifp
, u_int32_t new_caps
,
809 struct kev_msg ev_msg
;
810 struct net_event_data ev_data
;
815 ifnet_lock_exclusive(ifp
);
816 tmp
= (new_caps
& mask
) | (ifp
->if_capenable
& ~mask
);
817 if ((tmp
& ~IFCAP_VALID
) || (tmp
& ~ifp
->if_capabilities
))
820 ifp
->if_capenable
= tmp
;
821 ifnet_lock_done(ifp
);
823 /* Notify application of the change */
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
;
830 ev_msg
.event_code
= KEV_DL_IFCAP_CHANGED
;
831 strlcpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
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
;
836 ev_msg
.dv
[1].data_length
= 0;
837 dlil_post_complete_msg(ifp
, &ev_msg
);
843 ifnet_capabilities_enabled(ifnet_t ifp
)
845 return ((ifp
== NULL
) ? 0 : ifp
->if_capenable
);
848 static 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
|
851 IFNET_IPV6_FRAGMENT
| IFNET_CSUM_PARTIAL
| IFNET_VLAN_TAGGING
|
852 IFNET_VLAN_MTU
| IFNET_MULTIPAGES
| IFNET_TSO_IPV4
| IFNET_TSO_IPV6
|
853 IFNET_TX_STATUS
| IFNET_HW_TIMESTAMP
| IFNET_SW_TIMESTAMP
);
855 static const ifnet_offload_t any_offload_csum
= IFNET_CHECKSUMF
;
858 ifnet_set_offload(ifnet_t interface
, ifnet_offload_t offload
)
860 u_int32_t ifcaps
= 0;
862 if (interface
== NULL
)
865 ifnet_lock_exclusive(interface
);
866 interface
->if_hwassist
= (offload
& offload_mask
);
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.
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
);
878 log(LOG_DEBUG
, "%s: set offload flags=%b\n",
880 interface
->if_hwassist
, IFNET_OFFLOADF_BITS
);
882 ifnet_lock_done(interface
);
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
;
894 if ((offload
& IFNET_TX_STATUS
))
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
;
901 (void) ifnet_set_capabilities_supported(interface
, ifcaps
,
903 (void) ifnet_set_capabilities_enabled(interface
, ifcaps
,
911 ifnet_offload(ifnet_t interface
)
913 return ((interface
== NULL
) ?
914 0 : (interface
->if_hwassist
& offload_mask
));
918 ifnet_set_tso_mtu(ifnet_t interface
, sa_family_t family
, u_int32_t mtuLen
)
922 if (interface
== NULL
|| mtuLen
< interface
->if_mtu
)
927 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
928 interface
->if_tso_v4_mtu
= mtuLen
;
934 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
935 interface
->if_tso_v6_mtu
= mtuLen
;
941 error
= EPROTONOSUPPORT
;
949 ifnet_get_tso_mtu(ifnet_t interface
, sa_family_t family
, u_int32_t
*mtuLen
)
953 if (interface
== NULL
|| mtuLen
== NULL
)
958 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
959 *mtuLen
= interface
->if_tso_v4_mtu
;
965 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
966 *mtuLen
= interface
->if_tso_v6_mtu
;
972 error
= EPROTONOSUPPORT
;
980 ifnet_set_wake_flags(ifnet_t interface
, u_int32_t properties
, u_int32_t mask
)
982 struct kev_msg ev_msg
;
983 struct net_event_data ev_data
;
985 bzero(&ev_data
, sizeof (struct net_event_data
));
986 bzero(&ev_msg
, sizeof (struct kev_msg
));
988 if (interface
== NULL
)
991 /* Do not accept wacky values */
992 if ((properties
& mask
) & ~IF_WAKE_VALID_FLAGS
)
995 ifnet_lock_exclusive(interface
);
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
;
1001 interface
->if_xflags
&= ~IFXF_WAKE_ON_MAGIC_PACKET
;
1004 ifnet_lock_done(interface
);
1006 (void) ifnet_touch_lastchange(interface
);
1008 /* Notify application of the change */
1009 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1010 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1011 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
1013 ev_msg
.event_code
= KEV_DL_WAKEFLAGS_CHANGED
;
1014 strlcpy(&ev_data
.if_name
[0], interface
->if_name
, IFNAMSIZ
);
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
;
1019 ev_msg
.dv
[1].data_length
= 0;
1020 dlil_post_complete_msg(interface
, &ev_msg
);
1026 ifnet_get_wake_flags(ifnet_t interface
)
1028 u_int32_t flags
= 0;
1030 if (interface
== NULL
)
1033 if (interface
->if_xflags
& IFXF_WAKE_ON_MAGIC_PACKET
)
1034 flags
|= IF_WAKE_ON_MAGIC_PACKET
;
1040 * Should MIB data store a copy?
1043 ifnet_set_link_mib_data(ifnet_t interface
, void *mibData
, u_int32_t mibLen
)
1045 if (interface
== NULL
)
1048 ifnet_lock_exclusive(interface
);
1049 interface
->if_linkmib
= (void*)mibData
;
1050 interface
->if_linkmiblen
= mibLen
;
1051 ifnet_lock_done(interface
);
1056 ifnet_get_link_mib_data(ifnet_t interface
, void *mibData
, u_int32_t
*mibLen
)
1060 if (interface
== NULL
)
1063 ifnet_lock_shared(interface
);
1064 if (*mibLen
< interface
->if_linkmiblen
)
1066 if (result
== 0 && interface
->if_linkmib
== NULL
)
1070 *mibLen
= interface
->if_linkmiblen
;
1071 bcopy(interface
->if_linkmib
, mibData
, *mibLen
);
1073 ifnet_lock_done(interface
);
1079 ifnet_get_link_mib_data_length(ifnet_t interface
)
1081 return ((interface
== NULL
) ? 0 : interface
->if_linkmiblen
);
1085 ifnet_output(ifnet_t interface
, protocol_family_t protocol_family
,
1086 mbuf_t m
, void *route
, const struct sockaddr
*dest
)
1088 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
1093 return (dlil_output(interface
, protocol_family
, m
, route
, dest
, 0, NULL
));
1097 ifnet_output_raw(ifnet_t interface
, protocol_family_t protocol_family
, mbuf_t m
)
1099 if (interface
== NULL
|| m
== NULL
) {
1104 return (dlil_output(interface
, protocol_family
, m
, NULL
, NULL
, 1, NULL
));
1108 ifnet_set_mtu(ifnet_t interface
, u_int32_t mtu
)
1110 if (interface
== NULL
)
1113 interface
->if_mtu
= mtu
;
1118 ifnet_mtu(ifnet_t interface
)
1120 return ((interface
== NULL
) ? 0 : interface
->if_mtu
);
1124 ifnet_type(ifnet_t interface
)
1126 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_type
);
1130 ifnet_set_addrlen(ifnet_t interface
, u_char addrlen
)
1132 if (interface
== NULL
)
1135 interface
->if_data
.ifi_addrlen
= addrlen
;
1140 ifnet_addrlen(ifnet_t interface
)
1142 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_addrlen
);
1146 ifnet_set_hdrlen(ifnet_t interface
, u_char hdrlen
)
1148 if (interface
== NULL
)
1151 interface
->if_data
.ifi_hdrlen
= hdrlen
;
1156 ifnet_hdrlen(ifnet_t interface
)
1158 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_hdrlen
);
1162 ifnet_set_metric(ifnet_t interface
, u_int32_t metric
)
1164 if (interface
== NULL
)
1167 interface
->if_data
.ifi_metric
= metric
;
1172 ifnet_metric(ifnet_t interface
)
1174 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_metric
);
1178 ifnet_set_baudrate(struct ifnet
*ifp
, u_int64_t baudrate
)
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
;
1186 /* Pin if_baudrate to 32 bits until we can change the storage size */
1187 ifp
->if_baudrate
= (baudrate
> 0xFFFFFFFF) ? 0xFFFFFFFF : baudrate
;
1193 ifnet_baudrate(struct ifnet
*ifp
)
1195 return ((ifp
== NULL
) ? 0 : ifp
->if_baudrate
);
1199 ifnet_set_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*output_bw
,
1200 struct if_bandwidths
*input_bw
)
1205 /* set input values first (if any), as output values depend on them */
1206 if (input_bw
!= NULL
)
1207 (void) ifnet_set_input_bandwidths(ifp
, input_bw
);
1209 if (output_bw
!= NULL
)
1210 (void) ifnet_set_output_bandwidths(ifp
, output_bw
, FALSE
);
1216 ifnet_set_link_status_outbw(struct ifnet
*ifp
)
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
;
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
;
1235 ifnet_set_output_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*bw
,
1238 struct if_bandwidths old_bw
;
1239 struct ifclassq
*ifq
;
1242 VERIFY(ifp
!= NULL
&& bw
!= NULL
);
1247 IFCQ_LOCK_ASSERT_HELD(ifq
);
1249 old_bw
= ifp
->if_output_bw
;
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
;
1259 /* Pin if_baudrate to 32 bits */
1260 br
= MAX(ifp
->if_output_bw
.max_bw
, ifp
->if_input_bw
.max_bw
);
1262 ifp
->if_baudrate
= (br
> 0xFFFFFFFF) ? 0xFFFFFFFF : br
;
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
)
1267 ifnet_update_sndq(ifq
, CLASSQ_EV_LINK_BANDWIDTH
);
1273 * If this is a Wifi interface, update the values in
1274 * if_link_status structure also.
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
);
1286 ifnet_set_link_status_inbw(struct ifnet
*ifp
)
1288 struct if_wifi_status_v1
*sr
;
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
;
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
;
1305 ifnet_set_input_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*bw
)
1307 struct if_bandwidths old_bw
;
1309 VERIFY(ifp
!= NULL
&& bw
!= NULL
);
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
;
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
);
1327 if (old_bw
.eff_bw
!= ifp
->if_input_bw
.eff_bw
||
1328 old_bw
.max_bw
!= ifp
->if_input_bw
.max_bw
)
1329 ifnet_update_rcv(ifp
, CLASSQ_EV_LINK_BANDWIDTH
);
1335 ifnet_output_linkrate(struct ifnet
*ifp
)
1337 struct ifclassq
*ifq
= &ifp
->if_snd
;
1340 IFCQ_LOCK_ASSERT_HELD(ifq
);
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
);
1353 ifnet_input_linkrate(struct ifnet
*ifp
)
1355 return (ifp
->if_input_bw
.eff_bw
);
1359 ifnet_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*output_bw
,
1360 struct if_bandwidths
*input_bw
)
1365 if (output_bw
!= NULL
)
1366 *output_bw
= ifp
->if_output_bw
;
1367 if (input_bw
!= NULL
)
1368 *input_bw
= ifp
->if_input_bw
;
1374 ifnet_set_latencies(struct ifnet
*ifp
, struct if_latencies
*output_lt
,
1375 struct if_latencies
*input_lt
)
1380 if (output_lt
!= NULL
)
1381 (void) ifnet_set_output_latencies(ifp
, output_lt
, FALSE
);
1383 if (input_lt
!= NULL
)
1384 (void) ifnet_set_input_latencies(ifp
, input_lt
);
1390 ifnet_set_output_latencies(struct ifnet
*ifp
, struct if_latencies
*lt
,
1393 struct if_latencies old_lt
;
1394 struct ifclassq
*ifq
;
1396 VERIFY(ifp
!= NULL
&& lt
!= NULL
);
1401 IFCQ_LOCK_ASSERT_HELD(ifq
);
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
;
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
);
1425 ifnet_set_input_latencies(struct ifnet
*ifp
, struct if_latencies
*lt
)
1427 struct if_latencies old_lt
;
1429 VERIFY(ifp
!= NULL
&& lt
!= NULL
);
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
;
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
);
1449 ifnet_latencies(struct ifnet
*ifp
, struct if_latencies
*output_lt
,
1450 struct if_latencies
*input_lt
)
1455 if (output_lt
!= NULL
)
1456 *output_lt
= ifp
->if_output_lt
;
1457 if (input_lt
!= NULL
)
1458 *input_lt
= ifp
->if_input_lt
;
1464 ifnet_set_poll_params(struct ifnet
*ifp
, struct ifnet_poll_params
*p
)
1470 else if (!ifnet_is_attached(ifp
, 1))
1473 err
= dlil_rxpoll_set_params(ifp
, p
, FALSE
);
1475 /* Release the io ref count */
1476 ifnet_decr_iorefcnt(ifp
);
1482 ifnet_poll_params(struct ifnet
*ifp
, struct ifnet_poll_params
*p
)
1486 if (ifp
== NULL
|| p
== NULL
)
1488 else if (!ifnet_is_attached(ifp
, 1))
1491 err
= dlil_rxpoll_get_params(ifp
, p
);
1493 /* Release the io ref count */
1494 ifnet_decr_iorefcnt(ifp
);
1500 ifnet_stat_increment(struct ifnet
*ifp
,
1501 const struct ifnet_stat_increment_param
*s
)
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
);
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
);
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
);
1525 /* Touch the last change time. */
1526 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1532 ifnet_stat_increment_in(struct ifnet
*ifp
, u_int32_t packets_in
,
1533 u_int32_t bytes_in
, u_int32_t errors_in
)
1538 if (packets_in
!= 0)
1539 atomic_add_64(&ifp
->if_data
.ifi_ipackets
, packets_in
);
1541 atomic_add_64(&ifp
->if_data
.ifi_ibytes
, bytes_in
);
1543 atomic_add_64(&ifp
->if_data
.ifi_ierrors
, errors_in
);
1545 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1551 ifnet_stat_increment_out(struct ifnet
*ifp
, u_int32_t packets_out
,
1552 u_int32_t bytes_out
, u_int32_t errors_out
)
1557 if (packets_out
!= 0)
1558 atomic_add_64(&ifp
->if_data
.ifi_opackets
, packets_out
);
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
);
1564 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1570 ifnet_set_stat(struct ifnet
*ifp
, const struct ifnet_stats_param
*s
)
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
);
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
);
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
);
1589 /* Touch the last change time. */
1590 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1596 ifnet_stat(struct ifnet
*ifp
, struct ifnet_stats_param
*s
)
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
);
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
);
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
);
1619 ifnet_touch_lastchange(ifnet_t interface
)
1621 if (interface
== NULL
)
1624 TOUCHLASTCHANGE(&interface
->if_lastchange
);
1630 ifnet_lastchange(ifnet_t interface
, struct timeval
*last_change
)
1632 if (interface
== NULL
)
1635 *last_change
= interface
->if_data
.ifi_lastchange
;
1636 /* Crude conversion from uptime to calendar time */
1637 last_change
->tv_sec
+= boottime_sec();
1643 ifnet_get_address_list(ifnet_t interface
, ifaddr_t
**addresses
)
1645 return (addresses
== NULL
? EINVAL
:
1646 ifnet_get_address_list_family(interface
, addresses
, 0));
1649 struct ifnet_addr_list
{
1650 SLIST_ENTRY(ifnet_addr_list
) ifal_le
;
1651 struct ifaddr
*ifal_ifa
;
1655 ifnet_get_address_list_family(ifnet_t interface
, ifaddr_t
**addresses
,
1658 return (ifnet_get_address_list_family_internal(interface
, addresses
,
1659 family
, 0, M_NOWAIT
, 0));
1663 ifnet_get_inuse_address_list(ifnet_t interface
, ifaddr_t
**addresses
)
1665 return (addresses
== NULL
? EINVAL
:
1666 ifnet_get_address_list_family_internal(interface
, addresses
,
1667 0, 0, M_NOWAIT
, 1));
1670 extern uint32_t tcp_find_anypcb_byaddr(struct ifaddr
*ifa
);
1672 extern uint32_t udp_find_anypcb_byaddr(struct ifaddr
*ifa
);
1674 __private_extern__ errno_t
1675 ifnet_get_address_list_family_internal(ifnet_t interface
, ifaddr_t
**addresses
,
1676 sa_family_t family
, int detached
, int how
, int return_inuse_addrs
)
1678 SLIST_HEAD(, ifnet_addr_list
) ifal_head
;
1679 struct ifnet_addr_list
*ifal
, *ifal_tmp
;
1686 SLIST_INIT(&ifal_head
);
1688 if (addresses
== NULL
) {
1696 * Interface has been detached, so skip the lookup
1697 * at ifnet_head and go directly to inner loop.
1707 ifnet_head_lock_shared();
1708 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
1709 if (interface
!= NULL
&& ifp
!= interface
)
1712 ifnet_lock_shared(ifp
);
1713 if (interface
== NULL
|| interface
== ifp
) {
1715 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1718 ifa
->ifa_addr
->sa_family
!= family
) {
1722 MALLOC(ifal
, struct ifnet_addr_list
*,
1723 sizeof (*ifal
), M_TEMP
, how
);
1726 ifnet_lock_done(ifp
);
1732 ifal
->ifal_ifa
= ifa
;
1733 IFA_ADDREF_LOCKED(ifa
);
1734 SLIST_INSERT_HEAD(&ifal_head
, ifal
, ifal_le
);
1739 ifnet_lock_done(ifp
);
1750 MALLOC(*addresses
, ifaddr_t
*, sizeof (ifaddr_t
) * (count
+ 1),
1752 if (*addresses
== NULL
) {
1756 bzero(*addresses
, sizeof (ifaddr_t
) * (count
+ 1));
1759 SLIST_FOREACH_SAFE(ifal
, &ifal_head
, ifal_le
, ifal_tmp
) {
1760 SLIST_REMOVE(&ifal_head
, ifal
, ifnet_addr_list
, ifal_le
);
1762 if (return_inuse_addrs
) {
1763 usecount
= tcp_find_anypcb_byaddr(ifal
->ifal_ifa
);
1764 usecount
+= udp_find_anypcb_byaddr(ifal
->ifal_ifa
);
1766 (*addresses
)[index
] = ifal
->ifal_ifa
;
1769 IFA_REMREF(ifal
->ifal_ifa
);
1772 (*addresses
)[--count
] = ifal
->ifal_ifa
;
1775 IFA_REMREF(ifal
->ifal_ifa
);
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
);
1790 ifnet_free_address_list(ifaddr_t
*addresses
)
1794 if (addresses
== NULL
)
1797 for (i
= 0; addresses
[i
] != NULL
; i
++)
1798 IFA_REMREF(addresses
[i
]);
1800 FREE(addresses
, M_TEMP
);
1804 ifnet_lladdr(ifnet_t interface
)
1809 if (interface
== NULL
)
1813 * if_lladdr points to the permanent link address of
1814 * the interface and it never gets deallocated; internal
1815 * code should simply use IF_LLADDR() for performance.
1817 ifa
= interface
->if_lladdr
;
1819 lladdr
= LLADDR(SDL((void *)ifa
->ifa_addr
));
1826 ifnet_llbroadcast_copy_bytes(ifnet_t interface
, void *addr
, size_t buffer_len
,
1829 if (interface
== NULL
|| addr
== NULL
|| out_len
== NULL
)
1832 *out_len
= interface
->if_broadcast
.length
;
1834 if (buffer_len
< interface
->if_broadcast
.length
)
1837 if (interface
->if_broadcast
.length
== 0)
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
);
1845 bcopy(interface
->if_broadcast
.u
.ptr
, addr
,
1846 interface
->if_broadcast
.length
);
1853 ifnet_lladdr_copy_bytes_internal(ifnet_t interface
, void *lladdr
,
1854 size_t lladdr_len
, kauth_cred_t
*credp
)
1856 const u_int8_t
*bytes
;
1859 uint8_t sdlbuf
[SOCK_MAXADDRLEN
+ 1];
1863 * Make sure to accomodate the largest possible
1864 * size of SA(if_lladdr)->sa_len.
1866 _CASSERT(sizeof (sdlbuf
) == (SOCK_MAXADDRLEN
+ 1));
1868 if (interface
== NULL
|| lladdr
== NULL
)
1871 ifa
= interface
->if_lladdr
;
1873 bcopy(ifa
->ifa_addr
, &sdlbuf
, SDL(ifa
->ifa_addr
)->sdl_len
);
1876 bytes
= dlil_ifaddr_bytes(SDL(&sdlbuf
), &bytes_len
, credp
);
1877 if (bytes_len
!= lladdr_len
) {
1878 bzero(lladdr
, lladdr_len
);
1881 bcopy(bytes
, lladdr
, bytes_len
);
1888 ifnet_lladdr_copy_bytes(ifnet_t interface
, void *lladdr
, size_t length
)
1890 return (ifnet_lladdr_copy_bytes_internal(interface
, lladdr
, length
,
1895 ifnet_guarded_lladdr_copy_bytes(ifnet_t interface
, void *lladdr
, size_t length
)
1899 net_thread_marks_t marks
;
1901 kauth_cred_t
*credp
;
1906 marks
= net_thread_marks_push(NET_THREAD_CKREQ_LLADDR
);
1907 cred
= kauth_cred_proc_ref(current_proc());
1913 error
= ifnet_lladdr_copy_bytes_internal(interface
, lladdr
, length
,
1917 kauth_cred_unref(credp
);
1918 net_thread_marks_pop(marks
);
1925 ifnet_set_lladdr_internal(ifnet_t interface
, const void *lladdr
,
1926 size_t lladdr_len
, u_char new_type
, int apply_type
)
1931 if (interface
== NULL
)
1934 ifnet_head_lock_shared();
1935 ifnet_lock_exclusive(interface
);
1936 if (lladdr_len
!= 0 &&
1937 (lladdr_len
!= interface
->if_addrlen
|| lladdr
== 0)) {
1938 ifnet_lock_done(interface
);
1942 ifa
= ifnet_addrs
[interface
->if_index
- 1];
1944 struct sockaddr_dl
*sdl
;
1947 sdl
= (struct sockaddr_dl
*)(void *)ifa
->ifa_addr
;
1948 if (lladdr_len
!= 0) {
1949 bcopy(lladdr
, LLADDR(sdl
), lladdr_len
);
1951 bzero(LLADDR(sdl
), interface
->if_addrlen
);
1953 sdl
->sdl_alen
= lladdr_len
;
1956 sdl
->sdl_type
= new_type
;
1962 ifnet_lock_done(interface
);
1965 /* Generate a kernel event */
1967 dlil_post_msg(interface
, KEV_DL_SUBCLASS
,
1968 KEV_DL_LINK_ADDRESS_CHANGED
, NULL
, 0);
1975 ifnet_set_lladdr(ifnet_t interface
, const void* lladdr
, size_t lladdr_len
)
1977 return (ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, 0, 0));
1981 ifnet_set_lladdr_and_type(ifnet_t interface
, const void* lladdr
,
1982 size_t lladdr_len
, u_char type
)
1984 return (ifnet_set_lladdr_internal(interface
, lladdr
,
1985 lladdr_len
, type
, 1));
1989 ifnet_add_multicast(ifnet_t interface
, const struct sockaddr
*maddr
,
1990 ifmultiaddr_t
*ifmap
)
1992 if (interface
== NULL
|| maddr
== NULL
)
1995 /* Don't let users screw up protocols' entries. */
1996 if (maddr
->sa_family
!= AF_UNSPEC
&& maddr
->sa_family
!= AF_LINK
)
1999 return (if_addmulti_anon(interface
, maddr
, ifmap
));
2003 ifnet_remove_multicast(ifmultiaddr_t ifma
)
2005 struct sockaddr
*maddr
;
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
)
2015 return (if_delmulti_anon(ifma
->ifma_ifp
, maddr
));
2019 ifnet_get_multicast_list(ifnet_t ifp
, ifmultiaddr_t
**addresses
)
2023 struct ifmultiaddr
*addr
;
2025 if (ifp
== NULL
|| addresses
== NULL
)
2028 ifnet_lock_shared(ifp
);
2029 LIST_FOREACH(addr
, &ifp
->if_multiaddrs
, ifma_link
) {
2033 MALLOC(*addresses
, ifmultiaddr_t
*, sizeof (ifmultiaddr_t
) * (cmax
+ 1),
2035 if (*addresses
== NULL
) {
2036 ifnet_lock_done(ifp
);
2040 LIST_FOREACH(addr
, &ifp
->if_multiaddrs
, ifma_link
) {
2041 if (count
+ 1 > cmax
)
2043 (*addresses
)[count
] = (ifmultiaddr_t
)addr
;
2044 ifmaddr_reference((*addresses
)[count
]);
2047 (*addresses
)[cmax
] = NULL
;
2048 ifnet_lock_done(ifp
);
2054 ifnet_free_multicast_list(ifmultiaddr_t
*addresses
)
2058 if (addresses
== NULL
)
2061 for (i
= 0; addresses
[i
] != NULL
; i
++)
2062 ifmaddr_release(addresses
[i
]);
2064 FREE(addresses
, M_TEMP
);
2068 ifnet_find_by_name(const char *ifname
, ifnet_t
*ifpp
)
2076 namelen
= strlen(ifname
);
2080 ifnet_head_lock_shared();
2081 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
2083 struct sockaddr_dl
*ll_addr
;
2085 ifa
= ifnet_addrs
[ifp
->if_index
- 1];
2090 ll_addr
= (struct sockaddr_dl
*)(void *)ifa
->ifa_addr
;
2092 if (namelen
== ll_addr
->sdl_nlen
&& strncmp(ll_addr
->sdl_data
,
2093 ifname
, ll_addr
->sdl_nlen
) == 0) {
2096 ifnet_reference(*ifpp
);
2103 return ((ifp
== NULL
) ? ENXIO
: 0);
2107 ifnet_list_get(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
2109 return (ifnet_list_get_common(family
, FALSE
, list
, count
));
2112 __private_extern__ errno_t
2113 ifnet_list_get_all(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
2115 return (ifnet_list_get_common(family
, TRUE
, list
, count
));
2119 SLIST_ENTRY(ifnet_list
) ifl_le
;
2120 struct ifnet
*ifl_ifp
;
2124 ifnet_list_get_common(ifnet_family_t family
, boolean_t get_all
, ifnet_t
**list
,
2127 #pragma unused(get_all)
2128 SLIST_HEAD(, ifnet_list
) ifl_head
;
2129 struct ifnet_list
*ifl
, *ifl_tmp
;
2134 SLIST_INIT(&ifl_head
);
2136 if (list
== NULL
|| count
== NULL
) {
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
),
2154 ifnet_reference(ifp
);
2155 SLIST_INSERT_HEAD(&ifl_head
, ifl
, ifl_le
);
2166 MALLOC(*list
, ifnet_t
*, sizeof (ifnet_t
) * (cnt
+ 1),
2168 if (*list
== NULL
) {
2172 bzero(*list
, sizeof (ifnet_t
) * (cnt
+ 1));
2176 SLIST_FOREACH_SAFE(ifl
, &ifl_head
, ifl_le
, ifl_tmp
) {
2177 SLIST_REMOVE(&ifl_head
, ifl
, ifnet_list
, ifl_le
);
2179 (*list
)[--cnt
] = ifl
->ifl_ifp
;
2181 ifnet_release(ifl
->ifl_ifp
);
2189 ifnet_list_free(ifnet_t
*interfaces
)
2193 if (interfaces
== NULL
)
2196 for (i
= 0; interfaces
[i
]; i
++)
2197 ifnet_release(interfaces
[i
]);
2199 FREE(interfaces
, M_TEMP
);
2203 ifnet_transmit_burst_start(ifnet_t ifp
, mbuf_t pkt
)
2206 uint32_t orig_flags
;
2208 if (ifp
== NULL
|| !(pkt
->m_flags
& M_PKTHDR
))
2211 orig_flags
= OSBitOrAtomic(IF_MEASURED_BW_INPROGRESS
,
2213 if (orig_flags
& IF_MEASURED_BW_INPROGRESS
) {
2214 /* There is already a measurement in progress; skip this one */
2218 ifp
->if_bw
.start_seq
= pkt
->m_pkthdr
.pkt_bwseq
;
2219 ifp
->if_bw
.start_ts
= mach_absolute_time();
2220 #else /* !MEASURE_BW */
2221 #pragma unused(ifp, pkt)
2222 #endif /* !MEASURE_BW */
2226 ifnet_transmit_burst_end(ifnet_t ifp
, mbuf_t pkt
)
2229 uint64_t oseq
, ots
, bytes
, ts
, t
;
2232 if (ifp
== NULL
|| !(pkt
->m_flags
& M_PKTHDR
))
2235 flags
= OSBitOrAtomic(IF_MEASURED_BW_CALCULATION
, &ifp
->if_bw
.flags
);
2237 /* If a calculation is already in progress, just return */
2238 if (flags
& IF_MEASURED_BW_CALCULATION
)
2241 /* Check if a measurement was started at all */
2242 if (!(flags
& IF_MEASURED_BW_INPROGRESS
)) {
2244 * It is an error to call burst_end before burst_start.
2245 * Reset the calculation flag and return.
2250 oseq
= pkt
->m_pkthdr
.pkt_bwseq
;
2251 ots
= mach_absolute_time();
2253 if (ifp
->if_bw
.start_seq
> 0 && oseq
> ifp
->if_bw
.start_seq
) {
2254 ts
= ots
- ifp
->if_bw
.start_ts
;
2256 absolutetime_to_nanoseconds(ts
, &t
);
2257 bytes
= oseq
- ifp
->if_bw
.start_seq
;
2258 ifp
->if_bw
.bytes
= bytes
;
2264 /* Compute bandwidth as bytes/ms */
2265 bw
= (bytes
* NSEC_PER_MSEC
) / t
;
2267 if (ifp
->if_bw
.bw
> 0) {
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
;
2280 ifp
->if_bw
.last_seq
= oseq
;
2281 ifp
->if_bw
.last_ts
= ots
;
2286 flags
= ~(IF_MEASURED_BW_INPROGRESS
| IF_MEASURED_BW_CALCULATION
);
2287 OSBitAndAtomic(flags
, &ifp
->if_bw
.flags
);
2288 #else /* !MEASURE_BW */
2289 #pragma unused(ifp, pkt)
2290 #endif /* !MEASURE_BW */
2293 /*************************************************************************/
2294 /* ifaddr_t accessors */
2295 /*************************************************************************/
2298 ifaddr_reference(ifaddr_t ifa
)
2308 ifaddr_release(ifaddr_t ifa
)
2318 ifaddr_address_family(ifaddr_t ifa
)
2320 sa_family_t family
= 0;
2324 if (ifa
->ifa_addr
!= NULL
)
2325 family
= ifa
->ifa_addr
->sa_family
;
2332 ifaddr_address(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
2336 if (ifa
== NULL
|| out_addr
== NULL
)
2340 if (ifa
->ifa_addr
== NULL
) {
2345 copylen
= (addr_size
>= ifa
->ifa_addr
->sa_len
) ?
2346 ifa
->ifa_addr
->sa_len
: addr_size
;
2347 bcopy(ifa
->ifa_addr
, out_addr
, copylen
);
2349 if (ifa
->ifa_addr
->sa_len
> addr_size
) {
2359 ifaddr_dstaddress(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
2363 if (ifa
== NULL
|| out_addr
== NULL
)
2367 if (ifa
->ifa_dstaddr
== NULL
) {
2372 copylen
= (addr_size
>= ifa
->ifa_dstaddr
->sa_len
) ?
2373 ifa
->ifa_dstaddr
->sa_len
: addr_size
;
2374 bcopy(ifa
->ifa_dstaddr
, out_addr
, copylen
);
2376 if (ifa
->ifa_dstaddr
->sa_len
> addr_size
) {
2386 ifaddr_netmask(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
2390 if (ifa
== NULL
|| out_addr
== NULL
)
2394 if (ifa
->ifa_netmask
== NULL
) {
2399 copylen
= addr_size
>= ifa
->ifa_netmask
->sa_len
?
2400 ifa
->ifa_netmask
->sa_len
: addr_size
;
2401 bcopy(ifa
->ifa_netmask
, out_addr
, copylen
);
2403 if (ifa
->ifa_netmask
->sa_len
> addr_size
) {
2413 ifaddr_ifnet(ifaddr_t ifa
)
2420 /* ifa_ifp is set once at creation time; it is never changed */
2427 ifaddr_withaddr(const struct sockaddr
*address
)
2429 if (address
== NULL
)
2432 return (ifa_ifwithaddr(address
));
2436 ifaddr_withdstaddr(const struct sockaddr
*address
)
2438 if (address
== NULL
)
2441 return (ifa_ifwithdstaddr(address
));
2445 ifaddr_withnet(const struct sockaddr
*net
)
2450 return (ifa_ifwithnet(net
));
2454 ifaddr_withroute(int flags
, const struct sockaddr
*destination
,
2455 const struct sockaddr
*gateway
)
2457 if (destination
== NULL
|| gateway
== NULL
)
2460 return (ifa_ifwithroute(flags
, destination
, gateway
));
2464 ifaddr_findbestforaddr(const struct sockaddr
*addr
, ifnet_t interface
)
2466 if (addr
== NULL
|| interface
== NULL
)
2469 return (ifaof_ifpforaddr(addr
, interface
));
2473 ifmaddr_reference(ifmultiaddr_t ifmaddr
)
2475 if (ifmaddr
== NULL
)
2478 IFMA_ADDREF(ifmaddr
);
2483 ifmaddr_release(ifmultiaddr_t ifmaddr
)
2485 if (ifmaddr
== NULL
)
2488 IFMA_REMREF(ifmaddr
);
2493 ifmaddr_address(ifmultiaddr_t ifma
, struct sockaddr
*out_addr
,
2494 u_int32_t addr_size
)
2498 if (ifma
== NULL
|| out_addr
== NULL
)
2502 if (ifma
->ifma_addr
== NULL
) {
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
);
2511 if (ifma
->ifma_addr
->sa_len
> addr_size
) {
2520 ifmaddr_lladdress(ifmultiaddr_t ifma
, struct sockaddr
*out_addr
,
2521 u_int32_t addr_size
)
2523 struct ifmultiaddr
*ifma_ll
;
2525 if (ifma
== NULL
|| out_addr
== NULL
)
2527 if ((ifma_ll
= ifma
->ifma_ll
) == NULL
)
2530 return (ifmaddr_address(ifma_ll
, out_addr
, addr_size
));
2534 ifmaddr_ifnet(ifmultiaddr_t ifma
)
2536 return ((ifma
== NULL
) ? NULL
: ifma
->ifma_ifp
);
2539 /**************************************************************************/
2540 /* interface cloner */
2541 /**************************************************************************/
2544 ifnet_clone_attach(struct ifnet_clone_params
*cloner_params
,
2545 if_clone_t
*ifcloner
)
2548 struct if_clone
*ifc
= NULL
;
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
) {
2560 if (if_clone_lookup(cloner_params
->ifc_name
, NULL
) != NULL
) {
2561 printf("%s: already a cloner for %s\n", __func__
,
2562 cloner_params
->ifc_name
);
2567 /* Make room for name string */
2568 ifc
= _MALLOC(sizeof (struct if_clone
) + IFNAMSIZ
+ 1, M_CLONE
,
2571 printf("%s: _MALLOC failed\n", __func__
);
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
;
2582 error
= if_clone_attach(ifc
);
2584 printf("%s: if_clone_attach failed %d\n", __func__
, error
);
2597 ifnet_clone_detach(if_clone_t ifcloner
)
2600 struct if_clone
*ifc
= ifcloner
;
2602 if (ifc
== NULL
|| ifc
->ifc_name
== NULL
)
2605 if ((if_clone_lookup(ifc
->ifc_name
, NULL
)) == NULL
) {
2606 printf("%s: no cloner for %s\n", __func__
, ifc
->ifc_name
);
2611 if_clone_detach(ifc
);
2619 /**************************************************************************/
2621 /**************************************************************************/
2624 ifnet_get_local_ports_extended(ifnet_t ifp
, protocol_family_t protocol
,
2625 u_int32_t flags
, u_int8_t
*bitfield
)
2628 u_int32_t inp_flags
= 0;
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);
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);
2641 if (bitfield
== NULL
)
2653 /* bit string is long enough to hold 16-bit port values */
2654 bzero(bitfield
, bitstr_size(65536));
2656 ifindex
= (ifp
!= NULL
) ? ifp
->if_index
: 0;
2658 if (!(flags
& IFNET_GET_LOCAL_PORTS_TCPONLY
))
2659 udp_get_ports_used(ifindex
, protocol
, inp_flags
, bitfield
);
2661 if (!(flags
& IFNET_GET_LOCAL_PORTS_UDPONLY
))
2662 tcp_get_ports_used(ifindex
, protocol
, inp_flags
, bitfield
);
2668 ifnet_get_local_ports(ifnet_t ifp
, u_int8_t
*bitfield
)
2670 u_int32_t flags
= IFNET_GET_LOCAL_PORTS_WILDCARDOK
;
2671 return (ifnet_get_local_ports_extended(ifp
, PF_UNSPEC
, flags
,
2676 ifnet_notice_node_presence(ifnet_t ifp
, struct sockaddr
*sa
, int32_t rssi
,
2677 int lqm
, int npm
, u_int8_t srvinfo
[48])
2679 if (ifp
== NULL
|| sa
== NULL
|| srvinfo
== NULL
)
2681 if (sa
->sa_len
> sizeof(struct sockaddr_storage
))
2683 if (sa
->sa_family
!= AF_LINK
&& sa
->sa_family
!= AF_INET6
)
2686 dlil_node_present(ifp
, sa
, rssi
, lqm
, npm
, srvinfo
);
2691 ifnet_notice_node_absence(ifnet_t ifp
, struct sockaddr
*sa
)
2693 if (ifp
== NULL
|| sa
== NULL
)
2695 if (sa
->sa_len
> sizeof(struct sockaddr_storage
))
2697 if (sa
->sa_family
!= AF_LINK
&& sa
->sa_family
!= AF_INET6
)
2700 dlil_node_absent(ifp
, sa
);
2705 ifnet_notice_master_elected(ifnet_t ifp
)
2710 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_MASTER_ELECTED
, NULL
, 0);
2715 ifnet_tx_compl_status(ifnet_t ifp
, mbuf_t m
, tx_compl_val_t val
)
2719 m_do_tx_compl_callback(m
, ifp
);
2725 ifnet_tx_compl(ifnet_t ifp
, mbuf_t m
)
2727 m_do_tx_compl_callback(m
, ifp
);
2733 ifnet_report_issues(ifnet_t ifp
, u_int8_t modid
[IFNET_MODIDLEN
],
2734 u_int8_t info
[IFNET_MODARGLEN
])
2736 if (ifp
== NULL
|| modid
== NULL
)
2739 dlil_report_issues(ifp
, modid
, info
);
2744 ifnet_set_delegate(ifnet_t ifp
, ifnet_t delegated_ifp
)
2746 ifnet_t odifp
= NULL
;
2750 else if (!ifnet_is_attached(ifp
, 1))
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
);
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
);
2769 delegate_check_ifp
= delegate_check_ifp
->if_delegated
.ifp
;
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
;
2778 ifp
->if_delegated
.expensive
=
2779 delegated_ifp
->if_eflags
& IFEF_EXPENSIVE
? 1 : 0;
2782 * Propogate flags related to ECN from delegated interface
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
));
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
);
2794 ifnet_lock_done(ifp
);
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
);
2801 ifnet_release(odifp
);
2804 /* Generate a kernel event */
2805 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_IFDELEGATE_CHANGED
, NULL
, 0);
2808 /* Release the io ref count */
2809 ifnet_decr_iorefcnt(ifp
);
2815 ifnet_get_delegate(ifnet_t ifp
, ifnet_t
*pdelegated_ifp
)
2817 if (ifp
== NULL
|| pdelegated_ifp
== NULL
)
2819 else if (!ifnet_is_attached(ifp
, 1))
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
);
2828 /* Release the io ref count */
2829 ifnet_decr_iorefcnt(ifp
);
2835 ifnet_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
)
2842 if (frames_array
== NULL
|| used_frames_count
== NULL
||
2843 frame_data_offset
>= IFNET_KEEPALIVE_OFFLOAD_FRAME_DATA_SIZE
)
2846 /* frame_data_offset should be 32-bit aligned */
2847 if (P2ROUNDUP(frame_data_offset
, sizeof(u_int32_t
)) !=
2851 *used_frames_count
= 0;
2852 if (frames_array_count
== 0)
2855 for (i
= 0; i
< frames_array_count
; i
++) {
2856 struct ifnet_keepalive_offload_frame
*frame
= frames_array
+ i
;
2858 bzero(frame
, sizeof(struct ifnet_keepalive_offload_frame
));
2861 /* First collect IPSec related keep-alive frames */
2862 *used_frames_count
= key_fill_offload_frames_for_savs(ifp
,
2863 frames_array
, frames_array_count
, frame_data_offset
);
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
,
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
,
2877 VERIFY(*used_frames_count
<= frames_array_count
);
2883 ifnet_link_status_report(ifnet_t ifp
, const void *buffer
,
2886 struct if_link_status
*ifsr
;
2889 if (ifp
== NULL
|| buffer
== NULL
|| buffer_len
== 0)
2892 ifnet_lock_shared(ifp
);
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.
2898 if (!ifnet_is_attached(ifp
, 0)) {
2899 ifnet_lock_done(ifp
);
2903 lck_rw_lock_exclusive(&ifp
->if_link_status_lock
);
2906 * If this is the first status report then allocate memory
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
) {
2918 ifsr
= __DECONST(struct if_link_status
*, buffer
);
2920 if (ifp
->if_type
== IFT_CELLULAR
) {
2921 struct if_cellular_status_v1
*if_cell_sr
, *new_cell_sr
;
2923 * Currently we have a single version -- if it does
2924 * not match, just return.
2926 if (ifsr
->ifsr_version
!=
2927 IF_CELLULAR_STATUS_REPORT_CURRENT_VERSION
) {
2932 if (ifsr
->ifsr_len
!= sizeof(*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
;
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
);
2950 /* Finally copy the new information */
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
));
2956 } else if (ifp
->if_subfamily
== IFNET_SUBFAMILY_WIFI
) {
2957 struct if_wifi_status_v1
*if_wifi_sr
, *new_wifi_sr
;
2960 if (ifsr
->ifsr_version
!=
2961 IF_WIFI_STATUS_REPORT_CURRENT_VERSION
) {
2966 if (ifsr
->ifsr_len
!= sizeof(*if_wifi_sr
)) {
2972 &ifp
->if_link_status
->ifsr_u
.ifsr_wifi
.if_wifi_u
.if_status_v1
;
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
));
2981 * Update the bandwidth values if we got recent values
2982 * reported through the other KPI.
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
;
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
;
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
;
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
;
3019 lck_rw_done(&ifp
->if_link_status_lock
);
3020 ifnet_lock_done(ifp
);
3024 /*************************************************************************/
3025 /* Packet preamble */
3026 /*************************************************************************/
3028 #define MAX_IF_PACKET_PREAMBLE_LEN 32
3031 ifnet_set_packetpreamblelen(ifnet_t interface
, u_int32_t len
)
3035 if (interface
== NULL
|| len
> MAX_IF_PACKET_PREAMBLE_LEN
) {
3039 interface
->if_data
.ifi_preamblelen
= len
;
3045 ifnet_packetpreamblelen(ifnet_t interface
)
3047 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_preamblelen
);
3051 ifnet_maxpacketpreamblelen(void)
3053 return (MAX_IF_PACKET_PREAMBLE_LEN
);
3057 /*************************************************************************/
3058 /* Fastlane QoS Ca */
3059 /*************************************************************************/
3062 ifnet_set_fastlane_capable(ifnet_t interface
, boolean_t capable
)
3064 if (interface
== NULL
)
3067 if_set_qosmarking_mode(interface
,
3068 capable
? IFRTYPE_QOSMARKING_FASTLANE
: IFRTYPE_QOSMARKING_MODE_NONE
);
3074 ifnet_get_fastlane_capable(ifnet_t interface
, boolean_t
*capable
)
3076 if (interface
== NULL
|| capable
== NULL
)
3078 if (interface
->if_eflags
& IFEF_QOSMARKING_CAPABLE
)
3086 ifnet_get_unsent_bytes(ifnet_t interface
, int64_t *unsent_bytes
)
3090 if (interface
== NULL
|| unsent_bytes
== NULL
)
3093 bytes
= *unsent_bytes
= 0;
3095 if ((interface
->if_refflags
& (IFRF_ATTACHED
| IFRF_DETACHING
)) !=
3099 bytes
= interface
->if_sndbyte_unsent
;
3101 if (interface
->if_eflags
& IFEF_TXSTART
)
3102 bytes
+= IFCQ_BYTES(&interface
->if_snd
);
3103 *unsent_bytes
= bytes
;
3109 ifnet_get_buffer_status(const ifnet_t ifp
, ifnet_buffer_status_t
*buf_status
)
3111 if (ifp
== NULL
|| buf_status
== NULL
)
3114 bzero(buf_status
, sizeof (*buf_status
));
3116 if ((ifp
->if_refflags
& (IFRF_ATTACHED
| IFRF_DETACHING
)) !=
3120 buf_status
->buf_sndbuf
= ifp
->if_sndbyte_unsent
;
3122 if (ifp
->if_eflags
& IFEF_TXSTART
)
3123 buf_status
->buf_interface
= IFCQ_BYTES(&ifp
->if_snd
);
3129 ifnet_normalise_unsent_data(void)
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
)) !=
3138 ifnet_lock_done(ifp
);
3141 if (!(ifp
->if_eflags
& IFEF_TXSTART
)) {
3142 ifnet_lock_done(ifp
);
3146 if (ifp
->if_sndbyte_total
> 0 ||
3147 IFCQ_BYTES(&ifp
->if_snd
) > 0)
3148 ifp
->if_unsent_data_cnt
++;
3150 ifnet_lock_done(ifp
);