summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-04-23 12:18:09 +0200
committerDavid Lönnhager <david.l@mullvad.net>2020-04-24 16:51:47 +0200
commit2dfa1d08eb6a3c9d422bfbd84854073fa932182c (patch)
tree0f5e0a4a1dc7b29939fa7d4b4cf7e4a181d21598
parent0cbcd2cedfef07651c99e804a63e0d8ba2c3a09a (diff)
downloadmullvadvpn-2dfa1d08eb6a3c9d422bfbd84854073fa932182c.tar.xz
mullvadvpn-2dfa1d08eb6a3c9d422bfbd84854073fa932182c.zip
Try to enable IPv6 on Windows if it's disabled but required (instead of failing)
-rw-r--r--talpid-core/src/tunnel/mod.rs50
1 files changed, 41 insertions, 9 deletions
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index 22da520ce0..0f8a902406 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -3,6 +3,7 @@ use crate::logging;
#[cfg(not(target_os = "android"))]
use std::collections::HashMap;
use std::{
+ ffi::OsString,
io,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
path::{Path, PathBuf},
@@ -209,16 +210,17 @@ impl TunnelMonitor {
let options = tunnel_parameters.get_generic_options();
if options.enable_ipv6 {
#[cfg(target_os = "windows")]
- let enabled = match tunnel_parameters {
- TunnelParameters::OpenVpn(_) => is_ipv6_enabled_in_os(true),
- _ => is_ipv6_enabled_in_os(false),
- }?;
+ {
+ try_enabling_ipv6(tunnel_parameters)
+ }
#[cfg(not(target_os = "windows"))]
- let enabled = is_ipv6_enabled_in_os()?;
- if enabled {
- Ok(())
- } else {
- Err(Error::EnableIpv6Error)
+ {
+ let enabled = is_ipv6_enabled_in_os()?;
+ if enabled {
+ Ok(())
+ } else {
+ Err(Error::EnableIpv6Error)
+ }
}
} else {
Ok(())
@@ -327,6 +329,36 @@ impl InternalTunnelMonitor {
#[cfg(target_os = "windows")]
+fn try_enabling_ipv6(tunnel_parameters: &TunnelParameters) -> Result<()> {
+ use winreg::{enums::*, RegKey};
+
+ const IPV6_DISABLED_ON_TUNNELS_MASK: u32 = 0x01;
+
+ // Check registry if IPv6 is disabled on tunnel interfaces, as documented in
+ // https://support.microsoft.com/en-us/help/929852/guidance-for-configuring-ipv6-in-windows-for-advanced-users
+ let globally_enabled = 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 & IPV6_DISABLED_ON_TUNNELS_MASK) == 0)
+ .unwrap_or(true);
+
+ if !globally_enabled {
+ // TODO: Try to globally enable IPv6
+ log::debug!("IPv6 disabled in all tunnel interfaces");
+ return Err(Error::EnableIpv6Error);
+ }
+
+ let alias = match tunnel_parameters {
+ TunnelParameters::OpenVpn(..) => {
+ crate::winnet::get_tap_interface_alias().map_err(Error::WinnetError)?
+ }
+ TunnelParameters::Wireguard(..) => OsString::from("wg-mullvad"),
+ };
+
+ crate::winnet::enable_ipv6_for_adapter(&alias).map_err(Error::WinnetError)
+}
+
+#[cfg(target_os = "windows")]
fn is_ipv6_enabled_in_os(check_tap: bool) -> Result<bool> {
use winreg::{enums::*, RegKey};