summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'talpid-core/src')
-rw-r--r--talpid-core/src/firewall/windows/mod.rs11
-rw-r--r--talpid-core/src/firewall/windows/route.rs63
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;
+}