summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt69
-rw-r--r--android/src/main/kotlin/net/mullvad/talpid/tun_provider/InetNetwork.kt5
2 files changed, 71 insertions, 3 deletions
diff --git a/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt b/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
index f960f0c13f..8f095641a1 100644
--- a/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
@@ -1,12 +1,22 @@
package net.mullvad.talpid
import android.net.VpnService
+import android.os.ParcelFileDescriptor
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetAddress
+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 ->
+ ParcelFileDescriptor.adoptFd(oldTunFd).close()
+ }
+ }
+
+ private var currentTunConfig = defaultTunConfig()
+
val connectivityListener = ConnectivityListener()
override fun onCreate() {
@@ -17,7 +27,53 @@ open class TalpidVpnService : VpnService() {
connectivityListener.unregister(this)
}
- fun createTun(config: TunConfig): Int {
+ fun getTun(config: TunConfig): Int {
+ synchronized(this) {
+ val tunDevice = activeTunDevice
+
+ if (config == currentTunConfig && tunDevice != null) {
+ return tunDevice
+ } else {
+ val newTunDevice = createTun(config)
+
+ currentTunConfig = config
+ activeTunDevice = newTunDevice
+
+ return newTunDevice
+ }
+ }
+ }
+
+ fun createTun() {
+ synchronized(this) {
+ activeTunDevice = createTun(currentTunConfig)
+ }
+ }
+
+ fun createTunIfClosed() {
+ synchronized(this) {
+ if (activeTunDevice == null) {
+ activeTunDevice = createTun(currentTunConfig)
+ }
+ }
+ }
+
+ fun recreateTunIfOpen(config: TunConfig) {
+ synchronized(this) {
+ if (activeTunDevice != null) {
+ currentTunConfig = config
+ activeTunDevice = createTun(config)
+ }
+ }
+ }
+
+ fun closeTun() {
+ synchronized(this) {
+ activeTunDevice = null
+ }
+ }
+
+ private fun createTun(config: TunConfig): Int {
if (VpnService.prepare(this) != null) {
// VPN permission wasn't granted
return -1
@@ -41,8 +97,14 @@ open class TalpidVpnService : VpnService() {
}
val vpnInterface = builder.establish()
+ val tunFd = vpnInterface?.detachFd()
- return vpnInterface?.detachFd() ?: 0
+ if (tunFd != null) {
+ waitForTunnelUp(tunFd, config.routes.any { route -> route.isIpv6 })
+ return tunFd
+ } else {
+ return 0
+ }
}
fun bypass(socket: Int): Boolean {
@@ -56,4 +118,7 @@ open class TalpidVpnService : VpnService() {
else -> throw RuntimeException("Invalid IP address (not IPv4 nor IPv6)")
}
}
+
+ private external fun defaultTunConfig(): TunConfig
+ private external fun waitForTunnelUp(tunFd: Int, isIpv6Enabled: Boolean)
}
diff --git a/android/src/main/kotlin/net/mullvad/talpid/tun_provider/InetNetwork.kt b/android/src/main/kotlin/net/mullvad/talpid/tun_provider/InetNetwork.kt
index 9b133d352b..a8490b48bf 100644
--- a/android/src/main/kotlin/net/mullvad/talpid/tun_provider/InetNetwork.kt
+++ b/android/src/main/kotlin/net/mullvad/talpid/tun_provider/InetNetwork.kt
@@ -1,5 +1,8 @@
package net.mullvad.talpid.tun_provider
+import java.net.Inet6Address
import java.net.InetAddress
-data class InetNetwork(val address: InetAddress, val prefixLength: Short)
+data class InetNetwork(val address: InetAddress, val prefixLength: Short) {
+ val isIpv6 = address is Inet6Address
+}