diff options
Diffstat (limited to 'talpid-core/src')
| -rw-r--r-- | talpid-core/src/firewall/windows/mod.rs | 11 | ||||
| -rw-r--r-- | talpid-core/src/firewall/windows/route.rs | 63 |
2 files changed, 74 insertions, 0 deletions
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; +} |
