diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-04-23 18:37:06 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-04-24 16:51:47 +0200 |
| commit | 2eaa3845ef8e64208f30784575356f4137412133 (patch) | |
| tree | fa491fe7e5cc57e89694df884a4695f65dc69d8b /talpid-core/src | |
| parent | 2dfa1d08eb6a3c9d422bfbd84854073fa932182c (diff) | |
| download | mullvadvpn-2eaa3845ef8e64208f30784575356f4137412133.tar.xz mullvadvpn-2eaa3845ef8e64208f30784575356f4137412133.zip | |
Enable IPv6 for WireGuard interface
Diffstat (limited to 'talpid-core/src')
| -rw-r--r-- | talpid-core/src/tunnel/mod.rs | 22 | ||||
| -rw-r--r-- | talpid-core/src/winnet.rs | 44 |
2 files changed, 57 insertions, 9 deletions
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs index 0f8a902406..afee640829 100644 --- a/talpid-core/src/tunnel/mod.rs +++ b/talpid-core/src/tunnel/mod.rs @@ -3,7 +3,6 @@ use crate::logging; #[cfg(not(target_os = "android"))] use std::collections::HashMap; use std::{ - ffi::OsString, io, net::{IpAddr, Ipv4Addr, Ipv6Addr}, path::{Path, PathBuf}, @@ -348,14 +347,27 @@ fn try_enabling_ipv6(tunnel_parameters: &TunnelParameters) -> Result<()> { return Err(Error::EnableIpv6Error); } - let alias = match tunnel_parameters { + let guid_string: String; + + let guid = match tunnel_parameters { TunnelParameters::OpenVpn(..) => { - crate::winnet::get_tap_interface_alias().map_err(Error::WinnetError)? + // TODO: This status check can be removed if it is certain + // that `enable_ipv6_for_adapter` is reliable. + let status = + crate::winnet::get_tap_interface_ipv6_status().map_err(Error::WinnetError)?; + if status { + return Ok(()); + } + + let alias = crate::winnet::get_tap_interface_alias().map_err(Error::WinnetError)?; + guid_string = + crate::winnet::interface_alias_to_guid(&alias).map_err(Error::WinnetError)?; + &guid_string } - TunnelParameters::Wireguard(..) => OsString::from("wg-mullvad"), + TunnelParameters::Wireguard(..) => "{AFE43773-E1F8-4EBB-8536-576AB86AFE9A}", }; - crate::winnet::enable_ipv6_for_adapter(&alias).map_err(Error::WinnetError) + crate::winnet::enable_ipv6_for_adapter(&guid).map_err(Error::WinnetError) } #[cfg(target_os = "windows")] diff --git a/talpid-core/src/winnet.rs b/talpid-core/src/winnet.rs index 3e7a52bf75..534dab5228 100644 --- a/talpid-core/src/winnet.rs +++ b/talpid-core/src/winnet.rs @@ -25,6 +25,10 @@ pub enum Error { #[error(display = "Failed to enable IPv6 on the network interface")] EnableIpv6, + /// Failed to enable IPv6 on the network interface. + #[error(display = "Failed to obtain GUID for the network interface")] + GetInterfaceGuid, + /// Failed to read IPv6 status on the TAP network interface. #[error(display = "Failed to read IPv6 status on the TAP network interface")] GetIpv6Status, @@ -71,13 +75,13 @@ pub fn ensure_best_metric_for_interface(interface_alias: &str) -> Result<bool, E } /// Enables IPv6 for a given interface. -pub fn enable_ipv6_for_adapter(interface_alias: &OsStr) -> Result<(), Error> { - let interface_alias_ws = - WideCString::from_os_str(interface_alias).map_err(Error::InvalidInterfaceAlias)?; +pub fn enable_ipv6_for_adapter(interface_guid: &str) -> Result<(), Error> { + let interface_guid_ws = + WideCString::from_str(interface_guid).map_err(Error::InvalidInterfaceAlias)?; let result = unsafe { WinNet_EnableIpv6ForAdapter( - interface_alias_ws.as_ptr(), + interface_guid_ws.as_ptr(), Some(log_sink), logging_context(), ) @@ -133,6 +137,30 @@ pub fn get_tap_interface_alias() -> Result<OsString, Error> { Ok(alias.to_os_string()) } +/// Determines the interface guid for a given adapter alias. +pub fn interface_alias_to_guid(interface_alias: &OsStr) -> Result<String, Error> { + let interface_alias = + WideCString::from_os_str(interface_alias).map_err(Error::InvalidInterfaceAlias)?; + let mut guid_ptr: *mut wchar_t = ptr::null_mut(); + let status = unsafe { + WinNet_InterfaceAliasToGuid( + interface_alias.as_ptr(), + &mut guid_ptr as *mut _, + Some(log_sink), + logging_context(), + ) + }; + + if !status { + return Err(Error::GetInterfaceGuid); + } + + let guid = unsafe { WideCString::from_ptr_str(guid_ptr) }; + unsafe { WinNet_ReleaseString(guid_ptr) }; + + Ok(guid.to_string_lossy()) +} + #[allow(dead_code)] #[repr(u32)] pub enum WinNetAddrFamily { @@ -428,6 +456,14 @@ mod api { sink_context: *const u8, ) -> bool; + #[link_name = "WinNet_InterfaceAliasToGuid"] + pub fn WinNet_InterfaceAliasToGuid( + interface_alias: *const wchar_t, + interface_guid: *mut *mut wchar_t, + sink: Option<LogSink>, + sink_context: *const u8, + ) -> bool; + #[link_name = "WinNet_ReleaseString"] pub fn WinNet_ReleaseString(string: *mut wchar_t); |
