Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ pub mod types;

use crate::interface::interface::Interface;

#[cfg(feature = "gateway")]
use std::net::IpAddr;

/// Get default Network Interface
#[cfg(feature = "gateway")]
pub fn get_default_interface() -> Result<Interface, String> {
use crate::net::ip::get_local_ipaddr;
use std::net::IpAddr;

let interfaces: Vec<Interface> = interfaces();
for iface in &interfaces {
let ifaces: Vec<Interface> = interfaces();
for iface in &ifaces {
if iface.default {
return Ok(iface.clone());
}
Expand All @@ -22,26 +24,46 @@ pub fn get_default_interface() -> Result<Interface, String> {
Some(local_ip) => local_ip,
None => return Err(String::from("Local IP address not found")),
};
for iface in interfaces {
let idx: u32 = pick_default_iface_index(&ifaces, local_ip)
.ok_or_else(|| String::from("Default interface not found"))?;
ifaces
.into_iter()
.find(|it| it.index == idx)
.ok_or_else(|| String::from("Default interface not found"))
}

/// Get a list of available Network Interfaces
pub fn get_interfaces() -> Vec<Interface> {
interfaces()
}

/// Pick the interface index corresponding to the system's default route.
/// Prefers exact IP match; falls back to subnet containment.
#[cfg(feature = "gateway")]
pub(crate) fn pick_default_iface_index(ifaces: &[Interface], local_ip: IpAddr) -> Option<u32> {
let mut subnet_candidate: Option<u32> = None;

for iface in ifaces {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.iter().any(|x| x.addr() == local_ipv4) {
return Ok(iface);
IpAddr::V4(ipv4) => {
if iface.ipv4.iter().any(|x| x.addr() == ipv4) {
return Some(iface.index);
}
if subnet_candidate.is_none() && iface.ipv4.iter().any(|x| x.contains(&ipv4)) {
subnet_candidate = Some(iface.index);
}
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr() == local_ipv6) {
return Ok(iface);
IpAddr::V6(ipv6) => {
if iface.ipv6.iter().any(|x| x.addr() == ipv6) {
return Some(iface.index);
}
if subnet_candidate.is_none() && iface.ipv6.iter().any(|x| x.contains(&ipv6)) {
subnet_candidate = Some(iface.index);
}
}
}
}
Err(String::from("Default Interface not found"))
}

/// Get a list of available Network Interfaces
pub fn get_interfaces() -> Vec<Interface> {
interfaces()
subnet_candidate
}

pub(crate) fn interfaces() -> Vec<Interface> {
Expand Down
33 changes: 8 additions & 25 deletions src/os/android/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,11 @@ use std::net::{Ipv4Addr, Ipv6Addr};
#[cfg(feature = "gateway")]
use crate::net::device::NetworkDevice;
#[cfg(feature = "gateway")]
use crate::net::ip::get_local_ipaddr;
#[cfg(feature = "gateway")]
use crate::os::linux::procfs;
#[cfg(feature = "gateway")]
use crate::os::unix::dns::get_system_dns_conf;
#[cfg(feature = "gateway")]
use std::collections::HashMap;
#[cfg(feature = "gateway")]
use std::net::IpAddr;

fn push_ipv4(v: &mut Vec<Ipv4Net>, add: (Ipv4Addr, u8)) {
if v.iter()
Expand Down Expand Up @@ -55,10 +51,6 @@ fn calc_v6_scope_id(addr: &Ipv6Addr, ifindex: u32) -> u32 {

pub fn interfaces() -> Vec<Interface> {
let mut ifaces = Vec::new();

#[cfg(feature = "gateway")]
let local_ip_opt: Option<IpAddr> = get_local_ipaddr();

// Fill ifaces via netlink first
// If netlink fails, fallback to unix_interfaces
match netlink::collect_interfaces() {
Expand Down Expand Up @@ -155,23 +147,14 @@ pub fn interfaces() -> Vec<Interface> {
if iface.mtu.is_none() {
iface.mtu = mtu::get_mtu(&iface.name);
}

#[cfg(feature = "gateway")]
{
if let Some(local_ip) = local_ip_opt {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.iter().any(|x| x.addr() == local_ipv4) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr() == local_ipv6) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
#[cfg(feature = "gateway")]
{
if let Some(local_ip) = crate::net::ip::get_local_ipaddr() {
if let Some(idx) = crate::interface::pick_default_iface_index(&ifaces, local_ip) {
if let Some(iface) = ifaces.iter_mut().find(|it| it.index == idx) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
Expand Down
31 changes: 10 additions & 21 deletions src/os/bsd/interface.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#[cfg(feature = "gateway")]
use std::net::IpAddr;

use crate::{interface::interface::Interface, os::unix::interface::unix_interfaces};

pub fn interfaces() -> Vec<Interface> {
Expand All @@ -12,31 +9,23 @@ pub fn interfaces() -> Vec<Interface> {
{
use crate::os::unix::dns::get_system_dns_conf;

let mut interfaces: Vec<Interface> = unix_interfaces();
let local_ip_opt: Option<IpAddr> = crate::net::ip::get_local_ipaddr();
let mut ifaces: Vec<Interface> = unix_interfaces();

let gateway_map = super::route::get_gateway_map();

for iface in &mut interfaces {
for iface in &mut ifaces {
if let Some(gateway) = gateway_map.get(&iface.index) {
iface.gateway = Some(gateway.clone());
}

if let Some(local_ip) = local_ip_opt {
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;
}
});
}
if let Some(local_ip) = crate::net::ip::get_local_ipaddr() {
if let Some(idx) = crate::interface::pick_default_iface_index(&ifaces, local_ip) {
if let Some(iface) = ifaces.iter_mut().find(|it| it.index == idx) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
interfaces
ifaces
}
}
46 changes: 17 additions & 29 deletions src/os/ios/interface.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,29 @@
#[cfg(feature = "gateway")]
use std::net::IpAddr;

use crate::{interface::interface::Interface, os::unix::interface::unix_interfaces};

pub fn interfaces() -> Vec<Interface> {
let mut interfaces: Vec<Interface> = unix_interfaces();

#[cfg(feature = "gateway")]
let local_ip_opt: Option<IpAddr> = crate::net::ip::get_local_ipaddr();

#[cfg(not(feature = "gateway"))]
{
unix_interfaces()
}
#[cfg(feature = "gateway")]
let gateway_map = crate::os::darwin::route::get_gateway_map();
{
use crate::os::unix::dns::get_system_dns_conf;

for iface in &mut interfaces {
#[cfg(feature = "gateway")]
{
use crate::os::unix::dns::get_system_dns_conf;
let mut ifaces: Vec<Interface> = unix_interfaces();
let gateway_map = crate::os::darwin::route::get_gateway_map();
for iface in &mut ifaces {
if let Some(gateway) = gateway_map.get(&iface.index) {
iface.gateway = Some(gateway.clone());
}

if let Some(local_ip) = local_ip_opt {
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;
}
});
}
if let Some(local_ip) = crate::net::ip::get_local_ipaddr() {
if let Some(idx) = crate::interface::pick_default_iface_index(&ifaces, local_ip) {
if let Some(iface) = ifaces.iter_mut().find(|it| it.index == idx) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
ifaces
}

interfaces
}
33 changes: 8 additions & 25 deletions src/os/linux/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ use std::net::{Ipv4Addr, Ipv6Addr};
#[cfg(feature = "gateway")]
use crate::net::device::NetworkDevice;
#[cfg(feature = "gateway")]
use crate::net::ip::get_local_ipaddr;
#[cfg(feature = "gateway")]
use crate::os::unix::dns::get_system_dns_conf;
#[cfg(feature = "gateway")]
use std::collections::HashMap;
#[cfg(feature = "gateway")]
use std::net::IpAddr;

fn push_ipv4(v: &mut Vec<Ipv4Net>, add: (Ipv4Addr, u8)) {
if v.iter()
Expand Down Expand Up @@ -51,10 +47,6 @@ fn calc_v6_scope_id(addr: &Ipv6Addr, ifindex: u32) -> u32 {

pub fn interfaces() -> Vec<Interface> {
let mut ifaces = Vec::new();

#[cfg(feature = "gateway")]
let local_ip_opt: Option<IpAddr> = get_local_ipaddr();

// Fill ifaces via netlink first
// If netlink fails, fallback to unix_interfaces
match netlink::collect_interfaces() {
Expand Down Expand Up @@ -151,23 +143,14 @@ pub fn interfaces() -> Vec<Interface> {
if iface.mtu.is_none() {
iface.mtu = super::mtu::get_mtu(&iface.name);
}

#[cfg(feature = "gateway")]
{
if let Some(local_ip) = local_ip_opt {
match local_ip {
IpAddr::V4(local_ipv4) => {
if iface.ipv4.iter().any(|x| x.addr() == local_ipv4) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
IpAddr::V6(local_ipv6) => {
if iface.ipv6.iter().any(|x| x.addr() == local_ipv6) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
#[cfg(feature = "gateway")]
{
if let Some(local_ip) = crate::net::ip::get_local_ipaddr() {
if let Some(idx) = crate::interface::pick_default_iface_index(&ifaces, local_ip) {
if let Some(iface) = ifaces.iter_mut().find(|it| it.index == idx) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
Expand Down
37 changes: 14 additions & 23 deletions src/os/macos/interface.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#[cfg(feature = "gateway")]
use std::net::IpAddr;

use crate::{
interface::{interface::Interface, types::InterfaceType},
os::unix::interface::unix_interfaces,
Expand All @@ -16,43 +13,37 @@ pub struct SCInterface {

pub fn interfaces() -> Vec<Interface> {
let type_map = super::types::get_if_type_map();
let mut interfaces: Vec<Interface> = unix_interfaces();

#[cfg(feature = "gateway")]
let local_ip_opt: Option<IpAddr> = crate::net::ip::get_local_ipaddr();
let mut ifaces: Vec<Interface> = unix_interfaces();

#[cfg(feature = "gateway")]
let gateway_map = crate::os::darwin::route::get_gateway_map();

for iface in &mut interfaces {
for iface in &mut ifaces {
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();
}

#[cfg(feature = "gateway")]
{
use crate::os::unix::dns::get_system_dns_conf;
if let Some(gateway) = gateway_map.get(&iface.index) {
iface.gateway = Some(gateway.clone());
}
}
}

if let Some(local_ip) = local_ip_opt {
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")]
{
use crate::os::unix::dns::get_system_dns_conf;
if let Some(local_ip) = crate::net::ip::get_local_ipaddr() {
if let Some(idx) = crate::interface::pick_default_iface_index(&ifaces, local_ip) {
if let Some(iface) = ifaces.iter_mut().find(|it| it.index == idx) {
iface.default = true;
iface.dns_servers = get_system_dns_conf();
}
}
}
}

interfaces
ifaces
}