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-05-10 21:08:27 +0200
commit8033d4fb8ea06c5182fa79a6f6c9f9464a3543b8 (patch)
tree3bf11f940cef017603b409930a9e9f91148a912f /tunnel/src/main/java/com/wireguard/android
parentdfe485619b5d7c7a2a3a5fb3eff54bcec6776a79 (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.java53
1 files changed, 50 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 68acd2e8..ac1d03c4 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -9,7 +9,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.LocalSocketAddress;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.Build;
@@ -25,6 +29,8 @@ import com.google.protobuf.Empty;
import com.wireguard.android.backend.BackendException.Reason;
import com.wireguard.android.backend.Tunnel.State;
import com.wireguard.android.backend.gen.GetConnectionOwnerUidResponse;
+import com.wireguard.android.backend.gen.IpcSetRequest;
+import com.wireguard.android.backend.gen.IpcSetResponse;
import com.wireguard.android.backend.gen.LibwgGrpc;
import com.wireguard.android.backend.gen.ReverseRequest;
import com.wireguard.android.backend.gen.ReverseResponse;
@@ -32,6 +38,7 @@ import com.wireguard.android.backend.gen.StartHttpProxyRequest;
import com.wireguard.android.backend.gen.StartHttpProxyResponse;
import com.wireguard.android.backend.gen.StopHttpProxyRequest;
import com.wireguard.android.backend.gen.StopHttpProxyResponse;
+import com.wireguard.android.backend.gen.TunnelHandle;
import com.wireguard.android.backend.gen.VersionRequest;
import com.wireguard.android.backend.gen.VersionResponse;
import com.wireguard.android.util.SharedLibraryLoader;
@@ -43,6 +50,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 io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
@@ -94,6 +102,8 @@ public final class GoBackend implements Backend {
private int currentTunnelHandle = -1;
private ManagedChannel channel;
private ConnectivityManager connectivityManager;
+ private ConnectivityManager.NetworkCallback myNetworkCallback = new MyNetworkCallback();
+ @Nullable private Network activeNetwork;
/**
* Public constructor for GoBackend.
@@ -434,13 +444,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);
@@ -453,7 +469,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();
@@ -527,6 +543,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");
@@ -537,6 +556,8 @@ public final class GoBackend implements Backend {
currentTunnelHandle = -1;
currentConfig = null;
stopHttpProxy();
+ connectivityManager.unregisterNetworkCallback(myNetworkCallback);
+ activeNetwork = null;
wgTurnOff(handleToClose);
try {
vpnService.get(0, TimeUnit.NANOSECONDS).stopSelf();
@@ -605,8 +626,11 @@ public final class GoBackend implements Backend {
owner.stopHttpProxy();
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;
@@ -632,4 +656,27 @@ 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.toWgUserspaceStringWithChangedEndpoints(resolver);
+ Log.w(TAG, "is default network, config:" + goConfig);
+
+ LibwgGrpc.LibwgBlockingStub stub = LibwgGrpc.newBlockingStub(channel);
+ TunnelHandle tunnel = TunnelHandle.newBuilder().setHandle(currentTunnelHandle).build();
+ IpcSetRequest request = IpcSetRequest.newBuilder().setTunnel(tunnel).setConfig(goConfig).build();
+ IpcSetResponse resp = stub.ipcSet(request);
+ }
+ }
+ }
}