diff --git a/mullvad-cli/src/cmds/status.rs b/mullvad-cli/src/cmds/status.rs index bb1fbe41fe97..8880c4c69c85 100644 --- a/mullvad-cli/src/cmds/status.rs +++ b/mullvad-cli/src/cmds/status.rs @@ -34,16 +34,25 @@ impl Status { println!("New tunnel state: {new_state:#?}"); } else { // When we enter the connected or disconnected state, am.i.mullvad.net will - // be polled to get IP information. When it arrives, we will get another - // tunnel state of the same enum type, but with the IP filled in. This - // match statement checks for duplicate tunnel states and skips the second - // print to avoid spamming the user. + // be polled to get exit location. When it arrives, we will get another + // tunnel state of the same enum type, but with the location filled in. This + // match statement checks if the new state is an updated version of the old + // one and if so skips the print to avoid spamming the user. Note that for + // graphical frontends updating the drawn state with an identical one is + // invisible, so this is only an issue for the CLI. match (&previous_tunnel_state, &new_state) { ( - Some(TunnelState::Disconnected { .. }), - TunnelState::Disconnected { .. }, - ) - | ( + Some(TunnelState::Disconnected { + location: _, + locked_down: was_locked_down, + }), + TunnelState::Disconnected { + location: _, + locked_down, + }, + // Do print an updated state if the lockdown setting was changed + ) if was_locked_down == locked_down => continue, + ( Some(TunnelState::Connected { .. }), TunnelState::Connected { .. }, ) => continue, diff --git a/mullvad-daemon/src/device/mod.rs b/mullvad-daemon/src/device/mod.rs index ac65e2fbd5c7..8f836d90d537 100644 --- a/mullvad-daemon/src/device/mod.rs +++ b/mullvad-daemon/src/device/mod.rs @@ -1282,7 +1282,7 @@ impl TunnelStateChangeHandler { } TunnelStateTransition::Error(_) | TunnelStateTransition::Connected(_) - | TunnelStateTransition::Disconnected => 0, + | TunnelStateTransition::Disconnected { .. } => 0, _ => retry_attempt, } } diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 9b09fee6b39f..6fc930836b80 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -1000,10 +1000,9 @@ where .handle_state_transition(&tunnel_state_transition); let tunnel_state = match tunnel_state_transition { - TunnelStateTransition::Disconnected => TunnelState::Disconnected { + TunnelStateTransition::Disconnected { locked_down } => TunnelState::Disconnected { location: None, - // If lockdown mode is enabled and state is disconnected - locked_down: self.settings.block_when_disconnected, + locked_down, }, TunnelStateTransition::Connecting(endpoint) => TunnelState::Connecting { endpoint, diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs index d46f06e782f7..b81aa79a4104 100644 --- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs +++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs @@ -34,7 +34,6 @@ impl DisconnectedState { error.display_chain_with_msg("Unable to disable filtering resolver") ); } - #[cfg(windows)] Self::register_split_tunnel_addresses(shared_values, should_reset_firewall); Self::set_firewall_policy(shared_values, should_reset_firewall); @@ -43,9 +42,19 @@ impl DisconnectedState { #[cfg(target_os = "android")] shared_values.tun_provider.lock().unwrap().close_tun(); + Self::construct_state_transition(shared_values) + } + + fn construct_state_transition( + shared_values: &mut SharedTunnelStateValues, + ) -> (Box, TunnelStateTransition) { ( Box::new(DisconnectedState(())), - TunnelStateTransition::Disconnected, + TunnelStateTransition::Disconnected { + // Being disconnected and having lockdown mode enabled implies that your internet + // access is locked down + locked_down: shared_values.block_when_disconnected, + }, ) } @@ -158,8 +167,14 @@ impl TunnelState for DisconnectedState { SameState(self) } Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected, complete_tx)) => { - if shared_values.block_when_disconnected != block_when_disconnected { + if dbg!(shared_values.block_when_disconnected != block_when_disconnected) { shared_values.block_when_disconnected = block_when_disconnected; + + // TODO: Investigate if we can simply return + // `NewState(Self::enter(shared_values, true))`. + // The logic for updating the firewall in `DisconnectedState::enter` is + // identical but it does not enter the error state if setting the local DNS + // fails. Self::set_firewall_policy(shared_values, true); #[cfg(windows)] Self::register_split_tunnel_addresses(shared_values, true); @@ -178,9 +193,12 @@ impl TunnelState for DisconnectedState { } else { Self::reset_dns(shared_values); } + let _ = complete_tx.send(()); + NewState(Self::construct_state_transition(shared_values)) + } else { + let _ = complete_tx.send(()); + SameState(self) } - let _ = complete_tx.send(()); - SameState(self) } Some(TunnelCommand::IsOffline(is_offline)) => { shared_values.is_offline = is_offline;