summaryrefslogtreecommitdiffhomepage
path: root/talpid-core
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-09-06 08:57:14 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-09-06 08:57:14 -0300
commitd051e71ae289a92be1743a6b844d290cbfae4fd9 (patch)
tree1f5c410b06b846fa588b8536b77d4872c2b13c7f /talpid-core
parentc448ca931fddacce052a392614d2d906033ca933 (diff)
parent1c9d41c964c3844aa2cf5aaa557b6d549f93f298 (diff)
downloadmullvadvpn-d051e71ae289a92be1743a6b844d290cbfae4fd9.tar.xz
mullvadvpn-d051e71ae289a92be1743a6b844d290cbfae4fd9.zip
Merge branch 'check-ipv6-enabled'
Diffstat (limited to 'talpid-core')
-rw-r--r--talpid-core/Cargo.toml1
-rw-r--r--talpid-core/src/lib.rs2
-rw-r--r--talpid-core/src/tunnel/mod.rs52
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs34
4 files changed, 78 insertions, 11 deletions
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index 23df76dfd8..1041d184a3 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -43,6 +43,7 @@ tokio-core = "0.1"
[target.'cfg(windows)'.dependencies]
widestring = "0.3"
+winreg = "0.5"
[dev-dependencies]
tempfile = "3.0"
diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs
index 55df5e135f..ecc530aec3 100644
--- a/talpid-core/src/lib.rs
+++ b/talpid-core/src/lib.rs
@@ -34,6 +34,8 @@ extern crate tokio_core;
extern crate uuid;
#[cfg(target_os = "linux")]
extern crate which;
+#[cfg(windows)]
+extern crate winreg;
extern crate openvpn_plugin;
extern crate talpid_ipc;
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index ce49ea7b0d..59f032b286 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -60,6 +60,10 @@ error_chain!{
CredentialsWriteError {
description("Error while writing credentials to temporary file")
}
+ /// Tunnel can't have IPv6 enabled because the system has disabled IPv6 support.
+ EnableIpv6Error {
+ description("Can't enable IPv6 on tunnel interface because IPv6 is disabled")
+ }
/// Running on an operating system which is not supported yet.
UnsupportedPlatform {
description("Running on an unsupported operating system")
@@ -150,10 +154,9 @@ impl TunnelMonitor {
where
L: Fn(TunnelEvent) + Send + Sync + 'static,
{
- match tunnel_endpoint.tunnel {
- TunnelEndpointData::OpenVpn(_) => (),
- TunnelEndpointData::Wireguard(_) => bail!(ErrorKind::UnsupportedTunnelProtocol),
- }
+ Self::ensure_endpoint_is_openvpn(&tunnel_endpoint)?;
+ Self::ensure_ipv6_can_be_used_if_enabled(tunnel_options)?;
+
let user_pass_file =
Self::create_user_pass_file(username).chain_err(|| ErrorKind::CredentialsWriteError)?;
let cmd = Self::create_openvpn_cmd(
@@ -188,6 +191,21 @@ impl TunnelMonitor {
})
}
+ fn ensure_endpoint_is_openvpn(endpoint: &TunnelEndpoint) -> Result<()> {
+ match endpoint.tunnel {
+ TunnelEndpointData::OpenVpn(_) => Ok(()),
+ TunnelEndpointData::Wireguard(_) => bail!(ErrorKind::UnsupportedTunnelProtocol),
+ }
+ }
+
+ fn ensure_ipv6_can_be_used_if_enabled(tunnel_options: &TunnelOptions) -> Result<()> {
+ if tunnel_options.enable_ipv6 && !is_ipv6_enabled_in_os() {
+ bail!(ErrorKind::EnableIpv6Error);
+ } else {
+ Ok(())
+ }
+ }
+
fn create_openvpn_cmd(
remote: Endpoint,
tunnel_alias: Option<OsString>,
@@ -297,3 +315,29 @@ impl CloseHandle {
self.0.close()
}
}
+
+fn is_ipv6_enabled_in_os() -> bool {
+ #[cfg(windows)]
+ {
+ use winreg::enums::*;
+ use winreg::RegKey;
+
+ const IPV6_DISABLED: u8 = 0xFF;
+
+ RegKey::predef(HKEY_LOCAL_MACHINE)
+ .open_subkey(r#"SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters"#)
+ .and_then(|ipv6_config| ipv6_config.get_value("DisabledComponents"))
+ .map(|ipv6_disabled_bits: u32| (ipv6_disabled_bits & 0xFF) == IPV6_DISABLED as u32)
+ .unwrap_or(false)
+ }
+ #[cfg(target_os = "linux")]
+ {
+ fs::read_to_string("/proc/sys/net/ipv6/conf/all/disable_ipv6")
+ .map(|disable_ipv6| disable_ipv6.trim() == "0")
+ .unwrap_or(false)
+ }
+ #[cfg(target_os = "macos")]
+ {
+ true
+ }
+}
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index 80fd94f364..6c31a08c69 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -14,12 +14,12 @@ use talpid_types::tunnel::BlockReason;
use super::{
AfterDisconnect, BlockedState, ConnectedState, ConnectedStateBootstrap, DisconnectingState,
- EventConsequence, Result, ResultExt, SharedTunnelStateValues, TunnelCommand, TunnelParameters,
- TunnelState, TunnelStateTransition, TunnelStateWrapper,
+ EventConsequence, SharedTunnelStateValues, TunnelCommand, TunnelParameters, TunnelState,
+ TunnelStateTransition, TunnelStateWrapper,
};
use logging;
use security::SecurityPolicy;
-use tunnel::{CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor};
+use tunnel::{self, CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor};
const MIN_TUNNEL_ALIVE_TIME: Duration = Duration::from_millis(1000);
@@ -31,6 +31,18 @@ const TUNNEL_INTERFACE_ALIAS: Option<&str> = Some("Mullvad");
#[cfg(not(windows))]
const TUNNEL_INTERFACE_ALIAS: Option<&str> = None;
+error_chain! {
+ errors {
+ RotateLogError {
+ description("Failed to rotate tunnel log file")
+ }
+ }
+
+ links {
+ TunnelMonitorError(tunnel::Error, tunnel::ErrorKind);
+ }
+}
+
/// The tunnel has been started, but it is not established/functional.
pub struct ConnectingState {
tunnel_events: mpsc::UnboundedReceiver<TunnelEvent>,
@@ -101,7 +113,7 @@ impl ConnectingState {
};
let log_file = Self::prepare_tunnel_log_file(&parameters)?;
- TunnelMonitor::new(
+ Ok(TunnelMonitor::new(
parameters.endpoint,
&parameters.options,
TUNNEL_INTERFACE_ALIAS.to_owned().map(OsString::from),
@@ -109,7 +121,7 @@ impl ConnectingState {
log_file.as_ref().map(PathBuf::as_path),
&parameters.resource_dir,
on_tunnel_event,
- ).chain_err(|| "Unable to start tunnel monitor")
+ )?)
}
fn prepare_tunnel_log_file(parameters: &TunnelParameters) -> Result<Option<PathBuf>> {
@@ -119,7 +131,7 @@ impl ConnectingState {
TunnelEndpointData::Wireguard(_) => WIREGUARD_LOG_FILENAME,
};
let tunnel_log = log_dir.join(filename);
- logging::rotate_log(&tunnel_log).chain_err(|| "Unable to rotate tunnel log")?;
+ logging::rotate_log(&tunnel_log).chain_err(|| ErrorKind::RotateLogError)?;
Ok(Some(tunnel_log))
} else {
Ok(None)
@@ -291,9 +303,17 @@ impl TunnelState for ConnectingState {
TunnelStateTransition::Connecting,
),
Err(error) => {
+ let block_reason = match *error.kind() {
+ ErrorKind::TunnelMonitorError(tunnel::ErrorKind::EnableIpv6Error) => {
+ BlockReason::Ipv6Unavailable
+ }
+ _ => BlockReason::StartTunnelError,
+ };
+
let chained_error = error.chain_err(|| "Failed to start tunnel");
error!("{}", chained_error.display_chain());
- BlockedState::enter(shared_values, (BlockReason::StartTunnelError, allow_lan))
+
+ BlockedState::enter(shared_values, (block_reason, allow_lan))
}
}
}