Skip to content

Commit

Permalink
Update the tunnel state on lockdown mode change.
Browse files Browse the repository at this point in the history
The printing of lockdown mode by `mullvad status` does not reflect the
current setting unless the tunnel state has also been updated.
  • Loading branch information
Serock3 committed Jan 10, 2024
1 parent 5d595f4 commit 4cb98e9
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
25 changes: 17 additions & 8 deletions mullvad-cli/src/cmds/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion mullvad-daemon/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,7 @@ impl TunnelStateChangeHandler {
}
TunnelStateTransition::Error(_)
| TunnelStateTransition::Connected(_)
| TunnelStateTransition::Disconnected => 0,
| TunnelStateTransition::Disconnected { .. } => 0,
_ => retry_attempt,
}
}
Expand Down
5 changes: 2 additions & 3 deletions mullvad-daemon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 23 additions & 5 deletions talpid-core/src/tunnel_state_machine/disconnected_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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<dyn TunnelState>, 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,
},
)
}

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down

0 comments on commit 4cb98e9

Please sign in to comment.