mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-09-03 17:45:44 +00:00
use netlink instead of shell cmd to config ip (#593)
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
mod darwin;
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
mod netlink;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows;
|
||||
|
||||
mod route;
|
||||
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use tokio::process::Command;
|
||||
|
||||
use super::error::Error;
|
||||
|
||||
#[async_trait]
|
||||
pub trait IfConfiguerTrait: Send + Sync {
|
||||
async fn add_ipv4_route(
|
||||
&self,
|
||||
_name: &str,
|
||||
_address: Ipv4Addr,
|
||||
_cidr_prefix: u8,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn remove_ipv4_route(
|
||||
&self,
|
||||
_name: &str,
|
||||
_address: Ipv4Addr,
|
||||
_cidr_prefix: u8,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn add_ipv4_ip(
|
||||
&self,
|
||||
_name: &str,
|
||||
_address: Ipv4Addr,
|
||||
_cidr_prefix: u8,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn set_link_status(&self, _name: &str, _up: bool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn remove_ip(&self, _name: &str, _ip: Option<Ipv4Addr>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn wait_interface_show(&self, _name: &str) -> Result<(), Error> {
|
||||
return Ok(());
|
||||
}
|
||||
async fn set_mtu(&self, _name: &str, _mtu: u32) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn cidr_to_subnet_mask(prefix_length: u8) -> Ipv4Addr {
|
||||
if prefix_length > 32 {
|
||||
panic!("Invalid CIDR prefix length");
|
||||
}
|
||||
|
||||
let subnet_mask: u32 = (!0u32)
|
||||
.checked_shl(32 - u32::from(prefix_length))
|
||||
.unwrap_or(0);
|
||||
Ipv4Addr::new(
|
||||
((subnet_mask >> 24) & 0xFF) as u8,
|
||||
((subnet_mask >> 16) & 0xFF) as u8,
|
||||
((subnet_mask >> 8) & 0xFF) as u8,
|
||||
(subnet_mask & 0xFF) as u8,
|
||||
)
|
||||
}
|
||||
|
||||
async fn run_shell_cmd(cmd: &str) -> Result<(), Error> {
|
||||
let cmd_out: std::process::Output;
|
||||
let stdout: String;
|
||||
let stderr: String;
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
cmd_out = Command::new("cmd")
|
||||
.stdin(std::process::Stdio::null())
|
||||
.arg("/C")
|
||||
.arg(cmd)
|
||||
.creation_flags(CREATE_NO_WINDOW)
|
||||
.output()
|
||||
.await?;
|
||||
stdout = crate::utils::utf8_or_gbk_to_string(cmd_out.stdout.as_slice());
|
||||
stderr = crate::utils::utf8_or_gbk_to_string(cmd_out.stderr.as_slice());
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
cmd_out = Command::new("sh").arg("-c").arg(cmd).output().await?;
|
||||
stdout = String::from_utf8_lossy(cmd_out.stdout.as_slice()).to_string();
|
||||
stderr = String::from_utf8_lossy(cmd_out.stderr.as_slice()).to_string();
|
||||
};
|
||||
|
||||
let ec = cmd_out.status.code();
|
||||
let succ = cmd_out.status.success();
|
||||
tracing::info!(?cmd, ?ec, ?succ, ?stdout, ?stderr, "run shell cmd");
|
||||
|
||||
if !cmd_out.status.success() {
|
||||
return Err(Error::ShellCommandError(stdout + &stderr));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct DummyIfConfiger {}
|
||||
#[async_trait]
|
||||
impl IfConfiguerTrait for DummyIfConfiger {}
|
||||
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
pub type IfConfiger = netlink::NetlinkIfConfiger;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
pub type IfConfiger = darwin::MacIfConfiger;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub type IfConfiger = windows::WindowsIfConfiger;
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_os = "windows",
|
||||
target_os = "freebsd",
|
||||
)))]
|
||||
pub type IfConfiger = DummyIfConfiger;
|
||||
Reference in New Issue
Block a user