2 * Copyright (c) 2004-2012 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 <net/if_var.h>
43 #include <net/if_dl.h>
45 #include <net/if_types.h>
46 #include <net/if_dl.h>
47 #include <net/if_arp.h>
48 #include <net/if_llreach.h>
49 #include <net/route.h>
50 #include <libkern/libkern.h>
51 #include <libkern/OSAtomic.h>
52 #include <kern/locks.h>
53 #include <kern/clock.h>
54 #include <sys/sockio.h>
56 #include <sys/sysctl.h>
59 #include <netinet/igmp_var.h>
62 #include <netinet6/mld6_var.h>
65 #include "net/net_str_id.h"
67 #if IF_LASTCHANGEUPTIME
68 #define TOUCHLASTCHANGE(__if_lastchange) { \
69 (__if_lastchange)->tv_sec = net_uptime(); \
70 (__if_lastchange)->tv_usec = 0; \
73 #define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
76 #define _cast_non_const(p) ((void *)(uintptr_t)(p))
78 static errno_t
ifnet_defrouter_llreachinfo(ifnet_t
, int,
79 struct ifnet_llreach_info
*);
80 static void ifnet_kpi_free(ifnet_t
);
81 static errno_t
ifnet_list_get_common(ifnet_family_t
, boolean_t
, ifnet_t
**,
83 static errno_t
ifnet_set_lladdr_internal(ifnet_t
, const void *, size_t,
85 static errno_t
ifnet_awdl_check_eflags(ifnet_t
, u_int32_t
*, u_int32_t
*);
88 * Temporary work around until we have real reference counting
90 * We keep the bits about calling dlil_if_release (which should be
91 * called recycle) transparent by calling it from our if_free function
92 * pointer. We have to keep the client's original detach function
93 * somewhere so we can call it.
96 ifnet_kpi_free(ifnet_t ifp
)
98 ifnet_detached_func detach_func
= ifp
->if_kpi_storage
;
100 if (detach_func
!= NULL
)
103 if (ifp
->if_broadcast
.length
> sizeof (ifp
->if_broadcast
.u
.buffer
)) {
104 FREE(ifp
->if_broadcast
.u
.ptr
, M_IFADDR
);
105 ifp
->if_broadcast
.u
.ptr
= NULL
;
108 dlil_if_release(ifp
);
112 ifnet_allocate(const struct ifnet_init_params
*init
, ifnet_t
*interface
)
114 struct ifnet_init_eparams einit
;
116 bzero(&einit
, sizeof (einit
));
118 einit
.ver
= IFNET_INIT_CURRENT_VERSION
;
119 einit
.len
= sizeof (einit
);
120 einit
.flags
= IFNET_INIT_LEGACY
;
121 einit
.uniqueid
= init
->uniqueid
;
122 einit
.uniqueid_len
= init
->uniqueid_len
;
123 einit
.name
= init
->name
;
124 einit
.unit
= init
->unit
;
125 einit
.family
= init
->family
;
126 einit
.type
= init
->type
;
127 einit
.output
= init
->output
;
128 einit
.demux
= init
->demux
;
129 einit
.add_proto
= init
->add_proto
;
130 einit
.del_proto
= init
->del_proto
;
131 einit
.check_multi
= init
->check_multi
;
132 einit
.framer
= init
->framer
;
133 einit
.softc
= init
->softc
;
134 einit
.ioctl
= init
->ioctl
;
135 einit
.set_bpf_tap
= init
->set_bpf_tap
;
136 einit
.detach
= init
->detach
;
137 einit
.event
= init
->event
;
138 einit
.broadcast_addr
= init
->broadcast_addr
;
139 einit
.broadcast_len
= init
->broadcast_len
;
141 return (ifnet_allocate_extended(&einit
, interface
));
145 ifnet_allocate_extended(const struct ifnet_init_eparams
*einit0
,
148 struct ifnet_init_eparams einit
;
149 struct ifnet
*ifp
= NULL
;
154 if (einit
.ver
!= IFNET_INIT_CURRENT_VERSION
||
155 einit
.len
< sizeof (einit
))
158 if (einit
.family
== 0 || einit
.name
== NULL
||
159 strlen(einit
.name
) >= IFNAMSIZ
||
160 (einit
.type
& 0xFFFFFF00) != 0 || einit
.type
== 0)
163 if (einit
.flags
& IFNET_INIT_LEGACY
) {
164 if (einit
.output
== NULL
|| einit
.flags
!= IFNET_INIT_LEGACY
)
167 einit
.pre_enqueue
= NULL
;
169 einit
.output_ctl
= NULL
;
170 einit
.output_sched_model
= IFNET_SCHED_MODEL_NORMAL
;
171 einit
.input_poll
= NULL
;
172 einit
.input_ctl
= NULL
;
174 if (einit
.start
== NULL
)
178 if (einit
.output_sched_model
>= IFNET_SCHED_MODEL_MAX
)
181 if (einit
.flags
& IFNET_INIT_INPUT_POLL
) {
182 if (einit
.input_poll
== NULL
|| einit
.input_ctl
== NULL
)
185 einit
.input_poll
= NULL
;
186 einit
.input_ctl
= NULL
;
190 error
= dlil_if_acquire(einit
.family
, einit
.uniqueid
,
191 einit
.uniqueid_len
, &ifp
);
197 * Cast ifp->if_name as non const. dlil_if_acquire sets it up
198 * to point to storage of at least IFNAMSIZ bytes. It is safe
201 strncpy(_cast_non_const(ifp
->if_name
), einit
.name
, IFNAMSIZ
);
202 ifp
->if_type
= einit
.type
;
203 ifp
->if_family
= einit
.family
;
204 ifp
->if_unit
= einit
.unit
;
205 ifp
->if_output
= einit
.output
;
206 ifp
->if_pre_enqueue
= einit
.pre_enqueue
;
207 ifp
->if_start
= einit
.start
;
208 ifp
->if_output_ctl
= einit
.output_ctl
;
209 ifp
->if_output_sched_model
= einit
.output_sched_model
;
210 ifp
->if_output_bw
.eff_bw
= einit
.output_bw
;
211 ifp
->if_output_bw
.max_bw
= einit
.output_bw_max
;
212 ifp
->if_input_poll
= einit
.input_poll
;
213 ifp
->if_input_ctl
= einit
.input_ctl
;
214 ifp
->if_input_bw
.eff_bw
= einit
.input_bw
;
215 ifp
->if_input_bw
.max_bw
= einit
.input_bw_max
;
216 ifp
->if_demux
= einit
.demux
;
217 ifp
->if_add_proto
= einit
.add_proto
;
218 ifp
->if_del_proto
= einit
.del_proto
;
219 ifp
->if_check_multi
= einit
.check_multi
;
220 ifp
->if_framer
= einit
.framer
;
221 ifp
->if_softc
= einit
.softc
;
222 ifp
->if_ioctl
= einit
.ioctl
;
223 ifp
->if_set_bpf_tap
= einit
.set_bpf_tap
;
224 ifp
->if_free
= ifnet_kpi_free
;
225 ifp
->if_event
= einit
.event
;
226 ifp
->if_kpi_storage
= einit
.detach
;
228 if (ifp
->if_output_bw
.eff_bw
> ifp
->if_output_bw
.max_bw
)
229 ifp
->if_output_bw
.max_bw
= ifp
->if_output_bw
.eff_bw
;
230 else if (ifp
->if_output_bw
.eff_bw
== 0)
231 ifp
->if_output_bw
.eff_bw
= ifp
->if_output_bw
.max_bw
;
233 if (ifp
->if_input_bw
.eff_bw
> ifp
->if_input_bw
.max_bw
)
234 ifp
->if_input_bw
.max_bw
= ifp
->if_input_bw
.eff_bw
;
235 else if (ifp
->if_input_bw
.eff_bw
== 0)
236 ifp
->if_input_bw
.eff_bw
= ifp
->if_input_bw
.max_bw
;
238 if (ifp
->if_output_bw
.max_bw
== 0)
239 ifp
->if_output_bw
= ifp
->if_input_bw
;
240 else if (ifp
->if_input_bw
.max_bw
== 0)
241 ifp
->if_input_bw
= ifp
->if_output_bw
;
243 if (ifp
->if_ioctl
== NULL
)
244 ifp
->if_ioctl
= ifp_if_ioctl
;
246 /* Pin if_baudrate to 32 bits */
247 br
= MAX(ifp
->if_output_bw
.max_bw
, ifp
->if_input_bw
.max_bw
);
249 ifp
->if_baudrate
= (br
> 0xFFFFFFFF) ? 0xFFFFFFFF : br
;
251 if (ifp
->if_start
!= NULL
) {
252 ifp
->if_eflags
|= IFEF_TXSTART
;
253 if (ifp
->if_pre_enqueue
== NULL
)
254 ifp
->if_pre_enqueue
= ifnet_enqueue
;
255 ifp
->if_output
= ifp
->if_pre_enqueue
;
257 ifp
->if_eflags
&= ~IFEF_TXSTART
;
260 if (ifp
->if_input_poll
!= NULL
)
261 ifp
->if_eflags
|= IFEF_RXPOLL
;
263 ifp
->if_eflags
&= ~IFEF_RXPOLL
;
265 VERIFY(!(einit
.flags
& IFNET_INIT_LEGACY
) ||
266 (ifp
->if_pre_enqueue
== NULL
&& ifp
->if_start
== NULL
&&
267 ifp
->if_output_ctl
== NULL
&& ifp
->if_input_poll
== NULL
&&
268 ifp
->if_input_ctl
== NULL
));
269 VERIFY(!(einit
.flags
& IFNET_INIT_INPUT_POLL
) ||
270 (ifp
->if_input_poll
!= NULL
&& ifp
->if_input_ctl
!= NULL
));
272 if (einit
.broadcast_len
&& einit
.broadcast_addr
) {
273 if (einit
.broadcast_len
>
274 sizeof (ifp
->if_broadcast
.u
.buffer
)) {
275 MALLOC(ifp
->if_broadcast
.u
.ptr
, u_char
*,
276 einit
.broadcast_len
, M_IFADDR
, M_NOWAIT
);
277 if (ifp
->if_broadcast
.u
.ptr
== NULL
) {
280 bcopy(einit
.broadcast_addr
,
281 ifp
->if_broadcast
.u
.ptr
,
282 einit
.broadcast_len
);
285 bcopy(einit
.broadcast_addr
,
286 ifp
->if_broadcast
.u
.buffer
,
287 einit
.broadcast_len
);
289 ifp
->if_broadcast
.length
= einit
.broadcast_len
;
291 bzero(&ifp
->if_broadcast
, sizeof (ifp
->if_broadcast
));
294 IFCQ_MAXLEN(&ifp
->if_snd
) = einit
.sndq_maxlen
;
298 // temporary - this should be done in dlil_if_acquire
299 ifnet_reference(ifp
);
301 dlil_if_release(ifp
);
307 * Note: We should do something here to indicate that we haven't been
308 * attached yet. By doing so, we can catch the case in ifnet_release
309 * where the reference count reaches zero and call the recycle
310 * function. If the interface is attached, the interface will be
311 * recycled when the interface's if_free function is called. If the
312 * interface is never attached, the if_free function will never be
313 * called and the interface will never be recycled.
320 ifnet_reference(ifnet_t ifp
)
322 return (dlil_if_ref(ifp
));
326 ifnet_release(ifnet_t ifp
)
328 return (dlil_if_free(ifp
));
332 ifnet_interface_family_find(const char *module_string
,
333 ifnet_family_t
*family_id
)
335 if (module_string
== NULL
|| family_id
== NULL
)
338 return (net_str_id_find_internal(module_string
, family_id
,
343 ifnet_softc(ifnet_t interface
)
345 return ((interface
== NULL
) ? NULL
: interface
->if_softc
);
349 ifnet_name(ifnet_t interface
)
351 return ((interface
== NULL
) ? NULL
: interface
->if_name
);
355 ifnet_family(ifnet_t interface
)
357 return ((interface
== NULL
) ? 0 : interface
->if_family
);
361 ifnet_unit(ifnet_t interface
)
363 return ((interface
== NULL
) ? (u_int32_t
)0xffffffff :
364 (u_int32_t
)interface
->if_unit
);
368 ifnet_index(ifnet_t interface
)
370 return ((interface
== NULL
) ? (u_int32_t
)0xffffffff :
371 interface
->if_index
);
375 ifnet_set_flags(ifnet_t interface
, u_int16_t new_flags
, u_int16_t mask
)
379 if (interface
== NULL
)
382 ifnet_lock_exclusive(interface
);
384 /* If we are modifying the up/down state, call if_updown */
385 if ((mask
& IFF_UP
) != 0) {
386 if_updown(interface
, (new_flags
& IFF_UP
) == IFF_UP
);
389 old_flags
= interface
->if_flags
;
390 interface
->if_flags
= (new_flags
& mask
) | (interface
->if_flags
& ~mask
);
391 /* If we are modifying the multicast flag, set/unset the silent flag */
392 if ((old_flags
& IFF_MULTICAST
) !=
393 (interface
->if_flags
& IFF_MULTICAST
)) {
395 if (IGMP_IFINFO(interface
) != NULL
)
396 igmp_initsilent(interface
, IGMP_IFINFO(interface
));
399 if (MLD_IFINFO(interface
) != NULL
)
400 mld6_initsilent(interface
, MLD_IFINFO(interface
));
404 ifnet_lock_done(interface
);
410 ifnet_flags(ifnet_t interface
)
412 return ((interface
== NULL
) ? 0 : interface
->if_flags
);
416 * This routine ensures the following:
418 * If IFEF_AWDL is set by the caller, also set the rest of flags as
419 * defined in IFEF_AWDL_MASK.
421 * If IFEF_AWDL has been set on the interface and the caller attempts
422 * to clear one or more of the associated flags in IFEF_AWDL_MASK,
425 * All other flags not associated with AWDL are not affected.
427 * See <net/if.h> for current definition of IFEF_AWDL_MASK.
430 ifnet_awdl_check_eflags(ifnet_t ifp
, u_int32_t
*new_eflags
, u_int32_t
*mask
)
434 ifnet_lock_assert(ifp
, IFNET_LCK_ASSERT_EXCLUSIVE
);
436 eflags
= (*new_eflags
& *mask
) | (ifp
->if_eflags
& ~(*mask
));
438 if (ifp
->if_eflags
& IFEF_AWDL
) {
439 if (eflags
& IFEF_AWDL
) {
440 if ((eflags
& IFEF_AWDL_MASK
) != IFEF_AWDL_MASK
)
443 *new_eflags
&= ~IFEF_AWDL_MASK
;
444 *mask
|= IFEF_AWDL_MASK
;
446 } else if (eflags
& IFEF_AWDL
) {
447 *new_eflags
|= IFEF_AWDL_MASK
;
448 *mask
|= IFEF_AWDL_MASK
;
455 ifnet_set_eflags(ifnet_t interface
, u_int32_t new_flags
, u_int32_t mask
)
457 if (interface
== NULL
)
460 ifnet_lock_exclusive(interface
);
462 * Sanity checks for IFEF_AWDL and its related flags.
464 if (ifnet_awdl_check_eflags(interface
, &new_flags
, &mask
) != 0) {
465 ifnet_lock_done(interface
);
468 interface
->if_eflags
=
469 (new_flags
& mask
) | (interface
->if_eflags
& ~mask
);
470 ifnet_lock_done(interface
);
476 ifnet_eflags(ifnet_t interface
)
478 return ((interface
== NULL
) ? 0 : interface
->if_eflags
);
482 ifnet_set_idle_flags_locked(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
489 lck_mtx_assert(rnh_lock
, LCK_MTX_ASSERT_OWNED
);
490 ifnet_lock_assert(ifp
, IFNET_LCK_ASSERT_EXCLUSIVE
);
493 * If this is called prior to ifnet attach, the actual work will
494 * be done at attach time. Otherwise, if it is called after
495 * ifnet detach, then it is a no-op.
497 if (!ifnet_is_attached(ifp
, 0)) {
498 ifp
->if_idle_new_flags
= new_flags
;
499 ifp
->if_idle_new_flags_mask
= mask
;
502 ifp
->if_idle_new_flags
= ifp
->if_idle_new_flags_mask
= 0;
505 before
= ifp
->if_idle_flags
;
506 ifp
->if_idle_flags
= (new_flags
& mask
) | (ifp
->if_idle_flags
& ~mask
);
507 after
= ifp
->if_idle_flags
;
509 if ((after
- before
) < 0 && ifp
->if_idle_flags
== 0 &&
510 ifp
->if_want_aggressive_drain
!= 0) {
511 ifp
->if_want_aggressive_drain
= 0;
512 if (ifnet_aggressive_drainers
== 0)
513 panic("%s: ifp=%p negative aggdrain!", __func__
, ifp
);
514 if (--ifnet_aggressive_drainers
== 0)
516 } else if ((after
- before
) > 0 && ifp
->if_want_aggressive_drain
== 0) {
517 ifp
->if_want_aggressive_drain
++;
518 if (++ifnet_aggressive_drainers
== 0)
519 panic("%s: ifp=%p wraparound aggdrain!", __func__
, ifp
);
520 else if (ifnet_aggressive_drainers
== 1)
528 ifnet_set_idle_flags(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
532 lck_mtx_lock(rnh_lock
);
533 ifnet_lock_exclusive(ifp
);
534 err
= ifnet_set_idle_flags_locked(ifp
, new_flags
, mask
);
535 ifnet_lock_done(ifp
);
536 lck_mtx_unlock(rnh_lock
);
542 ifnet_idle_flags(ifnet_t ifp
)
544 return ((ifp
== NULL
) ? 0 : ifp
->if_idle_flags
);
548 ifnet_set_link_quality(ifnet_t ifp
, int quality
)
552 if (ifp
== NULL
|| quality
< IFNET_LQM_MIN
|| quality
> IFNET_LQM_MAX
) {
557 if (!ifnet_is_attached(ifp
, 0)) {
562 if_lqm_update(ifp
, quality
);
569 ifnet_link_quality(ifnet_t ifp
)
574 return (IFNET_LQM_THRESH_OFF
);
576 ifnet_lock_shared(ifp
);
578 ifnet_lock_done(ifp
);
584 ifnet_defrouter_llreachinfo(ifnet_t ifp
, int af
,
585 struct ifnet_llreach_info
*iflri
)
587 if (ifp
== NULL
|| iflri
== NULL
)
590 VERIFY(af
== AF_INET
|| af
== AF_INET6
);
592 return (ifnet_llreach_get_defrouter(ifp
, af
, iflri
));
596 ifnet_inet_defrouter_llreachinfo(ifnet_t ifp
, struct ifnet_llreach_info
*iflri
)
598 return (ifnet_defrouter_llreachinfo(ifp
, AF_INET
, iflri
));
602 ifnet_inet6_defrouter_llreachinfo(ifnet_t ifp
, struct ifnet_llreach_info
*iflri
)
604 return (ifnet_defrouter_llreachinfo(ifp
, AF_INET6
, iflri
));
608 ifnet_set_capabilities_supported(ifnet_t ifp
, u_int32_t new_caps
,
617 ifnet_lock_exclusive(ifp
);
618 tmp
= (new_caps
& mask
) | (ifp
->if_capabilities
& ~mask
);
619 if ((tmp
& ~IFCAP_VALID
))
622 ifp
->if_capabilities
= tmp
;
623 ifnet_lock_done(ifp
);
629 ifnet_capabilities_supported(ifnet_t ifp
)
631 return ((ifp
== NULL
) ? 0 : ifp
->if_capabilities
);
636 ifnet_set_capabilities_enabled(ifnet_t ifp
, u_int32_t new_caps
,
641 struct kev_msg ev_msg
;
642 struct net_event_data ev_data
;
647 ifnet_lock_exclusive(ifp
);
648 tmp
= (new_caps
& mask
) | (ifp
->if_capenable
& ~mask
);
649 if ((tmp
& ~IFCAP_VALID
) || (tmp
& ~ifp
->if_capabilities
))
652 ifp
->if_capenable
= tmp
;
653 ifnet_lock_done(ifp
);
655 /* Notify application of the change */
656 bzero(&ev_data
, sizeof (struct net_event_data
));
657 bzero(&ev_msg
, sizeof (struct kev_msg
));
658 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
659 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
660 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
662 ev_msg
.event_code
= KEV_DL_IFCAP_CHANGED
;
663 strlcpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
664 ev_data
.if_family
= ifp
->if_family
;
665 ev_data
.if_unit
= (u_int32_t
)ifp
->if_unit
;
666 ev_msg
.dv
[0].data_length
= sizeof (struct net_event_data
);
667 ev_msg
.dv
[0].data_ptr
= &ev_data
;
668 ev_msg
.dv
[1].data_length
= 0;
669 kev_post_msg(&ev_msg
);
675 ifnet_capabilities_enabled(ifnet_t ifp
)
677 return ((ifp
== NULL
) ? 0 : ifp
->if_capenable
);
680 static const ifnet_offload_t offload_mask
=
681 (IFNET_CSUM_IP
| IFNET_CSUM_TCP
| IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
|
682 IFNET_IP_FRAGMENT
| IFNET_CSUM_TCPIPV6
| IFNET_CSUM_UDPIPV6
|
683 IFNET_IPV6_FRAGMENT
| IFNET_CSUM_SUM16
| IFNET_VLAN_TAGGING
|
684 IFNET_VLAN_MTU
| IFNET_MULTIPAGES
| IFNET_TSO_IPV4
| IFNET_TSO_IPV6
);
686 static const ifnet_offload_t any_offload_csum
=
687 (IFNET_CSUM_IP
| IFNET_CSUM_TCP
| IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
|
688 IFNET_CSUM_TCPIPV6
| IFNET_CSUM_UDPIPV6
| IFNET_CSUM_SUM16
);
691 ifnet_set_offload(ifnet_t interface
, ifnet_offload_t offload
)
693 u_int32_t ifcaps
= 0;
695 if (interface
== NULL
)
698 ifnet_lock_exclusive(interface
);
699 interface
->if_hwassist
= (offload
& offload_mask
);
700 ifnet_lock_done(interface
);
702 if ((offload
& any_offload_csum
))
703 ifcaps
|= IFCAP_HWCSUM
;
704 if ((offload
& IFNET_TSO_IPV4
))
705 ifcaps
|= IFCAP_TSO4
;
706 if ((offload
& IFNET_TSO_IPV6
))
707 ifcaps
|= IFCAP_TSO6
;
708 if ((offload
& IFNET_VLAN_MTU
))
709 ifcaps
|= IFCAP_VLAN_MTU
;
710 if ((offload
& IFNET_VLAN_TAGGING
))
711 ifcaps
|= IFCAP_VLAN_HWTAGGING
;
713 (void) ifnet_set_capabilities_supported(interface
, ifcaps
,
715 (void) ifnet_set_capabilities_enabled(interface
, ifcaps
,
723 ifnet_offload(ifnet_t interface
)
725 return ((interface
== NULL
) ?
726 0 : (interface
->if_hwassist
& offload_mask
));
730 ifnet_set_tso_mtu(ifnet_t interface
, sa_family_t family
, u_int32_t mtuLen
)
734 if (interface
== NULL
|| mtuLen
< interface
->if_mtu
)
739 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
740 interface
->if_tso_v4_mtu
= mtuLen
;
746 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
747 interface
->if_tso_v6_mtu
= mtuLen
;
753 error
= EPROTONOSUPPORT
;
761 ifnet_get_tso_mtu(ifnet_t interface
, sa_family_t family
, u_int32_t
*mtuLen
)
765 if (interface
== NULL
|| mtuLen
== NULL
)
770 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
771 *mtuLen
= interface
->if_tso_v4_mtu
;
777 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
778 *mtuLen
= interface
->if_tso_v6_mtu
;
784 error
= EPROTONOSUPPORT
;
792 ifnet_set_wake_flags(ifnet_t interface
, u_int32_t properties
, u_int32_t mask
)
794 struct kev_msg ev_msg
;
795 struct net_event_data ev_data
;
797 bzero(&ev_data
, sizeof (struct net_event_data
));
798 bzero(&ev_msg
, sizeof (struct kev_msg
));
800 if (interface
== NULL
)
803 /* Do not accept wacky values */
804 if ((properties
& mask
) & ~IF_WAKE_VALID_FLAGS
)
807 ifnet_lock_exclusive(interface
);
809 interface
->if_wake_properties
=
810 (properties
& mask
) | (interface
->if_wake_properties
& ~mask
);
812 ifnet_lock_done(interface
);
814 (void) ifnet_touch_lastchange(interface
);
816 /* Notify application of the change */
817 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
818 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
819 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
821 ev_msg
.event_code
= KEV_DL_WAKEFLAGS_CHANGED
;
822 strlcpy(&ev_data
.if_name
[0], interface
->if_name
, IFNAMSIZ
);
823 ev_data
.if_family
= interface
->if_family
;
824 ev_data
.if_unit
= (u_int32_t
)interface
->if_unit
;
825 ev_msg
.dv
[0].data_length
= sizeof (struct net_event_data
);
826 ev_msg
.dv
[0].data_ptr
= &ev_data
;
827 ev_msg
.dv
[1].data_length
= 0;
828 kev_post_msg(&ev_msg
);
834 ifnet_get_wake_flags(ifnet_t interface
)
836 return ((interface
== NULL
) ? 0 : interface
->if_wake_properties
);
840 * Should MIB data store a copy?
843 ifnet_set_link_mib_data(ifnet_t interface
, void *mibData
, u_int32_t mibLen
)
845 if (interface
== NULL
)
848 ifnet_lock_exclusive(interface
);
849 interface
->if_linkmib
= (void*)mibData
;
850 interface
->if_linkmiblen
= mibLen
;
851 ifnet_lock_done(interface
);
856 ifnet_get_link_mib_data(ifnet_t interface
, void *mibData
, u_int32_t
*mibLen
)
860 if (interface
== NULL
)
863 ifnet_lock_shared(interface
);
864 if (*mibLen
< interface
->if_linkmiblen
)
866 if (result
== 0 && interface
->if_linkmib
== NULL
)
870 *mibLen
= interface
->if_linkmiblen
;
871 bcopy(interface
->if_linkmib
, mibData
, *mibLen
);
873 ifnet_lock_done(interface
);
879 ifnet_get_link_mib_data_length(ifnet_t interface
)
881 return ((interface
== NULL
) ? 0 : interface
->if_linkmiblen
);
885 ifnet_output(ifnet_t interface
, protocol_family_t protocol_family
,
886 mbuf_t m
, void *route
, const struct sockaddr
*dest
)
888 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
893 return (dlil_output(interface
, protocol_family
, m
, route
, dest
, 0, NULL
));
897 ifnet_output_raw(ifnet_t interface
, protocol_family_t protocol_family
, mbuf_t m
)
899 if (interface
== NULL
|| m
== NULL
) {
904 return (dlil_output(interface
, protocol_family
, m
, NULL
, NULL
, 1, NULL
));
908 ifnet_set_mtu(ifnet_t interface
, u_int32_t mtu
)
910 if (interface
== NULL
)
913 interface
->if_mtu
= mtu
;
918 ifnet_mtu(ifnet_t interface
)
920 return ((interface
== NULL
) ? 0 : interface
->if_mtu
);
924 ifnet_type(ifnet_t interface
)
926 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_type
);
930 ifnet_set_addrlen(ifnet_t interface
, u_char addrlen
)
932 if (interface
== NULL
)
935 interface
->if_data
.ifi_addrlen
= addrlen
;
940 ifnet_addrlen(ifnet_t interface
)
942 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_addrlen
);
946 ifnet_set_hdrlen(ifnet_t interface
, u_char hdrlen
)
948 if (interface
== NULL
)
951 interface
->if_data
.ifi_hdrlen
= hdrlen
;
956 ifnet_hdrlen(ifnet_t interface
)
958 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_hdrlen
);
962 ifnet_set_metric(ifnet_t interface
, u_int32_t metric
)
964 if (interface
== NULL
)
967 interface
->if_data
.ifi_metric
= metric
;
972 ifnet_metric(ifnet_t interface
)
974 return ((interface
== NULL
) ? 0 : interface
->if_data
.ifi_metric
);
978 ifnet_set_baudrate(struct ifnet
*ifp
, u_int64_t baudrate
)
983 ifp
->if_output_bw
.max_bw
= ifp
->if_input_bw
.max_bw
=
984 ifp
->if_output_bw
.eff_bw
= ifp
->if_input_bw
.eff_bw
= baudrate
;
986 /* Pin if_baudrate to 32 bits until we can change the storage size */
987 ifp
->if_baudrate
= (baudrate
> 0xFFFFFFFF) ? 0xFFFFFFFF : baudrate
;
993 ifnet_baudrate(struct ifnet
*ifp
)
995 return ((ifp
== NULL
) ? 0 : ifp
->if_baudrate
);
999 ifnet_set_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*output_bw
,
1000 struct if_bandwidths
*input_bw
)
1005 if (input_bw
!= NULL
)
1006 (void) ifnet_set_input_bandwidths(ifp
, input_bw
);
1008 if (output_bw
!= NULL
)
1009 (void) ifnet_set_output_bandwidths(ifp
, output_bw
, FALSE
);
1015 ifnet_set_output_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*bw
,
1018 struct if_bandwidths old_bw
;
1019 struct ifclassq
*ifq
;
1025 IFCQ_LOCK_ASSERT_HELD(ifq
);
1027 old_bw
= ifp
->if_output_bw
;
1029 if (bw
->eff_bw
!= 0)
1030 ifp
->if_output_bw
.eff_bw
= bw
->eff_bw
;
1031 if (bw
->max_bw
!= 0)
1032 ifp
->if_output_bw
.max_bw
= bw
->max_bw
;
1033 if (ifp
->if_output_bw
.eff_bw
> ifp
->if_output_bw
.max_bw
)
1034 ifp
->if_output_bw
.max_bw
= ifp
->if_output_bw
.eff_bw
;
1035 else if (ifp
->if_output_bw
.eff_bw
== 0)
1036 ifp
->if_output_bw
.eff_bw
= ifp
->if_output_bw
.max_bw
;
1039 /* Pin if_baudrate to 32 bits */
1040 br
= MAX(ifp
->if_output_bw
.max_bw
, ifp
->if_input_bw
.max_bw
);
1042 ifp
->if_baudrate
= (br
> 0xFFFFFFFF) ? 0xFFFFFFFF : br
;
1044 /* Adjust queue parameters if needed */
1045 if (old_bw
.eff_bw
!= ifp
->if_output_bw
.eff_bw
||
1046 old_bw
.max_bw
!= ifp
->if_output_bw
.max_bw
)
1047 ifnet_update_sndq(ifq
, CLASSQ_EV_LINK_SPEED
);
1056 ifnet_set_input_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*bw
)
1058 struct if_bandwidths old_bw
;
1060 old_bw
= ifp
->if_input_bw
;
1061 if (bw
->eff_bw
!= 0)
1062 ifp
->if_input_bw
.eff_bw
= bw
->eff_bw
;
1063 if (bw
->max_bw
!= 0)
1064 ifp
->if_input_bw
.max_bw
= bw
->max_bw
;
1065 if (ifp
->if_input_bw
.eff_bw
> ifp
->if_input_bw
.max_bw
)
1066 ifp
->if_input_bw
.max_bw
= ifp
->if_input_bw
.eff_bw
;
1067 else if (ifp
->if_input_bw
.eff_bw
== 0)
1068 ifp
->if_input_bw
.eff_bw
= ifp
->if_input_bw
.max_bw
;
1070 if (old_bw
.eff_bw
!= ifp
->if_input_bw
.eff_bw
||
1071 old_bw
.max_bw
!= ifp
->if_input_bw
.max_bw
)
1072 ifnet_update_rcv(ifp
, CLASSQ_EV_LINK_SPEED
);
1078 ifnet_output_linkrate(struct ifnet
*ifp
)
1080 struct ifclassq
*ifq
= &ifp
->if_snd
;
1083 IFCQ_LOCK_ASSERT_HELD(ifq
);
1085 rate
= ifp
->if_output_bw
.eff_bw
;
1086 if (IFCQ_TBR_IS_ENABLED(ifq
)) {
1087 u_int64_t tbr_rate
= ifp
->if_snd
.ifcq_tbr
.tbr_rate_raw
;
1088 VERIFY(tbr_rate
> 0);
1089 rate
= MIN(rate
, ifp
->if_snd
.ifcq_tbr
.tbr_rate_raw
);
1096 ifnet_input_linkrate(struct ifnet
*ifp
)
1098 return (ifp
->if_input_bw
.eff_bw
);
1102 ifnet_bandwidths(struct ifnet
*ifp
, struct if_bandwidths
*output_bw
,
1103 struct if_bandwidths
*input_bw
)
1108 if (output_bw
!= NULL
)
1109 *output_bw
= ifp
->if_output_bw
;
1110 if (input_bw
!= NULL
)
1111 *input_bw
= ifp
->if_input_bw
;
1117 ifnet_stat_increment(struct ifnet
*ifp
,
1118 const struct ifnet_stat_increment_param
*s
)
1123 if (s
->packets_in
!= 0)
1124 atomic_add_64(&ifp
->if_data
.ifi_ipackets
, s
->packets_in
);
1125 if (s
->bytes_in
!= 0)
1126 atomic_add_64(&ifp
->if_data
.ifi_ibytes
, s
->bytes_in
);
1127 if (s
->errors_in
!= 0)
1128 atomic_add_64(&ifp
->if_data
.ifi_ierrors
, s
->errors_in
);
1130 if (s
->packets_out
!= 0)
1131 atomic_add_64(&ifp
->if_data
.ifi_opackets
, s
->packets_out
);
1132 if (s
->bytes_out
!= 0)
1133 atomic_add_64(&ifp
->if_data
.ifi_obytes
, s
->bytes_out
);
1134 if (s
->errors_out
!= 0)
1135 atomic_add_64(&ifp
->if_data
.ifi_oerrors
, s
->errors_out
);
1137 if (s
->collisions
!= 0)
1138 atomic_add_64(&ifp
->if_data
.ifi_collisions
, s
->collisions
);
1139 if (s
->dropped
!= 0)
1140 atomic_add_64(&ifp
->if_data
.ifi_iqdrops
, s
->dropped
);
1142 /* Touch the last change time. */
1143 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1149 ifnet_stat_increment_in(struct ifnet
*ifp
, u_int32_t packets_in
,
1150 u_int32_t bytes_in
, u_int32_t errors_in
)
1155 if (packets_in
!= 0)
1156 atomic_add_64(&ifp
->if_data
.ifi_ipackets
, packets_in
);
1158 atomic_add_64(&ifp
->if_data
.ifi_ibytes
, bytes_in
);
1160 atomic_add_64(&ifp
->if_data
.ifi_ierrors
, errors_in
);
1162 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1168 ifnet_stat_increment_out(struct ifnet
*ifp
, u_int32_t packets_out
,
1169 u_int32_t bytes_out
, u_int32_t errors_out
)
1174 if (packets_out
!= 0)
1175 atomic_add_64(&ifp
->if_data
.ifi_opackets
, packets_out
);
1177 atomic_add_64(&ifp
->if_data
.ifi_obytes
, bytes_out
);
1178 if (errors_out
!= 0)
1179 atomic_add_64(&ifp
->if_data
.ifi_oerrors
, errors_out
);
1181 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1187 ifnet_set_stat(struct ifnet
*ifp
, const struct ifnet_stats_param
*s
)
1192 atomic_set_64(&ifp
->if_data
.ifi_ipackets
, s
->packets_in
);
1193 atomic_set_64(&ifp
->if_data
.ifi_ibytes
, s
->bytes_in
);
1194 atomic_set_64(&ifp
->if_data
.ifi_imcasts
, s
->multicasts_in
);
1195 atomic_set_64(&ifp
->if_data
.ifi_ierrors
, s
->errors_in
);
1197 atomic_set_64(&ifp
->if_data
.ifi_opackets
, s
->packets_out
);
1198 atomic_set_64(&ifp
->if_data
.ifi_obytes
, s
->bytes_out
);
1199 atomic_set_64(&ifp
->if_data
.ifi_omcasts
, s
->multicasts_out
);
1200 atomic_set_64(&ifp
->if_data
.ifi_oerrors
, s
->errors_out
);
1202 atomic_set_64(&ifp
->if_data
.ifi_collisions
, s
->collisions
);
1203 atomic_set_64(&ifp
->if_data
.ifi_iqdrops
, s
->dropped
);
1204 atomic_set_64(&ifp
->if_data
.ifi_noproto
, s
->no_protocol
);
1206 /* Touch the last change time. */
1207 TOUCHLASTCHANGE(&ifp
->if_lastchange
);
1213 ifnet_stat(struct ifnet
*ifp
, struct ifnet_stats_param
*s
)
1218 atomic_get_64(s
->packets_in
, &ifp
->if_data
.ifi_ipackets
);
1219 atomic_get_64(s
->bytes_in
, &ifp
->if_data
.ifi_ibytes
);
1220 atomic_get_64(s
->multicasts_in
, &ifp
->if_data
.ifi_imcasts
);
1221 atomic_get_64(s
->errors_in
, &ifp
->if_data
.ifi_ierrors
);
1223 atomic_get_64(s
->packets_out
, &ifp
->if_data
.ifi_opackets
);
1224 atomic_get_64(s
->bytes_out
, &ifp
->if_data
.ifi_obytes
);
1225 atomic_get_64(s
->multicasts_out
, &ifp
->if_data
.ifi_omcasts
);
1226 atomic_get_64(s
->errors_out
, &ifp
->if_data
.ifi_oerrors
);
1228 atomic_get_64(s
->collisions
, &ifp
->if_data
.ifi_collisions
);
1229 atomic_get_64(s
->dropped
, &ifp
->if_data
.ifi_iqdrops
);
1230 atomic_get_64(s
->no_protocol
, &ifp
->if_data
.ifi_noproto
);
1236 ifnet_touch_lastchange(ifnet_t interface
)
1238 if (interface
== NULL
)
1241 TOUCHLASTCHANGE(&interface
->if_lastchange
);
1247 ifnet_lastchange(ifnet_t interface
, struct timeval
*last_change
)
1249 if (interface
== NULL
)
1252 *last_change
= interface
->if_data
.ifi_lastchange
;
1253 #if IF_LASTCHANGEUPTIME
1254 /* Crude conversion from uptime to calendar time */
1255 last_change
->tv_sec
+= boottime_sec();
1261 ifnet_get_address_list(ifnet_t interface
, ifaddr_t
**addresses
)
1263 return (addresses
== NULL
? EINVAL
:
1264 ifnet_get_address_list_family(interface
, addresses
, 0));
1267 struct ifnet_addr_list
{
1268 SLIST_ENTRY(ifnet_addr_list
) ifal_le
;
1269 struct ifaddr
*ifal_ifa
;
1273 ifnet_get_address_list_family(ifnet_t interface
, ifaddr_t
**addresses
,
1276 return (ifnet_get_address_list_family_internal(interface
, addresses
,
1277 family
, 0, M_NOWAIT
));
1280 __private_extern__ errno_t
1281 ifnet_get_address_list_family_internal(ifnet_t interface
, ifaddr_t
**addresses
,
1282 sa_family_t family
, int detached
, int how
)
1284 SLIST_HEAD(, ifnet_addr_list
) ifal_head
;
1285 struct ifnet_addr_list
*ifal
, *ifal_tmp
;
1290 SLIST_INIT(&ifal_head
);
1292 if (addresses
== NULL
) {
1300 * Interface has been detached, so skip the lookup
1301 * at ifnet_head and go directly to inner loop.
1311 ifnet_head_lock_shared();
1312 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
1313 if (interface
!= NULL
&& ifp
!= interface
)
1316 ifnet_lock_shared(ifp
);
1317 if (interface
== NULL
|| interface
== ifp
) {
1319 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1322 ifa
->ifa_addr
->sa_family
!= family
) {
1326 MALLOC(ifal
, struct ifnet_addr_list
*,
1327 sizeof (*ifal
), M_TEMP
, how
);
1330 ifnet_lock_done(ifp
);
1336 ifal
->ifal_ifa
= ifa
;
1337 IFA_ADDREF_LOCKED(ifa
);
1338 SLIST_INSERT_HEAD(&ifal_head
, ifal
, ifal_le
);
1343 ifnet_lock_done(ifp
);
1354 MALLOC(*addresses
, ifaddr_t
*, sizeof (ifaddr_t
) * (count
+ 1),
1356 if (*addresses
== NULL
) {
1360 bzero(*addresses
, sizeof (ifaddr_t
) * (count
+ 1));
1363 SLIST_FOREACH_SAFE(ifal
, &ifal_head
, ifal_le
, ifal_tmp
) {
1364 SLIST_REMOVE(&ifal_head
, ifal
, ifnet_addr_list
, ifal_le
);
1366 (*addresses
)[--count
] = ifal
->ifal_ifa
;
1368 IFA_REMREF(ifal
->ifal_ifa
);
1376 ifnet_free_address_list(ifaddr_t
*addresses
)
1380 if (addresses
== NULL
)
1383 for (i
= 0; addresses
[i
] != NULL
; i
++)
1384 IFA_REMREF(addresses
[i
]);
1386 FREE(addresses
, M_TEMP
);
1390 ifnet_lladdr(ifnet_t interface
)
1395 if (interface
== NULL
)
1399 * if_lladdr points to the permanent link address of
1400 * the interface; it never gets deallocated.
1402 ifa
= interface
->if_lladdr
;
1404 lladdr
= LLADDR(SDL((void *)ifa
->ifa_addr
));
1411 ifnet_llbroadcast_copy_bytes(ifnet_t interface
, void *addr
, size_t buffer_len
,
1414 if (interface
== NULL
|| addr
== NULL
|| out_len
== NULL
)
1417 *out_len
= interface
->if_broadcast
.length
;
1419 if (buffer_len
< interface
->if_broadcast
.length
)
1422 if (interface
->if_broadcast
.length
== 0)
1425 if (interface
->if_broadcast
.length
<=
1426 sizeof (interface
->if_broadcast
.u
.buffer
)) {
1427 bcopy(interface
->if_broadcast
.u
.buffer
, addr
,
1428 interface
->if_broadcast
.length
);
1430 bcopy(interface
->if_broadcast
.u
.ptr
, addr
,
1431 interface
->if_broadcast
.length
);
1438 ifnet_lladdr_copy_bytes(ifnet_t interface
, void *lladdr
, size_t lladdr_len
)
1440 struct sockaddr_dl
*sdl
;
1443 if (interface
== NULL
|| lladdr
== NULL
)
1447 * if_lladdr points to the permanent link address of
1448 * the interface; it never gets deallocated.
1450 ifa
= interface
->if_lladdr
;
1452 sdl
= SDL((void *)ifa
->ifa_addr
);
1453 if (lladdr_len
!= sdl
->sdl_alen
) {
1454 bzero(lladdr
, lladdr_len
);
1458 bcopy(LLADDR(sdl
), lladdr
, lladdr_len
);
1465 ifnet_set_lladdr_internal(ifnet_t interface
, const void *lladdr
,
1466 size_t lladdr_len
, u_char new_type
, int apply_type
)
1471 if (interface
== NULL
)
1474 ifnet_head_lock_shared();
1475 ifnet_lock_exclusive(interface
);
1476 if (lladdr_len
!= 0 &&
1477 (lladdr_len
!= interface
->if_addrlen
|| lladdr
== 0)) {
1478 ifnet_lock_done(interface
);
1482 ifa
= ifnet_addrs
[interface
->if_index
- 1];
1484 struct sockaddr_dl
*sdl
;
1487 sdl
= (struct sockaddr_dl
*)(void *)ifa
->ifa_addr
;
1488 if (lladdr_len
!= 0) {
1489 bcopy(lladdr
, LLADDR(sdl
), lladdr_len
);
1491 bzero(LLADDR(sdl
), interface
->if_addrlen
);
1493 sdl
->sdl_alen
= lladdr_len
;
1496 sdl
->sdl_type
= new_type
;
1502 ifnet_lock_done(interface
);
1505 /* Generate a kernel event */
1507 dlil_post_msg(interface
, KEV_DL_SUBCLASS
,
1508 KEV_DL_LINK_ADDRESS_CHANGED
, NULL
, 0);
1515 ifnet_set_lladdr(ifnet_t interface
, const void* lladdr
, size_t lladdr_len
)
1517 return (ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, 0, 0));
1521 ifnet_set_lladdr_and_type(ifnet_t interface
, const void* lladdr
,
1522 size_t lladdr_len
, u_char type
)
1524 return (ifnet_set_lladdr_internal(interface
, lladdr
,
1525 lladdr_len
, type
, 1));
1529 ifnet_add_multicast(ifnet_t interface
, const struct sockaddr
*maddr
,
1530 ifmultiaddr_t
*ifmap
)
1532 if (interface
== NULL
|| maddr
== NULL
)
1535 /* Don't let users screw up protocols' entries. */
1536 if (maddr
->sa_family
!= AF_UNSPEC
&& maddr
->sa_family
!= AF_LINK
)
1539 return (if_addmulti_anon(interface
, maddr
, ifmap
));
1543 ifnet_remove_multicast(ifmultiaddr_t ifma
)
1545 struct sockaddr
*maddr
;
1550 maddr
= ifma
->ifma_addr
;
1551 /* Don't let users screw up protocols' entries. */
1552 if (maddr
->sa_family
!= AF_UNSPEC
&& maddr
->sa_family
!= AF_LINK
)
1555 return (if_delmulti_anon(ifma
->ifma_ifp
, maddr
));
1559 ifnet_get_multicast_list(ifnet_t ifp
, ifmultiaddr_t
**addresses
)
1563 struct ifmultiaddr
*addr
;
1565 if (ifp
== NULL
|| addresses
== NULL
)
1568 ifnet_lock_shared(ifp
);
1569 LIST_FOREACH(addr
, &ifp
->if_multiaddrs
, ifma_link
) {
1573 MALLOC(*addresses
, ifmultiaddr_t
*, sizeof (ifmultiaddr_t
) * (cmax
+ 1),
1575 if (*addresses
== NULL
) {
1576 ifnet_lock_done(ifp
);
1580 LIST_FOREACH(addr
, &ifp
->if_multiaddrs
, ifma_link
) {
1581 if (count
+ 1 > cmax
)
1583 (*addresses
)[count
] = (ifmultiaddr_t
)addr
;
1584 ifmaddr_reference((*addresses
)[count
]);
1587 (*addresses
)[cmax
] = NULL
;
1588 ifnet_lock_done(ifp
);
1594 ifnet_free_multicast_list(ifmultiaddr_t
*addresses
)
1598 if (addresses
== NULL
)
1601 for (i
= 0; addresses
[i
] != NULL
; i
++)
1602 ifmaddr_release(addresses
[i
]);
1604 FREE(addresses
, M_TEMP
);
1608 ifnet_find_by_name(const char *ifname
, ifnet_t
*ifpp
)
1616 namelen
= strlen(ifname
);
1620 ifnet_head_lock_shared();
1621 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
1623 struct sockaddr_dl
*ll_addr
;
1625 ifa
= ifnet_addrs
[ifp
->if_index
- 1];
1630 ll_addr
= (struct sockaddr_dl
*)(void *)ifa
->ifa_addr
;
1632 if (namelen
== ll_addr
->sdl_nlen
&& strncmp(ll_addr
->sdl_data
,
1633 ifname
, ll_addr
->sdl_nlen
) == 0) {
1636 ifnet_reference(*ifpp
);
1643 return ((ifp
== NULL
) ? ENXIO
: 0);
1647 ifnet_list_get(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1649 return (ifnet_list_get_common(family
, FALSE
, list
, count
));
1652 __private_extern__ errno_t
1653 ifnet_list_get_all(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1655 return (ifnet_list_get_common(family
, TRUE
, list
, count
));
1659 SLIST_ENTRY(ifnet_list
) ifl_le
;
1660 struct ifnet
*ifl_ifp
;
1664 ifnet_list_get_common(ifnet_family_t family
, boolean_t get_all
, ifnet_t
**list
,
1667 #pragma unused(get_all)
1668 SLIST_HEAD(, ifnet_list
) ifl_head
;
1669 struct ifnet_list
*ifl
, *ifl_tmp
;
1674 SLIST_INIT(&ifl_head
);
1676 if (list
== NULL
|| count
== NULL
) {
1683 ifnet_head_lock_shared();
1684 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
1685 if (family
== IFNET_FAMILY_ANY
|| ifp
->if_family
== family
) {
1686 MALLOC(ifl
, struct ifnet_list
*, sizeof (*ifl
),
1694 ifnet_reference(ifp
);
1695 SLIST_INSERT_HEAD(&ifl_head
, ifl
, ifl_le
);
1706 MALLOC(*list
, ifnet_t
*, sizeof (ifnet_t
) * (cnt
+ 1),
1708 if (*list
== NULL
) {
1712 bzero(*list
, sizeof (ifnet_t
) * (cnt
+ 1));
1716 SLIST_FOREACH_SAFE(ifl
, &ifl_head
, ifl_le
, ifl_tmp
) {
1717 SLIST_REMOVE(&ifl_head
, ifl
, ifnet_list
, ifl_le
);
1719 (*list
)[--cnt
] = ifl
->ifl_ifp
;
1721 ifnet_release(ifl
->ifl_ifp
);
1729 ifnet_list_free(ifnet_t
*interfaces
)
1733 if (interfaces
== NULL
)
1736 for (i
= 0; interfaces
[i
]; i
++)
1737 ifnet_release(interfaces
[i
]);
1739 FREE(interfaces
, M_TEMP
);
1743 ifnet_transmit_burst_start(ifnet_t ifp
, mbuf_t pkt
)
1745 uint32_t orig_flags
;
1747 if (ifp
== NULL
|| !(pkt
->m_flags
& M_PKTHDR
))
1750 orig_flags
= OSBitOrAtomic(IF_MEASURED_BW_INPROGRESS
,
1752 if (orig_flags
& IF_MEASURED_BW_INPROGRESS
) {
1753 /* There is already a measurement in progress; skip this one */
1757 ifp
->if_bw
.start_seq
= pkt
->m_pkthdr
.pf_mtag
.pftag_pktseq
;
1758 ifp
->if_bw
.start_ts
= mach_absolute_time();
1762 ifnet_transmit_burst_end(ifnet_t ifp
, mbuf_t pkt
)
1764 uint64_t oseq
, ots
, bytes
, ts
, t
;
1767 if ( ifp
== NULL
|| !(pkt
->m_flags
& M_PKTHDR
))
1770 flags
= OSBitOrAtomic(IF_MEASURED_BW_CALCULATION
, &ifp
->if_bw
.flags
);
1772 /* If a calculation is already in progress, just return */
1773 if (flags
& IF_MEASURED_BW_CALCULATION
)
1776 /* Check if a measurement was started at all */
1777 if (!(flags
& IF_MEASURED_BW_INPROGRESS
)) {
1779 * It is an error to call burst_end before burst_start.
1780 * Reset the calculation flag and return.
1785 oseq
= pkt
->m_pkthdr
.pf_mtag
.pftag_pktseq
;
1786 ots
= mach_absolute_time();
1788 if (ifp
->if_bw
.start_seq
> 0 && oseq
> ifp
->if_bw
.start_seq
) {
1789 ts
= ots
- ifp
->if_bw
.start_ts
;
1791 absolutetime_to_nanoseconds(ts
, &t
);
1792 bytes
= oseq
- ifp
->if_bw
.start_seq
;
1793 ifp
->if_bw
.bytes
= bytes
;
1799 /* Compute bandwidth as bytes/ms */
1800 bw
= (bytes
* NSEC_PER_MSEC
) / t
;
1802 if (ifp
->if_bw
.bw
> 0) {
1805 shft
= if_bw_smoothing_val
;
1806 /* Compute EWMA of bw */
1807 ifp
->if_bw
.bw
= (bw
+
1808 ((ifp
->if_bw
.bw
<< shft
) -
1809 ifp
->if_bw
.bw
)) >> shft
;
1815 ifp
->if_bw
.last_seq
= oseq
;
1816 ifp
->if_bw
.last_ts
= ots
;
1821 flags
= ~(IF_MEASURED_BW_INPROGRESS
| IF_MEASURED_BW_CALCULATION
);
1822 OSBitAndAtomic(flags
, &ifp
->if_bw
.flags
);
1825 /****************************************************************************/
1826 /* ifaddr_t accessors */
1827 /****************************************************************************/
1830 ifaddr_reference(ifaddr_t ifa
)
1840 ifaddr_release(ifaddr_t ifa
)
1850 ifaddr_address_family(ifaddr_t ifa
)
1852 sa_family_t family
= 0;
1856 if (ifa
->ifa_addr
!= NULL
)
1857 family
= ifa
->ifa_addr
->sa_family
;
1864 ifaddr_address(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
1868 if (ifa
== NULL
|| out_addr
== NULL
)
1872 if (ifa
->ifa_addr
== NULL
) {
1877 copylen
= (addr_size
>= ifa
->ifa_addr
->sa_len
) ?
1878 ifa
->ifa_addr
->sa_len
: addr_size
;
1879 bcopy(ifa
->ifa_addr
, out_addr
, copylen
);
1881 if (ifa
->ifa_addr
->sa_len
> addr_size
) {
1891 ifaddr_dstaddress(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
1895 if (ifa
== NULL
|| out_addr
== NULL
)
1899 if (ifa
->ifa_dstaddr
== NULL
) {
1904 copylen
= (addr_size
>= ifa
->ifa_dstaddr
->sa_len
) ?
1905 ifa
->ifa_dstaddr
->sa_len
: addr_size
;
1906 bcopy(ifa
->ifa_dstaddr
, out_addr
, copylen
);
1908 if (ifa
->ifa_dstaddr
->sa_len
> addr_size
) {
1918 ifaddr_netmask(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
1922 if (ifa
== NULL
|| out_addr
== NULL
)
1926 if (ifa
->ifa_netmask
== NULL
) {
1931 copylen
= addr_size
>= ifa
->ifa_netmask
->sa_len
?
1932 ifa
->ifa_netmask
->sa_len
: addr_size
;
1933 bcopy(ifa
->ifa_netmask
, out_addr
, copylen
);
1935 if (ifa
->ifa_netmask
->sa_len
> addr_size
) {
1945 ifaddr_ifnet(ifaddr_t ifa
)
1952 /* ifa_ifp is set once at creation time; it is never changed */
1959 ifaddr_withaddr(const struct sockaddr
*address
)
1961 if (address
== NULL
)
1964 return (ifa_ifwithaddr(address
));
1968 ifaddr_withdstaddr(const struct sockaddr
*address
)
1970 if (address
== NULL
)
1973 return (ifa_ifwithdstaddr(address
));
1977 ifaddr_withnet(const struct sockaddr
*net
)
1982 return (ifa_ifwithnet(net
));
1986 ifaddr_withroute(int flags
, const struct sockaddr
*destination
,
1987 const struct sockaddr
*gateway
)
1989 if (destination
== NULL
|| gateway
== NULL
)
1992 return (ifa_ifwithroute(flags
, destination
, gateway
));
1996 ifaddr_findbestforaddr(const struct sockaddr
*addr
, ifnet_t interface
)
1998 if (addr
== NULL
|| interface
== NULL
)
2001 return (ifaof_ifpforaddr(addr
, interface
));
2005 ifmaddr_reference(ifmultiaddr_t ifmaddr
)
2007 if (ifmaddr
== NULL
)
2010 IFMA_ADDREF(ifmaddr
);
2015 ifmaddr_release(ifmultiaddr_t ifmaddr
)
2017 if (ifmaddr
== NULL
)
2020 IFMA_REMREF(ifmaddr
);
2025 ifmaddr_address(ifmultiaddr_t ifma
, struct sockaddr
*out_addr
,
2026 u_int32_t addr_size
)
2030 if (ifma
== NULL
|| out_addr
== NULL
)
2034 if (ifma
->ifma_addr
== NULL
) {
2039 copylen
= (addr_size
>= ifma
->ifma_addr
->sa_len
?
2040 ifma
->ifma_addr
->sa_len
: addr_size
);
2041 bcopy(ifma
->ifma_addr
, out_addr
, copylen
);
2043 if (ifma
->ifma_addr
->sa_len
> addr_size
) {
2052 ifmaddr_lladdress(ifmultiaddr_t ifma
, struct sockaddr
*out_addr
,
2053 u_int32_t addr_size
)
2055 struct ifmultiaddr
*ifma_ll
;
2057 if (ifma
== NULL
|| out_addr
== NULL
)
2059 if ((ifma_ll
= ifma
->ifma_ll
) == NULL
)
2062 return (ifmaddr_address(ifma_ll
, out_addr
, addr_size
));
2066 ifmaddr_ifnet(ifmultiaddr_t ifma
)
2068 return ((ifma
== NULL
) ? NULL
: ifma
->ifma_ifp
);
2071 /******************************************************************************/
2072 /* interface cloner */
2073 /******************************************************************************/
2076 ifnet_clone_attach(struct ifnet_clone_params
*cloner_params
,
2077 if_clone_t
*ifcloner
)
2080 struct if_clone
*ifc
= NULL
;
2083 if (cloner_params
== NULL
|| ifcloner
== NULL
||
2084 cloner_params
->ifc_name
== NULL
||
2085 cloner_params
->ifc_create
== NULL
||
2086 cloner_params
->ifc_destroy
== NULL
||
2087 (namelen
= strlen(cloner_params
->ifc_name
)) >= IFNAMSIZ
) {
2092 if (if_clone_lookup(cloner_params
->ifc_name
, NULL
) != NULL
) {
2093 printf("%s: already a cloner for %s\n", __func__
,
2094 cloner_params
->ifc_name
);
2099 /* Make room for name string */
2100 ifc
= _MALLOC(sizeof (struct if_clone
) + IFNAMSIZ
+ 1, M_CLONE
,
2103 printf("%s: _MALLOC failed\n", __func__
);
2107 strlcpy((char *)(ifc
+ 1), cloner_params
->ifc_name
, IFNAMSIZ
+ 1);
2108 ifc
->ifc_name
= (char *)(ifc
+ 1);
2109 ifc
->ifc_namelen
= namelen
;
2110 ifc
->ifc_maxunit
= IF_MAXUNIT
;
2111 ifc
->ifc_create
= cloner_params
->ifc_create
;
2112 ifc
->ifc_destroy
= cloner_params
->ifc_destroy
;
2114 error
= if_clone_attach(ifc
);
2116 printf("%s: if_clone_attach failed %d\n", __func__
, error
);
2129 ifnet_clone_detach(if_clone_t ifcloner
)
2132 struct if_clone
*ifc
= ifcloner
;
2134 if (ifc
== NULL
|| ifc
->ifc_name
== NULL
)
2137 if ((if_clone_lookup(ifc
->ifc_name
, NULL
)) == NULL
) {
2138 printf("%s: no cloner for %s\n", __func__
, ifc
->ifc_name
);
2143 if_clone_detach(ifc
);
2151 /******************************************************************************/
2153 /******************************************************************************/
2155 extern void udp_get_ports_used(unsigned int ifindex
, uint8_t *bitfield
);
2156 extern void tcp_get_ports_used(unsigned int ifindex
, uint8_t *bitfield
);
2159 ifnet_get_local_ports(ifnet_t ifp
, uint8_t *bitfield
)
2161 if (bitfield
== NULL
)
2164 bzero(bitfield
, 8192);
2166 udp_get_ports_used(ifp
? ifp
->if_index
: 0, bitfield
);
2167 tcp_get_ports_used(ifp
? ifp
->if_index
: 0, bitfield
);
2173 ifnet_notice_node_presence(ifnet_t ifp
, struct sockaddr
* sa
, int32_t rssi
,
2174 int lqm
, int npm
, u_int8_t srvinfo
[48])
2176 if (ifp
== NULL
|| sa
== NULL
|| srvinfo
== NULL
)
2178 if (sa
->sa_len
> sizeof(struct sockaddr_storage
))
2180 if (sa
->sa_family
!= AF_LINK
&& sa
->sa_family
!= AF_INET6
)
2183 dlil_node_present(ifp
, sa
, rssi
, lqm
, npm
, srvinfo
);
2188 ifnet_notice_node_absence(ifnet_t ifp
, struct sockaddr
* sa
)
2190 if (ifp
== NULL
|| sa
== NULL
)
2192 if (sa
->sa_len
> sizeof(struct sockaddr_storage
))
2194 if (sa
->sa_family
!= AF_LINK
&& sa
->sa_family
!= AF_INET6
)
2197 dlil_node_absent(ifp
, sa
);
2202 ifnet_notice_master_elected(ifnet_t ifp
)
2207 dlil_post_msg(ifp
, KEV_DL_SUBCLASS
, KEV_DL_MASTER_ELECTED
, NULL
, 0);