|
|
|
@ -12,19 +12,52 @@ use std::str::from_utf8_unchecked; |
|
|
|
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
|
|
|
|
use crate::interface::InterfaceType; |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))] |
|
|
|
|
use std::convert::TryFrom; |
|
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))] |
|
|
|
|
use std::fs::read_to_string; |
|
|
|
|
#[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(){ |
|
|
|
|
Some(local_ip) => local_ip, |
|
|
|
|
None => return interfaces, |
|
|
|
|
}; |
|
|
|
|
for iface in &mut interfaces { |
|
|
|
|
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 = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))] |
|
|
|
|
#[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) { |
|
|
|
@ -53,12 +86,15 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
|
|
|
|
|
#[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) { |
|
|
|
@ -85,26 +121,72 @@ pub fn interfaces() -> Vec<Interface> { |
|
|
|
|
interfaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios"))] |
|
|
|
|
pub fn get_interface_type(_if_name: String) -> InterfaceType { |
|
|
|
|
// TODO
|
|
|
|
|
InterfaceType::Unknown |
|
|
|
|
#[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 = "linux", target_os = "android"))] |
|
|
|
|
pub fn get_interface_type(if_name: String) -> InterfaceType { |
|
|
|
|
let if_type_path: String = format!("/sys/class/net/{}/type", if_name); |
|
|
|
|
let r = read_to_string(if_type_path); |
|
|
|
|
let if_type_string = match r { |
|
|
|
|
Ok(content) => content.trim().to_string(), |
|
|
|
|
Err(_) => String::from("999"), |
|
|
|
|
}; |
|
|
|
|
match if_type_string.parse::<u32>() { |
|
|
|
|
Ok(if_type) => { |
|
|
|
|
InterfaceType::try_from(if_type).unwrap_or(InterfaceType::Unknown) |
|
|
|
|
}, |
|
|
|
|
Err(_) => { |
|
|
|
|
InterfaceType::Unknown |
|
|
|
|
#[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), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -160,7 +242,7 @@ pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
index: 0, |
|
|
|
|
name: name.clone(), |
|
|
|
|
description: None, |
|
|
|
|
if_type: get_interface_type(name.clone()), |
|
|
|
|
if_type: InterfaceType::Unknown, |
|
|
|
|
mac_addr: mac.clone(), |
|
|
|
|
ipv4: ini_ipv4, |
|
|
|
|
ipv6: ini_ipv6, |
|
|
|
@ -219,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::*; |
|
|
|
|