|
|
|
@ -10,8 +10,9 @@ use std::mem::{self, MaybeUninit}; |
|
|
|
|
use std::os::raw::c_char; |
|
|
|
|
use std::str::from_utf8_unchecked; |
|
|
|
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
|
|
|
|
use crate::interface::InterfaceType; |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))] |
|
|
|
|
#[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd"))] |
|
|
|
|
pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
let mut interfaces: Vec<Interface> = unix_interfaces(); |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr(){ |
|
|
|
@ -45,14 +46,55 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
interfaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "macos", target_os = "ios"))] |
|
|
|
|
pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
use super::macos; |
|
|
|
|
|
|
|
|
|
let type_map = macos::get_if_type_map(); |
|
|
|
|
let mut interfaces: Vec<Interface> = unix_interfaces(); |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr(){ |
|
|
|
|
Some(local_ip) => local_ip, |
|
|
|
|
None => return interfaces, |
|
|
|
|
}; |
|
|
|
|
for iface in &mut interfaces { |
|
|
|
|
iface.if_type = *type_map.get(&iface.name).unwrap_or(&InterfaceType::Unknown); |
|
|
|
|
match local_ip { |
|
|
|
|
IpAddr::V4(local_ipv4) => { |
|
|
|
|
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) { |
|
|
|
|
match gateway::unix::get_default_gateway(iface.name.clone()) { |
|
|
|
|
Ok(gateway) => { |
|
|
|
|
iface.gateway = Some(gateway); |
|
|
|
|
}, |
|
|
|
|
Err(_) => {}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
IpAddr::V6(local_ipv6) => { |
|
|
|
|
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) { |
|
|
|
|
match gateway::unix::get_default_gateway(iface.name.clone()) { |
|
|
|
|
Ok(gateway) => { |
|
|
|
|
iface.gateway = Some(gateway); |
|
|
|
|
}, |
|
|
|
|
Err(_) => {}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
interfaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))] |
|
|
|
|
pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
use super::linux; |
|
|
|
|
|
|
|
|
|
let mut interfaces: Vec<Interface> = unix_interfaces(); |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr(){ |
|
|
|
|
Some(local_ip) => local_ip, |
|
|
|
|
None => return interfaces, |
|
|
|
|
}; |
|
|
|
|
for iface in &mut interfaces { |
|
|
|
|
iface.if_type = linux::get_interface_type(iface.name.clone()); |
|
|
|
|
match local_ip { |
|
|
|
|
IpAddr::V4(local_ipv4) => { |
|
|
|
|
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) { |
|
|
|
@ -79,6 +121,76 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
interfaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))] |
|
|
|
|
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) { |
|
|
|
|
use std::net::SocketAddr; |
|
|
|
|
|
|
|
|
|
unsafe { |
|
|
|
|
if sa.is_null() { |
|
|
|
|
(None, None) |
|
|
|
|
} else if (*sa).sa_family as libc::c_int == libc::AF_PACKET { |
|
|
|
|
let sll: *const libc::sockaddr_ll = mem::transmute(sa); |
|
|
|
|
let mac = MacAddr( |
|
|
|
|
(*sll).sll_addr[0], |
|
|
|
|
(*sll).sll_addr[1], |
|
|
|
|
(*sll).sll_addr[2], |
|
|
|
|
(*sll).sll_addr[3], |
|
|
|
|
(*sll).sll_addr[4], |
|
|
|
|
(*sll).sll_addr[5], |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
(Some(mac), None) |
|
|
|
|
} else { |
|
|
|
|
let addr = sys::sockaddr_to_addr( |
|
|
|
|
mem::transmute(sa), |
|
|
|
|
mem::size_of::<libc::sockaddr_storage>(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
match addr { |
|
|
|
|
Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))), |
|
|
|
|
Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))), |
|
|
|
|
Err(_) => (None, None), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "macos", target_os = "ios"))] |
|
|
|
|
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) { |
|
|
|
|
use crate::bpf; |
|
|
|
|
use std::net::SocketAddr; |
|
|
|
|
|
|
|
|
|
unsafe { |
|
|
|
|
if sa.is_null() { |
|
|
|
|
(None, None) |
|
|
|
|
} else if (*sa).sa_family as libc::c_int == bpf::AF_LINK { |
|
|
|
|
let sdl: *const bpf::sockaddr_dl = mem::transmute(sa); |
|
|
|
|
let nlen = (*sdl).sdl_nlen as usize; |
|
|
|
|
let mac = MacAddr( |
|
|
|
|
(*sdl).sdl_data[nlen] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 1] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 2] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 3] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 4] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 5] as u8, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
(Some(mac), None) |
|
|
|
|
} else { |
|
|
|
|
let addr = sys::sockaddr_to_addr( |
|
|
|
|
mem::transmute(sa), |
|
|
|
|
mem::size_of::<libc::sockaddr_storage>(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
match addr { |
|
|
|
|
Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))), |
|
|
|
|
Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))), |
|
|
|
|
Err(_) => (None, None), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
let mut ifaces: Vec<Interface> = vec![]; |
|
|
|
|
let mut addrs: MaybeUninit<*mut libc::ifaddrs> = MaybeUninit::uninit(); |
|
|
|
@ -130,9 +242,11 @@ pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
index: 0, |
|
|
|
|
name: name.clone(), |
|
|
|
|
description: None, |
|
|
|
|
if_type: InterfaceType::Unknown, |
|
|
|
|
mac_addr: mac.clone(), |
|
|
|
|
ipv4: ini_ipv4, |
|
|
|
|
ipv6: ini_ipv6, |
|
|
|
|
flags: addr_ref.ifa_flags, |
|
|
|
|
gateway: None, |
|
|
|
|
}; |
|
|
|
|
let mut found: bool = false; |
|
|
|
@ -187,76 +301,6 @@ pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
ifaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))] |
|
|
|
|
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) { |
|
|
|
|
use std::net::SocketAddr; |
|
|
|
|
|
|
|
|
|
unsafe { |
|
|
|
|
if sa.is_null() { |
|
|
|
|
(None, None) |
|
|
|
|
} else if (*sa).sa_family as libc::c_int == libc::AF_PACKET { |
|
|
|
|
let sll: *const libc::sockaddr_ll = mem::transmute(sa); |
|
|
|
|
let mac = MacAddr( |
|
|
|
|
(*sll).sll_addr[0], |
|
|
|
|
(*sll).sll_addr[1], |
|
|
|
|
(*sll).sll_addr[2], |
|
|
|
|
(*sll).sll_addr[3], |
|
|
|
|
(*sll).sll_addr[4], |
|
|
|
|
(*sll).sll_addr[5], |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
(Some(mac), None) |
|
|
|
|
} else { |
|
|
|
|
let addr = sys::sockaddr_to_addr( |
|
|
|
|
mem::transmute(sa), |
|
|
|
|
mem::size_of::<libc::sockaddr_storage>(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
match addr { |
|
|
|
|
Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))), |
|
|
|
|
Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))), |
|
|
|
|
Err(_) => (None, None), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "macos", target_os = "ios"))] |
|
|
|
|
fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Option<IpAddr>) { |
|
|
|
|
use crate::bpf; |
|
|
|
|
use std::net::SocketAddr; |
|
|
|
|
|
|
|
|
|
unsafe { |
|
|
|
|
if sa.is_null() { |
|
|
|
|
(None, None) |
|
|
|
|
} else if (*sa).sa_family as libc::c_int == bpf::AF_LINK { |
|
|
|
|
let sdl: *const bpf::sockaddr_dl = mem::transmute(sa); |
|
|
|
|
let nlen = (*sdl).sdl_nlen as usize; |
|
|
|
|
let mac = MacAddr( |
|
|
|
|
(*sdl).sdl_data[nlen] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 1] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 2] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 3] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 4] as u8, |
|
|
|
|
(*sdl).sdl_data[nlen + 5] as u8, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
(Some(mac), None) |
|
|
|
|
} else { |
|
|
|
|
let addr = sys::sockaddr_to_addr( |
|
|
|
|
mem::transmute(sa), |
|
|
|
|
mem::size_of::<libc::sockaddr_storage>(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
match addr { |
|
|
|
|
Ok(SocketAddr::V4(sa)) => (None, Some(IpAddr::V4(*sa.ip()))), |
|
|
|
|
Ok(SocketAddr::V6(sa)) => (None, Some(IpAddr::V6(*sa.ip()))), |
|
|
|
|
Err(_) => (None, None), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
mod tests { |
|
|
|
|
use super::*; |
|
|
|
|