summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2022-03-28 14:38:46 +0100
committerEmīls <emils@mullvad.net>2022-03-28 14:38:46 +0100
commit2d3494f3ee886f4c2ec13025833e05e05bd1feac (patch)
tree3200f43bf81e63745c283e03e4a17e303d634643 /talpid-core/src
parent077a1f91b738195ec15731bb5cb8ec9608b66db2 (diff)
parent8d156280895239741fc506f93c7eb4c0f65ecf78 (diff)
downloadmullvadvpn-2d3494f3ee886f4c2ec13025833e05e05bd1feac.tar.xz
mullvadvpn-2d3494f3ee886f4c2ec13025833e05e05bd1feac.zip
Merge branch 'use-icmp-on-macos'
Diffstat (limited to 'talpid-core/src')
-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.rs30
-rw-r--r--talpid-core/src/ping_monitor/mod.rs10
-rw-r--r--talpid-core/src/tunnel/wireguard/connectivity_check.rs4
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs2
5 files changed, 41 insertions, 37 deletions
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,