diff --git a/talpid-routing/Cargo.toml b/talpid-routing/Cargo.toml index 3ebf8682a922..50bd4c1477a2 100644 --- a/talpid-routing/Cargo.toml +++ b/talpid-routing/Cargo.toml @@ -14,7 +14,7 @@ err-derive = { workspace = true } futures = "0.3.15" ipnetwork = "0.16" log = { workspace = true } -tokio = { workspace = true, features = ["process", "rt-multi-thread", "net", "io-util"] } +tokio = { workspace = true, features = ["process", "rt-multi-thread", "net", "io-util", "time"] } [target.'cfg(not(target_os="android"))'.dependencies] talpid-types = { path = "../talpid-types" } diff --git a/talpid-routing/src/unix/macos/interface.rs b/talpid-routing/src/unix/macos/interface.rs index abb674baf3ea..4f5fc5a15866 100644 --- a/talpid-routing/src/unix/macos/interface.rs +++ b/talpid-routing/src/unix/macos/interface.rs @@ -1,8 +1,6 @@ use ipnetwork::IpNetwork; -use libc::{if_indextoname, IFNAMSIZ}; -use nix::net::if_::{if_nametoindex, InterfaceFlags}; +use nix::net::if_::InterfaceFlags; use std::{ - ffi::{CStr, CString}, io, net::{IpAddr, Ipv4Addr, Ipv6Addr}, }; @@ -13,10 +11,7 @@ use system_configuration::{ preferences::SCPreferences, }; -use super::{ - data::{Destination, RouteMessage}, - watch::RoutingTable, -}; +use super::data::{Destination, RouteMessage}; #[derive(Debug, PartialEq, Clone, Copy)] pub enum Family { @@ -42,47 +37,6 @@ impl From for IpNetwork { } } -/// Retrieve the current unscoped default route. That is the only default route that does not have -/// the IF_SCOPE flag set, if such a route exists. -/// -/// # Note -/// -/// For some reason, the socket sometimes returns a route with the IF_SCOPE flag set, if there also -/// exists a scoped route for the same interface. This does not occur if there is no unscoped route, -/// so we can still rely on it. -pub async fn get_unscoped_default_route( - routing_table: &mut RoutingTable, - family: Family, -) -> Option { - let mut msg = RouteMessage::new_route(Destination::Network(IpNetwork::from(family))); - msg = msg.set_gateway_route(true); - - let route = routing_table - .get_route(&msg) - .await - .unwrap_or_else(|error| { - log::error!("Failed to retrieve unscoped default route: {error}"); - None - })?; - - let idx = u32::from(route.interface_index()); - if idx != 0 { - let mut ifname = [0u8; IFNAMSIZ]; - - // SAFETY: The buffer is large to contain any interface name. - if !unsafe { if_indextoname(idx, ifname.as_mut_ptr() as _) }.is_null() { - let ifname = CStr::from_bytes_until_nul(&ifname).unwrap(); - let name = ifname.to_str().expect("expected ascii"); - - // Ignore the unscoped route if its interface is not "active" - if !is_active_interface(name, family).unwrap_or(true) { - return None; - } - } - } - - Some(route) -} /// Retrieve the best current default route. That is the first scoped default route, ordered by /// network service order, and with interfaces filtered out if they do not have valid IP addresses /// assigned. @@ -90,10 +44,7 @@ pub async fn get_unscoped_default_route( /// # Note /// /// The tunnel interface is not even listed in the service order, so it will be skipped. -pub async fn get_best_default_route( - routing_table: &mut RoutingTable, - family: Family, -) -> Option { +pub async fn get_best_default_route(family: Family) -> Option { let mut msg = RouteMessage::new_route(Destination::Network(IpNetwork::from(family))); msg = msg.set_gateway_route(true); @@ -143,15 +94,15 @@ fn parse_v4_ipconfig_output(output: &str) -> Option { fn parse_v6_ipconfig_output(output: &str) -> Option { let mut iter = output.split_whitespace(); let pattern = ["RouterAdvertisement", ":", "from"]; - loop { + 'outer: loop { let mut next_chunk = iter.next()?; for expected_chunk in pattern { if expected_chunk != next_chunk { - continue; + continue 'outer; } next_chunk = iter.next()?; } - return iter.next()?.trim_end_matches(",").parse().ok(); + return next_chunk.trim_end_matches(",").parse().ok(); } } diff --git a/talpid-routing/src/unix/macos/mod.rs b/talpid-routing/src/unix/macos/mod.rs index 8e715d12f3dc..a38731bfc4a0 100644 --- a/talpid-routing/src/unix/macos/mod.rs +++ b/talpid-routing/src/unix/macos/mod.rs @@ -369,7 +369,7 @@ impl RouteManagerImpl { /// If there is no tunnel device, the "best route" is the unscoped default route, whatever it /// is. async fn update_best_default_route(&mut self, family: interface::Family) -> Result { - let best_route = interface::get_best_default_route(&mut self.routing_table, family).await; + let best_route = interface::get_best_default_route(family).await; log::trace!("Best route ({family:?}): {best_route:?}"); let default_route = get_current_best_default_route!(self, family); @@ -623,7 +623,7 @@ impl RouteManagerImpl { /// function returns true when no route had to be added. async fn restore_default_route(&mut self, family: interface::Family) -> bool { let Some(best_default_route) = - interface::get_best_default_route(&mut self.routing_table, family).await + interface::get_best_default_route(family).await else { let _ = self .routing_table @@ -652,7 +652,7 @@ impl RouteManagerImpl { .await; }; - let new_route = interface::get_best_default_route(&mut self.routing_table, family).await; + let new_route = interface::get_best_default_route(family).await; let old_route = std::mem::replace(current_route, new_route); let notify = &old_route != current_route;