summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJoakim Hulthe <joakim@hulthe.net>2025-04-22 17:22:50 +0200
committerJoakim Hulthe <joakim.hulthe@mullvad.net>2025-04-23 15:35:52 +0200
commite947e34ce6e83013f8d5bee86de3d59350efe447 (patch)
tree78a2c90ff1de687b8607417057fdb4f9395d1ef8
parent779cfe3790a3d43db67c33e937e2c3d2d4895b27 (diff)
downloadmullvadvpn-e947e34ce6e83013f8d5bee86de3d59350efe447.tar.xz
mullvadvpn-e947e34ce6e83013f8d5bee86de3d59350efe447.zip
Compare routes by interface_index instead of link addr
-rw-r--r--talpid-routing/src/unix/macos/mod.rs40
1 files changed, 21 insertions, 19 deletions
diff --git a/talpid-routing/src/unix/macos/mod.rs b/talpid-routing/src/unix/macos/mod.rs
index b88ad0c5f1..975ebef927 100644
--- a/talpid-routing/src/unix/macos/mod.rs
+++ b/talpid-routing/src/unix/macos/mod.rs
@@ -8,6 +8,7 @@ use futures::{
};
use ip_map::IpMap;
use ipnetwork::IpNetwork;
+use nix::net::if_::if_nametoindex;
use std::{
collections::{BTreeMap, HashSet},
net::{IpAddr, SocketAddr},
@@ -312,17 +313,24 @@ impl RouteManagerImpl {
// Add routes not using the default interface
for route in routes_to_apply {
- let mut message = if let Some(ref device) = route.node.device {
- // If we specify route by interface name, use the link address of the given
- // interface
- match interface_link_addrs.get(device) {
- Some(link_addr) => RouteMessage::new_route(Destination::from(route.prefix))
- .set_gateway_sockaddr(*link_addr),
- None => {
- log::error!("Route with unknown device: {route:?}, {device}");
- continue;
- }
- }
+ let mut message = if let Some(device) = route.node.get_device() {
+ // Get the link-address of the provided network interface (device).
+ // We need the link address to create a route that targets the interface.
+ let Some(link_addr) = interface_link_addrs.get(device) else {
+ log::error!("Route with unknown device: {route:?}, {device}");
+ continue;
+ };
+
+ // Get the index of the network interface. This is not needed to create the route,
+ // but we use it to later validate that the route is correct.
+ let Ok(interface_index) = if_nametoindex(device) else {
+ log::error!("Route with unknown device: {route:?}, {device}");
+ continue;
+ };
+
+ RouteMessage::new_route(Destination::from(route.prefix))
+ .set_gateway_sockaddr(*link_addr)
+ .set_interface_index(interface_index as u16)
} else {
log::error!("Specifying gateway by IP rather than device is unimplemented");
continue;
@@ -509,14 +517,8 @@ impl RouteManagerImpl {
let actual_default_route = self.get_actual_default_route(family).await.unwrap_or(None);
if let Some(actual_default_route) = actual_default_route {
- // TODO: compare interface index instead?
- let tun_gateway_link_addr =
- tunnel_route.gateway().and_then(|addr| addr.as_link_addr());
- let actual_link_addr = actual_default_route
- .gateway()
- .and_then(|addr| addr.as_link_addr());
-
- if actual_link_addr.is_none() || actual_link_addr != tun_gateway_link_addr {
+ debug_assert!(tunnel_route.interface_index() != 0);
+ if tunnel_route.interface_index() != actual_default_route.interface_index() {
log::trace!("Removing existing unscoped default route");
let _ = self