diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2018-06-27 11:45:57 +0100 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2018-06-27 11:45:57 +0100 |
| commit | 0f0ef6ff2447ce684d75920d259d84747962440f (patch) | |
| tree | 6022b306d0f74b942a88251e7d1ee57759f567c4 /talpid-core | |
| parent | fea7311975601287faed8182d48fa576483d384b (diff) | |
| parent | f97d2eb4aa9677802f7faff12d03459e0c173291 (diff) | |
| download | mullvadvpn-0f0ef6ff2447ce684d75920d259d84747962440f.tar.xz mullvadvpn-0f0ef6ff2447ce684d75920d259d84747962440f.zip | |
Merge branch 'windows-route'
Diffstat (limited to 'talpid-core')
| -rw-r--r-- | talpid-core/build.rs | 59 | ||||
| -rw-r--r-- | talpid-core/src/firewall/windows/mod.rs | 11 | ||||
| -rw-r--r-- | talpid-core/src/firewall/windows/route.rs | 63 |
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; +} |
