|
|
|
@ -1,10 +1,49 @@ |
|
|
|
|
use crate::interface::Interface; |
|
|
|
|
use once_cell::sync::OnceCell; |
|
|
|
|
|
|
|
|
|
pub fn unix_interfaces() -> Vec<Interface> { |
|
|
|
|
netlink::unix_interfaces() |
|
|
|
|
pub fn get_libc_ifaddrs() -> Option<( |
|
|
|
|
unsafe extern "C" fn(*mut *mut libc::ifaddrs) -> libc::c_int, |
|
|
|
|
unsafe extern "C" fn(*mut libc::ifaddrs), |
|
|
|
|
)> { |
|
|
|
|
match (get_getifaddrs(), get_freeifaddrs()) { |
|
|
|
|
(Some(a), Some(b)) => Some((a, b)), |
|
|
|
|
_ => None, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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")) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mod netlink { |
|
|
|
|
pub mod netlink { |
|
|
|
|
//! Netlink based getifaddrs.
|
|
|
|
|
//!
|
|
|
|
|
//! Based on the logic found in https://git.musl-libc.org/cgit/musl/tree/src/network/getifaddrs.c
|
|
|
|
|