From 2218cc197a8f7cff42051c4aa65459f8f25335ad Mon Sep 17 00:00:00 2001 From: shellrow <81893184+shellrow@users.noreply.github.com> Date: Sat, 8 Jan 2022 01:54:34 +0900 Subject: [PATCH] [WIP] Improve Windows support Get interface information using IP Helper API --- Cargo.toml | 3 +++ src/lib.rs | 1 + src/os/mod.rs | 2 ++ src/os/windows.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 src/os/mod.rs create mode 100644 src/os/windows.rs diff --git a/Cargo.toml b/Cargo.toml index 0e1ff8a..d21b498 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,6 @@ pnet_datalink = "0.28" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.9", features = [ "std" ] } +[dependencies.windows] +version = "0.29.0" +features = ["Win32_Foundation","Win32_NetworkManagement_IpHelper"] diff --git a/src/lib.rs b/src/lib.rs index 836c4ba..bad0a14 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod os; pub mod interface; pub mod gateway; diff --git a/src/os/mod.rs b/src/os/mod.rs new file mode 100644 index 0000000..581af77 --- /dev/null +++ b/src/os/mod.rs @@ -0,0 +1,2 @@ +#[cfg(target_os = "windows")] +pub mod windows; diff --git a/src/os/windows.rs b/src/os/windows.rs new file mode 100644 index 0000000..60cf672 --- /dev/null +++ b/src/os/windows.rs @@ -0,0 +1,69 @@ +use windows::Win32::NetworkManagement::IpHelper::{GetAdaptersInfo, IP_ADAPTER_INFO, IP_ADDR_STRING}; +use std::convert::TryInto; +use std::mem; + +pub const ERROR_BUFFER_OVERFLOW: u32 = 111; +pub const NO_ERROR: u32 = 0; + +// Get network interface information using the IP Helper API +// TODO: Make more rusty way... +// Reference: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo +pub fn get_interfaces() { + let mut out_buf_len : u32 = mem::size_of::().try_into().unwrap(); + let mut raw_adaptor_mem: Vec = Vec::with_capacity(out_buf_len as usize); + let mut p_adaptor: *mut IP_ADAPTER_INFO; + let mut res = unsafe { GetAdaptersInfo(raw_adaptor_mem.as_mut_ptr() as *mut IP_ADAPTER_INFO, &mut out_buf_len ) }; + // Make an initial call to GetAdaptersInfo to get the necessary size into the out_buf_len variable + if res == ERROR_BUFFER_OVERFLOW { + raw_adaptor_mem = Vec::with_capacity(out_buf_len as usize); + unsafe { + res = GetAdaptersInfo(raw_adaptor_mem.as_mut_ptr() as *mut IP_ADAPTER_INFO, &mut out_buf_len); + } + } + if res != NO_ERROR { + //TODO + println!("failed to get adapters info"); + // for test + std::process::exit(1); + } + //Enumerate all adapters + p_adaptor = unsafe { mem::transmute(&raw_adaptor_mem) }; + while p_adaptor as u64 != 0 { + unsafe { + let adapter = *p_adaptor; + let adapter_name = String::from_utf8_lossy(&adapter.AdapterName); + let adapter_desc = String::from_utf8_lossy(&adapter.Description); + let mac_addr = adapter.Address.to_vec(); + println!("{} {} {} {} {:?}", adapter.Index, adapter.ComboIndex, adapter_name, adapter_desc, mac_addr); + //Enumerate all IPs + let mut p_ip_addr: *mut IP_ADDR_STRING; + p_ip_addr = mem::transmute(&(*p_adaptor).IpAddressList); + while p_ip_addr as u64 != 0 { + let ip_addr_string = *p_ip_addr; + let ip_addr = String::from_utf8_lossy(&ip_addr_string.IpAddress.String); + println!("{}", ip_addr); + p_ip_addr = (*p_ip_addr).Next; + } + //Enumerate all gateways + let mut p_gateway_addr: *mut IP_ADDR_STRING; + p_gateway_addr = mem::transmute(&(*p_adaptor).GatewayList); + while p_gateway_addr as u64 != 0 { + let gateway_addr_string = *p_gateway_addr; + let gateway_addr = String::from_utf8_lossy(&gateway_addr_string.IpAddress.String); + println!("{}", gateway_addr); + p_gateway_addr = (*p_gateway_addr).Next; + } + //TODO + } + unsafe { p_adaptor = (*p_adaptor).Next; } + } +} + +#[cfg(test)] +mod tests { + use crate::os::windows; + #[test] + fn list_nw_interfaces() { + windows::get_interfaces(); + } +}