summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src/cmds/debug.rs
blob: 37c2d579e37a51161a46159b55428a03d8f89cca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use anyhow::{Result, bail};
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::{
    constraints::Constraint,
    relay_constraints::{RelayConstraints, RelaySettings},
};

#[derive(clap::Subcommand, Debug)]
pub enum DebugCommands {
    /// Block all internet connection by setting an invalid relay constraint.
    BlockConnection,
    /// Relay
    #[clap(subcommand)]
    Relay(RelayDebugCommands),
    /// Handy commands for interacting with the app release rollout system.
    #[clap(subcommand)]
    Rollout(RolloutDebugCommands),
}

#[derive(clap::Subcommand, Debug)]
pub enum RelayDebugCommands {
    /// Inactivate this _category of relays_ - a category can be one of the following: a relay, a
    /// city, a country or a tunnel protocol (`openvpn` or `wireguard`).
    Disable { relay: String },
    /// (Re)Activate this _category of relays_ - a category can be one of the following: a relay, a
    /// city, a country or a tunnel protocol (`openvpn` or `wireguard`).
    Enable { relay: String },
}

#[derive(clap::Subcommand, Debug)]
pub enum RolloutDebugCommands {
    /// Print your rollout threshold.
    Get,
    /// Generate a new rollout threshold (overwrites the current threshold value)
    Reroll,
    /// Set your rollout threshold seed to a known value.
    ///
    /// The seed is used to generate a rollout threshold.
    Seed { value: u32 },
}

impl DebugCommands {
    pub async fn handle(self) -> Result<()> {
        match self {
            DebugCommands::BlockConnection => {
                let mut rpc = MullvadProxyClient::new().await?;
                let settings = rpc.get_settings().await?;

                let relay_settings = settings.get_relay_settings();
                let mut constraints = match relay_settings {
                    RelaySettings::Normal(normal) => normal,
                    RelaySettings::CustomTunnelEndpoint(_custom) => {
                        println!("Removing custom relay settings");
                        RelayConstraints::default()
                    }
                };
                constraints.location = Constraint::Only(
                    mullvad_types::relay_constraints::LocationConstraint::Location(
                        mullvad_types::relay_constraints::GeographicLocationConstraint::Country(
                            "xx".into(),
                        ),
                    ),
                );
                rpc.set_relay_settings(RelaySettings::Normal(constraints))
                    .await?;

                rpc.connect_tunnel().await?;

                eprintln!("WARNING: ENTERED BLOCKED MODE");
                Ok(())
            }
            DebugCommands::Relay(RelayDebugCommands::Disable { relay }) => {
                let mut rpc = MullvadProxyClient::new().await?;
                rpc.disable_relay(relay.clone()).await?;
                println!("{relay} is now marked as inactive");
                Ok(())
            }
            DebugCommands::Relay(RelayDebugCommands::Enable { relay }) => {
                let mut rpc = MullvadProxyClient::new().await?;
                rpc.enable_relay(relay.clone()).await?;
                println!("{relay} is now marked as active");
                Ok(())
            }
            DebugCommands::Rollout(rollout_cmd) => rollout_cmd.handle().await,
        }
    }
}

impl RolloutDebugCommands {
    pub async fn handle(self) -> Result<()> {
        let mut rpc = MullvadProxyClient::new().await?;
        match self {
            RolloutDebugCommands::Get => {
                let Ok(threshold) = rpc.get_rollout_threshold().await else {
                    bail!("Failed to get rollout");
                };
                println!("{threshold}");
                Ok(())
            }
            RolloutDebugCommands::Reroll => {
                let Ok(threshold) = rpc.generate_new_rollout_threshold().await else {
                    bail!("Failed to get rollout");
                };
                println!("{threshold}");
                Ok(())
            }
            RolloutDebugCommands::Seed { value: seed } => {
                if rpc.set_new_rollout_threshold_seed(seed).await.is_err() {
                    bail!("Failed to update rollout seed");
                }
                Ok(())
            }
        }
    }
}