summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2022-01-07 09:10:23 +0100
committerDavid Lönnhager <david.l@mullvad.net>2022-01-14 10:53:16 +0100
commitfeaaec4a41726074e007073d9ef6686cab19647f (patch)
tree515d2e4e35466f021e8fd887ec0a34f77a183a42
parent4ea0baa61e1e8c5ffaa88f5fd3fee9c144ba95ef (diff)
downloadmullvadvpn-feaaec4a41726074e007073d9ef6686cab19647f.tar.xz
mullvadvpn-feaaec4a41726074e007073d9ef6686cab19647f.zip
Wait for IP interfaces before setting MTU
-rw-r--r--talpid-core/src/tunnel/wireguard/wireguard_nt.rs63
1 files changed, 52 insertions, 11 deletions
diff --git a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs
index dde1a991fd..e74eb58de4 100644
--- a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs
+++ b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs
@@ -27,9 +27,10 @@ use winapi::{
in6addr::IN6_ADDR,
inaddr::IN_ADDR,
minwindef::{BOOL, FARPROC, HINSTANCE, HMODULE},
+ netioapi::MibAddInstance,
nldef::RouterDiscoveryDisabled,
ntdef::FALSE,
- winerror::ERROR_MORE_DATA,
+ winerror::{ERROR_MORE_DATA, ERROR_NOT_FOUND},
ws2def::{ADDRESS_FAMILY, AF_INET, AF_INET6},
ws2ipdef::SOCKADDR_INET,
},
@@ -131,6 +132,10 @@ pub enum Error {
#[error(display = "Failed to set tunnel WireGuard config")]
SetWireGuardConfigError(#[error(source)] io::Error),
+ /// Failed to listen for IP interface events
+ #[error(display = "Failed to set up tunnel IP interface listener")]
+ SetUpInterfaceListener(#[error(source)] io::Error),
+
/// Failed to set MTU on tunnel device
#[error(display = "Failed to set tunnel IPv4 interface MTU")]
SetTunnelIpv4MtuError(#[error(source)] io::Error),
@@ -164,8 +169,9 @@ pub enum Error {
InvalidConfigData,
}
-pub struct WgNtTunnel {
+pub struct WgNtTunnel<'a> {
device: Option<WgNtAdapter>,
+ watcher: Option<Box<crate::windows::IpNotifierHandle<'a>>>,
interface_luid: NET_LUID,
interface_name: String,
_logger_handle: LoggerHandle,
@@ -405,7 +411,7 @@ enum WgAdapterState {
Up = 1,
}
-impl WgNtTunnel {
+impl WgNtTunnel<'_> {
pub fn start_tunnel(
config: &Config,
log_path: Option<&Path>,
@@ -427,8 +433,9 @@ impl WgNtTunnel {
.map_err(Error::ObtainAliasError)?
.to_string_lossy();
- let tunnel = WgNtTunnel {
+ let mut tunnel = WgNtTunnel {
device: Some(device),
+ watcher: None,
interface_luid,
interface_name,
_logger_handle: logger_handle,
@@ -438,10 +445,11 @@ impl WgNtTunnel {
}
fn stop_tunnel(&mut self) {
+ let _ = self.watcher.take();
let _ = self.device.take();
}
- fn configure(&self, config: &Config) -> Result<()> {
+ fn configure(&mut self, config: &Config) -> Result<()> {
let device = self.device.as_ref().unwrap();
if let Err(error) = device.set_logging(WireGuardAdapterLogState::On) {
log::error!(
@@ -450,11 +458,44 @@ impl WgNtTunnel {
);
}
device.set_config(config)?;
- prepare_interface(&device.luid(), AF_INET as u16, u32::from(config.mtu))
- .map_err(Error::SetTunnelIpv4MtuError)?;
+
+ let luid = device.luid();
+ let mtu = u32::from(config.mtu);
+ self.watcher = Some(
+ crate::windows::notify_ip_interface_change(
+ move |row, notification_type| {
+ if row.InterfaceLuid.Value != luid.Value {
+ return;
+ }
+ if notification_type != MibAddInstance {
+ return;
+ }
+ if let Err(error) = prepare_interface(&luid, row.Family, mtu) {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to set tunnel IP interface MTU"),
+ );
+ }
+ },
+ None,
+ )
+ .map_err(Error::SetUpInterfaceListener)?,
+ );
+
+ if let Err(error) = prepare_interface(&device.luid(), AF_INET as u16, u32::from(config.mtu))
+ {
+ if error.raw_os_error() != Some(ERROR_NOT_FOUND as i32) {
+ return Err(Error::SetTunnelIpv4MtuError(error));
+ }
+ }
if config.tunnel.addresses.iter().any(|addr| addr.is_ipv6()) {
- prepare_interface(&device.luid(), AF_INET6 as u16, u32::from(config.mtu))
- .map_err(Error::SetTunnelIpv6MtuError)?;
+ if let Err(error) =
+ prepare_interface(&device.luid(), AF_INET6 as u16, u32::from(config.mtu))
+ {
+ if error.raw_os_error() != Some(ERROR_NOT_FOUND as i32) {
+ return Err(Error::SetTunnelIpv6MtuError(error));
+ }
+ }
}
device
.set_state(WgAdapterState::Up)
@@ -463,7 +504,7 @@ impl WgNtTunnel {
}
}
-impl Drop for WgNtTunnel {
+impl Drop for WgNtTunnel<'_> {
fn drop(&mut self) {
self.stop_tunnel();
}
@@ -909,7 +950,7 @@ fn prepare_interface(luid: &NET_LUID, family: u16, mtu: u32) -> io::Result<()> {
windows::set_ip_interface_entry(&iface)
}
-impl Tunnel for WgNtTunnel {
+impl Tunnel for WgNtTunnel<'_> {
fn get_interface_name(&self) -> String {
self.interface_name.clone()
}