diff options
| author | Emīls <emils@mullvad.net> | 2022-10-18 22:21:03 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2023-06-05 19:31:49 +0200 |
| commit | 7747639ffa0a1f8d4ee685e88240ca3dff8a9a66 (patch) | |
| tree | b99853791db2fff37c358b8a0a48c325b6e99dbb /talpid-core/src | |
| parent | 2adf93174484af166c2104627530874698498b7d (diff) | |
| download | mullvadvpn-7747639ffa0a1f8d4ee685e88240ca3dff8a9a66.tar.xz mullvadvpn-7747639ffa0a1f8d4ee685e88240ca3dff8a9a66.zip | |
Attempt to setup routes the other way
Diffstat (limited to 'talpid-core/src')
| -rw-r--r-- | talpid-core/src/offline/macos.rs | 82 | ||||
| -rw-r--r-- | talpid-core/src/routing/scutil.rs | 43 |
2 files changed, 96 insertions, 29 deletions
diff --git a/talpid-core/src/offline/macos.rs b/talpid-core/src/offline/macos.rs index baae3c40f1..b14071839c 100644 --- a/talpid-core/src/offline/macos.rs +++ b/talpid-core/src/offline/macos.rs @@ -21,7 +21,7 @@ //! [`SCNetworkReachability`]: https://developer.apple.com/documentation/systemconfiguration/scnetworkreachability-g7d //! [`NWPathMonitor`]: https://developer.apple.com/documentation/network/nwpathmonitor use futures::{channel::mpsc::UnboundedSender, Future, StreamExt}; -use std::sync::{Arc, Weak}; +use std::sync::{Arc, Mutex, Weak}; use talpid_types::ErrorExt; #[derive(err_derive::Error, Debug)] @@ -31,6 +31,7 @@ pub enum Error { } pub struct MonitorHandle { + excluded_interface: Arc<Mutex<Option<String>>>, _notify_tx: Arc<UnboundedSender<bool>>, } @@ -38,58 +39,81 @@ impl MonitorHandle { /// Host is considered to be offline if the IPv4 internet is considered to be unreachable by the /// given reachability flags *or* there are no active physical interfaces. pub async fn host_is_offline(&self) -> bool { - !exists_non_tunnel_default_route().await + let excluded_interface: Option<String> = self + .excluded_interface + .lock() + .expect("excluded_interface lock poisoned") + .clone(); + !exists_non_tunnel_default_route(excluded_interface).await } -} -async fn exists_non_tunnel_default_route() -> bool { - match talpid_routing::get_default_routes().await { - Ok((Some(node), _)) | Ok((None, Some(node))) => { - let route_exists = node - .get_device() - .map(|iface_name| !iface_name.contains("tun")) - .unwrap_or(true); - log::debug!("Assuming non-tunnel default route exists due to {:?}", node); - route_exists - } - Ok((None, None)) => { - log::debug!("No default routes exist, assuming machine is offline"); - false - } - Err(err) => { - log::error!( - "{}", - err.display_chain_with_msg( - "Failed to obtain default routes, assuming machine is online." - ) - ); - true - } + /// Sets excluded interface - excluded interfaces will be assuemd to not provide any + /// connectivity. + pub fn set_excluded_interface(&self, excluded_interface: Option<String>) { + *self + .excluded_interface + .lock() + .expect("excluded interface lock poisoned") = excluded_interface; } } + +async fn exists_non_tunnel_default_route(excluded_interface: Option<String>) -> bool { + true + // match talpid_routing::get_default_routes(excluded_interface).await { + // Ok((Some(node), _)) | Ok((None, Some(node))) => { + // let route_exists = node + // .get_device() + // .map(|iface_name| !iface_name.contains("tun")) + // .unwrap_or(true); + // log::debug!("Assuming non-tunnel default route exists due to {:?}", node); + // route_exists + // } + // Ok((None, None)) => { + // log::debug!("No default routes exist, assuming machine is offline"); + // false + // } + // Err(err) => { + // log::error!( + // "{}", + // err.display_chain_with_msg( + // "Failed to obtain default routes, assuming machine is online." + // ) + // ); + // true + // } + // } +} pub async fn spawn_monitor(notify_tx: UnboundedSender<bool>) -> Result<MonitorHandle, Error> { let notify_tx = Arc::new(notify_tx); + let excluded_interface = Arc::new(Mutex::new(None)); let context = OfflineStateContext { sender: Arc::downgrade(¬ify_tx), - is_offline: !exists_non_tunnel_default_route().await, + is_offline: !exists_non_tunnel_default_route(None).await, }; - let route_monitor = watch_route_monitor(context)?; + let route_monitor = watch_route_monitor(context, excluded_interface.clone())?; tokio::spawn(route_monitor); Ok(MonitorHandle { + excluded_interface, _notify_tx: notify_tx, }) } fn watch_route_monitor( mut context: OfflineStateContext, + excluded_interface: Arc<Mutex<Option<String>>>, ) -> Result<impl Future<Output = ()>, Error> { let mut monitor = talpid_routing::listen_for_default_route_changes()?; Ok(async move { while let Some(_route_change) = monitor.next().await { - context.new_state(!exists_non_tunnel_default_route().await); + let interface = excluded_interface + .lock() + .expect("excluded_interface lock poisoned") + .clone(); + + context.new_state(!exists_non_tunnel_default_route(interface).await); if context.should_shut_down() { break; } diff --git a/talpid-core/src/routing/scutil.rs b/talpid-core/src/routing/scutil.rs new file mode 100644 index 0000000000..fa5f5dff6a --- /dev/null +++ b/talpid-core/src/routing/scutil.rs @@ -0,0 +1,43 @@ +use std::collections::HashMap; + +use tokio::process::Command; + +use super::{Error, Result}; + +fn get_default_interface() -> () { + () +} + +/// Expected to produce output like: +/// Network information +/// IPv4 network interface information +/// utun3 : flags : 0x5 (IPv4,DNS) +/// address : 10.113.48.185 +/// VPN server : 127.0.0.1 +/// reach : 0x00000003 (Reachable,Transient Connection) +/// en0 : flags : 0x5 (IPv4,DNS) +/// address : 192.168.102.106 +/// reach : 0x00000002 (Reachable) +/// +/// REACH : flags 0x00000003 (Reachable,Transient Connection) +/// +/// IPv6 network interface information +/// No IPv6 states found +/// +/// +/// REACH : flags 0x00000007 (Reachable,Transient Connection,Connection Required) +/// +/// Network interfaces: utun3 en0 + +/// +async fn obtain_output() -> Result<Vec<u8>> { + let mut cmd = Command::new("scutil"); + cmd.arg("--nwi"); + + Ok(cmd.output().await.map_err(|_| Error::ScUtilCommand)?.stdout) +} + +fn parse_scutil_output(output: &[u8]) -> Result<Vec<HashMap<&str, &[u8]>>> { + for line in output.split(|c| *c == b'\n') {} + Ok(vec![]) +} |
