mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-09-02 17:15:43 +00:00
fix: preserve macos shared tun ipv4 aliases
This commit is contained in:
@@ -1,10 +1,42 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::{
|
||||||
|
collections::{BTreeMap, BTreeSet},
|
||||||
|
net::Ipv4Addr,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{Error, IfConfiguerTrait, cidr_to_subnet_mask, run_shell_cmd};
|
use super::{Error, IfConfiguerTrait, cidr_to_subnet_mask, run_shell_cmd};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use cidr::{Ipv4Inet, Ipv6Inet};
|
use cidr::{Ipv4Inet, Ipv6Inet};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MacIfConfiger {
|
||||||
|
configured_ipv4: Arc<Mutex<BTreeMap<String, BTreeSet<Ipv4Inet>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MacIfConfiger {
|
||||||
|
fn build_add_ipv4_cmd(name: &str, addr: Ipv4Inet, has_configured_ipv4: bool) -> String {
|
||||||
|
let address = addr.address();
|
||||||
|
if has_configured_ipv4 {
|
||||||
|
format!(
|
||||||
|
"ifconfig {} alias {:?} {:?} netmask {}",
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
address,
|
||||||
|
cidr_to_subnet_mask(addr.network_length())
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"ifconfig {} {:?}/{:?} {:?} up",
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
addr.network_length(),
|
||||||
|
address,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MacIfConfiger {}
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl IfConfiguerTrait for MacIfConfiger {
|
impl IfConfiguerTrait for MacIfConfiger {
|
||||||
async fn add_ipv4_route(
|
async fn add_ipv4_route(
|
||||||
@@ -51,14 +83,23 @@ impl IfConfiguerTrait for MacIfConfiger {
|
|||||||
address: Ipv4Addr,
|
address: Ipv4Addr,
|
||||||
cidr_prefix: u8,
|
cidr_prefix: u8,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
run_shell_cmd(
|
let addr = Ipv4Inet::new(address, cidr_prefix).map_err(|err| {
|
||||||
format!(
|
Error::RouteError(Some(format!(
|
||||||
"ifconfig {} {:?}/{:?} {:?} up",
|
"invalid IPv4 address {address}/{cidr_prefix}: {err:?}"
|
||||||
name, address, cidr_prefix, address,
|
)))
|
||||||
)
|
})?;
|
||||||
.as_str(),
|
let mut configured_ipv4 = self.configured_ipv4.lock().await;
|
||||||
)
|
let has_configured_ipv4 = configured_ipv4
|
||||||
.await
|
.get(name)
|
||||||
|
.is_some_and(|addresses| !addresses.is_empty());
|
||||||
|
let cmd = Self::build_add_ipv4_cmd(name, addr, has_configured_ipv4);
|
||||||
|
|
||||||
|
run_shell_cmd(cmd.as_str()).await?;
|
||||||
|
configured_ipv4
|
||||||
|
.entry(name.to_owned())
|
||||||
|
.or_default()
|
||||||
|
.insert(addr);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_link_status(&self, name: &str, up: bool) -> Result<(), Error> {
|
async fn set_link_status(&self, name: &str, up: bool) -> Result<(), Error> {
|
||||||
@@ -67,12 +108,34 @@ impl IfConfiguerTrait for MacIfConfiger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_ip(&self, name: &str, ip: Option<Ipv4Inet>) -> Result<(), Error> {
|
async fn remove_ip(&self, name: &str, ip: Option<Ipv4Inet>) -> Result<(), Error> {
|
||||||
|
let mut configured_ipv4 = self.configured_ipv4.lock().await;
|
||||||
if let Some(ip) = ip {
|
if let Some(ip) = ip {
|
||||||
run_shell_cmd(format!("ifconfig {} inet {} delete", name, ip.address()).as_str()).await
|
run_shell_cmd(format!("ifconfig {} inet {} delete", name, ip.address()).as_str())
|
||||||
} else {
|
.await?;
|
||||||
run_shell_cmd(format!("ifconfig {} inet delete", name).as_str()).await
|
if let Some(addresses) = configured_ipv4.get_mut(name) {
|
||||||
|
addresses.remove(&ip);
|
||||||
|
if addresses.is_empty() {
|
||||||
|
configured_ipv4.remove(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(addresses) = configured_ipv4.get(name).cloned() {
|
||||||
|
for ip in addresses {
|
||||||
|
run_shell_cmd(
|
||||||
|
format!("ifconfig {} inet {} delete", name, ip.address()).as_str(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
if let Some(addresses) = configured_ipv4.get_mut(name) {
|
||||||
|
addresses.remove(&ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configured_ipv4.remove(name);
|
||||||
|
} else {
|
||||||
|
run_shell_cmd(format!("ifconfig {} inet delete", name).as_str()).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn set_mtu(&self, name: &str, mtu: u32) -> Result<(), Error> {
|
async fn set_mtu(&self, name: &str, mtu: u32) -> Result<(), Error> {
|
||||||
run_shell_cmd(format!("ifconfig {} mtu {}", name, mtu).as_str()).await
|
run_shell_cmd(format!("ifconfig {} mtu {}", name, mtu).as_str()).await
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ async fn run_shell_cmd(cmd: &str) -> Result<(), Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct DummyIfConfiger {}
|
pub struct DummyIfConfiger {}
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl IfConfiguerTrait for DummyIfConfiger {}
|
impl IfConfiguerTrait for DummyIfConfiger {}
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ impl From<RouteMessage> for Route {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct NetlinkIfConfiger {}
|
pub struct NetlinkIfConfiger {}
|
||||||
|
|
||||||
impl NetlinkIfConfiger {
|
impl NetlinkIfConfiger {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use winreg::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{Error, IfConfiguerTrait};
|
use super::{Error, IfConfiguerTrait};
|
||||||
|
#[derive(Default)]
|
||||||
pub struct WindowsIfConfiger {}
|
pub struct WindowsIfConfiger {}
|
||||||
|
|
||||||
fn format_win_error(error: u32) -> String {
|
fn format_win_error(error: u32) -> String {
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ impl VirtualNic {
|
|||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
ifname: None,
|
ifname: None,
|
||||||
ifcfg: Box::new(IfConfiger {}),
|
ifcfg: Box::new(IfConfiger::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -832,7 +832,7 @@ impl VirtualNic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ifcfg(&self) -> IfConfiger {
|
pub fn get_ifcfg(&self) -> IfConfiger {
|
||||||
IfConfiger {}
|
IfConfiger::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user