summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-09-25 14:41:31 +0100
committerEmīls Piņķis <emils@mullvad.net>2019-09-25 18:28:37 +0100
commit8a8f3fead0cb0ed86c7f399dcaf02c96a17bcdb9 (patch)
tree524e7d6bcbee39a5e93a944247ce6b8dc1fcf80c
parentc92f52de79106bc2f82dabc9944107af64ada15c (diff)
downloadmullvadvpn-8a8f3fead0cb0ed86c7f399dcaf02c96a17bcdb9.tar.xz
mullvadvpn-8a8f3fead0cb0ed86c7f399dcaf02c96a17bcdb9.zip
Duplicate tunnel fd on all platforms for wireguard-go
-rw-r--r--Cargo.lock1
-rw-r--r--mullvad-jni/Cargo.toml1
-rw-r--r--mullvad-jni/src/vpn_service_tun_provider.rs46
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs5
-rw-r--r--talpid-core/src/tunnel/wireguard/wireguard_go.rs50
5 files changed, 52 insertions, 51 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6751e21522..5203ab025e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1278,7 +1278,6 @@ dependencies = [
"jni 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mullvad-daemon 2019.8.0",
diff --git a/mullvad-jni/Cargo.toml b/mullvad-jni/Cargo.toml
index c75d9f901c..06dc9e8054 100644
--- a/mullvad-jni/Cargo.toml
+++ b/mullvad-jni/Cargo.toml
@@ -16,7 +16,6 @@ ipnetwork = "0.15"
jni = "0.12"
jsonrpc-client-core = "0.5"
lazy_static = "1"
-libc = "0.2"
log = "0.4"
log-panics = "2"
parking_lot = "0.9"
diff --git a/mullvad-jni/src/vpn_service_tun_provider.rs b/mullvad-jni/src/vpn_service_tun_provider.rs
index 49740f5e9f..f55bc466d6 100644
--- a/mullvad-jni/src/vpn_service_tun_provider.rs
+++ b/mullvad-jni/src/vpn_service_tun_provider.rs
@@ -7,14 +7,12 @@ use jni::{
};
use std::{
fs::File,
- io,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
use talpid_core::tunnel::tun_provider::{Tun, TunConfig, TunProvider};
use talpid_types::BoxedError;
-const MAX_PREPARE_TUN_ATTEMPTS: usize = 4;
/// Errors that occur while setting up VpnService tunnel.
#[derive(Debug, err_derive::Error)]
@@ -35,9 +33,6 @@ pub enum Error {
#[error(display = "Failed to create global reference to MullvadVpnService instance")]
CreateGlobalReference(#[error(cause)] jni::errors::Error),
- #[error(display = "Failed to duplicate tunnel file descriptor")]
- DuplicateTunFd(#[error(cause)] io::Error),
-
#[error(display = "Failed to find MullvadVpnService.{} method", _0)]
FindMethod(&'static str, #[error(cause)] jni::errors::Error),
@@ -95,42 +90,6 @@ impl VpnServiceTunProvider {
}
fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> {
- for retry in 1..=MAX_PREPARE_TUN_ATTEMPTS {
- let tun = self.prepare_tun(config.clone())?;
-
- match Self::duplicate_tun(tun) {
- Ok(fd) => return Ok(fd),
- Err(error) => match error.raw_os_error() {
- Some(libc::EBADF) => {
- self.active_tun = None;
-
- log::warn!(
- "VpnService returned a bad file descriptor, retrying ({}/{})",
- retry,
- MAX_PREPARE_TUN_ATTEMPTS
- );
- }
- _ => return Err(Error::DuplicateTunFd(error)),
- },
- }
- }
-
- Err(Error::DuplicateTunFd(io::Error::from_raw_os_error(
- libc::EBADF,
- )))
- }
-
- fn duplicate_tun(tun: &File) -> Result<RawFd, io::Error> {
- let tun_fd = unsafe { libc::dup(tun.as_raw_fd()) };
-
- if tun_fd >= 0 {
- Ok(tun_fd)
- } else {
- Err(io::Error::last_os_error())
- }
- }
-
- fn prepare_tun(&mut self, config: TunConfig) -> Result<&File, Error> {
if self.active_tun.is_none() || self.last_tun_config != config {
let env = self
.jvm
@@ -172,7 +131,8 @@ impl VpnServiceTunProvider {
Ok(self
.active_tun
.as_ref()
- .expect("Tunnel should be configured"))
+ .expect("Tunnel should be configured")
+ .as_raw_fd())
}
}
@@ -193,7 +153,7 @@ impl TunProvider for VpnServiceTunProvider {
fn create_tun_if_closed(&mut self) -> Result<(), BoxedError> {
if self.active_tun.is_none() {
- self.prepare_tun(self.last_tun_config.clone())
+ self.get_tun_fd(self.last_tun_config.clone())
.map_err(BoxedError::new)?;
}
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 {