summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2024-05-02 17:12:17 +0200
committerDavid Lönnhager <david.l@mullvad.net>2024-05-06 08:42:17 +0200
commit68422031c71f79634b272c6e5542b6fa0dd126a2 (patch)
tree331f0fa7ad6ba06c801d085317d3dc3b2b72e5e5
parent42c240ed3082a4a83fece474a48d6711b43ae821 (diff)
downloadmullvadvpn-68422031c71f79634b272c6e5542b6fa0dd126a2.tar.xz
mullvadvpn-68422031c71f79634b272c6e5542b6fa0dd126a2.zip
Fix daemon not starting when IPv6 is disabled on Linux
-rw-r--r--CHANGELOG.md1
-rw-r--r--talpid-core/src/offline/linux.rs64
2 files changed, 33 insertions, 32 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 595c366b97..4ebcd51688 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,7 @@ Line wrap the file at 100 chars. Th
### Fixed
#### Linux
- Fix GUI not working on Ubuntu 24.04 by adding an AppArmor profile.
+- Service failed to start when IPv6 was disabled in the kernel.
## [2024.2] - 2024-04-29
diff --git a/talpid-core/src/offline/linux.rs b/talpid-core/src/offline/linux.rs
index 1bb07149bf..b4f96ba8c5 100644
--- a/talpid-core/src/offline/linux.rs
+++ b/talpid-core/src/offline/linux.rs
@@ -28,15 +28,7 @@ const PUBLIC_INTERNET_ADDRESS_V6: IpAddr =
impl MonitorHandle {
pub async fn connectivity(&self) -> Connectivity {
- public_ip_unreachable(&self.route_manager, self.fwmark)
- .await
- .unwrap_or_else(|err| {
- log::error!(
- "Failed to verify offline state: {}. Presuming connectivity",
- err
- );
- Connectivity::PresumeOnline
- })
+ check_connectivity(&self.route_manager, self.fwmark).await
}
}
@@ -45,7 +37,7 @@ pub async fn spawn_monitor(
route_manager: RouteManagerHandle,
fwmark: Option<u32>,
) -> Result<MonitorHandle> {
- let mut is_offline = public_ip_unreachable(&route_manager, fwmark).await?;
+ let mut connectivity = check_connectivity(&route_manager, fwmark).await;
let mut listener = route_manager
.change_listener()
@@ -64,18 +56,10 @@ pub async fn spawn_monitor(
while let Some(_event) = listener.next().await {
match sender.upgrade() {
Some(sender) => {
- let new_offline_state = public_ip_unreachable(&route_manager, fwmark)
- .await
- .unwrap_or_else(|err| {
- log::error!(
- "{}",
- err.display_chain_with_msg("Failed to infer offline state")
- );
- Connectivity::PresumeOnline
- });
- if new_offline_state != is_offline {
- is_offline = new_offline_state;
- let _ = sender.unbounded_send(is_offline);
+ let new_connectivity = check_connectivity(&route_manager, fwmark).await;
+ if new_connectivity != connectivity {
+ connectivity = new_connectivity;
+ let _ = sender.unbounded_send(connectivity);
}
}
None => return,
@@ -86,20 +70,36 @@ pub async fn spawn_monitor(
Ok(monitor_handle)
}
-async fn public_ip_unreachable(
- handle: &RouteManagerHandle,
- fwmark: Option<u32>,
-) -> Result<Connectivity> {
+async fn check_connectivity(handle: &RouteManagerHandle, fwmark: Option<u32>) -> Connectivity {
let route_exists = |destination| async move {
handle
.get_destination_route(destination, fwmark)
.await
- .map_err(Error::RouteManagerError)
.map(|route| route.is_some())
};
- let connectivity = Connectivity::Status {
- ipv4: route_exists(PUBLIC_INTERNET_ADDRESS_V4).await?,
- ipv6: route_exists(PUBLIC_INTERNET_ADDRESS_V6).await?,
- };
- Ok(connectivity)
+
+ match (
+ route_exists(PUBLIC_INTERNET_ADDRESS_V4).await,
+ route_exists(PUBLIC_INTERNET_ADDRESS_V6).await,
+ ) {
+ (Ok(ipv4), Ok(ipv6)) => Connectivity::Status { ipv4, ipv6 },
+ // If we fail to retrieve the IPv4 route, always assume we're connected
+ (Err(err), _) => {
+ log::error!(
+ "Failed to verify offline state: {}. Presuming connectivity",
+ err
+ );
+ Connectivity::PresumeOnline
+ }
+ // Errors for IPv6 likely mean it's disabled, so assume it's unavailable
+ (Ok(ipv4), Err(err)) => {
+ log::trace!(
+ "{}",
+ err.display_chain_with_msg(
+ "Failed to infer offline state for IPv6. Assuming it's unavailable"
+ )
+ );
+ Connectivity::Status { ipv4, ipv6: false }
+ }
+ }
}