summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-04-23 18:37:06 +0200
committerDavid Lönnhager <david.l@mullvad.net>2020-04-24 16:51:47 +0200
commit2eaa3845ef8e64208f30784575356f4137412133 (patch)
treefa491fe7e5cc57e89694df884a4695f65dc69d8b
parent2dfa1d08eb6a3c9d422bfbd84854073fa932182c (diff)
downloadmullvadvpn-2eaa3845ef8e64208f30784575356f4137412133.tar.xz
mullvadvpn-2eaa3845ef8e64208f30784575356f4137412133.zip
Enable IPv6 for WireGuard interface
-rw-r--r--talpid-core/src/tunnel/mod.rs22
-rw-r--r--talpid-core/src/winnet.rs44
-rw-r--r--windows/winnet/src/winnet/netconfig.cpp25
-rw-r--r--windows/winnet/src/winnet/netconfig.h2
-rw-r--r--windows/winnet/src/winnet/winnet.cpp62
-rw-r--r--windows/winnet/src/winnet/winnet.def1
-rw-r--r--windows/winnet/src/winnet/winnet.h13
7 files changed, 132 insertions, 37 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);
diff --git a/windows/winnet/src/winnet/netconfig.cpp b/windows/winnet/src/winnet/netconfig.cpp
index 2bd96c907f..2a8e2e1c64 100644
--- a/windows/winnet/src/winnet/netconfig.cpp
+++ b/windows/winnet/src/winnet/netconfig.cpp
@@ -138,30 +138,11 @@ void SetIpv6BindingForBindName(INetCfg *netCfg, const std::wstring &bindName, bo
}
}
-std::wstring FindAdapterGuidForAlias(const std::wstring &alias)
-{
- const auto adapters = shared::network::InterfaceUtils::GetAllAdapters(
- AF_UNSPEC,
- GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
- );
- for (auto it = adapters.begin(); it != adapters.end(); ++it)
- {
- if (0 == it->alias().compare(alias))
- {
- return it->guid();
- }
- }
-
- throw std::runtime_error("Cannot find GUID for given alias");
-}
-
} // anonymous namespace
-void EnableIpv6ForAdapter(const std::wstring &alias)
+void EnableIpv6ForAdapter(const std::wstring &adapterGuid)
{
- std::wstring adapterGuid = FindAdapterGuidForAlias(alias);
-
//
// Initialize COM
//
@@ -190,7 +171,7 @@ void EnableIpv6ForAdapter(const std::wstring &alias)
nullptr,
CLSCTX_INPROC_SERVER,
IID_INetCfg,
- reinterpret_cast<void**>(&netCfg)
+ reinterpret_cast<void **>(&netCfg)
);
if (S_OK != result)
@@ -204,7 +185,7 @@ void EnableIpv6ForAdapter(const std::wstring &alias)
scopeDest += [&netCfg]() { netCfg->Release(); };
INetCfgLock *netCfgLock = nullptr;
- result = netCfg->QueryInterface(IID_INetCfgLock, reinterpret_cast<void**>(&netCfgLock));
+ result = netCfg->QueryInterface(IID_INetCfgLock, reinterpret_cast<void **>(&netCfgLock));
if (S_OK != result)
{
diff --git a/windows/winnet/src/winnet/netconfig.h b/windows/winnet/src/winnet/netconfig.h
index a729d98629..b2849857a2 100644
--- a/windows/winnet/src/winnet/netconfig.h
+++ b/windows/winnet/src/winnet/netconfig.h
@@ -2,4 +2,4 @@
#include <string>
-void EnableIpv6ForAdapter(const std::wstring &alias);
+void EnableIpv6ForAdapter(const std::wstring &guid);
diff --git a/windows/winnet/src/winnet/winnet.cpp b/windows/winnet/src/winnet/winnet.cpp
index 5f9d20f583..6a37b100f6 100644
--- a/windows/winnet/src/winnet/winnet.cpp
+++ b/windows/winnet/src/winnet/winnet.cpp
@@ -69,19 +69,19 @@ WINNET_LINKAGE
bool
WINNET_API
WinNet_EnableIpv6ForAdapter(
- const wchar_t *deviceAlias,
+ const wchar_t *deviceGuid,
MullvadLogSink logSink,
void *logSinkContext
)
{
try
{
- if (nullptr == deviceAlias)
+ if (nullptr == deviceGuid)
{
- THROW_ERROR("Invalid argument: deviceAlias");
+ THROW_ERROR("Invalid argument: deviceGuid");
}
- EnableIpv6ForAdapter(deviceAlias);
+ EnableIpv6ForAdapter(deviceGuid);
return true;
}
catch (const std::exception & err)
@@ -172,6 +172,60 @@ WinNet_GetTapInterfaceAlias(
extern "C"
WINNET_LINKAGE
+bool
+WINNET_API
+WinNet_InterfaceAliasToGuid(
+ const wchar_t *alias,
+ wchar_t **guid,
+ MullvadLogSink logSink,
+ void *logSinkContext
+)
+{
+ try
+ {
+ if (nullptr == guid)
+ {
+ THROW_ERROR("Invalid argument: guid");
+ }
+ if (nullptr == alias)
+ {
+ THROW_ERROR("Invalid argument: alias");
+ }
+
+ GUID tempGuid = { 0 };
+ NET_LUID luid = { 0 };
+
+ if (NO_ERROR != ConvertInterfaceAliasToLuid(alias, &luid))
+ {
+ THROW_ERROR("ConvertInterfaceAliasToLuid: invalid parameter");
+ }
+
+ if (NO_ERROR != ConvertInterfaceLuidToGuid(&luid, &tempGuid))
+ {
+ THROW_ERROR("ConvertInterfaceLuidToGuid: invalid parameter");
+ }
+
+ const auto guidStr = common::string::FormatGuid(tempGuid);
+
+ auto guidBuffer = new wchar_t[guidStr.size() + 1];
+ wcscpy(guidBuffer, guidStr.c_str());
+ *guid = guidBuffer;
+
+ return true;
+ }
+ catch (const std::exception & err)
+ {
+ shared::logging::UnwindAndLog(logSink, logSinkContext, err);
+ return false;
+ }
+ catch (...)
+ {
+ return false;
+ }
+}
+
+extern "C"
+WINNET_LINKAGE
void
WINNET_API
WinNet_ReleaseString(
diff --git a/windows/winnet/src/winnet/winnet.def b/windows/winnet/src/winnet/winnet.def
index 29a19dffe5..c281e481f5 100644
--- a/windows/winnet/src/winnet/winnet.def
+++ b/windows/winnet/src/winnet/winnet.def
@@ -1,6 +1,7 @@
LIBRARY winnet
EXPORTS
WinNet_EnsureBestMetric
+ WinNet_InterfaceAliasToGuid
WinNet_EnableIpv6ForAdapter
WinNet_GetTapInterfaceIpv6Status
WinNet_GetTapInterfaceAlias
diff --git a/windows/winnet/src/winnet/winnet.h b/windows/winnet/src/winnet/winnet.h
index 885ed8ef90..f084f0e737 100644
--- a/windows/winnet/src/winnet/winnet.h
+++ b/windows/winnet/src/winnet/winnet.h
@@ -38,7 +38,7 @@ WINNET_LINKAGE
bool
WINNET_API
WinNet_EnableIpv6ForAdapter(
- const wchar_t *deviceAlias,
+ const wchar_t *deviceGuid,
MullvadLogSink logSink,
void *logSinkContext
);
@@ -69,6 +69,17 @@ WinNet_GetTapInterfaceAlias(
void *logSinkContext
);
+extern "C"
+WINNET_LINKAGE
+bool
+WINNET_API
+WinNet_InterfaceAliasToGuid(
+ const wchar_t *alias,
+ wchar_t **guid,
+ MullvadLogSink logSink,
+ void *logSinkContext
+);
+
//
// This is a companion function to the above function.
// Generically named in case we need other functions here that return strings.