2 * Copyright (c) 2004-2007 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 #if IF_LASTCHANGEUPTIME
51 #define TOUCHLASTCHANGE(__if_lastchange) microuptime(__if_lastchange)
53 #define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
56 extern struct dlil_threading_info
*dlil_lo_thread_ptr
;
57 extern int dlil_multithreaded_input
;
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.
190 if (ifp
== NULL
) return EINVAL
;
192 oldval
= OSIncrementAtomic((SInt32
*)&ifp
->if_refcnt
);
203 if (ifp
== NULL
) return EINVAL
;
205 oldval
= OSDecrementAtomic((SInt32
*)&ifp
->if_refcnt
);
207 panic("ifnet_release - refcount decremented past zero!");
216 return interface
== NULL
? NULL
: interface
->if_softc
;
223 return interface
== NULL
? NULL
: interface
->if_name
;
230 return interface
== NULL
? 0 : interface
->if_family
;
237 return interface
== NULL
? (u_int32_t
)0xffffffff : (u_int32_t
)interface
->if_unit
;
244 return interface
== NULL
? (u_int32_t
)0xffffffff : interface
->if_index
;
255 if (interface
== NULL
) return EINVAL
;
256 lock
= (interface
->if_lock
!= 0);
258 if (lock
) ifnet_lock_exclusive(interface
);
260 /* If we are modifying the up/down state, call if_updown */
261 if (lock
&& (mask
& IFF_UP
) != 0) {
262 if_updown(interface
, (new_flags
& IFF_UP
) == IFF_UP
);
265 interface
->if_flags
= (new_flags
& mask
) | (interface
->if_flags
& ~mask
);
266 if (lock
) ifnet_lock_done(interface
);
275 return interface
== NULL
? 0 : interface
->if_flags
;
286 if (interface
== NULL
) return EINVAL
;
287 lock
= (interface
->if_lock
!= 0);
289 if (lock
) ifnet_lock_exclusive(interface
);
290 interface
->if_eflags
= (new_flags
& mask
) | (interface
->if_eflags
& ~mask
);
291 if (lock
) ifnet_lock_done(interface
);
300 return interface
== NULL
? 0 : interface
->if_eflags
;
303 static const ifnet_offload_t offload_mask
= IFNET_CSUM_IP
| IFNET_CSUM_TCP
|
304 IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
| IFNET_IP_FRAGMENT
|
305 IFNET_CSUM_SUM16
| IFNET_VLAN_TAGGING
| IFNET_VLAN_MTU
|
311 ifnet_offload_t offload
)
315 if (interface
== NULL
) return EINVAL
;
316 lock
= (interface
->if_lock
!= 0);
318 if (lock
) ifnet_lock_exclusive(interface
);
319 interface
->if_hwassist
= (offload
& offload_mask
);
320 if (lock
) ifnet_lock_done(interface
);
329 return interface
== NULL
? 0 : (interface
->if_hwassist
& offload_mask
);
333 * Should MIB data store a copy?
336 ifnet_set_link_mib_data(
343 if (interface
== NULL
) return EINVAL
;
344 lock
= (interface
->if_lock
!= 0);
346 if (lock
) ifnet_lock_exclusive(interface
);
347 interface
->if_linkmib
= (void*)mibData
;
348 interface
->if_linkmiblen
= mibLen
;
349 if (lock
) ifnet_lock_done(interface
);
354 ifnet_get_link_mib_data(
362 if (interface
== NULL
) return EINVAL
;
363 lock
= (interface
->if_lock
!= NULL
);
365 if (lock
) ifnet_lock_shared(interface
);
366 if (*mibLen
< interface
->if_linkmiblen
)
368 if (result
== 0 && interface
->if_linkmib
== NULL
)
372 *mibLen
= interface
->if_linkmiblen
;
373 bcopy(interface
->if_linkmib
, mibData
, *mibLen
);
375 if (lock
) ifnet_lock_done(interface
);
381 ifnet_get_link_mib_data_length(
384 return interface
== NULL
? 0 : interface
->if_linkmiblen
;
390 protocol_family_t protocol_family
,
393 const struct sockaddr
*dest
)
395 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
400 return dlil_output(interface
, protocol_family
, m
, route
, dest
, 0);
406 protocol_family_t protocol_family
,
409 if (interface
== NULL
|| m
== NULL
) {
414 return dlil_output(interface
, protocol_family
, m
, NULL
, NULL
, 1);
422 if (interface
== NULL
) return EINVAL
;
423 interface
->if_data
.ifi_mtu
= mtu
;
432 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_mtu
;
442 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_type
;
452 int lock
= (interface
->if_lock
!= 0);
453 if (lock
) ifnet_lock_exclusive(interface
);
454 interface
->if_data
.ifi_typelen
= typelen
;
455 if (lock
) ifnet_lock_done(interface
);
464 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_typelen
;
474 if (interface
== NULL
) return EINVAL
;
475 interface
->if_data
.ifi_addrlen
= addrlen
;
484 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_addrlen
;
493 if (interface
== NULL
) return EINVAL
;
494 interface
->if_data
.ifi_hdrlen
= hdrlen
;
503 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_hdrlen
;
512 if (interface
== NULL
) return EINVAL
;
513 interface
->if_data
.ifi_metric
= metric
;
522 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_metric
;
531 if (interface
== NULL
) return EINVAL
;
532 /* Pin baudrate to 32 bits until we can change the storage size */
533 interface
->if_data
.ifi_baudrate
= baudrate
> 0xFFFFFFFF ? 0xFFFFFFFF : baudrate
;
542 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_baudrate
;
547 ifnet_stat_increment(
549 const struct ifnet_stat_increment_param
*counts
)
551 struct dlil_threading_info
*thread
;
552 if (interface
== NULL
) return EINVAL
;
554 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
555 thread
= dlil_lo_thread_ptr
;
557 lck_mtx_lock(thread
->input_lck
);
559 interface
->if_data
.ifi_ipackets
+= counts
->packets_in
;
560 interface
->if_data
.ifi_ibytes
+= counts
->bytes_in
;
561 interface
->if_data
.ifi_ierrors
+= counts
->errors_in
;
563 interface
->if_data
.ifi_opackets
+= counts
->packets_out
;
564 interface
->if_data
.ifi_obytes
+= counts
->bytes_out
;
565 interface
->if_data
.ifi_oerrors
+= counts
->errors_out
;
567 interface
->if_data
.ifi_collisions
+= counts
->collisions
;
568 interface
->if_data
.ifi_iqdrops
+= counts
->dropped
;
570 /* Touch the last change time. */
571 TOUCHLASTCHANGE(&interface
->if_lastchange
);
573 lck_mtx_unlock(thread
->input_lck
);
579 ifnet_stat_increment_in(
581 u_int32_t packets_in
,
585 struct dlil_threading_info
*thread
;
587 if (interface
== NULL
) return EINVAL
;
589 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
590 thread
= dlil_lo_thread_ptr
;
592 lck_mtx_lock(thread
->input_lck
);
594 interface
->if_data
.ifi_ipackets
+= packets_in
;
595 interface
->if_data
.ifi_ibytes
+= bytes_in
;
596 interface
->if_data
.ifi_ierrors
+= errors_in
;
598 TOUCHLASTCHANGE(&interface
->if_lastchange
);
600 lck_mtx_unlock(thread
->input_lck
);
606 ifnet_stat_increment_out(
608 u_int32_t packets_out
,
610 u_int32_t errors_out
)
612 struct dlil_threading_info
*thread
;
613 if (interface
== NULL
) return EINVAL
;
615 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
616 thread
= dlil_lo_thread_ptr
;
618 lck_mtx_lock(thread
->input_lck
);
620 interface
->if_data
.ifi_opackets
+= packets_out
;
621 interface
->if_data
.ifi_obytes
+= bytes_out
;
622 interface
->if_data
.ifi_oerrors
+= errors_out
;
624 TOUCHLASTCHANGE(&interface
->if_lastchange
);
626 lck_mtx_unlock(thread
->input_lck
);
634 const struct ifnet_stats_param
*stats
)
636 struct dlil_threading_info
*thread
;
638 if (interface
== NULL
) return EINVAL
;
640 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
641 thread
= dlil_lo_thread_ptr
;
643 lck_mtx_lock(thread
->input_lck
);
645 interface
->if_data
.ifi_ipackets
= stats
->packets_in
;
646 interface
->if_data
.ifi_ibytes
= stats
->bytes_in
;
647 interface
->if_data
.ifi_imcasts
= stats
->multicasts_in
;
648 interface
->if_data
.ifi_ierrors
= stats
->errors_in
;
650 interface
->if_data
.ifi_opackets
= stats
->packets_out
;
651 interface
->if_data
.ifi_obytes
= stats
->bytes_out
;
652 interface
->if_data
.ifi_omcasts
= stats
->multicasts_out
;
653 interface
->if_data
.ifi_oerrors
= stats
->errors_out
;
655 interface
->if_data
.ifi_collisions
= stats
->collisions
;
656 interface
->if_data
.ifi_iqdrops
= stats
->dropped
;
657 interface
->if_data
.ifi_noproto
= stats
->no_protocol
;
659 /* Touch the last change time. */
660 TOUCHLASTCHANGE(&interface
->if_lastchange
);
662 lck_mtx_unlock(thread
->input_lck
);
670 struct ifnet_stats_param
*stats
)
672 struct dlil_threading_info
*thread
;
674 if (interface
== NULL
) return EINVAL
;
676 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
677 thread
= dlil_lo_thread_ptr
;
679 lck_mtx_lock(thread
->input_lck
);
681 stats
->packets_in
= interface
->if_data
.ifi_ipackets
;
682 stats
->bytes_in
= interface
->if_data
.ifi_ibytes
;
683 stats
->multicasts_in
= interface
->if_data
.ifi_imcasts
;
684 stats
->errors_in
= interface
->if_data
.ifi_ierrors
;
686 stats
->packets_out
= interface
->if_data
.ifi_opackets
;
687 stats
->bytes_out
= interface
->if_data
.ifi_obytes
;
688 stats
->multicasts_out
= interface
->if_data
.ifi_omcasts
;
689 stats
->errors_out
= interface
->if_data
.ifi_oerrors
;
691 stats
->collisions
= interface
->if_data
.ifi_collisions
;
692 stats
->dropped
= interface
->if_data
.ifi_iqdrops
;
693 stats
->no_protocol
= interface
->if_data
.ifi_noproto
;
695 lck_mtx_unlock(thread
->input_lck
);
701 ifnet_touch_lastchange(
704 struct dlil_threading_info
*thread
;
706 if (interface
== NULL
) return EINVAL
;
708 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
709 thread
= dlil_lo_thread_ptr
;
711 lck_mtx_lock(thread
->input_lck
);
713 TOUCHLASTCHANGE(&interface
->if_lastchange
);
715 lck_mtx_unlock(thread
->input_lck
);
723 struct timeval
*last_change
)
725 struct dlil_threading_info
*thread
;
727 if (interface
== NULL
) return EINVAL
;
729 if ((thread
= interface
->if_input_thread
) == NULL
|| (dlil_multithreaded_input
== 0))
730 thread
= dlil_lo_thread_ptr
;
732 lck_mtx_lock(thread
->input_lck
);
734 *last_change
= interface
->if_data
.ifi_lastchange
;
736 lck_mtx_unlock(thread
->input_lck
);
738 #if IF_LASTCHANGEUPTIME
739 /* Crude conversion from uptime to calendar time */
740 last_change
->tv_sec
+= boottime_sec();
747 ifnet_get_address_list(
749 ifaddr_t
**addresses
)
751 if (addresses
== NULL
) return EINVAL
;
752 return ifnet_get_address_list_family(interface
, addresses
, 0);
756 ifnet_get_address_list_family(
758 ifaddr_t
**addresses
,
765 if (addresses
== NULL
) return EINVAL
;
768 ifnet_head_lock_shared();
769 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
771 if (interface
&& ifp
!= interface
) continue;
773 ifnet_lock_shared(ifp
);
774 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0) {
775 if (interface
== NULL
|| interface
== ifp
)
778 TAILQ_FOREACH(addr
, &ifp
->if_addrhead
, ifa_link
)
780 if (family
== 0 || addr
->ifa_addr
->sa_family
== family
)
785 else if (interface
!= NULL
) {
786 ifnet_lock_done(ifp
);
790 ifnet_lock_done(ifp
);
793 MALLOC(*addresses
, ifaddr_t
*, sizeof(ifaddr_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
794 if (*addresses
== NULL
) {
799 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
801 if (interface
&& ifp
!= interface
) continue;
803 ifnet_lock_shared(ifp
);
804 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0) {
805 if (interface
== NULL
|| (struct ifnet
*)interface
== ifp
)
808 TAILQ_FOREACH(addr
, &ifp
->if_addrhead
, ifa_link
)
810 if (count
+ 1 > cmax
) break;
811 if (family
== 0 || addr
->ifa_addr
->sa_family
== family
) {
812 (*addresses
)[count
] = (ifaddr_t
)addr
;
813 ifaddr_reference((*addresses
)[count
]);
819 ifnet_lock_done(ifp
);
820 if (interface
|| count
== cmax
)
824 (*addresses
)[cmax
] = 0;
830 ifnet_free_address_list(
835 if (addresses
== NULL
) return;
837 for (i
= 0; addresses
[i
] != NULL
; i
++)
839 ifaddr_release(addresses
[i
]);
842 FREE(addresses
, M_TEMP
);
849 if (interface
== NULL
) return NULL
;
850 return LLADDR(SDL(interface
->if_addrhead
.tqh_first
->ifa_addr
));
854 ifnet_llbroadcast_copy_bytes(
860 if (interface
== NULL
|| addr
== NULL
|| out_len
== NULL
) return EINVAL
;
862 *out_len
= interface
->if_broadcast
.length
;
864 if (buffer_len
< interface
->if_broadcast
.length
) {
868 if (interface
->if_broadcast
.length
== 0)
871 if (interface
->if_broadcast
.length
<= sizeof(interface
->if_broadcast
.u
.buffer
)) {
872 bcopy(interface
->if_broadcast
.u
.buffer
, addr
, interface
->if_broadcast
.length
);
875 bcopy(interface
->if_broadcast
.u
.ptr
, addr
, interface
->if_broadcast
.length
);
882 ifnet_lladdr_copy_bytes(
887 struct sockaddr_dl
*sdl
;
888 if (interface
== NULL
|| lladdr
== NULL
) return EINVAL
;
890 sdl
= SDL(interface
->if_addrhead
.tqh_first
->ifa_addr
);
893 if (lladdr_len
!= sdl
->sdl_alen
) {
894 bzero(lladdr
, lladdr_len
);
897 bcopy(LLADDR(sdl
), lladdr
, lladdr_len
);
898 if (bcmp(lladdr
, LLADDR(sdl
), lladdr_len
) == 0 &&
899 lladdr_len
== sdl
->sdl_alen
)
906 ifnet_set_lladdr_internal(
914 struct sockaddr_dl
*sdl
;
917 if (interface
== NULL
) return EINVAL
;
919 if (lladdr_len
!= 0 && (lladdr_len
!= interface
->if_addrlen
|| lladdr
== 0))
922 ifnet_head_lock_shared();
923 ifa
= ifnet_addrs
[interface
->if_index
- 1];
925 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
926 if (lladdr_len
!= 0) {
927 bcopy(lladdr
, LLADDR(sdl
), lladdr_len
);
930 bzero(LLADDR(sdl
), interface
->if_addrlen
);
932 sdl
->sdl_alen
= lladdr_len
;
935 sdl
->sdl_type
= new_type
;
943 /* Generate a kernel event */
945 dlil_post_msg(interface
, KEV_DL_SUBCLASS
,
946 KEV_DL_LINK_ADDRESS_CHANGED
, NULL
, 0);
958 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, 0, 0);
962 ifnet_set_lladdr_and_type(
968 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, type
, 1);
974 const struct sockaddr
*maddr
,
975 ifmultiaddr_t
*address
)
977 if (interface
== NULL
|| maddr
== NULL
) return EINVAL
;
978 return if_addmulti(interface
, maddr
, address
);
982 ifnet_remove_multicast(
983 ifmultiaddr_t address
)
985 if (address
== NULL
) return EINVAL
;
986 return if_delmultiaddr(address
, 0);
989 errno_t
ifnet_get_multicast_list(ifnet_t interface
, ifmultiaddr_t
**addresses
)
993 struct ifmultiaddr
*addr
;
996 if (interface
== NULL
|| addresses
== NULL
)
999 lock
= (interface
->if_lock
!= 0);
1000 if (lock
) ifnet_lock_shared(interface
);
1001 if ((interface
->if_eflags
& IFEF_DETACHING
) == 0) {
1002 LIST_FOREACH(addr
, &interface
->if_multiaddrs
, ifma_link
)
1008 if (lock
) ifnet_lock_done(interface
);
1012 MALLOC(*addresses
, ifmultiaddr_t
*, sizeof(ifmultiaddr_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
1013 if (*addresses
== NULL
) {
1014 if (lock
) ifnet_lock_done(interface
);
1018 LIST_FOREACH(addr
, &interface
->if_multiaddrs
, ifma_link
)
1020 if (count
+ 1 > cmax
)
1022 (*addresses
)[count
] = (ifmultiaddr_t
)addr
;
1023 ifmaddr_reference((*addresses
)[count
]);
1026 (*addresses
)[cmax
] = 0;
1027 if (lock
) ifnet_lock_done(interface
);
1033 ifnet_free_multicast_list(
1034 ifmultiaddr_t
*addresses
)
1038 if (addresses
== NULL
) return;
1040 for (i
= 0; addresses
[i
] != NULL
; i
++)
1042 ifmaddr_release(addresses
[i
]);
1045 FREE(addresses
, M_TEMP
);
1056 if (ifname
== NULL
) return EINVAL
;
1058 namelen
= strlen(ifname
);
1062 ifnet_head_lock_shared();
1063 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
1065 struct ifaddr
*ifa
= ifnet_addrs
[ifp
->if_index
- 1];
1066 struct sockaddr_dl
*ll_addr
;
1068 if (!ifa
|| !ifa
->ifa_addr
)
1071 ll_addr
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1073 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0 &&
1074 namelen
== ll_addr
->sdl_nlen
&&
1075 (strncmp(ll_addr
->sdl_data
, ifname
, ll_addr
->sdl_nlen
) == 0))
1082 ifnet_reference(*interface
);
1086 return (ifp
== NULL
) ? ENXIO
: 0;
1090 ifnet_list_get(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1092 return (ifnet_list_get_common(family
, FALSE
, list
, count
));
1095 __private_extern__ errno_t
1096 ifnet_list_get_all(ifnet_family_t family
, ifnet_t
**list
, u_int32_t
*count
)
1098 return (ifnet_list_get_common(family
, TRUE
, list
, count
));
1102 ifnet_list_get_common(ifnet_family_t family
, boolean_t get_all
, ifnet_t
**list
,
1110 if (list
== NULL
|| count
== NULL
)
1113 ifnet_head_lock_shared();
1114 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
1115 if ((ifp
->if_eflags
& IFEF_DETACHING
) && !get_all
)
1117 if (family
== IFNET_FAMILY_ANY
|| ifp
->if_family
== family
)
1125 MALLOC(*list
, ifnet_t
*, sizeof(ifnet_t
) * (cmax
+ 1),
1132 TAILQ_FOREACH(ifp
, &ifnet
, if_link
) {
1133 if ((ifp
->if_eflags
& IFEF_DETACHING
) && !get_all
)
1135 if (*count
+ 1 > cmax
)
1137 if (family
== IFNET_FAMILY_ANY
||
1138 ((ifnet_family_t
)ifp
->if_family
) == family
) {
1139 (*list
)[*count
] = (ifnet_t
)ifp
;
1140 ifnet_reference((*list
)[*count
]);
1144 (*list
)[*count
] = NULL
;
1152 ifnet_list_free(ifnet_t
*interfaces
)
1156 if (interfaces
== NULL
)
1159 for (i
= 0; interfaces
[i
]; i
++) {
1160 ifnet_release(interfaces
[i
]);
1163 FREE(interfaces
, M_TEMP
);
1166 /****************************************************************************/
1167 /* ifaddr_t accessors */
1168 /****************************************************************************/
1174 if (ifa
== NULL
) return EINVAL
;
1183 if (ifa
== NULL
) return EINVAL
;
1189 ifaddr_address_family(
1192 if (ifa
&& ifa
->ifa_addr
)
1193 return ifa
->ifa_addr
->sa_family
;
1201 struct sockaddr
*out_addr
,
1202 u_int32_t addr_size
)
1206 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1207 if (ifa
->ifa_addr
== NULL
) return ENOTSUP
;
1209 copylen
= (addr_size
>= ifa
->ifa_addr
->sa_len
) ? ifa
->ifa_addr
->sa_len
: addr_size
;
1210 bcopy(ifa
->ifa_addr
, out_addr
, copylen
);
1212 if (ifa
->ifa_addr
->sa_len
> addr_size
) return EMSGSIZE
;
1220 struct sockaddr
*out_addr
,
1221 u_int32_t addr_size
)
1224 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1225 if (ifa
->ifa_dstaddr
== NULL
) return ENOTSUP
;
1227 copylen
= (addr_size
>= ifa
->ifa_dstaddr
->sa_len
) ? ifa
->ifa_dstaddr
->sa_len
: addr_size
;
1228 bcopy(ifa
->ifa_dstaddr
, out_addr
, copylen
);
1230 if (ifa
->ifa_dstaddr
->sa_len
> addr_size
) return EMSGSIZE
;
1238 struct sockaddr
*out_addr
,
1239 u_int32_t addr_size
)
1242 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1243 if (ifa
->ifa_netmask
== NULL
) return ENOTSUP
;
1245 copylen
= addr_size
>= ifa
->ifa_netmask
->sa_len
? ifa
->ifa_netmask
->sa_len
: addr_size
;
1246 bcopy(ifa
->ifa_netmask
, out_addr
, copylen
);
1248 if (ifa
->ifa_netmask
->sa_len
> addr_size
) return EMSGSIZE
;
1258 if (ifa
== NULL
) return NULL
;
1261 return (ifnet_t
)ifp
;
1266 const struct sockaddr
* address
)
1268 if (address
== NULL
) return NULL
;
1269 return ifa_ifwithaddr(address
);
1274 const struct sockaddr
* address
)
1276 if (address
== NULL
) return NULL
;
1277 return ifa_ifwithdstaddr(address
);
1282 const struct sockaddr
* net
)
1284 if (net
== NULL
) return NULL
;
1285 return ifa_ifwithnet(net
);
1291 const struct sockaddr
* destination
,
1292 const struct sockaddr
* gateway
)
1294 if (destination
== NULL
|| gateway
== NULL
) return NULL
;
1295 return ifa_ifwithroute(flags
, destination
, gateway
);
1299 ifaddr_findbestforaddr(
1300 const struct sockaddr
*addr
,
1303 if (addr
== NULL
|| interface
== NULL
) return NULL
;
1304 return ifaof_ifpforaddr(addr
, interface
);
1309 ifmultiaddr_t ifmaddr
)
1311 if (ifmaddr
== NULL
) return EINVAL
;
1312 ifma_reference(ifmaddr
);
1318 ifmultiaddr_t ifmaddr
)
1320 if (ifmaddr
== NULL
) return EINVAL
;
1321 ifma_release(ifmaddr
);
1327 ifmultiaddr_t ifmaddr
,
1328 struct sockaddr
*out_addr
,
1329 u_int32_t addr_size
)
1333 if (ifmaddr
== NULL
|| out_addr
== NULL
) return EINVAL
;
1334 if (ifmaddr
->ifma_addr
== NULL
) return ENOTSUP
;
1336 copylen
= addr_size
>= ifmaddr
->ifma_addr
->sa_len
? ifmaddr
->ifma_addr
->sa_len
: addr_size
;
1337 bcopy(ifmaddr
->ifma_addr
, out_addr
, copylen
);
1339 if (ifmaddr
->ifma_addr
->sa_len
> addr_size
) return EMSGSIZE
;
1346 ifmultiaddr_t ifmaddr
,
1347 struct sockaddr
*out_addr
,
1348 u_int32_t addr_size
)
1350 if (ifmaddr
== NULL
|| out_addr
== NULL
) return EINVAL
;
1351 if (ifmaddr
->ifma_ll
== NULL
) return ENOTSUP
;
1353 return ifmaddr_address(ifmaddr
->ifma_ll
, out_addr
, addr_size
);
1358 ifmultiaddr_t ifmaddr
)
1360 if (ifmaddr
== NULL
|| ifmaddr
->ifma_ifp
== NULL
) return NULL
;
1361 return ifmaddr
->ifma_ifp
;