summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-11-23 16:06:16 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-11-24 12:29:47 +0100
commitd22ff8ee3af9b3cc532a39e0b3965b9aca7dca19 (patch)
tree91975b196cd8e241376b67b9812fb47f73f1c6f4
parent720b7031b3c1eade961d81391f50753f74fa65cb (diff)
downloadmullvadvpn-d22ff8ee3af9b3cc532a39e0b3965b9aca7dca19.tar.xz
mullvadvpn-d22ff8ee3af9b3cc532a39e0b3965b9aca7dca19.zip
Remove default route tracking on Linux
-rw-r--r--talpid-core/src/routing/linux.rs217
-rw-r--r--talpid-core/src/routing/mod.rs1
2 files changed, 2 insertions, 216 deletions
diff --git a/talpid-core/src/routing/linux.rs b/talpid-core/src/routing/linux.rs
index 7329e4b70e..4c13bbc76d 100644
--- a/talpid-core/src/routing/linux.rs
+++ b/talpid-core/src/routing/linux.rs
@@ -29,7 +29,7 @@ use netlink_packet_route::{
use rtnetlink::{
constants::{RTMGRP_IPV4_ROUTE, RTMGRP_IPV6_ROUTE, RTMGRP_LINK, RTMGRP_NOTIFY},
sys::SocketAddr,
- Handle, IpVersion,
+ Handle,
};
use libc::{AF_INET, AF_INET6};
@@ -141,12 +141,6 @@ pub enum Error {
}
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
-struct RequiredDefaultRoute {
- table_id: u32,
- destination: IpNetwork,
-}
-
pub struct RouteManagerImpl {
handle: Handle,
messages: UnboundedReceiver<(NetlinkMessage<RtnlMessage>, SocketAddr)>,
@@ -154,12 +148,6 @@ pub struct RouteManagerImpl {
// currently added routes
added_routes: HashSet<Route>,
- // default route tracking
- // destinations that should be routed through the default route
- required_default_routes: HashSet<RequiredDefaultRoute>,
- default_routes: HashSet<Route>,
- best_default_node_v4: Option<Node>,
- best_default_node_v6: Option<Node>,
}
impl RouteManagerImpl {
@@ -182,23 +170,10 @@ impl RouteManagerImpl {
iface_map,
handle,
messages,
-
- required_default_routes: HashSet::new(),
added_routes: HashSet::new(),
-
- default_routes: HashSet::new(),
- best_default_node_v4: None,
- best_default_node_v6: None,
};
monitor.clear_routing_rules().await?;
-
- monitor.default_routes = monitor.get_default_routes().await?;
- monitor.best_default_node_v4 =
- Self::pick_best_default_node(&monitor.default_routes, IpVersion::V4);
- monitor.best_default_node_v6 =
- Self::pick_best_default_node(&monitor.default_routes, IpVersion::V6);
-
monitor.add_required_routes(required_routes).await?;
Ok(monitor)
@@ -306,29 +281,8 @@ impl RouteManagerImpl {
Ok(())
}
- async fn add_required_default_routes(
- &mut self,
- required_default_routes: HashSet<RequiredDefaultRoute>,
- ) -> Result<()> {
- for route in required_default_routes.into_iter() {
- if let (false, _, Some(default_node)) | (true, Some(default_node), _) = (
- route.destination.is_ipv4(),
- &self.best_default_node_v4,
- &self.best_default_node_v6,
- ) {
- // best to pick a single node identifier rather than device + ip
- let new_route =
- Route::new(default_node.clone(), route.destination).table(route.table_id);
- self.add_route(new_route).await?;
- }
- self.required_default_routes.insert(route);
- }
- Ok(())
- }
-
async fn add_required_routes(&mut self, required_routes: HashSet<RequiredRoute>) -> Result<()> {
let mut required_normal_routes = HashSet::new();
- let mut required_default_routes = HashSet::new();
for route in required_routes {
match route.node {
@@ -336,12 +290,6 @@ impl RouteManagerImpl {
required_normal_routes
.insert(Route::new(node, route.prefix).table(route.table_id));
}
- NetNode::DefaultNode => {
- required_default_routes.insert(RequiredDefaultRoute {
- table_id: route.table_id,
- destination: route.prefix,
- });
- }
}
}
@@ -349,49 +297,9 @@ impl RouteManagerImpl {
self.add_route(normal_route).await?;
}
- if self
- .add_required_default_routes(required_default_routes.clone())
- .await
- .is_err()
- {
- log::trace!("Refreshing default routes which may be stale");
-
- self.default_routes = self.get_default_routes().await?;
- self.best_default_node_v4 =
- Self::pick_best_default_node(&self.default_routes, IpVersion::V4);
- self.best_default_node_v6 =
- Self::pick_best_default_node(&self.default_routes, IpVersion::V6);
-
- self.add_required_default_routes(required_default_routes)
- .await?;
- }
-
Ok(())
}
- async fn get_default_routes(&self) -> Result<HashSet<Route>> {
- let mut routes = self.get_default_routes_inner(IpVersion::V4).await?;
- routes.extend(self.get_default_routes_inner(IpVersion::V6).await?);
- Ok(routes)
- }
-
- async fn get_default_routes_inner(&self, version: IpVersion) -> Result<HashSet<Route>> {
- let mut routes = HashSet::new();
- let mut route_request = self.handle.route().get(version).execute();
- while let Some(route) = route_request
- .try_next()
- .await
- .map_err(Error::NetlinkError)?
- {
- if route.header.destination_prefix_length == 0 {
- if let Some(default_route) = self.parse_route_message(route)? {
- routes.insert(default_route);
- }
- }
- }
- Ok(routes)
- }
-
async fn initialize_link_map(
handle: &rtnetlink::Handle,
) -> Result<BTreeMap<u32, NetworkInterface>> {
@@ -414,129 +322,12 @@ impl RouteManagerImpl {
.map(|(idx, _name)| *idx)
}
-
- async fn process_new_route(&mut self, route: Route) -> Result<()> {
- if route.prefix.prefix() == 0 {
- self.default_routes.insert(route);
- self.update_default_routes().await?;
- }
- Ok(())
- }
-
async fn process_deleted_route(&mut self, route: Route) -> Result<()> {
- if route.prefix.prefix() == 0 {
- self.default_routes.remove(&route);
- self.update_default_routes().await?;
- }
self.added_routes.remove(&route);
Ok(())
}
- async fn update_default_routes(&mut self) -> Result<()> {
- let new_best_v4 = Self::pick_best_default_node(&self.default_routes, IpVersion::V4);
- if self.best_default_node_v4 != new_best_v4 && new_best_v4.is_some() {
- let new_node = new_best_v4.unwrap();
- let old_node = self.best_default_node_v4.take();
- let v4_routes: Vec<_> = self
- .required_default_routes
- .iter()
- .filter(|ip| ip.destination.is_ipv4())
- .cloned()
- .collect();
- for route in v4_routes {
- let new_route =
- Route::new(new_node.clone(), route.destination).table(route.table_id);
-
- if let Some(old_node) = &old_node {
- let old_route =
- Route::new(old_node.clone(), route.destination).table(route.table_id);
-
- if let Err(e) = self.delete_route(&old_route).await {
- log::error!("Failed to remove old route {} - {}", &old_route, e);
- }
- }
- if let Err(e) = self.add_route(new_route).await {
- log::error!("Failed to add new route {} - {}", &new_node, e);
- }
- }
- self.best_default_node_v4 = Some(new_node);
- }
-
- let new_best_v6 = Self::pick_best_default_node(&self.default_routes, IpVersion::V6);
- if self.best_default_node_v6 != new_best_v6 && new_best_v6.is_some() {
- let new_node = new_best_v6.unwrap();
- let old_node = self.best_default_node_v6.take();
- let v6_routes: Vec<_> = self
- .required_default_routes
- .iter()
- .filter(|ip| !ip.destination.is_ipv4())
- .cloned()
- .collect();
-
- for route in v6_routes {
- let new_route =
- Route::new(new_node.clone(), route.destination).table(route.table_id);
-
- if let Some(old_node) = &old_node {
- let old_route =
- Route::new(old_node.clone(), route.destination).table(route.table_id);
-
- if let Err(e) = self.delete_route(&old_route).await {
- log::error!("Failed to remove old route {} - {}", &old_route, e);
- }
- }
- if let Err(e) = self.add_route(new_route).await {
- log::error!("Failed to add new route {} - {}", &new_node, e);
- }
- }
- self.best_default_node_v6 = Some(new_node);
- }
-
- Ok(())
- }
-
- fn pick_best_default_node(routes: &HashSet<Route>, version: IpVersion) -> Option<Node> {
- // Pick the route with the lowest metric - thus the most favourable route.
- routes
- .iter()
- .filter(|route| route.prefix.is_ipv4() == (version == IpVersion::V4))
- .fold(
- None,
- |best_route: Option<Route>, next_route| match best_route {
- Some(current_best) => {
- if current_best.metric.unwrap_or(0) > next_route.metric.unwrap_or(0) {
- Some(next_route.clone())
- } else {
- Some(current_best)
- }
- }
- None => Some(next_route.clone()),
- },
- )
- .map(|route| route.node)
- }
-
async fn cleanup_routes(&mut self) {
- for required_route in &self.required_default_routes {
- let best_node = if required_route.destination.is_ipv4() {
- self.best_default_node_v4.clone()
- } else {
- self.best_default_node_v6.clone()
- };
-
- let best_node = match best_node {
- None => continue,
- Some(node) => node,
- };
-
- let route =
- Route::new(best_node, required_route.destination).table(required_route.table_id);
- if let Err(e) = self.delete_route_if_exists(&route).await {
- log::error!("Failed to remove route - {} - {}", route, e);
- }
- }
- self.required_default_routes.clear();
-
for route in self.added_routes.drain().collect::<Vec<_>>().iter() {
if let Err(e) = self.delete_route_if_exists(&route).await {
log::error!("Failed to remove route - {} - {}", route, e);
@@ -603,12 +394,6 @@ impl RouteManagerImpl {
self.iface_map.remove(&idx);
}
}
-
- NetlinkPayload::InnerMessage(RtnlMessage::NewRoute(new_route)) => {
- if let Some(new_route) = self.parse_route_message(new_route)? {
- self.process_new_route(new_route).await?;
- }
- }
NetlinkPayload::InnerMessage(RtnlMessage::DelRoute(old_route)) => {
if let Some(deletion) = self.parse_route_message(old_route)? {
self.process_deleted_route(deletion).await?;
diff --git a/talpid-core/src/routing/mod.rs b/talpid-core/src/routing/mod.rs
index e8b43a5d2d..d1508f7c5f 100644
--- a/talpid-core/src/routing/mod.rs
+++ b/talpid-core/src/routing/mod.rs
@@ -98,6 +98,7 @@ pub enum NetNode {
RealNode(Node),
/// A default node is a symbolic node that will resolve to the network node used in the current
/// most preferable default route
+ #[cfg(not(target_os = "linux"))]
DefaultNode,
}