diff --git a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java index 602d757..e7e3e2b 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java +++ b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java @@ -23,6 +23,7 @@ public class GnirehtetActivity extends Activity { public static final String EXTRA_DNS_SERVERS = "dnsServers"; public static final String EXTRA_ROUTES = "routes"; + public static final String EXTRA_BUNDLE_IDS = "whitelistBundleIds"; private static final int VPN_REQUEST_CODE = 0; @@ -59,7 +60,11 @@ private static VpnConfiguration createConfig(Intent intent) { if (routes == null) { routes = new String[0]; } - return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes)); + String[] whitelistBundleIds = intent.getStringArrayExtra(EXTRA_BUNDLE_IDS); + if (whitelistBundleIds == null) { + whitelistBundleIds = new String[0]; + } + return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes), whitelistBundleIds); } private boolean startGnirehtet(VpnConfiguration config) { diff --git a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java index 7e8b716..0280c86 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java +++ b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java @@ -18,6 +18,7 @@ import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.LinkAddress; import android.net.LinkProperties; @@ -135,6 +136,18 @@ private boolean setupVpn(VpnConfiguration config) { } } + if (Build.VERSION.SDK_INT >= 21) { + Log.i(TAG, "Setting whitelist bundle id"); + for (String app : config.getWhitelistBundleIds()) { + Log.i(TAG, app + " traffic is being routed through USB"); + try { + builder.addAllowedApplication(app); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, app + " not found"); + } + } + } + // non-blocking by default, but FileChannel is not selectable, that's stupid! // so switch to synchronous I/O to avoid polling builder.setBlocking(true); diff --git a/app/src/main/java/com/genymobile/gnirehtet/VpnConfiguration.java b/app/src/main/java/com/genymobile/gnirehtet/VpnConfiguration.java index 9027a18..0881a4d 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/VpnConfiguration.java +++ b/app/src/main/java/com/genymobile/gnirehtet/VpnConfiguration.java @@ -26,15 +26,17 @@ public class VpnConfiguration implements Parcelable { private final InetAddress[] dnsServers; private final CIDR[] routes; + private String[] whitelistBundleIds = new String[0]; public VpnConfiguration() { this.dnsServers = new InetAddress[0]; this.routes = new CIDR[0]; } - public VpnConfiguration(InetAddress[] dnsServers, CIDR[] routes) { + public VpnConfiguration(InetAddress[] dnsServers, CIDR[] routes, String[] whitelistBundleIds) { this.dnsServers = dnsServers; this.routes = routes; + this.whitelistBundleIds = whitelistBundleIds; } private VpnConfiguration(Parcel source) { @@ -48,6 +50,7 @@ private VpnConfiguration(Parcel source) { throw new AssertionError("Invalid address", e); } routes = source.createTypedArray(CIDR.CREATOR); + whitelistBundleIds = source.createStringArray(); } public InetAddress[] getDnsServers() { @@ -58,6 +61,10 @@ public CIDR[] getRoutes() { return routes; } + public String[] getWhitelistBundleIds() { + return this.whitelistBundleIds; + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(dnsServers.length); @@ -65,6 +72,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByteArray(addr.getAddress()); } dest.writeTypedArray(routes, 0); + dest.writeStringArray(whitelistBundleIds); } @Override diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java b/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java index 6413d0c..1234237 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java @@ -27,6 +27,7 @@ public class CommandLineArguments { public static final int PARAM_DNS_SERVER = 1 << 1; public static final int PARAM_ROUTES = 1 << 2; public static final int PARAM_PORT = 1 << 3; + public static final int PARAM_WHITELIST_BUNDLE_IDS = 1 << 4; public static final int DEFAULT_PORT = 31416; @@ -34,6 +35,7 @@ public class CommandLineArguments { private String serial; private String dnsServers; private String routes; + private String whitelistBundleIds; public static CommandLineArguments parse(int acceptedParameters, String... args) { CommandLineArguments arguments = new CommandLineArguments(); @@ -69,6 +71,15 @@ public static CommandLineArguments parse(int acceptedParameters, String... args) throw new IllegalArgumentException("Invalid port: " + arguments.port); } ++i; + } else if ((acceptedParameters & PARAM_WHITELIST_BUNDLE_IDS) != 0 && "-b".equals(arg)) { + if (arguments.whitelistBundleIds != null) { + throw new IllegalArgumentException("Whitelist bundle ids already set"); + } + if (i == args.length - 1) { + throw new IllegalArgumentException("Missing -b parameter"); + } + arguments.whitelistBundleIds = args[i + 1]; + ++i; } else if ((acceptedParameters & PARAM_SERIAL) != 0 && arguments.serial == null) { arguments.serial = arg; } else { @@ -96,4 +107,8 @@ public String getRoutes() { public int getPort() { return port; } + + public String getWhitelistBundleIds() { + return whitelistBundleIds; + } } diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java b/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java index 03b6efc..cc3faa8 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java @@ -87,7 +87,7 @@ void execute(CommandLineArguments args) throws Exception { } }, RUN("run", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES - | CommandLineArguments.PARAM_PORT) { + | CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_WHITELIST_BUNDLE_IDS ) { @Override String getDescription() { return "Enable reverse tethering for exactly one device:\n" @@ -99,10 +99,10 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdRun(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort()); + cmdRun(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort(), args.getWhitelistBundleIds()); } }, - AUTORUN("autorun", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT) { + AUTORUN("autorun", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_WHITELIST_BUNDLE_IDS) { @Override String getDescription() { return "Enable reverse tethering for all devices:\n" @@ -112,11 +112,11 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdAutorun(args.getDnsServers(), args.getRoutes(), args.getPort()); + cmdAutorun(args.getDnsServers(), args.getRoutes(), args.getPort(), args.getWhitelistBundleIds()); } }, START("start", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES - | CommandLineArguments.PARAM_PORT) { + | CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_WHITELIST_BUNDLE_IDS) { @Override String getDescription() { return "Start a client on the Android device and exit.\n" @@ -126,6 +126,7 @@ String getDescription() { + "DNS server(s). Otherwise, use 8.8.8.8 (Google public DNS).\n" + "If -r is given, then only reverse tether the specified routes.\n" + "If -p is given, then make the relay server listen on the specified\n" + + "If -b is given, then reverse tethering will be enabled only for specified application's bundle ids\n" + "port. Otherwise, use port 31416.\n" + "Otherwise, use 0.0.0.0/0 (redirect the whole traffic).\n" + "If the client is already started, then do nothing, and ignore\n" @@ -135,10 +136,10 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdStart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort()); + cmdStart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort(), args.getWhitelistBundleIds()); } }, - AUTOSTART("autostart", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT) { + AUTOSTART("autostart", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_WHITELIST_BUNDLE_IDS) { @Override String getDescription() { return "Listen for device connexions and start a client on every detected\n" @@ -149,7 +150,7 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdAutostart(args.getDnsServers(), args.getRoutes(), args.getPort()); + cmdAutostart(args.getDnsServers(), args.getRoutes(), args.getPort(), args.getWhitelistBundleIds()); } }, STOP("stop", CommandLineArguments.PARAM_SERIAL) { @@ -166,7 +167,7 @@ void execute(CommandLineArguments args) throws Exception { } }, RESTART("restart", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES - | CommandLineArguments.PARAM_PORT) { + | CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_WHITELIST_BUNDLE_IDS) { @Override String getDescription() { return "Stop then start."; @@ -174,7 +175,7 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdRestart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort()); + cmdRestart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort(), args.getWhitelistBundleIds()); } }, TUNNEL("tunnel", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_PORT) { @@ -231,9 +232,9 @@ private static void cmdReinstall(String serial) throws InterruptedException, IOE cmdInstall(serial); } - private static void cmdRun(String serial, String dnsServers, String routes, int port) throws IOException { + private static void cmdRun(String serial, String dnsServers, String routes, int port, String whitelistBundleIds) throws IOException { // start in parallel so that the relay server is ready when the client connects - asyncStart(serial, dnsServers, routes, port); + asyncStart(serial, dnsServers, routes, port, whitelistBundleIds); Runtime.getRuntime().addShutdownHook(new Thread(() -> { // executed on Ctrl+C @@ -247,10 +248,10 @@ private static void cmdRun(String serial, String dnsServers, String routes, int cmdRelay(port); } - private static void cmdAutorun(final String dnsServers, final String routes, int port) throws IOException { + private static void cmdAutorun(final String dnsServers, final String routes, int port, final String whitelistBundleIds) throws IOException { new Thread(() -> { try { - cmdAutostart(dnsServers, routes, port); + cmdAutostart(dnsServers, routes, port, whitelistBundleIds); } catch (Exception e) { Log.e(TAG, "Cannot auto start clients", e); } @@ -260,7 +261,7 @@ private static void cmdAutorun(final String dnsServers, final String routes, int } @SuppressWarnings("checkstyle:MagicNumber") - private static void cmdStart(String serial, String dnsServers, String routes, int port) throws InterruptedException, IOException, + private static void cmdStart(String serial, String dnsServers, String routes, int port, String whitelistBundleIds) throws InterruptedException, IOException, CommandExecutionException { if (mustInstallClient(serial)) { cmdInstall(serial); @@ -280,12 +281,15 @@ private static void cmdStart(String serial, String dnsServers, String routes, in if (routes != null) { Collections.addAll(cmd, "--esa", "routes", routes); } + if (whitelistBundleIds != null) { + Collections.addAll(cmd, "--esa", "whitelistBundleIds", whitelistBundleIds); + } execAdb(serial, cmd); } - private static void cmdAutostart(final String dnsServers, final String routes, int port) { + private static void cmdAutostart(final String dnsServers, final String routes, int port, final String whitelistBundleIds) { AdbMonitor adbMonitor = new AdbMonitor((serial) -> { - asyncStart(serial, dnsServers, routes, port); + asyncStart(serial, dnsServers, routes, port, whitelistBundleIds); }); adbMonitor.monitor(); } @@ -296,10 +300,10 @@ private static void cmdStop(String serial) throws InterruptedException, IOExcept "com.genymobile.gnirehtet/.GnirehtetActivity"); } - private static void cmdRestart(String serial, String dnsServers, String routes, int port) throws InterruptedException, IOException, + private static void cmdRestart(String serial, String dnsServers, String routes, int port, String whitelistBundleIds) throws InterruptedException, IOException, CommandExecutionException { cmdStop(serial); - cmdStart(serial, dnsServers, routes, port); + cmdStart(serial, dnsServers, routes, port, whitelistBundleIds); } private static void cmdTunnel(String serial, int port) throws InterruptedException, IOException, CommandExecutionException { @@ -311,10 +315,10 @@ private static void cmdRelay(int port) throws IOException { new Relay(port).run(); } - private static void asyncStart(String serial, String dnsServers, String routes, int port) { + private static void asyncStart(String serial, String dnsServers, String routes, int port, String whitelistBundleIds) { new Thread(() -> { try { - cmdStart(serial, dnsServers, routes, port); + cmdStart(serial, dnsServers, routes, port, whitelistBundleIds); } catch (Exception e) { Log.e(TAG, "Cannot start client", e); } @@ -408,6 +412,9 @@ private static void appendCommandUsage(StringBuilder builder, Command command) { if ((command.acceptedParameters & CommandLineArguments.PARAM_ROUTES) != 0) { builder.append(" [-r ROUTE[,ROUTE2,...]]"); } + if ((command.acceptedParameters & CommandLineArguments.PARAM_WHITELIST_BUNDLE_IDS) != 0) { + builder.append(" [-b BUNDLE_ID[,BUNDLE_ID2,...]]"); + } builder.append(NL); String[] descLines = command.getDescription().split("\n"); for (String descLine : descLines) { diff --git a/relay-rust/src/cli_args.rs b/relay-rust/src/cli_args.rs index 438427f..44ad2ca 100644 --- a/relay-rust/src/cli_args.rs +++ b/relay-rust/src/cli_args.rs @@ -19,6 +19,7 @@ pub const PARAM_SERIAL: u8 = 1; pub const PARAM_DNS_SERVERS: u8 = 1 << 1; pub const PARAM_ROUTES: u8 = 1 << 2; pub const PARAM_PORT: u8 = 1 << 3; +pub const PARAM_WHITELIST_BUNDLE_IDS: u8 = 1 << 4; pub const DEFAULT_PORT: u16 = 31416; @@ -27,6 +28,7 @@ pub struct CommandLineArguments { dns_servers: Option, routes: Option, port: u16, + whitelist_bundle_ids: Option, } impl CommandLineArguments { @@ -36,6 +38,7 @@ impl CommandLineArguments { let mut dns_servers = None; let mut routes = None; let mut port = 0; + let mut whitelist_bundle_ids = None; let mut iter = args.into_iter(); while let Some(arg) = iter.next() { @@ -70,6 +73,15 @@ impl CommandLineArguments { } else { return Err(String::from("Missing -p parameter")); } + } else if (accepted_parameters & PARAM_WHITELIST_BUNDLE_IDS) != 0 && "-b" == arg { + if whitelist_bundle_ids.is_some() { + return Err(String::from("Bundle id already set")); + } + if let Some(value) = iter.next() { + whitelist_bundle_ids = Some(value.into()); + } else { + return Err(String::from("Missing -b parameter")); + } } else if (accepted_parameters & PARAM_SERIAL) != 0 && serial.is_none() { serial = Some(arg); } else { @@ -84,6 +96,7 @@ impl CommandLineArguments { dns_servers, routes, port, + whitelist_bundle_ids }) } @@ -102,19 +115,24 @@ impl CommandLineArguments { pub fn port(&self) -> u16 { self.port } + + pub fn whitelist_bundle_ids(&self) -> Option<&str> { + self.whitelist_bundle_ids.as_deref() + } } #[cfg(test)] mod tests { use super::*; - const ACCEPT_ALL: u8 = PARAM_SERIAL | PARAM_DNS_SERVERS | PARAM_ROUTES; + const ACCEPT_ALL: u8 = PARAM_SERIAL | PARAM_DNS_SERVERS | PARAM_ROUTES | PARAM_WHITELIST_BUNDLE_IDS; #[test] fn test_no_args() { let args = CommandLineArguments::parse(ACCEPT_ALL, Vec::<&str>::new()).unwrap(); assert!(args.serial.is_none()); assert!(args.dns_servers.is_none()); + assert!(args.whitelist_bundle_ids.is_none()); } #[test] @@ -178,4 +196,17 @@ mod tests { let raw_args = vec!["-r"]; assert!(CommandLineArguments::parse(ACCEPT_ALL, raw_args).is_err()); } + + #[test] + fn test_bundle_id_parameter() { + let raw_args = vec!["-b", "com.myapp.xyz"]; + let args = CommandLineArguments::parse(ACCEPT_ALL, raw_args).unwrap(); + assert_eq!("com.myapp.xyz", args.whitelist_bundle_ids.unwrap()); + } + + #[test] + fn test_no_bundle_id_parameter() { + let raw_args = vec!["-b"]; + assert!(CommandLineArguments::parse(ACCEPT_ALL, raw_args).is_err()); + } } diff --git a/relay-rust/src/main.rs b/relay-rust/src/main.rs index cb80e9c..896d66d 100644 --- a/relay-rust/src/main.rs +++ b/relay-rust/src/main.rs @@ -155,6 +155,7 @@ impl Command for RunCommand { | cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT + | cli_args::PARAM_WHITELIST_BUNDLE_IDS } fn description(&self) -> &'static str { @@ -171,6 +172,7 @@ impl Command for RunCommand { args.dns_servers(), args.routes(), args.port(), + args.whitelist_bundle_ids(), ) } } @@ -181,7 +183,7 @@ impl Command for AutorunCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT + cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT | cli_args::PARAM_WHITELIST_BUNDLE_IDS } fn description(&self) -> &'static str { @@ -191,7 +193,7 @@ impl Command for AutorunCommand { } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_autorun(args.dns_servers(), args.routes(), args.port()) + cmd_autorun(args.dns_servers(), args.routes(), args.port(), args.whitelist_bundle_ids()) } } @@ -205,6 +207,7 @@ impl Command for StartCommand { | cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT + | cli_args::PARAM_WHITELIST_BUNDLE_IDS } fn description(&self) -> &'static str { @@ -217,6 +220,7 @@ impl Command for StartCommand { Otherwise, use 0.0.0.0/0 (redirect the whole traffic).\n\ If -p is given, then make the relay server listen on the specified\n\ port. Otherwise, use port 31416.\n\ + If -b is given, then reverse tethering will be enabled only for specified application's bundle ids\n\ If the client is already started, then do nothing, and ignore\n\ the other parameters.\n\ 10.0.2.2 is mapped to the host 'localhost'." @@ -228,6 +232,7 @@ impl Command for StartCommand { args.dns_servers(), args.routes(), args.port(), + args.whitelist_bundle_ids(), ) } } @@ -238,7 +243,7 @@ impl Command for AutostartCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT + cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT | cli_args::PARAM_WHITELIST_BUNDLE_IDS } fn description(&self) -> &'static str { @@ -249,7 +254,7 @@ impl Command for AutostartCommand { } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_autostart(args.dns_servers(), args.routes(), args.port()) + cmd_autostart(args.dns_servers(), args.routes(), args.port(), args.whitelist_bundle_ids()) } } @@ -283,6 +288,7 @@ impl Command for RestartCommand { | cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT + | cli_args::PARAM_WHITELIST_BUNDLE_IDS } fn description(&self) -> &'static str { @@ -296,6 +302,7 @@ impl Command for RestartCommand { args.dns_servers(), args.routes(), args.port(), + args.whitelist_bundle_ids(), )?; Ok(()) } @@ -362,9 +369,10 @@ fn cmd_run( dns_servers: Option<&str>, routes: Option<&str>, port: u16, + whitelist_bundle_ids: Option<&str>, ) -> Result<(), CommandExecutionError> { // start in parallel so that the relay server is ready when the client connects - async_start(serial, dns_servers, routes, port); + async_start(serial, dns_servers, routes, port, whitelist_bundle_ids); let ctrlc_serial = serial.map(String::from); ctrlc::set_handler(move || { @@ -386,14 +394,17 @@ fn cmd_autorun( dns_servers: Option<&str>, routes: Option<&str>, port: u16, + whitelist_bundle_ids: Option<&str>, ) -> Result<(), CommandExecutionError> { { let autostart_dns_servers = dns_servers.map(String::from); let autostart_routes = routes.map(String::from); + let autostart_whitelist_bundle_ids = whitelist_bundle_ids.map(String::from); thread::spawn(move || { let dns_servers = autostart_dns_servers.as_ref().map(String::as_ref); let routes = autostart_routes.as_ref().map(String::as_ref); - if let Err(err) = cmd_autostart(dns_servers, routes, port) { + let whitelist_bundle_ids = autostart_whitelist_bundle_ids.as_ref().map(String::as_ref); + if let Err(err) = cmd_autostart(dns_servers, routes, port, whitelist_bundle_ids) { error!(target: TAG, "Cannot auto start clients: {}", err); } }); @@ -407,6 +418,7 @@ fn cmd_start( dns_servers: Option<&str>, routes: Option<&str>, port: u16, + whitelist_bundle_ids: Option<&str>, ) -> Result<(), CommandExecutionError> { if must_install_client(serial)? { cmd_install(serial)?; @@ -433,6 +445,9 @@ fn cmd_start( if let Some(routes) = routes { adb_args.append(&mut vec!["--esa", "routes", routes]); } + if let Some(whitelist_bundle_ids) = whitelist_bundle_ids { + adb_args.append(&mut vec!["--esa", "whitelistBundleIds", whitelist_bundle_ids]); + } exec_adb(serial, adb_args) } @@ -440,13 +455,16 @@ fn cmd_autostart( dns_servers: Option<&str>, routes: Option<&str>, port: u16, + whitelist_bundle_ids: Option<&str>, ) -> Result<(), CommandExecutionError> { let start_dns_servers = dns_servers.map(String::from); let start_routes = routes.map(String::from); + let start_whitelist_bundle_ids = whitelist_bundle_ids.map(String::from); let mut adb_monitor = AdbMonitor::new(Box::new(move |serial: &str| { let dns_servers = start_dns_servers.as_ref().map(String::as_ref); let routes = start_routes.as_ref().map(String::as_ref); - async_start(Some(serial), dns_servers, routes, port) + let whitelist_bundle_ids = start_whitelist_bundle_ids.as_ref().map(String::as_ref); + async_start(Some(serial), dns_servers, routes, port, whitelist_bundle_ids) })); adb_monitor.monitor(); Ok(()) @@ -485,15 +503,24 @@ fn cmd_relay(port: u16) -> Result<(), CommandExecutionError> { Ok(()) } -fn async_start(serial: Option<&str>, dns_servers: Option<&str>, routes: Option<&str>, port: u16) { +fn async_start( + serial: Option<&str>, + dns_servers: Option<&str>, + routes: Option<&str>, + port: u16, + whitelist_bundle_ids: Option<&str> +) { let start_serial = serial.map(String::from); let start_dns_servers = dns_servers.map(String::from); let start_routes = routes.map(String::from); + let start_whitelist_bundle_ids = whitelist_bundle_ids.map(String::from); + thread::spawn(move || { let serial = start_serial.as_ref().map(String::as_ref); let dns_servers = start_dns_servers.as_ref().map(String::as_ref); let routes = start_routes.as_ref().map(String::as_ref); - if let Err(err) = cmd_start(serial, dns_servers, routes, port) { + let whitelist_bundle_ids = start_whitelist_bundle_ids.as_ref().map(String::as_ref); + if let Err(err) = cmd_start(serial, dns_servers, routes, port, whitelist_bundle_ids) { error!(target: TAG, "Cannot start client: {}", err); } }); @@ -605,6 +632,9 @@ fn append_command_usage(msg: &mut String, command: &dyn Command) { if (accepted_parameters & cli_args::PARAM_ROUTES) != 0 { msg.push_str(" [-r ROUTE[,ROUTE2,...]]"); } + if (accepted_parameters & cli_args::PARAM_WHITELIST_BUNDLE_IDS) != 0 { + msg.push_str(" [-b BUNDLE_ID[,BUNDLE_ID2,...]]") + } msg.push('\n'); for desc_line in command.description().split('\n') { msg.push_str(" ");