diff options
| author | Emīls <emils@mullvad.net> | 2022-03-28 14:38:46 +0100 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2022-03-28 14:38:46 +0100 |
| commit | 2d3494f3ee886f4c2ec13025833e05e05bd1feac (patch) | |
| tree | 3200f43bf81e63745c283e03e4a17e303d634643 | |
| parent | 077a1f91b738195ec15731bb5cb8ec9608b66db2 (diff) | |
| parent | 8d156280895239741fc506f93c7eb4c0f65ecf78 (diff) | |
| download | mullvadvpn-2d3494f3ee886f4c2ec13025833e05e05bd1feac.tar.xz mullvadvpn-2d3494f3ee886f4c2ec13025833e05e05bd1feac.zip | |
Merge branch 'use-icmp-on-macos'
| -rw-r--r-- | talpid-core/Cargo.toml | 8 | ||||
| -rw-r--r-- | talpid-core/src/ping_monitor/android.rs (renamed from talpid-core/src/ping_monitor/unix.rs) | 32 | ||||
| -rw-r--r-- | talpid-core/src/ping_monitor/icmp.rs | 30 | ||||
| -rw-r--r-- | talpid-core/src/ping_monitor/mod.rs | 10 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/connectivity_check.rs | 4 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/mod.rs | 2 |
6 files changed, 44 insertions, 42 deletions
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index d0cf685753..7ff3b8721f 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -32,9 +32,11 @@ tokio = { version = "1.8", features = ["process", "rt-multi-thread", "fs"] } tokio-stream = { version = "0.1", features = ["io-util"] } rand = "0.7" tunnel-obfuscation = { path = "../tunnel-obfuscation" } -socket2 = { version = "0.4.2", features = ["all"] } [target.'cfg(not(target_os="android"))'.dependencies] +byteorder = "1" +internet-checksum = "0.2" +socket2 = { version = "0.4.2", features = ["all"] } parity-tokio-ipc = "0.9" triggered = "0.1.1" tonic = "0.5" @@ -57,13 +59,11 @@ netlink-packet-utils = "0.4" netlink-packet-route = "0.8" netlink-proto = "0.7" netlink-sys = "0.7" -byteorder = "1" nftnl = { version = "0.6.2", features = ["nftnl-1-1-0"] } mnl = { version = "0.2.2", features = ["mnl-1-0-4"] } which = { version = "4.0", default-features = false } tun = "0.5.1" talpid-dbus = { path = "../talpid-dbus" } -internet-checksum = "0.2" [target.'cfg(target_os = "macos")'.dependencies] @@ -75,8 +75,6 @@ subslice = "0.2" [target.'cfg(windows)'.dependencies] -byteorder = "1" -internet-checksum = "0.2" widestring = "0.5" winreg = { version = "0.7", features = ["transactions"] } winapi = { version = "0.3.6", features = ["combaseapi", "handleapi", "ifdef", "libloaderapi", "netioapi", "psapi", "stringapiset", "synchapi", "tlhelp32", "winbase", "winioctl", "winuser", "dbt"] } diff --git a/talpid-core/src/ping_monitor/unix.rs b/talpid-core/src/ping_monitor/android.rs index b93678a22b..9263dbac79 100644 --- a/talpid-core/src/ping_monitor/unix.rs +++ b/talpid-core/src/ping_monitor/android.rs @@ -15,17 +15,15 @@ pub enum Error { /// A pinger that sends ICMP requests without waiting for responses pub struct Pinger { addr: Ipv4Addr, - interface_name: String, processes: Vec<duct::Handle>, } impl Pinger { /// Creates a new pinger that will send ICMP requests only through the specified interface - pub fn new(addr: Ipv4Addr, interface_name: String) -> Result<Self, Error> { + pub fn new(addr: Ipv4Addr) -> Result<Self, Error> { Ok(Self { processes: vec![], addr, - interface_name, }) } @@ -45,7 +43,7 @@ impl super::Pinger for Pinger { fn send_icmp(&mut self) -> Result<(), Error> { self.try_deplete_process_list(); - let cmd = ping_cmd(self.addr, 1, &self.interface_name); + let cmd = ping_cmd(self.addr, 1); let handle = cmd.start().map_err(Error::PingError)?; self.processes.push(handle); Ok(()) @@ -77,32 +75,10 @@ impl Drop for Pinger { } } -fn ping_cmd(ip: Ipv4Addr, timeout_secs: u16, interface: &str) -> duct::Expression { - let mut args = vec!["-n", "-i", "1"]; - - let timeout_flag = if cfg!(target_os = "linux") || cfg!(target_os = "android") { - "-w" - } else { - "-t" - }; +fn ping_cmd(ip: Ipv4Addr, timeout_secs: u16) -> duct::Expression { let timeout_secs = timeout_secs.to_string(); - - args.extend_from_slice(&[timeout_flag, &timeout_secs]); - - let interface_flag = if cfg!(target_os = "linux") { - Some("-I") - } else if cfg!(target_os = "macos") { - Some("-b") - } else { - None - }; - - if let Some(interface_flag) = interface_flag { - args.extend_from_slice(&[interface_flag, interface]); - } - let ip = ip.to_string(); - args.push(&ip); + let args = ["-n", "-i", "1", "-w", &timeout_secs, &ip]; duct::cmd("ping", args) .stdin_null() diff --git a/talpid-core/src/ping_monitor/icmp.rs b/talpid-core/src/ping_monitor/icmp.rs index a25a31e1b2..67f5b70cb5 100644 --- a/talpid-core/src/ping_monitor/icmp.rs +++ b/talpid-core/src/ping_monitor/icmp.rs @@ -30,6 +30,16 @@ pub enum Error { #[error(display = "Failed to write to socket")] WriteError(#[error(source)] io::Error), + /// Failed to get device index + #[cfg(target_os = "macos")] + #[error(display = "Failed to obtain device index")] + DeviceIdxError(nix::errno::Errno), + + /// Failed to bind socket to device by index + #[cfg(target_os = "macos")] + #[error(display = "Failed to bind socket to device by index")] + BindSocketByDeviceError(io::Error), + /// ICMP buffer too small #[error(display = "ICMP message buffer too small")] BufferTooSmall, @@ -49,7 +59,10 @@ pub struct Pinger { } impl Pinger { - pub fn new(addr: Ipv4Addr, #[cfg(target_os = "linux")] interface_name: String) -> Result<Self> { + pub fn new( + addr: Ipv4Addr, + #[cfg(not(target_os = "windows"))] interface_name: String, + ) -> Result<Self> { let addr = SocketAddr::new(addr.into(), 0); let sock = Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::ICMPV4)) .map_err(Error::OpenError)?; @@ -59,6 +72,9 @@ impl Pinger { sock.bind_device(Some(interface_name.as_bytes())) .map_err(Error::SocketOptError)?; + #[cfg(target_os = "macos")] + Self::set_device_index(&sock, &interface_name)?; + Ok(Self { sock, addr, @@ -67,6 +83,18 @@ impl Pinger { }) } + #[cfg(target_os = "macos")] + fn set_device_index(socket: &Socket, interface_name: &str) -> Result<()> { + let index = nix::net::if_::if_nametoindex(interface_name).map_err(Error::DeviceIdxError)?; + // Asserting that `index` is non-zero since otherwise `if_nametoindex` would have return + // an error + socket + .bind_device_by_index(std::num::NonZeroU32::new(index)) + .map_err(Error::BindSocketByDeviceError)?; + + Ok(()) + } + fn send_ping_request(&mut self, message: &[u8], destination: SocketAddr) -> Result<()> { let mut tries = 0; let mut result = Ok(()); diff --git a/talpid-core/src/ping_monitor/mod.rs b/talpid-core/src/ping_monitor/mod.rs index e978bd38b2..9b105a50dc 100644 --- a/talpid-core/src/ping_monitor/mod.rs +++ b/talpid-core/src/ping_monitor/mod.rs @@ -1,8 +1,8 @@ -#[cfg(any(target_os = "android", target_os = "macos"))] -#[path = "unix.rs"] +#[cfg(any(target_os = "android"))] +#[path = "android.rs"] mod imp; -#[cfg(any(target_os = "windows", target_os = "linux"))] +#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] #[path = "icmp.rs"] mod imp; @@ -19,11 +19,11 @@ pub trait Pinger: Send { /// Create a new pinger pub fn new_pinger( addr: std::net::Ipv4Addr, - #[cfg(not(target_os = "windows"))] interface_name: String, + #[cfg(any(target_os = "linux", target_os = "macos"))] interface_name: String, ) -> Result<Box<dyn Pinger>, Error> { Ok(Box::new(imp::Pinger::new( addr, - #[cfg(not(target_os = "windows"))] + #[cfg(any(target_os = "linux", target_os = "macos"))] interface_name, )?)) } diff --git a/talpid-core/src/tunnel/wireguard/connectivity_check.rs b/talpid-core/src/tunnel/wireguard/connectivity_check.rs index 162fb248a3..d6bb61a5fc 100644 --- a/talpid-core/src/tunnel/wireguard/connectivity_check.rs +++ b/talpid-core/src/tunnel/wireguard/connectivity_check.rs @@ -81,13 +81,13 @@ pub struct ConnectivityMonitor { impl ConnectivityMonitor { pub(super) fn new( addr: Ipv4Addr, - #[cfg(not(target_os = "windows"))] interface: String, + #[cfg(any(target_os = "macos", target_os = "linux"))] interface: String, tunnel_handle: Weak<Mutex<Option<Box<dyn Tunnel>>>>, close_receiver: mpsc::Receiver<()>, ) -> Result<Self, Error> { let pinger = new_pinger( addr, - #[cfg(not(target_os = "windows"))] + #[cfg(any(target_os = "macos", target_os = "linux"))] interface, ) .map_err(Error::PingError)?; diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs index 817ad74eea..80c8e2ae8e 100644 --- a/talpid-core/src/tunnel/wireguard/mod.rs +++ b/talpid-core/src/tunnel/wireguard/mod.rs @@ -229,7 +229,7 @@ impl WireguardMonitor { let gateway = config.ipv4_gateway; let mut connectivity_monitor = connectivity_check::ConnectivityMonitor::new( gateway, - #[cfg(not(target_os = "windows"))] + #[cfg(any(target_os = "macos", target_os = "linux"))] iface_name.clone(), Arc::downgrade(&monitor.tunnel), pinger_rx, |
