summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2022-10-18 22:21:03 +0100
committerDavid Lönnhager <david.l@mullvad.net>2023-06-05 19:31:49 +0200
commit7747639ffa0a1f8d4ee685e88240ca3dff8a9a66 (patch)
treeb99853791db2fff37c358b8a0a48c325b6e99dbb /talpid-core/src
parent2adf93174484af166c2104627530874698498b7d (diff)
downloadmullvadvpn-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.rs82
-rw-r--r--talpid-core/src/routing/scutil.rs43
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(&notify_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![])
+}