From 1b42117791266251b41959fc18e6c6215a85f739 Mon Sep 17 00:00:00 2001 From: kari-ts <135075563+kari-ts@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:10:41 -0800 Subject: [PATCH] use network callback to update DNS config when network changes (#147) * use network callback to update DNS config when network changes -Use requestNetwork, which gets the best network matching the passed in network request, to listen for changes to network and cache DNS config -Call netmon.InjectEvent on network change to indicate a change Follow-up will fix issue in netmon where IsMajorChangeFrom doesn't identify major changes when a network is added Fixes #10107 * use network callback to update DNS config when network changes -Use requestNetwork, which gets the best network matching the passed in network request, to listen for changes to network and cache DNS config -Call netmon.InjectEvent on network change to indicate a change Follow-up will fix issue in netmon where IsMajorChangeFrom doesn't identify major changes when a network is added Updates tailscale/tailscale/#10107 hi * hi * . * use network callback to update DNS config when network changes -Use requestNetwork, which gets the best network matching the passed in network request, to listen for changes to network and cache DNS config -Call netmon.InjectEvent on network change to indicate a change Follow-up will fix issue in netmon where IsMajorChangeFrom doesn't identify major changes when a network is added Updates tailscale/tailscale/#10107 * fixed missing connectivity manager --- .vscode/settings.json | 0 android/src/main/AndroidManifest.xml | 1 + .../src/main/java/com/tailscale/ipn/App.java | 44 +-- .../java/com/tailscale/ipn/DnsConfig.java | 321 +----------------- .../java/com/tailscale/ipn/DnsConfigTest.java | 21 -- cmd/tailscale/backend.go | 2 +- cmd/tailscale/callbacks.go | 27 +- cmd/tailscale/main.go | 10 +- eclipse-formatter.xml | 315 +++++++++++++++++ 9 files changed, 373 insertions(+), 368 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 android/src/test/java/com/tailscale/ipn/DnsConfigTest.java create mode 100644 eclipse-formatter.xml diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e69de29 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 327951b..8523e9d 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ + diff --git a/android/src/main/java/com/tailscale/ipn/App.java b/android/src/main/java/com/tailscale/ipn/App.java index 299d354..a1da150 100644 --- a/android/src/main/java/com/tailscale/ipn/App.java +++ b/android/src/main/java/com/tailscale/ipn/App.java @@ -71,7 +71,7 @@ import androidx.browser.customtabs.CustomTabsIntent; import org.gioui.Gio; public class App extends Application { - private final static String PEER_TAG = "peer"; + private static final String PEER_TAG = "peer"; static final String STATUS_CHANNEL_ID = "tailscale-status"; static final int STATUS_NOTIFICATION_ID = 1; @@ -82,16 +82,19 @@ public class App extends Application { private static final String FILE_CHANNEL_ID = "tailscale-files"; private static final int FILE_NOTIFICATION_ID = 3; - private final static Handler mainHandler = new Handler(Looper.getMainLooper()); + private static final Handler mainHandler = new Handler(Looper.getMainLooper()); - public DnsConfig dns = new DnsConfig(this); + private ConnectivityManager connectivityManager; + public DnsConfig dns = new DnsConfig(); public DnsConfig getDnsConfigObj() { return this.dns; } @Override public void onCreate() { super.onCreate(); // Load and initialize the Go library. Gio.init(this); - registerNetworkCallback(); + + this.connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); + setAndRegisterNetworkCallbacks(); createNotificationChannel(NOTIFY_CHANNEL_ID, "Notifications", NotificationManagerCompat.IMPORTANCE_DEFAULT); createNotificationChannel(STATUS_CHANNEL_ID, "VPN Status", NotificationManagerCompat.IMPORTANCE_LOW); @@ -99,26 +102,27 @@ public class App extends Application { } - private void registerNetworkCallback() { - ConnectivityManager cMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); - cMgr.registerNetworkCallback(new NetworkRequest.Builder().build(), new ConnectivityManager.NetworkCallback() { - private void reportConnectivityChange() { - NetworkInfo active = cMgr.getActiveNetworkInfo(); - // https://developer.android.com/training/monitoring-device-state/connectivity-status-type - boolean isConnected = active != null && active.isConnectedOrConnecting(); - onConnectivityChanged(isConnected); + // 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. + private void setAndRegisterNetworkCallbacks() { + connectivityManager.requestNetwork(dns.getDNSConfigNetworkRequest(), new ConnectivityManager.NetworkCallback(){ + @Override + public void onAvailable(Network network){ + super.onAvailable(network); + StringBuilder sb = new StringBuilder(""); + LinkProperties linkProperties = connectivityManager.getLinkProperties(network); + List dnsList = linkProperties.getDnsServers(); + for (InetAddress ip : dnsList) { + sb.append(ip.getHostAddress()).append(" "); + } + dns.updateDNSFromNetwork(sb.toString()); + onDnsConfigChanged(); } @Override public void onLost(Network network) { super.onLost(network); - this.reportConnectivityChange(); - } - - @Override - public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { - super.onLinkPropertiesChanged(network, linkProperties); - this.reportConnectivityChange(); + onDnsConfigChanged(); } }); } @@ -347,7 +351,7 @@ public class App extends Application { } static native void onVPNPrepared(); - private static native void onConnectivityChanged(boolean connected); + private static native void onDnsConfigChanged(); static native void onShareIntent(int nfiles, int[] types, String[] mimes, String[] items, String[] names, long[] sizes); static native void onWriteStorageGranted(); diff --git a/android/src/main/java/com/tailscale/ipn/DnsConfig.java b/android/src/main/java/com/tailscale/ipn/DnsConfig.java index 5c2cdbc..1168e1a 100644 --- a/android/src/main/java/com/tailscale/ipn/DnsConfig.java +++ b/android/src/main/java/com/tailscale/ipn/DnsConfig.java @@ -4,14 +4,8 @@ package com.tailscale.ipn; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.DhcpInfo; -import android.net.LinkProperties; -import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.wifi.WifiManager; +import android.net.NetworkRequest; import java.lang.reflect.Method; @@ -20,6 +14,8 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; // Tailscale DNS Config retrieval // @@ -32,65 +28,9 @@ import java.util.Locale; // Importantly, after the Tailscale VPN comes up it will set a DNS server of 100.100.100.100 // but we still want to retrieve the underlying DNS servers received from DHCP. If we roam // from Wi-Fi to LTE, we want the DNS servers received from LTE. -// -// --------------------- Android 7 and later ----------------------------------------- -// -// ## getDnsConfigFromLinkProperties -// Android provides a getAllNetworks interface in the ConnectivityManager. We walk through -// each interface to pick the most appropriate one. -// - If there is an Ethernet interface active we use that. -// - If Wi-Fi is active we use that. -// - If LTE is active we use that. -// - We never use a VPN's DNS servers. That VPN is likely us. Even if not us, Android -// only allows one VPN at a time so a different VPN's DNS servers won't be available -// once Tailscale comes up. -// -// getAllNetworks() is used as the sole mechanism for retrieving the DNS config with -// Android 7 and later. -// -// --------------------- Releases older than Android 7 ------------------------------- -// -// We support Tailscale back to Android 5. Android versions 5 and 6 supply a getAllNetworks() -// implementation but it always returns an empty list. -// -// ## getDnsConfigFromLinkProperties with getActiveNetwork -// ConnectivityManager also supports a getActiveNetwork() routine, which Android 5 and 6 do -// return a value for. If Tailscale isn't up yet and we can get the Wi-Fi/LTE/etc DNS -// config using getActiveNetwork(), we use that. -// -// Once Tailscale is up, getActiveNetwork() returns tailscale0 with DNS server 100.100.100.100 -// and that isn't useful. So we try two other mechanisms: -// -// ## getDnsServersFromSystemProperties -// Android versions prior to 8 let us retrieve the actual system DNS servers from properties. -// Later Android versions removed the properties and only return an empty string. -// -// We check the net.dns1 - net.dns4 DNS servers. If Tailscale is up the DNS server will be -// 100.100.100.100, which isn't useful, but if we get something different we'll use that. -// -// getDnsServersFromSystemProperties can only retrieve the IPv4 or IPv6 addresses of the -// configured DNS servers. We also want to know the DNS Search Domains configured, but -// we have no way to retrieve this using these interfaces. We return an empty list of -// search domains. Sorry. -// -// ## getDnsServersFromNetworkInfo -// ConnectivityManager supports an older API called getActiveNetworkInfo to return the -// active network interface. It doesn't handle VPNs, so the interface will always be Wi-Fi -// or Cellular even if Tailscale is up. -// -// For Wi-Fi interfaces we retrieve the DHCP response from the WifiManager. For Cellular -// interfaces we check for properties populated by most of the radio drivers. -// -// getDnsServersFromNetworkInfo does not have a way to retrieve the DNS Search Domains, -// so we return an empty list. Additionally, these interfaces are so old that they only -// support IPv4. We can't retrieve IPv6 DNS server addresses this way. public class DnsConfig { - private Context ctx; - - public DnsConfig(Context ctx) { - this.ctx = ctx; - } + private String dnsConfigs; // getDnsConfigAsString returns the current DNS configuration as a multiline string: // line[0] DNS server addresses separated by spaces @@ -102,260 +42,27 @@ public class DnsConfig { // // an empty string means the current DNS configuration could not be retrieved. String getDnsConfigAsString() { - String s = getDnsConfigFromLinkProperties(); + String s = getDnsConfigs(); if (!s.trim().isEmpty()) { return s; } - if (android.os.Build.VERSION.SDK_INT >= 23) { - // If ConnectivityManager.getAllNetworks() works, it is the - // authoritative mechanism and we rely on it. The other methods - // which follow involve more compromises. - return ""; - } - - s = getDnsServersFromSystemProperties(); - if (!s.trim().isEmpty()) { - return s; - } - return getDnsServersFromNetworkInfo(); - } - - // getDnsConfigFromLinkProperties finds the DNS servers for each Network interface - // returned by ConnectivityManager getAllNetworks().LinkProperties, and return the - // one that (heuristically) would be the primary DNS servers. - // - // on a Nexus 4 with Android 5.1 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 - // on a Nexus 7 with Android 6.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 - // on a Pixel 3a with Android 12.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1\nlocaldomain - // on a Pixel 3a with Android 12.0 on LTE: fd00:976a::9 fd00:976a::10 - // - // One odd behavior noted on Pixel3a with Android 12: - // With Wi-Fi already connected, starting Tailscale returned DNS servers 2602:248:7b4a:ff60::1 10.1.10.1 - // Turning off Wi-Fi and connecting LTE returned DNS servers fd00:976a::9 fd00:976a::10. - // Turning Wi-Fi back on return DNS servers: 10.1.10.1. The IPv6 DNS server is gone. - // This appears to be the ConnectivityManager behavior, not something we are doing. - // - // This implementation can work through Android 12 (SDK 30). In SDK 31 the - // getAllNetworks() method is deprecated and we'll need to implement a - // android.net.ConnectivityManager.NetworkCallback instead to monitor - // link changes and track which DNS server to use. - String getDnsConfigFromLinkProperties() { - ConnectivityManager cMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); - if (cMgr == null) { - return ""; - } - - Network[] networks = cMgr.getAllNetworks(); - if (networks == null) { - // Android 6 and before often returns an empty list, but we - // can try again with just the active network. - // - // Once Tailscale is connected, the active network will be Tailscale - // which will have 100.100.100.100 for its DNS server. We reject - // TYPE_VPN in getPreferabilityForNetwork, so it won't be returned. - Network active = cMgr.getActiveNetwork(); - if (active == null) { - return ""; - } - networks = new Network[]{active}; - } - - // getPreferabilityForNetwork returns an index into dnsConfigs from 0-3. - String[] dnsConfigs = new String[]{"", "", "", ""}; - for (Network network : networks) { - int idx = getPreferabilityForNetwork(cMgr, network); - if ((idx < 0) || (idx > 3)) { - continue; - } - - LinkProperties linkProp = cMgr.getLinkProperties(network); - NetworkCapabilities nc = cMgr.getNetworkCapabilities(network); - List dnsList = linkProp.getDnsServers(); - StringBuilder sb = new StringBuilder(""); - for (InetAddress ip : dnsList) { - sb.append(ip.getHostAddress() + " "); - } - - String d = linkProp.getDomains(); - if (d != null) { - sb.append("\n"); - sb.append(d); - } - - dnsConfigs[idx] = sb.toString(); - } - - // return the lowest index DNS config which exists. If an Ethernet config - // was found, return it. Otherwise if Wi-fi was found, return it. Etc. - for (String s : dnsConfigs) { - if (!s.trim().isEmpty()) { - return s; - } - } - return ""; } - // getDnsServersFromSystemProperties returns DNS servers found in system properties. - // On Android versions prior to Android 8, we can directly query the DNS - // servers the system is using. More recent Android releases return empty strings. - // - // Once Tailscale is connected these properties will return 100.100.100.100, which we - // suppress. - // - // on a Nexus 4 with Android 5.1 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 - // on a Nexus 7 with Android 6.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1 - // on a Pixel 3a with Android 12.0 on wifi: - // on a Pixel 3a with Android 12.0 on LTE: - // - // The list of DNS search domains does not appear to be available in system properties. - String getDnsServersFromSystemProperties() { - try { - Class SystemProperties = Class.forName("android.os.SystemProperties"); - Method method = SystemProperties.getMethod("get", String.class); - List servers = new ArrayList(); - for (String name : new String[]{"net.dns1", "net.dns2", "net.dns3", "net.dns4"}) { - String value = (String) method.invoke(null, name); - if (value != null && !value.isEmpty() && - !value.equals("100.100.100.100") && - !servers.contains(value)) { - servers.add(value); - } - } - return String.join(" ", servers); - } catch (Exception e) { - return ""; + private String getDnsConfigs(){ + synchronized(this) { + return this.dnsConfigs; } } - - public String intToInetString(int hostAddress) { - return String.format(java.util.Locale.ROOT, "%d.%d.%d.%d", - (0xff & hostAddress), - (0xff & (hostAddress >> 8)), - (0xff & (hostAddress >> 16)), - (0xff & (hostAddress >> 24))); - } - - // getDnsServersFromNetworkInfo retrieves DNS servers using ConnectivityManager - // getActiveNetworkInfo() plus interface-specific mechanisms to retrieve the DNS servers. - // Only IPv4 DNS servers are supported by this mechanism, neither the WifiManager nor the - // interface-specific dns properties appear to populate IPv6 DNS server addresses. - // - // on a Nexus 4 with Android 5.1 on wifi: 10.1.10.1 - // on a Nexus 7 with Android 6.0 on wifi: 10.1.10.1 - // on a Pixel-3a with Android 12.0 on wifi: 10.1.10.1 - // on a Pixel-3a with Android 12.0 on LTE: - // - // The list of DNS search domains is not available in this way. - String getDnsServersFromNetworkInfo() { - ConnectivityManager cMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); - if (cMgr == null) { - return ""; - } - - NetworkInfo info = cMgr.getActiveNetworkInfo(); - if (info == null) { - return ""; + void updateDNSFromNetwork(String dnsConfigs){ + synchronized(this) { + this.dnsConfigs = dnsConfigs; } - - Class SystemProperties; - Method method; - - try { - SystemProperties = Class.forName("android.os.SystemProperties"); - method = SystemProperties.getMethod("get", String.class); - } catch (Exception e) { - return ""; - } - - List servers = new ArrayList(); - - switch(info.getType()) { - case ConnectivityManager.TYPE_WIFI: - case ConnectivityManager.TYPE_WIMAX: - for (String name : new String[]{ - "net.wifi0.dns1", "net.wifi0.dns2", "net.wifi0.dns3", "net.wifi0.dns4", - "net.wlan0.dns1", "net.wlan0.dns2", "net.wlan0.dns3", "net.wlan0.dns4", - "net.eth0.dns1", "net.eth0.dns2", "net.eth0.dns3", "net.eth0.dns4", - "dhcp.wlan0.dns1", "dhcp.wlan0.dns2", "dhcp.wlan0.dns3", "dhcp.wlan0.dns4", - "dhcp.tiwlan0.dns1", "dhcp.tiwlan0.dns2", "dhcp.tiwlan0.dns3", "dhcp.tiwlan0.dns4"}) { - try { - String value = (String) method.invoke(null, name); - if (value != null && !value.isEmpty() && !servers.contains(value)) { - servers.add(value); - } - } catch (Exception e) { - continue; - } - } - - WifiManager wMgr = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE); - if (wMgr != null) { - DhcpInfo dhcp = wMgr.getDhcpInfo(); - if (dhcp.dns1 != 0) { - String value = intToInetString(dhcp.dns1); - if (value != null && !value.isEmpty() && !servers.contains(value)) { - servers.add(value); - } - } - if (dhcp.dns2 != 0) { - String value = intToInetString(dhcp.dns2); - if (value != null && !value.isEmpty() && !servers.contains(value)) { - servers.add(value); - } - } - } - return String.join(" ", servers); - case ConnectivityManager.TYPE_MOBILE: - case ConnectivityManager.TYPE_MOBILE_HIPRI: - for (String name : new String[]{ - "net.rmnet0.dns1", "net.rmnet0.dns2", "net.rmnet0.dns3", "net.rmnet0.dns4", - "net.rmnet1.dns1", "net.rmnet1.dns2", "net.rmnet1.dns3", "net.rmnet1.dns4", - "net.rmnet2.dns1", "net.rmnet2.dns2", "net.rmnet2.dns3", "net.rmnet2.dns4", - "net.rmnet3.dns1", "net.rmnet3.dns2", "net.rmnet3.dns3", "net.rmnet3.dns4", - "net.rmnet4.dns1", "net.rmnet4.dns2", "net.rmnet4.dns3", "net.rmnet4.dns4", - "net.rmnet5.dns1", "net.rmnet5.dns2", "net.rmnet5.dns3", "net.rmnet5.dns4", - "net.rmnet6.dns1", "net.rmnet6.dns2", "net.rmnet6.dns3", "net.rmnet6.dns4", - "net.rmnet7.dns1", "net.rmnet7.dns2", "net.rmnet7.dns3", "net.rmnet7.dns4", - "net.pdp0.dns1", "net.pdp0.dns2", "net.pdp0.dns3", "net.pdp0.dns4", - "net.pdpbr0.dns1", "net.pdpbr0.dns2", "net.pdpbr0.dns3", "net.pdpbr0.dns4"}) { - try { - String value = (String) method.invoke(null, name); - if (value != null && !value.isEmpty() && !servers.contains(value)) { - servers.add(value); - } - } catch (Exception e) { - continue; - } - - } - } - - return ""; } - // getPreferabilityForNetwork is a utility routine which implements a priority for - // different types of network transport, used in a heuristic to pick DNS servers to use. - int getPreferabilityForNetwork(ConnectivityManager cMgr, Network network) { - NetworkCapabilities nc = cMgr.getNetworkCapabilities(network); - - if (nc == null) { - return -1; - } - if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { - // tun0 has both VPN and WIFI set, have to check VPN first and return. - return -1; - } - - if (nc.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { - return 0; - } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { - return 1; - } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - return 2; - } else { - return 3; - } + NetworkRequest getDNSConfigNetworkRequest(){ + // Request networks that are able to reach the Internet. + return new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); } } diff --git a/android/src/test/java/com/tailscale/ipn/DnsConfigTest.java b/android/src/test/java/com/tailscale/ipn/DnsConfigTest.java deleted file mode 100644 index b93e168..0000000 --- a/android/src/test/java/com/tailscale/ipn/DnsConfigTest.java +++ /dev/null @@ -1,21 +0,0 @@ -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import com.tailscale.ipn.DnsConfig; - -public class DnsConfigTest { - DnsConfig dns; - - @Before - public void setup() { - dns = new DnsConfig(null); - } - - @Test - public void dnsConfig_intToInetStringTest() { - assertEquals(dns.intToInetString(0x0101a8c0), "192.168.1.1"); - assertEquals(dns.intToInetString(0x04030201), "1.2.3.4"); - assertEquals(dns.intToInetString(0), "0.0.0.0"); - } -} diff --git a/cmd/tailscale/backend.go b/cmd/tailscale/backend.go index 8e1a446..e8c79e8 100644 --- a/cmd/tailscale/backend.go +++ b/cmd/tailscale/backend.go @@ -184,7 +184,7 @@ func (b *backend) Start(notify func(n ipn.Notify)) error { return b.backend.Start(ipn.Options{}) } -func (b *backend) LinkChange() { +func (b *backend) NetworkChanged() { if b.sys != nil { if nm, ok := b.sys.NetMon.GetOK(); ok { nm.InjectEvent() diff --git a/cmd/tailscale/callbacks.go b/cmd/tailscale/callbacks.go index 534e439..b922367 100644 --- a/cmd/tailscale/callbacks.go +++ b/cmd/tailscale/callbacks.go @@ -30,9 +30,6 @@ var ( // onDisconnect receives global IPNService references when // disconnecting. onDisconnect = make(chan jni.Object) - // onConnectivityChange is notified every time the network - // conditions change. - onConnectivityChange = make(chan bool, 1) // onGoogleToken receives google ID tokens. onGoogleToken = make(chan string) @@ -42,6 +39,9 @@ var ( // onWriteStorageGranted is notified when we are granted WRITE_STORAGE_PERMISSION. onWriteStorageGranted = make(chan struct{}, 1) + + // onDNSConfigChanged is notified when the network changes and the DNS config needs to be updated. + onDNSConfigChanged = make(chan struct{}, 1) ) const ( @@ -109,21 +109,12 @@ func Java_com_tailscale_ipn_IPNService_disconnect(env *C.JNIEnv, this C.jobject) //export Java_com_tailscale_ipn_StartVPNWorker_connect func Java_com_tailscale_ipn_StartVPNWorker_connect(env *C.JNIEnv, this C.jobject) { - requestBackend(ConnectEvent{Enable: true}) + requestBackend(ConnectEvent{Enable: true}) } //export Java_com_tailscale_ipn_StopVPNWorker_disconnect func Java_com_tailscale_ipn_StopVPNWorker_disconnect(env *C.JNIEnv, this C.jobject) { - requestBackend(ConnectEvent{Enable: false}) -} - -//export Java_com_tailscale_ipn_App_onConnectivityChanged -func Java_com_tailscale_ipn_App_onConnectivityChanged(env *C.JNIEnv, cls C.jclass, connected C.jboolean) { - select { - case <-onConnectivityChange: - default: - } - onConnectivityChange <- connected == C.JNI_TRUE + requestBackend(ConnectEvent{Enable: false}) } //export Java_com_tailscale_ipn_QuickToggleService_onTileClick @@ -200,3 +191,11 @@ func Java_com_tailscale_ipn_App_onShareIntent(env *C.JNIEnv, cls C.jclass, nfile } onFileShare <- files } + +//export Java_com_tailscale_ipn_App_onDnsConfigChanged +func Java_com_tailscale_ipn_App_onDnsConfigChanged(env *C.JNIEnv, cls C.jclass) { + select { + case onDNSConfigChanged <- struct{}{}: + default: + } +} diff --git a/cmd/tailscale/main.go b/cmd/tailscale/main.go index e1285a9..dde90d9 100644 --- a/cmd/tailscale/main.go +++ b/cmd/tailscale/main.go @@ -526,11 +526,6 @@ func (a *App) runBackend() error { notifyVPNClosed() } } - case <-onConnectivityChange: - if b != nil { - go b.LinkChange() - } - a.notify(state) case s := <-onDisconnect: b.CloseTUNs() jni.Do(a.jvm, func(env *jni.Env) error { @@ -545,6 +540,11 @@ func (a *App) runBackend() error { if state.State >= ipn.Starting { notifyVPNClosed() } + case <-onDNSConfigChanged: + if b != nil { + go b.NetworkChanged() + } + a.notify(state) } } } diff --git a/eclipse-formatter.xml b/eclipse-formatter.xml new file mode 100644 index 0000000..7f8c57d --- /dev/null +++ b/eclipse-formatter.xml @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +