use std::net::{IpAddr, Ipv4Addr};
use ipnetwork::IpNetwork;
use tracing::warn;
use super::interfaces::list_interfaces;
use super::types::IpConfig;
pub fn get_ip_configs() -> Vec<IpConfig> {
let interfaces = list_interfaces();
let gateways = read_default_gateways();
interfaces
.into_iter()
.map(|iface| {
let gateway = gateways.get(&iface.name).copied();
IpConfig {
interface: iface.name,
addrs: iface.addrs,
gateway,
}
})
.collect()
}
pub fn get_interface_addrs(name: &str) -> Vec<IpNetwork> {
list_interfaces()
.into_iter()
.find(|i| i.name == name)
.map(|i| i.addrs)
.unwrap_or_default()
}
fn read_default_gateways() -> std::collections::HashMap<String, IpAddr> {
let mut map = std::collections::HashMap::new();
#[cfg(target_os = "linux")]
{
let content = match std::fs::read_to_string("/proc/net/route") {
Ok(c) => c,
Err(e) => {
warn!("Could not read /proc/net/route: {e}");
return map;
}
};
for line in content.lines().skip(1) {
let cols: Vec<&str> = line.split_whitespace().collect();
if cols.len() < 8 {
continue;
}
let iface = cols[0];
let dest = u32::from_str_radix(cols[1], 16).unwrap_or(1);
let gw_hex = u32::from_str_radix(cols[2], 16).unwrap_or(0);
let flags = u32::from_str_radix(cols[3], 16).unwrap_or(0);
const RTF_UP: u32 = 0x1;
const RTF_GATEWAY: u32 = 0x2;
if dest == 0 && (flags & RTF_UP != 0) && (flags & RTF_GATEWAY != 0) && gw_hex != 0 {
let gw_bytes = gw_hex.to_le_bytes();
let gw = IpAddr::V4(Ipv4Addr::from(gw_bytes));
map.insert(iface.to_string(), gw);
}
}
}
map
}