summaryrefslogtreecommitdiffhomepage
path: root/talpid-core
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2018-06-27 11:45:57 +0100
committerEmīls Piņķis <emils@mullvad.net>2018-06-27 11:45:57 +0100
commit0f0ef6ff2447ce684d75920d259d84747962440f (patch)
tree6022b306d0f74b942a88251e7d1ee57759f567c4 /talpid-core
parentfea7311975601287faed8182d48fa576483d384b (diff)
parentf97d2eb4aa9677802f7faff12d03459e0c173291 (diff)
downloadmullvadvpn-0f0ef6ff2447ce684d75920d259d84747962440f.tar.xz
mullvadvpn-0f0ef6ff2447ce684d75920d259d84747962440f.zip
Merge branch 'windows-route'
Diffstat (limited to 'talpid-core')
-rw-r--r--talpid-core/build.rs59
-rw-r--r--talpid-core/src/firewall/windows/mod.rs11
-rw-r--r--talpid-core/src/firewall/windows/route.rs63
3 files changed, 94 insertions, 39 deletions
diff --git a/talpid-core/build.rs b/talpid-core/build.rs
index 7b433cf28f..b4c66db87c 100644
--- a/talpid-core/build.rs
+++ b/talpid-core/build.rs
@@ -3,19 +3,12 @@ mod win {
use std::env;
use std::path::PathBuf;
- static WINFW_BUILD_DIR: &'static str = "..\\windows\\winfw\\bin";
- static WINDNS_BUILD_DIR: &'static str = "..\\windows\\windns\\bin";
+ pub static WINFW_BUILD_DIR: &'static str = "..\\windows\\winfw\\bin";
+ pub static WINDNS_BUILD_DIR: &'static str = "..\\windows\\windns\\bin";
+ pub static WINROUTE_BUILD_DIR: &'static str = "..\\windows\\winroute\\bin";
- pub fn default_winfw_output_dir() -> PathBuf {
- manifest_dir()
- .join(WINFW_BUILD_DIR)
- .join(&target_platform_dir())
- }
-
- pub fn default_windns_output_dir() -> PathBuf {
- manifest_dir()
- .join(WINDNS_BUILD_DIR)
- .join(&target_platform_dir())
+ pub fn default_windows_build_artifact_dir(build_dir: &str) -> PathBuf {
+ manifest_dir().join(build_dir).join(&target_platform_dir())
}
fn target_platform_dir() -> PathBuf {
@@ -43,39 +36,27 @@ mod win {
"Debug"
}
}
+
+ pub fn declare_library(env_var: &str, default_dir: &str, lib_name: &str) {
+ println!("cargo:rerun-if-env-changed={}", env_var);
+ let lib_dir = env::var_os(env_var)
+ .map(PathBuf::from)
+ .unwrap_or_else(|| default_windows_build_artifact_dir(default_dir));
+ println!("cargo:rustc-link-search={}", lib_dir.display());
+ println!("cargo:rustc-link-lib=dylib={}", lib_name);
+ }
}
#[cfg(windows)]
fn main() {
- use std::env;
- use std::path::PathBuf;
use win::*;
- const WINFW_LIB_DIR_VAR: &str = "WINFW_LIB_DIR";
- println!("cargo:rerun-if-env-changed={}", WINFW_LIB_DIR_VAR);
- let winfw_dir = env::var_os(WINFW_LIB_DIR_VAR)
- .map(PathBuf::from)
- .unwrap_or_else(default_winfw_output_dir);
-
- println!(
- "cargo:rustc-link-search={}",
- winfw_dir
- .to_str()
- .expect("failed to construct path for winfw include directory")
- );
- println!("cargo:rustc-link-lib=dylib=winfw");
-
- let windns_dir = env::var_os("WINDNS_INCLUDE_DIR")
- .map(PathBuf::from)
- .unwrap_or_else(default_windns_output_dir);
- println!(
- "cargo:rustc-link-search={}",
- windns_dir
- .to_str()
- .expect("failed to construct path for windns include directory")
- );
-
- println!("cargo:rustc-link-lib=dylib=windns");
+ const WINFW_DIR_VAR: &str = "WINFW_LIB_DIR";
+ const WINDNS_DIR_VAR: &str = "WINDNS_LIB_DIR";
+ const WINROUTE_DIR_VAR: &str = "WINROUTE_LIB_DIR";
+ declare_library(WINFW_DIR_VAR, WINFW_BUILD_DIR, "winfw");
+ declare_library(WINDNS_DIR_VAR, WINDNS_BUILD_DIR, "windns");
+ declare_library(WINROUTE_DIR_VAR, WINROUTE_BUILD_DIR, "winroute");
}
#[cfg(not(windows))]
diff --git a/talpid-core/src/firewall/windows/mod.rs b/talpid-core/src/firewall/windows/mod.rs
index 01c6dd4c53..4068cd0970 100644
--- a/talpid-core/src/firewall/windows/mod.rs
+++ b/talpid-core/src/firewall/windows/mod.rs
@@ -14,6 +14,7 @@ use self::widestring::WideCString;
#[macro_use]
mod ffi;
mod dns;
+mod route;
mod system_state;
use self::dns::WinDns;
@@ -48,6 +49,7 @@ error_chain!{
links {
WinDns(dns::Error, dns::ErrorKind) #[doc = "WinDNS failure"];
+ WinRoute(route::Error, route::ErrorKind) #[doc = "Failure to modify system routing metrics"];
}
}
@@ -157,6 +159,15 @@ impl WindowsFirewall {
};
self.dns.set_dns(&vec![tunnel_metadata.gateway.into()])?;
+
+ let metrics_set = route::ensure_top_metric_for_interface(&tunnel_metadata.interface)?;
+ if metrics_set {
+ debug!("Network interface metrics were changed");
+ } else {
+ debug!("Network interface metrics were not changed");
+ }
+
+
unsafe {
WinFw_ApplyPolicyConnected(
winfw_settings,
diff --git a/talpid-core/src/firewall/windows/route.rs b/talpid-core/src/firewall/windows/route.rs
new file mode 100644
index 0000000000..6ecf336956
--- /dev/null
+++ b/talpid-core/src/firewall/windows/route.rs
@@ -0,0 +1,63 @@
+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;
+}