55use std:: ffi:: CStr ;
66use std:: io;
77use std:: mem:: MaybeUninit ;
8- use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr } ;
8+ use std:: net:: IpAddr ;
99
10+ use luomu_common:: sockaddr:: from_sockaddr;
1011use luomu_common:: { Address , MacAddr } ;
1112
12- #[ cfg( target_os = "macos" ) ]
13- use std:: slice;
14-
1513mod flags;
1614pub use flags:: Flags ;
1715
1816mod stats;
1917pub use stats:: IfStats ;
2018
21- /// Length of MAC address in bytes
22- const MAC_ADDR_LEN : usize = 6 ;
23-
2419/// Returns a linked list describing the network interfaces of
2520/// the local system.
2621pub fn getifaddrs ( ) -> io:: Result < IfAddrs > {
@@ -117,27 +112,6 @@ impl Iterator for IfAddrs {
117112 }
118113}
119114
120- /// Returns address family value from [libc::sockaddr]
121- const fn sa_get_family ( sa : * const libc:: sockaddr ) -> i32 {
122- unsafe { * sa } . sa_family as libc:: c_int
123- }
124-
125- /// Returns given [libc::sockaddr] pointer as a pointer to [libc::sockaddr_in]
126- const fn sa_as_sockaddr_in ( sa : * const libc:: sockaddr ) -> libc:: sockaddr_in {
127- unsafe { * ( sa. cast :: < libc:: sockaddr_in > ( ) ) }
128- }
129-
130- /// Returns given [libc::sockaddr] pointer as a pointer to [libc::sockaddr_in6]
131- const fn sa_as_sockaddr_in6 ( sa : * const libc:: sockaddr ) -> libc:: sockaddr_in6 {
132- unsafe { * ( sa. cast :: < libc:: sockaddr_in6 > ( ) ) }
133- }
134-
135- #[ cfg( target_os = "macos" ) ]
136- /// Returns given [libc::sockaddr] pointer as a pointer to [libc::sockaddr_dl]
137- const fn sa_as_sockaddr_dl ( sa : * const libc:: sockaddr ) -> libc:: sockaddr_dl {
138- unsafe { * ( sa. cast :: < libc:: sockaddr_dl > ( ) ) }
139- }
140-
141115/// This struct provides access to information about network interface.
142116pub struct IfAddr {
143117 /// pointer for the interface data
@@ -179,21 +153,21 @@ impl IfAddr {
179153
180154 /// Interface address
181155 pub fn addr ( & self ) -> Option < Address > {
182- IfAddr :: read_addr ( self . ifa ( ) . ifa_addr )
156+ from_sockaddr ( self . ifa ( ) . ifa_addr )
183157 }
184158
185159 /// Interface netmask
186160 pub fn netmask ( & self ) -> Option < IpAddr > {
187- IfAddr :: read_addr ( self . ifa ( ) . ifa_netmask ) . and_then ( |a| a. as_ip ( ) )
161+ from_sockaddr ( self . ifa ( ) . ifa_netmask ) . and_then ( |a| a. as_ip ( ) )
188162 }
189163
190164 /// Destination address for Point-to-Point link
191165 pub fn dstaddr ( & self ) -> Option < IpAddr > {
192166 cfg_if:: cfg_if! {
193167 if #[ cfg( target_os = "macos" ) ] {
194- IfAddr :: read_addr ( self . ifa( ) . ifa_dstaddr) . and_then( |a| a. as_ip( ) )
168+ from_sockaddr ( self . ifa( ) . ifa_dstaddr) . and_then( |a| a. as_ip( ) )
195169 } else if #[ cfg( target_os = "linux" ) ] {
196- IfAddr :: read_addr ( self . ifa( ) . ifa_ifu) . and_then( |a| a. as_ip( ) )
170+ from_sockaddr ( self . ifa( ) . ifa_ifu) . and_then( |a| a. as_ip( ) )
197171 }
198172 }
199173 }
@@ -204,7 +178,7 @@ impl IfAddr {
204178 return None ;
205179 }
206180
207- let family = sa_get_family ( self . ifa ( ) . ifa_addr ) ;
181+ let family = i32 :: from ( unsafe { * self . ifa ( ) . ifa_addr } . sa_family ) ;
208182
209183 #[ cfg( target_os = "linux" ) ]
210184 if family != libc:: AF_PACKET {
@@ -220,96 +194,6 @@ impl IfAddr {
220194 let link_stats = unsafe { & * ( ifa_data as * const stats:: LinkStats ) } ;
221195 Some ( * link_stats)
222196 }
223-
224- /// Reads address information from given socket address pointer.
225- ///
226- /// Address may contain IP address or Link address, the returned
227- /// [Addr] reflects which one was read. [None] is returned if no address
228- /// was available, or it could not be read.
229- fn read_addr ( ifa_addr : * const libc:: sockaddr ) -> Option < Address > {
230- if ifa_addr. is_null ( ) {
231- return None ;
232- }
233-
234- let family = sa_get_family ( ifa_addr) ;
235-
236- match family {
237- #[ cfg( target_os = "macos" ) ]
238- libc:: AF_INET if unsafe { * ifa_addr } . sa_len < 16 => {
239- let len = unsafe { * ifa_addr } . sa_len ;
240- debug_assert ! ( len >= 5 && len <= 8 , "invalid sa_len {len} for AF_INET" ) ;
241- let sa_data = unsafe { * ifa_addr } . sa_data ;
242- let mut ret = 0 ;
243- if len >= 5 {
244- ret += u32:: from ( sa_data[ 2 ] as u8 ) << 24 ;
245- }
246- if len >= 6 {
247- ret += u32:: from ( sa_data[ 3 ] as u8 ) << 16 ;
248- }
249- if len >= 7 {
250- ret += u32:: from ( sa_data[ 4 ] as u8 ) << 8 ;
251- }
252- if len == 8 {
253- ret += u32:: from ( sa_data[ 5 ] as u8 ) ;
254- }
255- Some ( Address :: from ( Ipv4Addr :: from_bits ( ret) ) )
256- }
257- libc:: AF_INET => {
258- #[ cfg( target_os = "macos" ) ]
259- debug_assert_eq ! ( unsafe { * ifa_addr } . sa_len, 16 , "invalid sa_len for AF_INET" ) ;
260- let a: libc:: sockaddr_in = sa_as_sockaddr_in ( ifa_addr) ;
261- Some ( Address :: from ( Ipv4Addr :: from ( u32:: from_be ( a. sin_addr . s_addr ) ) ) )
262- }
263- libc:: AF_INET6 => {
264- #[ cfg( target_os = "macos" ) ]
265- debug_assert_eq ! ( unsafe { * ifa_addr } . sa_len, 28 , "invalid sa_len for AF_INET6" ) ;
266- let a: libc:: sockaddr_in6 = sa_as_sockaddr_in6 ( ifa_addr) ;
267- Some ( Address :: from ( Ipv6Addr :: from ( a. sin6_addr . s6_addr ) ) )
268- }
269- #[ cfg( target_os = "macos" ) ]
270- libc:: AF_LINK => {
271- // MAC address for this interface
272- let a: libc:: sockaddr_dl = sa_as_sockaddr_dl ( ifa_addr) ;
273- // length of the address
274- let a_len = usize:: from ( a. sdl_alen ) ;
275- // length of the name
276- let n_len = usize:: from ( a. sdl_nlen ) ;
277- // If seems that name is stored to sdl_data before the mac
278- // address of the interface. However, libc::sockaddr_dl::sdl_data has been
279- // defined to contain 12 bytes. Thus, if name of the interface
280- // is longer than 6 bytes (characters), we can not read the MAC
281- // address of that interface.
282- if a_len != MAC_ADDR_LEN || n_len + a_len > a. sdl_data . len ( ) {
283- return None ;
284- }
285- // also, sdl_data has been defined as i8 for whatever reason,
286- // we need bytes for mac address, thus a bit of unsafery
287- let data = & a. sdl_data ;
288- let sdl_data_as_u8: & [ u8 ] =
289- unsafe { slice:: from_raw_parts ( data. as_ptr ( ) . cast :: < u8 > ( ) , data. len ( ) ) } ;
290- let mut address = [ 0u8 ; MAC_ADDR_LEN ] ;
291- // mac address stored after name
292- // You may want to look into LLADDR() macro somewhere on Mac OS headers
293- let offset = usize:: from ( a. sdl_nlen ) ;
294- address[ ..MAC_ADDR_LEN ] . copy_from_slice ( & sdl_data_as_u8[ offset..offset + MAC_ADDR_LEN ] ) ;
295- Some ( Address :: from ( address) )
296- }
297- #[ cfg( target_os = "linux" ) ]
298- libc:: AF_PACKET => {
299- // Mac address of the interface
300- let a: libc:: sockaddr_ll = unsafe { * ( ifa_addr. cast :: < libc:: sockaddr_ll > ( ) ) } ;
301- let a_len = usize:: from ( a. sll_halen ) ;
302- debug_assert ! ( a_len == MAC_ADDR_LEN ) ;
303- if a_len != MAC_ADDR_LEN {
304- return None ;
305- }
306- let mut address = [ 0u8 ; MAC_ADDR_LEN ] ;
307- address[ ..MAC_ADDR_LEN ] . copy_from_slice ( & a. sll_addr [ ..MAC_ADDR_LEN ] ) ;
308- Some ( Address :: from ( address) )
309- }
310- _ => None ,
311- }
312- }
313197}
314198
315199/// A view into interface data
0 commit comments