use super::TunError;
use std::net::Ipv6Addr;
use tokio::process::Command;
pub fn is_ipv6_disabled() -> bool {
std::process::Command::new("sysctl")
.args(["-n", "net.inet6.ip6.disabled"])
.output()
.map(|o| String::from_utf8_lossy(&o.stdout).trim() == "1")
.unwrap_or(false)
}
pub async fn interface_exists(name: &str) -> bool {
Command::new("ifconfig")
.arg(name)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.await
.map(|s| s.success())
.unwrap_or(false)
}
pub async fn delete_interface(name: &str) -> Result<(), TunError> {
run_cmd("ifconfig", &[name, "down"]).await
}
pub async fn configure_interface(name: &str, addr: Ipv6Addr, mtu: u16) -> Result<(), TunError> {
run_cmd(
"ifconfig",
&[name, "inet6", &addr.to_string(), "prefixlen", "128"],
)
.await?;
run_cmd("ifconfig", &[name, "mtu", &mtu.to_string()]).await?;
run_cmd("ifconfig", &[name, "up"]).await?;
run_cmd(
"route",
&[
"add",
"-inet6",
"-prefixlen",
"8",
"fd00::",
"-interface",
name,
],
)
.await?;
Ok(())
}
async fn run_cmd(program: &str, args: &[&str]) -> Result<(), TunError> {
let output = Command::new(program)
.args(args)
.output()
.await
.map_err(|e| TunError::Configure(format!("{} failed: {}", program, e)))?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(TunError::Configure(format!(
"{} {} failed: {}",
program,
args.join(" "),
stderr.trim()
)));
}
Ok(())
}