use std::net::Ipv4Addr; use super::{Error, IfConfiguerTrait, cidr_to_subnet_mask, run_shell_cmd}; use async_trait::async_trait; use cidr::{Ipv4Inet, Ipv6Inet}; pub struct MacIfConfiger {} #[async_trait] impl IfConfiguerTrait for MacIfConfiger { async fn add_ipv4_route( &self, name: &str, address: Ipv4Addr, cidr_prefix: u8, cost: Option, ) -> Result<(), Error> { run_shell_cmd( format!( "route -n add {} -netmask {} -interface {} -hopcount {}", address, cidr_to_subnet_mask(cidr_prefix), name, cost.unwrap_or(7) ) .as_str(), ) .await } async fn remove_ipv4_route( &self, name: &str, address: Ipv4Addr, cidr_prefix: u8, ) -> Result<(), Error> { run_shell_cmd( format!( "route -n delete {} -netmask {} -interface {}", address, cidr_to_subnet_mask(cidr_prefix), name ) .as_str(), ) .await } async fn add_ipv4_ip( &self, name: &str, address: Ipv4Addr, cidr_prefix: u8, ) -> Result<(), Error> { run_shell_cmd( format!( "ifconfig {} {:?}/{:?} {:?} up", name, address, cidr_prefix, address, ) .as_str(), ) .await } async fn set_link_status(&self, name: &str, up: bool) -> Result<(), Error> { run_shell_cmd(format!("ifconfig {} {}", name, if up { "up" } else { "down" }).as_str()) .await } async fn remove_ip(&self, name: &str, ip: Option) -> Result<(), Error> { if let Some(ip) = ip { run_shell_cmd(format!("ifconfig {} inet {} delete", name, ip.address()).as_str()).await } else { run_shell_cmd(format!("ifconfig {} inet delete", name).as_str()).await } } async fn set_mtu(&self, name: &str, mtu: u32) -> Result<(), Error> { run_shell_cmd(format!("ifconfig {} mtu {}", name, mtu).as_str()).await } async fn add_ipv6_ip( &self, name: &str, address: std::net::Ipv6Addr, cidr_prefix: u8, ) -> Result<(), Error> { run_shell_cmd(format!("ifconfig {} inet6 {}/{} add", name, address, cidr_prefix).as_str()) .await } async fn remove_ipv6(&self, name: &str, ip: Option) -> Result<(), Error> { if let Some(ip) = ip { run_shell_cmd(format!("ifconfig {} inet6 {} delete", name, ip.address()).as_str()).await } else { // Remove all IPv6 addresses is more complex on macOS, just succeed Ok(()) } } async fn add_ipv6_route( &self, name: &str, address: std::net::Ipv6Addr, cidr_prefix: u8, cost: Option, ) -> Result<(), Error> { let cmd = if let Some(cost) = cost { format!( "route -n add -inet6 {}/{} -interface {} -hopcount {}", address, cidr_prefix, name, cost ) } else { format!( "route -n add -inet6 {}/{} -interface {}", address, cidr_prefix, name ) }; run_shell_cmd(cmd.as_str()).await } async fn remove_ipv6_route( &self, name: &str, address: std::net::Ipv6Addr, cidr_prefix: u8, ) -> Result<(), Error> { run_shell_cmd( format!( "route -n delete -inet6 {}/{} -interface {}", address, cidr_prefix, name ) .as_str(), ) .await } }