summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-05-28 13:44:19 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-05-28 13:44:19 -0300
commit1093f3e65ea020201dcba918a75e88a1af26bceb (patch)
tree6cb925de4420fd02a63e402b5cfb4b23c4fa49ca
parentec6674bd044b866f388d6e68f8380e669c067193 (diff)
parent95a6729d2404536a3ea8ce2e5358c7710d4b43a1 (diff)
downloadmullvadvpn-1093f3e65ea020201dcba918a75e88a1af26bceb.tar.xz
mullvadvpn-1093f3e65ea020201dcba918a75e88a1af26bceb.zip
Merge branch 'tun-provider'
-rw-r--r--Cargo.lock2
-rw-r--r--mullvad-daemon/src/lib.rs8
-rw-r--r--mullvad-jni/Cargo.toml1
-rw-r--r--mullvad-jni/src/lib.rs4
-rw-r--r--talpid-core/Cargo.toml1
-rw-r--r--talpid-core/src/tunnel/mod.rs9
-rw-r--r--talpid-core/src/tunnel/tun_provider/mod.rs62
-rw-r--r--talpid-core/src/tunnel/tun_provider/stub.rs17
-rw-r--r--talpid-core/src/tunnel/tun_provider/unix.rs54
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs8
-rw-r--r--talpid-core/src/tunnel/wireguard/wireguard_go.rs26
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs15
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs9
-rw-r--r--talpid-types/src/lib.rs29
14 files changed, 221 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ccf2d2491f..d6232ef395 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1175,6 +1175,7 @@ dependencies = [
"mullvad-paths 0.1.0",
"mullvad-types 0.1.0",
"parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "talpid-core 0.1.0",
"talpid-types 0.1.0",
]
@@ -2094,6 +2095,7 @@ name = "talpid-core"
version = "0.1.0"
dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"duct 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 1d5851d94f..88cd834969 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -47,6 +47,7 @@ use mullvad_types::{
use std::{io, mem, path::PathBuf, sync::mpsc, thread, time::Duration};
use talpid_core::{
mpsc::IntoSender,
+ tunnel::tun_provider::{PlatformTunProvider, TunProvider},
tunnel_state_machine::{self, TunnelCommand, TunnelParametersGenerator},
};
use talpid_types::{
@@ -233,6 +234,7 @@ impl Daemon<ManagementInterfaceEventBroadcaster> {
tx,
rx,
management_interface_broadcaster,
+ PlatformTunProvider::default(),
log_dir,
resource_dir,
cache_dir,
@@ -278,8 +280,9 @@ impl<L> Daemon<L>
where
L: EventListener + Clone + Send + 'static,
{
- pub fn start_with_event_listener(
+ pub fn start_with_event_listener_and_tun_provider(
event_listener: L,
+ tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: PathBuf,
@@ -291,6 +294,7 @@ where
tx,
rx,
event_listener,
+ tun_provider,
log_dir,
resource_dir,
cache_dir,
@@ -302,6 +306,7 @@ where
internal_event_tx: mpsc::Sender<InternalDaemonEvent>,
internal_event_rx: mpsc::Receiver<InternalDaemonEvent>,
event_listener: L,
+ tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: PathBuf,
@@ -345,6 +350,7 @@ where
settings.get_allow_lan(),
settings.get_block_when_disconnected(),
tunnel_parameters_generator,
+ tun_provider,
log_dir,
resource_dir,
cache_dir.clone(),
diff --git a/mullvad-jni/Cargo.toml b/mullvad-jni/Cargo.toml
index bfb4cd7ede..9b1482f315 100644
--- a/mullvad-jni/Cargo.toml
+++ b/mullvad-jni/Cargo.toml
@@ -22,4 +22,5 @@ parking_lot = "0.8"
mullvad-daemon = { path = "../mullvad-daemon" }
mullvad-paths = { path = "../mullvad-paths" }
mullvad-types = { path = "../mullvad-types" }
+talpid-core = { path = "../talpid-core" }
talpid-types = { path = "../talpid-types" }
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 9e1b0c3b38..b35ec3efbf 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -19,6 +19,7 @@ use lazy_static::lazy_static;
use mullvad_daemon::{logging, version, Daemon, DaemonCommandSender};
use parking_lot::{Mutex, RwLock};
use std::{collections::HashMap, path::PathBuf, sync::mpsc, thread};
+use talpid_core::tunnel::tun_provider::StubTunProvider;
use talpid_types::ErrorExt;
const LOG_FILENAME: &str = "daemon.log";
@@ -152,8 +153,9 @@ fn create_daemon(
let resource_dir = mullvad_paths::get_resource_dir();
let cache_dir = mullvad_paths::cache_dir().map_err(Error::GetCacheDir)?;
- let daemon = Daemon::start_with_event_listener(
+ let daemon = Daemon::start_with_event_listener_and_tun_provider(
listener,
+ StubTunProvider,
Some(log_dir),
resource_dir,
cache_dir,
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index 833b2cb9b6..2402bd2e52 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
[dependencies]
atty = "0.2"
+cfg-if = "0.1"
derive_more = "0.14"
duct = "0.12"
err-derive = "0.1.5"
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index 4d27be32ec..68f6c8ed63 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -1,3 +1,4 @@
+use self::tun_provider::TunProvider;
use crate::logging;
#[cfg(not(target_os = "android"))]
use std::collections::HashMap;
@@ -19,6 +20,9 @@ pub mod openvpn;
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub mod wireguard;
+/// A module for low level platform specific tunnel device management.
+pub mod tun_provider;
+
const OPENVPN_LOG_FILENAME: &str = "openvpn.log";
const WIREGUARD_LOG_FILENAME: &str = "wireguard.log";
@@ -141,6 +145,7 @@ impl TunnelMonitor {
log_dir: &Option<PathBuf>,
resource_dir: &Path,
on_event: L,
+ tun_provider: &dyn TunProvider,
) -> Result<Self>
where
L: Fn(TunnelEvent) + Send + Clone + Sync + 'static,
@@ -155,7 +160,7 @@ impl TunnelMonitor {
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
TunnelParameters::Wireguard(config) => {
- Self::start_wireguard_tunnel(&config, log_file, on_event)
+ Self::start_wireguard_tunnel(&config, log_file, on_event, tun_provider)
}
#[cfg(target_os = "android")]
TunnelParameters::OpenVpn(_) => Err(Error::UnsupportedPlatform),
@@ -169,6 +174,7 @@ impl TunnelMonitor {
params: &wireguard_types::TunnelParameters,
log: Option<PathBuf>,
on_event: L,
+ tun_provider: &dyn TunProvider,
) -> Result<Self>
where
L: Fn(TunnelEvent) + Send + Sync + Clone + 'static,
@@ -178,6 +184,7 @@ impl TunnelMonitor {
&config,
log.as_ref().map(|p| p.as_path()),
on_event,
+ tun_provider,
)?;
Ok(TunnelMonitor {
monitor: InternalTunnelMonitor::Wireguard(monitor),
diff --git a/talpid-core/src/tunnel/tun_provider/mod.rs b/talpid-core/src/tunnel/tun_provider/mod.rs
new file mode 100644
index 0000000000..43020114c7
--- /dev/null
+++ b/talpid-core/src/tunnel/tun_provider/mod.rs
@@ -0,0 +1,62 @@
+use cfg_if::cfg_if;
+use std::net::IpAddr;
+#[cfg(unix)]
+use std::os::unix::io::AsRawFd;
+use talpid_types::BoxedError;
+
+cfg_if! {
+ if #[cfg(all(unix, not(target_os = "android")))] {
+ #[path = "unix.rs"]
+ mod imp;
+ use self::imp::UnixTunProvider;
+
+ /// Default implementation of `TunProvider` for Unix based operating systems.
+ ///
+ /// Android has a different mechanism to obtain tunnel interfaces, so it is not supported
+ /// here.
+ pub type PlatformTunProvider = UnixTunProvider;
+ } else {
+ mod stub;
+ pub use self::stub::StubTunProvider;
+
+ /// Default stub implementation of `TunProvider` for Android and Windows.
+ pub type PlatformTunProvider = StubTunProvider;
+ }
+}
+
+/// Generic tunnel device.
+///
+/// Must be associated with a platform specific file descriptor representing the device.
+#[cfg(unix)]
+pub trait Tun: AsRawFd + Send {
+ /// Retrieve the tunnel interface name.
+ fn interface_name(&self) -> &str;
+}
+
+/// Stub tunnel device.
+#[cfg(windows)]
+pub trait Tun: Send {
+ /// Retrieve the tunnel interface name.
+ fn interface_name(&self) -> &str;
+}
+
+/// Factory of tunnel devices.
+pub trait TunProvider: Send + 'static {
+ /// Create a tunnel device using the provided configuration.
+ fn create_tun(&self, config: TunConfig) -> Result<Box<dyn Tun>, BoxedError>;
+}
+
+/// Configuration for creating a tunnel device.
+pub struct TunConfig {
+ /// IP addresses for the tunnel interface.
+ pub addresses: Vec<IpAddr>,
+}
+
+impl TunConfig {
+ /// Create a new tunnel device configuration using the specified tunnel addresses.
+ pub fn new(addresses: impl IntoIterator<Item = IpAddr>) -> Self {
+ TunConfig {
+ addresses: addresses.into_iter().collect(),
+ }
+ }
+}
diff --git a/talpid-core/src/tunnel/tun_provider/stub.rs b/talpid-core/src/tunnel/tun_provider/stub.rs
new file mode 100644
index 0000000000..0b94b426bf
--- /dev/null
+++ b/talpid-core/src/tunnel/tun_provider/stub.rs
@@ -0,0 +1,17 @@
+use super::{Tun, TunConfig, TunProvider};
+use talpid_types::BoxedError;
+
+/// Factory stub of tunnel devices.
+pub struct StubTunProvider;
+
+impl Default for StubTunProvider {
+ fn default() -> Self {
+ StubTunProvider
+ }
+}
+
+impl TunProvider for StubTunProvider {
+ fn create_tun(&self, _: TunConfig) -> Result<Box<dyn Tun>, BoxedError> {
+ unimplemented!();
+ }
+}
diff --git a/talpid-core/src/tunnel/tun_provider/unix.rs b/talpid-core/src/tunnel/tun_provider/unix.rs
new file mode 100644
index 0000000000..c0715a81bd
--- /dev/null
+++ b/talpid-core/src/tunnel/tun_provider/unix.rs
@@ -0,0 +1,54 @@
+use super::{Tun, TunConfig, TunProvider};
+use crate::network_interface::{self, NetworkInterface, TunnelDevice};
+use std::net::IpAddr;
+use talpid_types::BoxedError;
+
+/// Errors that can occur while setting up a tunnel device.
+#[derive(Debug, err_derive::Error)]
+pub enum Error {
+ /// Failure to create a tunnel device.
+ #[error(display = "Failed to create a tunnel device")]
+ CreateTunnelDevice(#[cause] network_interface::Error),
+
+ /// Failure to set a tunnel device IP address.
+ #[error(display = "Failed to set tunnel IP address: {}", _0)]
+ SetIpAddr(IpAddr, #[cause] network_interface::Error),
+
+ /// Failure to set the tunnel device as up.
+ #[error(display = "Failed to set the tunnel device as up")]
+ SetUp(#[cause] network_interface::Error),
+}
+
+/// Factory of tunnel devices on Unix systems.
+pub struct UnixTunProvider;
+
+impl Default for UnixTunProvider {
+ fn default() -> Self {
+ UnixTunProvider
+ }
+}
+
+impl TunProvider for UnixTunProvider {
+ fn create_tun(&self, config: TunConfig) -> Result<Box<dyn Tun>, BoxedError> {
+ let mut tunnel_device = TunnelDevice::new()
+ .map_err(|cause| BoxedError::new(Error::CreateTunnelDevice(cause)))?;
+
+ for ip in config.addresses.iter() {
+ tunnel_device
+ .set_ip(*ip)
+ .map_err(|cause| BoxedError::new(Error::SetIpAddr(*ip, cause)))?;
+ }
+
+ tunnel_device
+ .set_up(true)
+ .map_err(|cause| BoxedError::new(Error::SetUp(cause)))?;
+
+ Ok(Box::new(tunnel_device))
+ }
+}
+
+impl Tun for TunnelDevice {
+ fn interface_name(&self) -> &str {
+ self.get_name()
+ }
+}
diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs
index 24805f7dbe..05fecdb29f 100644
--- a/talpid-core/src/tunnel/wireguard/mod.rs
+++ b/talpid-core/src/tunnel/wireguard/mod.rs
@@ -1,9 +1,10 @@
#![allow(missing_docs)]
use self::config::Config;
-use super::{TunnelEvent, TunnelMetadata};
+use super::{tun_provider::TunProvider, TunnelEvent, TunnelMetadata};
use crate::routing;
use std::{collections::HashMap, io, path::Path, sync::mpsc};
+use talpid_types::BoxedError;
pub mod config;
mod ping_monitor;
@@ -21,7 +22,7 @@ pub type Result<T> = std::result::Result<T, Error>;
pub enum Error {
/// Failed to setup a tunnel device.
#[error(display = "Failed to create tunnel device")]
- SetupTunnelDeviceError(#[error(cause)] crate::network_interface::Error),
+ SetupTunnelDeviceError(#[error(cause)] BoxedError),
/// Failed to setup wireguard tunnel.
#[error(display = "Failed to start wireguard tunnel - {}", status)]
@@ -65,8 +66,9 @@ impl WireguardMonitor {
config: &Config,
log_path: Option<&Path>,
on_event: F,
+ tun_provider: &dyn TunProvider,
) -> Result<WireguardMonitor> {
- let tunnel = Box::new(WgGoTunnel::start_tunnel(&config, log_path)?);
+ let tunnel = Box::new(WgGoTunnel::start_tunnel(&config, log_path, tun_provider)?);
let iface_name = tunnel.get_interface_name();
let route_handle = routing::RouteManager::new(
Self::get_routes(iface_name, &config),
diff --git a/talpid-core/src/tunnel/wireguard/wireguard_go.rs b/talpid-core/src/tunnel/wireguard/wireguard_go.rs
index 059147286d..9071766dbb 100644
--- a/talpid-core/src/tunnel/wireguard/wireguard_go.rs
+++ b/talpid-core/src/tunnel/wireguard/wireguard_go.rs
@@ -1,32 +1,28 @@
use super::{Config, Error, Result, Tunnel};
-use crate::network_interface::{NetworkInterface, TunnelDevice};
+use crate::tunnel::tun_provider::{Tun, TunConfig, TunProvider};
use std::{ffi::CString, fs, os::unix::io::AsRawFd, path::Path};
-
pub struct WgGoTunnel {
interface_name: String,
handle: Option<i32>,
// holding on to the tunnel device and the log file ensures that the associated file handles
// live long enough and get closed when the tunnel is stopped
- _tunnel_device: TunnelDevice,
+ _tunnel_device: Box<dyn Tun>,
_log_file: fs::File,
}
impl WgGoTunnel {
- pub fn start_tunnel(config: &Config, log_path: Option<&Path>) -> Result<Self> {
- let mut tunnel_device = TunnelDevice::new().map_err(Error::SetupTunnelDeviceError)?;
-
- for ip in config.tunnel.addresses.iter() {
- tunnel_device
- .set_ip(*ip)
- .map_err(Error::SetupTunnelDeviceError)?;
- }
-
- tunnel_device
- .set_up(true)
+ pub fn start_tunnel(
+ config: &Config,
+ log_path: Option<&Path>,
+ tun_provider: &dyn TunProvider,
+ ) -> Result<Self> {
+ let tunnel_config = TunConfig::new(config.tunnel.addresses.clone());
+ let tunnel_device = tun_provider
+ .create_tun(tunnel_config)
.map_err(Error::SetupTunnelDeviceError)?;
- let interface_name: String = tunnel_device.get_name().to_string();
+ let interface_name: String = tunnel_device.interface_name().to_string();
let log_file = prepare_log_file(log_path)?;
let wg_config_str = config.to_userspace_format();
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index 1f6afc16ad..c82ad27f73 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -5,7 +5,9 @@ use super::{
};
use crate::{
firewall::FirewallPolicy,
- tunnel::{self, CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor},
+ tunnel::{
+ self, tun_provider::TunProvider, CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor,
+ },
};
use futures::{
sync::{mpsc, oneshot},
@@ -13,6 +15,7 @@ use futures::{
};
use log::{debug, error, info, trace, warn};
use std::{
+ borrow::Borrow,
net::IpAddr,
path::{Path, PathBuf},
thread,
@@ -62,13 +65,20 @@ impl ConnectingState {
parameters: TunnelParameters,
log_dir: &Option<PathBuf>,
resource_dir: &Path,
+ tun_provider: &dyn TunProvider,
retry_attempt: u32,
) -> crate::tunnel::Result<Self> {
let (event_tx, event_rx) = mpsc::unbounded();
let on_tunnel_event = move |event| {
let _ = event_tx.unbounded_send(event);
};
- let monitor = TunnelMonitor::start(&parameters, log_dir, resource_dir, on_tunnel_event)?;
+ let monitor = TunnelMonitor::start(
+ &parameters,
+ log_dir,
+ resource_dir,
+ on_tunnel_event,
+ tun_provider,
+ )?;
let close_handle = monitor.close_handle();
let tunnel_close_event = Self::spawn_tunnel_monitor_wait_thread(monitor);
@@ -320,6 +330,7 @@ impl TunnelState for ConnectingState {
tunnel_parameters,
&shared_values.log_dir,
&shared_values.resource_dir,
+ shared_values.tun_provider.borrow(),
retry_attempt,
) {
Ok(connecting_state) => {
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 715c2d773c..d947792da6 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -19,6 +19,7 @@ use crate::{
firewall::{Firewall, FirewallArguments},
mpsc::IntoSender,
offline,
+ tunnel::tun_provider::TunProvider,
};
use futures::{sync::mpsc, Async, Future, Poll, Stream};
use std::{
@@ -63,6 +64,7 @@ pub fn spawn<P, T>(
allow_lan: bool,
block_when_disconnected: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
+ tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: P,
@@ -84,6 +86,7 @@ where
block_when_disconnected,
is_offline,
tunnel_parameters_generator,
+ tun_provider,
log_dir,
resource_dir,
cache_dir,
@@ -122,6 +125,7 @@ fn create_event_loop<T>(
block_when_disconnected: bool,
is_offline: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
+ tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: impl AsRef<Path>,
@@ -137,6 +141,7 @@ where
block_when_disconnected,
is_offline,
tunnel_parameters_generator,
+ tun_provider,
log_dir,
resource_dir,
cache_dir,
@@ -186,6 +191,7 @@ impl TunnelStateMachine {
block_when_disconnected: bool,
is_offline: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
+ tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: impl AsRef<Path>,
@@ -211,6 +217,7 @@ impl TunnelStateMachine {
block_when_disconnected,
is_offline,
tunnel_parameters_generator: Box::new(tunnel_parameters_generator),
+ tun_provider: Box::new(tun_provider),
log_dir,
resource_dir,
};
@@ -293,6 +300,8 @@ struct SharedTunnelStateValues {
is_offline: bool,
/// The generator of new `TunnelParameter`s
tunnel_parameters_generator: Box<dyn TunnelParametersGenerator>,
+ /// The provider of tunnel devices.
+ tun_provider: Box<dyn TunProvider>,
/// Directory to store tunnel log file.
log_dir: Option<PathBuf>,
/// Resource directory path.
diff --git a/talpid-types/src/lib.rs b/talpid-types/src/lib.rs
index 42a2dc4cf7..569bc94fb9 100644
--- a/talpid-types/src/lib.rs
+++ b/talpid-types/src/lib.rs
@@ -8,6 +8,8 @@
#![deny(rust_2018_idioms)]
+use std::{error::Error, fmt};
+
pub mod net;
pub mod tunnel;
@@ -20,7 +22,7 @@ pub trait ErrorExt {
fn display_chain_with_msg(&self, msg: &str) -> String;
}
-impl<E: std::error::Error> ErrorExt for E {
+impl<E: Error> ErrorExt for E {
fn display_chain(&self) -> String {
let mut s = format!("Error: {}", self);
let mut source = self.source();
@@ -41,3 +43,28 @@ impl<E: std::error::Error> ErrorExt for E {
s
}
}
+
+#[derive(Debug)]
+pub struct BoxedError(Box<dyn Error>);
+
+impl fmt::Display for BoxedError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl Error for BoxedError {
+ fn description(&self) -> &str {
+ self.0.description()
+ }
+
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ self.0.source()
+ }
+}
+
+impl BoxedError {
+ pub fn new(error: impl Error + 'static) -> Self {
+ BoxedError(Box::new(error))
+ }
+}