summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2024-08-19 10:25:25 +0200
committerDavid Lönnhager <david.l@mullvad.net>2024-08-20 12:02:24 +0200
commitcfd1accfed1c946ecff7c800c743771af3c9f477 (patch)
treea5294a92a8ef4bac6608fdabe16a5c391a9ed716
parentfc4facca1610e135bc40dae5453b9ae5ed6d4ae8 (diff)
downloadmullvadvpn-cfd1accfed1c946ecff7c800c743771af3c9f477.tar.xz
mullvadvpn-cfd1accfed1c946ecff7c800c743771af3c9f477.zip
Add interface/mtu change listener
-rw-r--r--talpid-routing/src/unix/macos/data.rs4
-rw-r--r--talpid-routing/src/unix/macos/mod.rs23
-rw-r--r--talpid-routing/src/unix/mod.rs20
3 files changed, 47 insertions, 0 deletions
diff --git a/talpid-routing/src/unix/macos/data.rs b/talpid-routing/src/unix/macos/data.rs
index a5e8a49efd..5ac83d0885 100644
--- a/talpid-routing/src/unix/macos/data.rs
+++ b/talpid-routing/src/unix/macos/data.rs
@@ -634,6 +634,10 @@ impl Interface {
self.header.ifm_index
}
+ pub fn mtu(&self) -> u32 {
+ self.header.ifm_data.ifi_mtu
+ }
+
fn from_byte_buffer(buffer: &[u8]) -> Result<Self> {
const INTERFACE_MESSAGE_HEADER_SIZE: usize = std::mem::size_of::<libc::if_msghdr>();
if INTERFACE_MESSAGE_HEADER_SIZE > buffer.len() {
diff --git a/talpid-routing/src/unix/macos/mod.rs b/talpid-routing/src/unix/macos/mod.rs
index 141b8c06d3..85a020ba79 100644
--- a/talpid-routing/src/unix/macos/mod.rs
+++ b/talpid-routing/src/unix/macos/mod.rs
@@ -90,6 +90,7 @@ pub struct RouteManagerImpl {
v6_default_route: Option<interface::DefaultRoute>,
update_trigger: BurstGuard,
default_route_listeners: Vec<mpsc::UnboundedSender<DefaultRouteEvent>>,
+ interface_change_listeners: Vec<mpsc::UnboundedSender<super::InterfaceEvent>>,
check_default_routes_restored: Pin<Box<dyn FusedStream<Item = ()> + Send>>,
unhandled_default_route_changes: bool,
primary_interface_monitor: interface::PrimaryInterfaceMonitor,
@@ -127,6 +128,7 @@ impl RouteManagerImpl {
v6_default_route: None,
update_trigger,
default_route_listeners: vec![],
+ interface_change_listeners: vec![],
check_default_routes_restored: Box::pin(futures::stream::pending()),
unhandled_default_route_changes: false,
primary_interface_monitor,
@@ -227,6 +229,13 @@ impl RouteManagerImpl {
log::error!("Failed to clean up rotues: {err}");
}
},
+
+ Some(RouteManagerCommand::NewInterfaceChangeListener(tx)) => {
+ let (events_tx, events_rx) = mpsc::unbounded();
+ self.interface_change_listeners.push(events_tx);
+ let _ = tx.send(events_rx);
+ }
+
Some(RouteManagerCommand::RefreshRoutes) => {
if let Err(error) = self.refresh_routes().await {
log::error!("Failed to refresh routes: {error}");
@@ -377,6 +386,20 @@ impl RouteManagerImpl {
Ok(RouteSocketMessage::AddAddress(_) | RouteSocketMessage::DeleteAddress(_)) => {
self.update_trigger.trigger();
}
+ Ok(RouteSocketMessage::Interface(iface)) => {
+ let Ok(mtu) = u16::try_from(iface.mtu()) else {
+ log::warn!("Invalid mtu for interface: {}", iface.index());
+ return;
+ };
+
+ self.interface_change_listeners.retain(|tx| {
+ tx.unbounded_send(super::InterfaceEvent {
+ interface_index: iface.index(),
+ mtu,
+ })
+ .is_ok()
+ });
+ }
// ignore all other message types
Ok(_) => {}
Err(err) => {
diff --git a/talpid-routing/src/unix/mod.rs b/talpid-routing/src/unix/mod.rs
index 044a09433a..d257140f7e 100644
--- a/talpid-routing/src/unix/mod.rs
+++ b/talpid-routing/src/unix/mod.rs
@@ -118,10 +118,18 @@ pub(crate) enum RouteManagerCommand {
RefreshRoutes,
NewDefaultRouteListener(oneshot::Sender<mpsc::UnboundedReceiver<DefaultRouteEvent>>),
GetDefaultRoutes(oneshot::Sender<(Option<DefaultRoute>, Option<DefaultRoute>)>),
+ NewInterfaceChangeListener(oneshot::Sender<mpsc::UnboundedReceiver<InterfaceEvent>>),
/// Return gateway for V4 and V6
GetDefaultGateway(oneshot::Sender<(Option<Gateway>, Option<Gateway>)>),
}
+/// Event that is sent when interface details may have changed for some interface.
+#[cfg(target_os = "macos")]
+pub struct InterfaceEvent {
+ pub interface_index: u16,
+ pub mtu: u16,
+}
+
/// Event that is sent when a preferred non-tunnel default route is
/// added or removed.
#[cfg(target_os = "macos")]
@@ -227,6 +235,18 @@ impl RouteManagerHandle {
response_rx.await.map_err(|_| Error::ManagerChannelDown)
}
+ /// Listen for interface changes.
+ #[cfg(target_os = "macos")]
+ pub async fn interface_change_listener(
+ &self,
+ ) -> Result<impl Stream<Item = InterfaceEvent>, Error> {
+ let (response_tx, response_rx) = oneshot::channel();
+ self.tx
+ .unbounded_send(RouteManagerCommand::NewInterfaceChangeListener(response_tx))
+ .map_err(|_| Error::RouteManagerDown)?;
+ response_rx.await.map_err(|_| Error::ManagerChannelDown)
+ }
+
/// Get default gateway
#[cfg(target_os = "macos")]
pub async fn get_default_gateway(&self) -> Result<(Option<Gateway>, Option<Gateway>), Error> {