From 07c74649d1d7e2140c33c36d04abe0c57a3e93aa Mon Sep 17 00:00:00 2001 From: shellrow <81893184+shellrow@users.noreply.github.com> Date: Sun, 9 Jan 2022 21:43:14 +0900 Subject: [PATCH] Impl interface for windows --- .gitignore | 3 + src/interface.rs | 26 ++++++++ src/lib.rs | 1 + src/os/mod.rs | 12 +++- src/os/shared.rs | 18 +++++ src/os/unix.rs | 6 ++ src/os/windows.rs | 165 +++++++++++++++++++++++----------------------- 7 files changed, 147 insertions(+), 84 deletions(-) create mode 100644 src/os/shared.rs create mode 100644 src/os/unix.rs diff --git a/.gitignore b/.gitignore index a3bef42..1ab4877 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ Cargo.lock # mac .DS_Store + +# debug +/.vscode/ \ No newline at end of file diff --git a/src/interface.rs b/src/interface.rs index 8d2616c..2d8039c 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,6 +1,7 @@ use std::net::UdpSocket; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use crate::gateway::{self, Gateway}; +use crate::os; /// Struct of MAC address #[derive(Clone, Debug)] @@ -43,6 +44,31 @@ pub struct Interface { pub gateway: Option, } +#[cfg(target_os = "windows")] +pub fn get_default_interface() -> Result { + let local_ip: IpAddr = match os::get_local_ipaddr(){ + Some(local_ip) => local_ip, + None => return Err(String::from("Local IP address not found")), + }; + let interfaces: Vec = os::get_interfaces(); + for iface in interfaces { + match local_ip { + IpAddr::V4(local_ipv4) => { + if iface.ipv4.contains(&local_ipv4) { + return Ok(iface); + } + }, + IpAddr::V6(local_ipv6) => { + if iface.ipv6.contains(&local_ipv6) { + return Ok(iface); + } + }, + } + } + Err(String::from("Default Interface not found")) +} + +#[cfg(not(target_os="windows"))] /// Get default Interface pub fn get_default_interface() -> Result { let local_ip = get_local_ipaddr(); diff --git a/src/lib.rs b/src/lib.rs index bad0a14..e255bef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,3 +6,4 @@ pub use interface::Interface; pub use interface::get_default_interface; pub use gateway::Gateway; pub use gateway::get_default_gateway; +pub use os::get_interfaces; diff --git a/src/os/mod.rs b/src/os/mod.rs index 581af77..81aa7a7 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -1,2 +1,12 @@ +mod shared; +pub use self::shared::*; + #[cfg(target_os = "windows")] -pub mod windows; +mod windows; +#[cfg(target_os = "windows")] +pub use self::windows::*; + +#[cfg(not(target_os="windows"))] +mod unix; +#[cfg(not(target_os="windows"))] +use self::unix::*; diff --git a/src/os/shared.rs b/src/os/shared.rs new file mode 100644 index 0000000..eb39895 --- /dev/null +++ b/src/os/shared.rs @@ -0,0 +1,18 @@ +use std::net::{IpAddr, UdpSocket}; + +pub fn get_local_ipaddr() -> Option { + let socket = match UdpSocket::bind("0.0.0.0:0") { + Ok(s) => s, + Err(_) => return None, + }; + + match socket.connect("1.1.1.1:80") { + Ok(()) => (), + Err(_) => return None, + }; + + match socket.local_addr() { + Ok(addr) => return Some(addr.ip()), + Err(_) => return None, + }; +} diff --git a/src/os/unix.rs b/src/os/unix.rs new file mode 100644 index 0000000..f35e66d --- /dev/null +++ b/src/os/unix.rs @@ -0,0 +1,6 @@ +use crate::interface::{Interface, MacAddr}; + +pub fn get_interfaces() -> Vec { + let interfaces: Vec = vec![]; + return interfaces; +} diff --git a/src/os/windows.rs b/src/os/windows.rs index 573f4fc..1f8e54d 100644 --- a/src/os/windows.rs +++ b/src/os/windows.rs @@ -9,7 +9,8 @@ use core::ffi::c_void; use crate::interface::{Interface, MacAddr}; use crate::gateway::Gateway; -pub const EXCEPTION_INTERFACE_INDEX: u32 = 0; +const EXCEPTION_INTERFACE_INDEX: u32 = 0; +const EXCEPTION_INTERFACE_COMBOINDEX: u32 = 4928; // Convert C string to Rust string without trailing null bytes fn bytes_to_string(bytes: &[u8]) -> String { @@ -76,92 +77,90 @@ pub fn get_interfaces() -> Vec { //Enumerate all adapters p_adaptor = unsafe { mem::transmute(&raw_adaptor_mem) }; while p_adaptor as u64 != 0 { - unsafe { - let adapter: IP_ADAPTER_INFO = *p_adaptor; - if adapter.Index == EXCEPTION_INTERFACE_INDEX{ - p_adaptor = (*p_adaptor).Next; - continue; - } - let adapter_name: String = bytes_to_string(&adapter.AdapterName); - let adapter_desc: String = bytes_to_string(&adapter.Description); - let mac_addr:[u8; 6] = adapter.Address[..6].try_into().unwrap_or([0, 0, 0, 0, 0, 0]); - //Enumerate all IPs - let mut ipv4_vec: Vec = vec![]; - let mut ipv6_vec: Vec = vec![]; - 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: IP_ADDR_STRING = *p_ip_addr; - let ip_addr: String = bytes_to_string(&ip_addr_string.IpAddress.String); - match ip_addr.parse::() { - Ok(ip_addr) => { - match ip_addr { - IpAddr::V4(ipv4_addr) => { - ipv4_vec.push(ipv4_addr); - }, - IpAddr::V6(ipv6_addr) => { - ipv6_vec.push(ipv6_addr); - } + let adapter: IP_ADAPTER_INFO = unsafe { *p_adaptor }; + if adapter.Index == EXCEPTION_INTERFACE_INDEX || adapter.ComboIndex == EXCEPTION_INTERFACE_COMBOINDEX{ + unsafe { p_adaptor = (*p_adaptor).Next; } + continue; + } + let adapter_name: String = bytes_to_string(&adapter.AdapterName); + let adapter_desc: String = bytes_to_string(&adapter.Description); + let mac_addr:[u8; 6] = adapter.Address[..6].try_into().unwrap_or([0, 0, 0, 0, 0, 0]); + //Enumerate all IPs + let mut ipv4_vec: Vec = vec![]; + let mut ipv6_vec: Vec = vec![]; + let mut p_ip_addr: *mut IP_ADDR_STRING; + p_ip_addr = unsafe { mem::transmute(&(*p_adaptor).IpAddressList) }; + while p_ip_addr as u64 != 0 { + let ip_addr_string: IP_ADDR_STRING = unsafe{ *p_ip_addr }; + let ip_addr: String = bytes_to_string(&ip_addr_string.IpAddress.String); + match ip_addr.parse::() { + Ok(ip_addr) => { + match ip_addr { + IpAddr::V4(ipv4_addr) => { + ipv4_vec.push(ipv4_addr); + }, + IpAddr::V6(ipv6_addr) => { + ipv6_vec.push(ipv6_addr); } - }, - Err(_) => {}, - } - p_ip_addr = (*p_ip_addr).Next; + } + }, + Err(_) => {}, } - //Enumerate all gateways - let mut gateway_ips: Vec = vec![]; - 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: IP_ADDR_STRING = *p_gateway_addr; - let gateway_addr: String = bytes_to_string(&gateway_addr_string.IpAddress.String); - match gateway_addr.parse::() { - Ok(ip_addr) => { - gateway_ips.push(ip_addr); - }, - Err(_) => {}, - } - p_gateway_addr = (*p_gateway_addr).Next; + unsafe { p_ip_addr = (*p_ip_addr).Next; } + } + //Enumerate all gateways + let mut gateway_ips: Vec = vec![]; + let mut p_gateway_addr: *mut IP_ADDR_STRING; + p_gateway_addr = unsafe { mem::transmute(&(*p_adaptor).GatewayList) }; + while p_gateway_addr as u64 != 0 { + let gateway_addr_string: IP_ADDR_STRING = unsafe { *p_gateway_addr }; + let gateway_addr: String = bytes_to_string(&gateway_addr_string.IpAddress.String); + match gateway_addr.parse::() { + Ok(ip_addr) => { + gateway_ips.push(ip_addr); + }, + Err(_) => {}, } - let default_gateway: Option = match gateway_ips.get(0) { - Some(gateway_ip) => { - let gateway_ip: IpAddr = *gateway_ip; - let default_gateway: Option = if gateway_ip != IpAddr::V4(Ipv4Addr::UNSPECIFIED) { - match gateway_ip { - IpAddr::V4(dst_ip) => { - if let Some(src_ip) = ipv4_vec.get(0) { - let mac_addr = get_mac_through_arp(*src_ip, dst_ip); - let gateway = Gateway { - mac_addr: mac_addr, - ip_addr: IpAddr::V4(dst_ip), - }; - Some(gateway) - }else{ - None - } - }, - IpAddr::V6(_dst_ip) => { + unsafe { p_gateway_addr = (*p_gateway_addr).Next; } + } + let default_gateway: Option = match gateway_ips.get(0) { + Some(gateway_ip) => { + let gateway_ip: IpAddr = *gateway_ip; + let default_gateway: Option = if gateway_ip != IpAddr::V4(Ipv4Addr::UNSPECIFIED) { + match gateway_ip { + IpAddr::V4(dst_ip) => { + if let Some(src_ip) = ipv4_vec.get(0) { + let mac_addr = get_mac_through_arp(*src_ip, dst_ip); + let gateway = Gateway { + mac_addr: mac_addr, + ip_addr: IpAddr::V4(dst_ip), + }; + Some(gateway) + }else{ None - }, - } - }else{ - None - }; - default_gateway - }, - None => None, - }; - let interface: Interface = Interface{ - index: adapter.Index, - name: adapter_name, - description: Some(adapter_desc), - mac_addr: Some(MacAddr::new(mac_addr)), - ipv4: ipv4_vec, - ipv6: ipv6_vec, - gateway: default_gateway, - }; - interfaces.push(interface); - } + } + }, + IpAddr::V6(_dst_ip) => { + None + }, + } + }else{ + None + }; + default_gateway + }, + None => None, + }; + let interface: Interface = Interface{ + index: adapter.Index, + name: adapter_name, + description: Some(adapter_desc), + mac_addr: Some(MacAddr::new(mac_addr)), + ipv4: ipv4_vec, + ipv6: ipv6_vec, + gateway: default_gateway, + }; + interfaces.push(interface); unsafe { p_adaptor = (*p_adaptor).Next; } } return interfaces;