android: stop tailscaled when VPN has been revoked (#480)
-add new Ipn UI state 'Stopping' to handle the case where the VPN is no longer active and a request to stop Tailscale has been issued (but is not complete yet) and use for optimistic UI -when VPN has been revoked, stop tailscaled and set the state to Stopping -this fixes the race condition where when we tell tailscaled to stop, stopping races against the netmap state updating as a result of the VPN being revoked -add isActive state and use instead of isPrepared for UI showing whether we are connected - we were previously using isPrepared as a proxy for connection, but sometimes the VPN has been prepared but is not active (eg when VPN permissions have been given and VPN has been connected previously, but has been revoked) -refactor network callbacks into its own class for readability Fixes tailscale/tailscale#12850 Signed-off-by: kari-ts <kari@tailscale.com>pull/484/head
parent
40090f179b
commit
29e3c187c2
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
package com.tailscale.ipn
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.LinkProperties
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.net.NetworkRequest
|
||||||
|
import android.util.Log
|
||||||
|
import libtailscale.Libtailscale
|
||||||
|
import java.net.InetAddress
|
||||||
|
import java.net.NetworkInterface
|
||||||
|
|
||||||
|
object NetworkChangeCallback {
|
||||||
|
|
||||||
|
// requestNetwork attempts to find the best network that matches the passed NetworkRequest. It is
|
||||||
|
// possible that this might return an unusuable network, eg a captive portal.
|
||||||
|
fun monitorDnsChanges(connectivityManager: ConnectivityManager, dns: DnsConfig) {
|
||||||
|
val networkConnectivityRequest =
|
||||||
|
NetworkRequest.Builder()
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
connectivityManager.registerNetworkCallback(
|
||||||
|
networkConnectivityRequest,
|
||||||
|
object : ConnectivityManager.NetworkCallback() {
|
||||||
|
override fun onAvailable(network: Network) {
|
||||||
|
super.onAvailable(network)
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val linkProperties: LinkProperties? = connectivityManager.getLinkProperties(network)
|
||||||
|
val dnsList: MutableList<InetAddress> = linkProperties?.dnsServers ?: mutableListOf()
|
||||||
|
for (ip in dnsList) {
|
||||||
|
sb.append(ip.hostAddress).append(" ")
|
||||||
|
}
|
||||||
|
val searchDomains: String? = linkProperties?.domains
|
||||||
|
if (searchDomains != null) {
|
||||||
|
sb.append("\n")
|
||||||
|
sb.append(searchDomains)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns.updateDNSFromNetwork(sb.toString())) {
|
||||||
|
Libtailscale.onDNSConfigChanged(linkProperties?.interfaceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLost(network: Network) {
|
||||||
|
super.onLost(network)
|
||||||
|
if (dns.updateDNSFromNetwork("")) {
|
||||||
|
Libtailscale.onDNSConfigChanged("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue