use core::net::IpAddr;
use std::{
io,
net::{Ipv4Addr, Ipv6Addr},
};
use super::{interface_addrs, interface_ipv4_addrs, interface_ipv6_addrs, interfaces};
#[inline]
fn interface_not_found_for_ip() -> io::Error {
io::Error::other("interface not found")
}
pub fn get_ip_mtu(ip: IpAddr) -> io::Result<u32> {
let ifis = interfaces()?;
if let Ok(addrs) = interface_addrs() {
if let Some(mtu) = addrs
.iter()
.find(|a| a.addr() == ip)
.and_then(|a| ifis.iter().find(|i| i.index() == a.index()))
.map(|i| i.mtu())
{
return Ok(mtu);
}
}
for iface in &ifis {
if let Ok(addrs) = iface.addrs() {
if addrs.iter().any(|a| a.addr() == ip) {
return Ok(iface.mtu());
}
}
}
Err(interface_not_found_for_ip())
}
pub fn get_ipv4_mtu(ip: Ipv4Addr) -> io::Result<u32> {
let ifis = interfaces()?;
if let Ok(addrs) = interface_ipv4_addrs() {
if let Some(mtu) = addrs
.iter()
.find(|a| a.addr() == ip)
.and_then(|a| ifis.iter().find(|i| i.index() == a.index()))
.map(|i| i.mtu())
{
return Ok(mtu);
}
}
for iface in &ifis {
if let Ok(addrs) = iface.ipv4_addrs() {
if addrs.iter().any(|a| a.addr() == ip) {
return Ok(iface.mtu());
}
}
}
Err(interface_not_found_for_ip())
}
pub fn get_ipv6_mtu(ip: Ipv6Addr) -> io::Result<u32> {
let ifis = interfaces()?;
if let Ok(addrs) = interface_ipv6_addrs() {
if let Some(mtu) = addrs
.iter()
.find(|a| a.addr() == ip)
.and_then(|a| ifis.iter().find(|i| i.index() == a.index()))
.map(|i| i.mtu())
{
return Ok(mtu);
}
}
for iface in &ifis {
if let Ok(addrs) = iface.ipv6_addrs() {
if addrs.iter().any(|a| a.addr() == ip) {
return Ok(iface.mtu());
}
}
}
Err(interface_not_found_for_ip())
}
#[cfg(test)]
mod tests {
use super::*;
fn assert_not_found(err: io::Error) {
assert_eq!(err.kind(), io::ErrorKind::Other);
assert!(
err.to_string().contains("interface not found"),
"expected interface-not-found error, got: {err}"
);
}
#[test]
fn get_ip_mtu_unknown_returns_not_found() {
let v4 = IpAddr::V4(Ipv4Addr::new(203, 0, 113, 1));
let v6 = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
assert_not_found(get_ip_mtu(v4).unwrap_err());
assert_not_found(get_ip_mtu(v6).unwrap_err());
}
#[test]
fn get_ipv4_mtu_unknown_returns_not_found() {
let ip = Ipv4Addr::new(203, 0, 113, 2);
assert_not_found(get_ipv4_mtu(ip).unwrap_err());
}
#[test]
fn get_ipv6_mtu_unknown_returns_not_found() {
let ip = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
assert_not_found(get_ipv6_mtu(ip).unwrap_err());
}
#[test]
fn get_ip_mtu_loopback_exercises_bulk_path() {
let _ = get_ip_mtu(IpAddr::V4(Ipv4Addr::LOCALHOST));
let _ = get_ip_mtu(IpAddr::V6(Ipv6Addr::LOCALHOST));
}
#[test]
fn get_ipv4_mtu_loopback_exercises_bulk_path() {
let _ = get_ipv4_mtu(Ipv4Addr::LOCALHOST);
}
}