summaryrefslogtreecommitdiffhomepage
path: root/tunnel/src/main/java/com/wireguard/android
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2022-12-29 00:23:17 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2023-07-05 21:40:32 +0200
commit7a12989f6241fe4ab2f56707c20e7aa7810f1212 (patch)
treec3fd2edda45018963a9608af68350b5478246404 /tunnel/src/main/java/com/wireguard/android
parenta0c1973bda70efb17490ac42c2111e8f1da2b4c3 (diff)
ui,tunnel: auto-detect IPv6/IPv4 preference
Detect IP address change. Request non-VPN network. Update endpoint when needed. Unregister network on wgTurnOff and use IPv4 if network is not known.
Diffstat (limited to 'tunnel/src/main/java/com/wireguard/android')
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java52
1 files changed, 49 insertions, 3 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
index 242f81d8..19f328f2 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -7,6 +7,11 @@ package com.wireguard.android.backend;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.ProxyInfo;
import android.os.Build;
import android.os.ParcelFileDescriptor;
@@ -23,6 +28,7 @@ import com.wireguard.config.Peer;
import com.wireguard.crypto.Key;
import com.wireguard.crypto.KeyFormatException;
import com.wireguard.util.NonNullForAll;
+import com.wireguard.util.Resolver;
import java.net.InetAddress;
import java.net.URL;
@@ -52,6 +58,9 @@ public final class GoBackend implements Backend {
@Nullable private Config currentConfig;
@Nullable private Tunnel currentTunnel;
private int currentTunnelHandle = -1;
+ private ConnectivityManager connectivityManager;
+ private ConnectivityManager.NetworkCallback myNetworkCallback = new MyNetworkCallback();
+ @Nullable private Network activeNetwork;
/**
* Public constructor for GoBackend.
@@ -61,6 +70,7 @@ public final class GoBackend implements Backend {
public GoBackend(final Context context) {
SharedLibraryLoader.loadSharedLibrary(context, "wg-go");
this.context = context;
+ connectivityManager = context.getSystemService(ConnectivityManager.class);
}
/**
@@ -79,6 +89,8 @@ public final class GoBackend implements Backend {
private static native int wgGetSocketV6(int handle);
+ private static native int wgSetConfig(int handle, String settings);
+
private static native void wgTurnOff(int handle);
private static native int wgTurnOn(String ifName, int tunFd, String settings);
@@ -258,13 +270,19 @@ public final class GoBackend implements Backend {
}
+ activeNetwork = connectivityManager.getActiveNetwork();
+ if (!connectivityManager.getNetworkCapabilities(activeNetwork).hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
+ Log.w(TAG, "VPN network is active, null activeNetwork");
+ activeNetwork = null;
+ }
+ final Resolver resolver = new Resolver(activeNetwork, connectivityManager.getLinkProperties(activeNetwork));
dnsRetry: for (int i = 0; i < DNS_RESOLUTION_RETRIES; ++i) {
// Pre-resolve IPs so they're cached when building the userspace string
for (final Peer peer : config.getPeers()) {
final InetEndpoint ep = peer.getEndpoint().orElse(null);
if (ep == null)
continue;
- if (ep.getResolved().orElse(null) == null) {
+ if (ep.getResolved(resolver, true).orElse(null) == null) {
if (i < DNS_RESOLUTION_RETRIES - 1) {
Log.w(TAG, "DNS host \"" + ep.getHost() + "\" failed to resolve; trying again");
Thread.sleep(1000);
@@ -277,7 +295,7 @@ public final class GoBackend implements Backend {
}
// Build config
- final String goConfig = config.toWgUserspaceString();
+ final String goConfig = config.toWgUserspaceString(resolver);
// Create the vpn tunnel with android API
final VpnService.Builder builder = service.getBuilder();
@@ -339,6 +357,9 @@ public final class GoBackend implements Backend {
service.protect(wgGetSocketV4(currentTunnelHandle));
service.protect(wgGetSocketV6(currentTunnelHandle));
+
+ NetworkRequest req = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).build();
+ connectivityManager.requestNetwork(req, myNetworkCallback);
} else {
if (currentTunnelHandle == -1) {
Log.w(TAG, "Tunnel already down");
@@ -348,6 +369,8 @@ public final class GoBackend implements Backend {
currentTunnel = null;
currentTunnelHandle = -1;
currentConfig = null;
+ connectivityManager.unregisterNetworkCallback(myNetworkCallback);
+ activeNetwork = null;
wgTurnOff(handleToClose);
try {
vpnService.get(0, TimeUnit.NANOSECONDS).stopSelf();
@@ -415,8 +438,11 @@ public final class GoBackend implements Backend {
if (owner != null) {
final Tunnel tunnel = owner.currentTunnel;
if (tunnel != null) {
- if (owner.currentTunnelHandle != -1)
+ if (owner.currentTunnelHandle != -1) {
+ owner.connectivityManager.unregisterNetworkCallback(owner.myNetworkCallback);
+ owner.activeNetwork = null;
wgTurnOff(owner.currentTunnelHandle);
+ }
owner.currentTunnel = null;
owner.currentTunnelHandle = -1;
owner.currentConfig = null;
@@ -442,4 +468,24 @@ public final class GoBackend implements Backend {
this.owner = owner;
}
}
+
+ private class MyNetworkCallback extends ConnectivityManager.NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ activeNetwork = network;
+ Log.w(TAG, "onAvailable: " + activeNetwork);
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
+ Log.w(TAG, "onLinkPropertiesChanged: " + network + " is default:" + (network.equals(activeNetwork)));
+ if (network.equals(activeNetwork) && currentConfig != null && currentTunnelHandle > -1) {
+ final Resolver resolver = new Resolver(network, linkProperties);
+ final String goConfig = currentConfig.toWgEndpointsUserspaceString(resolver);
+ Log.w(TAG, "is default network, config:" + goConfig);
+
+ wgSetConfig(currentTunnelHandle, goConfig);
+ }
+ }
+ }
}