2 * Copyright (c) 2004-2010 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 <net/if_var.h>
42 #include <net/if_dl.h>
44 #include <net/if_types.h>
45 #include <net/if_dl.h>
46 #include <net/if_arp.h>
47 #include <libkern/libkern.h>
48 #include <libkern/OSAtomic.h>
49 #include <kern/locks.h>
51 #include "net/net_str_id.h"
53 #if IF_LASTCHANGEUPTIME
54 #define TOUCHLASTCHANGE(__if_lastchange) microuptime(__if_lastchange)
56 #define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
60 ifnet_list_get_common(ifnet_family_t
, boolean_t
, ifnet_t
**, u_int32_t
*);
63 Temporary work around until we have real reference counting
65 We keep the bits about calling dlil_if_release (which should be
66 called recycle) transparent by calling it from our if_free function
67 pointer. We have to keep the client's original detach function
68 somewhere so we can call it.
74 ifnet_detached_func detach_func
= ifp
->if_kpi_storage
;
79 if (ifp
->if_broadcast
.length
> sizeof(ifp
->if_broadcast
.u
.buffer
)) {
80 FREE(ifp
->if_broadcast
.u
.ptr
, M_IFADDR
);
81 ifp
->if_broadcast
.u
.ptr
= NULL
;
87 static __inline__
void*
88 _cast_non_const(const void * ptr
) {
100 const struct ifnet_init_params
*init
,
104 struct ifnet
*ifp
= NULL
;
106 if (init
->family
== 0)
108 if (init
->name
== NULL
||
109 init
->output
== NULL
)
111 if (strlen(init
->name
) >= IFNAMSIZ
)
113 if ((init
->type
& 0xFFFFFF00) != 0 || init
->type
== 0)
116 error
= dlil_if_acquire(init
->family
, init
->uniqueid
, init
->uniqueid_len
, &ifp
);
120 * Cast ifp->if_name as non const. dlil_if_acquire sets it up
121 * to point to storage of at least IFNAMSIZ bytes. It is safe
124 strncpy(_cast_non_const(ifp
->if_name
), init
->name
, IFNAMSIZ
);
125 ifp
->if_type
= init
->type
;
126 ifp
->if_family
= init
->family
;
127 ifp
->if_unit
= init
->unit
;
128 ifp
->if_output
= init
->output
;
129 ifp
->if_demux
= init
->demux
;
130 ifp
->if_add_proto
= init
->add_proto
;
131 ifp
->if_del_proto
= init
->del_proto
;
132 ifp
->if_check_multi
= init
->check_multi
;
133 ifp
->if_framer
= init
->framer
;
134 ifp
->if_softc
= init
->softc
;
135 ifp
->if_ioctl
= init
->ioctl
;
136 ifp
->if_set_bpf_tap
= init
->set_bpf_tap
;
137 ifp
->if_free
= ifnet_kpi_free
;
138 ifp
->if_event
= init
->event
;
139 ifp
->if_kpi_storage
= init
->detach
;
140 ifp
->if_eflags
|= IFEF_USEKPI
;
142 if (init
->broadcast_len
&& init
->broadcast_addr
) {
143 if (init
->broadcast_len
> sizeof(ifp
->if_broadcast
.u
.buffer
)) {
144 MALLOC(ifp
->if_broadcast
.u
.ptr
, u_char
*, init
->broadcast_len
, M_IFADDR
, M_NOWAIT
);
145 if (ifp
->if_broadcast
.u
.ptr
== NULL
) {
149 bcopy(init
->broadcast_addr
, ifp
->if_broadcast
.u
.ptr
, init
->broadcast_len
);
153 bcopy(init
->broadcast_addr
, ifp
->if_broadcast
.u
.buffer
, init
->broadcast_len
);
155 ifp
->if_broadcast
.length
= init
->broadcast_len
;
158 bzero(&ifp
->if_broadcast
, sizeof(ifp
->if_broadcast
));
163 ifnet_reference(ifp
); // temporary - this should be done in dlil_if_acquire
166 dlil_if_release(ifp
);
172 Note: We should do something here to indicate that we haven't been
173 attached yet. By doing so, we can catch the case in ifnet_release
174 where the reference count reaches zero and call the recycle
175 function. If the interface is attached, the interface will be
176 recycled when the interface's if_free function is called. If the
177 interface is never attached, the if_free function will never be
178 called and the interface will never be recycled.
185 ifnet_reference(ifnet_t ifp
)
187 return (dlil_if_ref(ifp
));
191 ifnet_release(ifnet_t ifp
)
193 return (dlil_if_free(ifp
));
197 ifnet_interface_family_find(const char *module_string
, ifnet_family_t
*family_id
)
199 if (module_string
== NULL
|| family_id
== NULL
)
201 return net_str_id_find_internal(module_string
, family_id
, NSI_IF_FAM_ID
, 1);
209 return interface
== NULL
? NULL
: interface
->if_softc
;
216 return interface
== NULL
? NULL
: interface
->if_name
;
223 return interface
== NULL
? 0 : interface
->if_family
;
230 return interface
== NULL
? (u_int32_t
)0xffffffff : (u_int32_t
)interface
->if_unit
;
237 return interface
== NULL
? (u_int32_t
)0xffffffff : interface
->if_index
;
241 ifnet_set_flags(ifnet_t interface
, u_int16_t new_flags
, u_int16_t mask
)
243 if (interface
== NULL
)
246 ifnet_lock_exclusive(interface
);
248 /* If we are modifying the up/down state, call if_updown */
249 if ((mask
& IFF_UP
) != 0) {
250 if_updown(interface
, (new_flags
& IFF_UP
) == IFF_UP
);
253 interface
->if_flags
= (new_flags
& mask
) | (interface
->if_flags
& ~mask
);
254 ifnet_lock_done(interface
);
263 return interface
== NULL
? 0 : interface
->if_flags
;
267 ifnet_set_eflags(ifnet_t interface
, u_int32_t new_flags
, u_int32_t mask
)
269 if (interface
== NULL
)
272 ifnet_lock_exclusive(interface
);
273 interface
->if_eflags
= (new_flags
& mask
) | (interface
->if_eflags
& ~mask
);
274 ifnet_lock_done(interface
);
283 return interface
== NULL
? 0 : interface
->if_eflags
;
287 ifnet_set_idle_flags_locked(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
294 lck_mtx_assert(rnh_lock
, LCK_MTX_ASSERT_OWNED
);
295 ifnet_lock_assert(ifp
, IFNET_LCK_ASSERT_EXCLUSIVE
);
298 * If this is called prior to ifnet attach, the actual work will
299 * be done at attach time. Otherwise, if it is called after
300 * ifnet detach, then it is a no-op.
302 if (!ifnet_is_attached(ifp
, 0)) {
303 ifp
->if_idle_new_flags
= new_flags
;
304 ifp
->if_idle_new_flags_mask
= mask
;
307 ifp
->if_idle_new_flags
= ifp
->if_idle_new_flags_mask
= 0;
310 before
= ifp
->if_idle_flags
;
311 ifp
->if_idle_flags
= (new_flags
& mask
) | (ifp
->if_idle_flags
& ~mask
);
312 after
= ifp
->if_idle_flags
;
314 if ((after
- before
) < 0 && ifp
->if_idle_flags
== 0 &&
315 ifp
->if_want_aggressive_drain
!= 0) {
316 ifp
->if_want_aggressive_drain
= 0;
317 if (ifnet_aggressive_drainers
== 0)
318 panic("%s: ifp=%p negative aggdrain!", __func__
, ifp
);
319 if (--ifnet_aggressive_drainers
== 0)
321 } else if ((after
- before
) > 0 && ifp
->if_want_aggressive_drain
== 0) {
322 ifp
->if_want_aggressive_drain
++;
323 if (++ifnet_aggressive_drainers
== 0)
324 panic("%s: ifp=%p wraparound aggdrain!", __func__
, ifp
);
325 else if (ifnet_aggressive_drainers
== 1)
333 ifnet_set_idle_flags(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
337 lck_mtx_lock(rnh_lock
);
338 ifnet_lock_exclusive(ifp
);
339 err
= ifnet_set_idle_flags_locked(ifp
, new_flags
, mask
);
340 ifnet_lock_done(ifp
);
341 lck_mtx_unlock(rnh_lock
);
347 ifnet_idle_flags(ifnet_t ifp
)
349 return ((ifp
== NULL
) ? 0 : ifp
->if_idle_flags
);
352 errno_t
ifnet_set_capabilities_supported(ifnet_t ifp
, u_int32_t new_caps
,
361 ifnet_lock_exclusive(ifp
);
362 tmp
= (new_caps
& mask
) | (ifp
->if_capabilities
& ~mask
);
363 if ((tmp
& ~IFCAP_VALID
))
366 ifp
->if_capabilities
= tmp
;
367 ifnet_lock_done(ifp
);
372 u_int32_t
ifnet_capabilities_supported(ifnet_t ifp
)
374 return ((ifp
== NULL
) ? 0 : ifp
->if_capabilities
);
378 errno_t
ifnet_set_capabilities_enabled(ifnet_t ifp
, u_int32_t new_caps
,
383 struct kev_msg ev_msg
;
384 struct net_event_data ev_data
;
389 ifnet_lock_exclusive(ifp
);
390 tmp
= (new_caps
& mask
) | (ifp
->if_capenable
& ~mask
);
391 if ((tmp
& ~IFCAP_VALID
) || (tmp
& ~ifp
->if_capabilities
))
394 ifp
->if_capenable
= tmp
;
395 ifnet_lock_done(ifp
);
397 /* Notify application of the change */
398 bzero(&ev_data
, sizeof(struct net_event_data
));
399 bzero(&ev_msg
, sizeof(struct kev_msg
));
400 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
401 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
402 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
404 ev_msg
.event_code
= KEV_DL_IFCAP_CHANGED
;
405 strlcpy(&ev_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
406 ev_data
.if_family
= ifp
->if_family
;
407 ev_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
408 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
409 ev_msg
.dv
[0].data_ptr
= &ev_data
;
410 ev_msg
.dv
[1].data_length
= 0;
411 kev_post_msg(&ev_msg
);
416 u_int32_t
ifnet_capabilities_enabled(ifnet_t ifp
)
418 return ((ifp
== NULL
) ? 0 : ifp
->if_capenable
);
423 static const ifnet_offload_t offload_mask
= IFNET_CSUM_IP
| IFNET_CSUM_TCP
|
424 IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
| IFNET_IP_FRAGMENT
|
425 IFNET_CSUM_TCPIPV6
| IFNET_CSUM_UDPIPV6
| IFNET_IPV6_FRAGMENT
|
426 IFNET_CSUM_SUM16
| IFNET_VLAN_TAGGING
| IFNET_VLAN_MTU
|
427 IFNET_MULTIPAGES
| IFNET_TSO_IPV4
| IFNET_TSO_IPV6
;
429 static const ifnet_offload_t any_offload_csum
= IFNET_CSUM_IP
| IFNET_CSUM_TCP
|
430 IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
|
431 IFNET_CSUM_TCPIPV6
| IFNET_CSUM_UDPIPV6
|
436 ifnet_set_offload(ifnet_t interface
, ifnet_offload_t offload
)
438 u_int32_t ifcaps
= 0;
440 if (interface
== NULL
)
443 ifnet_lock_exclusive(interface
);
444 interface
->if_hwassist
= (offload
& offload_mask
);
445 ifnet_lock_done(interface
);
447 if ((offload
& any_offload_csum
))
448 ifcaps
|= IFCAP_HWCSUM
;
449 if ((offload
& IFNET_TSO_IPV4
))
450 ifcaps
|= IFCAP_TSO4
;
451 if ((offload
& IFNET_TSO_IPV6
))
452 ifcaps
|= IFCAP_TSO6
;
453 if ((offload
& IFNET_VLAN_MTU
))
454 ifcaps
|= IFCAP_VLAN_MTU
;
455 if ((offload
& IFNET_VLAN_TAGGING
))
456 ifcaps
|= IFCAP_VLAN_HWTAGGING
;
458 (void) ifnet_set_capabilities_supported(interface
, ifcaps
, IFCAP_VALID
);
459 (void) ifnet_set_capabilities_enabled(interface
, ifcaps
, IFCAP_VALID
);
469 return interface
== NULL
? 0 : (interface
->if_hwassist
& offload_mask
);
480 if (interface
== NULL
) return EINVAL
;
482 if (mtuLen
< interface
->if_mtu
)
489 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
490 interface
->if_tso_v4_mtu
= mtuLen
;
496 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
497 interface
->if_tso_v6_mtu
= mtuLen
;
503 error
= EPROTONOSUPPORT
;
517 if (interface
== NULL
|| mtuLen
== NULL
) return EINVAL
;
522 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
523 *mtuLen
= interface
->if_tso_v4_mtu
;
529 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
530 *mtuLen
= interface
->if_tso_v6_mtu
;
535 error
= EPROTONOSUPPORT
;
542 ifnet_set_wake_flags(ifnet_t interface
, u_int32_t properties
, u_int32_t mask
)
544 struct kev_msg ev_msg
;
545 struct net_event_data ev_data
;
547 bzero(&ev_data
, sizeof(struct net_event_data
));
548 bzero(&ev_msg
, sizeof(struct kev_msg
));
549 if (interface
== NULL
)
552 /* Do not accept wacky values */
553 if ((properties
& mask
) & ~IF_WAKE_VALID_FLAGS
)
556 ifnet_lock_exclusive(interface
);
558 interface
->if_wake_properties
= (properties
& mask
) | (interface
->if_wake_properties
& ~mask
);
560 ifnet_lock_done(interface
);
562 (void) ifnet_touch_lastchange(interface
);
564 /* Notify application of the change */
565 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
566 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
567 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
569 ev_msg
.event_code
= KEV_DL_WAKEFLAGS_CHANGED
;
570 strlcpy(&ev_data
.if_name
[0], interface
->if_name
, IFNAMSIZ
);
571 ev_data
.if_family
= interface
->if_family
;
572 ev_data
.if_unit
= (u_int32_t
) interface
->if_unit
;
573 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
574 ev_msg
.dv
[0].data_ptr
= &ev_data
;
575 ev_msg
.dv
[1].data_length
= 0;
576 kev_post_msg(&ev_msg
);
582 ifnet_get_wake_flags(ifnet_t interface
)
584 return interface
== NULL
? 0 : interface
->if_wake_properties
;
588 * Should MIB data store a copy?
591 ifnet_set_link_mib_data(ifnet_t interface
, void *mibData
, u_int32_t mibLen
)
593 if (interface
== NULL
)
596 ifnet_lock_exclusive(interface
);
597 interface
->if_linkmib
= (void*)mibData
;
598 interface
->if_linkmiblen
= mibLen
;
599 ifnet_lock_done(interface
);
604 ifnet_get_link_mib_data(ifnet_t interface
, void *mibData
, u_int32_t
*mibLen
)
608 if (interface
== NULL
)
611 ifnet_lock_shared(interface
);
612 if (*mibLen
< interface
->if_linkmiblen
)
614 if (result
== 0 && interface
->if_linkmib
== NULL
)
618 *mibLen
= interface
->if_linkmiblen
;
619 bcopy(interface
->if_linkmib
, mibData
, *mibLen
);
621 ifnet_lock_done(interface
);
627 ifnet_get_link_mib_data_length(
630 return interface
== NULL
? 0 : interface
->if_linkmiblen
;
636 protocol_family_t protocol_family
,
639 const struct sockaddr
*dest
)
641 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
646 return dlil_output(interface
, protocol_family
, m
, route
, dest
, 0);
652 protocol_family_t protocol_family
,
655 if (interface
== NULL
|| m
== NULL
) {
660 return dlil_output(interface
, protocol_family
, m
, NULL
, NULL
, 1);
668 if (interface
== NULL
) return EINVAL
;
669 interface
->if_data
.ifi_mtu
= mtu
;
678 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_mtu
;
688 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_type
;
694 ifnet_set_typelen(ifnet_t interface
, u_char typelen
)
696 ifnet_lock_exclusive(interface
);
697 interface
->if_data
.ifi_typelen
= typelen
;
698 ifnet_lock_done(interface
);
707 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_typelen
;
717 if (interface
== NULL
) return EINVAL
;
718 interface
->if_data
.ifi_addrlen
= addrlen
;
727 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_addrlen
;
736 if (interface
== NULL
) return EINVAL
;
737 interface
->if_data
.ifi_hdrlen
= hdrlen
;
746 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_hdrlen
;
755 if (interface
== NULL
) return EINVAL
;
756 interface
->if_data
.ifi_metric
= metric
;
765 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_metric
;
774 if (interface
== NULL
) return EINVAL
;
775 /* Pin baudrate to 32 bits until we can change the storage size */
776 interface
->if_data
.ifi_baudrate
= baudrate
> 0xFFFFFFFF ? 0xFFFFFFFF : baudrate
;
785 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_baudrate
;
790 ifnet_stat_increment(ifnet_t interface
,
791 const struct ifnet_stat_increment_param
*counts
)
793 if (interface
== NULL
)
796 atomic_add_64(&interface
->if_data
.ifi_ipackets
, counts
->packets_in
);
797 atomic_add_64(&interface
->if_data
.ifi_ibytes
, counts
->bytes_in
);
798 atomic_add_64(&interface
->if_data
.ifi_ierrors
, counts
->errors_in
);
800 atomic_add_64(&interface
->if_data
.ifi_opackets
, counts
->packets_out
);
801 atomic_add_64(&interface
->if_data
.ifi_obytes
, counts
->bytes_out
);
802 atomic_add_64(&interface
->if_data
.ifi_oerrors
, counts
->errors_out
);
804 atomic_add_64(&interface
->if_data
.ifi_collisions
, counts
->collisions
);
805 atomic_add_64(&interface
->if_data
.ifi_iqdrops
, counts
->dropped
);
807 /* Touch the last change time. */
808 TOUCHLASTCHANGE(&interface
->if_lastchange
);
814 ifnet_stat_increment_in(ifnet_t interface
, u_int32_t packets_in
,
815 u_int32_t bytes_in
, u_int32_t errors_in
)
817 if (interface
== NULL
)
820 atomic_add_64(&interface
->if_data
.ifi_ipackets
, packets_in
);
821 atomic_add_64(&interface
->if_data
.ifi_ibytes
, bytes_in
);
822 atomic_add_64(&interface
->if_data
.ifi_ierrors
, errors_in
);
824 TOUCHLASTCHANGE(&interface
->if_lastchange
);
830 ifnet_stat_increment_out(ifnet_t interface
, u_int32_t packets_out
,
831 u_int32_t bytes_out
, u_int32_t errors_out
)
833 if (interface
== NULL
)
836 atomic_add_64(&interface
->if_data
.ifi_opackets
, packets_out
);
837 atomic_add_64(&interface
->if_data
.ifi_obytes
, bytes_out
);
838 atomic_add_64(&interface
->if_data
.ifi_oerrors
, errors_out
);
840 TOUCHLASTCHANGE(&interface
->if_lastchange
);
846 ifnet_set_stat(ifnet_t interface
, const struct ifnet_stats_param
*stats
)
848 if (interface
== NULL
)
851 atomic_set_64(&interface
->if_data
.ifi_ipackets
, stats
->packets_in
);
852 atomic_set_64(&interface
->if_data
.ifi_ibytes
, stats
->bytes_in
);
853 atomic_set_64(&interface
->if_data
.ifi_imcasts
, stats
->multicasts_in
);
854 atomic_set_64(&interface
->if_data
.ifi_ierrors
, stats
->errors_in
);
856 atomic_set_64(&interface
->if_data
.ifi_opackets
, stats
->packets_out
);
857 atomic_set_64(&interface
->if_data
.ifi_obytes
, stats
->bytes_out
);
858 atomic_set_64(&interface
->if_data
.ifi_omcasts
, stats
->multicasts_out
);
859 atomic_set_64(&interface
->if_data
.ifi_oerrors
, stats
->errors_out
);
861 atomic_set_64(&interface
->if_data
.ifi_collisions
, stats
->collisions
);
862 atomic_set_64(&interface
->if_data
.ifi_iqdrops
, stats
->dropped
);
863 atomic_set_64(&interface
->if_data
.ifi_noproto
, stats
->no_protocol
);
865 /* Touch the last change time. */
866 TOUCHLASTCHANGE(&interface
->if_lastchange
);
872 ifnet_stat(ifnet_t interface
, struct ifnet_stats_param
*stats
)
874 if (interface
== NULL
)
877 atomic_get_64(stats
->packets_in
, &interface
->if_data
.ifi_ipackets
);
878 atomic_get_64(stats
->bytes_in
, &interface
->if_data
.ifi_ibytes
);
879 atomic_get_64(stats
->multicasts_in
, &interface
->if_data
.ifi_imcasts
);
880 atomic_get_64(stats
->errors_in
, &interface
->if_data
.ifi_ierrors
);
882 atomic_get_64(stats
->packets_out
, &interface
->if_data
.ifi_opackets
);
883 atomic_get_64(stats
->bytes_out
, &interface
->if_data
.ifi_obytes
);
884 atomic_get_64(stats
->multicasts_out
, &interface
->if_data
.ifi_omcasts
);
885 atomic_get_64(stats
->errors_out
, &interface
->if_data
.ifi_oerrors
);
887 atomic_get_64(stats
->collisions
, &interface
->if_data
.ifi_collisions
);
888 atomic_get_64(stats
->dropped
, &interface
->if_data
.ifi_iqdrops
);
889 atomic_get_64(stats
->no_protocol
, &interface
->if_data
.ifi_noproto
);
895 ifnet_touch_lastchange(ifnet_t interface
)
897 if (interface
== NULL
)
900 TOUCHLASTCHANGE(&interface
->if_lastchange
);
906 ifnet_lastchange(ifnet_t interface
, struct timeval
*last_change
)
908 if (interface
== NULL
)
911 *last_change
= interface
->if_data
.ifi_lastchange
;
912 #if IF_LASTCHANGEUPTIME
913 /* Crude conversion from uptime to calendar time */
914 last_change
->tv_sec
+= boottime_sec();
920 ifnet_get_address_list(ifnet_t interface
, ifaddr_t
**addresses
)
922 return (addresses
== NULL
? EINVAL
:
923 ifnet_get_address_list_family(interface
, addresses
, 0));
926 struct ifnet_addr_list
{
927 SLIST_ENTRY(ifnet_addr_list
) ifal_le
;
928 struct ifaddr
*ifal_ifa
;
932 ifnet_get_address_list_family(ifnet_t interface
, ifaddr_t
**addresses
,
935 return (ifnet_get_address_list_family_internal(interface
, addresses
,
936 family
, 0, M_NOWAIT
));
939 __private_extern__ errno_t
940 ifnet_get_address_list_family_internal(ifnet_t interface
, ifaddr_t
**addresses
,
941 sa_family_t family
, int detached
, int how
)
943 SLIST_HEAD(, ifnet_addr_list
) ifal_head
;
944 struct ifnet_addr_list
*ifal
, *ifal_tmp
;
949 SLIST_INIT(&ifal_head
);
951 if (addresses
== NULL
) {
959 * Interface has been detached, so skip the lookup
960 * at ifnet_head and go directly to inner loop.
970 ifnet_head_lock_shared();
971 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
972 if (interface
!= NULL
&& ifp
!= interface
)
975 ifnet_lock_shared(ifp
);
976 if (interface
== NULL
|| interface
== ifp
) {
978 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
981 ifa
->ifa_addr
->sa_family
!= family
) {
985 MALLOC(ifal
, struct ifnet_addr_list
*,
986 sizeof (*ifal
), M_TEMP
, how
);
989 ifnet_lock_done(ifp
);
995 ifal
->ifal_ifa
= ifa
;
996 IFA_ADDREF_LOCKED(ifa
);
997 SLIST_INSERT_HEAD(&ifal_head
, ifal
, ifal_le
);
1002 ifnet_lock_done(ifp
);
1013 MALLOC(*addresses
, ifaddr_t
*, sizeof (ifaddr_t
) * (count
+ 1),
1015 if (*addresses
== NULL
) {
1019 bzero(*addresses
, sizeof (ifaddr_t
) * (count
+ 1));
1022 SLIST_FOREACH_SAFE(ifal
, &ifal_head
, ifal_le
, ifal_tmp
) {
1023 SLIST_REMOVE(&ifal_head
, ifal
, ifnet_addr_list
, ifal_le
);
1025 (*addresses
)[--count
] = ifal
->ifal_ifa
;
1027 IFA_REMREF(ifal
->ifal_ifa
);
1035 ifnet_free_address_list(ifaddr_t
*addresses
)
1039 if (addresses
== NULL
)
1042 for (i
= 0; addresses
[i
] != NULL
; i
++)
1043 IFA_REMREF(addresses
[i
]);
1045 FREE(addresses
, M_TEMP
);
1049 ifnet_lladdr(ifnet_t interface
)
1054 if (interface
== NULL
)
1058 * if_lladdr points to the permanent link address of
1059 * the interface; it never gets deallocated.
1061 ifa
= interface
->if_lladdr
;
1063 lladdr
= LLADDR(SDL(ifa
->ifa_addr
));
1070 ifnet_llbroadcast_copy_bytes(
1076 if (interface
== NULL
|| addr
== NULL
|| out_len
== NULL
) return EINVAL
;
1078 *out_len
= interface
->if_broadcast
.length
;
1080 if (buffer_len
< interface
->if_broadcast
.length
) {
1084 if (interface
->if_broadcast
.length
== 0)
1087 if (interface
->if_broadcast
.length
<= sizeof(interface
->if_broadcast
.u
.buffer
)) {
1088 bcopy(interface
->if_broadcast
.u
.buffer
, addr
, interface
->if_broadcast
.length
);
1091 bcopy(interface
->if_broadcast
.u
.ptr
, addr
, interface
->if_broadcast
.length
);
1098 ifnet_lladdr_copy_bytes(ifnet_t interface
, void *lladdr
, size_t lladdr_len
)
1100 struct sockaddr_dl
*sdl
;
1103 if (interface
== NULL
|| lladdr
== NULL
)
1107 * if_lladdr points to the permanent link address of
1108 * the interface; it never gets deallocated.
1110 ifa
= interface
->if_lladdr
;
1112 sdl
= SDL(ifa
->ifa_addr
);
1113 if (lladdr_len
!= sdl
->sdl_alen
) {
1114 bzero(lladdr
, lladdr_len
);
1118 bcopy(LLADDR(sdl
), lladdr
, lladdr_len
);
1125 ifnet_set_lladdr_internal(ifnet_t interface
, const void *lladdr
,
1126 size_t lladdr_len
, u_char new_type
, int apply_type
)
1131 if (interface
== NULL
)
1134 ifnet_head_lock_shared();
1135 ifnet_lock_exclusive(interface
);
1136 if (lladdr_len
!= 0 &&
1137 (lladdr_len
!= interface
->if_addrlen
|| lladdr
== 0)) {
1138 ifnet_lock_done(interface
);
1142 ifa
= ifnet_addrs
[interface
->if_index
- 1];
1144 struct sockaddr_dl
*sdl
;
1147 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1148 if (lladdr_len
!= 0) {
1149 bcopy(lladdr
, LLADDR(sdl
), lladdr_len
);
1151 bzero(LLADDR(sdl
), interface
->if_addrlen
);
1153 sdl
->sdl_alen
= lladdr_len
;
1156 sdl
->sdl_type
= new_type
;
1162 ifnet_lock_done(interface
);
1165 /* Generate a kernel event */
1167 dlil_post_msg(interface
, KEV_DL_SUBCLASS
,
1168 KEV_DL_LINK_ADDRESS_CHANGED
, NULL
, 0);
1180 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, 0, 0);
1184 ifnet_set_lladdr_and_type(
1190 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, type
, 1);
1194 ifnet_add_multicast(ifnet_t interface
, const struct sockaddr
*maddr
,
1195 ifmultiaddr_t
*ifmap
)
1197 if (interface
== NULL
|| maddr
== NULL
)
1200 /* Don't let users screw up protocols' entries. */
1201 if (maddr
->sa_family
!= AF_UNSPEC
&& maddr
->sa_family
!= AF_LINK
)
1204 return (if_addmulti_anon(interface
, maddr
, ifmap
));
1208 ifnet_remove_multicast(ifmultiaddr_t ifma
)
1210 struct sockaddr
*maddr
;
1215 maddr
= ifma
->ifma_addr
;
1216 /* Don't let users screw up protocols' entries. */
1217 if (maddr
->sa_family
!= AF_UNSPEC
&& maddr
->sa_family
!= AF_LINK
)
1220 return (if_delmulti_anon(ifma
->ifma_ifp
, maddr
));
1224 ifnet_get_multicast_list(ifnet_t ifp
, ifmultiaddr_t
**addresses
)
1228 struct ifmultiaddr
*addr
;
1230 if (ifp
== NULL
|| addresses
== NULL
)
1233 ifnet_lock_shared(ifp
);
1234 LIST_FOREACH(addr
, &ifp
->if_multiaddrs
, ifma_link
) {
1238 MALLOC(*addresses
, ifmultiaddr_t
*, sizeof (ifmultiaddr_t
) * (cmax
+ 1),
1240 if (*addresses
== NULL
) {
1241 ifnet_lock_done(ifp
);
1245 LIST_FOREACH(addr
, &ifp
->if_multiaddrs
, ifma_link
) {
1246 if (count
+ 1 > cmax
)
1248 (*addresses
)[count
] = (ifmultiaddr_t
)addr
;
1249 ifmaddr_reference((*addresses
)[count
]);
1252 (*addresses
)[cmax
] = NULL
;
1253 ifnet_lock_done(ifp
);
1259 ifnet_free_multicast_list(
1260 ifmultiaddr_t
*addresses
)
1264 if (addresses
== NULL
) return;
1266 for (i
= 0; addresses
[i
] != NULL
; i
++)
1268 ifmaddr_release(addresses
[i
]);
1271 FREE(addresses
, M_TEMP
);
1275 ifnet_find_by_name(const char *ifname
, ifnet_t
*ifpp
)
1283 namelen
= strlen(ifname
);
1287 ifnet_head_lock_shared();
1288 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
1290 struct sockaddr_dl
*ll_addr
;
1292 ifa
= ifnet_addrs
[ifp
->if_index
- 1];
1297 ll_addr
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1299 if (namelen
== ll_addr
->sdl_nlen
&&
1300 !strncmp(ll_addr
->sdl_data
, ifname
, ll_addr
->sdl_nlen
)) {
1303 ifnet_reference(*ifpp
);
1310 return ((ifp
== NULL
) ? ENXIO
: 0);
1314 ifnet_list_get(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1316 return (ifnet_list_get_common(family
, FALSE
, list
, count
));
1319 __private_extern__ errno_t
1320 ifnet_list_get_all(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1322 return (ifnet_list_get_common(family
, TRUE
, list
, count
));
1326 SLIST_ENTRY(ifnet_list
) ifl_le
;
1327 struct ifnet
*ifl_ifp
;
1331 ifnet_list_get_common(ifnet_family_t family
, boolean_t get_all
, ifnet_t
**list
,
1334 #pragma unused(get_all)
1335 SLIST_HEAD(, ifnet_list
) ifl_head
;
1336 struct ifnet_list
*ifl
, *ifl_tmp
;
1341 SLIST_INIT(&ifl_head
);
1343 if (list
== NULL
|| count
== NULL
) {
1350 ifnet_head_lock_shared();
1351 TAILQ_FOREACH(ifp
, &ifnet_head
, if_link
) {
1352 if (family
== IFNET_FAMILY_ANY
|| ifp
->if_family
== family
) {
1353 MALLOC(ifl
, struct ifnet_list
*, sizeof (*ifl
),
1361 ifnet_reference(ifp
);
1362 SLIST_INSERT_HEAD(&ifl_head
, ifl
, ifl_le
);
1373 MALLOC(*list
, ifnet_t
*, sizeof (ifnet_t
) * (cnt
+ 1),
1375 if (*list
== NULL
) {
1379 bzero(*list
, sizeof (ifnet_t
) * (cnt
+ 1));
1383 SLIST_FOREACH_SAFE(ifl
, &ifl_head
, ifl_le
, ifl_tmp
) {
1384 SLIST_REMOVE(&ifl_head
, ifl
, ifnet_list
, ifl_le
);
1386 (*list
)[--cnt
] = ifl
->ifl_ifp
;
1388 ifnet_release(ifl
->ifl_ifp
);
1396 ifnet_list_free(ifnet_t
*interfaces
)
1400 if (interfaces
== NULL
)
1403 for (i
= 0; interfaces
[i
]; i
++)
1404 ifnet_release(interfaces
[i
]);
1406 FREE(interfaces
, M_TEMP
);
1409 /****************************************************************************/
1410 /* ifaddr_t accessors */
1411 /****************************************************************************/
1414 ifaddr_reference(ifaddr_t ifa
)
1424 ifaddr_release(ifaddr_t ifa
)
1434 ifaddr_address_family(ifaddr_t ifa
)
1436 sa_family_t family
= 0;
1440 if (ifa
->ifa_addr
!= NULL
)
1441 family
= ifa
->ifa_addr
->sa_family
;
1448 ifaddr_address(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
1452 if (ifa
== NULL
|| out_addr
== NULL
)
1456 if (ifa
->ifa_addr
== NULL
) {
1461 copylen
= (addr_size
>= ifa
->ifa_addr
->sa_len
) ?
1462 ifa
->ifa_addr
->sa_len
: addr_size
;
1463 bcopy(ifa
->ifa_addr
, out_addr
, copylen
);
1465 if (ifa
->ifa_addr
->sa_len
> addr_size
) {
1475 ifaddr_dstaddress(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
1479 if (ifa
== NULL
|| out_addr
== NULL
)
1483 if (ifa
->ifa_dstaddr
== NULL
) {
1488 copylen
= (addr_size
>= ifa
->ifa_dstaddr
->sa_len
) ?
1489 ifa
->ifa_dstaddr
->sa_len
: addr_size
;
1490 bcopy(ifa
->ifa_dstaddr
, out_addr
, copylen
);
1492 if (ifa
->ifa_dstaddr
->sa_len
> addr_size
) {
1502 ifaddr_netmask(ifaddr_t ifa
, struct sockaddr
*out_addr
, u_int32_t addr_size
)
1506 if (ifa
== NULL
|| out_addr
== NULL
)
1510 if (ifa
->ifa_netmask
== NULL
) {
1515 copylen
= addr_size
>= ifa
->ifa_netmask
->sa_len
?
1516 ifa
->ifa_netmask
->sa_len
: addr_size
;
1517 bcopy(ifa
->ifa_netmask
, out_addr
, copylen
);
1519 if (ifa
->ifa_netmask
->sa_len
> addr_size
) {
1529 ifaddr_ifnet(ifaddr_t ifa
)
1536 /* ifa_ifp is set once at creation time; it is never changed */
1544 const struct sockaddr
* address
)
1546 if (address
== NULL
) return NULL
;
1547 return ifa_ifwithaddr(address
);
1552 const struct sockaddr
* address
)
1554 if (address
== NULL
) return NULL
;
1555 return ifa_ifwithdstaddr(address
);
1560 const struct sockaddr
* net
)
1562 if (net
== NULL
) return NULL
;
1563 return ifa_ifwithnet(net
);
1569 const struct sockaddr
* destination
,
1570 const struct sockaddr
* gateway
)
1572 if (destination
== NULL
|| gateway
== NULL
) return NULL
;
1573 return ifa_ifwithroute(flags
, destination
, gateway
);
1577 ifaddr_findbestforaddr(
1578 const struct sockaddr
*addr
,
1581 if (addr
== NULL
|| interface
== NULL
) return NULL
;
1582 return ifaof_ifpforaddr(addr
, interface
);
1586 ifmaddr_reference(ifmultiaddr_t ifmaddr
)
1588 if (ifmaddr
== NULL
)
1591 IFMA_ADDREF(ifmaddr
);
1596 ifmaddr_release(ifmultiaddr_t ifmaddr
)
1598 if (ifmaddr
== NULL
)
1601 IFMA_REMREF(ifmaddr
);
1606 ifmaddr_address(ifmultiaddr_t ifma
, struct sockaddr
*out_addr
,
1607 u_int32_t addr_size
)
1611 if (ifma
== NULL
|| out_addr
== NULL
)
1615 if (ifma
->ifma_addr
== NULL
) {
1620 copylen
= (addr_size
>= ifma
->ifma_addr
->sa_len
?
1621 ifma
->ifma_addr
->sa_len
: addr_size
);
1622 bcopy(ifma
->ifma_addr
, out_addr
, copylen
);
1624 if (ifma
->ifma_addr
->sa_len
> addr_size
) {
1633 ifmaddr_lladdress(ifmultiaddr_t ifma
, struct sockaddr
*out_addr
,
1634 u_int32_t addr_size
)
1636 struct ifmultiaddr
*ifma_ll
;
1638 if (ifma
== NULL
|| out_addr
== NULL
)
1640 if ((ifma_ll
= ifma
->ifma_ll
) == NULL
)
1643 return (ifmaddr_address(ifma_ll
, out_addr
, addr_size
));
1647 ifmaddr_ifnet(ifmultiaddr_t ifma
)
1649 return (ifma
== NULL
? NULL
: ifma
->ifma_ifp
);
1652 /******************************************************************************/
1653 /* interface cloner */
1654 /******************************************************************************/
1657 ifnet_clone_attach(struct ifnet_clone_params
*cloner_params
, if_clone_t
*ifcloner
)
1660 struct if_clone
*ifc
= NULL
;
1663 if (cloner_params
== NULL
|| ifcloner
== NULL
|| cloner_params
->ifc_name
== NULL
||
1664 cloner_params
->ifc_create
== NULL
|| cloner_params
->ifc_destroy
== NULL
||
1665 (namelen
= strlen(cloner_params
->ifc_name
)) >= IFNAMSIZ
) {
1670 if (if_clone_lookup(cloner_params
->ifc_name
, NULL
) != NULL
) {
1671 printf("ifnet_clone_attach: already a cloner for %s\n", cloner_params
->ifc_name
);
1676 /* Make room for name string */
1677 ifc
= _MALLOC(sizeof(struct if_clone
) + IFNAMSIZ
+ 1, M_CLONE
, M_WAITOK
| M_ZERO
);
1679 printf("ifnet_clone_attach: _MALLOC failed\n");
1683 strlcpy((char *)(ifc
+ 1), cloner_params
->ifc_name
, IFNAMSIZ
+ 1);
1684 ifc
->ifc_name
= (char *)(ifc
+ 1);
1685 ifc
->ifc_namelen
= namelen
;
1686 ifc
->ifc_maxunit
= IF_MAXUNIT
;
1687 ifc
->ifc_create
= cloner_params
->ifc_create
;
1688 ifc
->ifc_destroy
= cloner_params
->ifc_destroy
;
1690 error
= if_clone_attach(ifc
);
1692 printf("ifnet_clone_attach: if_clone_attach failed %d\n", error
);
1705 ifnet_clone_detach(if_clone_t ifcloner
)
1708 struct if_clone
*ifc
= ifcloner
;
1710 if (ifc
== NULL
|| ifc
->ifc_name
== NULL
)
1713 if ((if_clone_lookup(ifc
->ifc_name
, NULL
)) == NULL
) {
1714 printf("ifnet_clone_attach: no cloner for %s\n", ifc
->ifc_name
);
1719 if_clone_detach(ifc
);