summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2024-08-29 10:33:16 +0200
committerDavid Lönnhager <david.l@mullvad.net>2024-09-02 12:35:30 +0200
commitbe93a1f57b1f8fff5fce546f3fd48c0efae5fd74 (patch)
treef0ab209894d1d0b31a018d80ffa7fd927d3e3b90
parent020dc16cd790cc460f967bdf888dcad072a57e62 (diff)
downloadmullvadvpn-be93a1f57b1f8fff5fce546f3fd48c0efae5fd74.tar.xz
mullvadvpn-be93a1f57b1f8fff5fce546f3fd48c0efae5fd74.zip
Remove split tunnel utun when entering the disconnected state
-rw-r--r--talpid-core/src/split_tunnel/macos/mod.rs60
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs10
2 files changed, 70 insertions, 0 deletions
diff --git a/talpid-core/src/split_tunnel/macos/mod.rs b/talpid-core/src/split_tunnel/macos/mod.rs
index 1c705f5e6d..b3acdb0136 100644
--- a/talpid-core/src/split_tunnel/macos/mod.rs
+++ b/talpid-core/src/split_tunnel/macos/mod.rs
@@ -113,6 +113,11 @@ enum Message {
result_tx: oneshot::Sender<Result<(), Error>>,
vpn_interface: VpnInterface,
},
+ /// Remove VPN tunnel interface. It is sufficient to call this when entering the disconnected
+ /// state, to avoid pointless cleanup during reconnects.
+ ResetTunnel {
+ result_tx: oneshot::Sender<Result<(), Error>>,
+ },
}
/// Handle for interacting with the split tunnel module
@@ -157,6 +162,14 @@ impl Handle {
});
result_rx.await.map_err(|_| Error::unavailable())?
}
+
+ /// Forget the VPN tunnel interface. This destroys the split tunneling interface when it is
+ /// active.
+ pub async fn reset_tunnel(&self) -> Result<(), Error> {
+ let (result_tx, result_rx) = oneshot::channel();
+ let _ = self.tx.send(Message::ResetTunnel { result_tx });
+ result_rx.await.map_err(|_| Error::unavailable())?
+ }
}
impl SplitTunnel {
@@ -259,6 +272,9 @@ impl SplitTunnel {
} => {
let _ = result_tx.send(self.state.set_tunnel(vpn_interface).await);
}
+ Message::ResetTunnel { result_tx } => {
+ let _ = result_tx.send(self.state.reset_tunnel().await);
+ }
}
true
}
@@ -473,6 +489,50 @@ impl State {
}
}
+ /// Forget the VPN tunnel interface. This destroys the split tunneling interface when it is
+ /// active.
+ pub async fn reset_tunnel(&mut self) -> Result<(), Error> {
+ self.transition(|state| state.reset_tunnel_inner()).await
+ }
+
+ async fn reset_tunnel_inner(self) -> Result<Self, ErrorWithTransition> {
+ match self {
+ // If split tunneling is currently active, that means that there are paths to exclude,
+ // so shut down the ST utun but keep the process monitor.
+ State::Active {
+ route_manager,
+ process,
+ tun_handle,
+ vpn_interface: _,
+ } => {
+ if let Err(error) = tun_handle.shutdown().await {
+ log::error!("Failed to stop split tunnel: {error}");
+ }
+ Ok(State::ProcessMonitorOnly {
+ route_manager,
+ process,
+ })
+ }
+ // If we're in standby mode, simply forget the VPN interface.
+ State::StandBy {
+ route_manager,
+ vpn_interface: _,
+ } => Ok(State::NoExclusions { route_manager }),
+ // If we're in `Failed`, just forget the VPN interface.
+ State::Failed {
+ route_manager,
+ vpn_interface: _,
+ cause,
+ } => Ok(State::Failed {
+ route_manager,
+ vpn_interface: None,
+ cause,
+ }),
+ // For any other state, do nothing.
+ _ => Ok(self),
+ }
+ }
+
/// Update VPN tunnel interface that non-excluded packets are sent on
async fn set_tunnel(&mut self, vpn_interface: VpnInterface) -> Result<(), Error> {
self.transition(move |self_| self_.set_tunnel_inner(vpn_interface))
diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
index 4ee19a5e16..74cd3b65c4 100644
--- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
@@ -21,6 +21,16 @@ impl DisconnectedState {
should_reset_firewall: bool,
) -> (Box<dyn TunnelState>, TunnelStateTransition) {
#[cfg(target_os = "macos")]
+ if let Err(err) = shared_values
+ .runtime
+ .block_on(shared_values.split_tunnel.reset_tunnel())
+ {
+ log::error!(
+ "{}",
+ err.display_chain_with_msg("Failed to disable split tunneling")
+ );
+ }
+ #[cfg(target_os = "macos")]
if shared_values.block_when_disconnected {
if let Err(err) = Self::setup_local_dns_config(shared_values) {
log::error!(