summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--talpid-core/src/tunnel/openvpn/mod.rs36
-rw-r--r--wireguard/libwg/libwg_windows.go27
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)