diff options
| -rw-r--r-- | talpid-core/src/tunnel/openvpn/mod.rs | 36 | ||||
| -rw-r--r-- | wireguard/libwg/libwg_windows.go | 27 |
2 files changed, 49 insertions, 14 deletions
diff --git a/talpid-core/src/tunnel/openvpn/mod.rs b/talpid-core/src/tunnel/openvpn/mod.rs index 9eaa25875f..22acb985cf 100644 --- a/talpid-core/src/tunnel/openvpn/mod.rs +++ b/talpid-core/src/tunnel/openvpn/mod.rs @@ -82,6 +82,8 @@ const ADAPTER_GUID: GUID = GUID { const DEVICE_READY_TIMEOUT: Duration = Duration::from_secs(5); #[cfg(windows)] const DEVICE_CHECK_INTERVAL: Duration = Duration::from_millis(100); +#[cfg(windows)] +const MAX_WINTUN_CREATION_ATTEMPTS: u32 = 3; /// Results from fallible operations on the OpenVPN tunnel. @@ -265,7 +267,7 @@ pub struct OpenVpnMonitor<C: OpenVpnBuilder = OpenVpnCommand> { server_join_handle: Option<task::JoinHandle<std::result::Result<(), event_server::Error>>>, #[cfg(windows)] - wintun: Arc<Box<dyn WintunContext>>, + _wintun: Arc<Box<dyn WintunContext>>, } #[cfg(windows)] @@ -378,13 +380,29 @@ impl OpenVpnMonitor<OpenVpnCommand> { } } - let (adapter, reboot_required) = windows::TemporaryWintunAdapter::create( - dll.clone(), - &*ADAPTER_ALIAS, - &*ADAPTER_POOL, - Some(ADAPTER_GUID.clone()), - ) - .map_err(Error::WintunError)?; + let mut attempt = 0; + let (adapter, reboot_required) = loop { + let error = match windows::TemporaryWintunAdapter::create( + dll.clone(), + &*ADAPTER_ALIAS, + &*ADAPTER_POOL, + Some(ADAPTER_GUID.clone()), + ) { + Ok(result) => break result, + Err(error) => error, + }; + + attempt += 1; + if attempt == MAX_WINTUN_CREATION_ATTEMPTS { + return Err(Error::WintunError(error)); + } + log::error!( + "{} (attempt {})", + error.display_chain_with_msg("Failed to create Wintun interface"), + attempt + ); + std::thread::sleep(std::time::Duration::from_secs(1)); + }; if reboot_required { log::warn!("You may need to restart Windows to complete the install of Wintun"); @@ -572,7 +590,7 @@ impl<C: OpenVpnBuilder + Send + 'static> OpenVpnMonitor<C> { server_join_handle: Some(server_join_handle), #[cfg(windows)] - wintun, + _wintun: wintun, }) } diff --git a/wireguard/libwg/libwg_windows.go b/wireguard/libwg/libwg_windows.go index 2cf04ed140..91d63a002c 100644 --- a/wireguard/libwg/libwg_windows.go +++ b/wireguard/libwg/libwg_windows.go @@ -13,6 +13,7 @@ import ( "bufio" "fmt" "strings" + "time" "unsafe" "golang.org/x/sys/windows" @@ -26,6 +27,10 @@ import ( "github.com/mullvad/mullvadvpn-app/wireguard/libwg/tunnelcontainer" ) +const ( + MAX_WINTUN_CREATION_ATTEMPTS = 3 +) + // Redefined here because otherwise the compiler doesn't realize it's a type alias for a type that's safe to export. // Taken from the contained logging package. type LogSink = unsafe.Pointer @@ -68,11 +73,23 @@ func wgTurnOn(cIfaceName *C.char, mtu int, waitOnIpv6 bool, cSettings *C.char, c tun.WintunPool = MullvadPool } - wintun, err := tun.CreateTUNWithRequestedGUID(ifaceName, &networkId, mtu) - if err != nil { - logger.Errorf("Failed to create tunnel\n") - logger.Errorf("%s\n", err) - return ERROR_GENERAL_FAILURE + var wintun tun.Device + var wintunErr error + + attempt := 0 + for { + attempt += 1 + wintun, wintunErr = tun.CreateTUNWithRequestedGUID(ifaceName, &networkId, mtu) + if wintunErr != nil { + logger.Errorf("Failed to create tunnel\n") + logger.Errorf("%s\n", wintunErr) + if attempt == MAX_WINTUN_CREATION_ATTEMPTS { + return ERROR_GENERAL_FAILURE + } + time.Sleep(1 * time.Second) + continue + } + break } nativeTun := wintun.(*tun.NativeTun) |
