use crate::{ config::Config, netns::{DockerExecTransport, NsTransport, NsenterTransport, nsenter_available}, }; pub fn detect_interface(cfg: &Config, pid: u32, container: &str) -> anyhow::Result { let boxed: Box = if nsenter_available() { Box::new(NsenterTransport { pid }) } else { Box::new(DockerExecTransport { container: container.to_string(), }) }; detect_interface_with_transport(cfg, boxed.as_ref()) } pub fn detect_interface_with_transport( cfg: &Config, transport: &dyn NsTransport, ) -> anyhow::Result { for ifname in &cfg.amnezia.interface_candidates { if transport .run(&["ip", "link", "show", ifname]) .is_ok() { return Ok(ifname.clone()); } } let links = transport.run(&["sh", "-c", "ip -o link show | awk -F': ' '{print $2}'"])?; for raw in links.lines() { let name = raw.trim(); for p in &cfg.amnezia.interface_patterns { if glob_like_match(p, name) { return Ok(name.to_string()); } } } anyhow::bail!("unable to detect amnezia interface") } fn glob_like_match(pattern: &str, value: &str) -> bool { if let Some(prefix) = pattern.strip_suffix('*') { value.starts_with(prefix) } else { pattern == value } }