summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTobias Järvelöv <tobias.jarvelov@mullvad.net>2025-09-30 10:57:14 +0200
committerTobias Järvelöv <tobias.jarvelov@mullvad.net>2025-09-30 10:57:14 +0200
commitceca0206a3af013470ab77d34468e76aa129fd78 (patch)
treeba85d992bf54bb5c04abc687af37251b00ba99a1
parenta937623372b83783d5867e45c14fc32dd1db5bb5 (diff)
parentcfa2ca239265663b50e580e0828e406581172df5 (diff)
downloadmullvadvpn-ceca0206a3af013470ab77d34468e76aa129fd78.tar.xz
mullvadvpn-ceca0206a3af013470ab77d34468e76aa129fd78.zip
Merge branch 'rename-block_when_disconnected-to-lockdown_mode-des-1334'
-rw-r--r--Cargo.lock1
-rw-r--r--desktop/packages/mullvad-vpn/src/main/daemon-rpc.ts4
-rw-r--r--desktop/packages/mullvad-vpn/src/main/default-settings.ts2
-rw-r--r--desktop/packages/mullvad-vpn/src/main/index.ts2
-rw-r--r--desktop/packages/mullvad-vpn/src/main/settings.ts8
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/app.tsx8
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx63
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx10
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/views/login/LoginView.tsx16
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/components/views/vpn-settings/components/lockdown-mode-setting/LockdownModeSetting.tsx24
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/redux/settings/actions.ts18
-rw-r--r--desktop/packages/mullvad-vpn/src/renderer/redux/settings/reducers.ts8
-rw-r--r--desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts2
-rw-r--r--desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts2
-rw-r--r--desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts11
-rw-r--r--mullvad-cli/src/cmds/lockdown.rs4
-rw-r--r--mullvad-daemon/Cargo.toml3
-rw-r--r--mullvad-daemon/src/lib.rs49
-rw-r--r--mullvad-daemon/src/management_interface.rs17
-rw-r--r--mullvad-daemon/src/migrations/mod.rs3
-rw-r--r--mullvad-daemon/src/migrations/snapshots/mullvad_daemon__migrations__v11__test__v11_to_v12_migration_access_method_name_duplicates.snap136
-rw-r--r--mullvad-daemon/src/migrations/v11.rs326
-rw-r--r--mullvad-daemon/src/settings/mod.rs8
-rw-r--r--mullvad-management-interface/proto/management_interface.proto4
-rw-r--r--mullvad-management-interface/src/client.rs4
-rw-r--r--mullvad-management-interface/src/types/conversions/settings.rs6
-rw-r--r--mullvad-types/src/features.rs4
-rw-r--r--mullvad-types/src/settings/mod.rs8
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs20
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnecting_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/error_state.rs4
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs42
-rw-r--r--test/test-manager/src/tests/settings.rs2
-rw-r--r--test/test-manager/src/tests/windows.rs6
36 files changed, 643 insertions, 194 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 801bf03b00..8fada8070e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3045,6 +3045,7 @@ dependencies = [
"fern",
"futures",
"hickory-resolver",
+ "insta",
"ipnetwork",
"libc",
"log",
diff --git a/desktop/packages/mullvad-vpn/src/main/daemon-rpc.ts b/desktop/packages/mullvad-vpn/src/main/daemon-rpc.ts
index c3594b9590..8db5d1b5f2 100644
--- a/desktop/packages/mullvad-vpn/src/main/daemon-rpc.ts
+++ b/desktop/packages/mullvad-vpn/src/main/daemon-rpc.ts
@@ -297,8 +297,8 @@ export class DaemonRpc extends GrpcClient {
await this.callBool(this.client.setEnableIpv6, enableIpv6);
}
- public async setBlockWhenDisconnected(blockWhenDisconnected: boolean): Promise<void> {
- await this.callBool(this.client.setBlockWhenDisconnected, blockWhenDisconnected);
+ public async setLockdownMode(lockdownMode: boolean): Promise<void> {
+ await this.callBool(this.client.setLockdownMode, lockdownMode);
}
public async setBridgeState(bridgeState: BridgeState): Promise<void> {
diff --git a/desktop/packages/mullvad-vpn/src/main/default-settings.ts b/desktop/packages/mullvad-vpn/src/main/default-settings.ts
index a80afa03e1..9ba2b18e9b 100644
--- a/desktop/packages/mullvad-vpn/src/main/default-settings.ts
+++ b/desktop/packages/mullvad-vpn/src/main/default-settings.ts
@@ -34,7 +34,7 @@ export function getDefaultSettings(): ISettings {
return {
allowLan: false,
autoConnect: false,
- blockWhenDisconnected: false,
+ lockdownMode: false,
showBetaReleases: false,
splitTunnel: {
enableExclusions: false,
diff --git a/desktop/packages/mullvad-vpn/src/main/index.ts b/desktop/packages/mullvad-vpn/src/main/index.ts
index 0b582c3cd6..d56247dd4d 100644
--- a/desktop/packages/mullvad-vpn/src/main/index.ts
+++ b/desktop/packages/mullvad-vpn/src/main/index.ts
@@ -695,7 +695,7 @@ class ApplicationMain
// update the tray icon to indicate that the computer is not secure anymore
this.userInterface?.updateTray(false, {
state: 'disconnected',
- lockedDown: this.settings.blockWhenDisconnected,
+ lockedDown: this.settings.lockdownMode,
});
// notify renderer process
diff --git a/desktop/packages/mullvad-vpn/src/main/settings.ts b/desktop/packages/mullvad-vpn/src/main/settings.ts
index bfe2bc140d..20c000a3dc 100644
--- a/desktop/packages/mullvad-vpn/src/main/settings.ts
+++ b/desktop/packages/mullvad-vpn/src/main/settings.ts
@@ -37,8 +37,8 @@ export default class Settings implements Readonly<ISettings> {
IpcMainEventChannel.settings.handleSetEnableIpv6((enableIpv6) =>
this.daemonRpc.setEnableIpv6(enableIpv6),
);
- IpcMainEventChannel.settings.handleSetBlockWhenDisconnected((blockWhenDisconnected) =>
- this.daemonRpc.setBlockWhenDisconnected(blockWhenDisconnected),
+ IpcMainEventChannel.settings.handleSetLockdownMode((lockdownMode) =>
+ this.daemonRpc.setLockdownMode(lockdownMode),
);
IpcMainEventChannel.settings.handleSetBridgeState(async (bridgeState) => {
await this.daemonRpc.setBridgeState(bridgeState);
@@ -158,8 +158,8 @@ export default class Settings implements Readonly<ISettings> {
public get autoConnect() {
return this.settingsValue.autoConnect;
}
- public get blockWhenDisconnected() {
- return this.settingsValue.blockWhenDisconnected;
+ public get lockdownMode() {
+ return this.settingsValue.lockdownMode;
}
public get showBetaReleases() {
return this.settingsValue.showBetaReleases;
diff --git a/desktop/packages/mullvad-vpn/src/renderer/app.tsx b/desktop/packages/mullvad-vpn/src/renderer/app.tsx
index 69ae19338d..5b7f625019 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/app.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/app.tsx
@@ -594,10 +594,10 @@ export default class AppRenderer {
actions.settings.updateBridgeState(bridgeState);
};
- public setBlockWhenDisconnected = async (blockWhenDisconnected: boolean) => {
+ public setLockdownMode = async (lockdownMode: boolean) => {
const actions = this.reduxActions;
- await IpcRendererEventChannel.settings.setBlockWhenDisconnected(blockWhenDisconnected);
- actions.settings.updateBlockWhenDisconnected(blockWhenDisconnected);
+ await IpcRendererEventChannel.settings.setLockdownMode(lockdownMode);
+ actions.settings.updateLockdownMode(lockdownMode);
};
public setOpenVpnMssfix = async (mssfix?: number) => {
@@ -956,7 +956,7 @@ export default class AppRenderer {
reduxSettings.updateAllowLan(newSettings.allowLan);
reduxSettings.updateEnableIpv6(newSettings.tunnelOptions.generic.enableIpv6);
- reduxSettings.updateBlockWhenDisconnected(newSettings.blockWhenDisconnected);
+ reduxSettings.updateLockdownMode(newSettings.lockdownMode);
reduxSettings.updateShowBetaReleases(newSettings.showBetaReleases);
reduxSettings.updateOpenVpnMssfix(newSettings.tunnelOptions.openvpn.mssfix);
reduxSettings.updateWireguardMtu(newSettings.tunnelOptions.wireguard.mtu);
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx
index 28e00e4151..61db44db59 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/ExpiredAccountErrorView.tsx
@@ -34,7 +34,7 @@ import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
enum RecoveryAction {
openBrowser,
disconnect,
- disableBlockedWhenDisconnected,
+ disableLockdownMode,
}
export default function ExpiredAccountErrorView() {
@@ -103,7 +103,7 @@ function ExpiredAccountErrorViewComponent() {
</FlexColumn>
</Footer>
- <BlockWhenDisconnectedAlert />
+ <LockdownModeAlert />
</StyledContainer>
</StyledCustomScrollbars>
</Layout>
@@ -183,7 +183,7 @@ function Content() {
}
function ExternalPaymentButton() {
- const { setShowBlockWhenDisconnectedAlert } = useExpiredAccountContext();
+ const { setShowLockdownModeAlert } = useExpiredAccountContext();
const { recoveryAction } = useRecoveryAction();
const { openUrlWithAuth } = useAppContext();
const isNewAccount = useIsNewAccount();
@@ -193,8 +193,8 @@ function ExternalPaymentButton() {
: messages.gettext('Buy more credit');
const [openExternalPayment, openingExternalPayment] = useExclusiveTask(async () => {
- if (recoveryAction === RecoveryAction.disableBlockedWhenDisconnected) {
- setShowBlockWhenDisconnectedAlert(true);
+ if (recoveryAction === RecoveryAction.disableLockdownMode) {
+ setShowLockdownModeAlert(true);
} else {
await openUrlWithAuth(urls.purchase);
}
@@ -215,38 +215,37 @@ function ExternalPaymentButton() {
);
}
-function BlockWhenDisconnectedAlert() {
- const { showBlockWhenDisconnectedAlert, setShowBlockWhenDisconnectedAlert } =
- useExpiredAccountContext();
- const { setBlockWhenDisconnected } = useAppContext();
- const blockWhenDisconnected = useSelector((state) => state.settings.blockWhenDisconnected);
+function LockdownModeAlert() {
+ const { showLockdownModeAlert, setShowLockdownModeAlert } = useExpiredAccountContext();
+ const { setLockdownMode } = useAppContext();
+ const lockdownMode = useSelector((state) => state.settings.lockdownMode);
- const onCloseBlockWhenDisconnectedInstructions = useCallback(() => {
- setShowBlockWhenDisconnectedAlert(false);
- }, [setShowBlockWhenDisconnectedAlert]);
+ const onCloseLockdownModeInstructions = useCallback(() => {
+ setShowLockdownModeAlert(false);
+ }, [setShowLockdownModeAlert]);
const onChange = useCallback(
- async (blockWhenDisconnected: boolean) => {
+ async (lockdownMode: boolean) => {
try {
- await setBlockWhenDisconnected(blockWhenDisconnected);
+ await setLockdownMode(lockdownMode);
} catch (e) {
const error = e as Error;
- log.error('Failed to update block when disconnected', error.message);
+ log.error('Failed to update lockdown mode', error.message);
}
},
- [setBlockWhenDisconnected],
+ [setLockdownMode],
);
return (
<ModalAlert
- isOpen={showBlockWhenDisconnectedAlert}
+ isOpen={showLockdownModeAlert}
type={ModalAlertType.caution}
buttons={[
- <Button key="cancel" onClick={onCloseBlockWhenDisconnectedInstructions}>
+ <Button key="cancel" onClick={onCloseLockdownModeInstructions}>
<Button.Text>{messages.gettext('Close')}</Button.Text>
</Button>,
]}
- close={onCloseBlockWhenDisconnectedInstructions}>
+ close={onCloseLockdownModeInstructions}>
<ModalMessage>
{messages.pgettext(
'connect-view',
@@ -261,28 +260,28 @@ function BlockWhenDisconnectedAlert() {
</ModalMessage>
<StyledModalCellContainer>
<Cell.Label>{messages.pgettext('vpn-settings-view', 'Lockdown mode')}</Cell.Label>
- <Cell.Switch isOn={blockWhenDisconnected} onChange={onChange} />
+ <Cell.Switch isOn={lockdownMode} onChange={onChange} />
</StyledModalCellContainer>
</ModalAlert>
);
}
type ExpiredAccountContextType = {
- setShowBlockWhenDisconnectedAlert: (val: boolean) => void;
- showBlockWhenDisconnectedAlert: boolean;
+ setShowLockdownModeAlert: (val: boolean) => void;
+ showLockdownModeAlert: boolean;
};
const ExpiredAccountContext = createContext<ExpiredAccountContextType | undefined>(undefined);
const ExpiredAccountContextProvider = ({ children }: { children: ReactNode }) => {
- const [showBlockWhenDisconnectedAlert, setShowBlockWhenDisconnectedAlert] = useState(false);
+ const [showLockdownModeAlert, setShowLockdownModeAlert] = useState(false);
const value: ExpiredAccountContextType = useMemo(
() => ({
- setShowBlockWhenDisconnectedAlert,
- showBlockWhenDisconnectedAlert,
+ setShowLockdownModeAlert,
+ showLockdownModeAlert,
}),
- [setShowBlockWhenDisconnectedAlert, showBlockWhenDisconnectedAlert],
+ [setShowLockdownModeAlert, showLockdownModeAlert],
);
return <ExpiredAccountContext.Provider value={value}>{children}</ExpiredAccountContext.Provider>;
};
@@ -300,13 +299,13 @@ const useExpiredAccountContext = () => {
const useRecoveryAction = () => {
const isBlocked = useSelector((state) => state.connection.isBlocked);
- const blockWhenDisconnected = useSelector((state) => state.settings.blockWhenDisconnected);
+ const lockdownMode = useSelector((state) => state.settings.lockdownMode);
let recoveryAction: RecoveryAction;
- if (blockWhenDisconnected && isBlocked) {
- recoveryAction = RecoveryAction.disableBlockedWhenDisconnected;
- } else if (!blockWhenDisconnected && isBlocked) {
+ if (lockdownMode && isBlocked) {
+ recoveryAction = RecoveryAction.disableLockdownMode;
+ } else if (!lockdownMode && isBlocked) {
recoveryAction = RecoveryAction.disconnect;
} else {
recoveryAction = RecoveryAction.openBrowser;
@@ -316,7 +315,7 @@ const useRecoveryAction = () => {
switch (recoveryAction) {
case RecoveryAction.openBrowser:
- case RecoveryAction.disableBlockedWhenDisconnected:
+ case RecoveryAction.disableLockdownMode:
recoveryMessage = messages.pgettext(
'connect-view',
'Either buy credit on our website or redeem a voucher.',
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx
index 64c82197eb..bf61ff8003 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx
@@ -3,13 +3,13 @@ import { useCallback, useState } from 'react';
import { messages } from '../../shared/gettext';
import log from '../../shared/logging';
import {
- BlockWhenDisconnectedNotificationProvider,
CloseToAccountExpiryNotificationProvider,
ConnectingNotificationProvider,
ErrorNotificationProvider,
InAppNotificationAction,
InAppNotificationProvider,
InconsistentVersionNotificationProvider,
+ LockdownModeNotificationProvider,
ReconnectingNotificationProvider,
UnsupportedVersionNotificationProvider,
} from '../../shared/notifications';
@@ -69,9 +69,7 @@ export default function NotificationArea(props: IProps) {
const allowedPortRanges = useSelector((state) => state.settings.wireguardEndpointData.portRanges);
const relaySettings = useSelector((state) => state.settings.relaySettings);
- const blockWhenDisconnectedSetting = useSelector(
- (state: IReduxState) => state.settings.blockWhenDisconnected,
- );
+ const lockdownModeSetting = useSelector((state: IReduxState) => state.settings.lockdownMode);
const hasExcludedApps = useSelector(
(state: IReduxState) =>
state.settings.splitTunneling && state.settings.splitTunnelingApplications.length > 0,
@@ -122,9 +120,9 @@ export default function NotificationArea(props: IProps) {
const notificationProviders: InAppNotificationProvider[] = [
new ConnectingNotificationProvider({ tunnelState }),
new ReconnectingNotificationProvider(tunnelState),
- new BlockWhenDisconnectedNotificationProvider({
+ new LockdownModeNotificationProvider({
tunnelState,
- blockWhenDisconnectedSetting,
+ lockdownModeSetting,
hasExcludedApps,
}),
new AppUpgradeErrorNotificationProvider({
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/login/LoginView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/login/LoginView.tsx
index 87de6e1a61..939eb82e20 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/views/login/LoginView.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/login/LoginView.tsx
@@ -552,23 +552,23 @@ function AccountDropdownItem({ label, onRemove, onSelect, value }: AccountDropdo
}
function BlockMessage() {
- const { setBlockWhenDisconnected, disconnectTunnel } = useAppContext();
+ const { setLockdownMode, disconnectTunnel } = useAppContext();
const tunnelState = useSelector((state) => state.connection.status);
- const blockWhenDisconnected = tunnelState.state === 'disconnected' && tunnelState.lockedDown;
+ const lockdownMode = tunnelState.state === 'disconnected' && tunnelState.lockedDown;
const unlock = useCallback(() => {
- if (blockWhenDisconnected) {
- void setBlockWhenDisconnected(false);
+ if (lockdownMode) {
+ void setLockdownMode(false);
}
if (tunnelState.state === 'error') {
void disconnectTunnel();
}
- }, [blockWhenDisconnected, tunnelState, setBlockWhenDisconnected, disconnectTunnel]);
+ }, [lockdownMode, tunnelState, setLockdownMode, disconnectTunnel]);
const lockdownModeSettingName = messages.pgettext('vpn-settings-view', 'Lockdown mode');
const message = formatHtml(
- blockWhenDisconnected
+ lockdownMode
? sprintf(
// TRANSLATORS: This is a warning message shown when the app is blocking the users
// TRANSLATORS: internet connection while logged out.
@@ -585,9 +585,7 @@ function BlockMessage() {
// TRANSLATORS: internet connection while logged out.
messages.pgettext('login-view', 'Our kill switch is currently blocking your connection.'),
);
- const buttonText = blockWhenDisconnected
- ? messages.gettext('Disable')
- : messages.gettext('Unblock');
+ const buttonText = lockdownMode ? messages.gettext('Disable') : messages.gettext('Unblock');
return (
<StyledBlockMessageContainer>
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/vpn-settings/components/lockdown-mode-setting/LockdownModeSetting.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/vpn-settings/components/lockdown-mode-setting/LockdownModeSetting.tsx
index 30da61d848..381e8605ea 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/components/views/vpn-settings/components/lockdown-mode-setting/LockdownModeSetting.tsx
+++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/vpn-settings/components/lockdown-mode-setting/LockdownModeSetting.tsx
@@ -11,22 +11,22 @@ import { ModalAlert, ModalAlertType, ModalMessage } from '../../../../Modal';
import { SettingsToggleListItem } from '../../../../settings-toggle-list-item';
export function LockdownModeSetting() {
- const blockWhenDisconnected = useSelector((state) => state.settings.blockWhenDisconnected);
- const { setBlockWhenDisconnected: setBlockWhenDisconnectedImpl } = useAppContext();
+ const lockdownMode = useSelector((state) => state.settings.lockdownMode);
+ const { setLockdownMode: setLockdownModeImpl } = useAppContext();
const [confirmationDialogVisible, showConfirmationDialog, hideConfirmationDialog] =
useBoolean(false);
- const setBlockWhenDisconnected = useCallback(
- async (blockWhenDisconnected: boolean) => {
+ const setLockdownMode = useCallback(
+ async (lockdownMode: boolean) => {
try {
- await setBlockWhenDisconnectedImpl(blockWhenDisconnected);
+ await setLockdownModeImpl(lockdownMode);
} catch (e) {
const error = e as Error;
- log.error('Failed to update block when disconnected', error.message);
+ log.error('Failed to update lockdown mode', error.message);
}
},
- [setBlockWhenDisconnectedImpl],
+ [setLockdownModeImpl],
);
const setLockDownMode = useCallback(
@@ -34,21 +34,21 @@ export function LockdownModeSetting() {
if (newValue) {
showConfirmationDialog();
} else {
- await setBlockWhenDisconnected(false);
+ await setLockdownMode(false);
}
},
- [setBlockWhenDisconnected, showConfirmationDialog],
+ [setLockdownMode, showConfirmationDialog],
);
const confirmLockdownMode = useCallback(async () => {
hideConfirmationDialog();
- await setBlockWhenDisconnected(true);
- }, [hideConfirmationDialog, setBlockWhenDisconnected]);
+ await setLockdownMode(true);
+ }, [hideConfirmationDialog, setLockdownMode]);
return (
<SettingsToggleListItem
anchorId="lockdown-mode-setting"
- checked={blockWhenDisconnected}
+ checked={lockdownMode}
onCheckedChange={setLockDownMode}>
<SettingsToggleListItem.Label>
{messages.pgettext('vpn-settings-view', 'Lockdown mode')}
diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/settings/actions.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/settings/actions.ts
index d2a3fb1c4a..c87b9a73a0 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/redux/settings/actions.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/redux/settings/actions.ts
@@ -43,9 +43,9 @@ export interface IUpdateEnableIpv6Action {
enableIpv6: boolean;
}
-export interface IUpdateBlockWhenDisconnectedAction {
- type: 'UPDATE_BLOCK_WHEN_DISCONNECTED';
- blockWhenDisconnected: boolean;
+export interface IUpdateLockdownModeAction {
+ type: 'UPDATE_LOCKDOWN_MODE';
+ lockdownMode: boolean;
}
export interface IUpdateShowBetaReleasesAction {
@@ -135,7 +135,7 @@ export type SettingsAction =
| IUpdateWireguardEndpointData
| IUpdateAllowLanAction
| IUpdateEnableIpv6Action
- | IUpdateBlockWhenDisconnectedAction
+ | IUpdateLockdownModeAction
| IUpdateShowBetaReleasesAction
| IUpdateBridgeSettingsAction
| IUpdateBridgeStateAction
@@ -199,12 +199,10 @@ function updateEnableIpv6(enableIpv6: boolean): IUpdateEnableIpv6Action {
};
}
-function updateBlockWhenDisconnected(
- blockWhenDisconnected: boolean,
-): IUpdateBlockWhenDisconnectedAction {
+function updateLockdownMode(lockdownMode: boolean): IUpdateLockdownModeAction {
return {
- type: 'UPDATE_BLOCK_WHEN_DISCONNECTED',
- blockWhenDisconnected,
+ type: 'UPDATE_LOCKDOWN_MODE',
+ lockdownMode,
};
}
@@ -333,7 +331,7 @@ export default {
updateWireguardEndpointData,
updateAllowLan,
updateEnableIpv6,
- updateBlockWhenDisconnected,
+ updateLockdownMode,
updateShowBetaReleases,
updateBridgeSettings,
updateBridgeState,
diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/settings/reducers.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/settings/reducers.ts
index 9ac8bb3a61..285a0500e2 100644
--- a/desktop/packages/mullvad-vpn/src/renderer/redux/settings/reducers.ts
+++ b/desktop/packages/mullvad-vpn/src/renderer/redux/settings/reducers.ts
@@ -105,7 +105,7 @@ export interface ISettingsReduxState {
enableIpv6: boolean;
bridgeSettings: BridgeSettingsRedux;
bridgeState: BridgeState;
- blockWhenDisconnected: boolean;
+ lockdownMode: boolean;
showBetaReleases: boolean;
openVpn: {
mssfix?: number;
@@ -166,7 +166,7 @@ const initialState: ISettingsReduxState = {
custom: undefined,
},
bridgeState: 'auto',
- blockWhenDisconnected: false,
+ lockdownMode: false,
showBetaReleases: false,
openVpn: {},
wireguard: {},
@@ -242,10 +242,10 @@ export default function (
enableIpv6: action.enableIpv6,
};
- case 'UPDATE_BLOCK_WHEN_DISCONNECTED':
+ case 'UPDATE_LOCKDOWN_MODE':
return {
...state,
- blockWhenDisconnected: action.blockWhenDisconnected,
+ lockdownMode: action.lockdownMode,
};
case 'UPDATE_SHOW_BETA_NOTIFICATIONS':
diff --git a/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts b/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts
index 026df6d189..f1c3dd8ac4 100644
--- a/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts
+++ b/desktop/packages/mullvad-vpn/src/shared/daemon-rpc-types.ts
@@ -492,7 +492,7 @@ export type AccessMethodExistsError = { type: 'name already exists' };
export interface ISettings {
allowLan: boolean;
autoConnect: boolean;
- blockWhenDisconnected: boolean;
+ lockdownMode: boolean;
showBetaReleases: boolean;
relaySettings: RelaySettings;
tunnelOptions: ITunnelOptions;
diff --git a/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts b/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts
index a685a2974e..dae1de0da3 100644
--- a/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts
+++ b/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts
@@ -195,7 +195,7 @@ export const ipcSchema = {
setAllowLan: invoke<boolean, void>(),
setShowBetaReleases: invoke<boolean, void>(),
setEnableIpv6: invoke<boolean, void>(),
- setBlockWhenDisconnected: invoke<boolean, void>(),
+ setLockdownMode: invoke<boolean, void>(),
setBridgeState: invoke<BridgeState, void>(),
setOpenVpnMssfix: invoke<number | undefined, void>(),
setWireguardMtu: invoke<number | undefined, void>(),
diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts
index 6b8022c381..9950aa3b8b 100644
--- a/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts
+++ b/desktop/packages/mullvad-vpn/src/shared/notifications/block-when-disconnected.ts
@@ -12,21 +12,20 @@ import {
SystemNotificationSeverityType,
} from './notification';
-interface BlockWhenDisconnectedNotificationContext {
+interface LockdownModeNotificationContext {
tunnelState: TunnelState;
- blockWhenDisconnectedSetting: boolean;
+ lockdownModeSetting: boolean;
hasExcludedApps: boolean;
}
-export class BlockWhenDisconnectedNotificationProvider
+export class LockdownModeNotificationProvider
implements InAppNotificationProvider, SystemNotificationProvider
{
- public constructor(private context: BlockWhenDisconnectedNotificationContext) {}
+ public constructor(private context: LockdownModeNotificationContext) {}
public mayDisplay() {
return (
- (this.context.tunnelState.state === 'disconnecting' &&
- this.context.blockWhenDisconnectedSetting) ||
+ (this.context.tunnelState.state === 'disconnecting' && this.context.lockdownModeSetting) ||
(this.context.tunnelState.state === 'disconnected' && this.context.tunnelState.lockedDown)
);
}
diff --git a/mullvad-cli/src/cmds/lockdown.rs b/mullvad-cli/src/cmds/lockdown.rs
index 001f195fda..c165770dfa 100644
--- a/mullvad-cli/src/cmds/lockdown.rs
+++ b/mullvad-cli/src/cmds/lockdown.rs
@@ -22,14 +22,14 @@ impl LockdownMode {
async fn set(policy: BooleanOption) -> Result<()> {
let mut rpc = MullvadProxyClient::new().await?;
- rpc.set_block_when_disconnected(*policy).await?;
+ rpc.set_lockdown_mode(*policy).await?;
println!("Changed lockdown mode setting");
Ok(())
}
async fn get() -> Result<()> {
let mut rpc = MullvadProxyClient::new().await?;
- let state = BooleanOption::from(rpc.get_settings().await?.block_when_disconnected);
+ let state = BooleanOption::from(rpc.get_settings().await?.lockdown_mode);
println!("Block traffic when the VPN is disconnected: {state}");
Ok(())
}
diff --git a/mullvad-daemon/Cargo.toml b/mullvad-daemon/Cargo.toml
index 857c629e92..e98b126942 100644
--- a/mullvad-daemon/Cargo.toml
+++ b/mullvad-daemon/Cargo.toml
@@ -27,7 +27,7 @@ libc = "0.2"
log = { workspace = true }
regex = "1.0"
serde = { workspace = true, features = ["derive"] }
-serde_json = { workspace = true }
+serde_json = { workspace = true, features = ["std"] }
tokio = { workspace = true, features = ["fs", "io-util", "rt-multi-thread", "sync", "time"] }
tokio-stream = { version = "0.1", features = ["sync"]}
socket2 = { workspace = true }
@@ -55,6 +55,7 @@ log-panics = "2.0.0"
mullvad-management-interface = { path = "../mullvad-management-interface" }
[dev-dependencies]
+insta = { workspace = true, features = ["json"] }
talpid-time = { path = "../talpid-time", features = ["test"] }
tokio = { workspace = true, features = ["test-util"] }
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 33f904947c..5783baef4e 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -88,7 +88,7 @@ use std::{
#[cfg(target_os = "android")]
use talpid_core::connectivity_listener::ConnectivityListener;
#[cfg(not(target_os = "android"))]
-use talpid_core::tunnel_state_machine::BlockWhenDisconnected;
+use talpid_core::tunnel_state_machine::LockdownMode;
use talpid_core::{
mpsc::Sender,
split_tunnel,
@@ -271,9 +271,9 @@ pub enum DaemonCommand {
SetAllowLan(ResponseTx<(), settings::Error>, bool),
/// Set the beta program setting.
SetShowBetaReleases(ResponseTx<(), settings::Error>, bool),
- /// Set the block_when_disconnected setting.
+ /// Set the lockdown_mode setting.
#[cfg(not(target_os = "android"))]
- SetBlockWhenDisconnected(ResponseTx<(), settings::Error>, bool),
+ SetLockdownMode(ResponseTx<(), settings::Error>, bool),
/// Set the auto-connect setting.
SetAutoConnect(ResponseTx<(), settings::Error>, bool),
/// Set the mssfix argument for OpenVPN
@@ -883,9 +883,7 @@ impl Daemon {
tunnel_state_machine::InitialTunnelState {
allow_lan: settings.allow_lan,
#[cfg(not(target_os = "android"))]
- block_when_disconnected: BlockWhenDisconnected::from(
- settings.block_when_disconnected,
- ),
+ lockdown_mode: LockdownMode::from(settings.lockdown_mode),
dns_config: dns::addresses_from_options(&settings.tunnel_options.dns_options),
allowed_endpoint: access_mode_handler
.get_current()
@@ -973,7 +971,7 @@ impl Daemon {
tunnel_state: TunnelState::Disconnected {
location: None,
#[cfg(not(target_os = "android"))]
- locked_down: settings.block_when_disconnected,
+ locked_down: settings.lockdown_mode,
},
target_state,
#[cfg(target_os = "linux")]
@@ -1432,9 +1430,8 @@ impl Daemon {
SetAllowLan(tx, allow_lan) => self.on_set_allow_lan(tx, allow_lan).await,
SetShowBetaReleases(tx, enabled) => self.on_set_show_beta_releases(tx, enabled).await,
#[cfg(not(target_os = "android"))]
- SetBlockWhenDisconnected(tx, block_when_disconnected) => {
- self.on_set_block_when_disconnected(tx, block_when_disconnected)
- .await
+ SetLockdownMode(tx, lockdown_mode) => {
+ self.on_set_lockdown_mode(tx, lockdown_mode).await
}
SetAutoConnect(tx, auto_connect) => self.on_set_auto_connect(tx, auto_connect).await,
SetOpenVpnMssfix(tx, mssfix_arg) => self.on_set_openvpn_mssfix(tx, mssfix_arg).await,
@@ -2456,31 +2453,31 @@ impl Daemon {
}
#[cfg(not(target_os = "android"))]
- async fn on_set_block_when_disconnected(
+ async fn on_set_lockdown_mode(
&mut self,
tx: ResponseTx<(), settings::Error>,
- block_when_disconnected: bool,
+ lockdown_mode: bool,
) {
match self
.settings
- .update(move |settings| settings.block_when_disconnected = block_when_disconnected)
+ .update(move |settings| settings.lockdown_mode = lockdown_mode)
.await
{
Ok(settings_changed) => {
if settings_changed {
- self.send_tunnel_command(TunnelCommand::BlockWhenDisconnected(
- BlockWhenDisconnected::from(block_when_disconnected),
+ self.send_tunnel_command(TunnelCommand::LockdownMode(
+ LockdownMode::from(lockdown_mode),
oneshot_map(tx, |tx, ()| {
- Self::oneshot_send(tx, Ok(()), "set_block_when_disconnected response");
+ Self::oneshot_send(tx, Ok(()), "set_lockdown_mode response");
}),
));
} else {
- Self::oneshot_send(tx, Ok(()), "set_block_when_disconnected response");
+ Self::oneshot_send(tx, Ok(()), "set_lockdown_mode response");
}
}
Err(e) => {
log::error!("{}", e.display_chain_with_msg("Unable to save settings"));
- Self::oneshot_send(tx, Err(e), "set_block_when_disconnected response");
+ Self::oneshot_send(tx, Err(e), "set_lockdown_mode response");
}
}
}
@@ -3191,8 +3188,8 @@ impl Daemon {
#[cfg(not(target_os = "android"))]
{
let (tx, _rx) = oneshot::channel();
- self.send_tunnel_command(TunnelCommand::BlockWhenDisconnected(
- BlockWhenDisconnected::from(self.settings.block_when_disconnected),
+ self.send_tunnel_command(TunnelCommand::LockdownMode(
+ LockdownMode::from(self.settings.lockdown_mode),
tx,
));
}
@@ -3254,10 +3251,7 @@ impl Daemon {
{
log::debug!("Blocking firewall during shutdown");
let (tx, _rx) = oneshot::channel();
- self.send_tunnel_command(TunnelCommand::BlockWhenDisconnected(
- BlockWhenDisconnected::yes(),
- tx,
- ));
+ self.send_tunnel_command(TunnelCommand::LockdownMode(LockdownMode::yes(), tx));
}
self.disconnect_tunnel();
@@ -3277,14 +3271,13 @@ impl Daemon {
// non-persistent. If the installation of the new version fails and
// the user is left in blocked state with no app, they can reboot
// to regain internet access.
- self.settings.settings().block_when_disconnected
- || self.settings.settings().auto_connect
+ self.settings.settings().lockdown_mode || self.settings.settings().auto_connect
} else {
true
};
let (tx, _rx) = oneshot::channel();
- self.send_tunnel_command(TunnelCommand::BlockWhenDisconnected(
- BlockWhenDisconnected::yes().persist(persist),
+ self.send_tunnel_command(TunnelCommand::LockdownMode(
+ LockdownMode::yes().persist(persist),
tx,
));
}
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 7407208d55..a584b95f38 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -285,22 +285,19 @@ impl ManagementService for ManagementServiceImpl {
}
#[cfg(not(target_os = "android"))]
- async fn set_block_when_disconnected(&self, request: Request<bool>) -> ServiceResult<()> {
- let block_when_disconnected = request.into_inner();
- log::debug!("set_block_when_disconnected({})", block_when_disconnected);
+ async fn set_lockdown_mode(&self, request: Request<bool>) -> ServiceResult<()> {
+ let lockdown_mode = request.into_inner();
+ log::debug!("set_lockdown_mode({})", lockdown_mode);
let (tx, rx) = oneshot::channel();
- self.send_command_to_daemon(DaemonCommand::SetBlockWhenDisconnected(
- tx,
- block_when_disconnected,
- ))?;
+ self.send_command_to_daemon(DaemonCommand::SetLockdownMode(tx, lockdown_mode))?;
self.wait_for_result(rx).await??;
Ok(Response::new(()))
}
#[cfg(target_os = "android")]
- async fn set_block_when_disconnected(&self, request: Request<bool>) -> ServiceResult<()> {
- let block_when_disconnected = request.into_inner();
- log::debug!("set_block_when_disconnected({})", block_when_disconnected);
+ async fn set_lockdown_mode(&self, request: Request<bool>) -> ServiceResult<()> {
+ let lockdown_mode = request.into_inner();
+ log::debug!("set_lockdown_mode({})", lockdown_mode);
Err(Status::unimplemented(
"Setting Lockdown mode on Android is not supported - this is handled by the OS, not the daemon",
))
diff --git a/mullvad-daemon/src/migrations/mod.rs b/mullvad-daemon/src/migrations/mod.rs
index 251546ef57..284928073e 100644
--- a/mullvad-daemon/src/migrations/mod.rs
+++ b/mullvad-daemon/src/migrations/mod.rs
@@ -47,6 +47,7 @@ mod account_history;
mod device;
mod v1;
mod v10;
+mod v11;
mod v2;
mod v3;
mod v4;
@@ -210,6 +211,8 @@ async fn migrate_settings(
v10::migrate(settings)?;
+ v11::migrate(settings)?;
+
Ok(migration_data)
}
diff --git a/mullvad-daemon/src/migrations/snapshots/mullvad_daemon__migrations__v11__test__v11_to_v12_migration_access_method_name_duplicates.snap b/mullvad-daemon/src/migrations/snapshots/mullvad_daemon__migrations__v11__test__v11_to_v12_migration_access_method_name_duplicates.snap
new file mode 100644
index 0000000000..0bd3fe26ff
--- /dev/null
+++ b/mullvad-daemon/src/migrations/snapshots/mullvad_daemon__migrations__v11__test__v11_to_v12_migration_access_method_name_duplicates.snap
@@ -0,0 +1,136 @@
+---
+source: mullvad-daemon/src/migrations/v11.rs
+expression: "serde_json::to_string_pretty(&old_settings).unwrap()"
+---
+{
+ "api_access_methods": {
+ "custom": [
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-128-cfb",
+ "endpoint": "127.0.0.1:80",
+ "password": ""
+ }
+ }
+ },
+ "enabled": true,
+ "id": "90d35296-3823-4805-8926-720fff53c752",
+ "name": "test_3"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-256-cfb",
+ "endpoint": "127.0.0.1:443",
+ "password": "secret"
+ }
+ }
+ },
+ "enabled": true,
+ "id": "d879f6e9-c052-4452-8e53-088183d01c0a",
+ "name": "test_2"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-256-gcm",
+ "endpoint": "127.0.0.1:443",
+ "password": ""
+ }
+ }
+ },
+ "enabled": true,
+ "id": "7b49cef8-5a9f-4bbc-9bee-00841edc98e9",
+ "name": "test"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-128-gcm",
+ "endpoint": "127.0.0.1:80",
+ "password": ""
+ }
+ }
+ },
+ "enabled": true,
+ "id": "0bafc4ed-cd4f-4368-b067-74527f42451b",
+ "name": "test_1"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-128-cfb",
+ "endpoint": "127.0.0.1:443",
+ "password": ""
+ }
+ }
+ },
+ "enabled": false,
+ "id": "09d032bc-7e3a-4d85-a63f-528b6c4b890e",
+ "name": "test_2_1"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-256-gcm",
+ "endpoint": "127.0.0.1:80",
+ "password": "secret"
+ }
+ }
+ },
+ "enabled": false,
+ "id": "4471b3f5-a87e-4355-aea8-72c4c4936479",
+ "name": "test_1_1"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-128-cfb",
+ "endpoint": "127.0.0.1:443",
+ "password": ""
+ }
+ }
+ },
+ "enabled": false,
+ "id": "d284a9d5-307b-4959-94a6-89fef8187807",
+ "name": "test_4"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-256-cfb",
+ "endpoint": "127.0.0.1:9090",
+ "password": ""
+ }
+ }
+ },
+ "enabled": false,
+ "id": "6f8db7c3-2258-46c0-8b7d-2016dd9e5739",
+ "name": "other_name"
+ },
+ {
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "cipher": "aes-128-gcm",
+ "endpoint": "127.0.0.1:8080",
+ "password": ""
+ }
+ }
+ },
+ "enabled": true,
+ "id": "ffdf9900-e843-4298-9478-a9dfbaa63b17",
+ "name": "test_5"
+ }
+ ]
+ }
+}
diff --git a/mullvad-daemon/src/migrations/v11.rs b/mullvad-daemon/src/migrations/v11.rs
new file mode 100644
index 0000000000..905361bad6
--- /dev/null
+++ b/mullvad-daemon/src/migrations/v11.rs
@@ -0,0 +1,326 @@
+use super::{Error, Result};
+use mullvad_types::settings::SettingsVersion;
+
+/// The migration handles:
+/// - Renaming of block_when_disconnected option to lockdown_mode.
+/// - API access method names must now be unique and duplicates will be renamed.
+pub fn migrate(settings: &mut serde_json::Value) -> Result<()> {
+ if !(version(settings) == Some(SettingsVersion::V11)) {
+ return Ok(());
+ }
+
+ log::info!("Migrating settings format to v12");
+
+ migrate_block_when_disconnected(settings)?;
+ migrate_duplicated_api_access_method_names(settings)?;
+
+ settings["settings_version"] = serde_json::json!(SettingsVersion::V12);
+
+ Ok(())
+}
+
+fn version(settings: &serde_json::Value) -> Option<SettingsVersion> {
+ settings
+ .get("settings_version")
+ .and_then(|version| serde_json::from_value(version.clone()).ok())
+}
+
+fn migrate_block_when_disconnected(settings: &mut serde_json::Value) -> Result<()> {
+ let key_name_before = "block_when_disconnected";
+ let key_name_after = "lockdown_mode";
+
+ let settings_map = settings
+ .as_object_mut()
+ .ok_or(Error::InvalidSettingsContent)?;
+
+ // Get the old key's value and insert the new key with that value
+ let value = settings_map
+ .get(key_name_before)
+ .ok_or(Error::InvalidSettingsContent)?;
+ settings_map.insert(key_name_after.to_string(), value.clone());
+
+ // Remove the old key
+ settings_map.remove(key_name_before);
+
+ Ok(())
+}
+
+fn generate_access_method_name_initial_suffix(
+ access_method_names: &[impl AsRef<str>],
+ access_method_name: &String,
+) -> usize {
+ let access_method_name_count = access_method_names
+ .iter()
+ .filter(|name| name.as_ref() == access_method_name)
+ .count();
+
+ let mut suffix = 1;
+ if access_method_name_count > 1 {
+ suffix = access_method_name_count - 1
+ }
+
+ suffix
+}
+
+/// Only consider renaming access methods with a duplicate name if it has a higher index
+/// thab other access methods. This is to ensure that older entries' names are preserved,
+/// in favor of renaming newer access methods.
+fn get_should_rename_api_access_method(
+ access_method_names: &[impl AsRef<str>],
+ access_method_name: &String,
+ access_method_name_index: usize,
+) -> bool {
+ access_method_names.iter().enumerate().any(|(index, name)| {
+ access_method_name_index > index && name.as_ref() == *access_method_name
+ })
+}
+
+fn generate_access_method_name(
+ access_method_names: &[impl AsRef<str>],
+ access_method_name: &String,
+ access_method_name_index: usize,
+ access_method_name_suffix: usize,
+) -> String {
+ // Generate a new name for the access method
+ let generated_access_method_name = format!("{access_method_name}_{access_method_name_suffix}");
+
+ // Verify if the generated name is unique or if a new name should be generated
+ let should_rename_api_access_method = get_should_rename_api_access_method(
+ access_method_names,
+ &generated_access_method_name,
+ access_method_name_index,
+ );
+ if should_rename_api_access_method {
+ // Increment the suffix for the next attempt to generate a new access method name
+ generate_access_method_name(
+ access_method_names,
+ access_method_name,
+ access_method_name_index,
+ access_method_name_suffix + 1,
+ )
+ } else {
+ generated_access_method_name
+ }
+}
+
+fn migrate_duplicated_api_access_method_names(settings: &mut serde_json::Value) -> Result<()> {
+ let settings_map = settings
+ .as_object_mut()
+ .ok_or(Error::InvalidSettingsContent)?;
+
+ let mut custom_api_access_methods: Vec<&mut String> = settings_map
+ .get_mut("api_access_methods")
+ .and_then(serde_json::Value::as_object_mut)
+ .and_then(|api_access_method| api_access_method.get_mut("custom")?.as_array_mut())
+ .into_iter()
+ .flat_map(|array| array.iter_mut())
+ // Take a &mut to each custom api access method name as a String
+ .filter_map(|custom_api_access_method| custom_api_access_method.as_object_mut()?.get_mut("name"))
+ .filter_map(|custom_api_access_method| match custom_api_access_method {
+ serde_json::Value::String(custom_api_access_method_name) => {
+ Some(custom_api_access_method_name)
+ }
+ _ => None,
+ })
+ .collect();
+
+ for index in 0..custom_api_access_methods.len() {
+ let access_method_name = &*custom_api_access_methods[index];
+
+ let should_rename_api_access_method = get_should_rename_api_access_method(
+ &custom_api_access_methods,
+ access_method_name,
+ index,
+ );
+ if should_rename_api_access_method {
+ let access_method_name_suffix = generate_access_method_name_initial_suffix(
+ &custom_api_access_methods,
+ access_method_name,
+ );
+
+ let generated_access_method_name = generate_access_method_name(
+ &custom_api_access_methods,
+ access_method_name,
+ index,
+ access_method_name_suffix,
+ );
+
+ // Update the access method's name to the new unique name that was generated
+ *custom_api_access_methods[index] = generated_access_method_name;
+ }
+ }
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod test {
+ use serde_json::json;
+
+ use crate::migrations::v11::migrate_block_when_disconnected;
+ use crate::migrations::v11::migrate_duplicated_api_access_method_names;
+
+ /// "block_when_disconnected" is renamed to "lockdown_mode"
+ #[test]
+ fn test_v11_to_v12_migration_block_when_disconnected_disabled() {
+ let mut old_settings = json!({
+ "block_when_disconnected": false,
+ });
+ migrate_block_when_disconnected(&mut old_settings).unwrap();
+ let new_settings: serde_json::Value = json!({
+ "lockdown_mode": false,
+ });
+ assert_eq!(&old_settings, &new_settings);
+ }
+
+ #[test]
+ fn test_v11_to_v12_migration_block_when_disconnected_enabled() {
+ let mut old_settings = json!({
+ "block_when_disconnected": true,
+ });
+ migrate_block_when_disconnected(&mut old_settings).unwrap();
+ let new_settings: serde_json::Value = json!({
+ "lockdown_mode": true,
+ });
+ assert_eq!(&old_settings, &new_settings);
+ }
+
+ // custom access method's names are renamed if they are not unique
+ #[test]
+ fn test_v11_to_v12_migration_access_method_name_duplicates() {
+ let mut old_settings = json!({
+ "api_access_methods": {
+ "custom": [
+ {
+ "id": "90d35296-3823-4805-8926-720fff53c752",
+ "name": "test_3",
+ "enabled": true,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:80",
+ "password": "",
+ "cipher": "aes-128-cfb"
+ }
+ }
+ }
+ },
+ {
+ "id": "d879f6e9-c052-4452-8e53-088183d01c0a",
+ "name": "test_2",
+ "enabled": true,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:443",
+ "password": "secret",
+ "cipher": "aes-256-cfb"
+ }
+ }
+ }
+ },
+ {
+ "id": "7b49cef8-5a9f-4bbc-9bee-00841edc98e9",
+ "name": "test",
+ "enabled": true,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:443",
+ "password": "",
+ "cipher": "aes-256-gcm"
+ }
+ }
+ }
+ },
+ {
+ "id": "0bafc4ed-cd4f-4368-b067-74527f42451b",
+ "name": "test_1",
+ "enabled": true,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:80",
+ "password": "",
+ "cipher": "aes-128-gcm"
+ }
+ }
+ }
+ },
+ {
+ "id": "09d032bc-7e3a-4d85-a63f-528b6c4b890e",
+ "name": "test_2",
+ "enabled": false,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:443",
+ "password": "",
+ "cipher": "aes-128-cfb"
+ }
+ }
+ }
+ },
+ {
+ "id": "4471b3f5-a87e-4355-aea8-72c4c4936479",
+ "name": "test_1",
+ "enabled": false,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:80",
+ "password": "secret",
+ "cipher": "aes-256-gcm"
+ }
+ }
+ }
+ },
+ {
+ "id": "d284a9d5-307b-4959-94a6-89fef8187807",
+ "name": "test",
+ "enabled": false,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:443",
+ "password": "",
+ "cipher": "aes-128-cfb"
+ }
+ }
+ }
+ },
+ {
+ "id": "6f8db7c3-2258-46c0-8b7d-2016dd9e5739",
+ "name": "other_name",
+ "enabled": false,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:9090",
+ "password": "",
+ "cipher": "aes-256-cfb"
+ }
+ }
+ }
+ },
+ {
+ "id": "ffdf9900-e843-4298-9478-a9dfbaa63b17",
+ "name": "test",
+ "enabled": true,
+ "access_method": {
+ "custom": {
+ "shadowsocks": {
+ "endpoint": "127.0.0.1:8080",
+ "password": "",
+ "cipher": "aes-128-gcm"
+ }
+ }
+ }
+ }
+ ]
+ }
+ });
+ migrate_duplicated_api_access_method_names(&mut old_settings).unwrap();
+ insta::assert_snapshot!(serde_json::to_string_pretty(&old_settings).unwrap());
+ }
+}
diff --git a/mullvad-daemon/src/settings/mod.rs b/mullvad-daemon/src/settings/mod.rs
index a1d9434299..2fb0abcad0 100644
--- a/mullvad-daemon/src/settings/mod.rs
+++ b/mullvad-daemon/src/settings/mod.rs
@@ -193,7 +193,7 @@ impl SettingsPersister {
// On android lockdown mode is handled by the OS so setting this to true
// has no effect.
#[cfg(not(target_os = "android"))]
- block_when_disconnected: true,
+ lockdown_mode: true,
..Self::default_settings()
};
@@ -613,7 +613,7 @@ mod test {
},
"bridge_state": "auto",
"allow_lan": true,
- "block_when_disconnected": false,
+ "lockdown_mode": false,
"auto_connect": true,
"tunnel_options": {
"openvpn": {
@@ -690,7 +690,7 @@ mod test {
);
assert!(
- !settings.block_when_disconnected,
+ !settings.lockdown_mode,
"The daemon should not block the internet if settings are missing"
);
}
@@ -720,7 +720,7 @@ mod test {
);
assert!(
- settings.block_when_disconnected,
+ settings.lockdown_mode,
"The daemon should block the internet if settings are corrupt"
);
}
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index ff3206cb6a..207b977070 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -43,7 +43,7 @@ service ManagementService {
rpc ResetSettings(google.protobuf.Empty) returns (google.protobuf.Empty) {}
rpc SetAllowLan(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetShowBetaReleases(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
- rpc SetBlockWhenDisconnected(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
+ rpc SetLockdownMode(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetAutoConnect(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetOpenvpnMssfix(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
rpc SetWireguardMtu(google.protobuf.UInt32Value) returns (google.protobuf.Empty) {}
@@ -531,7 +531,7 @@ message Settings {
BridgeSettings bridge_settings = 2;
BridgeState bridge_state = 3;
bool allow_lan = 4;
- bool block_when_disconnected = 5;
+ bool lockdown_mode = 5;
bool auto_connect = 6;
TunnelOptions tunnel_options = 7;
bool show_beta_releases = 8;
diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs
index afadfd0875..aa8b67d930 100644
--- a/mullvad-management-interface/src/client.rs
+++ b/mullvad-management-interface/src/client.rs
@@ -265,8 +265,8 @@ impl MullvadProxyClient {
Ok(())
}
- pub async fn set_block_when_disconnected(&mut self, state: bool) -> Result<()> {
- self.0.set_block_when_disconnected(state).await?;
+ pub async fn set_lockdown_mode(&mut self, state: bool) -> Result<()> {
+ self.0.set_lockdown_mode(state).await?;
Ok(())
}
diff --git a/mullvad-management-interface/src/types/conversions/settings.rs b/mullvad-management-interface/src/types/conversions/settings.rs
index e9f68524ce..8e1275b72b 100644
--- a/mullvad-management-interface/src/types/conversions/settings.rs
+++ b/mullvad-management-interface/src/types/conversions/settings.rs
@@ -34,9 +34,9 @@ impl From<&mullvad_types::settings::Settings> for proto::Settings {
bridge_state: Some(proto::BridgeState::from(settings.bridge_state)),
allow_lan: settings.allow_lan,
#[cfg(not(target_os = "android"))]
- block_when_disconnected: settings.block_when_disconnected,
+ lockdown_mode: settings.lockdown_mode,
#[cfg(target_os = "android")]
- block_when_disconnected: false,
+ lockdown_mode: false,
auto_connect: settings.auto_connect,
tunnel_options: Some(proto::TunnelOptions::from(&settings.tunnel_options)),
show_beta_releases: settings.show_beta_releases,
@@ -180,7 +180,7 @@ impl TryFrom<proto::Settings> for mullvad_types::settings::Settings {
bridge_state,
allow_lan: settings.allow_lan,
#[cfg(not(target_os = "android"))]
- block_when_disconnected: settings.block_when_disconnected,
+ lockdown_mode: settings.lockdown_mode,
auto_connect: settings.auto_connect,
tunnel_options: mullvad_types::settings::TunnelOptions::try_from(tunnel_options)?,
relay_overrides: settings
diff --git a/mullvad-types/src/features.rs b/mullvad-types/src/features.rs
index a16f7ca33f..8dc8f5cad5 100644
--- a/mullvad-types/src/features.rs
+++ b/mullvad-types/src/features.rs
@@ -138,7 +138,7 @@ pub fn compute_feature_indicators(
let split_tunneling = false;
#[cfg(not(target_os = "android"))]
- let lockdown_mode = settings.block_when_disconnected;
+ let lockdown_mode = settings.lockdown_mode;
let lan_sharing = settings.allow_lan;
let dns_content_blockers = settings
.tunnel_options
@@ -267,7 +267,7 @@ mod tests {
If this is not true anymore, please update this test."
);
- settings.block_when_disconnected = true;
+ settings.lockdown_mode = true;
expected_indicators.0.insert(FeatureIndicator::LockdownMode);
assert_eq!(
diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs
index ae55fd3d79..1263089d8f 100644
--- a/mullvad-types/src/settings/mod.rs
+++ b/mullvad-types/src/settings/mod.rs
@@ -20,7 +20,7 @@ mod dns;
/// latest version that exists in `SettingsVersion`.
/// This should be bumped when a new version is introduced along with a migration
/// being added to `mullvad-daemon`.
-pub const CURRENT_SETTINGS_VERSION: SettingsVersion = SettingsVersion::V11;
+pub const CURRENT_SETTINGS_VERSION: SettingsVersion = SettingsVersion::V12;
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
#[repr(u32)]
@@ -35,6 +35,7 @@ pub enum SettingsVersion {
V9 = 9,
V10 = 10,
V11 = 11,
+ V12 = 12,
}
impl<'de> Deserialize<'de> for SettingsVersion {
@@ -53,6 +54,7 @@ impl<'de> Deserialize<'de> for SettingsVersion {
v if v == SettingsVersion::V9 as u32 => Ok(SettingsVersion::V9),
v if v == SettingsVersion::V10 as u32 => Ok(SettingsVersion::V10),
v if v == SettingsVersion::V11 as u32 => Ok(SettingsVersion::V11),
+ v if v == SettingsVersion::V12 as u32 => Ok(SettingsVersion::V12),
v => Err(serde::de::Error::custom(format!(
"{v} is not a valid SettingsVersion"
))),
@@ -88,7 +90,7 @@ pub struct Settings {
/// Extra level of kill switch. When this setting is on, the disconnected state will block
/// the firewall to not allow any traffic in or out.
#[cfg(not(target_os = "android"))]
- pub block_when_disconnected: bool,
+ pub lockdown_mode: bool,
/// If the daemon should connect the VPN tunnel directly on start or not.
pub auto_connect: bool,
/// Options that should be applied to tunnels of a specific type regardless of where the relays
@@ -270,7 +272,7 @@ impl Default for Settings {
api_access_methods: access_method::Settings::default(),
allow_lan: false,
#[cfg(not(target_os = "android"))]
- block_when_disconnected: false,
+ lockdown_mode: false,
auto_connect: false,
tunnel_options: TunnelOptions::default(),
relay_overrides: vec![],
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index 5076338653..b488c4dec0 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -337,8 +337,8 @@ impl ConnectedState {
consequence
}
#[cfg(not(target_os = "android"))]
- Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected, complete_tx)) => {
- shared_values.block_when_disconnected = block_when_disconnected;
+ Some(TunnelCommand::LockdownMode(lockdown_mode, complete_tx)) => {
+ shared_values.lockdown_mode = lockdown_mode;
let _ = complete_tx.send(());
SameState(self)
}
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index 479238af60..f338a9b7c3 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -474,8 +474,8 @@ impl ConnectingState {
consequence
}
#[cfg(not(target_os = "android"))]
- Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected, complete_tx)) => {
- shared_values.block_when_disconnected = block_when_disconnected;
+ Some(TunnelCommand::LockdownMode(lockdown_mode, complete_tx)) => {
+ shared_values.lockdown_mode = lockdown_mode;
let _ = complete_tx.send(());
SameState(self)
}
diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
index 024958bdc6..3d1e98830e 100644
--- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
@@ -30,7 +30,7 @@ impl DisconnectedState {
);
}
#[cfg(target_os = "macos")]
- if shared_values.block_when_disconnected.bool() {
+ if shared_values.lockdown_mode.bool() {
if let Err(err) = Self::setup_local_dns_config(shared_values) {
log::error!(
"{}",
@@ -64,7 +64,7 @@ impl DisconnectedState {
// Being disconnected and having lockdown mode enabled implies that your internet
// access is locked down
#[cfg(not(target_os = "android"))]
- locked_down: shared_values.block_when_disconnected.bool(),
+ locked_down: shared_values.lockdown_mode.bool(),
},
)
}
@@ -74,13 +74,13 @@ impl DisconnectedState {
shared_values: &mut SharedTunnelStateValues,
should_reset_firewall: bool,
) {
- let result = if shared_values.block_when_disconnected.bool() {
+ let result = if shared_values.lockdown_mode.bool() {
#[cfg(target_os = "windows")]
{
- // Respect the persist flag of BlockWhenDisconnected.
+ // Respect the persist flag of LockdownMode.
shared_values
.firewall
- .persist(shared_values.block_when_disconnected.should_persist());
+ .persist(shared_values.lockdown_mode.should_persist());
}
let policy = FirewallPolicy::Blocked {
@@ -118,7 +118,7 @@ impl DisconnectedState {
shared_values: &mut SharedTunnelStateValues,
should_reset_firewall: bool,
) {
- if should_reset_firewall && !shared_values.block_when_disconnected.bool() {
+ if should_reset_firewall && !shared_values.lockdown_mode.bool() {
if let Err(error) = shared_values.split_tunnel.clear_tunnel_addresses() {
log::error!(
"{}",
@@ -193,9 +193,9 @@ impl TunnelState for DisconnectedState {
SameState(self)
}
#[cfg(not(target_os = "android"))]
- Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected, complete_tx)) => {
- if shared_values.block_when_disconnected != block_when_disconnected {
- shared_values.block_when_disconnected = block_when_disconnected;
+ Some(TunnelCommand::LockdownMode(lockdown_mode, complete_tx)) => {
+ if shared_values.lockdown_mode != lockdown_mode {
+ shared_values.lockdown_mode = lockdown_mode;
// TODO: Investigate if we can simply return
// `NewState(Self::enter(shared_values, true))`.
@@ -206,7 +206,7 @@ impl TunnelState for DisconnectedState {
#[cfg(windows)]
Self::register_split_tunnel_addresses(shared_values, true);
#[cfg(target_os = "macos")]
- if block_when_disconnected.bool() {
+ if lockdown_mode.bool() {
if let Err(err) = Self::setup_local_dns_config(shared_values) {
log::error!(
"{}",
diff --git a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
index a93be7b740..51807b76da 100644
--- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
@@ -51,8 +51,8 @@ impl DisconnectingState {
let _ = complete_tx.send(());
}
#[cfg(not(target_os = "android"))]
- Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected, complete_tx)) => {
- shared_values.block_when_disconnected = block_when_disconnected;
+ Some(TunnelCommand::LockdownMode(lockdown_mode, complete_tx)) => {
+ shared_values.lockdown_mode = lockdown_mode;
let _ = complete_tx.send(());
}
Some(TunnelCommand::Connectivity(connectivity)) => {
diff --git a/talpid-core/src/tunnel_state_machine/error_state.rs b/talpid-core/src/tunnel_state_machine/error_state.rs
index 32e4747f47..e6f1008a73 100644
--- a/talpid-core/src/tunnel_state_machine/error_state.rs
+++ b/talpid-core/src/tunnel_state_machine/error_state.rs
@@ -177,8 +177,8 @@ impl TunnelState for ErrorState {
consequence
}
#[cfg(not(target_os = "android"))]
- Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected, complete_tx)) => {
- shared_values.block_when_disconnected = block_when_disconnected;
+ Some(TunnelCommand::LockdownMode(lockdown_mode, complete_tx)) => {
+ shared_values.lockdown_mode = lockdown_mode;
let _ = complete_tx.send(());
SameState(self)
}
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 0dd029cf86..16e15d08a0 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -95,7 +95,7 @@ pub struct InitialTunnelState {
pub allow_lan: bool,
/// Block traffic unless connected to the VPN.
#[cfg(not(target_os = "android"))]
- pub block_when_disconnected: BlockWhenDisconnected,
+ pub lockdown_mode: LockdownMode,
/// DNS configuration to use
pub dns_config: DnsConfig,
/// A single endpoint that is allowed to communicate outside the tunnel, i.e.
@@ -199,9 +199,9 @@ pub enum TunnelCommand {
AllowEndpoint(AllowedEndpoint, oneshot::Sender<()>),
/// Set DNS configuration to use.
Dns(crate::dns::DnsConfig, oneshot::Sender<()>),
- /// Enable or disable the block_when_disconnected feature.
+ /// Enable or disable the lockdown_mode feature.
#[cfg(not(target_os = "android"))]
- BlockWhenDisconnected(BlockWhenDisconnected, oneshot::Sender<()>),
+ LockdownMode(LockdownMode, oneshot::Sender<()>),
/// Notify the state machine of the connectivity of the device.
Connectivity(Connectivity),
/// Open tunnel connection.
@@ -236,12 +236,12 @@ enum EventResult {
}
/// If firewall should apply blocking rules in the disconnected state.
-/// Argument of TunnelCommand::BlockWhenDisconnected message.
+/// Argument of TunnelCommand::LockdownMode message.
///
/// Semantically equivalent to a boolean value, but is grouped togetether with the persist
/// parameter on Windows for cohesiveness.
#[derive(Clone, Copy, Debug)]
-pub enum BlockWhenDisconnected {
+pub enum LockdownMode {
/// Firewall should *not* apply blocking rules.
Disabled,
/// Firewall should apply blocking rules.
@@ -251,28 +251,28 @@ pub enum BlockWhenDisconnected {
},
}
-impl BlockWhenDisconnected {
+impl LockdownMode {
/// `true`. Apply blocking firewall rules in the disconnected state.
pub const fn yes() -> Self {
- BlockWhenDisconnected::Enabled { persist: true }
+ LockdownMode::Enabled { persist: true }
}
/// `false`. Do *not* apply blocking firewall rules in the disconnected state.
pub const fn no() -> Self {
- BlockWhenDisconnected::Disabled
+ LockdownMode::Disabled
}
/// [self] as a boolean value.
pub const fn bool(&self) -> bool {
- matches!(self, BlockWhenDisconnected::Enabled { .. })
+ matches!(self, LockdownMode::Enabled { .. })
}
- /// If [BlockWhenDisconnected] should persist across reboots.
+ /// If [LockdownMode] should persist across reboots.
///
/// Semantically meaningless on non-Windows platforms, will always return true.
pub const fn should_persist(&self) -> bool {
if cfg!(target_os = "windows") {
- matches!(&self, BlockWhenDisconnected::Enabled { persist: true })
+ matches!(&self, LockdownMode::Enabled { persist: true })
} else {
true
}
@@ -288,24 +288,24 @@ impl BlockWhenDisconnected {
#[cfg(target_os = "windows")]
pub fn persist(self, persist: bool) -> Self {
match self {
- BlockWhenDisconnected::Disabled => BlockWhenDisconnected::Disabled,
+ LockdownMode::Disabled => LockdownMode::Disabled,
// Forget previous value of persist
- BlockWhenDisconnected::Enabled { .. } => BlockWhenDisconnected::Enabled { persist },
+ LockdownMode::Enabled { .. } => LockdownMode::Enabled { persist },
}
}
}
-impl From<bool> for BlockWhenDisconnected {
+impl From<bool> for LockdownMode {
fn from(block: bool) -> Self {
if block {
- BlockWhenDisconnected::yes()
+ LockdownMode::yes()
} else {
- BlockWhenDisconnected::no()
+ LockdownMode::no()
}
}
}
-impl PartialEq for BlockWhenDisconnected {
+impl PartialEq for LockdownMode {
fn eq(&self, other: &Self) -> bool {
self.bool() == other.bool()
}
@@ -385,9 +385,7 @@ impl TunnelStateMachine {
let fw_args = FirewallArguments {
#[cfg(not(target_os = "android"))]
- initial_state: if args.settings.block_when_disconnected.bool()
- || !args.settings.reset_firewall
- {
+ initial_state: if args.settings.lockdown_mode.bool() || !args.settings.reset_firewall {
InitialFirewallState::Blocked(args.settings.allowed_endpoint.clone())
} else {
InitialFirewallState::None
@@ -470,7 +468,7 @@ impl TunnelStateMachine {
_offline_monitor: offline_monitor,
allow_lan: args.settings.allow_lan,
#[cfg(not(target_os = "android"))]
- block_when_disconnected: args.settings.block_when_disconnected,
+ lockdown_mode: args.settings.lockdown_mode,
connectivity,
dns_config: args.settings.dns_config,
allowed_endpoint: args.settings.allowed_endpoint,
@@ -565,7 +563,7 @@ struct SharedTunnelStateValues {
allow_lan: bool,
/// Should network access be allowed when in the disconnected state.
#[cfg(not(target_os = "android"))]
- block_when_disconnected: BlockWhenDisconnected,
+ lockdown_mode: LockdownMode,
/// True when the computer is known to be offline.
connectivity: Connectivity,
/// DNS configuration to use.
diff --git a/test/test-manager/src/tests/settings.rs b/test/test-manager/src/tests/settings.rs
index bc7ad3287d..d07a55c5c9 100644
--- a/test/test-manager/src/tests/settings.rs
+++ b/test/test-manager/src/tests/settings.rs
@@ -112,7 +112,7 @@ pub async fn test_lockdown(
// Enable lockdown mode
//
mullvad_client
- .set_block_when_disconnected(true)
+ .set_lockdown_mode(true)
.await
.expect("failed to enable lockdown mode");
diff --git a/test/test-manager/src/tests/windows.rs b/test/test-manager/src/tests/windows.rs
index e857b6901f..0923825969 100644
--- a/test/test-manager/src/tests/windows.rs
+++ b/test/test-manager/src/tests/windows.rs
@@ -22,7 +22,7 @@ async fn test_clearing_blocked_state_on_failed_upgrade(
{
let settings = mullvad_client.get_settings().await?;
ensure!(
- !settings.block_when_disconnected,
+ !settings.lockdown_mode,
"Block when disconnected should be disabled"
);
ensure!(!settings.auto_connect, "Auto connect should be disabled");
@@ -88,10 +88,10 @@ async fn test_not_clearing_blocked_state_on_failed_upgrade_with_lockdown_mode(
// Make sure that lockdown mode is enabled.
// If it is not, then blocking firewall rules *will not* persist after a reboot.
{
- mullvad_client.set_block_when_disconnected(true).await?;
+ mullvad_client.set_lockdown_mode(true).await?;
let settings = mullvad_client.get_settings().await?;
ensure!(
- settings.block_when_disconnected,
+ settings.lockdown_mode,
"Block when disconnected should be enabled"
);
ensure!(!settings.auto_connect, "Auto connect should be disabled");