summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-06-11 01:00:35 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-06-11 01:00:35 -0300
commit14d227892a2e5de8045ec185188a69ad7ada8813 (patch)
tree9ffd9efb92a1ddd5528514b614e01674378fb21c
parenta265fc596b7b2fca79592b494d6e3a55034bfbe2 (diff)
parent76de34848a130d44831d5e57ddb56f13fb570bea (diff)
downloadmullvadvpn-14d227892a2e5de8045ec185188a69ad7ada8813.tar.xz
mullvadvpn-14d227892a2e5de8045ec185188a69ad7ada8813.zip
Merge branch 'wireguard-on-android'
-rw-r--r--android/build.gradle7
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt2
m---------dist-assets/binaries0
-rw-r--r--mullvad-jni/src/into_java.rs18
-rw-r--r--talpid-core/build.rs19
-rw-r--r--talpid-core/src/tunnel/mod.rs41
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs5
-rw-r--r--talpid-core/src/tunnel/wireguard/ping_monitor.rs39
-rw-r--r--talpid-core/src/tunnel/wireguard/wireguard_go.rs38
9 files changed, 114 insertions, 55 deletions
diff --git a/android/build.gradle b/android/build.gradle
index d511691624..914ee21e88 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -46,6 +46,7 @@ android {
variant.ndkCompileProvider.configure {
dependsOn copyMullvadJni
+ dependsOn copyWireguardGo
}
}
}
@@ -99,6 +100,12 @@ task copyMullvadJni(type: Copy) {
into "$extraJniDirectory/arm64-v8a"
}
+task copyWireguardGo(type: Copy) {
+ from "$repoRootPath/dist-assets/binaries/android"
+ include 'libwg.so'
+ into "$extraJniDirectory/arm64-v8a"
+}
+
task copyApiRootCertificate(type: Copy) {
from "$repoRootPath/dist-assets"
include "api_root_ca.pem"
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
index dcd4935ee4..ec71738ef2 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
@@ -66,7 +66,7 @@ class MullvadVpnService(val context: Context) {
}
for (route in config.routes) {
- addRoute(route.address, route.prefixLength as Int)
+ addRoute(route.address, route.prefixLength.toInt())
}
setMtu(config.mtu)
diff --git a/dist-assets/binaries b/dist-assets/binaries
-Subproject 5569328323fc1c1a7352861602029da149b1745
+Subproject c79a133c850e05f588000e5e45f6909607b4176
diff --git a/mullvad-jni/src/into_java.rs b/mullvad-jni/src/into_java.rs
index 1ab7cd54e6..06116d8c3b 100644
--- a/mullvad-jni/src/into_java.rs
+++ b/mullvad-jni/src/into_java.rs
@@ -196,10 +196,22 @@ impl<'env> IntoJava<'env> for TunConfig {
fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType {
let class = get_class("net/mullvad/mullvadvpn/model/TunConfig");
let addresses = env.auto_local(self.addresses.into_java(env));
- let parameters = [JValue::Object(addresses.as_obj())];
+ let dns_servers = env.auto_local(self.dns_servers.into_java(env));
+ let routes = env.auto_local(self.routes.into_java(env));
+ let mtu = self.mtu as jint;
+ let parameters = [
+ JValue::Object(addresses.as_obj()),
+ JValue::Object(dns_servers.as_obj()),
+ JValue::Object(routes.as_obj()),
+ JValue::Int(mtu),
+ ];
- env.new_object(&class, "(Ljava/util/List;)V", &parameters)
- .expect("Failed to create TunConfig Java object")
+ env.new_object(
+ &class,
+ "(Ljava/util/List;Ljava/util/List;Ljava/util/List;I)V",
+ &parameters,
+ )
+ .expect("Failed to create TunConfig Java object")
}
}
diff --git a/talpid-core/build.rs b/talpid-core/build.rs
index 4741a440d0..b494703653 100644
--- a/talpid-core/build.rs
+++ b/talpid-core/build.rs
@@ -57,13 +57,20 @@ fn main() {
#[cfg(not(windows))]
fn main() {
- let lib_dir = if cfg!(target_os = "macos") {
- manifest_dir().join("../dist-assets/binaries/macos")
- } else {
- manifest_dir().join("../dist-assets/binaries/linux")
+ let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS not set");
+
+ let link_type = match target_os.as_str() {
+ "android" => "",
+ "linux" | "macos" => "=static",
+ _ => panic!("Unsupported platform: {}", target_os),
};
- println!("cargo:rustc-link-search={}", &lib_dir.display());
- println!("cargo:rustc-link-lib=static=wg");
+
+ let lib_dir = manifest_dir()
+ .join("../dist-assets/binaries")
+ .join(target_os);
+
+ println!("cargo:rustc-link-search={}", lib_dir.display());
+ println!("cargo:rustc-link-lib{}=wg", link_type);
}
fn manifest_dir() -> PathBuf {
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index 62bc165ed6..a8c601b724 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -9,7 +9,7 @@ use std::{
};
#[cfg(not(target_os = "android"))]
use talpid_types::net::openvpn as openvpn_types;
-#[cfg(any(target_os = "linux", target_os = "macos"))]
+#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
use talpid_types::net::wireguard as wireguard_types;
use talpid_types::net::{GenericTunnelOptions, TunnelParameters};
@@ -17,7 +17,7 @@ use talpid_types::net::{GenericTunnelOptions, TunnelParameters};
#[cfg(not(target_os = "android"))]
pub mod openvpn;
-#[cfg(any(target_os = "linux", target_os = "macos"))]
+#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
pub mod wireguard;
/// A module for low level platform specific tunnel device management.
@@ -45,7 +45,7 @@ pub enum Error {
RotateLogError(#[error(cause)] crate::logging::RotateLogError),
/// Failure to build Wireguard configuration.
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
#[error(display = "Failed to configure Wireguard with the given parameters")]
WireguardConfigError(#[error(cause)] self::wireguard::config::Error),
@@ -55,7 +55,7 @@ pub enum Error {
OpenVpnTunnelMonitoringError(#[error(cause)] openvpn::Error),
/// There was an error listening for events from the Wireguard tunnel
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
#[error(display = "Failed while listening for events from the Wireguard tunnel")]
WirguardTunnelMonitoringError(#[error(cause)] wireguard::Error),
}
@@ -158,18 +158,19 @@ impl TunnelMonitor {
TunnelParameters::OpenVpn(config) => {
Self::start_openvpn_tunnel(&config, log_file, resource_dir, on_event)
}
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(target_os = "android")]
+ TunnelParameters::OpenVpn(_) => Err(Error::UnsupportedPlatform),
+
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
TunnelParameters::Wireguard(config) => {
Self::start_wireguard_tunnel(&config, log_file, on_event, tun_provider)
}
- #[cfg(target_os = "android")]
- TunnelParameters::OpenVpn(_) => Err(Error::UnsupportedPlatform),
- #[cfg(any(windows, target_os = "android"))]
+ #[cfg(windows)]
TunnelParameters::Wireguard(_) => Err(Error::UnsupportedPlatform),
}
}
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
fn start_wireguard_tunnel<L>(
params: &wireguard_types::TunnelParameters,
log: Option<PathBuf>,
@@ -252,7 +253,7 @@ pub enum CloseHandle {
#[cfg(not(target_os = "android"))]
/// OpenVpn close handle
OpenVpn(openvpn::OpenVpnCloseHandle),
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
/// Wireguard close handle
Wireguard(wireguard::CloseHandle),
}
@@ -260,13 +261,10 @@ pub enum CloseHandle {
impl CloseHandle {
/// Closes the underlying tunnel, making the `TunnelMonitor::wait` method return.
pub fn close(self) -> io::Result<()> {
- #[cfg(target_os = "android")]
- unimplemented!();
-
- #[cfg(not(target_os = "android"))]
match self {
+ #[cfg(not(target_os = "android"))]
CloseHandle::OpenVpn(handle) => handle.close(),
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
CloseHandle::Wireguard(mut handle) => {
handle.close();
Ok(())
@@ -278,28 +276,25 @@ impl CloseHandle {
enum InternalTunnelMonitor {
#[cfg(not(target_os = "android"))]
OpenVpn(openvpn::OpenVpnMonitor),
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
Wireguard(wireguard::WireguardMonitor),
}
impl InternalTunnelMonitor {
fn close_handle(&self) -> CloseHandle {
- #[cfg(not(target_os = "android"))]
match self {
+ #[cfg(not(target_os = "android"))]
InternalTunnelMonitor::OpenVpn(tun) => CloseHandle::OpenVpn(tun.close_handle()),
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
InternalTunnelMonitor::Wireguard(tun) => CloseHandle::Wireguard(tun.close_handle()),
}
-
- #[cfg(target_os = "android")]
- unimplemented!();
}
fn wait(self) -> Result<()> {
- #[cfg(not(target_os = "android"))]
match self {
+ #[cfg(not(target_os = "android"))]
InternalTunnelMonitor::OpenVpn(tun) => tun.wait()?,
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
InternalTunnelMonitor::Wireguard(tun) => tun.wait()?,
}
diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs
index 36d0f9d61b..810aadff49 100644
--- a/talpid-core/src/tunnel/wireguard/mod.rs
+++ b/talpid-core/src/tunnel/wireguard/mod.rs
@@ -44,6 +44,11 @@ pub enum Error {
#[error(display = "Invalid tunnel interface name")]
InterfaceNameError(#[error(cause)] std::ffi::NulError),
+ /// Failed to configure Wireguard sockets to bypass the tunnel.
+ #[cfg(target_os = "android")]
+ #[error(display = "Failed to configure Wireguard sockets to bypass the tunnel")]
+ BypassError(#[error(cause)] BoxedError),
+
/// Pinging timed out.
#[error(display = "Ping timed out")]
PingTimeoutError,
diff --git a/talpid-core/src/tunnel/wireguard/ping_monitor.rs b/talpid-core/src/tunnel/wireguard/ping_monitor.rs
index 69f22fc83f..89b13ee637 100644
--- a/talpid-core/src/tunnel/wireguard/ping_monitor.rs
+++ b/talpid-core/src/tunnel/wireguard/ping_monitor.rs
@@ -48,30 +48,29 @@ fn ping_cmd(
interface: &str,
exit_on_first_reply: bool,
) -> duct::Expression {
- let interface_flag = if cfg!(target_os = "linux") {
- "-I"
- } else {
- "-b"
- };
- let timeout_flag = if cfg!(target_os = "linux") {
+ let mut args = vec!["-n", "-i", "1"];
+
+ let timeout_flag = if cfg!(target_os = "linux") || cfg!(target_os = "android") {
"-w"
} else {
"-t"
};
-
let timeout_secs = timeout_secs.to_string();
- let ip = ip.to_string();
- let mut args = vec![
- "-n",
- "-i",
- "1",
- &interface_flag,
- &interface,
- timeout_flag,
- &timeout_secs,
- &ip,
- ];
+ args.extend_from_slice(&[timeout_flag, &timeout_secs]);
+
+ let interface_flag = if cfg!(target_os = "linux") {
+ Some("-I")
+ } else if cfg!(target_os = "macos") {
+ Some("-b")
+ } else {
+ None
+ };
+
+ if let Some(interface_flag) = interface_flag {
+ args.extend_from_slice(&[interface_flag, interface]);
+ }
+
if exit_on_first_reply {
if cfg!(target_os = "macos") {
args.push("-o");
@@ -79,6 +78,10 @@ fn ping_cmd(
args.extend_from_slice(&["-c", "1"])
}
}
+
+ let ip = ip.to_string();
+ args.push(&ip);
+
duct::cmd("ping", args)
.stdin_null()
.stdout_null()
diff --git a/talpid-core/src/tunnel/wireguard/wireguard_go.rs b/talpid-core/src/tunnel/wireguard/wireguard_go.rs
index eca00b76bc..f72371eb11 100644
--- a/talpid-core/src/tunnel/wireguard/wireguard_go.rs
+++ b/talpid-core/src/tunnel/wireguard/wireguard_go.rs
@@ -2,6 +2,8 @@ use super::{Config, Error, Result, Tunnel};
use crate::tunnel::tun_provider::{Tun, TunConfig, TunProvider};
use ipnetwork::IpNetwork;
use std::{ffi::CString, fs, net::IpAddr, os::unix::io::AsRawFd, path::Path};
+#[cfg(target_os = "android")]
+use talpid_types::BoxedError;
pub struct WgGoTunnel {
interface_name: String,
@@ -19,7 +21,8 @@ impl WgGoTunnel {
tun_provider: &dyn TunProvider,
routes: impl Iterator<Item = IpNetwork>,
) -> Result<Self> {
- let tunnel_device = tun_provider
+ #[cfg_attr(not(target_os = "android"), allow(unused_mut))]
+ let mut tunnel_device = tun_provider
.create_tun(Self::create_tunnel_config(config, routes))
.map_err(Error::SetupTunnelDeviceError)?;
@@ -32,9 +35,9 @@ impl WgGoTunnel {
let handle = unsafe {
wgTurnOnWithFd(
- iface_name.as_ptr(),
+ iface_name.as_ptr() as *const i8,
config.mtu as i64,
- wg_config_str.as_ptr(),
+ wg_config_str.as_ptr() as *const i8,
tunnel_device.as_raw_fd(),
log_file.as_raw_fd(),
WG_GO_LOG_DEBUG,
@@ -45,6 +48,9 @@ impl WgGoTunnel {
return Err(Error::StartWireguardError { status: handle });
}
+ #[cfg(target_os = "android")]
+ Self::bypass_tunnel_sockets(&mut tunnel_device, handle).map_err(Error::BypassError)?;
+
Ok(WgGoTunnel {
interface_name,
handle: Some(handle),
@@ -65,6 +71,20 @@ impl WgGoTunnel {
}
}
+ #[cfg(target_os = "android")]
+ fn bypass_tunnel_sockets(
+ tunnel_device: &mut Box<dyn Tun>,
+ handle: i32,
+ ) -> std::result::Result<(), BoxedError> {
+ let socket_v4 = unsafe { wgGetSocketV4(handle) };
+ let socket_v6 = unsafe { wgGetSocketV6(handle) };
+
+ tunnel_device.bypass(socket_v4)?;
+ tunnel_device.bypass(socket_v6)?;
+
+ Ok(())
+ }
+
fn stop_tunnel(&mut self) -> Result<()> {
if let Some(handle) = self.handle.take() {
let status = unsafe { wgTurnOff(handle) };
@@ -108,7 +128,8 @@ type WgLogLevel = i32;
// wireguard-go supports log levels 0 through 3 with 3 being the most verbose
const WG_GO_LOG_DEBUG: WgLogLevel = 3;
-#[link(name = "wg", kind = "static")]
+#[cfg_attr(target_os = "android", link(name = "wg", kind = "dylib"))]
+#[cfg_attr(not(target_os = "android"), link(name = "wg", kind = "static"))]
extern "C" {
// Creates a new wireguard tunnel, uses the specific interface name, MTU and file descriptors
// for the tunnel device and logging.
@@ -123,6 +144,15 @@ extern "C" {
log_fd: Fd,
logLevel: WgLogLevel,
) -> i32;
+
// Pass a handle that was created by wgTurnOnWithFd to stop a wireguard tunnel.
fn wgTurnOff(handle: i32) -> i32;
+
+ // Returns the file descriptor of the tunnel IPv4 socket.
+ #[cfg(target_os = "android")]
+ fn wgGetSocketV4(handle: i32) -> Fd;
+
+ // Returns the file descriptor of the tunnel IPv6 socket.
+ #[cfg(target_os = "android")]
+ fn wgGetSocketV6(handle: i32) -> Fd;
}