diff options
| author | David Lönnhager <david.l@mullvad.net> | 2023-05-03 11:20:31 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2023-05-03 11:20:31 +0200 |
| commit | 49ea114adddba1a1db6ffc6c440e743c01797a47 (patch) | |
| tree | 66f1bf1e3e1d208e233e5622045503abe85a3a89 /mullvad-cli/src/cmds/split_tunnel | |
| parent | beaa6d3b80d9c9dfed99c710c793830db3ddc7ec (diff) | |
| parent | aade46c9c73c874e4153caa450e713d8f8b37760 (diff) | |
| download | mullvadvpn-49ea114adddba1a1db6ffc6c440e743c01797a47.tar.xz mullvadvpn-49ea114adddba1a1db6ffc6c440e743c01797a47.zip | |
Merge branch 'update-clap'
Diffstat (limited to 'mullvad-cli/src/cmds/split_tunnel')
| -rw-r--r-- | mullvad-cli/src/cmds/split_tunnel/linux.rs | 99 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/split_tunnel/windows.rs | 207 |
2 files changed, 119 insertions, 187 deletions
diff --git a/mullvad-cli/src/cmds/split_tunnel/linux.rs b/mullvad-cli/src/cmds/split_tunnel/linux.rs index 8b235f1027..5a66d899ab 100644 --- a/mullvad-cli/src/cmds/split_tunnel/linux.rs +++ b/mullvad-cli/src/cmds/split_tunnel/linux.rs @@ -1,82 +1,61 @@ -use crate::{new_rpc_client, Command, Result}; +use anyhow::Result; +use clap::Subcommand; +use mullvad_management_interface::MullvadProxyClient; -pub struct SplitTunnel; - -#[mullvad_management_interface::async_trait] -impl Command for SplitTunnel { - fn name(&self) -> &'static str { - "split-tunnel" - } - - fn clap_subcommand(&self) -> clap::App<'static> { - clap::App::new(self.name()) - .about( - "Manage split tunneling. To launch applications outside \ - the tunnel, use the program 'mullvad-exclude' instead of this command.", - ) - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .subcommand(create_pid_subcommand()) - } - - async fn run(&self, matches: &clap::ArgMatches) -> Result<()> { - match matches.subcommand() { - Some(("pid", pid_matches)) => Self::handle_pid_cmd(pid_matches).await, - _ => unreachable!("unhandled command"), - } - } -} - -fn create_pid_subcommand() -> clap::App<'static> { - clap::App::new("pid") - .about("Manage processes to exclude from the tunnel") - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .subcommand(clap::App::new("add").arg(clap::Arg::new("pid").required(true))) - .subcommand(clap::App::new("delete").arg(clap::Arg::new("pid").required(true))) - .subcommand(clap::App::new("clear")) - .subcommand(clap::App::new("list")) +/// Manage split tunneling. To launch applications outside the tunnel, use the program +/// 'mullvad-exclude' instead of this command +#[derive(Subcommand, Debug)] +pub enum SplitTunnel { + /// List all processes that are excluded from the tunnel + List, + /// Add a PID to exclude from the tunnel + Add { pid: i32 }, + /// Stop excluding a PID from the tunnel + Delete { pid: i32 }, + /// Stop excluding all processes from the tunnel + Clear, } impl SplitTunnel { - async fn handle_pid_cmd(matches: &clap::ArgMatches) -> Result<()> { - match matches.subcommand() { - Some(("add", matches)) => { - let pid: i32 = matches.value_of_t_or_exit("pid"); - new_rpc_client() + pub async fn handle(self) -> Result<()> { + match self { + SplitTunnel::List => { + let pids = MullvadProxyClient::new() .await? - .add_split_tunnel_process(pid) + .get_split_tunnel_processes() .await?; + + println!("Excluded PIDs:"); + for pid in &pids { + println!("{pid}"); + } + Ok(()) } - Some(("delete", matches)) => { - let pid: i32 = matches.value_of_t_or_exit("pid"); - new_rpc_client() + SplitTunnel::Add { pid } => { + MullvadProxyClient::new() .await? - .remove_split_tunnel_process(pid) + .add_split_tunnel_process(pid) .await?; + println!("Excluding process"); Ok(()) } - Some(("clear", _)) => { - new_rpc_client() + SplitTunnel::Delete { pid } => { + MullvadProxyClient::new() .await? - .clear_split_tunnel_processes(()) + .remove_split_tunnel_process(pid) .await?; + println!("Stopped excluding process"); Ok(()) } - Some(("list", _)) => { - let mut pids_stream = new_rpc_client() - .await? - .get_split_tunnel_processes(()) + SplitTunnel::Clear => { + MullvadProxyClient::new() .await? - .into_inner(); - println!("Excluded PIDs:"); - - while let Some(pid) = pids_stream.message().await? { - println!(" {pid}"); - } - + .clear_split_tunnel_processes() + .await?; + println!("Stopped excluding all processes"); Ok(()) } - _ => unreachable!("unhandled command"), } } } diff --git a/mullvad-cli/src/cmds/split_tunnel/windows.rs b/mullvad-cli/src/cmds/split_tunnel/windows.rs index a133ab9682..f17a3382f3 100644 --- a/mullvad-cli/src/cmds/split_tunnel/windows.rs +++ b/mullvad-cli/src/cmds/split_tunnel/windows.rs @@ -1,157 +1,110 @@ -use std::{ffi::OsStr, path::Path}; +use anyhow::Result; +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, +}; -use crate::{new_rpc_client, Command, Result}; +use clap::Subcommand; +use mullvad_management_interface::MullvadProxyClient; -pub struct SplitTunnel; +use super::super::BooleanOption; -#[mullvad_management_interface::async_trait] -impl Command for SplitTunnel { - fn name(&self) -> &'static str { - "split-tunnel" - } +/// Set options for applications to exclude from the tunnel. +#[derive(Subcommand, Debug)] +pub enum SplitTunnel { + /// Display the split tunnel status and apps + Get { + /// List processes that are currently being excluded, as well as whether they are + /// excluded because of their executable paths or because they're subprocesses of + /// such processes + #[arg(long)] + list_processes: bool, + }, - fn clap_subcommand(&self) -> clap::App<'static> { - clap::App::new(self.name()) - .about("Set options for applications to exclude from the tunnel") - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .subcommand(create_app_subcommand()) - .subcommand( - clap::App::new("set") - .about("Enable or disable split tunnel") - .arg( - clap::Arg::new("policy") - .required(true) - .possible_values(["on", "off"]), - ), - ) - .subcommand(clap::App::new("get").about("Display the split tunnel status")) - .subcommand(create_pid_subcommand()) - } + /// Enable or disable split tunnel + Set { policy: BooleanOption }, - async fn run(&self, matches: &clap::ArgMatches) -> Result<()> { - match matches.subcommand() { - Some(("app", matches)) => Self::handle_app_subcommand(matches).await, - Some(("pid", matches)) => Self::handle_pid_subcommand(matches).await, - Some(("get", _)) => self.get().await, - Some(("set", matches)) => { - let enabled = matches.value_of("policy").expect("missing policy"); - self.set(enabled == "on").await - } - _ => { - unreachable!("unhandled command"); - } - } - } -} - -fn create_app_subcommand() -> clap::App<'static> { - clap::App::new("app") - .about("Manage applications to exclude from the tunnel") - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .subcommand(clap::App::new("list")) - .subcommand(clap::App::new("add").arg(clap::Arg::new("path").required(true))) - .subcommand(clap::App::new("remove").arg(clap::Arg::new("path").required(true))) - .subcommand(clap::App::new("clear")) + /// Manage applications to exclude from the tunnel + #[clap(subcommand)] + App(App), } -fn create_pid_subcommand() -> clap::App<'static> { - clap::App::new("pid") - .about("Manages processes (PIDs) excluded from the tunnel") - .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .subcommand(clap::App::new("list") - .about("List processes that are currently being excluded, i.e. their PIDs, as well as whether \ - they are excluded because of their executable paths or because they're subprocesses of \ - such processes")) +#[derive(Subcommand, Debug)] +pub enum App { + Add { path: PathBuf }, + Remove { path: PathBuf }, + Clear, } impl SplitTunnel { - async fn handle_app_subcommand(matches: &clap::ArgMatches) -> Result<()> { - match matches.subcommand() { - Some(("list", _)) => { - let paths = new_rpc_client() - .await? - .get_settings(()) - .await? - .into_inner() - .split_tunnel - .unwrap() - .apps; + pub async fn handle(self) -> Result<()> { + match self { + SplitTunnel::Get { list_processes } => { + let mut rpc = MullvadProxyClient::new().await?; + let settings = rpc.get_settings().await?.split_tunnel; + + let enable_exclusions = BooleanOption::from(settings.enable_exclusions); + + println!("Split tunneling state: {enable_exclusions}"); println!("Excluded applications:"); - for path in &paths { - println!(" {}", path); + for path in &settings.apps { + println!("{}", path.display()); + } + + if list_processes { + let processes = rpc.get_excluded_processes().await?; + for process in &processes { + let subproc = if process.inherited { "subprocess" } else { "" }; + println!( + "{:<7}{subproc:<12}{}", + process.pid, + Path::new(&process.image) + .file_name() + .unwrap_or(OsStr::new("unknown")) + .to_string_lossy() + ); + } } Ok(()) } - Some(("add", matches)) => { - let path: String = matches.value_of_t_or_exit("path"); - new_rpc_client().await?.add_split_tunnel_app(path).await?; + SplitTunnel::Set { policy } => { + let mut rpc = MullvadProxyClient::new().await?; + rpc.set_split_tunnel_state(*policy).await?; + println!("Split tunnel policy: {policy}"); Ok(()) } - Some(("remove", matches)) => { - let path: String = matches.value_of_t_or_exit("path"); - new_rpc_client() + SplitTunnel::App(subcmd) => Self::app(subcmd).await, + } + } + + async fn app(subcmd: App) -> Result<()> { + match subcmd { + App::Add { path } => { + MullvadProxyClient::new() .await? - .remove_split_tunnel_app(path) + .add_split_tunnel_app(path) .await?; + println!("Added path to excluded apps list"); Ok(()) } - Some(("clear", _)) => { - new_rpc_client().await?.clear_split_tunnel_apps(()).await?; + App::Remove { path } => { + MullvadProxyClient::new() + .await? + .remove_split_tunnel_app(path) + .await?; + println!("Stopped excluding app from tunnel"); Ok(()) } - _ => unreachable!("unhandled subcommand"), - } - } - - async fn handle_pid_subcommand(matches: &clap::ArgMatches) -> Result<()> { - match matches.subcommand() { - Some(("list", _)) => { - let processes = new_rpc_client() - .await? - .get_excluded_processes(()) + App::Clear => { + MullvadProxyClient::new() .await? - .into_inner(); - - for process in &processes.processes { - let subproc = if process.inherited { "subprocess" } else { "" }; - println!( - "{:<7}{subproc:<12}{}", - process.pid, - Path::new(&process.image) - .file_name() - .unwrap_or(OsStr::new("unknown")) - .to_string_lossy() - ); - } - + .clear_split_tunnel_apps() + .await?; + println!("Stopped excluding all apps"); Ok(()) } - _ => unreachable!("unhandled subcommand"), } } - - async fn set(&self, enabled: bool) -> Result<()> { - let mut rpc = new_rpc_client().await?; - rpc.set_split_tunnel_state(enabled).await?; - println!("Changed split tunnel setting"); - Ok(()) - } - - async fn get(&self) -> Result<()> { - let mut rpc = new_rpc_client().await?; - let enabled = rpc - .get_settings(()) - .await? - .into_inner() - .split_tunnel - .unwrap() - .enable_exclusions; - println!( - "Split tunnel status: {}", - if enabled { "on" } else { "off" } - ); - Ok(()) - } } |
