summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-12-04 10:28:41 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-12-04 10:28:41 -0300
commit26981772fb092e9865d14b9a0dc70d7a52481cf4 (patch)
treeb64ff66d00ced9fe0bb3c3e9afbf5cb136767a09
parent0ce5d9d70ab5e7779be8cd201526689231eb1ea5 (diff)
parent9b263846b9a7774b4a98404d2419f363b98e2586 (diff)
downloadmullvadvpn-26981772fb092e9865d14b9a0dc70d7a52481cf4.tar.xz
mullvadvpn-26981772fb092e9865d14b9a0dc70d7a52481cf4.zip
Merge branch 'custom-dns-on-android'
-rw-r--r--Cargo.lock8
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt68
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt5
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceConnection.kt1
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt5
-rw-r--r--mullvad-daemon/src/lib.rs12
-rw-r--r--mullvad-daemon/src/settings.rs5
-rw-r--r--mullvad-jni/Cargo.toml2
-rw-r--r--mullvad-jni/src/classes.rs1
-rw-r--r--mullvad-jni/src/daemon_interface.rs10
-rw-r--r--mullvad-jni/src/lib.rs27
-rw-r--r--mullvad-types/Cargo.toml2
-rw-r--r--mullvad-types/src/settings/mod.rs8
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/tunnel/tun_provider/android/mod.rs46
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs49
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs9
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs7
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnecting_state.rs9
-rw-r--r--talpid-core/src/tunnel_state_machine/error_state.rs8
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs39
-rw-r--r--talpid-types/Cargo.toml2
27 files changed, 262 insertions, 81 deletions
diff --git a/Cargo.lock b/Cargo.lock
index de0f19a4aa..6c4168a3a9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -999,9 +999,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jnix"
-version = "0.2.3"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6354ae923ca4df982181ae2cd77eb4214f8c11d11d0c0cd8606c9347ac2abc57"
+checksum = "1c610361550ad147bf2d7ddf71b67035706759ebf6f503cc6cbe4a581004de8a"
dependencies = [
"jni",
"jnix-macros",
@@ -1011,9 +1011,9 @@ dependencies = [
[[package]]
name = "jnix-macros"
-version = "0.2.3"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c78132fe420156f13b30518fcda9449b0ab8ae3b5584e8a1c53ce390fe770b44"
+checksum = "13e87ff0edc1c5199f084e3175e9a3f5ee2bb56035403b685d0ec8edd5157250"
dependencies = [
"heck",
"proc-macro2",
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt
new file mode 100644
index 0000000000..e4d7b75481
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt
@@ -0,0 +1,6 @@
+package net.mullvad.mullvadvpn.model
+
+import java.net.InetAddress
+import java.util.ArrayList
+
+data class DnsOptions(val custom: Boolean, val addresses: ArrayList<InetAddress>)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt
index 7579a469ca..7e3bdef2b3 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt
@@ -2,4 +2,4 @@ package net.mullvad.mullvadvpn.model
import net.mullvad.talpid.net.wireguard.TunnelOptions as WireguardTunnelOptions
-data class TunnelOptions(val wireguard: WireguardTunnelOptions)
+data class TunnelOptions(val wireguard: WireguardTunnelOptions, val dnsOptions: DnsOptions)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt
new file mode 100644
index 0000000000..95a4be3cb9
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt
@@ -0,0 +1,68 @@
+package net.mullvad.mullvadvpn.service
+
+import java.net.InetAddress
+import java.util.ArrayList
+import kotlin.properties.Delegates.observable
+import net.mullvad.mullvadvpn.model.DnsOptions
+import net.mullvad.talpid.util.EventNotifier
+
+class CustomDns(val daemon: MullvadDaemon, val settingsListener: SettingsListener) {
+ private var enabled by observable(false) { _, oldValue, newValue ->
+ if (oldValue != newValue) {
+ onEnabledChanged.notify(newValue)
+ }
+ }
+
+ private var dnsServers by observable<ArrayList<InetAddress>>(ArrayList()) { _, _, servers ->
+ onDnsServersChanged.notify(servers.toList())
+ }
+
+ val onEnabledChanged = EventNotifier(false)
+ val onDnsServersChanged = EventNotifier<List<InetAddress>>(emptyList())
+
+ init {
+ settingsListener.dnsOptionsNotifier.subscribe(this) { dnsOptions ->
+ enabled = dnsOptions.custom
+ dnsServers = ArrayList(dnsOptions.addresses)
+ }
+ }
+
+ fun onDestroy() {
+ settingsListener.dnsOptionsNotifier.unsubscribe(this)
+ }
+
+ fun enable() {
+ synchronized(this) {
+ changeDnsOptions(true, dnsServers)
+ }
+ }
+
+ fun disable() {
+ synchronized(this) {
+ changeDnsOptions(false, dnsServers)
+ }
+ }
+
+ fun addDnsServer(server: InetAddress) {
+ synchronized(this) {
+ if (!dnsServers.contains(server)) {
+ dnsServers.add(server)
+ changeDnsOptions(enabled, dnsServers)
+ }
+ }
+ }
+
+ fun removeDnsServer(server: InetAddress) {
+ synchronized(this) {
+ if (dnsServers.remove(server)) {
+ changeDnsOptions(enabled, dnsServers)
+ }
+ }
+ }
+
+ private fun changeDnsOptions(enable: Boolean, dnsServers: ArrayList<InetAddress>) {
+ val options = DnsOptions(enable, dnsServers)
+
+ daemon.setDnsOptions(options)
+ }
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
index 838fe80c31..083568f726 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn.service
import net.mullvad.mullvadvpn.model.AppVersionInfo
+import net.mullvad.mullvadvpn.model.DnsOptions
import net.mullvad.mullvadvpn.model.GeoIpLocation
import net.mullvad.mullvadvpn.model.GetAccountDataResult
import net.mullvad.mullvadvpn.model.KeygenEvent
@@ -106,6 +107,10 @@ class MullvadDaemon(val vpnService: MullvadVpnService) {
setAutoConnect(daemonInterfaceAddress, autoConnect)
}
+ fun setDnsOptions(dnsOptions: DnsOptions) {
+ setDnsOptions(daemonInterfaceAddress, dnsOptions)
+ }
+
fun setWireguardMtu(wireguardMtu: Int?) {
setWireguardMtu(daemonInterfaceAddress, wireguardMtu)
}
@@ -158,6 +163,7 @@ class MullvadDaemon(val vpnService: MullvadVpnService) {
private external fun setAccount(daemonInterfaceAddress: Long, accountToken: String?)
private external fun setAllowLan(daemonInterfaceAddress: Long, allowLan: Boolean)
private external fun setAutoConnect(daemonInterfaceAddress: Long, alwaysOn: Boolean)
+ private external fun setDnsOptions(daemonInterfaceAddress: Long, dnsOptions: DnsOptions)
private external fun setWireguardMtu(daemonInterfaceAddress: Long, wireguardMtu: Int?)
private external fun shutdown(daemonInterfaceAddress: Long)
private external fun submitVoucher(
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
index be49d3723c..1b31605adc 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
@@ -226,6 +226,7 @@ class MullvadVpnService : TalpidVpnService() {
private suspend fun setUpInstance(daemon: MullvadDaemon, settings: Settings) {
val settingsListener = SettingsListener(daemon, settings)
val connectionProxy = ConnectionProxy(this, daemon)
+ val customDns = CustomDns(daemon, settingsListener)
val splitTunneling = splitTunneling.await()
splitTunneling.onChange = { excludedApps ->
@@ -241,6 +242,7 @@ class MullvadVpnService : TalpidVpnService() {
daemon,
connectionProxy,
connectivityListener,
+ customDns,
settingsListener,
splitTunneling
)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt
index 5ef94a4f5c..135ea9ef28 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt
@@ -6,6 +6,7 @@ class ServiceInstance(
val daemon: MullvadDaemon,
val connectionProxy: ConnectionProxy,
val connectivityListener: ConnectivityListener,
+ val customDns: CustomDns,
val settingsListener: SettingsListener,
val splitTunneling: SplitTunneling
) {
@@ -16,6 +17,7 @@ class ServiceInstance(
fun onDestroy() {
accountCache.onDestroy()
connectionProxy.onDestroy()
+ customDns.onDestroy()
keyStatusListener.onDestroy()
locationInfoCache.onDestroy()
settingsListener.onDestroy()
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt
index 17af7022a8..5ffe9a1a2f 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt
@@ -14,6 +14,7 @@ class SettingsListener(val daemon: MullvadDaemon, val initialSettings: Settings)
private val settingsNotifier: EventNotifier<Settings> = EventNotifier(settings)
val accountNumberNotifier = EventNotifier(initialSettings.accountToken)
+ val dnsOptionsNotifier = EventNotifier(initialSettings.tunnelOptions.dnsOptions)
var onRelaySettingsChange: ((RelaySettings?) -> Unit)? = null
set(value) {
@@ -50,6 +51,10 @@ class SettingsListener(val daemon: MullvadDaemon, val initialSettings: Settings)
accountNumberNotifier.notify(newSettings.accountToken)
}
+ if (settings.tunnelOptions.dnsOptions != newSettings.tunnelOptions.dnsOptions) {
+ dnsOptionsNotifier.notify(newSettings.tunnelOptions.dnsOptions)
+ }
+
if (settings.relaySettings != newSettings.relaySettings) {
onRelaySettingsChange?.invoke(newSettings.relaySettings)
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceConnection.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceConnection.kt
index 88de95d04a..33e1698b15 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceConnection.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceConnection.kt
@@ -9,6 +9,7 @@ class ServiceConnection(private val service: ServiceInstance, val mainActivity:
val accountCache = service.accountCache
val connectionProxy = service.connectionProxy
val connectivityListener = service.connectivityListener
+ val customDns = service.customDns
val keyStatusListener = service.keyStatusListener
val locationInfoCache = service.locationInfoCache
val settingsListener = service.settingsListener
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt
index 7f84f09008..1e1ba969ed 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt
@@ -9,6 +9,7 @@ import net.mullvad.mullvadvpn.dataproxy.AppVersionInfoCache
import net.mullvad.mullvadvpn.dataproxy.RelayListListener
import net.mullvad.mullvadvpn.service.AccountCache
import net.mullvad.mullvadvpn.service.ConnectionProxy
+import net.mullvad.mullvadvpn.service.CustomDns
import net.mullvad.mullvadvpn.service.KeyStatusListener
import net.mullvad.mullvadvpn.service.LocationInfoCache
import net.mullvad.mullvadvpn.service.MullvadDaemon
@@ -44,6 +45,9 @@ abstract class ServiceDependentFragment(val onNoService: OnNoService) : ServiceA
lateinit var connectivityListener: ConnectivityListener
private set
+ lateinit var customDns: CustomDns
+ private set
+
lateinit var daemon: MullvadDaemon
private set
@@ -69,6 +73,7 @@ abstract class ServiceDependentFragment(val onNoService: OnNoService) : ServiceA
appVersionInfoCache = serviceConnection.appVersionInfoCache
connectionProxy = serviceConnection.connectionProxy
connectivityListener = serviceConnection.connectivityListener
+ customDns = serviceConnection.customDns
daemon = serviceConnection.daemon
keyStatusListener = serviceConnection.keyStatusListener
locationInfoCache = serviceConnection.locationInfoCache
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index b4e5dd3279..290fdaa9ee 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -26,8 +26,6 @@ use futures::{
};
use log::{debug, error, info, warn};
use mullvad_rpc::AccountsProxy;
-#[cfg(not(target_os = "android"))]
-use mullvad_types::settings::DnsOptions;
use mullvad_types::{
account::{AccountData, AccountToken, VoucherSubmission},
endpoint::MullvadEndpoint,
@@ -37,21 +35,20 @@ use mullvad_types::{
RelaySettingsUpdate,
},
relay_list::{Relay, RelayList},
- settings::Settings,
+ settings::{DnsOptions, Settings},
states::{TargetState, TunnelState},
version::{AppVersion, AppVersionInfo},
wireguard::KeygenEvent,
};
use settings::SettingsPersister;
#[cfg(not(target_os = "android"))]
-use std::net::IpAddr;
-#[cfg(not(target_os = "android"))]
use std::path::Path;
use std::{
fs::{self, File},
io,
marker::PhantomData,
mem,
+ net::IpAddr,
path::PathBuf,
sync::{mpsc as sync_mpsc, Arc, Weak},
time::Duration,
@@ -197,7 +194,6 @@ pub enum DaemonCommand {
/// Set if IPv6 should be enabled in the tunnel
SetEnableIpv6(oneshot::Sender<()>, bool),
/// Set custom DNS servers to use instead of passing requests to the gateway
- #[cfg(not(target_os = "android"))]
SetDnsOptions(oneshot::Sender<()>, DnsOptions),
/// Set MTU for wireguard tunnels
SetWireguardMtu(oneshot::Sender<()>, Option<u16>),
@@ -583,7 +579,6 @@ where
let tunnel_command_tx = tunnel_state_machine::spawn(
settings.allow_lan,
settings.block_when_disconnected,
- #[cfg(not(target_os = "android"))]
Self::get_custom_resolvers(&settings.tunnel_options.dns_options),
tunnel_parameters_generator,
log_dir,
@@ -637,7 +632,6 @@ where
Ok(daemon)
}
- #[cfg(not(target_os = "android"))]
fn get_custom_resolvers(dns_options: &DnsOptions) -> Option<Vec<IpAddr>> {
if dns_options.custom {
Some(dns_options.addresses.clone())
@@ -1057,7 +1051,6 @@ where
}
SetBridgeState(tx, bridge_state) => self.on_set_bridge_state(tx, bridge_state),
SetEnableIpv6(tx, enable_ipv6) => self.on_set_enable_ipv6(tx, enable_ipv6),
- #[cfg(not(target_os = "android"))]
SetDnsOptions(tx, dns_servers) => self.on_set_dns_options(tx, dns_servers),
SetWireguardMtu(tx, mtu) => self.on_set_wireguard_mtu(tx, mtu),
SetWireguardRotationInterval(tx, interval) => {
@@ -1697,7 +1690,6 @@ where
}
}
- #[cfg(not(target_os = "android"))]
fn on_set_dns_options(&mut self, tx: oneshot::Sender<()>, dns_options: DnsOptions) {
let save_result = self.settings.set_dns_options(dns_options.clone());
match save_result {
diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs
index d67702c575..fc177c1da1 100644
--- a/mullvad-daemon/src/settings.rs
+++ b/mullvad-daemon/src/settings.rs
@@ -1,9 +1,7 @@
use log::{debug, error, info};
-#[cfg(not(target_os = "android"))]
-use mullvad_types::settings::DnsOptions;
use mullvad_types::{
relay_constraints::{BridgeSettings, BridgeState, RelaySettingsUpdate},
- settings::Settings,
+ settings::{DnsOptions, Settings},
};
use std::{
fs::{self, File},
@@ -212,7 +210,6 @@ impl SettingsPersister {
self.update(should_save)
}
- #[cfg(not(target_os = "android"))]
pub fn set_dns_options(&mut self, options: DnsOptions) -> Result<bool, Error> {
let should_save =
Self::update_field(&mut self.settings.tunnel_options.dns_options, options);
diff --git a/mullvad-jni/Cargo.toml b/mullvad-jni/Cargo.toml
index 9f61403249..21cc9612bb 100644
--- a/mullvad-jni/Cargo.toml
+++ b/mullvad-jni/Cargo.toml
@@ -14,7 +14,7 @@ crate_type = ["cdylib"]
err-derive = "0.2.1"
futures = "0.3"
ipnetwork = "0.16"
-jnix = { version = "0.2.3", features = ["derive"] }
+jnix = { version = "0.3", features = ["derive"] }
lazy_static = "1"
log = "0.4"
log-panics = "2"
diff --git a/mullvad-jni/src/classes.rs b/mullvad-jni/src/classes.rs
index 068e75f63c..d402d1a8a3 100644
--- a/mullvad-jni/src/classes.rs
+++ b/mullvad-jni/src/classes.rs
@@ -7,6 +7,7 @@ pub const CLASSES: &[&str] = &[
"net/mullvad/mullvadvpn/model/AppVersionInfo",
"net/mullvad/mullvadvpn/model/Constraint$Any",
"net/mullvad/mullvadvpn/model/Constraint$Only",
+ "net/mullvad/mullvadvpn/model/DnsOptions",
"net/mullvad/mullvadvpn/model/GeoIpLocation",
"net/mullvad/mullvadvpn/model/GetAccountDataResult$Ok",
"net/mullvad/mullvadvpn/model/GetAccountDataResult$InvalidAccount",
diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs
index b00a1b6b50..d3ab959b33 100644
--- a/mullvad-jni/src/daemon_interface.rs
+++ b/mullvad-jni/src/daemon_interface.rs
@@ -5,7 +5,7 @@ use mullvad_types::{
location::GeoIpLocation,
relay_constraints::RelaySettingsUpdate,
relay_list::RelayList,
- settings::Settings,
+ settings::{DnsOptions, Settings},
states::{TargetState, TunnelState},
version::AppVersionInfo,
wireguard::{self, KeygenEvent},
@@ -202,6 +202,14 @@ impl DaemonInterface {
block_on(rx).map_err(|_| Error::NoResponse)
}
+ pub fn set_dns_options(&self, dns_options: DnsOptions) -> Result<()> {
+ let (tx, rx) = oneshot::channel();
+
+ self.send_command(DaemonCommand::SetDnsOptions(tx, dns_options))?;
+
+ block_on(rx).map_err(|_| Error::NoResponse)
+ }
+
pub fn set_wireguard_mtu(&self, wireguard_mtu: Option<u16>) -> Result<()> {
let (tx, rx) = oneshot::channel();
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 48be979ac1..94d5d77313 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -21,7 +21,10 @@ use mullvad_daemon::{
exception_logging, logging, runtime::new_runtime_builder, version, Daemon, DaemonCommandChannel,
};
use mullvad_rpc::{rest::Error as RestError, StatusCode};
-use mullvad_types::account::{AccountData, VoucherSubmission};
+use mullvad_types::{
+ account::{AccountData, VoucherSubmission},
+ settings::DnsOptions,
+};
use std::{
io,
path::{Path, PathBuf},
@@ -825,6 +828,28 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_setAuto
#[no_mangle]
#[allow(non_snake_case)]
+pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_setDnsOptions(
+ env: JNIEnv<'_>,
+ _: JObject<'_>,
+ daemon_interface_address: jlong,
+ dnsOptions: JObject<'_>,
+) {
+ let env = JnixEnv::from(env);
+
+ if let Some(daemon_interface) = get_daemon_interface(daemon_interface_address) {
+ let dns_options = DnsOptions::from_java(&env, dnsOptions);
+
+ if let Err(error) = daemon_interface.set_dns_options(dns_options) {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to set custom DNS options")
+ );
+ }
+ }
+}
+
+#[no_mangle]
+#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_setWireguardMtu(
env: JNIEnv<'_>,
_: JObject<'_>,
diff --git a/mullvad-types/Cargo.toml b/mullvad-types/Cargo.toml
index 548712d7d8..ab0989c948 100644
--- a/mullvad-types/Cargo.toml
+++ b/mullvad-types/Cargo.toml
@@ -20,4 +20,4 @@ serde_json = "1.0"
talpid-types = { path = "../talpid-types" }
[target.'cfg(target_os = "android")'.dependencies]
-jnix = { version = "0.2.3", features = ["derive"] }
+jnix = { version = "0.3", features = ["derive"] }
diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs
index 4f09fa480b..867f1c311e 100644
--- a/mullvad-types/src/settings/mod.rs
+++ b/mullvad-types/src/settings/mod.rs
@@ -3,11 +3,10 @@ use crate::relay_constraints::{
RelayConstraints, RelaySettings, RelaySettingsUpdate,
};
#[cfg(target_os = "android")]
-use jnix::IntoJava;
+use jnix::{FromJava, IntoJava};
use log::{debug, info};
use serde::{Deserialize, Serialize};
use serde_json;
-#[cfg(not(target_os = "android"))]
use std::net::IpAddr;
use talpid_types::net::{openvpn, wireguard, GenericTunnelOptions};
@@ -167,14 +166,14 @@ pub struct TunnelOptions {
#[cfg_attr(target_os = "android", jnix(skip))]
pub generic: GenericTunnelOptions,
/// Custom DNS options.
- #[cfg(not(target_os = "android"))]
pub dns_options: DnsOptions,
}
/// Custom DNS config
-#[cfg(not(target_os = "android"))]
#[serde(default)]
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
+#[cfg_attr(target_os = "android", derive(FromJava, IntoJava))]
+#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))]
pub struct DnsOptions {
/// Whether to use the addresses in `custom_dns`.
pub custom: bool,
@@ -194,7 +193,6 @@ impl Default for TunnelOptions {
// Enable IPv6 be default on Android
enable_ipv6: cfg!(target_os = "android"),
},
- #[cfg(not(target_os = "android"))]
dns_options: DnsOptions::default(),
}
}
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index d9e9b544a9..dd1367e770 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -42,7 +42,7 @@ nix = "0.19"
[target.'cfg(target_os = "android")'.dependencies]
-jnix = { version = "0.2.3", features = ["derive"] }
+jnix = { version = "0.3", features = ["derive"] }
[target.'cfg(target_os = "linux")'.dependencies]
diff --git a/talpid-core/src/tunnel/tun_provider/android/mod.rs b/talpid-core/src/tunnel/tun_provider/android/mod.rs
index c744ca96fa..4c136ef189 100644
--- a/talpid-core/src/tunnel/tun_provider/android/mod.rs
+++ b/talpid-core/src/tunnel/tun_provider/android/mod.rs
@@ -60,11 +60,16 @@ pub struct AndroidTunProvider {
object: GlobalRef,
last_tun_config: TunConfig,
allow_lan: bool,
+ custom_dns_servers: Option<Vec<IpAddr>>,
}
impl AndroidTunProvider {
/// Create a new AndroidTunProvider interfacing with Android's VpnService.
- pub fn new(context: AndroidContext, allow_lan: bool) -> Self {
+ pub fn new(
+ context: AndroidContext,
+ allow_lan: bool,
+ custom_dns_servers: Option<Vec<IpAddr>>,
+ ) -> Self {
let env = JnixEnv::from(
context
.jvm
@@ -79,6 +84,7 @@ impl AndroidTunProvider {
object: context.vpn_service,
last_tun_config: TunConfig::default(),
allow_lan,
+ custom_dns_servers,
}
}
@@ -91,6 +97,15 @@ impl AndroidTunProvider {
Ok(())
}
+ pub fn set_custom_dns_servers(&mut self, servers: Option<Vec<IpAddr>>) -> Result<(), Error> {
+ if self.custom_dns_servers != servers {
+ self.custom_dns_servers = servers;
+ self.recreate_tun_if_open()?;
+ }
+
+ Ok(())
+ }
+
/// Retrieve a tunnel device with the provided configuration.
pub fn get_tun(&mut self, config: TunConfig) -> Result<VpnServiceTun, Error> {
let tun_fd = self.get_tun_fd(config.clone())?;
@@ -170,10 +185,11 @@ impl AndroidTunProvider {
}
}
- fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> {
+ fn get_tun_fd(&mut self, mut config: TunConfig) -> Result<RawFd, Error> {
+ self.prepare_tun_config(&mut config);
+
let env = self.env()?;
- let actual_config = self.prepare_tun_config(config);
- let java_config = actual_config.into_java(&env);
+ let java_config = config.into_java(&env);
let result = self.call_method(
"getTun",
@@ -191,8 +207,11 @@ impl AndroidTunProvider {
}
fn recreate_tun_if_open(&mut self) -> Result<(), Error> {
+ let mut actual_config = self.last_tun_config.clone();
+
+ self.prepare_tun_config(&mut actual_config);
+
let env = self.env()?;
- let actual_config = self.prepare_tun_config(self.last_tun_config.clone());
let java_config = actual_config.into_java(&env);
let result = self.call_method(
@@ -208,7 +227,12 @@ impl AndroidTunProvider {
}
}
- fn prepare_tun_config(&self, config: TunConfig) -> TunConfig {
+ fn prepare_tun_config(&self, config: &mut TunConfig) {
+ self.prepare_tun_config_for_allow_lan(config);
+ self.prepare_tun_config_for_custom_dns(config);
+ }
+
+ fn prepare_tun_config_for_allow_lan(&self, config: &mut TunConfig) {
if self.allow_lan {
let (required_ipv4_routes, required_ipv6_routes) = config
.required_routes
@@ -245,9 +269,13 @@ impl AndroidTunProvider {
})
.collect();
- TunConfig { routes, ..config }
- } else {
- config
+ config.routes = routes;
+ }
+ }
+
+ fn prepare_tun_config_for_custom_dns(&self, config: &mut TunConfig) {
+ if let Some(custom_dns_servers) = self.custom_dns_servers.clone() {
+ config.dns_servers = custom_dns_servers;
}
}
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index a5a8861016..7292da0c67 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -192,30 +192,39 @@ impl ConnectedState {
}
}
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- if shared_values.custom_dns != servers {
- shared_values.custom_dns = servers;
-
- if let Err(error) = self.set_firewall_policy(shared_values) {
- return self.disconnect(
- shared_values,
- AfterDisconnect::Block(ErrorStateCause::SetFirewallPolicyError(error)),
- );
- }
-
- match self.set_dns(shared_values) {
- Ok(()) => SameState(self.into()),
- Err(error) => {
- log::error!("{}", error.display_chain_with_msg("Failed to set DNS"));
- self.disconnect(
+ match shared_values.set_custom_dns(servers) {
+ Ok(true) => {
+ if let Err(error) = self.set_firewall_policy(shared_values) {
+ return self.disconnect(
shared_values,
- AfterDisconnect::Block(ErrorStateCause::SetDnsError),
- )
+ AfterDisconnect::Block(ErrorStateCause::SetFirewallPolicyError(
+ error,
+ )),
+ );
+ }
+
+ match self.set_dns(shared_values) {
+ #[cfg(target_os = "android")]
+ Ok(()) => self.disconnect(shared_values, AfterDisconnect::Reconnect(0)),
+ #[cfg(not(target_os = "android"))]
+ Ok(()) => SameState(self.into()),
+ Err(error) => {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to set DNS")
+ );
+ self.disconnect(
+ shared_values,
+ AfterDisconnect::Block(ErrorStateCause::SetDnsError),
+ )
+ }
}
}
- } else {
- SameState(self.into())
+ Ok(false) => SameState(self.into()),
+ Err(error_cause) => {
+ self.disconnect(shared_values, AfterDisconnect::Block(error_cause))
+ }
}
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index 146d7c293a..6e561acc6b 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -235,10 +235,13 @@ impl ConnectingState {
}
}
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- shared_values.custom_dns = servers;
- SameState(self.into())
+ match shared_values.set_custom_dns(servers) {
+ #[cfg(target_os = "android")]
+ Ok(true) => self.disconnect(shared_values, AfterDisconnect::Reconnect(0)),
+ Ok(_) => SameState(self.into()),
+ Err(cause) => self.disconnect(shared_values, AfterDisconnect::Block(cause)),
+ }
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
shared_values.block_when_disconnected = block_when_disconnected;
diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
index fb55000a9a..dcc4660e9f 100644
--- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
@@ -77,9 +77,12 @@ impl TunnelState for DisconnectedState {
}
SameState(self.into())
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- shared_values.custom_dns = servers;
+ // Same situation as allow LAN above.
+ shared_values
+ .set_custom_dns(servers)
+ .expect("Failed to reconnect after changing custom DNS servers");
+
SameState(self.into())
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
diff --git a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
index 35278901e1..0928834d1c 100644
--- a/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnecting_state.rs
@@ -32,9 +32,8 @@ impl DisconnectingState {
let _ = shared_values.set_allow_lan(allow_lan);
AfterDisconnect::Nothing
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- shared_values.custom_dns = servers;
+ let _ = shared_values.set_custom_dns(servers);
AfterDisconnect::Nothing
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
@@ -54,9 +53,8 @@ impl DisconnectingState {
let _ = shared_values.set_allow_lan(allow_lan);
AfterDisconnect::Block(reason)
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- shared_values.custom_dns = servers;
+ let _ = shared_values.set_custom_dns(servers);
AfterDisconnect::Block(reason)
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
@@ -81,9 +79,8 @@ impl DisconnectingState {
let _ = shared_values.set_allow_lan(allow_lan);
AfterDisconnect::Reconnect(retry_attempt)
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- shared_values.custom_dns = servers;
+ let _ = shared_values.set_custom_dns(servers);
AfterDisconnect::Reconnect(retry_attempt)
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
diff --git a/talpid-core/src/tunnel_state_machine/error_state.rs b/talpid-core/src/tunnel_state_machine/error_state.rs
index 7c01969ade..a87dccd5b4 100644
--- a/talpid-core/src/tunnel_state_machine/error_state.rs
+++ b/talpid-core/src/tunnel_state_machine/error_state.rs
@@ -105,10 +105,12 @@ impl TunnelState for ErrorState {
SameState(self.into())
}
}
- #[cfg(not(target_os = "android"))]
Some(TunnelCommand::CustomDns(servers)) => {
- shared_values.custom_dns = servers;
- SameState(self.into())
+ if let Err(error_state_cause) = shared_values.set_custom_dns(servers) {
+ NewState(Self::enter(shared_values, error_state_cause))
+ } else {
+ SameState(self.into())
+ }
}
Some(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
shared_values.block_when_disconnected = block_when_disconnected;
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 3e07bde0f4..adafe9f16e 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -23,11 +23,10 @@ use futures::{
channel::{mpsc, oneshot},
stream, StreamExt,
};
-#[cfg(not(target_os = "android"))]
-use std::net::IpAddr;
use std::{
collections::HashSet,
io,
+ net::IpAddr,
path::{Path, PathBuf},
sync::{mpsc as sync_mpsc, Arc},
};
@@ -75,7 +74,7 @@ pub enum Error {
pub async fn spawn(
allow_lan: bool,
block_when_disconnected: bool,
- #[cfg(not(target_os = "android"))] custom_dns: Option<Vec<IpAddr>>,
+ custom_dns: Option<Vec<IpAddr>>,
tunnel_parameters_generator: impl TunnelParametersGenerator,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
@@ -101,6 +100,8 @@ pub async fn spawn(
android_context,
#[cfg(target_os = "android")]
allow_lan,
+ #[cfg(target_os = "android")]
+ custom_dns.clone(),
);
let runtime = tokio::runtime::Handle::current();
@@ -112,7 +113,6 @@ pub async fn spawn(
allow_lan,
block_when_disconnected,
is_offline,
- #[cfg(not(target_os = "android"))]
custom_dns,
tunnel_parameters_generator,
tun_provider,
@@ -153,7 +153,6 @@ pub enum TunnelCommand {
/// Enable or disable LAN access in the firewall.
AllowLan(bool),
/// Set custom DNS servers to use.
- #[cfg(not(target_os = "android"))]
CustomDns(Option<Vec<IpAddr>>),
/// Enable or disable the block_when_disconnected feature.
BlockWhenDisconnected(bool),
@@ -193,7 +192,7 @@ impl TunnelStateMachine {
allow_lan: bool,
block_when_disconnected: bool,
is_offline: bool,
- #[cfg(not(target_os = "android"))] custom_dns: Option<Vec<IpAddr>>,
+ custom_dns: Option<Vec<IpAddr>>,
tunnel_parameters_generator: impl TunnelParametersGenerator,
tun_provider: TunProvider,
log_dir: Option<PathBuf>,
@@ -218,7 +217,6 @@ impl TunnelStateMachine {
allow_lan,
block_when_disconnected,
is_offline,
- #[cfg(not(target_os = "android"))]
custom_dns,
tunnel_parameters_generator: Box::new(tunnel_parameters_generator),
tun_provider,
@@ -292,7 +290,6 @@ struct SharedTunnelStateValues {
/// True when the computer is known to be offline.
is_offline: bool,
/// Custom DNS servers to use.
- #[cfg(not(target_os = "android"))]
custom_dns: Option<Vec<IpAddr>>,
/// The generator of new `TunnelParameter`s
tunnel_parameters_generator: Box<dyn TunnelParametersGenerator>,
@@ -331,6 +328,32 @@ impl SharedTunnelStateValues {
Ok(())
}
+ pub fn set_custom_dns(
+ &mut self,
+ custom_dns: Option<Vec<IpAddr>>,
+ ) -> Result<bool, ErrorStateCause> {
+ if self.custom_dns != custom_dns {
+ self.custom_dns = custom_dns.clone();
+
+ #[cfg(target_os = "android")]
+ {
+ if let Err(error) = self.tun_provider.set_custom_dns_servers(custom_dns) {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg(
+ "Failed to restart tunnel after changing custom DNS servers",
+ )
+ );
+ return Err(ErrorStateCause::StartTunnelError);
+ }
+ }
+
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+ }
+
/// NetworkManager's connectivity check can get hung when DNS requests fail, thus the TSM
/// should always disable it before applying firewall rules. The connectivity check should be
/// reset whenever the firewall is cleared.
diff --git a/talpid-types/Cargo.toml b/talpid-types/Cargo.toml
index bde982e50c..2b40fca5a8 100644
--- a/talpid-types/Cargo.toml
+++ b/talpid-types/Cargo.toml
@@ -16,4 +16,4 @@ rand = "0.7"
err-derive = "0.2.1"
[target.'cfg(target_os = "android")'.dependencies]
-jnix = { version = "0.2.3", features = ["derive"] }
+jnix = { version = "0.3", features = ["derive"] }