diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2019-09-25 14:41:31 +0100 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2019-09-25 18:28:37 +0100 |
| commit | 8a8f3fead0cb0ed86c7f399dcaf02c96a17bcdb9 (patch) | |
| tree | 524e7d6bcbee39a5e93a944247ce6b8dc1fcf80c /talpid-core/src | |
| parent | c92f52de79106bc2f82dabc9944107af64ada15c (diff) | |
| download | mullvadvpn-8a8f3fead0cb0ed86c7f399dcaf02c96a17bcdb9.tar.xz mullvadvpn-8a8f3fead0cb0ed86c7f399dcaf02c96a17bcdb9.zip | |
Duplicate tunnel fd on all platforms for wireguard-go
Diffstat (limited to 'talpid-core/src')
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/mod.rs | 5 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_go.rs | 50 |
2 files changed, 49 insertions, 6 deletions
diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs index 1eecfe8f85..0721a2ead7 100644 --- a/talpid-core/src/tunnel/wireguard/mod.rs +++ b/talpid-core/src/tunnel/wireguard/mod.rs @@ -60,6 +60,11 @@ pub enum Error { #[error(display = "Failed to configure Wireguard sockets to bypass the tunnel")] BypassError(#[error(cause)] BoxedError), + /// Failed to duplicate file descriptors for logging on wireguard-go + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))] + #[error(display = "Failed to configure Wireguard sockets to bypass the tunnel")] + FdDuplicationError(#[error(cause)] nix::Error), + /// Pinging timed out. #[error(display = "Ping timed out")] PingTimeoutError, diff --git a/talpid-core/src/tunnel/wireguard/wireguard_go.rs b/talpid-core/src/tunnel/wireguard/wireguard_go.rs index a771bfae4a..ff45685191 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_go.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_go.rs @@ -1,10 +1,18 @@ use super::{Config, Error, Result, Tunnel}; use crate::tunnel::tun_provider::{Tun, TunConfig, TunProvider}; use ipnetwork::IpNetwork; -use std::{ffi::CString, fs, net::IpAddr, os::unix::io::AsRawFd, path::Path}; +use std::{ + ffi::CString, + fs, + net::IpAddr, + os::unix::io::{AsRawFd, RawFd}, + path::Path, +}; #[cfg(target_os = "android")] use talpid_types::BoxedError; +const MAX_PREPARE_TUN_ATTEMPTS: usize = 4; + pub struct WgGoTunnel { interface_name: String, handle: Option<i32>, @@ -22,10 +30,7 @@ impl WgGoTunnel { routes: impl Iterator<Item = IpNetwork>, ) -> Result<Self> { #[cfg_attr(not(target_os = "android"), allow(unused_mut))] - let mut tunnel_device = tun_provider - .get_tun(Self::create_tunnel_config(config, routes)) - .map_err(Error::SetupTunnelDeviceError)?; - + let (mut tunnel_device, tunnel_fd) = Self::get_tunnel(tun_provider, config, routes)?; let interface_name: String = tunnel_device.interface_name().to_string(); let log_file = prepare_log_file(log_path)?; @@ -33,12 +38,13 @@ impl WgGoTunnel { let iface_name = CString::new(interface_name.as_bytes()).map_err(Error::InterfaceNameError)?; + let handle = unsafe { wgTurnOnWithFd( iface_name.as_ptr() as *const i8, config.mtu as isize, wg_config_str.as_ptr() as *const i8, - tunnel_device.as_raw_fd(), + tunnel_fd, log_file.as_raw_fd(), WG_GO_LOG_DEBUG, ) @@ -99,6 +105,38 @@ impl WgGoTunnel { } Ok(()) } + + fn get_tunnel( + tun_provider: &mut dyn TunProvider, + config: &Config, + routes: impl Iterator<Item = IpNetwork>, + ) -> Result<(Box<dyn Tun>, RawFd)> { + let tunnel_config = Self::create_tunnel_config(config, routes); + for _ in 1..=MAX_PREPARE_TUN_ATTEMPTS { + let tunnel_device = tun_provider + .get_tun(tunnel_config.clone()) + .map_err(Error::SetupTunnelDeviceError)?; + + match nix::unistd::dup(tunnel_device.as_raw_fd()) { + Ok(fd) => { + return Ok((tunnel_device, fd)); + } + #[cfg(not(target_os = "macos"))] + Err(nix::Error::Sys(nix::errno::Errno::EBADFD)) => continue, + #[cfg(target_os = "macos")] + Err(nix::Error::Sys(nix::errno::Errno::EBADF)) => continue, + Err(error) => return Err(Error::FdDuplicationError(error)), + } + } + #[cfg(not(target_os = "macos"))] + return Err(Error::FdDuplicationError(nix::Error::Sys( + nix::errno::Errno::EBADFD, + ))); + #[cfg(target_os = "macos")] + return Err(Error::FdDuplicationError(nix::Error::Sys( + nix::errno::Errno::EBADF, + ))); + } } impl Drop for WgGoTunnel { |
