From 8c2e33223c999c3c214ef658f1704d2802e390b8 Mon Sep 17 00:00:00 2001 From: qinghon Date: Sun, 23 Mar 2025 17:16:29 +0800 Subject: [PATCH 1/2] move gateway to option --- Cargo.toml | 6 ++- examples/list_interfaces.rs | 3 ++ src/interface/android.rs | 3 ++ src/interface/mod.rs | 12 +++++- src/interface/shared.rs | 1 + src/interface/unix.rs | 83 +++++++++++++++++++++++-------------- src/interface/windows.rs | 8 ++++ src/lib.rs | 3 ++ 8 files changed, 86 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 57a78d8..1719e7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,9 @@ system-configuration = "0.6" serde_json = "1.0" [features] +default = ["gateway"] serde = ["dep:serde", "ipnet/serde"] +gateway = [] [[example]] name = "list_interfaces" @@ -46,12 +48,14 @@ path = "examples/list_interfaces.rs" [[example]] name = "default_interface" path = "examples/default_interface.rs" +required-features = ["gateway"] [[example]] name = "default_gateway" path = "examples/default_gateway.rs" +required-features = ["gateway"] [[example]] name = "serialize" path = "examples/serialize.rs" -required-features = ["serde"] +required-features = ["serde", "gateway"] diff --git a/examples/list_interfaces.rs b/examples/list_interfaces.rs index 526e279..6f686bd 100644 --- a/examples/list_interfaces.rs +++ b/examples/list_interfaces.rs @@ -36,6 +36,7 @@ fn main() { println!("\tTransmit Speed: {:?}", interface.transmit_speed); println!("\tReceive Speed: {:?}", interface.receive_speed); + #[cfg(feature = "gateway")] if let Some(gateway) = interface.gateway { println!("Gateway"); println!("\tMAC Address: {}", gateway.mac_addr); @@ -44,8 +45,10 @@ fn main() { } else { println!("Gateway: (Not found)"); } + #[cfg(feature = "gateway")] println!("DNS Servers: {:?}", interface.dns_servers); println!("MTU: {:?}", interface.mtu); + #[cfg(feature = "gateway")] println!("Default: {}", interface.default); println!(); } diff --git a/src/interface/android.rs b/src/interface/android.rs index dc148ad..a608f4b 100644 --- a/src/interface/android.rs +++ b/src/interface/android.rs @@ -105,9 +105,12 @@ pub mod netlink { flags: link_msg.header.flags.bits(), transmit_speed: None, receive_speed: None, + #[cfg(feature = "gateway")] gateway: None, + #[cfg(feature = "gateway")] dns_servers: Vec::new(), mtu: None, + #[cfg(feature = "gateway")] default: false, }; diff --git a/src/interface/mod.rs b/src/interface/mod.rs index bf7dce8..0352f83 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -41,11 +41,12 @@ mod android; #[cfg(any(target_os = "macos", target_os = "ios"))] mod macos; - +#[cfg(feature = "gateway")] use crate::device::NetworkDevice; use crate::ipnet::{Ipv4Net, Ipv6Net}; use crate::mac::MacAddr; use crate::sys; +#[cfg(feature = "gateway")] use std::net::IpAddr; /// Structure of Network Interface information @@ -92,17 +93,21 @@ pub struct Interface { /// Default gateway for the network interface. This is the address of the router to which /// IP packets are forwarded when they need to be sent to a device outside /// of the local network. + #[cfg(feature = "gateway")] pub gateway: Option, /// DNS server addresses for the network interface + #[cfg(feature = "gateway")] pub dns_servers: Vec, /// Maximum Transmission Unit (MTU) for the network interface pub mtu: Option, /// Whether this is the default interface for accessing the Internet. + #[cfg(feature = "gateway")] pub default: bool, } impl Interface { /// Construct a new default Interface instance + #[cfg(feature = "gateway")] pub fn default() -> Result { let interfaces: Vec = interfaces(); for iface in &interfaces { @@ -145,9 +150,12 @@ impl Interface { flags: 0, transmit_speed: None, receive_speed: None, + #[cfg(feature = "gateway")] gateway: None, + #[cfg(feature = "gateway")] dns_servers: Vec::new(), mtu: None, + #[cfg(feature = "gateway")] default: false, } } @@ -188,6 +196,7 @@ impl Interface { } /// Get default Network Interface +#[cfg(feature = "gateway")] pub fn get_default_interface() -> Result { let interfaces: Vec = interfaces(); for iface in &interfaces { @@ -232,6 +241,7 @@ mod tests { } } #[test] + #[cfg(feature = "gateway")] fn test_default_interface() { println!("{:#?}", get_default_interface()); } diff --git a/src/interface/shared.rs b/src/interface/shared.rs index deaa1e5..538f9ac 100644 --- a/src/interface/shared.rs +++ b/src/interface/shared.rs @@ -16,6 +16,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; /// Returns: /// - `Some(IpAddr)`: IP address of the default network interface if successful. /// - `None`: If any error occurs during the operations. +#[cfg(feature = "gateway")] pub fn get_local_ipaddr() -> Option { // Attempt to bind a UDP socket to an unspecified address and port. let socket = match UdpSocket::bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)) { diff --git a/src/interface/unix.rs b/src/interface/unix.rs index bf3b2fc..62c419c 100644 --- a/src/interface/unix.rs +++ b/src/interface/unix.rs @@ -1,5 +1,6 @@ use super::Interface; use super::MacAddr; +#[cfg(feature = "gateway")] use crate::gateway; use crate::interface::InterfaceType; use crate::ipnet::{Ipv4Net, Ipv6Net}; @@ -7,10 +8,13 @@ use crate::sys; use libc; use std::ffi::{CStr, CString}; use std::mem::{self, MaybeUninit}; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, ToSocketAddrs}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::os::raw::c_char; use std::str::from_utf8_unchecked; +#[cfg(feature = "gateway")] +use std::net::ToSocketAddrs; +#[cfg(feature = "gateway")] pub fn get_system_dns_conf() -> Vec { use std::fs::read_to_string; const PATH_RESOLV_CONF: &str = "/etc/resolv.conf"; @@ -48,31 +52,36 @@ pub fn interfaces() -> Vec { let type_map = macos::get_if_type_map(); let mut interfaces: Vec = unix_interfaces(); + #[cfg(feature = "gateway")] let local_ip: IpAddr = match super::get_local_ipaddr() { Some(local_ip) => local_ip, None => return interfaces, }; + #[cfg(feature = "gateway")] let gateway_map = gateway::macos::get_gateway_map(); for iface in &mut interfaces { if let Some(sc_interface) = type_map.get(&iface.name) { iface.if_type = sc_interface.interface_type; iface.friendly_name = sc_interface.friendly_name.clone(); } - if let Some(gateway) = gateway_map.get(&iface.index) { - iface.gateway = Some(gateway.clone()); - } - iface.ipv4.iter().for_each(|ipv4| { - if IpAddr::V4(ipv4.addr()) == local_ip { - iface.dns_servers = get_system_dns_conf(); - iface.default = true; - } - }); - iface.ipv6.iter().for_each(|ipv6| { - if IpAddr::V6(ipv6.addr()) == local_ip { - iface.dns_servers = get_system_dns_conf(); - iface.default = true; + #[cfg(feature = "gateway")] + { + if let Some(gateway) = gateway_map.get(&iface.index) { + iface.gateway = Some(gateway.clone()); } - }); + iface.ipv4.iter().for_each(|ipv4| { + if IpAddr::V4(ipv4.addr()) == local_ip { + iface.dns_servers = get_system_dns_conf(); + iface.default = true; + } + }); + iface.ipv6.iter().for_each(|ipv6| { + if IpAddr::V6(ipv6.addr()) == local_ip { + iface.dns_servers = get_system_dns_conf(); + iface.default = true; + } + }); + } } interfaces } @@ -82,19 +91,24 @@ pub fn interfaces() -> Vec { use super::linux; let mut interfaces: Vec = unix_interfaces(); + + #[cfg(feature = "gateway")] let local_ip: IpAddr = match super::get_local_ipaddr() { Some(local_ip) => local_ip, None => return interfaces, }; + #[cfg(feature = "gateway")] let gateway_map = gateway::linux::get_gateway_map(); for iface in &mut interfaces { iface.if_type = linux::get_interface_type(iface.name.clone()); let if_speed: Option = linux::get_interface_speed(iface.name.clone()); iface.transmit_speed = if_speed; iface.receive_speed = if_speed; + #[cfg(feature = "gateway")] if let Some(gateway) = gateway_map.get(&iface.name) { iface.gateway = Some(gateway.clone()); } + #[cfg(feature = "gateway")] match local_ip { IpAddr::V4(local_ipv4) => { if iface.ipv4.iter().any(|x| x.addr() == local_ipv4) { @@ -116,27 +130,31 @@ pub fn interfaces() -> Vec { #[cfg(any(target_os = "openbsd", target_os = "freebsd", target_os = "netbsd"))] pub fn interfaces() -> Vec { let mut interfaces: Vec = unix_interfaces(); + #[cfg(feature = "gateway")] let local_ip: IpAddr = match super::get_local_ipaddr() { Some(local_ip) => local_ip, None => return interfaces, }; - let gateway_map = gateway::bsd::get_gateway_map(); - for iface in &mut interfaces { - if let Some(gateway) = gateway_map.get(&iface.index) { - iface.gateway = Some(gateway.clone()); - } - iface.ipv4.iter().for_each(|ipv4| { - if IpAddr::V4(ipv4.addr()) == local_ip { - iface.dns_servers = get_system_dns_conf(); - iface.default = true; + #[cfg(feature = "gateway")] + { + let gateway_map = gateway::bsd::get_gateway_map(); + for iface in &mut interfaces { + if let Some(gateway) = gateway_map.get(&iface.index) { + iface.gateway = Some(gateway.clone()); } - }); - iface.ipv6.iter().for_each(|ipv6| { - if IpAddr::V6(ipv6.addr()) == local_ip { - iface.dns_servers = get_system_dns_conf(); - iface.default = true; - } - }); + iface.ipv4.iter().for_each(|ipv4| { + if IpAddr::V4(ipv4.addr()) == local_ip { + iface.dns_servers = get_system_dns_conf(); + iface.default = true; + } + }); + iface.ipv6.iter().for_each(|ipv6| { + if IpAddr::V6(ipv6.addr()) == local_ip { + iface.dns_servers = get_system_dns_conf(); + iface.default = true; + } + }); + } } interfaces } @@ -457,9 +475,12 @@ fn unix_interfaces_inner( flags: addr_ref.ifa_flags, transmit_speed: None, receive_speed: None, + #[cfg(feature = "gateway")] gateway: None, + #[cfg(feature = "gateway")] dns_servers: Vec::new(), mtu: get_mtu(addr_ref, &name), + #[cfg(feature = "gateway")] default: false, }; ifaces.push(interface); diff --git a/src/interface/windows.rs b/src/interface/windows.rs index b8e2acf..e0b6aec 100644 --- a/src/interface/windows.rs +++ b/src/interface/windows.rs @@ -230,10 +230,13 @@ pub fn interfaces() -> Vec { } } // Gateway + #[cfg(feature = "gateway")] let gateway_ips: Vec = unsafe { linked_list_iter!(&cur.FirstGatewayAddress) } .filter_map(|cur_g| unsafe { socket_address_to_ipaddr(&cur_g.Address).0 }) .collect(); + #[cfg(feature = "gateway")] let mut default_gateway: NetworkDevice = NetworkDevice::new(); + #[cfg(feature = "gateway")] if flags & sys::IFF_UP != 0 { for gateway_ip in gateway_ips { match gateway_ip { @@ -253,9 +256,11 @@ pub fn interfaces() -> Vec { } } // DNS Servers + #[cfg(feature = "gateway")] let dns_servers: Vec = unsafe { linked_list_iter!(&cur.FirstDnsServerAddress) } .filter_map(|cur_d| unsafe { socket_address_to_ipaddr(&cur_d.Address).0 }) .collect(); + #[cfg(feature = "gateway")] let default: bool = match local_ip { IpAddr::V4(local_ipv4) => ipv4_vec.iter().any(|x| x.addr() == local_ipv4), IpAddr::V6(local_ipv6) => ipv6_vec.iter().any(|x| x.addr() == local_ipv6), @@ -273,13 +278,16 @@ pub fn interfaces() -> Vec { flags, transmit_speed: Some(cur.TransmitLinkSpeed), receive_speed: Some(cur.ReceiveLinkSpeed), + #[cfg(feature = "gateway")] gateway: if default_gateway.mac_addr == MacAddr::zero() { None } else { Some(default_gateway) }, + #[cfg(feature = "gateway")] dns_servers, mtu: Some(cur.Mtu), + #[cfg(feature = "gateway")] default, }; Some(interface) diff --git a/src/lib.rs b/src/lib.rs index 69dc364..6c5849c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,15 @@ mod db; pub mod device; +#[cfg(feature = "gateway")] pub mod gateway; pub mod interface; pub mod mac; mod sys; pub use device::NetworkDevice; +#[cfg(feature = "gateway")] pub use gateway::get_default_gateway; +#[cfg(feature = "gateway")] pub use interface::get_default_interface; pub use interface::get_interfaces; pub use interface::Interface; From 3001b30d9371aa0874b2ca7b1d32204515d49d21 Mon Sep 17 00:00:00 2001 From: qinghon Date: Sun, 23 Mar 2025 22:59:32 +0800 Subject: [PATCH 2/2] fix build warning --- src/interface/mod.rs | 2 ++ src/interface/shared.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 0352f83..e26dd1a 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -1,4 +1,6 @@ +#[cfg(feature = "gateway")] mod shared; +#[cfg(feature = "gateway")] pub use self::shared::*; mod types; diff --git a/src/interface/shared.rs b/src/interface/shared.rs index 538f9ac..09d9947 100644 --- a/src/interface/shared.rs +++ b/src/interface/shared.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "gateway")] use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; /// Retrieve the IP address of the default network interface.