use crate::core::telemetry::parse_ip_addr_output;
use crate::platform::InterfaceDetector;
use std::process::Command;
fn cmd_output(cmd: &mut Command) -> Option<std::process::Output> {
cmd.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.ok()
}
pub struct LinuxInterface;
impl InterfaceDetector for LinuxInterface {
fn check_wireguard_interface(name: &str) -> bool {
check_wg_interface_exists(name)
}
fn resolve_wireguard_interface(name: &str) -> Option<String> {
if check_wg_interface_exists(name) {
return Some(name.to_string());
}
if let Some(output) = cmd_output(Command::new("wg").arg("show")) {
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
if line.starts_with("interface: ") {
let iface = line.trim_start_matches("interface: ").trim();
if iface == name {
return Some(iface.to_string());
}
}
}
}
None
}
fn get_wireguard_pid(interface: &str) -> Option<u32> {
if let Some(output) = cmd_output(Command::new("ps").args(["-eo", "pid,args"])) {
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
let line_lower = line.to_lowercase();
if line_lower.contains("wireguard")
&& line_lower.contains(&interface.to_lowercase())
{
let parts: Vec<&str> = line.split_whitespace().collect();
if let Some(pid_str) = parts.first() {
if let Ok(pid) = pid_str.parse::<u32>() {
return Some(pid);
}
}
}
}
}
None
}
fn get_interface_info(interface: &str) -> (String, String) {
if let Some(output) = cmd_output(Command::new("ip").args(["addr", "show", interface])) {
let stdout = String::from_utf8_lossy(&output.stdout);
return parse_ip_addr_output(&stdout);
}
(String::new(), String::new())
}
}
fn check_wg_interface_exists(name: &str) -> bool {
cmd_output(Command::new("wg").args(["show", name, "public-key"]))
.is_some_and(|o| o.status.success())
}