feat: try to dynamically load libc.so on Android

main
dignifiedquire 2 years ago
parent 8f22d88792
commit a8bed97314
  1. 4
      Cargo.toml
  2. 64
      src/interface/android.rs
  3. 14
      src/interface/linux.rs
  4. 70
      src/interface/mod.rs
  5. 138
      src/interface/unix.rs

@ -13,6 +13,10 @@ license = "MIT"
[dependencies] [dependencies]
libc = "0.2" libc = "0.2"
[target.'cfg(target_os = "android")'.dependencies]
dlopen = "0.1.8"
once_cell = "1.17.1"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
memalloc = "0.1.0" memalloc = "0.1.0"

@ -0,0 +1,64 @@
use once_cell::sync::OnceCell;
fn load_symbol<T>(sym: &'static str) -> Option<T> {
const LIB_NAME: &str = "libc.so";
println!("loading symbol: {} from {}", sym, LIB_NAME);
match dlopen::raw::Library::open(LIB_NAME) {
Ok(lib) => match unsafe { lib.symbol::<T>(sym) } {
Ok(val) => Some(val),
Err(err) => {
eprintln!("failed to load symbol {} from {}: {:?}", sym, LIB_NAME, err);
None
}
},
Err(err) => {
eprintln!("failed to load {}: {:?}", LIB_NAME, err);
None
}
}
}
fn get_getifaddrs() -> Option<unsafe extern "C" fn(*mut *mut libc::ifaddrs) -> libc::c_int> {
static INSTANCE: OnceCell<
Option<unsafe extern "C" fn(*mut *mut libc::ifaddrs) -> libc::c_int>,
> = OnceCell::new();
*INSTANCE.get_or_init(|| load_symbol("getifaddrs"))
}
fn get_freeifaddrs() -> Option<unsafe extern "C" fn(*mut libc::ifaddrs)> {
static INSTANCE: OnceCell<Option<unsafe extern "C" fn(*mut libc::ifaddrs)>> = OnceCell::new();
*INSTANCE.get_or_init(|| load_symbol("freeifaddrs"))
}
pub unsafe fn getifaddrs(ifap: *mut *mut libc::ifaddrs) -> libc::c_int {
// Android is complicated
// API 24+ contains the getifaddrs and freeifaddrs functions but the NDK doesn't
// expose those functions in ifaddrs.h when the minimum supported SDK is lower than 24
// and therefore we need to load them manually.
if let Some(dyn_getifaddrs) = get_getifaddrs() {
return dyn_getifaddrs(ifap);
}
// If API < 24 (or we can't load libc for some other reason), we fallback to using netlink
netlink_getifaddrs(ifap)
}
pub unsafe fn freeifaddrs(ifa: *mut libc::ifaddrs) {
if let Some(dyn_freeifaddrs) = get_freeifaddrs() {
return dyn_freeifaddrs(ifa);
}
netlink_freeifaddrs(ifa)
}
unsafe fn netlink_getifaddrs(ifap: *mut *mut libc::ifaddrs) -> libc::c_int {
todo!()
}
unsafe fn netlink_freeifaddrs(ifa: *mut libc::ifaddrs) {
todo!()
}

@ -1,6 +1,6 @@
use crate::interface::InterfaceType;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::read_to_string; use std::fs::read_to_string;
use crate::interface::InterfaceType;
pub fn get_interface_type(if_name: String) -> InterfaceType { pub fn get_interface_type(if_name: String) -> InterfaceType {
let if_type_path: String = format!("/sys/class/net/{}/type", if_name); let if_type_path: String = format!("/sys/class/net/{}/type", if_name);
@ -11,16 +11,16 @@ pub fn get_interface_type(if_name: String) -> InterfaceType {
match if_type_string.parse::<u32>() { match if_type_string.parse::<u32>() {
Ok(if_type) => { Ok(if_type) => {
return InterfaceType::try_from(if_type).unwrap_or(InterfaceType::Unknown); return InterfaceType::try_from(if_type).unwrap_or(InterfaceType::Unknown);
}, }
Err(_) => { Err(_) => {
return InterfaceType::Unknown; return InterfaceType::Unknown;
} }
} }
}, }
Err(_) => { Err(_) => {
return InterfaceType::Unknown; return InterfaceType::Unknown;
} }
}; };
} }
pub fn get_interface_speed(if_name: String) -> Option<u64> { pub fn get_interface_speed(if_name: String) -> Option<u64> {
@ -33,14 +33,14 @@ pub fn get_interface_speed(if_name: String) -> Option<u64> {
Ok(if_speed) => { Ok(if_speed) => {
// Convert Mbps to bps // Convert Mbps to bps
return Some(if_speed * 1000000); return Some(if_speed * 1000000);
}, }
Err(_) => { Err(_) => {
return None; return None;
} }
} }
}, }
Err(_) => { Err(_) => {
return None; return None;
} }
}; };
} }

@ -4,9 +4,25 @@ pub use self::shared::*;
mod types; mod types;
pub use self::types::*; pub use self::types::*;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios", target_os = "android"))] #[cfg(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios",
target_os = "android"
))]
mod unix; mod unix;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "openbsd", target_os = "freebsd", target_os = "netbsd", target_os = "ios", target_os = "android"))] #[cfg(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "ios",
target_os = "android"
))]
use self::unix::*; use self::unix::*;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@ -17,12 +33,15 @@ use self::windows::*;
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
mod linux; mod linux;
#[cfg(target_os = "android")]
mod android;
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
mod macos; mod macos;
use std::net::IpAddr; use crate::gateway::Gateway;
use crate::ip::{Ipv4Net, Ipv6Net}; use crate::ip::{Ipv4Net, Ipv6Net};
use crate::gateway::{Gateway}; use std::net::IpAddr;
/// Structure of MAC address /// Structure of MAC address
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -31,24 +50,29 @@ pub struct MacAddr(u8, u8, u8, u8, u8, u8);
impl MacAddr { impl MacAddr {
/// Construct a new MacAddr instance from the given octets /// Construct a new MacAddr instance from the given octets
pub fn new(octets: [u8; 6]) -> MacAddr { pub fn new(octets: [u8; 6]) -> MacAddr {
MacAddr(octets[0], octets[1], octets[2], octets[3], octets[4], octets[5]) MacAddr(
octets[0], octets[1], octets[2], octets[3], octets[4], octets[5],
)
} }
/// Returns an array of MAC address octets /// Returns an array of MAC address octets
pub fn octets(&self) -> [u8; 6] { pub fn octets(&self) -> [u8; 6] {
[self.0,self.1,self.2,self.3,self.4,self.5] [self.0, self.1, self.2, self.3, self.4, self.5]
} }
/// Return a formatted string of MAC address /// Return a formatted string of MAC address
pub fn address(&self) -> String { pub fn address(&self) -> String {
format!("{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", self.0,self.1,self.2,self.3,self.4,self.5) format!(
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
self.0, self.1, self.2, self.3, self.4, self.5
)
} }
/// Construct an all-zero MacAddr instance /// Construct an all-zero MacAddr instance
pub fn zero() -> MacAddr { pub fn zero() -> MacAddr {
MacAddr(0,0,0,0,0,0) MacAddr(0, 0, 0, 0, 0, 0)
} }
/// Construct a new MacAddr instance from a colon-separated string of hex format /// Construct a new MacAddr instance from a colon-separated string of hex format
pub fn from_hex_format(hex_mac_addr: &str) -> MacAddr { pub fn from_hex_format(hex_mac_addr: &str) -> MacAddr {
if hex_mac_addr.len() != 17 { if hex_mac_addr.len() != 17 {
return MacAddr(0,0,0,0,0,0) return MacAddr(0, 0, 0, 0, 0, 0);
} }
let fields: Vec<&str> = hex_mac_addr.split(":").collect(); let fields: Vec<&str> = hex_mac_addr.split(":").collect();
let o1: u8 = u8::from_str_radix(&fields[0], 0x10).unwrap_or(0); let o1: u8 = u8::from_str_radix(&fields[0], 0x10).unwrap_or(0);
@ -63,8 +87,12 @@ impl MacAddr {
impl std::fmt::Display for MacAddr { impl std::fmt::Display for MacAddr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let _ = write!(f,"{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}",self.0,self.1,self.2,self.3,self.4,self.5); let _ = write!(
Ok(()) f,
"{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}",
self.0, self.1, self.2, self.3, self.4, self.5
);
Ok(())
} }
} }
@ -76,7 +104,7 @@ pub struct Interface {
/// Name of network interface /// Name of network interface
pub name: String, pub name: String,
/// Friendly Name of network interface /// Friendly Name of network interface
pub friendly_name : Option<String>, pub friendly_name: Option<String>,
/// Description of the network interface /// Description of the network interface
pub description: Option<String>, pub description: Option<String>,
/// Interface Type /// Interface Type
@ -99,7 +127,7 @@ pub struct Interface {
/// Get default Network Interface /// Get default Network Interface
pub fn get_default_interface() -> Result<Interface, String> { pub fn get_default_interface() -> Result<Interface, String> {
let local_ip: IpAddr = match get_local_ipaddr(){ let local_ip: IpAddr = match get_local_ipaddr() {
Some(local_ip) => local_ip, Some(local_ip) => local_ip,
None => return Err(String::from("Local IP address not found")), None => return Err(String::from("Local IP address not found")),
}; };
@ -110,12 +138,12 @@ pub fn get_default_interface() -> Result<Interface, String> {
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) { if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
return Ok(iface); return Ok(iface);
} }
}, }
IpAddr::V6(local_ipv6) => { IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) { if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
return Ok(iface); return Ok(iface);
} }
}, }
} }
} }
Err(String::from("Default Interface not found")) Err(String::from("Default Interface not found"))
@ -123,7 +151,7 @@ pub fn get_default_interface() -> Result<Interface, String> {
/// Get default Network Interface index /// Get default Network Interface index
pub fn get_default_interface_index() -> Option<u32> { pub fn get_default_interface_index() -> Option<u32> {
let local_ip: IpAddr = match get_local_ipaddr(){ let local_ip: IpAddr = match get_local_ipaddr() {
Some(local_ip) => local_ip, Some(local_ip) => local_ip,
None => return None, None => return None,
}; };
@ -134,12 +162,12 @@ pub fn get_default_interface_index() -> Option<u32> {
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) { if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
return Some(iface.index); return Some(iface.index);
} }
}, }
IpAddr::V6(local_ipv6) => { IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) { if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
return Some(iface.index); return Some(iface.index);
} }
}, }
} }
} }
None None
@ -147,7 +175,7 @@ pub fn get_default_interface_index() -> Option<u32> {
/// Get default Network Interface name /// Get default Network Interface name
pub fn get_default_interface_name() -> Option<String> { pub fn get_default_interface_name() -> Option<String> {
let local_ip: IpAddr = match get_local_ipaddr(){ let local_ip: IpAddr = match get_local_ipaddr() {
Some(local_ip) => local_ip, Some(local_ip) => local_ip,
None => return None, None => return None,
}; };
@ -158,12 +186,12 @@ pub fn get_default_interface_name() -> Option<String> {
if iface.ipv4.iter().any(|x| x.addr == local_ipv4) { if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
return Some(iface.name); return Some(iface.name);
} }
}, }
IpAddr::V6(local_ipv6) => { IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr == local_ipv6) { if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
return Some(iface.name); return Some(iface.name);
} }
}, }
} }
} }
None None

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

Loading…
Cancel
Save