2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 #include "kpi_interface.h"
33 #include <sys/queue.h>
34 #include <sys/param.h> /* for definition of NULL */
35 #include <sys/errno.h>
36 #include <sys/socket.h>
37 #include <sys/kern_event.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/kpi_mbuf.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 <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 lck_spin_t
*dlil_input_lock
;
59 Temporary work around until we have real reference counting
61 We keep the bits about calling dlil_if_release (which should be
62 called recycle) transparent by calling it from our if_free function
63 pointer. We have to keep the client's original detach function
64 somewhere so we can call it.
70 ifnet_detached_func detach_func
= ifp
->if_kpi_storage
;
75 if (ifp
->if_broadcast
.length
> sizeof(ifp
->if_broadcast
.u
.buffer
)) {
76 FREE(ifp
->if_broadcast
.u
.ptr
, M_IFADDR
);
77 ifp
->if_broadcast
.u
.ptr
= NULL
;
85 const struct ifnet_init_params
*init
,
89 struct ifnet
*ifp
= NULL
;
91 if (init
->family
== 0)
93 if (init
->name
== NULL
||
96 if (strlen(init
->name
) >= IFNAMSIZ
)
98 if ((init
->type
& 0xFFFFFF00) != 0 || init
->type
== 0)
101 error
= dlil_if_acquire(init
->family
, init
->uniqueid
, init
->uniqueid_len
, &ifp
);
104 strncpy(ifp
->if_name
, init
->name
, IFNAMSIZ
);
105 ifp
->if_type
= init
->type
;
106 ifp
->if_family
= init
->family
;
107 ifp
->if_unit
= init
->unit
;
108 ifp
->if_output
= init
->output
;
109 ifp
->if_demux
= init
->demux
;
110 ifp
->if_add_proto_u
.kpi
= init
->add_proto
;
111 ifp
->if_del_proto
= init
->del_proto
;
112 ifp
->if_check_multi
= init
->check_multi
;
113 ifp
->if_framer
= init
->framer
;
114 ifp
->if_softc
= init
->softc
;
115 ifp
->if_ioctl
= init
->ioctl
;
116 ifp
->if_set_bpf_tap
= init
->set_bpf_tap
;
117 ifp
->if_free
= ifnet_kpi_free
;
118 ifp
->if_event
= init
->event
;
119 ifp
->if_kpi_storage
= init
->detach
;
120 ifp
->if_eflags
|= IFEF_USEKPI
;
122 if (init
->broadcast_len
&& init
->broadcast_addr
) {
123 if (init
->broadcast_len
> sizeof(ifp
->if_broadcast
.u
.buffer
)) {
124 MALLOC(ifp
->if_broadcast
.u
.ptr
, u_char
*, init
->broadcast_len
, M_IFADDR
, M_NOWAIT
);
125 if (ifp
->if_broadcast
.u
.ptr
== NULL
) {
129 bcopy(init
->broadcast_addr
, ifp
->if_broadcast
.u
.ptr
, init
->broadcast_len
);
133 bcopy(init
->broadcast_addr
, ifp
->if_broadcast
.u
.buffer
, init
->broadcast_len
);
135 ifp
->if_broadcast
.length
= init
->broadcast_len
;
138 bzero(&ifp
->if_broadcast
, sizeof(ifp
->if_broadcast
));
143 ifnet_reference(ifp
); // temporary - this should be done in dlil_if_acquire
146 dlil_if_release(ifp
);
152 Note: We should do something here to indicate that we haven't been
153 attached yet. By doing so, we can catch the case in ifnet_release
154 where the reference count reaches zero and call the recycle
155 function. If the interface is attached, the interface will be
156 recycled when the interface's if_free function is called. If the
157 interface is never attached, the if_free function will never be
158 called and the interface will never be recycled.
168 if (interface
== NULL
) return EINVAL
;
169 ifp_reference(interface
);
177 if (interface
== NULL
) return EINVAL
;
178 ifp_release(interface
);
185 const struct sockaddr_dl
*ll_addr
)
187 if (interface
== NULL
) return EINVAL
;
188 if (ll_addr
&& interface
->if_addrlen
== 0) {
189 interface
->if_addrlen
= ll_addr
->sdl_alen
;
191 else if (ll_addr
&& ll_addr
->sdl_alen
!= interface
->if_addrlen
) {
194 return dlil_if_attach_with_address(interface
, ll_addr
);
203 if (interface
== NULL
) return EINVAL
;
205 error
= dlil_if_detach(interface
);
206 if (error
== DLIL_WAIT_FOR_FREE
) error
= 0; /* Client should always wait for detach */
215 return interface
== NULL
? NULL
: interface
->if_softc
;
222 return interface
== NULL
? NULL
: interface
->if_name
;
229 return interface
== NULL
? 0 : interface
->if_family
;
236 return interface
== NULL
? (u_int32_t
)0xffffffff : (u_int32_t
)interface
->if_unit
;
243 return interface
== NULL
? (u_int32_t
)0xffffffff : interface
->if_index
;
254 if (interface
== NULL
) return EINVAL
;
255 lock
= (interface
->if_lock
!= 0);
257 if (lock
) ifnet_lock_exclusive(interface
);
259 /* If we are modifying the up/down state, call if_updown */
260 if (lock
&& (mask
& IFF_UP
) != 0) {
261 if_updown(interface
, (new_flags
& IFF_UP
) == IFF_UP
);
264 interface
->if_flags
= (new_flags
& mask
) | (interface
->if_flags
& ~mask
);
265 if (lock
) ifnet_lock_done(interface
);
274 return interface
== NULL
? 0 : interface
->if_flags
;
285 if (interface
== NULL
) return EINVAL
;
286 lock
= (interface
->if_lock
!= 0);
288 if (lock
) ifnet_lock_exclusive(interface
);
289 interface
->if_eflags
= (new_flags
& mask
) | (interface
->if_eflags
& ~mask
);
290 if (lock
) ifnet_lock_done(interface
);
299 return interface
== NULL
? 0 : interface
->if_eflags
;
302 static const ifnet_offload_t offload_mask
= IFNET_CSUM_IP
| IFNET_CSUM_TCP
|
303 IFNET_CSUM_UDP
| IFNET_CSUM_FRAGMENT
| IFNET_IP_FRAGMENT
|
304 IFNET_CSUM_SUM16
| IFNET_VLAN_TAGGING
| IFNET_VLAN_MTU
;
309 ifnet_offload_t offload
)
313 if (interface
== NULL
) return EINVAL
;
314 lock
= (interface
->if_lock
!= 0);
316 if (lock
) ifnet_lock_exclusive(interface
);
317 interface
->if_hwassist
= (offload
& offload_mask
);
318 if (lock
) ifnet_lock_done(interface
);
327 return interface
== NULL
? 0 : (interface
->if_hwassist
& offload_mask
);
331 * Should MIB data store a copy?
334 ifnet_set_link_mib_data(
341 if (interface
== NULL
) return EINVAL
;
342 lock
= (interface
->if_lock
!= 0);
344 if (lock
) ifnet_lock_exclusive(interface
);
345 interface
->if_linkmib
= (void*)mibData
;
346 interface
->if_linkmiblen
= mibLen
;
347 if (lock
) ifnet_lock_done(interface
);
352 ifnet_get_link_mib_data(
360 if (interface
== NULL
) return EINVAL
;
361 lock
= (interface
->if_lock
!= NULL
);
363 if (lock
) ifnet_lock_shared(interface
);
364 if (*mibLen
< interface
->if_linkmiblen
)
366 if (result
== 0 && interface
->if_linkmib
== NULL
)
370 *mibLen
= interface
->if_linkmiblen
;
371 bcopy(interface
->if_linkmib
, mibData
, *mibLen
);
373 if (lock
) ifnet_lock_done(interface
);
379 ifnet_get_link_mib_data_length(
382 return interface
== NULL
? 0 : interface
->if_linkmiblen
;
386 ifnet_attach_protocol(
388 protocol_family_t protocol
,
389 const struct ifnet_attach_proto_param
*proto_details
)
391 if (interface
== NULL
|| protocol
== 0 || proto_details
== NULL
)
393 return dlil_attach_protocol_kpi(interface
, protocol
, proto_details
);
397 ifnet_detach_protocol(
399 protocol_family_t protocol
)
401 if (interface
== NULL
|| protocol
== 0) return EINVAL
;
402 return dlil_detach_protocol(interface
, protocol
);
408 protocol_family_t protocol_family
,
411 const struct sockaddr
*dest
)
413 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
418 return dlil_output(interface
, protocol_family
, m
, route
, dest
, 0);
424 protocol_family_t protocol_family
,
427 if (interface
== NULL
|| protocol_family
== 0 || m
== NULL
) {
432 return dlil_output(interface
, protocol_family
, m
, NULL
, NULL
, 1);
439 const struct ifnet_stat_increment_param
*stats
)
441 mbuf_t last_packet
= first_packet
;
443 if (interface
== NULL
|| first_packet
== NULL
) {
445 mbuf_freem_list(first_packet
);
449 while (mbuf_nextpkt(last_packet
) != NULL
)
450 last_packet
= mbuf_nextpkt(last_packet
);
451 return dlil_input_with_stats(interface
, first_packet
, last_packet
, stats
);
457 protocol_family_t protocol_family
,
458 u_int32_t ioctl_code
,
461 if (interface
== NULL
|| protocol_family
== 0 || ioctl_code
== 0)
463 return dlil_ioctl(protocol_family
, interface
,
464 ioctl_code
, ioctl_arg
);
470 struct kern_event_msg
* event_ptr
)
472 if (interface
== NULL
|| event_ptr
== NULL
) return EINVAL
;
473 return dlil_event(interface
, event_ptr
);
481 if (interface
== NULL
) return EINVAL
;
482 interface
->if_data
.ifi_mtu
= mtu
;
491 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_mtu
;
501 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_type
;
511 int lock
= (interface
->if_lock
!= 0);
512 if (lock
) ifnet_lock_exclusive(interface
);
513 interface
->if_data
.ifi_typelen
= typelen
;
514 if (lock
) ifnet_lock_done(interface
);
523 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_typelen
;
533 if (interface
== NULL
) return EINVAL
;
534 interface
->if_data
.ifi_addrlen
= addrlen
;
543 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_addrlen
;
552 if (interface
== NULL
) return EINVAL
;
553 interface
->if_data
.ifi_hdrlen
= hdrlen
;
562 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_hdrlen
;
571 if (interface
== NULL
) return EINVAL
;
572 interface
->if_data
.ifi_metric
= metric
;
581 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_metric
;
590 if (interface
== NULL
) return EINVAL
;
591 /* Pin baudrate to 32 bits until we can change the storage size */
592 interface
->if_data
.ifi_baudrate
= baudrate
> 0xFFFFFFFF ? 0xFFFFFFFF : baudrate
;
601 retval
= interface
== NULL
? 0 : interface
->if_data
.ifi_baudrate
;
606 ifnet_stat_increment(
608 const struct ifnet_stat_increment_param
*counts
)
610 if (interface
== NULL
) return EINVAL
;
612 lck_spin_lock(dlil_input_lock
);
614 interface
->if_data
.ifi_ipackets
+= counts
->packets_in
;
615 interface
->if_data
.ifi_ibytes
+= counts
->bytes_in
;
616 interface
->if_data
.ifi_ierrors
+= counts
->errors_in
;
618 interface
->if_data
.ifi_opackets
+= counts
->packets_out
;
619 interface
->if_data
.ifi_obytes
+= counts
->bytes_out
;
620 interface
->if_data
.ifi_oerrors
+= counts
->errors_out
;
622 interface
->if_data
.ifi_collisions
+= counts
->collisions
;
623 interface
->if_data
.ifi_iqdrops
+= counts
->dropped
;
625 /* Touch the last change time. */
626 TOUCHLASTCHANGE(&interface
->if_lastchange
);
628 lck_spin_unlock(dlil_input_lock
);
634 ifnet_stat_increment_in(
636 u_int32_t packets_in
,
640 if (interface
== NULL
) return EINVAL
;
642 lck_spin_lock(dlil_input_lock
);
644 interface
->if_data
.ifi_ipackets
+= packets_in
;
645 interface
->if_data
.ifi_ibytes
+= bytes_in
;
646 interface
->if_data
.ifi_ierrors
+= errors_in
;
648 TOUCHLASTCHANGE(&interface
->if_lastchange
);
650 lck_spin_unlock(dlil_input_lock
);
656 ifnet_stat_increment_out(
658 u_int32_t packets_out
,
660 u_int32_t errors_out
)
662 if (interface
== NULL
) return EINVAL
;
664 lck_spin_lock(dlil_input_lock
);
666 interface
->if_data
.ifi_opackets
+= packets_out
;
667 interface
->if_data
.ifi_obytes
+= bytes_out
;
668 interface
->if_data
.ifi_oerrors
+= errors_out
;
670 TOUCHLASTCHANGE(&interface
->if_lastchange
);
672 lck_spin_unlock(dlil_input_lock
);
680 const struct ifnet_stats_param
*stats
)
682 if (interface
== NULL
) return EINVAL
;
684 lck_spin_lock(dlil_input_lock
);
686 interface
->if_data
.ifi_ipackets
= stats
->packets_in
;
687 interface
->if_data
.ifi_ibytes
= stats
->bytes_in
;
688 interface
->if_data
.ifi_imcasts
= stats
->multicasts_in
;
689 interface
->if_data
.ifi_ierrors
= stats
->errors_in
;
691 interface
->if_data
.ifi_opackets
= stats
->packets_out
;
692 interface
->if_data
.ifi_obytes
= stats
->bytes_out
;
693 interface
->if_data
.ifi_omcasts
= stats
->multicasts_out
;
694 interface
->if_data
.ifi_oerrors
= stats
->errors_out
;
696 interface
->if_data
.ifi_collisions
= stats
->collisions
;
697 interface
->if_data
.ifi_iqdrops
= stats
->dropped
;
698 interface
->if_data
.ifi_noproto
= stats
->no_protocol
;
700 /* Touch the last change time. */
701 TOUCHLASTCHANGE(&interface
->if_lastchange
);
703 lck_spin_unlock(dlil_input_lock
);
711 struct ifnet_stats_param
*stats
)
713 if (interface
== NULL
) return EINVAL
;
715 lck_spin_lock(dlil_input_lock
);
717 stats
->packets_in
= interface
->if_data
.ifi_ipackets
;
718 stats
->bytes_in
= interface
->if_data
.ifi_ibytes
;
719 stats
->multicasts_in
= interface
->if_data
.ifi_imcasts
;
720 stats
->errors_in
= interface
->if_data
.ifi_ierrors
;
722 stats
->packets_out
= interface
->if_data
.ifi_opackets
;
723 stats
->bytes_out
= interface
->if_data
.ifi_obytes
;
724 stats
->multicasts_out
= interface
->if_data
.ifi_omcasts
;
725 stats
->errors_out
= interface
->if_data
.ifi_oerrors
;
727 stats
->collisions
= interface
->if_data
.ifi_collisions
;
728 stats
->dropped
= interface
->if_data
.ifi_iqdrops
;
729 stats
->no_protocol
= interface
->if_data
.ifi_noproto
;
731 lck_spin_unlock(dlil_input_lock
);
737 ifnet_touch_lastchange(
740 if (interface
== NULL
) return EINVAL
;
742 lck_spin_lock(dlil_input_lock
);
743 TOUCHLASTCHANGE(&interface
->if_lastchange
);
744 lck_spin_unlock(dlil_input_lock
);
752 struct timeval
*last_change
)
754 if (interface
== NULL
) return EINVAL
;
756 lck_spin_lock(dlil_input_lock
);
757 *last_change
= interface
->if_data
.ifi_lastchange
;
758 lck_spin_unlock(dlil_input_lock
);
760 #if IF_LASTCHANGEUPTIME
761 /* Crude conversion from uptime to calendar time */
762 last_change
->tv_sec
+= boottime_sec();
769 ifnet_get_address_list(
771 ifaddr_t
**addresses
)
773 if (interface
== NULL
|| addresses
== NULL
) return EINVAL
;
774 return ifnet_get_address_list_family(interface
, addresses
, 0);
778 ifnet_get_address_list_family(
780 ifaddr_t
**addresses
,
787 if (interface
== NULL
|| addresses
== NULL
) return EINVAL
;
790 ifnet_head_lock_shared();
791 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
793 if (interface
&& ifp
!= interface
) continue;
795 ifnet_lock_shared(ifp
);
796 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0) {
797 if (interface
== NULL
|| interface
== ifp
)
800 TAILQ_FOREACH(addr
, &ifp
->if_addrhead
, ifa_link
)
802 if (family
== 0 || addr
->ifa_addr
->sa_family
== family
)
807 else if (interface
!= NULL
) {
808 ifnet_lock_done(ifp
);
812 ifnet_lock_done(ifp
);
815 MALLOC(*addresses
, ifaddr_t
*, sizeof(ifaddr_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
816 if (*addresses
== NULL
) {
821 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
823 if (interface
&& ifp
!= interface
) continue;
825 ifnet_lock_shared(ifp
);
826 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0) {
827 if (interface
== NULL
|| (struct ifnet
*)interface
== ifp
)
830 TAILQ_FOREACH(addr
, &ifp
->if_addrhead
, ifa_link
)
832 if (count
+ 1 > cmax
) break;
833 if (family
== 0 || addr
->ifa_addr
->sa_family
== family
) {
834 (*addresses
)[count
] = (ifaddr_t
)addr
;
835 ifaddr_reference((*addresses
)[count
]);
841 ifnet_lock_done(ifp
);
842 if (interface
|| count
== cmax
)
846 (*addresses
)[cmax
] = 0;
852 ifnet_free_address_list(
857 if (addresses
== NULL
) return;
859 for (i
= 0; addresses
[i
] != NULL
; i
++)
861 ifaddr_release(addresses
[i
]);
864 FREE(addresses
, M_TEMP
);
871 if (interface
== NULL
) return NULL
;
872 return LLADDR(SDL(interface
->if_addrhead
.tqh_first
->ifa_addr
));
876 ifnet_llbroadcast_copy_bytes(
882 if (interface
== NULL
|| addr
== NULL
|| out_len
== NULL
) return EINVAL
;
884 *out_len
= interface
->if_broadcast
.length
;
886 if (buffer_len
< interface
->if_broadcast
.length
) {
890 if (interface
->if_broadcast
.length
== 0)
893 if (interface
->if_broadcast
.length
<= sizeof(interface
->if_broadcast
.u
.buffer
)) {
894 bcopy(interface
->if_broadcast
.u
.buffer
, addr
, interface
->if_broadcast
.length
);
897 bcopy(interface
->if_broadcast
.u
.ptr
, addr
, interface
->if_broadcast
.length
);
904 ifnet_lladdr_copy_bytes(
909 struct sockaddr_dl
*sdl
;
910 if (interface
== NULL
|| lladdr
== NULL
) return EINVAL
;
912 sdl
= SDL(interface
->if_addrhead
.tqh_first
->ifa_addr
);
915 if (lladdr_len
!= sdl
->sdl_alen
) {
916 bzero(lladdr
, lladdr_len
);
919 bcopy(LLADDR(sdl
), lladdr
, lladdr_len
);
920 if (bcmp(lladdr
, LLADDR(sdl
), lladdr_len
) == 0 &&
921 lladdr_len
== sdl
->sdl_alen
)
928 ifnet_set_lladdr_internal(
936 struct sockaddr_dl
*sdl
;
939 if (interface
== NULL
) return EINVAL
;
941 if (lladdr_len
!= 0 && (lladdr_len
!= interface
->if_addrlen
|| lladdr
== 0))
944 ifnet_head_lock_shared();
945 ifa
= ifnet_addrs
[interface
->if_index
- 1];
947 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
948 if (lladdr_len
!= 0) {
949 bcopy(lladdr
, LLADDR(sdl
), lladdr_len
);
952 bzero(LLADDR(sdl
), interface
->if_addrlen
);
954 sdl
->sdl_alen
= lladdr_len
;
957 sdl
->sdl_type
= new_type
;
965 /* Generate a kernel event */
967 dlil_post_msg(interface
, KEV_DL_SUBCLASS
,
968 KEV_DL_LINK_ADDRESS_CHANGED
, NULL
, 0);
980 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, 0, 0);
984 ifnet_set_lladdr_and_type(
990 return ifnet_set_lladdr_internal(interface
, lladdr
, lladdr_len
, type
, 1);
996 const struct sockaddr
*maddr
,
997 ifmultiaddr_t
*address
)
999 if (interface
== NULL
|| maddr
== NULL
) return EINVAL
;
1000 return if_addmulti(interface
, maddr
, address
);
1004 ifnet_remove_multicast(
1005 ifmultiaddr_t address
)
1007 if (address
== NULL
) return EINVAL
;
1008 return if_delmultiaddr(address
, 0);
1011 errno_t
ifnet_get_multicast_list(ifnet_t interface
, ifmultiaddr_t
**addresses
)
1015 struct ifmultiaddr
*addr
;
1018 if (interface
== NULL
|| addresses
== NULL
)
1021 lock
= (interface
->if_lock
!= 0);
1022 if (lock
) ifnet_lock_shared(interface
);
1023 if ((interface
->if_eflags
& IFEF_DETACHING
) == 0) {
1024 LIST_FOREACH(addr
, &interface
->if_multiaddrs
, ifma_link
)
1030 if (lock
) ifnet_lock_done(interface
);
1034 MALLOC(*addresses
, ifmultiaddr_t
*, sizeof(ifmultiaddr_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
1035 if (*addresses
== NULL
) {
1036 if (lock
) ifnet_lock_done(interface
);
1040 LIST_FOREACH(addr
, &interface
->if_multiaddrs
, ifma_link
)
1042 if (count
+ 1 > cmax
)
1044 (*addresses
)[count
] = (ifmultiaddr_t
)addr
;
1045 ifmaddr_reference((*addresses
)[count
]);
1048 (*addresses
)[cmax
] = 0;
1049 if (lock
) ifnet_lock_done(interface
);
1055 ifnet_free_multicast_list(
1056 ifmultiaddr_t
*addresses
)
1060 if (addresses
== NULL
) return;
1062 for (i
= 0; addresses
[i
] != NULL
; i
++)
1064 ifmaddr_release(addresses
[i
]);
1067 FREE(addresses
, M_TEMP
);
1078 if (ifname
== NULL
) return EINVAL
;
1080 namelen
= strlen(ifname
);
1084 ifnet_head_lock_shared();
1085 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
1087 struct ifaddr
*ifa
= ifnet_addrs
[ifp
->if_index
- 1];
1088 struct sockaddr_dl
*ll_addr
;
1090 if (!ifa
|| !ifa
->ifa_addr
)
1093 ll_addr
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1095 if ((ifp
->if_eflags
& IFEF_DETACHING
) == 0 &&
1096 namelen
== ll_addr
->sdl_nlen
&&
1097 (strncmp(ll_addr
->sdl_data
, ifname
, ll_addr
->sdl_nlen
) == 0))
1104 ifnet_reference(*interface
);
1108 return (ifp
== NULL
) ? ENXIO
: 0;
1113 ifnet_family_t family
,
1122 if (list
== NULL
|| count
== NULL
) return EINVAL
;
1124 ifnet_head_lock_shared();
1125 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
1127 if (ifp
->if_eflags
& IFEF_DETACHING
) continue;
1128 if (family
== 0 || ifp
->if_family
== family
)
1136 MALLOC(*list
, ifnet_t
*, sizeof(ifnet_t
) * (cmax
+ 1), M_TEMP
, M_NOWAIT
);
1142 TAILQ_FOREACH(ifp
, &ifnet
, if_link
)
1144 if (ifp
->if_eflags
& IFEF_DETACHING
) continue;
1145 if (*count
+ 1 > cmax
) break;
1146 if (family
== 0 || ((ifnet_family_t
)ifp
->if_family
) == family
)
1148 (*list
)[*count
] = (ifnet_t
)ifp
;
1149 ifnet_reference((*list
)[*count
]);
1153 (*list
)[*count
] = NULL
;
1162 ifnet_t
*interfaces
)
1166 if (interfaces
== NULL
) return;
1168 for (i
= 0; interfaces
[i
]; i
++)
1170 ifnet_release(interfaces
[i
]);
1173 FREE(interfaces
, M_TEMP
);
1176 /****************************************************************************/
1177 /* ifaddr_t accessors */
1178 /****************************************************************************/
1184 if (ifa
== NULL
) return EINVAL
;
1193 if (ifa
== NULL
) return EINVAL
;
1199 ifaddr_address_family(
1202 if (ifa
&& ifa
->ifa_addr
)
1203 return ifa
->ifa_addr
->sa_family
;
1211 struct sockaddr
*out_addr
,
1212 u_int32_t addr_size
)
1216 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1217 if (ifa
->ifa_addr
== NULL
) return ENOTSUP
;
1219 copylen
= (addr_size
>= ifa
->ifa_addr
->sa_len
) ? ifa
->ifa_addr
->sa_len
: addr_size
;
1220 bcopy(ifa
->ifa_addr
, out_addr
, copylen
);
1222 if (ifa
->ifa_addr
->sa_len
> addr_size
) return EMSGSIZE
;
1230 struct sockaddr
*out_addr
,
1231 u_int32_t addr_size
)
1234 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1235 if (ifa
->ifa_dstaddr
== NULL
) return ENOTSUP
;
1237 copylen
= (addr_size
>= ifa
->ifa_dstaddr
->sa_len
) ? ifa
->ifa_dstaddr
->sa_len
: addr_size
;
1238 bcopy(ifa
->ifa_dstaddr
, out_addr
, copylen
);
1240 if (ifa
->ifa_dstaddr
->sa_len
> addr_size
) return EMSGSIZE
;
1248 struct sockaddr
*out_addr
,
1249 u_int32_t addr_size
)
1252 if (ifa
== NULL
|| out_addr
== NULL
) return EINVAL
;
1253 if (ifa
->ifa_netmask
== NULL
) return ENOTSUP
;
1255 copylen
= addr_size
>= ifa
->ifa_netmask
->sa_len
? ifa
->ifa_netmask
->sa_len
: addr_size
;
1256 bcopy(ifa
->ifa_netmask
, out_addr
, copylen
);
1258 if (ifa
->ifa_netmask
->sa_len
> addr_size
) return EMSGSIZE
;
1268 if (ifa
== NULL
) return NULL
;
1271 return (ifnet_t
)ifp
;
1276 const struct sockaddr
* address
)
1278 if (address
== NULL
) return NULL
;
1279 return ifa_ifwithaddr(address
);
1284 const struct sockaddr
* address
)
1286 if (address
== NULL
) return NULL
;
1287 return ifa_ifwithdstaddr(address
);
1292 const struct sockaddr
* net
)
1294 if (net
== NULL
) return NULL
;
1295 return ifa_ifwithnet(net
);
1301 const struct sockaddr
* destination
,
1302 const struct sockaddr
* gateway
)
1304 if (destination
== NULL
|| gateway
== NULL
) return NULL
;
1305 return ifa_ifwithroute(flags
, destination
, gateway
);
1309 ifaddr_findbestforaddr(
1310 const struct sockaddr
*addr
,
1313 if (addr
== NULL
|| interface
== NULL
) return NULL
;
1314 return ifaof_ifpforaddr(addr
, interface
);
1319 ifmultiaddr_t ifmaddr
)
1321 if (ifmaddr
== NULL
) return EINVAL
;
1322 ifma_reference(ifmaddr
);
1328 ifmultiaddr_t ifmaddr
)
1330 if (ifmaddr
== NULL
) return EINVAL
;
1331 ifma_release(ifmaddr
);
1337 ifmultiaddr_t ifmaddr
,
1338 struct sockaddr
*out_addr
,
1339 u_int32_t addr_size
)
1343 if (ifmaddr
== NULL
|| out_addr
== NULL
) return EINVAL
;
1344 if (ifmaddr
->ifma_addr
== NULL
) return ENOTSUP
;
1346 copylen
= addr_size
>= ifmaddr
->ifma_addr
->sa_len
? ifmaddr
->ifma_addr
->sa_len
: addr_size
;
1347 bcopy(ifmaddr
->ifma_addr
, out_addr
, copylen
);
1349 if (ifmaddr
->ifma_addr
->sa_len
> addr_size
) return EMSGSIZE
;
1356 ifmultiaddr_t ifmaddr
,
1357 struct sockaddr
*out_addr
,
1358 u_int32_t addr_size
)
1360 if (ifmaddr
== NULL
|| out_addr
== NULL
) return EINVAL
;
1361 if (ifmaddr
->ifma_ll
== NULL
) return ENOTSUP
;
1363 return ifmaddr_address(ifmaddr
->ifma_ll
, out_addr
, addr_size
);
1368 ifmultiaddr_t ifmaddr
)
1370 if (ifmaddr
== NULL
|| ifmaddr
->ifma_ifp
== NULL
) return NULL
;
1371 return ifmaddr
->ifma_ifp
;