summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-04-16 13:05:17 +0200
committerDavid Lönnhager <david.l@mullvad.net>2021-07-02 09:54:19 +0200
commitfb2b7e9778350bace1ea636b8f11c76890eb5b98 (patch)
tree83f984fa943d896c5937734983f00668fb1cd771
parentaf7d9b09663672d0a8a8a84c02387a9749a3bf98 (diff)
downloadmullvadvpn-fb2b7e9778350bace1ea636b8f11c76890eb5b98.tar.xz
mullvadvpn-fb2b7e9778350bace1ea636b8f11c76890eb5b98.zip
Notify tunnel of errors while registering addresses in driver
-rw-r--r--mullvad-cli/src/format.rs2
-rw-r--r--mullvad-management-interface/proto/management_interface.proto1
-rw-r--r--mullvad-management-interface/src/types.rs4
-rw-r--r--talpid-core/src/split_tunnel/windows/mod.rs27
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs9
-rw-r--r--talpid-types/src/tunnel.rs5
6 files changed, 38 insertions, 10 deletions
diff --git a/mullvad-cli/src/format.rs b/mullvad-cli/src/format.rs
index 52014076c3..b056ffff53 100644
--- a/mullvad-cli/src/format.rs
+++ b/mullvad-cli/src/format.rs
@@ -160,6 +160,8 @@ fn error_state_to_string(error_state: &ErrorState) -> String {
IsOffline => "This device is offline, no tunnels can be established",
#[cfg(target_os = "android")]
VpnPermissionDenied => "The Android VPN permission was denied when creating the tunnel",
+ #[cfg(target_os = "windows")]
+ SplitTunnelError => "The split tunneling module reported an error",
#[cfg(not(target_os = "android"))]
_ => unreachable!("unknown error cause"),
};
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index e5ee4cb23f..39bfa20669 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -108,6 +108,7 @@ message ErrorState {
TUNNEL_PARAMETER_ERROR = 5;
IS_OFFLINE = 6;
VPN_PERMISSION_DENIED = 7;
+ SPLIT_TUNNEL_ERROR = 8;
}
enum GenerationError {
diff --git a/mullvad-management-interface/src/types.rs b/mullvad-management-interface/src/types.rs
index bebdb14d77..abd0b3a17c 100644
--- a/mullvad-management-interface/src/types.rs
+++ b/mullvad-management-interface/src/types.rs
@@ -143,6 +143,10 @@ impl From<mullvad_types::states::TunnelState> for TunnelState {
talpid_tunnel::ErrorStateCause::VpnPermissionDenied => {
i32::from(Cause::VpnPermissionDenied)
}
+ #[cfg(target_os = "windows")]
+ talpid_tunnel::ErrorStateCause::SplitTunnelError => {
+ i32::from(Cause::SplitTunnelError)
+ }
},
blocking_error: error_state.block_failure().map(map_firewall_error),
auth_fail_reason: if let talpid_tunnel::ErrorStateCause::AuthFailed(
diff --git a/talpid-core/src/split_tunnel/windows/mod.rs b/talpid-core/src/split_tunnel/windows/mod.rs
index c8a0eb183d..bf7ef40ee6 100644
--- a/talpid-core/src/split_tunnel/windows/mod.rs
+++ b/talpid-core/src/split_tunnel/windows/mod.rs
@@ -3,10 +3,12 @@ mod windows;
use crate::{
tunnel::TunnelMetadata,
+ tunnel_state_machine::TunnelCommand,
winnet::{
self, get_best_default_route, interface_luid_to_ip, WinNetAddrFamily, WinNetCallbackHandle,
},
};
+use futures::channel::mpsc;
use lazy_static::lazy_static;
use std::{
ffi::OsStr,
@@ -14,9 +16,9 @@ use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr},
os::windows::io::{AsRawHandle, RawHandle},
ptr,
- sync::{Arc, Mutex},
+ sync::{Arc, Mutex, Weak},
};
-use talpid_types::ErrorExt;
+use talpid_types::{tunnel::ErrorStateCause, ErrorExt};
use winapi::{
shared::minwindef::{FALSE, TRUE},
um::{
@@ -77,6 +79,7 @@ pub struct SplitTunnel {
event_thread: Option<std::thread::JoinHandle<()>>,
quit_event: RawHandle,
_route_change_callback: Option<WinNetCallbackHandle>,
+ daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>,
}
struct EventThreadContext {
@@ -88,7 +91,7 @@ unsafe impl Send for EventThreadContext {}
impl SplitTunnel {
/// Initialize the driver.
- pub fn new() -> Result<Self, Error> {
+ pub fn new(daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>) -> Result<Self, Error> {
let handle = driver::DeviceHandle::new().map_err(Error::InitializationFailed)?;
let mut event_overlapped: OVERLAPPED = unsafe { mem::zeroed() };
@@ -248,6 +251,7 @@ impl SplitTunnel {
event_thread: Some(event_thread),
quit_event,
_route_change_callback: None,
+ daemon_tx,
})
}
@@ -303,6 +307,7 @@ impl SplitTunnel {
let context = SplitTunnelDefaultRouteChangeHandlerContext::new(
self.handle.clone(),
+ self.daemon_tx.clone(),
tunnel_ipv4,
tunnel_ipv6,
internet_ipv4,
@@ -399,6 +404,7 @@ impl Drop for SplitTunnel {
struct SplitTunnelDefaultRouteChangeHandlerContext {
handle: Arc<Mutex<driver::DeviceHandle>>,
+ pub daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>,
pub tunnel_ipv4: Ipv4Addr,
pub tunnel_ipv6: Option<Ipv6Addr>,
pub internet_ipv4: Ipv4Addr,
@@ -408,6 +414,7 @@ struct SplitTunnelDefaultRouteChangeHandlerContext {
impl SplitTunnelDefaultRouteChangeHandlerContext {
pub fn new(
handle: Arc<Mutex<driver::DeviceHandle>>,
+ daemon_tx: Weak<mpsc::UnboundedSender<TunnelCommand>>,
tunnel_ipv4: Ipv4Addr,
tunnel_ipv6: Option<Ipv6Addr>,
internet_ipv4: Ipv4Addr,
@@ -415,6 +422,7 @@ impl SplitTunnelDefaultRouteChangeHandlerContext {
) -> Self {
SplitTunnelDefaultRouteChangeHandlerContext {
handle,
+ daemon_tx,
tunnel_ipv4,
tunnel_ipv6,
internet_ipv4,
@@ -442,6 +450,13 @@ unsafe extern "system" fn split_tunnel_default_route_change_handler(
// Update the "internet interface" IP when best default route changes
let ctx = &mut *(ctx as *mut SplitTunnelDefaultRouteChangeHandlerContext);
+ let daemon_tx = ctx.daemon_tx.upgrade();
+ let maybe_send = move |content| {
+ if let Some(tx) = daemon_tx {
+ let _ = tx.unbounded_send(content);
+ }
+ };
+
let result = match event_type {
winnet::WinNetDefaultRouteChangeEventType::DefaultRouteChanged => {
let ip = interface_luid_to_ip(address_family.clone(), default_route.interface_luid);
@@ -450,7 +465,7 @@ unsafe extern "system" fn split_tunnel_default_route_change_handler(
Ok(Some(ip)) => ip,
Ok(None) => {
log::error!("Failed to obtain new default route address: none found",);
- // TODO: Send tunnel command
+ maybe_send(TunnelCommand::Block(ErrorStateCause::SplitTunnelError));
return;
}
Err(error) => {
@@ -458,7 +473,7 @@ unsafe extern "system" fn split_tunnel_default_route_change_handler(
"{}",
error.display_chain_with_msg("Failed to obtain new default route address")
);
- // TODO: Send tunnel command
+ maybe_send(TunnelCommand::Block(ErrorStateCause::SplitTunnelError));
return;
}
};
@@ -491,10 +506,10 @@ unsafe extern "system" fn split_tunnel_default_route_change_handler(
};
if let Err(error) = result {
- // TODO: Send tunnel command
log::error!(
"{}",
error.display_chain_with_msg("Failed to register new addresses in split tunnel driver")
);
+ maybe_send(TunnelCommand::Block(ErrorStateCause::SplitTunnelError));
}
}
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 1ea7365688..2f8f6cea0c 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -218,7 +218,7 @@ impl TunnelStateMachine {
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: impl AsRef<Path>,
- commands: mpsc::UnboundedReceiver<TunnelCommand>,
+ commands_rx: mpsc::UnboundedReceiver<TunnelCommand>,
reset_firewall: bool,
#[cfg(target_os = "android")] android_context: AndroidContext,
#[cfg(windows)] exclude_paths: Vec<OsString>,
@@ -243,7 +243,7 @@ impl TunnelStateMachine {
)
.map_err(Error::InitDnsMonitorError)?;
let mut offline_monitor = offline::spawn_monitor(
- command_tx,
+ command_tx.clone(),
#[cfg(target_os = "linux")]
route_manager
.handle()
@@ -256,7 +256,8 @@ impl TunnelStateMachine {
let is_offline = offline_monitor.is_offline().await;
#[cfg(windows)]
- let split_tunnel = split_tunnel::SplitTunnel::new().map_err(Error::InitSplitTunneling)?;
+ let split_tunnel =
+ split_tunnel::SplitTunnel::new(command_tx).map_err(Error::InitSplitTunneling)?;
#[cfg(windows)]
split_tunnel
.set_paths(&exclude_paths)
@@ -287,7 +288,7 @@ impl TunnelStateMachine {
Ok(TunnelStateMachine {
current_state: Some(initial_state),
- commands: commands.fuse(),
+ commands: commands_rx.fuse(),
shared_values,
})
}
diff --git a/talpid-types/src/tunnel.rs b/talpid-types/src/tunnel.rs
index b3a75999b4..3c300c30cc 100644
--- a/talpid-types/src/tunnel.rs
+++ b/talpid-types/src/tunnel.rs
@@ -104,6 +104,9 @@ pub enum ErrorStateCause {
/// The Android VPN permission was denied.
#[cfg(target_os = "android")]
VpnPermissionDenied,
+ /// Error reported by split tunnel module.
+ #[cfg(target_os = "windows")]
+ SplitTunnelError,
}
/// Errors that can occur when generating tunnel parameters.
@@ -194,6 +197,8 @@ impl fmt::Display for ErrorStateCause {
IsOffline => "This device is offline, no tunnels can be established",
#[cfg(target_os = "android")]
VpnPermissionDenied => "The Android VPN permission was denied when creating the tunnel",
+ #[cfg(target_os = "windows")]
+ SplitTunnelError => "The split tunneling module reported an error",
};
write!(f, "{}", description)