diff options
Diffstat (limited to 'app/src/main/java/com/wireguard/android/backend/GoBackend.java')
-rw-r--r-- | app/src/main/java/com/wireguard/android/backend/GoBackend.java | 292 |
1 files changed, 0 insertions, 292 deletions
diff --git a/app/src/main/java/com/wireguard/android/backend/GoBackend.java b/app/src/main/java/com/wireguard/android/backend/GoBackend.java deleted file mode 100644 index 6ad5afa4..00000000 --- a/app/src/main/java/com/wireguard/android/backend/GoBackend.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package com.wireguard.android.backend; - -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.ParcelFileDescriptor; -import androidx.annotation.Nullable; -import androidx.collection.ArraySet; -import android.util.Log; - -import com.wireguard.android.backend.BackendException.Reason; -import com.wireguard.android.backend.Tunnel.State; -import com.wireguard.android.util.SharedLibraryLoader; -import com.wireguard.config.Config; -import com.wireguard.config.InetNetwork; -import com.wireguard.config.Peer; -import com.wireguard.crypto.Key; -import com.wireguard.crypto.KeyFormatException; - -import java.net.InetAddress; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import java9.util.concurrent.CompletableFuture; - -public final class GoBackend implements Backend { - private static final String TAG = "WireGuard/" + GoBackend.class.getSimpleName(); - private static CompletableFuture<VpnService> vpnService = new CompletableFuture<>(); - public interface AlwaysOnCallback { - void alwaysOnTriggered(); - } - @Nullable private static AlwaysOnCallback alwaysOnCallback; - public static void setAlwaysOnCallback(AlwaysOnCallback cb) { - alwaysOnCallback = cb; - } - - private final Context context; - @Nullable private Tunnel currentTunnel; - @Nullable private Config currentConfig; - private int currentTunnelHandle = -1; - - public GoBackend(final Context context) { - SharedLibraryLoader.loadSharedLibrary(context, "wg-go"); - this.context = context; - } - - private static native String wgGetConfig(int handle); - - private static native int wgGetSocketV4(int handle); - - private static native int wgGetSocketV6(int handle); - - private static native void wgTurnOff(int handle); - - private static native int wgTurnOn(String ifName, int tunFd, String settings); - - private static native String wgVersion(); - - @Override - public Set<String> getRunningTunnelNames() { - if (currentTunnel != null) { - final Set<String> runningTunnels = new ArraySet<>(); - runningTunnels.add(currentTunnel.getName()); - return runningTunnels; - } - return Collections.emptySet(); - } - - @Override - public State getState(final Tunnel tunnel) { - return currentTunnel == tunnel ? State.UP : State.DOWN; - } - - @Override - public Statistics getStatistics(final Tunnel tunnel) { - final Statistics stats = new Statistics(); - if (tunnel != currentTunnel) { - return stats; - } - final String config = wgGetConfig(currentTunnelHandle); - Key key = null; - long rx = 0, tx = 0; - for (final String line : config.split("\\n")) { - if (line.startsWith("public_key=")) { - if (key != null) - stats.add(key, rx, tx); - rx = 0; - tx = 0; - try { - key = Key.fromHex(line.substring(11)); - } catch (final KeyFormatException ignored) { - key = null; - } - } else if (line.startsWith("rx_bytes=")) { - if (key == null) - continue; - try { - rx = Long.parseLong(line.substring(9)); - } catch (final NumberFormatException ignored) { - rx = 0; - } - } else if (line.startsWith("tx_bytes=")) { - if (key == null) - continue; - try { - tx = Long.parseLong(line.substring(9)); - } catch (final NumberFormatException ignored) { - tx = 0; - } - } - } - if (key != null) - stats.add(key, rx, tx); - return stats; - } - - @Override - public String getVersion() { - return wgVersion(); - } - - @Override - public State setState(final Tunnel tunnel, State state, @Nullable final Config config) throws Exception { - final State originalState = getState(tunnel); - - if (state == State.TOGGLE) - state = originalState == State.UP ? State.DOWN : State.UP; - if (state == originalState && tunnel == currentTunnel && config == currentConfig) - return originalState; - if (state == State.UP) { - final Config originalConfig = currentConfig; - final Tunnel originalTunnel = currentTunnel; - if (currentTunnel != null) - setStateInternal(currentTunnel, null, State.DOWN); - try { - setStateInternal(tunnel, config, state); - } catch(final Exception e) { - if (originalTunnel != null) - setStateInternal(originalTunnel, originalConfig, State.UP); - throw e; - } - } else if (state == State.DOWN && tunnel == currentTunnel) { - setStateInternal(tunnel, null, State.DOWN); - } - return getState(tunnel); - } - - 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 (VpnService.prepare(context) != null) - throw new BackendException(Reason.VPN_NOT_AUTHORIZED); - - final VpnService service; - if (!vpnService.isDone()) - startVpnService(); - - try { - service = vpnService.get(2, TimeUnit.SECONDS); - } catch (final TimeoutException e) { - final Exception be = new BackendException(Reason.UNABLE_TO_START_VPN); - be.initCause(e); - throw be; - } - service.setOwner(this); - - if (currentTunnelHandle != -1) { - Log.w(TAG, "Tunnel already up"); - return; - } - - // Build config - final String goConfig = config.toWgUserspaceString(); - - // Create the vpn tunnel with android API - final VpnService.Builder builder = service.getBuilder(); - builder.setSession(tunnel.getName()); - - for (final String excludedApplication : config.getInterface().getExcludedApplications()) - builder.addDisallowedApplication(excludedApplication); - - for (final InetNetwork addr : config.getInterface().getAddresses()) - builder.addAddress(addr.getAddress(), addr.getMask()); - - for (final InetAddress addr : config.getInterface().getDnsServers()) - builder.addDnsServer(addr.getHostAddress()); - - for (final Peer peer : config.getPeers()) { - for (final InetNetwork addr : peer.getAllowedIps()) - builder.addRoute(addr.getAddress(), addr.getMask()); - } - - builder.setMtu(config.getInterface().getMtu().orElse(1280)); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - builder.setMetered(false); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - service.setUnderlyingNetworks(null); - - builder.setBlocking(true); - try (final ParcelFileDescriptor tun = builder.establish()) { - if (tun == null) - throw new BackendException(Reason.TUN_CREATION_ERROR); - Log.d(TAG, "Go backend v" + wgVersion()); - currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig); - } - if (currentTunnelHandle < 0) - throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle); - - currentTunnel = tunnel; - currentConfig = config; - - service.protect(wgGetSocketV4(currentTunnelHandle)); - service.protect(wgGetSocketV6(currentTunnelHandle)); - } else { - if (currentTunnelHandle == -1) { - Log.w(TAG, "Tunnel already down"); - return; - } - - wgTurnOff(currentTunnelHandle); - currentTunnel = null; - currentTunnelHandle = -1; - currentConfig = null; - } - - tunnel.onStateChange(state); - } - - private void startVpnService() { - Log.d(TAG, "Requesting to start VpnService"); - context.startService(new Intent(context, VpnService.class)); - } - - public static class VpnService extends android.net.VpnService { - @Nullable private GoBackend owner; - - public void setOwner(final GoBackend owner) { - this.owner = owner; - } - - public Builder getBuilder() { - return new Builder(); - } - - @Override - public void onCreate() { - vpnService.complete(this); - super.onCreate(); - } - - @Override - public void onDestroy() { - if (owner != null) { - final Tunnel tunnel = owner.currentTunnel; - if (tunnel != null) { - if (owner.currentTunnelHandle != -1) - wgTurnOff(owner.currentTunnelHandle); - owner.currentTunnel = null; - owner.currentTunnelHandle = -1; - owner.currentConfig = null; - tunnel.onStateChange(State.DOWN); - } - } - vpnService = vpnService.newIncompleteFuture(); - super.onDestroy(); - } - - @Override - public int onStartCommand(@Nullable final Intent intent, final int flags, final int startId) { - vpnService.complete(this); - if (intent == null || intent.getComponent() == null || !intent.getComponent().getPackageName().equals(getPackageName())) { - Log.d(TAG, "Service started by Always-on VPN feature"); - if (alwaysOnCallback != null) - alwaysOnCallback.alwaysOnTriggered(); - } - return super.onStartCommand(intent, flags, startId); - } - } -} |