summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2024-05-24 13:50:11 +0200
committerDavid Lönnhager <david.l@mullvad.net>2024-05-29 12:55:01 +0200
commit461bb179af039b2ab9622f8df2c2bffd09a21b77 (patch)
tree38f67fdda816084a54d888d3f4df0a5d3754e85a
parent2b04fed8d6a486d97af47f1add45b0eeb1071db8 (diff)
downloadmullvadvpn-461bb179af039b2ab9622f8df2c2bffd09a21b77.tar.xz
mullvadvpn-461bb179af039b2ab9622f8df2c2bffd09a21b77.zip
Add error state cause for full disk permissions error
-rw-r--r--gui/src/main/daemon-rpc.ts6
-rw-r--r--gui/src/shared/notifications/error.ts17
-rw-r--r--mullvad-management-interface/proto/management_interface.proto1
-rw-r--r--mullvad-management-interface/src/types/conversions/states.rs10
-rw-r--r--talpid-core/src/split_tunnel/macos/mod.rs17
-rw-r--r--talpid-core/src/split_tunnel/macos/process.rs10
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs6
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs6
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs8
-rw-r--r--talpid-types/src/tunnel.rs5
10 files changed, 64 insertions, 22 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index 10e39f020d..c51524f1ee 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -1046,6 +1046,12 @@ function convertFromTunnelStateError(state: grpcTypes.ErrorState.AsObject): Erro
...baseError,
cause: ErrorStateCause.splitTunnelError,
};
+ case grpcTypes.ErrorState.Cause.NEED_FULL_DISK_PERMISSIONS:
+ // TODO: handle correctly
+ return {
+ ...baseError,
+ cause: ErrorStateCause.splitTunnelError,
+ };
case grpcTypes.ErrorState.Cause.VPN_PERMISSION_DENIED:
// VPN_PERMISSION_DENIED is only ever created on Android
throw invalidErrorStateCause;
diff --git a/gui/src/shared/notifications/error.ts b/gui/src/shared/notifications/error.ts
index 673d6cea28..1d36b7e1de 100644
--- a/gui/src/shared/notifications/error.ts
+++ b/gui/src/shared/notifications/error.ts
@@ -183,10 +183,18 @@ function getMessage(errorState: ErrorState): string {
'Your device is offline. The tunnel will automatically connect once your device is back online.',
);
case ErrorStateCause.splitTunnelError:
- return messages.pgettext(
- 'notifications',
- 'Unable to communicate with Mullvad kernel driver. Try reconnecting or send a problem report.',
- );
+ switch (process.platform ?? window.env.platform) {
+ case 'darwin':
+ return messages.pgettext(
+ 'notifications',
+ 'Failed to enable split tunneling. Please try again or disable it.',
+ );
+ default:
+ return messages.pgettext(
+ 'notifications',
+ 'Unable to communicate with Mullvad kernel driver. Try reconnecting or send a problem report.',
+ );
+ }
}
}
}
@@ -265,6 +273,7 @@ function getActions(errorState: ErrorState): InAppNotificationAction | void {
},
};
} else if (errorState.cause === ErrorStateCause.splitTunnelError) {
+ // TODO: macos: handle this and full disk access error
return {
type: 'troubleshoot-dialog',
troubleshoot: {
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index efe9f9eb87..3f9de9b189 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -142,6 +142,7 @@ message ErrorState {
IS_OFFLINE = 7;
VPN_PERMISSION_DENIED = 8;
SPLIT_TUNNEL_ERROR = 9;
+ NEED_FULL_DISK_PERMISSIONS = 10;
}
enum AuthFailedError {
diff --git a/mullvad-management-interface/src/types/conversions/states.rs b/mullvad-management-interface/src/types/conversions/states.rs
index 881cbc6c9a..58766a9925 100644
--- a/mullvad-management-interface/src/types/conversions/states.rs
+++ b/mullvad-management-interface/src/types/conversions/states.rs
@@ -107,6 +107,10 @@ impl From<mullvad_types::states::TunnelState> for proto::TunnelState {
talpid_tunnel::ErrorStateCause::SplitTunnelError => {
i32::from(Cause::SplitTunnelError)
}
+ #[cfg(target_os = "macos")]
+ talpid_tunnel::ErrorStateCause::NeedFullDiskPermissions => {
+ i32::from(Cause::NeedFullDiskPermissions)
+ }
},
blocking_error: error_state.block_failure().map(map_firewall_error),
auth_failed_error: mullvad_types::auth_failed::AuthFailed::try_from(
@@ -325,10 +329,14 @@ impl TryFrom<proto::TunnelState> for mullvad_types::states::TunnelState {
Ok(proto::error_state::Cause::VpnPermissionDenied) => {
talpid_tunnel::ErrorStateCause::VpnPermissionDenied
}
- #[cfg(target_os = "windows")]
+ #[cfg(any(target_os = "windows", target_os = "macos"))]
Ok(proto::error_state::Cause::SplitTunnelError) => {
talpid_tunnel::ErrorStateCause::SplitTunnelError
}
+ #[cfg(target_os = "macos")]
+ Ok(proto::error_state::Cause::NeedFullDiskPermissions) => {
+ talpid_tunnel::ErrorStateCause::NeedFullDiskPermissions
+ }
_ => {
return Err(FromProtobufTypeError::InvalidArgument(
"invalid error cause",
diff --git a/talpid-core/src/split_tunnel/macos/mod.rs b/talpid-core/src/split_tunnel/macos/mod.rs
index 980097d94b..d43c124043 100644
--- a/talpid-core/src/split_tunnel/macos/mod.rs
+++ b/talpid-core/src/split_tunnel/macos/mod.rs
@@ -42,6 +42,16 @@ impl Error {
}
}
+impl From<&Error> for ErrorStateCause {
+ fn from(value: &Error) -> Self {
+ match value {
+ Error::Process(error) => ErrorStateCause::from(error),
+ _v if _v.is_offline() => ErrorStateCause::IsOffline,
+ _ => ErrorStateCause::SplitTunnelError,
+ }
+ }
+}
+
/// Split tunneling actor
pub struct SplitTunnel {
state: State,
@@ -171,6 +181,10 @@ impl SplitTunnel {
/// Handle process monitor unexpectedly stopping
fn handle_process_monitor_shutdown(&mut self, result: Result<(), process::Error>) {
+ let cause = match result {
+ Ok(_) => ErrorStateCause::SplitTunnelError,
+ Err(ref error) => ErrorStateCause::from(error),
+ };
match result {
Ok(()) => log::error!("Process monitor stopped unexpectedly with no error"),
Err(error) => {
@@ -185,8 +199,7 @@ impl SplitTunnel {
// decisions for new processes
if self.state.active() {
if let Some(tunnel_tx) = self.tunnel_tx.upgrade() {
- let _ = tunnel_tx
- .unbounded_send(TunnelCommand::Block(ErrorStateCause::SplitTunnelError));
+ let _ = tunnel_tx.unbounded_send(TunnelCommand::Block(cause));
}
}
diff --git a/talpid-core/src/split_tunnel/macos/process.rs b/talpid-core/src/split_tunnel/macos/process.rs
index f913b9bb49..013aca34e4 100644
--- a/talpid-core/src/split_tunnel/macos/process.rs
+++ b/talpid-core/src/split_tunnel/macos/process.rs
@@ -21,6 +21,7 @@ use std::{
time::Duration,
};
use talpid_platform_metadata::MacosVersion;
+use talpid_types::tunnel::ErrorStateCause;
use tokio::io::{AsyncBufReadExt, BufReader};
const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(3);
@@ -56,6 +57,15 @@ pub enum Error {
FindProcessPath(#[source] io::Error, u32),
}
+impl From<&Error> for ErrorStateCause {
+ fn from(value: &Error) -> Self {
+ match value {
+ Error::NeedFullDiskPermissions => ErrorStateCause::NeedFullDiskPermissions,
+ _ => ErrorStateCause::SplitTunnelError,
+ }
+ }
+}
+
pub struct ProcessMonitor(());
#[derive(Debug)]
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index 80ca26ec56..395a67a057 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -353,11 +353,9 @@ impl ConnectedState {
}
}
Err(error) => {
+ let cause = ErrorStateCause::from(&error);
let _ = result_tx.send(Err(error));
- return self.disconnect(
- shared_values,
- AfterDisconnect::Block(ErrorStateCause::SplitTunnelError),
- );
+ return self.disconnect(shared_values, AfterDisconnect::Block(cause));
}
}
SameState(self)
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index 5df58a6adf..a4267d0d56 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -498,11 +498,9 @@ impl ConnectingState {
}
}
Err(error) => {
+ let cause = ErrorStateCause::from(&error);
let _ = result_tx.send(Err(error));
- return self.disconnect(
- shared_values,
- AfterDisconnect::Block(ErrorStateCause::SplitTunnelError),
- );
+ return self.disconnect(shared_values, AfterDisconnect::Block(cause));
}
}
SameState(self)
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index e31dec3624..a74d7e39b5 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -540,13 +540,7 @@ impl SharedTunnelStateValues {
error.display_chain_with_msg("Failed to set VPN interface for split tunnel")
)
})
- .map_err(|error| {
- if error.is_offline() {
- ErrorStateCause::IsOffline
- } else {
- ErrorStateCause::SplitTunnelError
- }
- })
+ .map_err(|error| ErrorStateCause::from(&error))
}
pub fn set_allow_lan(&mut self, allow_lan: bool) -> Result<(), ErrorStateCause> {
diff --git a/talpid-types/src/tunnel.rs b/talpid-types/src/tunnel.rs
index e67db2f0c4..686f7ae19a 100644
--- a/talpid-types/src/tunnel.rs
+++ b/talpid-types/src/tunnel.rs
@@ -110,6 +110,9 @@ pub enum ErrorStateCause {
/// Error reported by split tunnel module.
#[cfg(any(target_os = "windows", target_os = "macos"))]
SplitTunnelError,
+ /// Missing permissions required by macOS split tunneling.
+ #[cfg(target_os = "macos")]
+ NeedFullDiskPermissions,
}
impl ErrorStateCause {
@@ -217,6 +220,8 @@ impl fmt::Display for ErrorStateCause {
VpnPermissionDenied => "The Android VPN permission was denied when creating the tunnel",
#[cfg(any(target_os = "windows", target_os = "macos"))]
SplitTunnelError => "The split tunneling module reported an error",
+ #[cfg(target_os = "macos")]
+ NeedFullDiskPermissions => "Need full disk access to enable split tunneling",
};
write!(f, "{description}")