|
|
|
@ -1,21 +1,24 @@ |
|
|
|
|
use super::Interface; |
|
|
|
|
use super::MacAddr; |
|
|
|
|
use crate::sys; |
|
|
|
|
use crate::gateway; |
|
|
|
|
use crate::ip::{Ipv4Net, Ipv6Net}; |
|
|
|
|
use crate::sys; |
|
|
|
|
|
|
|
|
|
use crate::interface::InterfaceType; |
|
|
|
|
use libc; |
|
|
|
|
use std::ffi::{CStr, CString}; |
|
|
|
|
use std::mem::{self, MaybeUninit}; |
|
|
|
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
|
|
|
|
use std::os::raw::c_char; |
|
|
|
|
use std::str::from_utf8_unchecked; |
|
|
|
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
|
|
|
|
use crate::interface::InterfaceType; |
|
|
|
|
|
|
|
|
|
#[cfg(target_os = "android")] |
|
|
|
|
use super::android::{freeifaddrs, getifaddrs}; |
|
|
|
|
|
|
|
|
|
#[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(){ |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr() { |
|
|
|
|
Some(local_ip) => local_ip, |
|
|
|
|
None => return interfaces, |
|
|
|
|
}; |
|
|
|
@ -26,21 +29,21 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
match gateway::unix::get_default_gateway(iface.name.clone()) { |
|
|
|
|
Ok(gateway) => { |
|
|
|
|
iface.gateway = Some(gateway); |
|
|
|
|
}, |
|
|
|
|
Err(_) => {}, |
|
|
|
|
} |
|
|
|
|
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(_) => {}, |
|
|
|
|
} |
|
|
|
|
Err(_) => {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
interfaces |
|
|
|
@ -52,7 +55,7 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
|
|
|
|
|
let type_map = macos::get_if_type_map(); |
|
|
|
|
let mut interfaces: Vec<Interface> = unix_interfaces(); |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr(){ |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr() { |
|
|
|
|
Some(local_ip) => local_ip, |
|
|
|
|
None => return interfaces, |
|
|
|
|
}; |
|
|
|
@ -64,21 +67,21 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
match gateway::unix::get_default_gateway(iface.name.clone()) { |
|
|
|
|
Ok(gateway) => { |
|
|
|
|
iface.gateway = Some(gateway); |
|
|
|
|
}, |
|
|
|
|
Err(_) => {}, |
|
|
|
|
} |
|
|
|
|
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(_) => {}, |
|
|
|
|
} |
|
|
|
|
Err(_) => {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
interfaces |
|
|
|
@ -89,7 +92,7 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
use super::linux; |
|
|
|
|
|
|
|
|
|
let mut interfaces: Vec<Interface> = unix_interfaces(); |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr(){ |
|
|
|
|
let local_ip: IpAddr = match super::get_local_ipaddr() { |
|
|
|
|
Some(local_ip) => local_ip, |
|
|
|
|
None => return interfaces, |
|
|
|
|
}; |
|
|
|
@ -104,21 +107,21 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
match gateway::linux::get_default_gateway(iface.name.clone()) { |
|
|
|
|
Ok(gateway) => { |
|
|
|
|
iface.gateway = Some(gateway); |
|
|
|
|
}, |
|
|
|
|
Err(_) => {}, |
|
|
|
|
} |
|
|
|
|
Err(_) => {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
IpAddr::V6(local_ipv6) => { |
|
|
|
|
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) { |
|
|
|
|
match gateway::linux::get_default_gateway(iface.name.clone()) { |
|
|
|
|
Ok(gateway) => { |
|
|
|
|
iface.gateway = Some(gateway); |
|
|
|
|
}, |
|
|
|
|
Err(_) => {}, |
|
|
|
|
} |
|
|
|
|
Err(_) => {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
interfaces |
|
|
|
@ -144,10 +147,8 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti |
|
|
|
|
|
|
|
|
|
(Some(mac), None) |
|
|
|
|
} else { |
|
|
|
|
let addr = sys::sockaddr_to_addr( |
|
|
|
|
mem::transmute(sa), |
|
|
|
|
mem::size_of::<libc::sockaddr_storage>(), |
|
|
|
|
); |
|
|
|
|
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()))), |
|
|
|
@ -158,7 +159,13 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "macos", target_os = "ios"))] |
|
|
|
|
#[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; |
|
|
|
@ -180,10 +187,8 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti |
|
|
|
|
|
|
|
|
|
(Some(mac), None) |
|
|
|
|
} else { |
|
|
|
|
let addr = sys::sockaddr_to_addr( |
|
|
|
|
mem::transmute(sa), |
|
|
|
|
mem::size_of::<libc::sockaddr_storage>(), |
|
|
|
|
); |
|
|
|
|
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()))), |
|
|
|
@ -197,16 +202,16 @@ fn sockaddr_to_network_addr(sa: *const libc::sockaddr) -> (Option<MacAddr>, Opti |
|
|
|
|
pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
let mut ifaces: Vec<Interface> = vec![]; |
|
|
|
|
let mut addrs: MaybeUninit<*mut libc::ifaddrs> = MaybeUninit::uninit(); |
|
|
|
|
if unsafe { libc::getifaddrs(addrs.as_mut_ptr()) } != 0 { |
|
|
|
|
if unsafe { getifaddrs(addrs.as_mut_ptr()) } != 0 { |
|
|
|
|
return ifaces; |
|
|
|
|
} |
|
|
|
|
let addrs = unsafe { addrs.assume_init() }; |
|
|
|
|
let mut addr = addrs; |
|
|
|
|
while !addr.is_null() { |
|
|
|
|
let addr_ref: &libc::ifaddrs = unsafe {&*addr}; |
|
|
|
|
let addr_ref: &libc::ifaddrs = unsafe { &*addr }; |
|
|
|
|
let c_str = addr_ref.ifa_name as *const c_char; |
|
|
|
|
let bytes = unsafe { CStr::from_ptr(c_str).to_bytes() }; |
|
|
|
|
let name = unsafe {from_utf8_unchecked(bytes).to_owned() }; |
|
|
|
|
let name = unsafe { from_utf8_unchecked(bytes).to_owned() }; |
|
|
|
|
let (mac, ip) = sockaddr_to_network_addr(addr_ref.ifa_addr as *const libc::sockaddr); |
|
|
|
|
let (_, netmask) = sockaddr_to_network_addr(addr_ref.ifa_netmask as *const libc::sockaddr); |
|
|
|
|
let mut ini_ipv4: Vec<Ipv4Net> = vec![]; |
|
|
|
@ -215,33 +220,29 @@ pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
match ip { |
|
|
|
|
IpAddr::V4(ipv4) => { |
|
|
|
|
let netmask: Ipv4Addr = match netmask { |
|
|
|
|
Some(netmask) => { |
|
|
|
|
match netmask { |
|
|
|
|
IpAddr::V4(netmask) => netmask, |
|
|
|
|
IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED, |
|
|
|
|
} |
|
|
|
|
Some(netmask) => match netmask { |
|
|
|
|
IpAddr::V4(netmask) => netmask, |
|
|
|
|
IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED, |
|
|
|
|
}, |
|
|
|
|
None => Ipv4Addr::UNSPECIFIED, |
|
|
|
|
}; |
|
|
|
|
let ipv4_net: Ipv4Net = Ipv4Net::new_with_netmask(ipv4, netmask); |
|
|
|
|
ini_ipv4.push(ipv4_net); |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
IpAddr::V6(ipv6) => { |
|
|
|
|
let netmask: Ipv6Addr = match netmask { |
|
|
|
|
Some(netmask) => { |
|
|
|
|
match netmask { |
|
|
|
|
IpAddr::V4(_) => Ipv6Addr::UNSPECIFIED, |
|
|
|
|
IpAddr::V6(netmask) => netmask, |
|
|
|
|
} |
|
|
|
|
Some(netmask) => match netmask { |
|
|
|
|
IpAddr::V4(_) => Ipv6Addr::UNSPECIFIED, |
|
|
|
|
IpAddr::V6(netmask) => netmask, |
|
|
|
|
}, |
|
|
|
|
None => Ipv6Addr::UNSPECIFIED, |
|
|
|
|
}; |
|
|
|
|
let ipv6_net: Ipv6Net = Ipv6Net::new_with_netmask(ipv6, netmask); |
|
|
|
|
ini_ipv6.push(ipv6_net); |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
let interface: Interface = Interface{ |
|
|
|
|
let interface: Interface = Interface { |
|
|
|
|
index: 0, |
|
|
|
|
name: name.clone(), |
|
|
|
|
friendly_name: None, |
|
|
|
@ -265,30 +266,26 @@ pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
match ip { |
|
|
|
|
IpAddr::V4(ipv4) => { |
|
|
|
|
let netmask: Ipv4Addr = match netmask { |
|
|
|
|
Some(netmask) => { |
|
|
|
|
match netmask { |
|
|
|
|
IpAddr::V4(netmask) => netmask, |
|
|
|
|
IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED, |
|
|
|
|
} |
|
|
|
|
Some(netmask) => match netmask { |
|
|
|
|
IpAddr::V4(netmask) => netmask, |
|
|
|
|
IpAddr::V6(_) => Ipv4Addr::UNSPECIFIED, |
|
|
|
|
}, |
|
|
|
|
None => Ipv4Addr::UNSPECIFIED, |
|
|
|
|
}; |
|
|
|
|
let ipv4_net: Ipv4Net = Ipv4Net::new_with_netmask(ipv4, netmask); |
|
|
|
|
iface.ipv4.push(ipv4_net); |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
IpAddr::V6(ipv6) => { |
|
|
|
|
let netmask: Ipv6Addr = match netmask { |
|
|
|
|
Some(netmask) => { |
|
|
|
|
match netmask { |
|
|
|
|
IpAddr::V4(_) => Ipv6Addr::UNSPECIFIED, |
|
|
|
|
IpAddr::V6(netmask) => netmask, |
|
|
|
|
} |
|
|
|
|
Some(netmask) => match netmask { |
|
|
|
|
IpAddr::V4(_) => Ipv6Addr::UNSPECIFIED, |
|
|
|
|
IpAddr::V6(netmask) => netmask, |
|
|
|
|
}, |
|
|
|
|
None => Ipv6Addr::UNSPECIFIED, |
|
|
|
|
}; |
|
|
|
|
let ipv6_net: Ipv6Net = Ipv6Net::new_with_netmask(ipv6, netmask); |
|
|
|
|
iface.ipv6.push(ipv6_net); |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
found = true; |
|
|
|
@ -299,14 +296,29 @@ pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
} |
|
|
|
|
addr = addr_ref.ifa_next; |
|
|
|
|
} |
|
|
|
|
unsafe{ libc::freeifaddrs(addrs); }
|
|
|
|
|
unsafe { |
|
|
|
|
freeifaddrs(addrs); |
|
|
|
|
} |
|
|
|
|
for iface in &mut ifaces { |
|
|
|
|
let name = CString::new(iface.name.as_bytes()).unwrap(); |
|
|
|
|
unsafe { iface.index = libc::if_nametoindex(name.as_ptr()); } |
|
|
|
|
unsafe { |
|
|
|
|
iface.index = libc::if_nametoindex(name.as_ptr()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
ifaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(not(target_os = "android"))] |
|
|
|
|
unsafe fn getifaddrs(ifap: *mut *mut libc::ifaddrs) -> libc::c_int { |
|
|
|
|
// Not android, everything is easy
|
|
|
|
|
libc::getifaddrs(ifap) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(not(target_os = "android"))] |
|
|
|
|
unsafe fn freeifaddrs(ifa: *mut libc::ifaddrs) { |
|
|
|
|
libc::freeifaddrs(ifa); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
mod tests { |
|
|
|
|
use super::*; |
|
|
|
|