Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 926a2a40 authored by Chalard Jean's avatar Chalard Jean Committed by Automerger Merge Worker
Browse files

Resolve the endpoint in legacy VPN am: 002944f7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12325669

Change-Id: I31744fca265bd28d01562003c507f4214278285c
parents 69955037 002944f7
Loading
Loading
Loading
Loading
+88 −18
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
import android.net.DnsResolver;
import android.net.INetworkManagementEventObserver;
import android.net.Ikev2VpnProfile;
import android.net.IpPrefix;
@@ -79,6 +80,7 @@ import android.net.ipsec.ike.IkeSessionParams;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -135,6 +137,8 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -325,15 +329,52 @@ public class Vpn {
            }
        }

        // TODO : implement and use this.
        @NonNull
        public InetAddress resolve(final String endpoint) throws UnknownHostException {
        public InetAddress resolve(final String endpoint)
                throws ExecutionException, InterruptedException {
            try {
                return InetAddress.parseNumericAddress(endpoint);
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Endpoint is not numeric");
                // Endpoint is not numeric : fall through and resolve
            }

            final CancellationSignal cancellationSignal = new CancellationSignal();
            try {
                final DnsResolver resolver = DnsResolver.getInstance();
                final CompletableFuture<InetAddress> result = new CompletableFuture();
                final DnsResolver.Callback<List<InetAddress>> cb =
                        new DnsResolver.Callback<List<InetAddress>>() {
                            @Override
                            public void onAnswer(@NonNull final List<InetAddress> answer,
                                    final int rcode) {
                                if (answer.size() > 0) {
                                    result.complete(answer.get(0));
                                } else {
                                    result.completeExceptionally(
                                            new UnknownHostException(endpoint));
                                }
                            }

                            @Override
                            public void onError(@Nullable final DnsResolver.DnsException error) {
                                // Unfortunately UnknownHostException doesn't accept a cause, so
                                // print a message here instead. Only show the summary, not the
                                // full stack trace.
                                Log.e(TAG, "Async dns resolver error : " + error);
                                result.completeExceptionally(new UnknownHostException(endpoint));
                            }
                        };
                resolver.query(null /* network, null for default */, endpoint,
                        DnsResolver.FLAG_EMPTY, r -> r.run(), cancellationSignal, cb);
                return result.get();
            } catch (final ExecutionException e) {
                Log.e(TAG, "Cannot resolve VPN endpoint : " + endpoint + ".", e);
                throw e;
            } catch (final InterruptedException e) {
                Log.e(TAG, "Legacy VPN was interrupted while resolving the endpoint", e);
                cancellationSignal.cancel();
                throw e;
            }
            throw new UnknownHostException(endpoint);
        }

        public boolean checkInterfacePresent(final Vpn vpn, final String iface) {
@@ -2747,9 +2788,43 @@ public class Vpn {
            }
        }

        private void checkAndFixupArguments(@NonNull final InetAddress endpointAddress) {
            final String endpointAddressString = endpointAddress.getHostAddress();
            // Perform some safety checks before inserting the address in place.
            // Position 0 in mDaemons and mArguments must be racoon, and position 1 must be mtpd.
            if (!"racoon".equals(mDaemons[0]) || !"mtpd".equals(mDaemons[1])) {
                throw new IllegalStateException("Unexpected daemons order");
            }

            // Respectively, the positions at which racoon and mtpd take the server address
            // argument are 1 and 2. Not all types of VPN require both daemons however, and
            // in that case the corresponding argument array is null.
            if (mArguments[0] != null) {
                if (!mProfile.server.equals(mArguments[0][1])) {
                    throw new IllegalStateException("Invalid server argument for racoon");
                }
                mArguments[0][1] = endpointAddressString;
            }

            if (mArguments[1] != null) {
                if (!mProfile.server.equals(mArguments[1][2])) {
                    throw new IllegalStateException("Invalid server argument for mtpd");
                }
                mArguments[1][2] = endpointAddressString;
            }
        }

        private void bringup() {
            // Catch all exceptions so we can clean up a few things.
            try {
                // resolve never returns null. If it does because of some bug, it will be
                // caught by the catch() block below and cleanup gracefully.
                final InetAddress endpointAddress = mDeps.resolve(mProfile.server);

                // Big hack : dynamically replace the address of the server in the arguments
                // with the resolved address.
                checkAndFixupArguments(endpointAddress);

                // Initialize the timer.
                mBringupStartTime = SystemClock.elapsedRealtime();

@@ -2848,20 +2923,15 @@ public class Vpn {
                }

                // Add a throw route for the VPN server endpoint, if one was specified.
                String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5];
                if (!endpoint.isEmpty()) {
                    try {
                        InetAddress addr = InetAddress.parseNumericAddress(endpoint);
                        if (addr instanceof Inet4Address) {
                            mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
                        } else if (addr instanceof Inet6Address) {
                            mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
                if (endpointAddress instanceof Inet4Address) {
                    mConfig.routes.add(new RouteInfo(
                            new IpPrefix(endpointAddress, 32), RTN_THROW));
                } else if (endpointAddress instanceof Inet6Address) {
                    mConfig.routes.add(new RouteInfo(
                            new IpPrefix(endpointAddress, 128), RTN_THROW));
                } else {
                            Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
                        }
                    } catch (IllegalArgumentException e) {
                        Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
                    }
                    Log.e(TAG, "Unknown IP address family for VPN endpoint: "
                            + endpointAddress);
                }

                // Here is the last step and it must be done synchronously.
+0 −2
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ import com.android.internal.net.VpnProfile;
import com.android.server.IpSecService;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -1054,7 +1053,6 @@ public class VpnTest {
    }

    @Test
    @Ignore("b/158974172") // remove when the bug is fixed
    public void testStartRacoonHostname() throws Exception {
        startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve
    }