summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-12-16 09:56:38 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-12-16 09:56:38 -0300
commit71ef54b0f1559c3e999d8c29c2dc3333db8adeb8 (patch)
tree85ce2de26e6ec1bf30c26112569a99e7b58d583e /android
parent683d2e3468445929c02ab2894b184adb1db20e01 (diff)
parent8f166356bccf13b5c90c7fa7db2644e328f7bc9d (diff)
downloadmullvadvpn-71ef54b0f1559c3e999d8c29c2dc3333db8adeb8.tar.xz
mullvadvpn-71ef54b0f1559c3e999d8c29c2dc3333db8adeb8.zip
Merge branch 'handle-invalid-dns-server-addresses'
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/TunnelStateNotification.kt43
-rw-r--r--android/src/main/kotlin/net/mullvad/talpid/CreateTunResult.kt24
-rw-r--r--android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt68
-rw-r--r--android/src/main/kotlin/net/mullvad/talpid/tunnel/ErrorStateCause.kt3
-rw-r--r--android/src/main/res/values/strings.xml1
5 files changed, 100 insertions, 39 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/TunnelStateNotification.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/TunnelStateNotification.kt
index d352b3fc2a..80ae9da5e4 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/TunnelStateNotification.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/TunnelStateNotification.kt
@@ -8,6 +8,7 @@ import net.mullvad.talpid.tunnel.ActionAfterDisconnect
import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.tunnel.ErrorStateCause
import net.mullvad.talpid.tunnel.ParameterGenerationError
+import net.mullvad.talpid.util.addressString
class TunnelStateNotification(
private val context: Context,
@@ -53,10 +54,27 @@ class TunnelStateNotification(
}
private fun show(error: ErrorState?) {
- val cause = error?.cause
+ // if the error state is null, we can assume that we are secure
+ if (error?.isBlocking ?: true) {
+ title = blockingTitle
+ message = error?.cause?.let { cause -> blockingErrorMessage(cause) }
+ } else {
+ title = notBlockingTitle
+ message = notBlockingErrorMessage(error?.cause)
+ }
+
+ shouldShow = true
+ }
+
+ private fun blockingErrorMessage(cause: ErrorStateCause): String {
+ val messageId = when (cause) {
+ is ErrorStateCause.InvalidDnsServers -> {
+ val addresses = cause.addresses
+ .map { address -> address.addressString() }
+ .joinToString()
- val messageText = when (cause) {
- null -> null
+ return context.getString(R.string.invalid_dns_servers, addresses)
+ }
is ErrorStateCause.AuthFailed -> R.string.auth_failed
is ErrorStateCause.Ipv6Unavailable -> R.string.ipv6_unavailable
is ErrorStateCause.SetFirewallPolicyError -> R.string.set_firewall_policy_error
@@ -78,21 +96,16 @@ class TunnelStateNotification(
is ErrorStateCause.VpnPermissionDenied -> R.string.vpn_permission_denied_error
}
- // if the error state is null, we can assume that we are secure
- if (error?.isBlocking ?: true) {
- title = blockingTitle
- message = messageText?.let { id -> context.getString(id) }
- } else {
- val updatedMessageText = when (cause) {
- is ErrorStateCause.VpnPermissionDenied -> messageText
- else -> R.string.failed_to_block_internet
- }
+ return context.getString(messageId)
+ }
- title = notBlockingTitle
- message = updatedMessageText?.let { id -> context.getString(id) }
+ private fun notBlockingErrorMessage(cause: ErrorStateCause?): String {
+ val messageId = when (cause) {
+ is ErrorStateCause.VpnPermissionDenied -> R.string.vpn_permission_denied_error
+ else -> R.string.failed_to_block_internet
}
- shouldShow = true
+ return context.getString(messageId)
}
private fun hide() {
diff --git a/android/src/main/kotlin/net/mullvad/talpid/CreateTunResult.kt b/android/src/main/kotlin/net/mullvad/talpid/CreateTunResult.kt
new file mode 100644
index 0000000000..dfa82852f1
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/talpid/CreateTunResult.kt
@@ -0,0 +1,24 @@
+package net.mullvad.talpid
+
+import java.net.InetAddress
+
+sealed class CreateTunResult {
+ open val isOpen
+ get() = false
+
+ class Success(val tunFd: Int) : CreateTunResult() {
+ override val isOpen
+ get() = true
+ }
+
+ class InvalidDnsServers(
+ val addresses: ArrayList<InetAddress>,
+ val tunFd: Int
+ ) : CreateTunResult() {
+ override val isOpen
+ get() = true
+ }
+
+ class PermissionDenied : CreateTunResult()
+ class TunnelDeviceError : CreateTunResult()
+}
diff --git a/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt b/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
index a0dfd029f2..7da32ad71b 100644
--- a/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
@@ -10,12 +10,21 @@ import kotlin.properties.Delegates.observable
import net.mullvad.talpid.tun_provider.TunConfig
open class TalpidVpnService : VpnService() {
- private var activeTunDevice by observable<Int?>(null) { _, oldTunDevice, _ ->
- oldTunDevice?.let { oldTunFd ->
+ private var activeTunStatus by observable<CreateTunResult?>(null) { _, oldTunStatus, _ ->
+ val oldTunFd = when (oldTunStatus) {
+ is CreateTunResult.Success -> oldTunStatus.tunFd
+ is CreateTunResult.InvalidDnsServers -> oldTunStatus.tunFd
+ else -> null
+ }
+
+ if (oldTunFd != null) {
ParcelFileDescriptor.adoptFd(oldTunFd).close()
}
}
+ private val tunIsOpen
+ get() = activeTunStatus?.isOpen ?: false
+
private var currentTunConfig = defaultTunConfig()
private var tunIsStale = false
@@ -31,52 +40,52 @@ open class TalpidVpnService : VpnService() {
connectivityListener.unregister()
}
- fun getTun(config: TunConfig): Int {
+ fun getTun(config: TunConfig): CreateTunResult {
synchronized(this) {
- val tunDevice = activeTunDevice
+ val tunStatus = activeTunStatus
- if (config == currentTunConfig && tunDevice != null && !tunIsStale) {
- return tunDevice
+ if (config == currentTunConfig && tunIsOpen && !tunIsStale) {
+ return tunStatus!!
} else {
- val newTunDevice = createTun(config)
+ val newTunStatus = createTun(config)
currentTunConfig = config
- activeTunDevice = newTunDevice
+ activeTunStatus = newTunStatus
tunIsStale = false
- return newTunDevice
+ return newTunStatus
}
}
}
fun createTun() {
synchronized(this) {
- activeTunDevice = createTun(currentTunConfig)
+ activeTunStatus = createTun(currentTunConfig)
}
}
fun createTunIfClosed(): Boolean {
synchronized(this) {
- if (activeTunDevice == null) {
- activeTunDevice = createTun(currentTunConfig)
+ if (!tunIsOpen) {
+ activeTunStatus = createTun(currentTunConfig)
}
- return activeTunDevice?.let { tunFd -> tunFd > 0 } ?: false
+ return tunIsOpen
}
}
fun recreateTunIfOpen(config: TunConfig) {
synchronized(this) {
- if (activeTunDevice != null) {
+ if (tunIsOpen) {
currentTunConfig = config
- activeTunDevice = createTun(config)
+ activeTunStatus = createTun(config)
}
}
}
fun closeTun() {
synchronized(this) {
- activeTunDevice = null
+ activeTunStatus = null
}
}
@@ -86,19 +95,25 @@ open class TalpidVpnService : VpnService() {
}
}
- private fun createTun(config: TunConfig): Int {
+ private fun createTun(config: TunConfig): CreateTunResult {
if (VpnService.prepare(this) != null) {
// VPN permission wasn't granted
- return -1
+ return CreateTunResult.PermissionDenied()
}
+ var invalidDnsServerAddresses = ArrayList<InetAddress>()
+
val builder = Builder().apply {
for (address in config.addresses) {
addAddress(address, prefixForAddress(address))
}
for (dnsServer in config.dnsServers) {
- addDnsServer(dnsServer)
+ try {
+ addDnsServer(dnsServer)
+ } catch (exception: IllegalArgumentException) {
+ invalidDnsServerAddresses.add(dnsServer)
+ }
}
for (route in config.routes) {
@@ -122,12 +137,17 @@ open class TalpidVpnService : VpnService() {
val vpnInterface = builder.establish()
val tunFd = vpnInterface?.detachFd()
- if (tunFd != null) {
- waitForTunnelUp(tunFd, config.routes.any { route -> route.isIpv6 })
- return tunFd
- } else {
- return 0
+ if (tunFd == null) {
+ return CreateTunResult.TunnelDeviceError()
}
+
+ waitForTunnelUp(tunFd, config.routes.any { route -> route.isIpv6 })
+
+ if (!invalidDnsServerAddresses.isEmpty()) {
+ return CreateTunResult.InvalidDnsServers(invalidDnsServerAddresses, tunFd)
+ }
+
+ return CreateTunResult.Success(tunFd)
}
fun bypass(socket: Int): Boolean {
diff --git a/android/src/main/kotlin/net/mullvad/talpid/tunnel/ErrorStateCause.kt b/android/src/main/kotlin/net/mullvad/talpid/tunnel/ErrorStateCause.kt
index e65f70be63..22962630b6 100644
--- a/android/src/main/kotlin/net/mullvad/talpid/tunnel/ErrorStateCause.kt
+++ b/android/src/main/kotlin/net/mullvad/talpid/tunnel/ErrorStateCause.kt
@@ -1,10 +1,13 @@
package net.mullvad.talpid.tunnel
+import java.net.InetAddress
+
sealed class ErrorStateCause {
class AuthFailed(val reason: String?) : ErrorStateCause()
class Ipv6Unavailable : ErrorStateCause()
class SetFirewallPolicyError : ErrorStateCause()
class SetDnsError : ErrorStateCause()
+ class InvalidDnsServers(val addresses: ArrayList<InetAddress>) : ErrorStateCause()
class StartTunnelError : ErrorStateCause()
class TunnelParameterError(val error: ParameterGenerationError) : ErrorStateCause()
class IsOffline : ErrorStateCause()
diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml
index fbb8182bf4..720a406465 100644
--- a/android/src/main/res/values/strings.xml
+++ b/android/src/main/res/values/strings.xml
@@ -118,6 +118,7 @@
<string name="set_firewall_policy_error">Failed to apply firewall rules. The device might
currently be unsecured</string>
<string name="set_dns_error">Failed to set system DNS server</string>
+ <string name="invalid_dns_servers">Custom DNS server addresses %1$s are invalid</string>
<string name="start_tunnel_error">Failed to start tunnel connection</string>
<string name="vpn_permission_denied_error">VPN permission was denied when creating the tunnel.
Please try connecting again.</string>