summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-09-11 12:54:40 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-09-11 12:54:40 -0300
commitaa44a945fcf7115c0786d83100d548fc4d8cdb12 (patch)
treedf2ef808429fabd901c48271b78af4e9cf7af2a5
parentb3f21d87471d589b3ce8b1de08373b98ffe5cb09 (diff)
parent945e99c2ececce5277dbaa064b38a898265ef2a7 (diff)
downloadmullvadvpn-aa44a945fcf7115c0786d83100d548fc4d8cdb12.tar.xz
mullvadvpn-aa44a945fcf7115c0786d83100d548fc4d8cdb12.zip
Merge branch 'check-tap-ipv6'
-rw-r--r--talpid-core/src/lib.rs5
-rw-r--r--talpid-core/src/security/windows/dns.rs16
-rw-r--r--talpid-core/src/security/windows/ffi.rs13
-rw-r--r--talpid-core/src/security/windows/mod.rs34
-rw-r--r--talpid-core/src/security/windows/route.rs63
-rw-r--r--talpid-core/src/tunnel/mod.rs21
-rw-r--r--talpid-core/src/winnet.rs92
-rw-r--r--windows/winroute/extras.sln57
-rw-r--r--windows/winroute/src/extras/loader/loader.cpp10
-rw-r--r--windows/winroute/src/extras/loader/loader.vcxproj176
-rw-r--r--windows/winroute/src/extras/loader/loader.vcxproj.filters11
-rw-r--r--windows/winroute/src/extras/loader/stdafx.cpp8
-rw-r--r--windows/winroute/src/extras/loader/stdafx.h15
-rw-r--r--windows/winroute/src/extras/loader/targetver.h8
-rw-r--r--windows/winroute/src/winroute/InterfacePair.h4
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.cpp52
-rw-r--r--windows/winroute/src/winroute/NetworkInterfaces.h7
-rw-r--r--windows/winroute/src/winroute/winroute.cpp45
-rw-r--r--windows/winroute/src/winroute/winroute.def3
-rw-r--r--windows/winroute/src/winroute/winroute.h20
20 files changed, 540 insertions, 120 deletions
diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs
index ecc530aec3..54e3ef08ef 100644
--- a/talpid-core/src/lib.rs
+++ b/talpid-core/src/lib.rs
@@ -35,6 +35,8 @@ extern crate uuid;
#[cfg(target_os = "linux")]
extern crate which;
#[cfg(windows)]
+extern crate widestring;
+#[cfg(windows)]
extern crate winreg;
extern crate openvpn_plugin;
@@ -45,6 +47,9 @@ extern crate talpid_types;
#[macro_use]
extern crate nftnl;
+#[cfg(windows)]
+mod winnet;
+
/// Working with processes.
pub mod process;
diff --git a/talpid-core/src/security/windows/dns.rs b/talpid-core/src/security/windows/dns.rs
index d068cb4151..4904946c98 100644
--- a/talpid-core/src/security/windows/dns.rs
+++ b/talpid-core/src/security/windows/dns.rs
@@ -1,16 +1,14 @@
-extern crate widestring;
-
-use super::ffi;
-use super::system_state::SystemStateWriter;
-
-use self::widestring::WideCString;
-use libc;
use std::net::IpAddr;
use std::path::Path;
use std::ptr;
use std::slice;
use error_chain::ChainedError;
+use libc;
+use widestring::WideCString;
+
+use super::system_state::SystemStateWriter;
+use winnet;
const DNS_STATE_FILENAME: &'static str = "dns-state-backup";
@@ -49,7 +47,7 @@ pub struct WinDns {
impl WinDns {
pub fn new<P: AsRef<Path>>(cache_dir: P) -> Result<Self> {
- unsafe { WinDns_Initialize(Some(ffi::error_sink), ptr::null_mut()).into_result()? };
+ unsafe { WinDns_Initialize(Some(winnet::error_sink), ptr::null_mut()).into_result()? };
let backup_writer = SystemStateWriter::new(
cache_dir
@@ -191,7 +189,7 @@ extern "system" {
#[link_name(WinDns_Initialize)]
pub fn WinDns_Initialize(
- sink: Option<ffi::ErrorSink>,
+ sink: Option<winnet::ErrorSink>,
sink_context: *mut libc::c_void,
) -> InitializationResult;
diff --git a/talpid-core/src/security/windows/ffi.rs b/talpid-core/src/security/windows/ffi.rs
index 029989359e..2362876897 100644
--- a/talpid-core/src/security/windows/ffi.rs
+++ b/talpid-core/src/security/windows/ffi.rs
@@ -1,16 +1,3 @@
-use libc::{c_char, c_void};
-
-pub type ErrorSink = extern "system" fn(msg: *const c_char, ctx: *mut c_void);
-
-pub extern "system" fn error_sink(msg: *const c_char, _ctx: *mut c_void) {
- use std::ffi::CStr;
- if msg.is_null() {
- error!("Log message from FFI boundary is NULL");
- } else {
- error!("{}", unsafe { CStr::from_ptr(msg).to_string_lossy() });
- }
-}
-
#[macro_export]
macro_rules! ffi_error {
($result:ident, $error:expr) => {
diff --git a/talpid-core/src/security/windows/mod.rs b/talpid-core/src/security/windows/mod.rs
index e762a4887a..6ecca8988b 100644
--- a/talpid-core/src/security/windows/mod.rs
+++ b/talpid-core/src/security/windows/mod.rs
@@ -1,24 +1,21 @@
-extern crate widestring;
-
-use super::{NetworkSecurityT, SecurityPolicy};
use std::net::IpAddr;
use std::path::Path;
use std::ptr;
-use self::winfw::*;
use talpid_types::net::Endpoint;
+use widestring::WideCString;
-use self::widestring::WideCString;
-
+use self::dns::WinDns;
+use self::winfw::*;
+use super::{NetworkSecurityT, SecurityPolicy};
+use winnet;
#[macro_use]
mod ffi;
+
mod dns;
-mod route;
mod system_state;
-use self::dns::WinDns;
-
error_chain! {
errors {
/// Failure to initialize windows firewall module
@@ -50,11 +47,15 @@ error_chain! {
ResettingPolicy {
description("Failed to reset firewall policies")
}
+
+ /// Failure to set TAP adapter metric
+ SetTapMetric {
+ description("Unable to set TAP adapter metric")
+ }
}
links {
WinDns(dns::Error, dns::ErrorKind) #[doc = "WinDNS failure"];
- WinRoute(route::Error, route::ErrorKind) #[doc = "Failure to modify system routing metrics"];
}
}
@@ -73,7 +74,7 @@ impl NetworkSecurityT for NetworkSecurity {
unsafe {
WinFw_Initialize(
WINFW_TIMEOUT_SECONDS,
- Some(ffi::error_sink),
+ Some(winnet::error_sink),
ptr::null_mut(),
).into_result()?
};
@@ -168,14 +169,15 @@ impl NetworkSecurity {
self.dns.set_dns(&vec![tunnel_metadata.gateway.into()])?;
- let metrics_set = route::ensure_top_metric_for_interface(&tunnel_metadata.interface)?;
+ let metrics_set = winnet::ensure_top_metric_for_interface(&tunnel_metadata.interface)
+ .chain_err(|| ErrorKind::SetTapMetric)?;
+
if metrics_set {
debug!("Network interface metrics were changed");
} else {
debug!("Network interface metrics were not changed");
}
-
unsafe {
WinFw_ApplyPolicyConnected(
winfw_settings,
@@ -195,10 +197,12 @@ impl NetworkSecurity {
#[allow(non_snake_case)]
mod winfw {
- use super::{ffi, ErrorKind, Result};
use libc;
use talpid_types::net::TransportProtocol;
+ use super::{ErrorKind, Result};
+ use winnet;
+
#[repr(C)]
pub struct WinFwRelay {
pub ip: *const libc::wchar_t,
@@ -254,7 +258,7 @@ mod winfw {
#[link_name(WinFw_Initialize)]
pub fn WinFw_Initialize(
timeout: libc::c_uint,
- sink: Option<ffi::ErrorSink>,
+ sink: Option<winnet::ErrorSink>,
sink_context: *mut libc::c_void,
) -> InitializationResult;
diff --git a/talpid-core/src/security/windows/route.rs b/talpid-core/src/security/windows/route.rs
deleted file mode 100644
index 6ecf336956..0000000000
--- a/talpid-core/src/security/windows/route.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use super::ffi;
-use super::widestring::WideCString;
-use libc;
-use std::ptr;
-
-error_chain!{
- errors{
- /// Failure to set metrics of network interfaces
- MetricApplication{
- description("Failed to set the metrics for a network interface")
- }
- InvalidInterfaceAlias{
- description("Supplied interface alias is invalid")
- }
- }
-}
-
-/// Returns true if metrics were changed, false otherwise
-pub fn ensure_top_metric_for_interface(interface_alias: &str) -> Result<bool> {
- let interface_alias_ws =
- WideCString::from_str(interface_alias).chain_err(|| ErrorKind::InvalidInterfaceAlias)?;
- unsafe {
- WinRoute_EnsureTopMetric(
- interface_alias_ws.as_wide_c_str().as_ptr(),
- Some(ffi::error_sink),
- ptr::null_mut(),
- ).into()
- }
-}
-
-// Allowing dead code here as this type should only ever be constructed by an
-// FFI function.
-#[allow(dead_code)]
-#[repr(u32)]
-enum MetricResult {
- MetricsUnchanged = 0u32,
- MetricsChanged = 1u32,
- Failure = 2u32,
- UnexpectedValue,
-}
-
-impl Into<Result<bool>> for MetricResult {
- fn into(self) -> Result<bool> {
- match self {
- MetricResult::MetricsUnchanged => Ok(false),
- MetricResult::MetricsChanged => Ok(true),
- MetricResult::Failure => Err(Error::from(ErrorKind::MetricApplication)),
- MetricResult::UnexpectedValue => {
- error!("Unexpected return code from WinRoute_EnsureTopMetric");
- Err(Error::from(ErrorKind::MetricApplication))
- }
- }
- }
-}
-
-extern "system" {
- #[link_name(WinRoute_EnsureTopMetric)]
- fn WinRoute_EnsureTopMetric(
- tunnel_interface_alias: *const libc::wchar_t,
- sink: Option<ffi::ErrorSink>,
- sink_context: *mut libc::c_void,
- ) -> MetricResult;
-}
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index 59f032b286..36b3ff654b 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -322,13 +322,26 @@ fn is_ipv6_enabled_in_os() -> bool {
use winreg::enums::*;
use winreg::RegKey;
- const IPV6_DISABLED: u8 = 0xFF;
+ const IPV6_DISABLED_ON_TUNNELS_MASK: u32 = 0x01;
- RegKey::predef(HKEY_LOCAL_MACHINE)
+ // 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 & 0xFF) == IPV6_DISABLED as u32)
- .unwrap_or(false)
+ .map(|ipv6_disabled_bits: u32| {
+ (ipv6_disabled_bits & IPV6_DISABLED_ON_TUNNELS_MASK) == 0
+ }).unwrap_or(true);
+ let enabled_on_tap = ::winnet::get_tap_interface_ipv6_status().unwrap_or(false);
+
+ if !globally_enabled {
+ debug!("IPv6 disabled in tunnel interfaces");
+ }
+ if !enabled_on_tap {
+ debug!("IPv6 disabled in TAP adapter");
+ }
+
+ globally_enabled && enabled_on_tap
}
#[cfg(target_os = "linux")]
{
diff --git a/talpid-core/src/winnet.rs b/talpid-core/src/winnet.rs
new file mode 100644
index 0000000000..ef3930649c
--- /dev/null
+++ b/talpid-core/src/winnet.rs
@@ -0,0 +1,92 @@
+use std::ptr;
+
+use libc::{c_char, c_void, wchar_t};
+use widestring::WideCString;
+
+error_chain!{
+ errors{
+ /// Failure to set metrics of network interfaces
+ MetricApplication{
+ description("Failed to set the metrics for a network interface")
+ }
+ InvalidInterfaceAlias{
+ description("Supplied interface alias is invalid")
+ }
+ GetIpv6Status {
+ description("Failed to read IPv6 status on the TAP network interface")
+ }
+ }
+}
+
+pub type ErrorSink = extern "system" fn(msg: *const c_char, ctx: *mut c_void);
+
+pub extern "system" fn error_sink(msg: *const c_char, _ctx: *mut c_void) {
+ use std::ffi::CStr;
+ if msg.is_null() {
+ error!("Log message from FFI boundary is NULL");
+ } else {
+ error!("{}", unsafe { CStr::from_ptr(msg).to_string_lossy() });
+ }
+}
+
+/// Returns true if metrics were changed, false otherwise
+pub fn ensure_top_metric_for_interface(interface_alias: &str) -> Result<bool> {
+ let interface_alias_ws =
+ WideCString::from_str(interface_alias).chain_err(|| ErrorKind::InvalidInterfaceAlias)?;
+
+ let metric_result = unsafe {
+ WinRoute_EnsureTopMetric(
+ interface_alias_ws.as_wide_c_str().as_ptr(),
+ Some(error_sink),
+ ptr::null_mut(),
+ )
+ };
+
+ match metric_result {
+ // Metrics didn't change
+ 0 => Ok(false),
+ // Metrics changed
+ 1 => Ok(true),
+ // Failure
+ 2 => Err(Error::from(ErrorKind::MetricApplication)),
+ // Unexpected value
+ _ => {
+ error!("Unexpected return code from WinRoute_EnsureTopMetric");
+ Err(Error::from(ErrorKind::MetricApplication))
+ }
+ }
+}
+
+extern "system" {
+ #[link_name(WinRoute_EnsureTopMetric)]
+ fn WinRoute_EnsureTopMetric(
+ tunnel_interface_alias: *const wchar_t,
+ sink: Option<ErrorSink>,
+ sink_context: *mut c_void,
+ ) -> u32;
+}
+
+
+/// Checks if IPv6 is enabled for the TAP interface
+pub fn get_tap_interface_ipv6_status() -> Result<bool> {
+ let tap_ipv6_status = unsafe { GetTapInterfaceIpv6Status(Some(error_sink), ptr::null_mut()) };
+
+ match tap_ipv6_status {
+ // Enabled
+ 0 => Ok(true),
+ // Disabled
+ 1 => Ok(false),
+ // Failure
+ 2 => Err(Error::from(ErrorKind::GetIpv6Status)),
+ // Unexpected value
+ _ => {
+ error!("Unexpected return code from GetTapInterfaceIpv6Status");
+ Err(Error::from(ErrorKind::GetIpv6Status))
+ }
+ }
+}
+
+extern "system" {
+ #[link_name(GetTapInterfaceIpv6Status)]
+ fn GetTapInterfaceIpv6Status(sink: Option<ErrorSink>, sink_context: *mut c_void) -> u32;
+}
diff --git a/windows/winroute/extras.sln b/windows/winroute/extras.sln
new file mode 100644
index 0000000000..28d1d51341
--- /dev/null
+++ b/windows/winroute/extras.sln
@@ -0,0 +1,57 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2027
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader", "src\extras\loader\loader.vcxproj", "{227C50F4-D9F6-4D9A-84A0-33CE84432D0D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF}
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4} = {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winroute", "src\winroute\winroute.vcxproj", "{89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF} = {B52E2D10-A94A-4605-914A-2DCEF6A757EF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcommon", "..\windows-libraries\src\libcommon\libcommon.vcxproj", "{B52E2D10-A94A-4605-914A-2DCEF6A757EF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Debug|x64.ActiveCfg = Debug|x64
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Debug|x64.Build.0 = Debug|x64
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Debug|x86.ActiveCfg = Debug|Win32
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Debug|x86.Build.0 = Debug|Win32
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Release|x64.ActiveCfg = Release|x64
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Release|x64.Build.0 = Release|x64
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Release|x86.ActiveCfg = Release|Win32
+ {227C50F4-D9F6-4D9A-84A0-33CE84432D0D}.Release|x86.Build.0 = Release|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x64.ActiveCfg = Debug|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x64.Build.0 = Debug|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x86.ActiveCfg = Debug|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Debug|x86.Build.0 = Debug|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x64.ActiveCfg = Release|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x64.Build.0 = Release|x64
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x86.ActiveCfg = Release|Win32
+ {89C5CDE8-04DB-4D9C-A8D8-7F786DAFB6D4}.Release|x86.Build.0 = Release|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.ActiveCfg = Debug|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x64.Build.0 = Debug|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.ActiveCfg = Debug|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Debug|x86.Build.0 = Debug|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.ActiveCfg = Release|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x64.Build.0 = Release|x64
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.ActiveCfg = Release|Win32
+ {B52E2D10-A94A-4605-914A-2DCEF6A757EF}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B11B65B3-3DA6-495C-B0F5-5ACBB2F1743D}
+ EndGlobalSection
+EndGlobal
diff --git a/windows/winroute/src/extras/loader/loader.cpp b/windows/winroute/src/extras/loader/loader.cpp
new file mode 100644
index 0000000000..cb775538f9
--- /dev/null
+++ b/windows/winroute/src/extras/loader/loader.cpp
@@ -0,0 +1,10 @@
+#include "stdafx.h"
+#include "../../winroute/winroute.h"
+
+int main()
+{
+ const auto status = GetTapInterfaceIpv6Status(nullptr, nullptr);
+
+ return 0;
+}
+
diff --git a/windows/winroute/src/extras/loader/loader.vcxproj b/windows/winroute/src/extras/loader/loader.vcxproj
new file mode 100644
index 0000000000..bf010c1fd0
--- /dev/null
+++ b/windows/winroute/src/extras/loader/loader.vcxproj
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="loader.cpp" />
+ <ClCompile Include="stdafx.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{227C50F4-D9F6-4D9A-84A0-33CE84432D0D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>loader</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(SolutionDir)bin\temp\$(Platform)-$(Configuration)\$(ProjectName)\</IntDir>
+ <OutDir>$(SolutionDir)bin\$(Platform)-$(Configuration)\</OutDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>winroute.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>winroute.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>winroute.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(SolutionDir)/bin/$(Platform)-$(Configuration)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>winroute.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/windows/winroute/src/extras/loader/loader.vcxproj.filters b/windows/winroute/src/extras/loader/loader.vcxproj.filters
new file mode 100644
index 0000000000..cd0f4643c7
--- /dev/null
+++ b/windows/winroute/src/extras/loader/loader.vcxproj.filters
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="loader.cpp" />
+ <ClCompile Include="stdafx.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/windows/winroute/src/extras/loader/stdafx.cpp b/windows/winroute/src/extras/loader/stdafx.cpp
new file mode 100644
index 0000000000..8d6fa45555
--- /dev/null
+++ b/windows/winroute/src/extras/loader/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// loader.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/windows/winroute/src/extras/loader/stdafx.h b/windows/winroute/src/extras/loader/stdafx.h
new file mode 100644
index 0000000000..b005a839de
--- /dev/null
+++ b/windows/winroute/src/extras/loader/stdafx.h
@@ -0,0 +1,15 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/windows/winroute/src/extras/loader/targetver.h b/windows/winroute/src/extras/loader/targetver.h
new file mode 100644
index 0000000000..87c0086de7
--- /dev/null
+++ b/windows/winroute/src/extras/loader/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/windows/winroute/src/winroute/InterfacePair.h b/windows/winroute/src/winroute/InterfacePair.h
index 3926ba0430..9582bac3cd 100644
--- a/windows/winroute/src/winroute/InterfacePair.h
+++ b/windows/winroute/src/winroute/InterfacePair.h
@@ -14,8 +14,8 @@ public:
private:
- MIB_IPINTERFACE_ROW IPv4Iface;
- MIB_IPINTERFACE_ROW IPv6Iface;
+ MIB_IPINTERFACE_ROW IPv4Iface = { 0 };
+ MIB_IPINTERFACE_ROW IPv6Iface = { 0 };
void InitializeInterface(PMIB_IPINTERFACE_ROW iface);
bool HasIPv4();
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.cpp b/windows/winroute/src/winroute/NetworkInterfaces.cpp
index a0a4d53db8..2aa352de27 100644
--- a/windows/winroute/src/winroute/NetworkInterfaces.cpp
+++ b/windows/winroute/src/winroute/NetworkInterfaces.cpp
@@ -74,19 +74,7 @@ NetworkInterfaces::NetworkInterfaces()
bool NetworkInterfaces::SetTopMetricForInterfacesByAlias(const wchar_t * deviceAlias)
{
- NET_LUID targetIfaceLuid;
- DWORD success = 0;
- success = ConvertInterfaceAliasToLuid(deviceAlias, &targetIfaceLuid);
- if (success != NO_ERROR)
- {
- std::wstringstream ss;
- ss << L"Failed to convert interface alias '"
- << deviceAlias
- << "' into LUID: "
- << success;
- throw std::runtime_error(common::string::ToAnsi(ss.str()));
- }
- return SetTopMetricForInterfacesWithLuid(targetIfaceLuid);
+ return SetTopMetricForInterfacesWithLuid(GetInterfaceLuid(deviceAlias));
}
bool NetworkInterfaces::SetTopMetricForInterfacesWithLuid(NET_LUID targetIfaceId)
@@ -107,3 +95,41 @@ NetworkInterfaces::~NetworkInterfaces()
{
FreeMibTable(mInterfaces);
}
+
+//static
+NET_LUID NetworkInterfaces::GetInterfaceLuid(const std::wstring &interfaceAlias)
+{
+ NET_LUID interfaceLuid;
+
+ const auto status = ConvertInterfaceAliasToLuid(interfaceAlias.c_str(), &interfaceLuid);
+
+ if (status != NO_ERROR)
+ {
+ std::wstringstream ss;
+
+ ss << L"Failed to convert interface alias '"
+ << interfaceAlias
+ << "' into LUID. Error: "
+ << status;
+
+ throw std::runtime_error(common::string::ToAnsi(ss.str()));
+ }
+
+ return interfaceLuid;
+}
+
+const MIB_IPINTERFACE_ROW *NetworkInterfaces::GetInterface(NET_LUID interfaceLuid, ADDRESS_FAMILY interfaceFamily)
+{
+ for (unsigned int i = 0; i < mInterfaces->NumEntries; ++i)
+ {
+ MIB_IPINTERFACE_ROW &candidateInterface = mInterfaces->Table[i];
+
+ if (candidateInterface.InterfaceLuid.Value == interfaceLuid.Value
+ && candidateInterface.Family == interfaceFamily)
+ {
+ return &candidateInterface;
+ }
+ }
+
+ return nullptr;
+}
diff --git a/windows/winroute/src/winroute/NetworkInterfaces.h b/windows/winroute/src/winroute/NetworkInterfaces.h
index b29ce0fa44..bf1d53dddf 100644
--- a/windows/winroute/src/winroute/NetworkInterfaces.h
+++ b/windows/winroute/src/winroute/NetworkInterfaces.h
@@ -6,6 +6,7 @@
#include <iphlpapi.h>
#include <netioapi.h>
#include <cstdint>
+#include <string>
class NetworkInterfaces
{
@@ -15,11 +16,17 @@ private:
bool HasHighestMetric(PMIB_IPINTERFACE_ROW targetIface);
public:
+ NetworkInterfaces(const NetworkInterfaces &) = delete;
+ NetworkInterfaces &operator=(const NetworkInterfaces &) = delete;
+
void EnsureIfaceMetricIsHighest(NET_LUID interfaceLuid);
NetworkInterfaces();
bool SetTopMetricForInterfacesByAlias(const wchar_t *deviceAlias);
bool SetTopMetricForInterfacesWithLuid(NET_LUID targetIface);
~NetworkInterfaces();
+
+ static NET_LUID GetInterfaceLuid(const std::wstring &interfaceAlias);
+ const MIB_IPINTERFACE_ROW *GetInterface(NET_LUID interfaceLuid, ADDRESS_FAMILY interfaceFamily);
};
const static uint32_t MAX_METRIC = 1;
diff --git a/windows/winroute/src/winroute/winroute.cpp b/windows/winroute/src/winroute/winroute.cpp
index c417bd44ea..b9f10e3786 100644
--- a/windows/winroute/src/winroute/winroute.cpp
+++ b/windows/winroute/src/winroute/winroute.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "winroute.h"
#include "NetworkInterfaces.h"
+#include "libcommon/error.h"
#include <cstdint>
#include <stdexcept>
@@ -35,3 +36,47 @@ WinRoute_EnsureTopMetric(
}
};
+extern "C"
+WINROUTE_LINKAGE
+TAP_IPV6_STATUS
+WINROUTE_API
+GetTapInterfaceIpv6Status(
+ WinRouteErrorSink errorSink,
+ void* errorSinkContext
+)
+{
+ try
+ {
+ MIB_IPINTERFACE_ROW interface = { 0 };
+
+ interface.InterfaceLuid = NetworkInterfaces::GetInterfaceLuid(L"Mullvad");
+ interface.Family = AF_INET6;
+
+ const auto status = GetIpInterfaceEntry(&interface);
+
+ if (NO_ERROR == status)
+ {
+ return TAP_IPV6_STATUS::ENABLED;
+ }
+
+ if (ERROR_NOT_FOUND == status)
+ {
+ return TAP_IPV6_STATUS::DISABLED;
+ }
+
+ common::error::Throw("Resolve TAP IPv6 interface", status);
+ }
+ catch (std::exception &err)
+ {
+ if (nullptr != errorSink)
+ {
+ errorSink(err.what(), errorSinkContext);
+ }
+
+ return TAP_IPV6_STATUS::FAILURE;
+ }
+ catch (...)
+ {
+ return TAP_IPV6_STATUS::FAILURE;
+ }
+}
diff --git a/windows/winroute/src/winroute/winroute.def b/windows/winroute/src/winroute/winroute.def
index d409889c50..2ea9222482 100644
--- a/windows/winroute/src/winroute/winroute.def
+++ b/windows/winroute/src/winroute/winroute.def
@@ -1,3 +1,4 @@
LIBRARY winroute
EXPORTS
- WinRoute_EnsureTopMetric \ No newline at end of file
+ WinRoute_EnsureTopMetric
+ GetTapInterfaceIpv6Status
diff --git a/windows/winroute/src/winroute/winroute.h b/windows/winroute/src/winroute/winroute.h
index 6bf0c3b882..6b500cee7e 100644
--- a/windows/winroute/src/winroute/winroute.h
+++ b/windows/winroute/src/winroute/winroute.h
@@ -28,3 +28,23 @@ WinRoute_EnsureTopMetric(
WinRouteErrorSink errorSink,
void* errorSinkContext
);
+
+enum class TAP_IPV6_STATUS : uint32_t
+{
+ ENABLED = 0,
+ DISABLED = 1,
+ FAILURE = 2,
+};
+
+//
+// This has nothing to do with routing.
+// We should probably rename this module and use it to gather one-off network functions.
+//
+extern "C"
+WINROUTE_LINKAGE
+TAP_IPV6_STATUS
+WINROUTE_API
+GetTapInterfaceIpv6Status(
+ WinRouteErrorSink errorSink,
+ void* errorSinkContext
+);