diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2025-04-07 15:20:30 +0200 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2025-04-09 09:46:21 +0200 |
| commit | 0db6e80bbc591eeefb2408fa2e335b2804135eb2 (patch) | |
| tree | 3b465d233d94a4739f9a0850607fc0424c9cb8af | |
| parent | 9a6938a4a32ecc162cc5afcf15fa636de2f9b9fe (diff) | |
| download | mullvadvpn-0db6e80bbc591eeefb2408fa2e335b2804135eb2.tar.xz mullvadvpn-0db6e80bbc591eeefb2408fa2e335b2804135eb2.zip | |
Improve error message when an unavailable ip version is selected
11 files changed, 63 insertions, 25 deletions
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt index 40ee4d6bcf..10c417cf1c 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt @@ -302,7 +302,11 @@ internal fun ManagementInterface.ErrorState.GenerationError.toDomain(): Paramete ManagementInterface.ErrorState.GenerationError.NO_WIREGUARD_KEY -> ParameterGenerationError.NoWireguardKey ManagementInterface.ErrorState.GenerationError.CUSTOM_TUNNEL_HOST_RESOLUTION_ERROR -> - ParameterGenerationError.CustomTunnelHostResultionError + ParameterGenerationError.CustomTunnelHostResolutionError + ManagementInterface.ErrorState.GenerationError.NETWORK_IPV4_UNAVAILABLE -> + ParameterGenerationError.Ipv4_Unavailable + ManagementInterface.ErrorState.GenerationError.NETWORK_IPV6_UNAVAILABLE -> + ParameterGenerationError.Ipv6_Unavailable ManagementInterface.ErrorState.GenerationError.UNRECOGNIZED -> throw IllegalArgumentException("Unrecognized parameter generation error") } diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ParameterGenerationError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ParameterGenerationError.kt index 0aadc19094..5683dc08b1 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ParameterGenerationError.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ParameterGenerationError.kt @@ -4,5 +4,7 @@ enum class ParameterGenerationError { NoMatchingRelay, NoMatchingBridgeRelay, NoWireguardKey, - CustomTunnelHostResultionError, + CustomTunnelHostResolutionError, + Ipv4_Unavailable, + Ipv6_Unavailable, } diff --git a/android/lib/resource/src/main/res/values/strings.xml b/android/lib/resource/src/main/res/values/strings.xml index 4fc739770c..30bc03d3dc 100644 --- a/android/lib/resource/src/main/res/values/strings.xml +++ b/android/lib/resource/src/main/res/values/strings.xml @@ -407,4 +407,6 @@ <string name="uri_browser_app_not_found">No browser app installed, could not open link</string> <string name="device_ip_version_subtitle">This allows access to WireGuard for devices that only support IPv6.</string> <string name="ipv6_info">When this feature is enabled, IPv6 can be used alongside IPv4 in the VPN tunnel to communicate with internet services.</string> + <string name="ip_version_v4_unavailable">IPv4 is not available</string> + <string name="ip_version_v6_unavailable">IPv6 is not available</string> </resources> diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt index c7fdad4793..b022ca8c07 100644 --- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt +++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/NotificationData.kt @@ -237,8 +237,10 @@ private fun ParameterGenerationError.errorMessageId(): Int = R.string.no_matching_relay } ParameterGenerationError.NoWireguardKey -> R.string.no_wireguard_key - ParameterGenerationError.CustomTunnelHostResultionError -> + ParameterGenerationError.CustomTunnelHostResolutionError -> R.string.custom_tunnel_host_resolution_error + ParameterGenerationError.Ipv4_Unavailable -> R.string.ip_version_v4_unavailable + ParameterGenerationError.Ipv6_Unavailable -> R.string.ip_version_v6_unavailable } private fun InetAddress.addressString(): String { diff --git a/desktop/packages/mullvad-vpn/locales/messages.pot b/desktop/packages/mullvad-vpn/locales/messages.pot index 30b7d64fba..9f84dcd613 100644 --- a/desktop/packages/mullvad-vpn/locales/messages.pot +++ b/desktop/packages/mullvad-vpn/locales/messages.pot @@ -2599,6 +2599,12 @@ msgstr "" msgid "Google Play unavailable" msgstr "" +msgid "IPv4 is not available" +msgstr "" + +msgid "IPv6 is not available" +msgstr "" + msgid "If the split tunneling feature is used, then the app queries your system for a list of all installed applications. This list is only retrieved in the split tunneling view. The list of installed applications is never sent from the device." msgstr "" diff --git a/mullvad-daemon/src/tunnel.rs b/mullvad-daemon/src/tunnel.rs index 4874ee167a..ab2efb62cf 100644 --- a/mullvad-daemon/src/tunnel.rs +++ b/mullvad-daemon/src/tunnel.rs @@ -220,12 +220,12 @@ impl InnerParametersGenerator { GetRelay::Custom(custom_relay) => { self.last_generated_relays = None; custom_relay - // TODO: generate proxy settings for custom tunnels - .to_tunnel_parameters(self.tunnel_options.clone(), None) - .map_err(|e| { - log::error!("Failed to resolve hostname for custom tunnel config: {}", e); - Error::ResolveCustomHostname - }) + // TODO: generate proxy settings for custom tunnels + .to_tunnel_parameters(self.tunnel_options.clone(), None) + .map_err(|e| { + log::error!("Failed to resolve hostname for custom tunnel config: {}", e); + Error::ResolveCustomHostname + }) } } } @@ -325,7 +325,10 @@ impl From<Error> for ParameterGenerationError { ParameterGenerationError::NoMatchingBridgeRelay } Error::ResolveCustomHostname => { - ParameterGenerationError::CustomTunnelHostResultionError + ParameterGenerationError::CustomTunnelHostResolutionError + } + Error::SelectRelay(mullvad_relay_selector::Error::IpVersionUnavailable { family }) => { + ParameterGenerationError::IpVersionUnavailable { family } } Error::NoAuthDetails | Error::SelectRelay(_) | Error::Device(_) => { ParameterGenerationError::NoMatchingRelay diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 5acc8c3463..c804751a4c 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -187,6 +187,8 @@ message ErrorState { NO_MATCHING_BRIDGE_RELAY = 1; NO_WIREGUARD_KEY = 2; CUSTOM_TUNNEL_HOST_RESOLUTION_ERROR = 3; + NETWORK_IPV4_UNAVAILABLE = 4; + NETWORK_IPV6_UNAVAILABLE = 5; } message FirewallPolicyError { diff --git a/mullvad-management-interface/src/types/conversions/states.rs b/mullvad-management-interface/src/types/conversions/states.rs index 79e517e750..7d9cc3f417 100644 --- a/mullvad-management-interface/src/types/conversions/states.rs +++ b/mullvad-management-interface/src/types/conversions/states.rs @@ -1,4 +1,5 @@ use crate::types::{proto, FromProtobufTypeError}; +use talpid_types::net::IpVersion; impl From<mullvad_types::states::TunnelState> for proto::TunnelState { fn from(state: mullvad_types::states::TunnelState) -> Self { @@ -187,9 +188,15 @@ impl From<mullvad_types::states::TunnelState> for proto::TunnelState { talpid_tunnel::ParameterGenerationError::NoWireguardKey => { i32::from(GenerationError::NoWireguardKey) } - talpid_tunnel::ParameterGenerationError::CustomTunnelHostResultionError => { + talpid_tunnel::ParameterGenerationError::CustomTunnelHostResolutionError => { i32::from(GenerationError::CustomTunnelHostResolutionError) } + talpid_tunnel::ParameterGenerationError::IpVersionUnavailable { family: IpVersion::V4 } => { + i32::from(GenerationError::NetworkIpv4Unavailable) + } + talpid_tunnel::ParameterGenerationError::IpVersionUnavailable { family: IpVersion::V6 } => { + i32::from(GenerationError::NetworkIpv6Unavailable) + } } } else { 0 @@ -382,7 +389,7 @@ impl TryFrom<proto::TunnelState> for mullvad_types::states::TunnelState { } Ok(proto::error_state::Cause::TunnelParameterError) => { let parameter_error = match proto::error_state::GenerationError::try_from(parameter_error) { - Ok(proto::error_state::GenerationError::CustomTunnelHostResolutionError) => talpid_tunnel::ParameterGenerationError::CustomTunnelHostResultionError, + Ok(proto::error_state::GenerationError::CustomTunnelHostResolutionError) => talpid_tunnel::ParameterGenerationError::CustomTunnelHostResolutionError, Ok(proto::error_state::GenerationError::NoMatchingBridgeRelay) => talpid_tunnel::ParameterGenerationError::NoMatchingBridgeRelay, Ok(proto::error_state::GenerationError::NoMatchingRelay) => talpid_tunnel::ParameterGenerationError::NoMatchingRelay, Ok(proto::error_state::GenerationError::NoWireguardKey) => talpid_tunnel::ParameterGenerationError::NoWireguardKey, diff --git a/mullvad-relay-selector/src/error.rs b/mullvad-relay-selector/src/error.rs index 2df69074e4..e2de09eac0 100644 --- a/mullvad-relay-selector/src/error.rs +++ b/mullvad-relay-selector/src/error.rs @@ -1,9 +1,9 @@ //! Definition of relay selector errors #![allow(dead_code)] -use mullvad_types::{relay_constraints::MissingCustomBridgeSettings, relay_list::Relay}; - use crate::{detailer, relay_selector::relays::WireguardConfig}; +use mullvad_types::{relay_constraints::MissingCustomBridgeSettings, relay_list::Relay}; +use talpid_types::net::IpVersion; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -37,8 +37,8 @@ pub enum Error { #[error("Invalid bridge settings")] InvalidBridgeSettings(#[from] MissingCustomBridgeSettings), - #[error("The requested IP version is not available")] - IpVersionUnavailable, + #[error("The requested IP version ({family}) does not match ip availability")] + IpVersionUnavailable { family: IpVersion }, } /// Special type which only shows up in [`Error`]. This error variant signals that no valid diff --git a/mullvad-relay-selector/src/relay_selector/mod.rs b/mullvad-relay-selector/src/relay_selector/mod.rs index 1468f608b3..e55db12669 100644 --- a/mullvad-relay-selector/src/relay_selector/mod.rs +++ b/mullvad-relay-selector/src/relay_selector/mod.rs @@ -20,12 +20,6 @@ use crate::{ }, }; -use std::{ - path::Path, - sync::{Arc, LazyLock, Mutex}, - time::SystemTime, -}; - use chrono::{DateTime, Local}; use itertools::Itertools; use mullvad_types::{ @@ -43,6 +37,11 @@ use mullvad_types::{ wireguard::QuantumResistantState, CustomTunnelEndpoint, Intersection, }; +use std::{ + path::Path, + sync::{Arc, LazyLock, Mutex}, + time::SystemTime, +}; use talpid_types::{ net::{ obfuscation::ObfuscatorConfig, @@ -1161,7 +1160,15 @@ fn apply_ip_availability( ip_version, ..Default::default() }) - .ok_or(Error::IpVersionUnavailable)?; + .ok_or_else(|| { + // It is safe to call `unwrap` on `wireguard_constraints().ip_version` here + // because this will only be called if intersection returns None + // and the only way None can be returned is if both + // ip_version and wireguard_constraints.ip_version are Constraint::Only and thus + // guarantees that wireguard_constraints.ip_version is Constraint::Only + let family = user_query.wireguard_constraints().ip_version.unwrap(); + Error::IpVersionUnavailable { family } + })?; user_query.set_wireguard_constraints(wireguard_constraints)?; Ok(()) } diff --git a/talpid-types/src/tunnel.rs b/talpid-types/src/tunnel.rs index 77c952583d..ddd65d87b1 100644 --- a/talpid-types/src/tunnel.rs +++ b/talpid-types/src/tunnel.rs @@ -1,4 +1,4 @@ -use crate::net::TunnelEndpoint; +use crate::net::{IpVersion, TunnelEndpoint}; use serde::{Deserialize, Serialize}; use std::fmt; #[cfg(target_os = "android")] @@ -132,7 +132,10 @@ pub enum ParameterGenerationError { NoWireguardKey, /// Failure to resolve the hostname of a custom tunnel configuration #[error("Can't resolve hostname for custom tunnel host")] - CustomTunnelHostResultionError, + CustomTunnelHostResolutionError, + /// User has selected an IP version that is not available on the network + #[error("The requested IP version ({family}) is not available")] + IpVersionUnavailable { family: IpVersion }, } /// Application that prevents setting the firewall policy. |
