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

Commit bc8f2567 authored by Taras Antoshchuk's avatar Taras Antoshchuk Committed by Gerrit Code Review
Browse files

Merge "Revert "Revert "Revert "Revert "Add APIs that allow to exclude r...""

parents 19041e21 fe5a57e8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -26896,11 +26896,13 @@ package android.net {
    method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull java.net.InetAddress);
    method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull String);
    method @NonNull public android.net.VpnService.Builder addRoute(@NonNull java.net.InetAddress, int);
    method @NonNull public android.net.VpnService.Builder addRoute(@NonNull android.net.IpPrefix);
    method @NonNull public android.net.VpnService.Builder addRoute(@NonNull String, int);
    method @NonNull public android.net.VpnService.Builder addSearchDomain(@NonNull String);
    method @NonNull public android.net.VpnService.Builder allowBypass();
    method @NonNull public android.net.VpnService.Builder allowFamily(int);
    method @Nullable public android.os.ParcelFileDescriptor establish();
    method @NonNull public android.net.VpnService.Builder excludeRoute(@NonNull android.net.IpPrefix);
    method @NonNull public android.net.VpnService.Builder setBlocking(boolean);
    method @NonNull public android.net.VpnService.Builder setConfigureIntent(@NonNull android.app.PendingIntent);
    method @NonNull public android.net.VpnService.Builder setHttpProxy(@NonNull android.net.ProxyInfo);
+106 −17
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.NetworkUtilsInternal;
import com.android.internal.net.VpnConfig;

@@ -50,6 +51,7 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@@ -471,6 +473,13 @@ public class VpnService extends Service {
        }
    }

    private static void checkNonPrefixBytes(@NonNull InetAddress address, int prefixLength) {
        final IpPrefix prefix = new IpPrefix(address, prefixLength);
        if (!prefix.getAddress().equals(address)) {
            throw new IllegalArgumentException("Bad address");
        }
    }

    /**
     * Helper class to create a VPN interface. This class should be always
     * used within the scope of the outer {@link VpnService}.
@@ -481,9 +490,9 @@ public class VpnService extends Service {

        private final VpnConfig mConfig = new VpnConfig();
        @UnsupportedAppUsage
        private final List<LinkAddress> mAddresses = new ArrayList<LinkAddress>();
        private final List<LinkAddress> mAddresses = new ArrayList<>();
        @UnsupportedAppUsage
        private final List<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
        private final List<RouteInfo> mRoutes = new ArrayList<>();

        public Builder() {
            mConfig.user = VpnService.this.getClass().getName();
@@ -555,7 +564,6 @@ public class VpnService extends Service {
                throw new IllegalArgumentException("Bad address");
            }
            mAddresses.add(new LinkAddress(address, prefixLength));
            mConfig.updateAllowedFamilies(address);
            return this;
        }

@@ -575,6 +583,32 @@ public class VpnService extends Service {
            return addAddress(InetAddress.parseNumericAddress(address), prefixLength);
        }

        /**
         * Add a network route to the VPN interface. Both IPv4 and IPv6
         * routes are supported.
         *
         * If a route with the same destination is already present, its type will be updated.
         *
         * @throws IllegalArgumentException if the route is invalid.
         */
        @NonNull
        private Builder addRoute(@NonNull IpPrefix prefix, int type) {
            check(prefix.getAddress(), prefix.getPrefixLength());

            final RouteInfo newRoute = new RouteInfo(prefix, /* gateway */
                    null, /* interface */ null, type);

            final int index = findRouteIndexByDestination(newRoute);

            if (index == -1) {
                mRoutes.add(newRoute);
            } else {
                mRoutes.set(index, newRoute);
            }

            return this;
        }

        /**
         * Add a network route to the VPN interface. Both IPv4 and IPv6
         * routes are supported.
@@ -582,25 +616,39 @@ public class VpnService extends Service {
         * Adding a route implicitly allows traffic from that address family
         * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
         *
         * Calling this method overrides previous calls to {@link #excludeRoute} for the same
         * destination.
         *
         * If multiple routes match the packet destination, route with the longest prefix takes
         * precedence.
         *
         * @throws IllegalArgumentException if the route is invalid.
         */
        @NonNull
        public Builder addRoute(@NonNull InetAddress address, int prefixLength) {
            check(address, prefixLength);
            checkNonPrefixBytes(address, prefixLength);

            int offset = prefixLength / 8;
            byte[] bytes = address.getAddress();
            if (offset < bytes.length) {
                for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) {
                    if (bytes[offset] != 0) {
                        throw new IllegalArgumentException("Bad address");
                    }
            return addRoute(new IpPrefix(address, prefixLength), RouteInfo.RTN_UNICAST);
        }
            }
            mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null, null,
                RouteInfo.RTN_UNICAST));
            mConfig.updateAllowedFamilies(address);
            return this;

        /**
         * Add a network route to the VPN interface. Both IPv4 and IPv6
         * routes are supported.
         *
         * Adding a route implicitly allows traffic from that address family
         * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
         *
         * Calling this method overrides previous calls to {@link #excludeRoute} for the same
         * destination.
         *
         * If multiple routes match the packet destination, route with the longest prefix takes
         * precedence.
         *
         * @throws IllegalArgumentException if the route is invalid.
         */
        @NonNull
        public Builder addRoute(@NonNull IpPrefix prefix) {
            return addRoute(prefix, RouteInfo.RTN_UNICAST);
        }

        /**
@@ -611,6 +659,12 @@ public class VpnService extends Service {
         * Adding a route implicitly allows traffic from that address family
         * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
         *
         * Calling this method overrides previous calls to {@link #excludeRoute} for the same
         * destination.
         *
         * If multiple routes match the packet destination, route with the longest prefix takes
         * precedence.
         *
         * @throws IllegalArgumentException if the route is invalid.
         * @see #addRoute(InetAddress, int)
         */
@@ -619,6 +673,23 @@ public class VpnService extends Service {
            return addRoute(InetAddress.parseNumericAddress(address), prefixLength);
        }

        /**
         * Exclude a network route from the VPN interface. Both IPv4 and IPv6
         * routes are supported.
         *
         * Calling this method overrides previous calls to {@link #addRoute} for the same
         * destination.
         *
         * If multiple routes match the packet destination, route with the longest prefix takes
         * precedence.
         *
         * @throws IllegalArgumentException if the route is invalid.
         */
        @NonNull
        public Builder excludeRoute(@NonNull IpPrefix prefix) {
            return addRoute(prefix, RouteInfo.RTN_THROW);
        }

        /**
         * Add a DNS server to the VPN connection. Both IPv4 and IPv6
         * addresses are supported. If none is set, the DNS servers of
@@ -900,5 +971,23 @@ public class VpnService extends Service {
                throw new IllegalStateException(e);
            }
        }

        private int findRouteIndexByDestination(RouteInfo route) {
            for (int i = 0; i < mRoutes.size(); i++) {
                if (mRoutes.get(i).getDestination().equals(route.getDestination())) {
                    return i;
                }
            }
            return -1;
        }

        /**
         * Method for testing, to observe mRoutes while builder is being used.
         * @hide
         */
        @VisibleForTesting
        public List<RouteInfo> routes() {
            return Collections.unmodifiableList(mRoutes);
        }
    }
}
+28 −12
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -93,8 +91,8 @@ public class VpnConfig implements Parcelable {
    public String interfaze;
    public String session;
    public int mtu = -1;
    public List<LinkAddress> addresses = new ArrayList<LinkAddress>();
    public List<RouteInfo> routes = new ArrayList<RouteInfo>();
    public List<LinkAddress> addresses = new ArrayList<>();
    public List<RouteInfo> routes = new ArrayList<>();
    public List<String> dnsServers;
    public List<String> searchDomains;
    public List<String> allowedApplications;
@@ -114,12 +112,32 @@ public class VpnConfig implements Parcelable {
    public VpnConfig() {
    }

    public void updateAllowedFamilies(InetAddress address) {
        if (address instanceof Inet4Address) {
            allowIPv4 = true;
        } else {
            allowIPv6 = true;
    public VpnConfig(VpnConfig other) {
        user = other.user;
        interfaze = other.interfaze;
        session = other.session;
        mtu = other.mtu;
        addresses = copyOf(other.addresses);
        routes = copyOf(other.routes);
        dnsServers = copyOf(other.dnsServers);
        searchDomains = copyOf(other.searchDomains);
        allowedApplications = copyOf(other.allowedApplications);
        disallowedApplications = copyOf(other.disallowedApplications);
        configureIntent = other.configureIntent;
        startTime = other.startTime;
        legacy = other.legacy;
        blocking = other.blocking;
        allowBypass = other.allowBypass;
        allowIPv4 = other.allowIPv4;
        allowIPv6 = other.allowIPv6;
        isMetered = other.isMetered;
        underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
                other.underlyingNetworks, other.underlyingNetworks.length) : null;
        proxyInfo = other.proxyInfo;
    }

    private static <T> List<T> copyOf(List<T> list) {
        return list != null ? new ArrayList<>(list) : null;
    }

    public void addLegacyRoutes(String routesStr) {
@@ -131,7 +149,6 @@ public class VpnConfig implements Parcelable {
            //each route is ip/prefix
            RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
            this.routes.add(info);
            updateAllowedFamilies(info.getDestination().getAddress());
        }
    }

@@ -144,7 +161,6 @@ public class VpnConfig implements Parcelable {
            //each address is ip/prefix
            LinkAddress addr = new LinkAddress(address);
            this.addresses.add(addr);
            updateAllowedFamilies(addr.getAddress());
        }
    }

+5 −2
Original line number Diff line number Diff line
@@ -1208,10 +1208,13 @@ public class Vpn {
            for (RouteInfo route : mConfig.routes) {
                lp.addRoute(route);
                InetAddress address = route.getDestination().getAddress();

                if (route.getType() == RouteInfo.RTN_UNICAST) {
                    allowIPv4 |= address instanceof Inet4Address;
                    allowIPv6 |= address instanceof Inet6Address;
                }
            }
        }

        if (mConfig.dnsServers != null) {
            for (String dnsServer : mConfig.dnsServers) {