diff options
Diffstat (limited to 'tunnel/src/main')
-rw-r--r-- | tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java | 104 |
1 files changed, 86 insertions, 18 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 edf6ac9e..f077189a 100644 --- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -18,6 +18,7 @@ import com.wireguard.android.util.SharedLibraryLoader; import com.wireguard.config.Config; import com.wireguard.config.InetEndpoint; import com.wireguard.config.InetNetwork; +import com.wireguard.config.ParseException; import com.wireguard.config.Peer; import com.wireguard.crypto.Key; import com.wireguard.crypto.KeyFormatException; @@ -25,6 +26,7 @@ import com.wireguard.util.NonNullForAll; import java.net.InetAddress; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -76,10 +78,14 @@ public final class GoBackend implements Backend, EventHandler { private static native int wgGetSocketV6(int handle); + private static native void wgSetFd(int handle, int tunFd); + private static native void wgTurnOff(int handle); private static native int wgTurnOn(String ifName, int tunFd, String settings, EventHandler handler); + private static native int wgTurnOnDhcp(String ifName, String settings, EventHandler handler); + private static native String wgVersion(); /** @@ -205,14 +211,9 @@ public final class GoBackend implements Backend, EventHandler { return getState(tunnel); } - private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state) + private void setStateInternalFinalize(final Tunnel tunnel, final Config config, Set<InetNetwork> addresses) throws Exception { - Log.i(TAG, "Bringing tunnel " + tunnel.getName() + ' ' + state); - - if (state == State.UP) { - if (config == null) - throw new BackendException(Reason.TUNNEL_MISSING_CONFIG); - + if (true) { // Add scope to avoid changing indentation level if (VpnService.prepare(context) != null) throw new BackendException(Reason.VPN_NOT_AUTHORIZED); @@ -231,12 +232,6 @@ public final class GoBackend implements Backend, EventHandler { } service.setOwner(this); - if (currentTunnelHandle != -1) { - Log.w(TAG, "Tunnel already up"); - return; - } - - 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()) { @@ -268,9 +263,13 @@ public final class GoBackend implements Backend, EventHandler { for (final String includedApplication : config.getInterface().getIncludedApplications()) builder.addAllowedApplication(includedApplication); - for (final InetNetwork addr : config.getInterface().getAddresses()) - builder.addAddress(addr.getAddress(), addr.getMask()); - + if (addresses.size() > 0) { + for (final InetNetwork addr : addresses) + builder.addAddress(addr.getAddress(), addr.getMask()); + } else { + for (final InetNetwork addr : config.getInterface().getAddresses()) + builder.addAddress(addr.getAddress(), addr.getMask()); + } for (final InetAddress addr : config.getInterface().getDnsServers()) builder.addDnsServer(addr.getHostAddress()); @@ -304,7 +303,11 @@ public final class GoBackend implements Backend, EventHandler { if (tun == null) throw new BackendException(Reason.TUN_CREATION_ERROR); Log.d(TAG, "Go backend " + wgVersion()); - currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig, this); + if (currentTunnelHandle < 0) { + currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig, this); + } else { + wgSetFd(currentTunnelHandle, tun.detachFd()); + } } if (currentTunnelHandle < 0) throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle); @@ -314,6 +317,35 @@ public final class GoBackend implements Backend, EventHandler { service.protect(wgGetSocketV4(currentTunnelHandle)); service.protect(wgGetSocketV6(currentTunnelHandle)); + } + } + + private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state) + throws Exception { + Log.i(TAG, "Bringing tunnel " + tunnel.getName() + ' ' + state); + + if (state == State.UP) { + if (config == null) + throw new BackendException(Reason.TUNNEL_MISSING_CONFIG); + + if (currentTunnelHandle != -1) { + Log.w(TAG, "Tunnel already up"); + return; + } + + if (false) { + setStateInternalFinalize(tunnel, config, null); + } else { + // Build config + final String goConfig = config.toWgUserspaceString(); + + currentTunnelHandle = wgTurnOnDhcp(tunnel.getName(), goConfig, this); + if (currentTunnelHandle < 0) + throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle); + + currentTunnel = tunnel; + currentConfig = config; + } } else { if (currentTunnelHandle == -1) { Log.w(TAG, "Tunnel already down"); @@ -330,7 +362,43 @@ public final class GoBackend implements Backend, EventHandler { } public void onEvent(String event) { - Log.d(TAG, "onEvent: " + event); + boolean isEvent = false; + Set<InetNetwork> addresses = new LinkedHashSet<>(); + + Log.d(TAG, "onEvent: " + event); + for (final String line : event.split("\\n")) { + final String[] params = line.split("=", 2); + if (params.length != 2) + break; + + final String key = params[0]; + final String value = params[1]; + + if ("event".equals(key)) { + isEvent = true; + } else if (!isEvent) { + break; + } + + if ("address".equals(key)) { + for (final String strAddr : value.split(",")) { + try { + InetNetwork addr = InetNetwork.parse(strAddr); + if (addr.getMask() < 33 || addr.getMask() == 128) + addresses.add(addr); + } catch(final ParseException ignored) { + } + } + } + } + + if (addresses.size() > 0) { + try { + setStateInternalFinalize(currentTunnel, currentConfig, addresses); + } catch (final Exception e) { + Log.d(TAG, "setStateInternalFinalize", e); + } + } } /** |