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 <net/if_var.h>
41 #include <net/if_dl.h>
43 #include <net/if_types.h>
44 #include <net/if_dl.h>
45 #include <net/if_arp.h>
46 #include <libkern/libkern.h>
47 #include <libkern/OSAtomic.h>
48 #include <kern/locks.h>
50 #include "net/net_str_id.h"
52 #if IF_LASTCHANGEUPTIME
53 #define TOUCHLASTCHANGE(__if_lastchange) microuptime(__if_lastchange)
55 #define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
58 extern struct dlil_threading_info
*dlil_lo_thread_ptr
;
59 extern int dlil_multithreaded_input
;
62 ifnet_list_get_common(ifnet_family_t
, boolean_t
, ifnet_t
**, u_int32_t
*);
65 Temporary work around until we have real reference counting
67 We keep the bits about calling dlil_if_release (which should be
68 called recycle) transparent by calling it from our if_free function
69 pointer. We have to keep the client's original detach function
70 somewhere so we can call it.
76 ifnet_detached_func detach_func
= ifp
->if_kpi_storage
;
81 if (ifp
->if_broadcast
.length
> sizeof(ifp
->if_broadcast
.u
.buffer
)) {
82 FREE(ifp
->if_broadcast
.u
.ptr
, M_IFADDR
);
83 ifp
->if_broadcast
.u
.ptr
= NULL
;
89 static __inline__
void*
90 _cast_non_const(const void * ptr
) {
102 const struct ifnet_init_params
*init
,
106 struct ifnet
*ifp
= NULL
;
108 if (init
->family
== 0)
110 if (init
->name
== NULL
||
111 init
->output
== NULL
)
113 if (strlen(init
->name
) >= IFNAMSIZ
)
115 if ((init
->type
& 0xFFFFFF00) != 0 || init
->type
== 0)
118 error
= dlil_if_acquire(init
->family
, init
->uniqueid
, init
->uniqueid_len
, &ifp
);
122 * Cast ifp->if_name as non const. dlil_if_acquire sets it up
123 * to point to storage of at least IFNAMSIZ bytes. It is safe
126 strncpy(_cast_non_const(ifp
->if_name
), init
->name
, IFNAMSIZ
);
127 ifp
->if_type
= init
->type
;
128 ifp
->if_family
= init
->family
;
129 ifp
->if_unit
= init
->unit
;
130 ifp
->if_output
= init
->output
;
131 ifp
->if_demux
= init
->demux
;
132 ifp
->if_add_proto
= init
->add_proto
;
133 ifp
->if_del_proto
= init
->del_proto
;
134 ifp
->if_check_multi
= init
->check_multi
;
135 ifp
->if_framer
= init
->framer
;
136 ifp
->if_softc
= init
->softc
;
137 ifp
->if_ioctl
= init
->ioctl
;
138 ifp
->if_set_bpf_tap
= init
->set_bpf_tap
;
139 ifp
->if_free
= ifnet_kpi_free
;
140 ifp
->if_event
= init
->event
;
141 ifp
->if_kpi_storage
= init
->detach
;
142 ifp
->if_eflags
|= IFEF_USEKPI
;
144 if (init
->broadcast_len
&& init
->broadcast_addr
) {
145 if (init
->broadcast_len
> sizeof(ifp
->if_broadcast
.u
.buffer
)) {
146 MALLOC(ifp
->if_broadcast
.u
.ptr
, u_char
*, init
->broadcast_len
, M_IFADDR
, M_NOWAIT
);
147 if (ifp
->if_broadcast
.u
.ptr
== NULL
) {
151 bcopy(init
->broadcast_addr
, ifp
->if_broadcast
.u
.ptr
, init
->broadcast_len
);
155 bcopy(init
->broadcast_addr
, ifp
->if_broadcast
.u
.buffer
, init
->broadcast_len
);
157 ifp
->if_broadcast
.length
= init
->broadcast_len
;
160 bzero(&ifp
->if_broadcast
, sizeof(ifp
->if_broadcast
));
165 ifnet_reference(ifp
); // temporary - this should be done in dlil_if_acquire
168 dlil_if_release(ifp
);
174 Note: We should do something here to indicate that we haven't been
175 attached yet. By doing so, we can catch the case in ifnet_release
176 where the reference count reaches zero and call the recycle
177 function. If the interface is attached, the interface will be
178 recycled when the interface's if_free function is called. If the
179 interface is never attached, the if_free function will never be
180 called and the interface will never be recycled.
192 if (ifp
== NULL
) return EINVAL
;
194 oldval
= OSIncrementAtomic(&ifp
->if_refcnt
);
205 if (ifp
== NULL
) return EINVAL
;
207 oldval
= OSDecrementAtomic(&ifp
->if_refcnt
);
209 panic("ifnet_release - refcount decremented past zero!");
215 ifnet_interface_family_find(const char *module_string
, ifnet_family_t
*family_id
)
217 if (module_string
== NULL
|| family_id
== NULL
)
219 return net_str_id_find_internal(module_string
, family_id
, NSI_IF_FAM_ID
, 1);
227 return interface
== NULL
? NULL
: interface
->if_softc
;
234 return interface
== NULL
? NULL
: interface
->if_name
;
241 return interface
== NULL
? 0 : interface
->if_family
;
248 return interface
== NULL
? (u_int32_t
)0xffffffff : (u_int32_t
)interface
->if_unit
;
255 return interface
== NULL
? (u_int32_t
)0xffffffff : interface
->if_index
;
266 if (interface
== NULL
) return EINVAL
;
267 lock
= (interface
->if_lock
!= 0);
269 if (lock
) ifnet_lock_exclusive(interface
);
271 /* If we are modifying the up/down state, call if_updown */
272 if (lock
&& (mask
& IFF_UP
) != 0) {
273 if_updown(interface
, (new_flags
& IFF_UP
) == IFF_UP
);
276 interface
->if_flags
= (new_flags
& mask
) | (interface
->if_flags
& ~mask
);
277 if (lock
) ifnet_lock_done(interface
);
286 return interface
== NULL
? 0 : interface
->if_flags
;
297 if (interface
== NULL
) return EINVAL
;
298 lock
= (interface
->if_lock
!= 0);
300 if (lock
) ifnet_lock_exclusive(interface
);
301 interface
->if_eflags
= (new_flags
& mask
) | (interface
->if_eflags
& ~mask
);
302 if (lock
) ifnet_lock_done(interface
);
311 return interface
== NULL
? 0 : interface
->if_eflags
;
315 ifnet_set_idle_flags(ifnet_t ifp
, u_int32_t new_flags
, u_int32_t mask
)
317 #if IFNET_ROUTE_REFCNT
318 int lock
, before
, after
;
323 lck_mtx_lock(rnh_lock
);
325 lock
= (ifp
->if_lock
!= NULL
);
327 ifnet_lock_exclusive(ifp
);
329 before
= ifp
->if_idle_flags
;
330 ifp
->if_idle_flags
= (new_flags
& mask
) | (ifp
->if_idle_flags
& ~mask
);
331 after
= ifp
->if_idle_flags
;
333 if ((after
- before
) < 0 && ifp
->if_idle_flags
== 0 &&
334 ifp
->if_want_aggressive_drain
!= 0) {
335 ifp
->if_want_aggressive_drain
= 0;
336 if (ifnet_aggressive_drainers
== 0)
337 panic("%s: ifp=%p negative aggdrain!", __func__
, ifp
);
338 if (--ifnet_aggressive_drainers
== 0)
340 } else if ((after
- before
) > 0 && ifp
->if_want_aggressive_drain
== 0) {
341 ifp
->if_want_aggressive_drain
++;
342 if (++ifnet_aggressive_drainers
== 0)
343 panic("%s: ifp=%p wraparound aggdrain!", __func__
, ifp
);
344 else if (ifnet_aggressive_drainers
== 1)
349 ifnet_lock_done(ifp
);
351 lck_mtx_unlock(rnh_lock
);
355 #pragma unused(ifp, new_flags, mask)
357 #endif /* IFNET_ROUTE_REFCNT */
361 ifnet_idle_flags(ifnet_t ifp
)
363 #if IFNET_ROUTE_REFCNT
364 return ((ifp
== NULL
) ? 0 : ifp
->if_idle_flags
);
368 #endif /* IFNET_ROUTE_REFCNT */
371 static const ifnet_offload_t offload_mask
= IFNET_CSUM_IP
| IFNET_CSUM_TCP
|
372 IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
| IFNET_IP_FRAGMENT
|
373 IFNET_CSUM_SUM16
| IFNET_VLAN_TAGGING
| IFNET_VLAN_MTU
|
374 IFNET_MULTIPAGES
| IFNET_TSO_IPV4
| IFNET_TSO_IPV6
;
379 ifnet_offload_t offload
)
383 if (interface
== NULL
) return EINVAL
;
384 lock
= (interface
->if_lock
!= 0);
386 if (lock
) ifnet_lock_exclusive(interface
);
387 interface
->if_hwassist
= (offload
& offload_mask
);
388 if (lock
) ifnet_lock_done(interface
);
397 return interface
== NULL
? 0 : (interface
->if_hwassist
& offload_mask
);
408 if (interface
== NULL
) return EINVAL
;
410 if (mtuLen
< interface
->if_mtu
)
417 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
418 interface
->if_tso_v4_mtu
= mtuLen
;
424 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
425 interface
->if_tso_v6_mtu
= mtuLen
;
431 error
= EPROTONOSUPPORT
;
445 if (interface
== NULL
|| mtuLen
== NULL
) return EINVAL
;
450 if (interface
->if_hwassist
& IFNET_TSO_IPV4
)
451 *mtuLen
= interface
->if_tso_v4_mtu
;
457 if (interface
->if_hwassist
& IFNET_TSO_IPV6
)
458 *mtuLen
= interface
->if_tso_v6_mtu
;
463 error
= EPROTONOSUPPORT
;
470 ifnet_set_wake_flags(ifnet_t interface
, u_int32_t properties
, u_int32_t mask
)
473 struct kev_msg ev_msg
;
474 struct net_event_data ev_data
;
476 if (interface
== NULL
)
479 /* Do not accept wacky values */
480 if ((properties
& mask
) & ~IF_WAKE_VALID_FLAGS
)
483 lock
= (interface
->if_lock
!= 0);
486 ifnet_lock_exclusive(interface
);
488 interface
->if_wake_properties
= (properties
& mask
) | (interface
->if_wake_properties
& ~mask
);
491 ifnet_lock_done(interface
);
493 (void) ifnet_touch_lastchange(interface
);
495 /* Notify application of the change */
496 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
497 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
498 ev_msg
.kev_subclass
= KEV_DL_SUBCLASS
;
500 ev_msg
.event_code
= KEV_DL_WAKEFLAGS_CHANGED
;
501 strlcpy(&ev_data
.if_name
[0], interface
->if_name
, IFNAMSIZ
);
502 ev_data
.if_family
= interface
->if_family
;
503 ev_data
.if_unit
= (u_int32_t
) interface
->if_unit
;
504 ev_msg
.dv
[0].data_length
= sizeof(struct net_event_data
);
505 ev_msg
.dv
[0].data_ptr
= &ev_data
;
506 ev_msg
.dv
[1].data_length
= 0;
507 kev_post_msg(&ev_msg
);
513 ifnet_get_wake_flags(ifnet_t interface
)
515 return interface
== NULL
? 0 : interface
->if_wake_properties
;
522 * Should MIB data store a copy?
525 ifnet_set_link_mib_data(
532 if (interface
== NULL
) return EINVAL
;
533 lock
= (interface
->if_lock
!= 0);
535 if (lock
) ifnet_lock_exclusive(interface
);
536 interface
->if_linkmib
= (void*)mibData
;
537 interface
->if_linkmiblen
= mibLen
;
538 if (lock
) ifnet_lock_done(interface
);
543 ifnet_get_link_mib_data(
551 if (interface
== NULL
) return EINVAL
;
552 lock
= (interface
->if_lock
!= NULL
);
554 if (lock
) ifnet_lock_shared(interface
);
555 if (*mibLen
< interface
->if_linkmiblen
)
557 if (result
== 0 && interface
->if_linkmib
== NULL
)
561 *mibLen
= interface
->if_linkmiblen
;
562 bcopy(interface
->if_linkmib
, mibData
, *mibLen
);
564 if (lock
) ifnet_lock_done(interface
);
570 ifnet_get_link_mib_data_length(
573 return interface
== NULL
? 0 : interface
->if_linkmiblen
;
579 protocol_family_t protocol_family
,
582 const struct sockaddr
*dest
)
584 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
589 return dlil_output(interface
, protocol_family
, m
, route
, dest
, 0);
595 protocol_family_t protocol_family
,
598 if (interface
== NULL
|| m
== NULL
) {
603 return dlil_output(interface
, protocol_family
, m
, NULL
, NULL
, 1);
611 if (interface
== NULL
) return EINVAL
;
612 interface
->if_data
.ifi_mtu
= mtu
;
621 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_mtu
;
631 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_type
;
641 int lock
= (interface
->if_lock
!= 0);
642 if (lock
) ifnet_lock_exclusive(interface
);
643 interface
->if_data
.ifi_typelen
= typelen
;
644 if (lock
) ifnet_lock_done(interface
);
653 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_typelen
;
663 if (interface
== NULL
) return EINVAL
;
664 interface
->if_data
.ifi_addrlen
= addrlen
;
673 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_addrlen
;
682 if (interface
== NULL
) return EINVAL
;
683 interface
->if_data
.ifi_hdrlen
= hdrlen
;
692 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_hdrlen
;
701 if (interface
== NULL
) return EINVAL
;
702 interface
->if_data
.ifi_metric
= metric
;
711 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_metric
;
720 if (interface
== NULL
) return EINVAL
;
721 /* Pin baudrate to 32 bits until we can change the storage size */
722 interface
->if_data
.ifi_baudrate
= baudrate
> 0xFFFFFFFF ? 0xFFFFFFFF : baudrate
;
731 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_baudrate
;
736 ifnet_stat_increment(
738 const struct ifnet_stat_increment_param
*counts
)
740 struct dlil_threading_info
*thread
;
741 if (interface
== NULL
) return EINVAL
;
743 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
744 thread
= dlil_lo_thread_ptr
;
746 lck_mtx_lock(thread
->input_lck
);
748 interface
->if_data
.ifi_ipackets
+= counts
->packets_in
;
749 interface
->if_data
.ifi_ibytes
+= counts
->bytes_in
;
750 interface
->if_data
.ifi_ierrors
+= counts
->errors_in
;
752 interface
->if_data
.ifi_opackets
+= counts
->packets_out
;
753 interface
->if_data
.ifi_obytes
+= counts
->bytes_out
;
754 interface
->if_data
.ifi_oerrors
+= counts
->errors_out
;
756 interface
->if_data
.ifi_collisions
+= counts
->collisions
;
757 interface
->if_data
.ifi_iqdrops
+= counts
->dropped
;
759 /* Touch the last change time. */
760 TOUCHLASTCHANGE(&interface
->if_lastchange
);
762 lck_mtx_unlock(thread
->input_lck
);
768 ifnet_stat_increment_in(
770 u_int32_t packets_in
,
774 struct dlil_threading_info
*thread
;
776 if (interface
== NULL
) return EINVAL
;
778 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
779 thread
= dlil_lo_thread_ptr
;
781 lck_mtx_lock(thread
->input_lck
);
783 interface
->if_data
.ifi_ipackets
+= packets_in
;
784 interface
->if_data
.ifi_ibytes
+= bytes_in
;
785 interface
->if_data
.ifi_ierrors
+= errors_in
;
787 TOUCHLASTCHANGE(&interface
->if_lastchange
);
789 lck_mtx_unlock(thread
->input_lck
);
795 ifnet_stat_increment_out(
797 u_int32_t packets_out
,
799 u_int32_t errors_out
)
801 struct dlil_threading_info
*thread
;
802 if (interface
== NULL
) return EINVAL
;
804 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
805 thread
= dlil_lo_thread_ptr
;
807 lck_mtx_lock(thread
->input_lck
);
809 interface
->if_data
.ifi_opackets
+= packets_out
;
810 interface
->if_data
.ifi_obytes
+= bytes_out
;
811 interface
->if_data
.ifi_oerrors
+= errors_out
;
813 TOUCHLASTCHANGE(&interface
->if_lastchange
);
815 lck_mtx_unlock(thread
->input_lck
);
823 const struct ifnet_stats_param
*stats
)
825 struct dlil_threading_info
*thread
;
827 if (interface
== NULL
) return EINVAL
;
829 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
830 thread
= dlil_lo_thread_ptr
;
832 lck_mtx_lock(thread
->input_lck
);
834 interface
->if_data
.ifi_ipackets
= stats
->packets_in
;
835 interface
->if_data
.ifi_ibytes
= stats
->bytes_in
;
836 interface
->if_data
.ifi_imcasts
= stats
->multicasts_in
;
837 interface
->if_data
.ifi_ierrors
= stats
->errors_in
;
839 interface
->if_data
.ifi_opackets
= stats
->packets_out
;
840 interface
->if_data
.ifi_obytes
= stats
->bytes_out
;
841 interface
->if_data
.ifi_omcasts
= stats
->multicasts_out
;
842 interface
->if_data
.ifi_oerrors
= stats
->errors_out
;
844 interface
->if_data
.ifi_collisions
= stats
->collisions
;
845 interface
->if_data
.ifi_iqdrops
= stats
->dropped
;
846 interface
->if_data
.ifi_noproto
= stats
->no_protocol
;
848 /* Touch the last change time. */
849 TOUCHLASTCHANGE(&interface
->if_lastchange
);
851 lck_mtx_unlock(thread
->input_lck
);
859 struct ifnet_stats_param
*stats
)
861 struct dlil_threading_info
*thread
;
863 if (interface
== NULL
) return EINVAL
;
865 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
866 thread
= dlil_lo_thread_ptr
;
868 lck_mtx_lock(thread
->input_lck
);
870 stats
->packets_in
= interface
->if_data
.ifi_ipackets
;
871 stats
->bytes_in
= interface
->if_data
.ifi_ibytes
;
872 stats
->multicasts_in
= interface
->if_data
.ifi_imcasts
;
873 stats
->errors_in
= interface
->if_data
.ifi_ierrors
;
875 stats
->packets_out
= interface
->if_data
.ifi_opackets
;
876 stats
->bytes_out
= interface
->if_data
.ifi_obytes
;
877 stats
->multicasts_out
= interface
->if_data
.ifi_omcasts
;
878 stats
->errors_out
= interface
->if_data
.ifi_oerrors
;
880 stats
->collisions
= interface
->if_data
.ifi_collisions
;
881 stats
->dropped
= interface
->if_data
.ifi_iqdrops
;
882 stats
->no_protocol
= interface
->if_data
.ifi_noproto
;
884 lck_mtx_unlock(thread
->input_lck
);
890 ifnet_touch_lastchange(
893 struct dlil_threading_info
*thread
;
895 if (interface
== NULL
) return EINVAL
;
897 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
898 thread
= dlil_lo_thread_ptr
;
900 lck_mtx_lock(thread
->input_lck
);
902 TOUCHLASTCHANGE(&interface
->if_lastchange
);
904 lck_mtx_unlock(thread
->input_lck
);
912 struct timeval
*last_change
)
914 struct dlil_threading_info
*thread
;
916 if (interface
== NULL
) return EINVAL
;
918 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
919 thread
= dlil_lo_thread_ptr
;
921 lck_mtx_lock(thread
->input_lck
);
923 *last_change
= interface
->if_data
.ifi_lastchange
;
925 lck_mtx_unlock(thread
->input_lck
);
927 #if IF_LASTCHANGEUPTIME
928 /* Crude conversion from uptime to calendar time */
929 last_change
->tv_sec
+= boottime_sec();
936 ifnet_get_address_list(
938 ifaddr_t
**addresses
)
940 if (addresses
== NULL
) return EINVAL
;
941 return ifnet_get_address_list_family(interface
, addresses
, 0);
945 ifnet_get_address_list_family(
947 ifaddr_t
**addresses
,
954 if (addresses
== NULL
) return EINVAL
;
957 ifnet_head_lock_shared();
958 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
960 if (interface
&& ifp
!= interface
) continue;
962 ifnet_lock_shared(ifp
);
963 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0) {
964 if (interface
== NULL
|| interface
== ifp
)
967 TAILQ_FOREACH(addr
, &ifp
->if_addrhead
, ifa_link
)
969 if (family
== 0 || addr
->ifa_addr
->sa_family
== family
)
974 else if (interface
!= NULL
) {
975 ifnet_lock_done(ifp
);
979 ifnet_lock_done(ifp
);
982 MALLOC(*addresses
, ifaddr_t
*, sizeof(ifaddr_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
983 if (*addresses
== NULL
) {
988 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
990 if (interface
&& ifp
!= interface
) continue;
992 ifnet_lock_shared(ifp
);
993 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0) {
994 if (interface
== NULL
|| (struct ifnet
*)interface
== ifp
)
997 TAILQ_FOREACH(addr
, &ifp
->if_addrhead
, ifa_link
)
999 if (count
+ 1 > cmax
) break;
1000 if (family
== 0 || addr
->ifa_addr
->sa_family
== family
) {
1001 (*addresses
)[count
] = (ifaddr_t
)addr
;
1002 ifaddr_reference((*addresses
)[count
]);
1008 ifnet_lock_done(ifp
);
1009 if (interface
|| count
== cmax
)
1013 (*addresses
)[cmax
] = 0;
1019 ifnet_free_address_list(
1020 ifaddr_t
*addresses
)
1024 if (addresses
== NULL
) return;
1026 for (i
= 0; addresses
[i
] != NULL
; i
++)
1028 ifaddr_release(addresses
[i
]);
1031 FREE(addresses
, M_TEMP
);
1038 if (interface
== NULL
) return NULL
;
1039 return LLADDR(SDL(interface
->if_addrhead
.tqh_first
->ifa_addr
));
1043 ifnet_llbroadcast_copy_bytes(
1049 if (interface
== NULL
|| addr
== NULL
|| out_len
== NULL
) return EINVAL
;
1051 *out_len
= interface
->if_broadcast
.length
;
1053 if (buffer_len
< interface
->if_broadcast
.length
) {
1057 if (interface
->if_broadcast
.length
== 0)
1060 if (interface
->if_broadcast
.length
<= sizeof(interface
->if_broadcast
.u
.buffer
)) {
1061 bcopy(interface
->if_broadcast
.u
.buffer
, addr
, interface
->if_broadcast
.length
);
1064 bcopy(interface
->if_broadcast
.u
.ptr
, addr
, interface
->if_broadcast
.length
);
1071 ifnet_lladdr_copy_bytes(
1076 struct sockaddr_dl
*sdl
;
1077 if (interface
== NULL
|| lladdr
== NULL
) return EINVAL
;
1079 sdl
= SDL(interface
->if_addrhead
.tqh_first
->ifa_addr
);
1082 if (lladdr_len
!= sdl
->sdl_alen
) {
1083 bzero(lladdr
, lladdr_len
);
1086 bcopy(LLADDR(sdl
), lladdr
, lladdr_len
);
1087 if (bcmp(lladdr
, LLADDR(sdl
), lladdr_len
) == 0 &&
1088 lladdr_len
== sdl
->sdl_alen
)
1095 ifnet_set_lladdr_internal(
1103 struct sockaddr_dl
*sdl
;
1106 if (interface
== NULL
) return EINVAL
;
1108 if (lladdr_len
!= 0 && (lladdr_len
!= interface
->if_addrlen
|| lladdr
== 0))
1111 ifnet_head_lock_shared();
1112 ifa
= ifnet_addrs
[interface
->if_index
- 1];
1114 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1115 if (lladdr_len
!= 0) {
1116 bcopy(lladdr
, LLADDR(sdl
), lladdr_len
);
1119 bzero(LLADDR(sdl
), interface
->if_addrlen
);
1121 sdl
->sdl_alen
= lladdr_len
;
1124 sdl
->sdl_type
= new_type
;
1132 /* Generate a kernel event */
1134 dlil_post_msg(interface
, KEV_DL_SUBCLASS
,
1135 KEV_DL_LINK_ADDRESS_CHANGED
, NULL
, 0);
1147 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, 0, 0);
1151 ifnet_set_lladdr_and_type(
1157 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, type
, 1);
1161 ifnet_add_multicast(
1163 const struct sockaddr
*maddr
,
1164 ifmultiaddr_t
*address
)
1166 if (interface
== NULL
|| maddr
== NULL
) return EINVAL
;
1167 return if_addmulti(interface
, maddr
, address
);
1171 ifnet_remove_multicast(
1172 ifmultiaddr_t address
)
1174 if (address
== NULL
) return EINVAL
;
1175 return if_delmultiaddr(address
, 0);
1178 errno_t
ifnet_get_multicast_list(ifnet_t interface
, ifmultiaddr_t
**addresses
)
1182 struct ifmultiaddr
*addr
;
1185 if (interface
== NULL
|| addresses
== NULL
)
1188 lock
= (interface
->if_lock
!= 0);
1189 if (lock
) ifnet_lock_shared(interface
);
1190 if ((interface
->if_eflags
& IFEF_DETACHING
) == 0) {
1191 LIST_FOREACH(addr
, &interface
->if_multiaddrs
, ifma_link
)
1197 if (lock
) ifnet_lock_done(interface
);
1201 MALLOC(*addresses
, ifmultiaddr_t
*, sizeof(ifmultiaddr_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
1202 if (*addresses
== NULL
) {
1203 if (lock
) ifnet_lock_done(interface
);
1207 LIST_FOREACH(addr
, &interface
->if_multiaddrs
, ifma_link
)
1209 if (count
+ 1 > cmax
)
1211 (*addresses
)[count
] = (ifmultiaddr_t
)addr
;
1212 ifmaddr_reference((*addresses
)[count
]);
1215 (*addresses
)[cmax
] = 0;
1216 if (lock
) ifnet_lock_done(interface
);
1222 ifnet_free_multicast_list(
1223 ifmultiaddr_t
*addresses
)
1227 if (addresses
== NULL
) return;
1229 for (i
= 0; addresses
[i
] != NULL
; i
++)
1231 ifmaddr_release(addresses
[i
]);
1234 FREE(addresses
, M_TEMP
);
1245 if (ifname
== NULL
) return EINVAL
;
1247 namelen
= strlen(ifname
);
1251 ifnet_head_lock_shared();
1252 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
1254 struct ifaddr
*ifa
= ifnet_addrs
[ifp
->if_index
- 1];
1255 struct sockaddr_dl
*ll_addr
;
1257 if (!ifa
|| !ifa
->ifa_addr
)
1260 ll_addr
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1262 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0 &&
1263 namelen
== ll_addr
->sdl_nlen
&&
1264 (strncmp(ll_addr
->sdl_data
, ifname
, ll_addr
->sdl_nlen
) == 0))
1271 ifnet_reference(*interface
);
1275 return (ifp
== NULL
) ? ENXIO
: 0;
1279 ifnet_list_get(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1281 return (ifnet_list_get_common(family
, FALSE
, list
, count
));
1284 __private_extern__ errno_t
1285 ifnet_list_get_all(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1287 return (ifnet_list_get_common(family
, TRUE
, list
, count
));
1291 ifnet_list_get_common(ifnet_family_t family
, boolean_t get_all
, ifnet_t
**list
,
1299 if (list
== NULL
|| count
== NULL
)
1302 ifnet_head_lock_shared();
1303 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
1304 if ((ifp
->if_eflags
& IFEF_DETACHING
) && !get_all
)
1306 if (family
== IFNET_FAMILY_ANY
|| ifp
->if_family
== family
)
1314 MALLOC(*list
, ifnet_t
*, sizeof(ifnet_t
) * (cmax
+ 1),
1321 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
1322 if ((ifp
->if_eflags
& IFEF_DETACHING
) && !get_all
)
1324 if (*count
+ 1 > cmax
)
1326 if (family
== IFNET_FAMILY_ANY
||
1327 ((ifnet_family_t
)ifp
->if_family
) == family
) {
1328 (*list
)[*count
] = (ifnet_t
)ifp
;
1329 ifnet_reference((*list
)[*count
]);
1333 (*list
)[*count
] = NULL
;
1341 ifnet_list_free(ifnet_t
*interfaces
)
1345 if (interfaces
== NULL
)
1348 for (i
= 0; interfaces
[i
]; i
++) {
1349 ifnet_release(interfaces
[i
]);
1352 FREE(interfaces
, M_TEMP
);
1355 /****************************************************************************/
1356 /* ifaddr_t accessors */
1357 /****************************************************************************/
1363 if (ifa
== NULL
) return EINVAL
;
1372 if (ifa
== NULL
) return EINVAL
;
1378 ifaddr_address_family(
1381 if (ifa
&& ifa
->ifa_addr
)
1382 return ifa
->ifa_addr
->sa_family
;
1390 struct sockaddr
*out_addr
,
1391 u_int32_t addr_size
)
1395 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1396 if (ifa
->ifa_addr
== NULL
) return ENOTSUP
;
1398 copylen
= (addr_size
>= ifa
->ifa_addr
->sa_len
) ? ifa
->ifa_addr
->sa_len
: addr_size
;
1399 bcopy(ifa
->ifa_addr
, out_addr
, copylen
);
1401 if (ifa
->ifa_addr
->sa_len
> addr_size
) return EMSGSIZE
;
1409 struct sockaddr
*out_addr
,
1410 u_int32_t addr_size
)
1413 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1414 if (ifa
->ifa_dstaddr
== NULL
) return ENOTSUP
;
1416 copylen
= (addr_size
>= ifa
->ifa_dstaddr
->sa_len
) ? ifa
->ifa_dstaddr
->sa_len
: addr_size
;
1417 bcopy(ifa
->ifa_dstaddr
, out_addr
, copylen
);
1419 if (ifa
->ifa_dstaddr
->sa_len
> addr_size
) return EMSGSIZE
;
1427 struct sockaddr
*out_addr
,
1428 u_int32_t addr_size
)
1431 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1432 if (ifa
->ifa_netmask
== NULL
) return ENOTSUP
;
1434 copylen
= addr_size
>= ifa
->ifa_netmask
->sa_len
? ifa
->ifa_netmask
->sa_len
: addr_size
;
1435 bcopy(ifa
->ifa_netmask
, out_addr
, copylen
);
1437 if (ifa
->ifa_netmask
->sa_len
> addr_size
) return EMSGSIZE
;
1447 if (ifa
== NULL
) return NULL
;
1450 return (ifnet_t
)ifp
;
1455 const struct sockaddr
* address
)
1457 if (address
== NULL
) return NULL
;
1458 return ifa_ifwithaddr(address
);
1463 const struct sockaddr
* address
)
1465 if (address
== NULL
) return NULL
;
1466 return ifa_ifwithdstaddr(address
);
1471 const struct sockaddr
* net
)
1473 if (net
== NULL
) return NULL
;
1474 return ifa_ifwithnet(net
);
1480 const struct sockaddr
* destination
,
1481 const struct sockaddr
* gateway
)
1483 if (destination
== NULL
|| gateway
== NULL
) return NULL
;
1484 return ifa_ifwithroute(flags
, destination
, gateway
);
1488 ifaddr_findbestforaddr(
1489 const struct sockaddr
*addr
,
1492 if (addr
== NULL
|| interface
== NULL
) return NULL
;
1493 return ifaof_ifpforaddr(addr
, interface
);
1498 ifmultiaddr_t ifmaddr
)
1500 if (ifmaddr
== NULL
) return EINVAL
;
1501 ifma_reference(ifmaddr
);
1507 ifmultiaddr_t ifmaddr
)
1509 if (ifmaddr
== NULL
) return EINVAL
;
1510 ifma_release(ifmaddr
);
1516 ifmultiaddr_t ifmaddr
,
1517 struct sockaddr
*out_addr
,
1518 u_int32_t addr_size
)
1522 if (ifmaddr
== NULL
|| out_addr
== NULL
) return EINVAL
;
1523 if (ifmaddr
->ifma_addr
== NULL
) return ENOTSUP
;
1525 copylen
= addr_size
>= ifmaddr
->ifma_addr
->sa_len
? ifmaddr
->ifma_addr
->sa_len
: addr_size
;
1526 bcopy(ifmaddr
->ifma_addr
, out_addr
, copylen
);
1528 if (ifmaddr
->ifma_addr
->sa_len
> addr_size
) return EMSGSIZE
;
1535 ifmultiaddr_t ifmaddr
,
1536 struct sockaddr
*out_addr
,
1537 u_int32_t addr_size
)
1539 if (ifmaddr
== NULL
|| out_addr
== NULL
) return EINVAL
;
1540 if (ifmaddr
->ifma_ll
== NULL
) return ENOTSUP
;
1542 return ifmaddr_address(ifmaddr
->ifma_ll
, out_addr
, addr_size
);
1547 ifmultiaddr_t ifmaddr
)
1549 if (ifmaddr
== NULL
|| ifmaddr
->ifma_ifp
== NULL
) return NULL
;
1550 return ifmaddr
->ifma_ifp
;
1553 /******************************************************************************/
1554 /* interface cloner */
1555 /******************************************************************************/
1558 ifnet_clone_attach(struct ifnet_clone_params
*cloner_params
, if_clone_t
*ifcloner
)
1561 struct if_clone
*ifc
= NULL
;
1564 if (cloner_params
== NULL
|| ifcloner
== NULL
|| cloner_params
->ifc_name
== NULL
||
1565 cloner_params
->ifc_create
== NULL
|| cloner_params
->ifc_destroy
== NULL
||
1566 (namelen
= strlen(cloner_params
->ifc_name
)) >= IFNAMSIZ
) {
1571 if (if_clone_lookup(cloner_params
->ifc_name
, NULL
) != NULL
) {
1572 printf("ifnet_clone_attach: already a cloner for %s\n", cloner_params
->ifc_name
);
1577 /* Make room for name string */
1578 ifc
= _MALLOC(sizeof(struct if_clone
) + IFNAMSIZ
+ 1, M_CLONE
, M_WAITOK
| M_ZERO
);
1580 printf("ifnet_clone_attach: _MALLOC failed\n");
1584 strlcpy((char *)(ifc
+ 1), cloner_params
->ifc_name
, IFNAMSIZ
+ 1);
1585 ifc
->ifc_name
= (char *)(ifc
+ 1);
1586 ifc
->ifc_namelen
= namelen
;
1587 ifc
->ifc_maxunit
= IF_MAXUNIT
;
1588 ifc
->ifc_create
= cloner_params
->ifc_create
;
1589 ifc
->ifc_destroy
= cloner_params
->ifc_destroy
;
1591 error
= if_clone_attach(ifc
);
1593 printf("ifnet_clone_attach: if_clone_attach failed %d\n", error
);
1606 ifnet_clone_detach(if_clone_t ifcloner
)
1609 struct if_clone
*ifc
= ifcloner
;
1611 if (ifc
== NULL
|| ifc
->ifc_name
== NULL
)
1614 if ((if_clone_lookup(ifc
->ifc_name
, NULL
)) == NULL
) {
1615 printf("ifnet_clone_attach: no cloner for %s\n", ifc
->ifc_name
);
1620 if_clone_detach(ifc
);