summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-08-31 13:31:09 +0200
committerDavid Lönnhager <david.l@mullvad.net>2023-08-31 13:31:09 +0200
commitbbe31c1e236d66f1a77a7f944c8a264a486b6223 (patch)
treef213aa245e742dd6ae58ccd82193b81001c2f9c5
parent08ec4a88df17088a2fc81c3ee5f2d1d62ef0c1f1 (diff)
parent32f5426bb5c9ec886cfdcbb0c4fc3b516ef2d142 (diff)
downloadmullvadvpn-bbe31c1e236d66f1a77a7f944c8a264a486b6223.tar.xz
mullvadvpn-bbe31c1e236d66f1a77a7f944c8a264a486b6223.zip
Merge branch 'win-remove-user-wg-des-316' into main
-rw-r--r--.github/workflows/daemon.yml5
-rw-r--r--BuildInstructions.md7
-rw-r--r--CHANGELOG.md3
-rwxr-xr-xbuild.sh9
-rwxr-xr-xci/check-rust.sh4
-rw-r--r--gui/tasks/distribution.js1
-rw-r--r--mullvad-daemon/src/lib.rs40
-rw-r--r--mullvad-daemon/src/management_interface.rs16
-rw-r--r--mullvad-management-interface/proto/management_interface.proto3
-rw-r--r--mullvad-management-interface/src/client.rs9
-rw-r--r--mullvad-management-interface/src/types/conversions/settings.rs6
-rw-r--r--mullvad-types/src/wireguard.rs8
-rw-r--r--talpid-core/build.rs1
-rw-r--r--talpid-types/src/net/wireguard.rs3
-rw-r--r--talpid-wireguard/build.rs3
-rw-r--r--talpid-wireguard/src/config.rs5
-rw-r--r--talpid-wireguard/src/lib.rs65
-rw-r--r--talpid-wireguard/src/logging.rs41
-rw-r--r--talpid-wireguard/src/stats.rs142
-rw-r--r--talpid-wireguard/src/wireguard_go.rs338
-rw-r--r--talpid-wireguard/src/wireguard_kernel/mod.rs1
-rw-r--r--talpid-wireguard/src/wireguard_kernel/stats.rs32
-rw-r--r--talpid-wireguard/src/wireguard_nt.rs10
-rwxr-xr-xwireguard/build-wireguard-go.sh46
-rw-r--r--wireguard/libwg/README.md3
-rw-r--r--wireguard/libwg/go.mod2
-rw-r--r--wireguard/libwg/go.sum4
-rw-r--r--wireguard/libwg/interfacewatcher/interfacewatcher_windows.go123
-rw-r--r--wireguard/libwg/libwg_windows.go132
29 files changed, 238 insertions, 824 deletions
diff --git a/.github/workflows/daemon.yml b/.github/workflows/daemon.yml
index ab270c7b67..6112f30fe8 100644
--- a/.github/workflows/daemon.yml
+++ b/.github/workflows/daemon.yml
@@ -148,11 +148,6 @@ jobs:
target: i686-pc-windows-msvc
default: true
- - name: Install Go
- uses: actions/setup-go@v3
- with:
- go-version: 1.18.5
-
- name: Install msbuild
uses: microsoft/setup-msbuild@v1.0.2
with:
diff --git a/BuildInstructions.md b/BuildInstructions.md
index 15d8a29ec2..00d5c5440e 100644
--- a/BuildInstructions.md
+++ b/BuildInstructions.md
@@ -23,7 +23,7 @@ on your platform please submit an issue or a pull request.
Install the `msi` hosted here: https://github.com/volta-cli/volta
-- Install Go (ideally version `1.18`) by following the [official
+- (Not Windows) Install Go (ideally version `1.18`) by following the [official
instructions](https://golang.org/doc/install). Newer versions may work
too.
@@ -102,11 +102,6 @@ The host has to have the following installed:
- `bash` installed as well as a few base unix utilities, including `sed` and `tail`.
You are recommended to use [Git for Windows].
-- `mingw` is required for CGo.
- The latest [`mingw-w64`](https://github.com/niXman/mingw-builds-binaries/releases) build works
- well. Specifically, you'll need one of the releases labeled `x86_64`, `win32`, and `msvcrt`,
- such as <https://github.com/niXman/mingw-builds-binaries/releases/download/13.1.0-rt_v11-rev1/x86_64-13.1.0-release-win32-seh-msvcrt-rt_v11-rev1.7z>.
-
- The `x86` target is required for building some NSIS plugins:
```bash
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6cc31848ef..fd5886c5f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -101,6 +101,9 @@ Line wrap the file at 100 chars. Th
### Removed
- Remove the CLI subcommand `mullvad relay set hostname`.
+#### Windows
+- Remove wireguard-go (userspace WireGuard) support.
+
## [2023.4] - 2023-06-27
### Fixed
diff --git a/build.sh b/build.sh
index 2539d61203..367febba7f 100755
--- a/build.sh
+++ b/build.sh
@@ -200,12 +200,9 @@ function build {
# Compile and link all binaries.
################################################################################
- log_header "Building wireguard-go$for_target_string"
-
- ./wireguard/build-wireguard-go.sh "$current_target"
- if [[ "$SIGN" == "true" && "$(uname -s)" == "MINGW"* ]]; then
- # Windows can only be built for this one target anyway, so it can be hardcoded.
- sign_win "build/lib/x86_64-pc-windows-msvc/libwg.dll"
+ if [[ "$(uname -s)" != "MINGW"* ]]; then
+ log_header "Building wireguard-go$for_target_string"
+ ./wireguard/build-wireguard-go.sh "$current_target"
fi
log_header "Building Rust code in $RUST_BUILD_MODE mode using $RUSTC_VERSION$for_target_string"
diff --git a/ci/check-rust.sh b/ci/check-rust.sh
index 9ecf050f8e..d42784d36e 100755
--- a/ci/check-rust.sh
+++ b/ci/check-rust.sh
@@ -5,7 +5,9 @@ set -eux
export RUSTFLAGS="--deny warnings"
# Build WireGuard Go
-./wireguard/build-wireguard-go.sh
+if [[ "$(uname -s)" != "MINGW"* ]]; then
+ ./wireguard/build-wireguard-go.sh
+fi
# Build Rust crates
source env.sh
diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js
index fa27093e93..e1ba96103e 100644
--- a/gui/tasks/distribution.js
+++ b/gui/tasks/distribution.js
@@ -143,7 +143,6 @@ const config = {
to: '.',
},
{ from: distAssets('binaries/x86_64-pc-windows-msvc/openvpn.exe'), to: '.' },
- { from: buildAssets('lib/x86_64-pc-windows-msvc/libwg.dll'), to: '.' },
{ from: distAssets('binaries/x86_64-pc-windows-msvc/wintun/wintun.dll'), to: '.' },
{ from: distAssets('binaries/x86_64-pc-windows-msvc/split-tunnel/mullvad-split-tunnel.sys'), to: '.' },
{
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index f0516dd1fc..e757258c73 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -292,9 +292,6 @@ pub enum DaemonCommand {
/// Returns all processes currently being excluded from the tunnel
#[cfg(windows)]
GetSplitTunnelProcesses(ResponseTx<Vec<ExcludedProcess>, split_tunnel::Error>),
- /// Toggle wireguard-nt on or off
- #[cfg(target_os = "windows")]
- UseWireGuardNt(ResponseTx<(), Error>, bool),
/// Notify the split tunnel monitor that a volume was mounted or dismounted
#[cfg(target_os = "windows")]
CheckVolumes(ResponseTx<(), Error>),
@@ -1064,8 +1061,6 @@ where
#[cfg(windows)]
GetSplitTunnelProcesses(tx) => self.on_get_split_tunnel_processes(tx),
#[cfg(target_os = "windows")]
- UseWireGuardNt(tx, state) => self.on_use_wireguard_nt(tx, state).await,
- #[cfg(target_os = "windows")]
CheckVolumes(tx) => self.on_check_volumes(tx),
SetObfuscationSettings(tx, settings) => {
self.on_set_obfuscation_settings(tx, settings).await
@@ -1753,41 +1748,6 @@ where
}
#[cfg(windows)]
- async fn on_use_wireguard_nt(&mut self, tx: ResponseTx<(), Error>, state: bool) {
- match self
- .settings
- .update(move |settings| settings.tunnel_options.wireguard.use_wireguard_nt = state)
- .await
- {
- Ok(settings_changed) => {
- Self::oneshot_send(tx, Ok(()), "use_wireguard_nt response");
- if settings_changed {
- self.parameters_generator
- .set_tunnel_options(&self.settings.tunnel_options)
- .await;
- self.event_listener
- .notify_settings(self.settings.to_settings());
- if let Some(TunnelType::Wireguard) = self.get_target_tunnel_type() {
- log::info!("Initiating tunnel restart");
- self.reconnect_tunnel();
- }
- }
- }
- Err(error) => {
- log::error!(
- "{}",
- error.display_chain_with_msg("Unable to save settings")
- );
- Self::oneshot_send(
- tx,
- Err(Error::SettingsError(error)),
- "use_wireguard_nt response",
- );
- }
- }
- }
-
- #[cfg(windows)]
fn on_check_volumes(&mut self, tx: ResponseTx<(), Error>) {
if self.volume_update_tx.unbounded_send(()).is_ok() {
let _ = tx.send(Ok(()));
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index 1e21cc881d..76b6a7e4fd 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -846,22 +846,6 @@ impl ManagementService for ManagementServiceImpl {
}
#[cfg(windows)]
- async fn set_use_wireguard_nt(&self, request: Request<bool>) -> ServiceResult<()> {
- log::debug!("set_use_wireguard_nt");
- let state = request.into_inner();
- let (tx, rx) = oneshot::channel();
- self.send_command_to_daemon(DaemonCommand::UseWireGuardNt(tx, state))?;
- self.wait_for_result(rx)
- .await?
- .map_err(map_daemon_error)
- .map(Response::new)
- }
- #[cfg(not(windows))]
- async fn set_use_wireguard_nt(&self, _: Request<bool>) -> ServiceResult<()> {
- Ok(Response::new(()))
- }
-
- #[cfg(windows)]
async fn check_volumes(&self, _: Request<()>) -> ServiceResult<()> {
log::debug!("check_volumes");
let (tx, rx) = oneshot::channel();
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index f82f55078a..4fdff3e75c 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -89,8 +89,6 @@ service ManagementService {
rpc SetSplitTunnelState(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc GetExcludedProcesses(google.protobuf.Empty) returns (ExcludedProcessList) {}
- rpc SetUseWireguardNt(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
-
// Notify the split tunnel monitor that a volume was mounted or dismounted
// (Windows).
rpc CheckVolumes(google.protobuf.Empty) returns (google.protobuf.Empty) {}
@@ -469,7 +467,6 @@ message TunnelOptions {
message WireguardOptions {
uint32 mtu = 1;
google.protobuf.Duration rotation_interval = 2;
- bool use_wireguard_nt = 3;
QuantumResistantState quantum_resistant = 4;
}
message GenericOptions { bool enable_ipv6 = 1; }
diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs
index b8c0b32085..e9acad1337 100644
--- a/mullvad-management-interface/src/client.rs
+++ b/mullvad-management-interface/src/client.rs
@@ -582,15 +582,6 @@ impl MullvadProxyClient {
.collect::<Vec<_>>())
}
- #[cfg(target_os = "windows")]
- pub async fn set_use_wireguard_nt(&mut self, state: bool) -> Result<()> {
- self.0
- .set_use_wireguard_nt(state)
- .await
- .map_err(Error::Rpc)?;
- Ok(())
- }
-
// check_volumes
}
diff --git a/mullvad-management-interface/src/types/conversions/settings.rs b/mullvad-management-interface/src/types/conversions/settings.rs
index c0611c799f..a429937410 100644
--- a/mullvad-management-interface/src/types/conversions/settings.rs
+++ b/mullvad-management-interface/src/types/conversions/settings.rs
@@ -84,10 +84,6 @@ impl From<&mullvad_types::settings::TunnelOptions> for proto::TunnelOptions {
prost_types::Duration::try_from(std::time::Duration::from(ivl))
.expect("Failed to convert std::time::Duration to prost_types::Duration for tunnel_options.wireguard.rotation_interval")
}),
- #[cfg(windows)]
- use_wireguard_nt: options.wireguard.use_wireguard_nt,
- #[cfg(not(windows))]
- use_wireguard_nt: false,
quantum_resistant: Some(proto::QuantumResistantState::from(options.wireguard.quantum_resistant)),
}),
generic: Some(proto::tunnel_options::GenericOptions {
@@ -250,8 +246,6 @@ impl TryFrom<proto::TunnelOptions> for mullvad_types::settings::TunnelOptions {
} else {
None
},
- #[cfg(windows)]
- use_wireguard_nt: wireguard_options.use_wireguard_nt,
rotation_interval: wireguard_options
.rotation_interval
.map(std::time::Duration::try_from)
diff --git a/mullvad-types/src/wireguard.rs b/mullvad-types/src/wireguard.rs
index 9fdda6cb20..f551250324 100644
--- a/mullvad-types/src/wireguard.rs
+++ b/mullvad-types/src/wireguard.rs
@@ -198,10 +198,6 @@ pub struct TunnelOptions {
jnix(map = "|maybe_mtu| maybe_mtu.map(|mtu| mtu as i32)")
)]
pub mtu: Option<u16>,
- /// Temporary switch for wireguard-nt
- #[cfg(windows)]
- #[serde(rename = "wireguard_nt")]
- pub use_wireguard_nt: bool,
/// Obtain a PSK using the relay config client.
pub quantum_resistant: QuantumResistantState,
/// Interval used for automatic key rotation
@@ -215,8 +211,6 @@ impl Default for TunnelOptions {
TunnelOptions {
mtu: None,
quantum_resistant: QuantumResistantState::Auto,
- #[cfg(windows)]
- use_wireguard_nt: true,
rotation_interval: None,
}
}
@@ -226,8 +220,6 @@ impl TunnelOptions {
pub fn into_talpid_tunnel_options(self) -> wireguard::TunnelOptions {
wireguard::TunnelOptions {
mtu: self.mtu,
- #[cfg(windows)]
- use_wireguard_nt: self.use_wireguard_nt,
quantum_resistant: match self.quantum_resistant {
QuantumResistantState::Auto => QUANTUM_RESISTANT_AUTO_STATE,
QuantumResistantState::On => true,
diff --git a/talpid-core/build.rs b/talpid-core/build.rs
index 1c16a35e74..330d3c490f 100644
--- a/talpid-core/build.rs
+++ b/talpid-core/build.rs
@@ -54,7 +54,6 @@ fn main() {
declare_library(WINFW_DIR_VAR, WINFW_BUILD_DIR, "winfw");
let lib_dir = manifest_dir().join("../build/lib/x86_64-pc-windows-msvc");
println!("cargo:rustc-link-search={}", &lib_dir.display());
- println!("cargo:rustc-link-lib=dylib=libwg");
}
#[cfg(not(windows))]
diff --git a/talpid-types/src/net/wireguard.rs b/talpid-types/src/net/wireguard.rs
index 4de5ceb9c1..2c79e2938b 100644
--- a/talpid-types/src/net/wireguard.rs
+++ b/talpid-types/src/net/wireguard.rs
@@ -74,9 +74,6 @@ pub struct TunnelConfig {
pub struct TunnelOptions {
/// MTU for the wireguard tunnel
pub mtu: Option<u16>,
- /// Temporary switch for wireguard-nt
- #[cfg(windows)]
- pub use_wireguard_nt: bool,
/// Perform PQ-safe PSK exchange when connecting
pub quantum_resistant: bool,
}
diff --git a/talpid-wireguard/build.rs b/talpid-wireguard/build.rs
index b02f603440..91a4a4e5d3 100644
--- a/talpid-wireguard/build.rs
+++ b/talpid-wireguard/build.rs
@@ -20,6 +20,9 @@ fn main() {
};
println!("cargo:rustc-link-lib{link_type}=wg");
+
+ #[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))]
+ println!("cargo:rustc-cfg=wireguard_go");
}
fn declare_libs_dir(base: &str) {
diff --git a/talpid-wireguard/src/config.rs b/talpid-wireguard/src/config.rs
index 358aa5d64a..fa4b7e078e 100644
--- a/talpid-wireguard/src/config.rs
+++ b/talpid-wireguard/src/config.rs
@@ -24,9 +24,6 @@ pub struct Config {
/// Enable IPv6 routing rules
#[cfg(target_os = "linux")]
pub enable_ipv6: bool,
- /// Temporary switch for wireguard-nt
- #[cfg(target_os = "windows")]
- pub use_wireguard_nt: bool,
/// Obfuscator config to be used for reaching the relay.
pub obfuscator_config: Option<ObfuscatorConfig>,
}
@@ -121,8 +118,6 @@ impl Config {
fwmark: connection_config.fwmark,
#[cfg(target_os = "linux")]
enable_ipv6: generic_options.enable_ipv6,
- #[cfg(target_os = "windows")]
- use_wireguard_nt: wg_options.use_wireguard_nt,
obfuscator_config,
})
}
diff --git a/talpid-wireguard/src/lib.rs b/talpid-wireguard/src/lib.rs
index 784cafa75b..cdc09224ef 100644
--- a/talpid-wireguard/src/lib.rs
+++ b/talpid-wireguard/src/lib.rs
@@ -29,15 +29,13 @@ use talpid_tunnel::tun_provider;
use talpid_tunnel::{tun_provider::TunProvider, TunnelArgs, TunnelEvent, TunnelMetadata};
use ipnetwork::IpNetwork;
-#[cfg(windows)]
-use talpid_types::BoxedError;
use talpid_types::{
net::{
obfuscation::ObfuscatorConfig,
wireguard::{PresharedKey, PrivateKey, PublicKey},
AllowedTunnelTraffic, Endpoint, TransportProtocol,
},
- ErrorExt,
+ BoxedError, ErrorExt,
};
use tokio::sync::Mutex as AsyncMutex;
use tunnel_obfuscation::{
@@ -50,12 +48,14 @@ mod connectivity_check;
mod logging;
mod ping_monitor;
mod stats;
+#[cfg(wireguard_go)]
mod wireguard_go;
#[cfg(target_os = "linux")]
pub(crate) mod wireguard_kernel;
#[cfg(windows)]
mod wireguard_nt;
+#[cfg(wireguard_go)]
use self::wireguard_go::WgGoTunnel;
type Result<T> = std::result::Result<T, Error>;
@@ -764,44 +764,33 @@ impl WireguardMonitor {
}
#[cfg(target_os = "windows")]
- if config.use_wireguard_nt {
- log::debug!("Using WireGuardNT");
- return wireguard_nt::WgNtTunnel::start_tunnel(
- config,
- log_path,
- resource_dir,
- setup_done_tx,
- )
- .map(|tun| Box::new(tun) as Box<dyn Tunnel + 'static>)
- .map_err(Error::TunnelError);
+ {
+ wireguard_nt::WgNtTunnel::start_tunnel(config, log_path, resource_dir, setup_done_tx)
+ .map(|tun| Box::new(tun) as Box<dyn Tunnel + 'static>)
+ .map_err(Error::TunnelError)
}
- #[cfg(not(windows))]
- let routes = Self::get_tunnel_destinations(config).flat_map(Self::replace_default_prefixes);
+ #[cfg(wireguard_go)]
+ {
+ let routes =
+ Self::get_tunnel_destinations(config).flat_map(Self::replace_default_prefixes);
- #[cfg(target_os = "android")]
- let config = Self::patch_allowed_ips(config, psk_negotiation);
+ #[cfg(target_os = "android")]
+ let config = Self::patch_allowed_ips(config, psk_negotiation);
- #[cfg(any(target_os = "linux", windows))]
- log::debug!("Using userspace WireGuard implementation");
- Ok(Box::new(
- WgGoTunnel::start_tunnel(
- #[allow(clippy::needless_borrow)]
- &config,
- log_path,
- #[cfg(not(windows))]
- tun_provider,
- #[cfg(not(windows))]
- routes,
- #[cfg(windows)]
- route_manager_handle,
- #[cfg(windows)]
- setup_done_tx,
- #[cfg(windows)]
- &runtime,
- )
- .map_err(Error::TunnelError)?,
- ))
+ #[cfg(target_os = "linux")]
+ log::debug!("Using userspace WireGuard implementation");
+ Ok(Box::new(
+ WgGoTunnel::start_tunnel(
+ #[allow(clippy::needless_borrow)]
+ &config,
+ log_path,
+ tun_provider,
+ routes,
+ )
+ .map_err(Error::TunnelError)?,
+ ))
+ }
}
/// Blocks the current thread until tunnel disconnects
@@ -1014,7 +1003,7 @@ pub enum TunnelError {
/// Error whilst trying to parse the WireGuard config to read the stats
#[error(display = "Reading tunnel stats failed")]
- StatsError(#[error(source)] stats::Error),
+ StatsError(#[error(source)] BoxedError),
/// Error whilst trying to retrieve config of a WireGuard tunnel
#[error(display = "Failed to get config of WireGuard tunnel")]
diff --git a/talpid-wireguard/src/logging.rs b/talpid-wireguard/src/logging.rs
index 5f006d418c..f9adcb7f53 100644
--- a/talpid-wireguard/src/logging.rs
+++ b/talpid-wireguard/src/logging.rs
@@ -1,6 +1,5 @@
use once_cell::sync::Lazy;
use parking_lot::Mutex;
-use std::ffi::{c_char, c_void};
use std::{collections::HashMap, fmt, fs, io::Write, path::Path};
static LOG_MUTEX: Lazy<Mutex<HashMap<u32, fs::File>>> = Lazy::new(|| Mutex::new(HashMap::new()));
@@ -45,10 +44,12 @@ pub fn clean_up_logging(ordinal: u32) {
map.remove(&ordinal);
}
-#[allow(dead_code)]
pub enum LogLevel {
+ #[cfg_attr(windows, allow(dead_code))]
Verbose,
+ #[cfg_attr(wireguard_go, allow(dead_code))]
Info,
+ #[cfg_attr(wireguard_go, allow(dead_code))]
Warning,
Error,
}
@@ -70,7 +71,6 @@ impl AsRef<str> for LogLevel {
}
}
-#[cfg(windows)]
pub fn log(context: u32, level: LogLevel, tag: &str, msg: &str) {
let mut map = LOG_MUTEX.lock();
if let Some(logfile) = map.get_mut(&{ context }) {
@@ -88,38 +88,3 @@ fn log_inner(logfile: &mut fs::File, level: LogLevel, tag: &str, msg: &str) {
msg,
);
}
-
-// Callback that receives messages from WireGuard
-pub unsafe extern "system" fn wg_go_logging_callback(
- level: WgLogLevel,
- msg: *const c_char,
- context: *mut c_void,
-) {
- let mut map = LOG_MUTEX.lock();
- if let Some(logfile) = map.get_mut(&(context as u32)) {
- let managed_msg = if !msg.is_null() {
- #[cfg(not(target_os = "windows"))]
- let m = std::ffi::CStr::from_ptr(msg).to_string_lossy().to_string();
- #[cfg(target_os = "windows")]
- let m = std::ffi::CStr::from_ptr(msg)
- .to_string_lossy()
- .to_string()
- .replace('\n', "\r\n");
- m
- } else {
- "Logging message from WireGuard is NULL".to_string()
- };
-
- let level = match level {
- WG_GO_LOG_VERBOSE => LogLevel::Verbose,
- _ => LogLevel::Error,
- };
- log_inner(logfile, level, "wireguard-go", &managed_msg);
- }
-}
-
-pub type WgLogLevel = u32;
-// wireguard-go supports log levels 0 through 3 with 3 being the most verbose
-// const WG_GO_LOG_SILENT: WgLogLevel = 0;
-// const WG_GO_LOG_ERROR: WgLogLevel = 1;
-const WG_GO_LOG_VERBOSE: WgLogLevel = 2;
diff --git a/talpid-wireguard/src/stats.rs b/talpid-wireguard/src/stats.rs
index bd7b578545..cdbe8318cf 100644
--- a/talpid-wireguard/src/stats.rs
+++ b/talpid-wireguard/src/stats.rs
@@ -1,21 +1,3 @@
-#[cfg(target_os = "linux")]
-use super::wireguard_kernel::wg_message::{DeviceMessage, DeviceNla, PeerNla};
-
-#[derive(err_derive::Error, Debug, PartialEq)]
-pub enum Error {
- #[error(display = "Failed to parse peer pubkey from string \"_0\"")]
- PubKeyParse(String, #[error(source)] hex::FromHexError),
-
- #[error(display = "Failed to parse integer from string \"_0\"")]
- IntParse(String, #[error(source)] std::num::ParseIntError),
-
- #[error(display = "Device no longer exists")]
- NoTunnelDevice,
-
- #[error(display = "Failed to obtain tunnel config")]
- NoTunnelConfig,
-}
-
/// Contains bytes sent and received through a tunnel
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
pub struct Stats {
@@ -25,127 +7,3 @@ pub struct Stats {
/// A map from peer pubkeys to peer stats.
pub type StatsMap = std::collections::HashMap<[u8; 32], Stats>;
-
-impl Stats {
- pub fn parse_config_str(config: &str) -> Result<StatsMap, Error> {
- let mut map = StatsMap::new();
-
- let mut peer = None;
- let mut tx_bytes = None;
- let mut rx_bytes = None;
-
- // parts iterates over keys and values
- let parts = config.split('\n').filter_map(|line| {
- let mut pair = line.split('=');
- let key = pair.next()?;
- let value = pair.next()?;
- Some((key, value))
- });
-
- for (key, value) in parts {
- match key {
- "public_key" => {
- let mut buffer = [0u8; 32];
- hex::decode_to_slice(value, &mut buffer)
- .map_err(|err| Error::PubKeyParse(value.to_string(), err))?;
- peer = Some(buffer);
- tx_bytes = None;
- rx_bytes = None;
- }
- "rx_bytes" => {
- rx_bytes = Some(
- value
- .trim()
- .parse()
- .map_err(|err| Error::IntParse(value.to_string(), err))?,
- );
- }
- "tx_bytes" => {
- tx_bytes = Some(
- value
- .trim()
- .parse()
- .map_err(|err| Error::IntParse(value.to_string(), err))?,
- );
- }
-
- _ => continue,
- }
-
- if let (Some(peer_val), Some(tx_bytes_val), Some(rx_bytes_val)) =
- (peer, tx_bytes, rx_bytes)
- {
- map.insert(
- peer_val,
- Self {
- tx_bytes: tx_bytes_val,
- rx_bytes: rx_bytes_val,
- },
- );
- peer = None;
- tx_bytes = None;
- rx_bytes = None;
- }
- }
- Ok(map)
- }
-
- #[cfg(target_os = "linux")]
- pub fn parse_device_message(message: &DeviceMessage) -> StatsMap {
- let mut map = StatsMap::new();
-
- for nla in &message.nlas {
- if let DeviceNla::Peers(peers) = nla {
- for msg in peers {
- let mut tx_bytes = 0;
- let mut rx_bytes = 0;
- let mut pub_key = None;
-
- for nla in &msg.0 {
- match nla {
- PeerNla::TxBytes(bytes) => tx_bytes = *bytes,
- PeerNla::RxBytes(bytes) => rx_bytes = *bytes,
- PeerNla::PublicKey(key) => pub_key = Some(*key),
- _ => continue,
- }
- }
- if let Some(key) = pub_key {
- map.insert(key, Stats { tx_bytes, rx_bytes });
- }
- }
- }
- }
-
- map
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::{Error, Stats};
-
- #[test]
- fn test_parsing() {
- let valid_input = "private_key=0000000000000000000000000000000000000000000000000000000000000000\npublic_key=0000000000000000000000000000000000000000000000000000000000000000\npreshared_key=0000000000000000000000000000000000000000000000000000000000000000\nprotocol_version=1\nendpoint=000.000.000.000:00000\nlast_handshake_time_sec=1578420649\nlast_handshake_time_nsec=369416131\ntx_bytes=2740\nrx_bytes=2396\npersistent_keepalive_interval=0\nallowed_ip=0.0.0.0/0\n";
- let pubkey = [0u8; 32];
-
- let stats = Stats::parse_config_str(valid_input).expect("Failed to parse valid input");
- assert_eq!(stats.len(), 1);
- let actual_keys: Vec<[u8; 32]> = stats.keys().cloned().collect();
- assert_eq!(actual_keys, [pubkey]);
- assert_eq!(stats[&pubkey].rx_bytes, 2396);
- assert_eq!(stats[&pubkey].tx_bytes, 2740);
- }
-
- #[test]
- fn test_parsing_invalid_input() {
- let invalid_input = "private_key=0000000000000000000000000000000000000000000000000000000000000000\npublic_key=0000000000000000000000000000000000000000000000000000000000000000\npreshared_key=0000000000000000000000000000000000000000000000000000000000000000\nprotocol_version=1\nendpoint=000.000.000.000:00000\nlast_handshake_time_sec=1578420649\nlast_handshake_time_nsec=369416131\ntx_bytes=27error40\npersistent_keepalive_interval=0\nallowed_ip=0.0.0.0/0\n";
- let invalid_str = "27error40".to_string();
- let int_err = invalid_str.parse::<u64>().unwrap_err();
-
- assert_eq!(
- Stats::parse_config_str(invalid_input),
- Err(Error::IntParse(invalid_str, int_err))
- );
- }
-}
diff --git a/talpid-wireguard/src/wireguard_go.rs b/talpid-wireguard/src/wireguard_go.rs
index e848e32679..0e3ea3e9ce 100644
--- a/talpid-wireguard/src/wireguard_go.rs
+++ b/talpid-wireguard/src/wireguard_go.rs
@@ -2,42 +2,31 @@ use super::{
stats::{Stats, StatsMap},
Config, Tunnel, TunnelError,
};
-use crate::logging::{clean_up_logging, initialize_logging, wg_go_logging_callback, WgLogLevel};
-#[cfg(windows)]
-use futures::SinkExt;
+use crate::logging::{clean_up_logging, initialize_logging};
+use ipnetwork::IpNetwork;
use std::{
ffi::{c_char, c_void, CStr},
future::Future,
path::Path,
pin::Pin,
};
-#[cfg(windows)]
+use talpid_tunnel::tun_provider::TunProvider;
use talpid_types::BoxedError;
use zeroize::Zeroize;
-#[cfg(not(windows))]
-use {ipnetwork::IpNetwork, talpid_tunnel::tun_provider::TunProvider};
-
-#[cfg(target_os = "windows")]
-use std::ffi::CString;
#[cfg(target_os = "android")]
use talpid_tunnel::tun_provider;
-#[cfg(not(target_os = "windows"))]
-use {
- std::{
- net::IpAddr,
- os::unix::io::{AsRawFd, RawFd},
- },
- talpid_tunnel::tun_provider::{Tun, TunConfig},
+use std::{
+ net::IpAddr,
+ os::unix::io::{AsRawFd, RawFd},
};
+use talpid_tunnel::tun_provider::{Tun, TunConfig};
type Result<T> = std::result::Result<T, TunnelError>;
-#[cfg(not(target_os = "windows"))]
use std::sync::{Arc, Mutex};
-#[cfg(not(target_os = "windows"))]
const MAX_PREPARE_TUN_ATTEMPTS: usize = 4;
struct LoggingContext(u32);
@@ -53,20 +42,14 @@ pub struct WgGoTunnel {
handle: Option<i32>,
// holding on to the tunnel device and the log file ensures that the associated file handles
// live long enough and get closed when the tunnel is stopped
- #[cfg(not(target_os = "windows"))]
_tunnel_device: Tun,
// context that maps to fs::File instance, used with logging callback
_logging_context: LoggingContext,
- #[cfg(target_os = "windows")]
- _route_callback_handle: Option<talpid_routing::CallbackHandle>,
- #[cfg(target_os = "windows")]
- setup_handle: tokio::task::JoinHandle<()>,
#[cfg(target_os = "android")]
tun_provider: Arc<Mutex<TunProvider>>,
}
impl WgGoTunnel {
- #[cfg(not(target_os = "windows"))]
pub fn start_tunnel(
config: &Config,
log_path: Option<&Path>,
@@ -93,7 +76,7 @@ impl WgGoTunnel {
mtu,
wg_config_str.as_ptr() as _,
tunnel_fd,
- Some(wg_go_logging_callback),
+ Some(logging::wg_go_logging_callback),
logging_context.0 as *mut c_void,
)
};
@@ -113,139 +96,6 @@ impl WgGoTunnel {
})
}
- #[cfg(target_os = "windows")]
- pub fn start_tunnel(
- config: &Config,
- log_path: Option<&Path>,
- route_manager_handle: talpid_routing::RouteManagerHandle,
- mut done_tx: futures::channel::mpsc::Sender<std::result::Result<(), BoxedError>>,
- runtime: &tokio::runtime::Handle,
- ) -> Result<Self> {
- use talpid_types::ErrorExt;
-
- let route_callback_handle = runtime
- .block_on(
- route_manager_handle.add_default_route_change_callback(Box::new(
- WgGoTunnel::default_route_changed_callback,
- )),
- )
- .ok();
- if route_callback_handle.is_none() {
- log::warn!("Failed to register default route callback");
- }
-
- let wg_config_str = config.to_userspace_format();
- let iface_name: String = "Mullvad".to_string();
- let cstr_iface_name =
- CString::new(iface_name.as_bytes()).map_err(TunnelError::InterfaceNameError)?;
- let logging_context = initialize_logging(log_path)
- .map(LoggingContext)
- .map_err(TunnelError::LoggingError)?;
-
- let mut alias_ptr = std::ptr::null_mut();
- let mut interface_luid = 0u64;
-
- let handle = unsafe {
- wgTurnOn(
- cstr_iface_name.as_ptr(),
- config.mtu as i64,
- wg_config_str.as_ptr(),
- &mut alias_ptr,
- &mut interface_luid,
- Some(wg_go_logging_callback),
- logging_context.0 as *mut c_void,
- )
- };
- check_wg_status(handle)?;
-
- let actual_iface_name = {
- let actual_iface_name_c = unsafe { CStr::from_ptr(alias_ptr) };
- let actual_iface_name = actual_iface_name_c
- .to_str()
- .map_err(|_| TunnelError::InvalidAlias)?
- .to_string();
- unsafe { wgFreePtr(alias_ptr as *mut c_void) };
- actual_iface_name
- };
-
- log::debug!("Adapter alias: {}", actual_iface_name);
-
- let has_ipv6 = config.tunnel.addresses.iter().any(|addr| addr.is_ipv6());
- let setup_handle = tokio::spawn(async move {
- use windows_sys::Win32::NetworkManagement::Ndis::NET_LUID_LH;
- let luid = NET_LUID_LH {
- Value: interface_luid,
- };
- log::debug!("Waiting for tunnel IP interfaces to arrive");
-
- let prepare_interfaces = async move {
- talpid_windows_net::wait_for_interfaces(luid, true, has_ipv6).await?;
-
- if let Err(error) =
- talpid_tunnel::network_interface::initialize_interfaces(luid, None)
- {
- log::error!(
- "{}",
- error.display_chain_with_msg("Failed to set tunnel interface metric"),
- );
- }
-
- Ok(())
- };
-
- let _ = done_tx
- .send(
- prepare_interfaces
- .await
- .map_err(|error| BoxedError::new(TunnelError::SetupIpInterfaces(error))),
- )
- .await;
- log::debug!("Waiting for tunnel IP interfaces: Done");
- });
-
- Ok(WgGoTunnel {
- interface_name: actual_iface_name,
- handle: Some(handle),
- setup_handle,
- _logging_context: logging_context,
- _route_callback_handle: route_callback_handle,
- })
- }
-
- // Callback to be used to rebind the tunnel sockets when the default route changes
- #[cfg(target_os = "windows")]
- pub fn default_route_changed_callback(
- event_type: crate::routing::EventType<'_>,
- address_family: talpid_windows_net::AddressFamily,
- ) {
- use crate::routing::EventType::*;
- use windows_sys::Win32::NetworkManagement::IpHelper::ConvertInterfaceLuidToIndex;
-
- let iface_idx: u32 = match event_type {
- Updated(default_route) => {
- let mut iface_idx = 0u32;
- let iface_luid = default_route.iface;
- let status = unsafe { ConvertInterfaceLuidToIndex(&iface_luid, &mut iface_idx) };
- if status != 0 {
- log::error!(
- "Failed to convert interface LUID to interface index: {}: {}",
- status,
- std::io::Error::last_os_error()
- );
- return;
- }
- iface_idx
- }
- // if there is no new default route, specify 0 as the interface index
- Removed => 0,
- // ignore interface updates that don't affect the interface to use
- UpdatedDetails(_) => return,
- };
-
- unsafe { wgRebindTunnelSocket(address_family.to_af_family(), iface_idx) };
- }
-
- #[cfg(not(target_os = "windows"))]
fn create_tunnel_config(config: &Config, routes: impl Iterator<Item = IpNetwork>) -> TunConfig {
let mut dns_servers = vec![IpAddr::V4(config.ipv4_gateway)];
dns_servers.extend(config.ipv6_gateway.map(IpAddr::V6));
@@ -287,8 +137,6 @@ impl WgGoTunnel {
}
fn stop_tunnel(&mut self) -> Result<()> {
- #[cfg(windows)]
- self.setup_handle.abort();
if let Some(handle) = self.handle.take() {
let status = unsafe { wgTurnOff(handle) };
if status < 0 {
@@ -298,7 +146,6 @@ impl WgGoTunnel {
Ok(())
}
- #[cfg(not(target_os = "windows"))]
fn get_tunnel(
tun_provider: Arc<Mutex<TunProvider>>,
config: &Config,
@@ -355,7 +202,7 @@ impl Tunnel for WgGoTunnel {
let result =
Stats::parse_config_str(config_str.to_str().expect("Go strings are always UTF-8"))
- .map_err(TunnelError::StatsError);
+ .map_err(|error| TunnelError::StatsError(BoxedError::new(error)));
unsafe {
// Zeroing out config string to not leave private key in memory.
let slice = std::slice::from_raw_parts_mut(
@@ -420,12 +267,8 @@ fn check_wg_status(wg_code: i32) -> Result<()> {
}
}
-#[cfg(unix)]
pub type Fd = std::os::unix::io::RawFd;
-pub type LoggingCallback =
- unsafe extern "system" fn(level: WgLogLevel, msg: *const c_char, context: *mut c_void);
-
const ERROR_GENERAL_FAILURE: i32 = -1;
const ERROR_INTERMITTENT_FAILURE: i32 = -2;
@@ -435,12 +278,12 @@ extern "C" {
///
/// Positive return values are tunnel handles for this specific wireguard tunnel instance.
/// Negative return values signify errors. All error codes are opaque.
- #[cfg(not(any(target_os = "android", target_os = "windows")))]
+ #[cfg(not(target_os = "android"))]
fn wgTurnOn(
mtu: isize,
settings: *const i8,
fd: Fd,
- logging_callback: Option<LoggingCallback>,
+ logging_callback: Option<logging::LoggingCallback>,
logging_context: *mut c_void,
) -> i32;
@@ -449,19 +292,7 @@ extern "C" {
fn wgTurnOn(
settings: *const i8,
fd: Fd,
- logging_callback: Option<LoggingCallback>,
- logging_context: *mut c_void,
- ) -> i32;
-
- // Windows
- #[cfg(target_os = "windows")]
- fn wgTurnOn(
- iface_name: *const i8,
- mtu: i64,
- settings: *const i8,
- iface_name_out: *mut *mut c_char,
- iface_luid_out: *mut u64,
- logging_callback: Option<LoggingCallback>,
+ logging_callback: Option<logging::LoggingCallback>,
logging_context: *mut c_void,
) -> i32;
@@ -484,8 +315,147 @@ extern "C" {
// Returns the file descriptor of the tunnel IPv6 socket.
#[cfg(target_os = "android")]
fn wgGetSocketV6(handle: i32) -> Fd;
+}
+
+mod stats {
+ use super::{Stats, StatsMap};
+
+ #[derive(err_derive::Error, Debug, PartialEq)]
+ pub enum Error {
+ #[error(display = "Failed to parse peer pubkey from string \"{}\"", _0)]
+ PubKeyParse(String, #[error(source)] hex::FromHexError),
+
+ #[error(display = "Failed to parse integer from string \"{}\"", _0)]
+ IntParse(String, #[error(source)] std::num::ParseIntError),
+ }
+
+ impl Stats {
+ pub fn parse_config_str(config: &str) -> std::result::Result<StatsMap, Error> {
+ let mut map = StatsMap::new();
+
+ let mut peer = None;
+ let mut tx_bytes = None;
+ let mut rx_bytes = None;
+
+ // parts iterates over keys and values
+ let parts = config.split('\n').filter_map(|line| {
+ let mut pair = line.split('=');
+ let key = pair.next()?;
+ let value = pair.next()?;
+ Some((key, value))
+ });
+
+ for (key, value) in parts {
+ match key {
+ "public_key" => {
+ let mut buffer = [0u8; 32];
+ hex::decode_to_slice(value, &mut buffer)
+ .map_err(|err| Error::PubKeyParse(value.to_string(), err))?;
+ peer = Some(buffer);
+ tx_bytes = None;
+ rx_bytes = None;
+ }
+ "rx_bytes" => {
+ rx_bytes = Some(
+ value
+ .trim()
+ .parse()
+ .map_err(|err| Error::IntParse(value.to_string(), err))?,
+ );
+ }
+ "tx_bytes" => {
+ tx_bytes = Some(
+ value
+ .trim()
+ .parse()
+ .map_err(|err| Error::IntParse(value.to_string(), err))?,
+ );
+ }
+
+ _ => continue,
+ }
+
+ if let (Some(peer_val), Some(tx_bytes_val), Some(rx_bytes_val)) =
+ (peer, tx_bytes, rx_bytes)
+ {
+ map.insert(
+ peer_val,
+ Self {
+ tx_bytes: tx_bytes_val,
+ rx_bytes: rx_bytes_val,
+ },
+ );
+ peer = None;
+ tx_bytes = None;
+ rx_bytes = None;
+ }
+ }
+ Ok(map)
+ }
+ }
+
+ #[cfg(test)]
+ mod test {
+ use super::super::stats::{Error, Stats};
+
+ #[test]
+ fn test_parsing() {
+ let valid_input = "private_key=0000000000000000000000000000000000000000000000000000000000000000\npublic_key=0000000000000000000000000000000000000000000000000000000000000000\npreshared_key=0000000000000000000000000000000000000000000000000000000000000000\nprotocol_version=1\nendpoint=000.000.000.000:00000\nlast_handshake_time_sec=1578420649\nlast_handshake_time_nsec=369416131\ntx_bytes=2740\nrx_bytes=2396\npersistent_keepalive_interval=0\nallowed_ip=0.0.0.0/0\n";
+ let pubkey = [0u8; 32];
+
+ let stats = Stats::parse_config_str(valid_input).expect("Failed to parse valid input");
+ assert_eq!(stats.len(), 1);
+ let actual_keys: Vec<[u8; 32]> = stats.keys().cloned().collect();
+ assert_eq!(actual_keys, [pubkey]);
+ assert_eq!(stats[&pubkey].rx_bytes, 2396);
+ assert_eq!(stats[&pubkey].tx_bytes, 2740);
+ }
+
+ #[test]
+ fn test_parsing_invalid_input() {
+ let invalid_input = "private_key=0000000000000000000000000000000000000000000000000000000000000000\npublic_key=0000000000000000000000000000000000000000000000000000000000000000\npreshared_key=0000000000000000000000000000000000000000000000000000000000000000\nprotocol_version=1\nendpoint=000.000.000.000:00000\nlast_handshake_time_sec=1578420649\nlast_handshake_time_nsec=369416131\ntx_bytes=27error40\npersistent_keepalive_interval=0\nallowed_ip=0.0.0.0/0\n";
+ let invalid_str = "27error40".to_string();
+ let int_err = invalid_str.parse::<u64>().unwrap_err();
+
+ assert_eq!(
+ Stats::parse_config_str(invalid_input),
+ Err(Error::IntParse(invalid_str, int_err))
+ );
+ }
+ }
+}
+
+mod logging {
+ use super::super::logging::{log, LogLevel};
+ use std::ffi::{c_char, c_void};
+
+ // Callback that receives messages from WireGuard
+ pub unsafe extern "system" fn wg_go_logging_callback(
+ level: WgLogLevel,
+ msg: *const c_char,
+ context: *mut c_void,
+ ) {
+ let managed_msg = if !msg.is_null() {
+ std::ffi::CStr::from_ptr(msg).to_string_lossy().to_string()
+ } else {
+ "Logging message from WireGuard is NULL".to_string()
+ };
+
+ let level = match level {
+ WG_GO_LOG_VERBOSE => LogLevel::Verbose,
+ _ => LogLevel::Error,
+ };
+
+ log(context as u32, level, "wireguard-go", &managed_msg);
+ }
+
+ // wireguard-go supports log levels 0 through 3 with 3 being the most verbose
+ // const WG_GO_LOG_SILENT: WgLogLevel = 0;
+ // const WG_GO_LOG_ERROR: WgLogLevel = 1;
+ const WG_GO_LOG_VERBOSE: WgLogLevel = 2;
+
+ pub type WgLogLevel = u32;
- // Rebind tunnel socket when network interfaces change
- #[cfg(target_os = "windows")]
- fn wgRebindTunnelSocket(family: u16, interfaceIndex: u32);
+ pub type LoggingCallback =
+ unsafe extern "system" fn(level: WgLogLevel, msg: *const c_char, context: *mut c_void);
}
diff --git a/talpid-wireguard/src/wireguard_kernel/mod.rs b/talpid-wireguard/src/wireguard_kernel/mod.rs
index 7a64ee3f65..15eaad4c24 100644
--- a/talpid-wireguard/src/wireguard_kernel/mod.rs
+++ b/talpid-wireguard/src/wireguard_kernel/mod.rs
@@ -18,6 +18,7 @@ use std::{ffi::CString, net::IpAddr};
use tokio_stream::StreamExt;
mod parsers;
+mod stats;
pub mod wg_message;
use wg_message::{DeviceMessage, DeviceNla};
diff --git a/talpid-wireguard/src/wireguard_kernel/stats.rs b/talpid-wireguard/src/wireguard_kernel/stats.rs
new file mode 100644
index 0000000000..8604e8243f
--- /dev/null
+++ b/talpid-wireguard/src/wireguard_kernel/stats.rs
@@ -0,0 +1,32 @@
+use super::wg_message::{DeviceMessage, DeviceNla, PeerNla};
+use crate::stats::{Stats, StatsMap};
+
+impl Stats {
+ pub fn parse_device_message(message: &DeviceMessage) -> StatsMap {
+ let mut map = StatsMap::new();
+
+ for nla in &message.nlas {
+ if let DeviceNla::Peers(peers) = nla {
+ for msg in peers {
+ let mut tx_bytes = 0;
+ let mut rx_bytes = 0;
+ let mut pub_key = None;
+
+ for nla in &msg.0 {
+ match nla {
+ PeerNla::TxBytes(bytes) => tx_bytes = *bytes,
+ PeerNla::RxBytes(bytes) => rx_bytes = *bytes,
+ PeerNla::PublicKey(key) => pub_key = Some(*key),
+ _ => continue,
+ }
+ }
+ if let Some(key) = pub_key {
+ map.insert(key, Stats { tx_bytes, rx_bytes });
+ }
+ }
+ }
+ }
+
+ map
+ }
+}
diff --git a/talpid-wireguard/src/wireguard_nt.rs b/talpid-wireguard/src/wireguard_nt.rs
index 00cbeed0a9..1b4405eba2 100644
--- a/talpid-wireguard/src/wireguard_nt.rs
+++ b/talpid-wireguard/src/wireguard_nt.rs
@@ -946,9 +946,9 @@ impl Tunnel for WgNtTunnel {
let (_interface, peers) = device.get_config().map_err(|error| {
log::error!(
"{}",
- error.display_chain_with_msg("Failed to obtain wg-nt tunnel config")
+ error.display_chain_with_msg("Failed to obtain tunnel config")
);
- super::TunnelError::StatsError(super::stats::Error::NoTunnelConfig)
+ super::TunnelError::GetConfigError
})?;
for (peer, _allowed_ips) in &peers {
map.insert(
@@ -961,9 +961,8 @@ impl Tunnel for WgNtTunnel {
}
Ok(map)
} else {
- Err(super::TunnelError::StatsError(
- super::stats::Error::NoTunnelDevice,
- ))
+ log::error!("Failed to obtain tunnel stats as device no longer exists");
+ Err(super::TunnelError::GetConfigError)
}
}
@@ -1027,7 +1026,6 @@ mod tests {
ipv4_gateway: "0.0.0.0".parse().unwrap(),
ipv6_gateway: None,
mtu: 0,
- use_wireguard_nt: true,
obfuscator_config: None,
});
diff --git a/wireguard/build-wireguard-go.sh b/wireguard/build-wireguard-go.sh
index f800634f73..ebf0d2e33f 100755
--- a/wireguard/build-wireguard-go.sh
+++ b/wireguard/build-wireguard-go.sh
@@ -26,47 +26,6 @@ function is_docker_build {
return 0
}
-
-function win_deduce_lib_executable_path {
- msbuild_path="$(which msbuild.exe)"
- msbuild_dir=$(dirname "$msbuild_path")
- find "$msbuild_dir/../../../../" -name "lib.exe" | \
- grep -i "hostx64/x64" | \
- head -n1
-}
-
-function win_gather_export_symbols {
- grep -Eo "\/\/export \w+" libwg.go libwg_windows.go | cut -d' ' -f2
-}
-
-function win_create_lib_file {
- echo "LIBRARY libwg" > exports.def
- echo "EXPORTS" >> exports.def
-
- for symbol in $(win_gather_export_symbols); do
- printf "\t%s\n" "$symbol" >> exports.def
- done
-
- lib_path="$(win_deduce_lib_executable_path)"
- "$lib_path" \
- "/def:exports.def" \
- "/out:libwg.lib" \
- "/machine:X64"
-
-}
-
-function build_windows {
- echo "Building wireguard-go for Windows"
- pushd libwg
- go build -v -o libwg.dll -buildmode c-shared
- win_create_lib_file
-
- target_dir=../../build/lib/x86_64-pc-windows-msvc/
- mkdir -p $target_dir
- mv libwg.dll libwg.lib $target_dir
- popd
-}
-
function unix_target_triple {
local platform="$(uname -s)"
if [[ ("${platform}" == "Linux") ]]; then
@@ -144,7 +103,10 @@ function build_wireguard_go {
local platform="$(uname -s)";
case "$platform" in
Linux*|Darwin*) build_unix ${1:-$(unix_target_triple)};;
- MINGW*|MSYS_NT*) build_windows;;
+ *)
+ echo "Unsupported platform"
+ return 1
+ ;;
esac
}
diff --git a/wireguard/libwg/README.md b/wireguard/libwg/README.md
index e5b96928f7..39ad48e3e0 100644
--- a/wireguard/libwg/README.md
+++ b/wireguard/libwg/README.md
@@ -7,7 +7,6 @@ It currently offers support for the following platforms:
- Linux
- macOS
- Android
-- Windows
# Organization
@@ -17,8 +16,6 @@ It currently offers support for the following platforms:
`libwg_android.go` has code specifically for Android.
-`libwg_windows.go` has code specifically for Windows.
-
# Usage
Call `wgTurnOn` to create and activate a tunnel. The prototype is different on different platforms, see the code for details.
diff --git a/wireguard/libwg/go.mod b/wireguard/libwg/go.mod
index 27f48a3d06..fb74c9beb8 100644
--- a/wireguard/libwg/go.mod
+++ b/wireguard/libwg/go.mod
@@ -5,11 +5,9 @@ go 1.18
require (
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478
- golang.zx2c4.com/wireguard/windows v0.5.3
)
require (
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.0.0-20220809184613-07c6da5e1ced // indirect
- golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
)
diff --git a/wireguard/libwg/go.sum b/wireguard/libwg/go.sum
index d1f125b01c..3907746df4 100644
--- a/wireguard/libwg/go.sum
+++ b/wireguard/libwg/go.sum
@@ -4,9 +4,5 @@ golang.org/x/net v0.0.0-20220809184613-07c6da5e1ced h1:3dYNDff0VT5xj+mbj2XucFst9
golang.org/x/net v0.0.0-20220809184613-07c6da5e1ced/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664 h1:v1W7bwXHsnLLloWYTVEdvGvA7BHMeBYsPcF0GLDxIRs=
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
-golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
-golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
-golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
diff --git a/wireguard/libwg/interfacewatcher/interfacewatcher_windows.go b/wireguard/libwg/interfacewatcher/interfacewatcher_windows.go
deleted file mode 100644
index fcb53b8584..0000000000
--- a/wireguard/libwg/interfacewatcher/interfacewatcher_windows.go
+++ /dev/null
@@ -1,123 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- * Copyright (C) 2021 Mullvad VPN AB. All Rights Reserved.
- */
-
-package interfacewatcher
-
-import (
- "sync"
- "time"
-
- "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
-)
-
-type Event struct {
- Luid winipcfg.LUID
- Family winipcfg.AddressFamily
-}
-
-type interfaceWatcher struct {
- ready chan bool
- processingMutex sync.Mutex
- interfaceChangeCallback *winipcfg.InterfaceChangeCallback
- seenEvents []Event
- wantedEvents []Event
- expired bool
-}
-
-func NewWatcher() (*interfaceWatcher, error) {
- iw := &interfaceWatcher{
- ready: make(chan bool, 1),
- expired: false,
- }
- var err error
- iw.interfaceChangeCallback, err = winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
- if notificationType != winipcfg.MibAddInstance {
- return
- }
-
- iw.processingMutex.Lock()
- defer iw.processingMutex.Unlock()
-
- if iw.expired {
- return
- }
-
- iw.seenEvents = append(iw.seenEvents, Event{iface.InterfaceLUID, iface.Family})
-
- if len(iw.wantedEvents) != 0 {
- iw.evaluateEvents()
- }
- })
- if err != nil {
- return nil, err
- }
- return iw, nil
-}
-
-func (iw *interfaceWatcher) evaluateEvents() {
- matched := 0
-
- // This is n*n, but typically very few items in both slices :-)
- for _, wanted := range iw.wantedEvents {
- for _, seen := range iw.seenEvents {
- if seen == wanted {
- matched += 1
- break
- }
- }
- }
-
- if len(iw.wantedEvents) != matched {
- return
- }
-
- iw.expired = true
- iw.ready <- true
-}
-
-// You can only join() once after which the watcher becomes expired.
-func (iw *interfaceWatcher) Join(wantedEvents []Event, timeoutSeconds int) bool {
- {
- iw.processingMutex.Lock()
-
- if iw.expired || len(wantedEvents) == 0 {
- iw.processingMutex.Unlock()
- return false
- }
-
- iw.wantedEvents = wantedEvents
- iw.evaluateEvents()
-
- iw.processingMutex.Unlock()
- }
-
- result := false
-
- select {
- case <- iw.ready:
- result = true
- case <- time.After(time.Duration(timeoutSeconds) * time.Second):
- result = false
- }
-
- {
- iw.processingMutex.Lock()
-
- iw.wantedEvents = nil
- iw.expired = true
-
- iw.processingMutex.Unlock()
- }
-
- return result
-}
-
-func (iw *interfaceWatcher) Destroy() {
- if iw.interfaceChangeCallback != nil {
- iw.interfaceChangeCallback.Unregister()
- iw.interfaceChangeCallback = nil
- }
-}
diff --git a/wireguard/libwg/libwg_windows.go b/wireguard/libwg/libwg_windows.go
deleted file mode 100644
index a1dc4fd265..0000000000
--- a/wireguard/libwg/libwg_windows.go
+++ /dev/null
@@ -1,132 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0
- *
- * Copyright (C) 2017-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
- * Copyright (C) 2021 Mullvad VPN AB. All Rights Reserved.
- */
-
-package main
-
-// #include <stdlib.h>
-import "C"
-
-import (
- "bufio"
- "strings"
- "unsafe"
-
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/device"
- "golang.zx2c4.com/wireguard/tun"
-
- "github.com/mullvad/mullvadvpn-app/wireguard/libwg/logging"
- "github.com/mullvad/mullvadvpn-app/wireguard/libwg/tunnelcontainer"
-)
-
-// 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
-type LogContext = unsafe.Pointer
-
-//export wgTurnOn
-func wgTurnOn(cIfaceName *C.char, mtu int, cSettings *C.char, cIfaceNameOut **C.char, cLuidOut *uint64, logSink LogSink, logContext LogContext) int32 {
- logger := logging.NewLogger(logSink, logContext)
- if cIfaceNameOut != nil {
- *cIfaceNameOut = nil
- }
-
- if cIfaceName == nil {
- logger.Errorf("cIfaceName is null\n")
- return ERROR_GENERAL_FAILURE
- }
-
- if cSettings == nil {
- logger.Errorf("cSettings is null\n")
- return ERROR_GENERAL_FAILURE
- }
-
- settings := C.GoString(cSettings)
- ifaceName := C.GoString(cIfaceName)
-
- // {AFE43773-E1F8-4EBB-8536-576AB86AFE9A}
- networkId := windows.GUID{0xafe43773, 0xe1f8, 0x4ebb, [8]byte{0x85, 0x36, 0x57, 0x6a, 0xb8, 0x6a, 0xfe, 0x9a}}
-
- tun.WintunTunnelType = "Mullvad"
-
- wintun, err := tun.CreateTUNWithRequestedGUID(ifaceName, &networkId, mtu)
- if err != nil {
- logger.Errorf("Failed to create tunnel\n")
- logger.Errorf("%s\n", err)
- return ERROR_INTERMITTENT_FAILURE
- }
-
- nativeTun := wintun.(*tun.NativeTun)
-
- actualInterfaceName, err := nativeTun.Name()
- if err != nil {
- nativeTun.Close()
- logger.Errorf("Failed to determine name of wintun adapter\n")
- return ERROR_GENERAL_FAILURE
- }
- if actualInterfaceName != ifaceName {
- // WireGuard picked a different name for the adapter than the one we expected.
- // This indicates there is already an adapter with the name we intended to use.
- logger.Verbosef("Failed to create adapter with specific name\n")
- }
-
- device := device.NewDevice(wintun, conn.NewDefaultBind(), logger)
-
- setError := device.IpcSetOperation(bufio.NewReader(strings.NewReader(settings)))
- if setError != nil {
- logger.Errorf("Failed to set device configuration\n")
- logger.Errorf("%s\n", setError)
- device.Close()
- return ERROR_GENERAL_FAILURE
- }
-
- device.Up()
-
- context := tunnelcontainer.Context{
- Device: device,
- Logger: logger,
- }
-
- handle, err := tunnels.Insert(context)
- if err != nil {
- logger.Errorf("%s\n", err)
- device.Close()
- return ERROR_GENERAL_FAILURE
- }
-
- if cIfaceNameOut != nil {
- *cIfaceNameOut = C.CString(actualInterfaceName)
- }
- if cLuidOut != nil {
- *cLuidOut = nativeTun.LUID()
- }
-
- return handle
-}
-
-//export wgRebindTunnelSocket
-func wgRebindTunnelSocket(family uint16, interfaceIndex uint32) {
- tunnels.ForEach(func(tunnel tunnelcontainer.Context) {
- blackhole := (interfaceIndex == 0)
- bind := tunnel.Device.Bind().(conn.BindSocketToInterface)
-
- if family == windows.AF_INET {
- tunnel.Logger.Verbosef("Binding v4 socket to interface %d (blackhole=%v)\n", interfaceIndex, blackhole)
- err := bind.BindSocketToInterface4(interfaceIndex, blackhole)
- if err != nil {
- tunnel.Logger.Verbosef("%s\n", err)
- }
- } else if family == windows.AF_INET6 {
- tunnel.Logger.Verbosef("Binding v6 socket to interface %d (blackhole=%v)\n", interfaceIndex, blackhole)
- err := bind.BindSocketToInterface6(interfaceIndex, blackhole)
- if err != nil {
- tunnel.Logger.Verbosef("%s\n", err)
- }
- }
- })
-}