Merge "Revert "Revert "Revert "Revert "Add APIs that allow to exclude r...""
This commit is contained in:
@@ -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 java.net.InetAddress);
|
||||||
method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull String);
|
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 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 addRoute(@NonNull String, int);
|
||||||
method @NonNull public android.net.VpnService.Builder addSearchDomain(@NonNull String);
|
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 allowBypass();
|
||||||
method @NonNull public android.net.VpnService.Builder allowFamily(int);
|
method @NonNull public android.net.VpnService.Builder allowFamily(int);
|
||||||
method @Nullable public android.os.ParcelFileDescriptor establish();
|
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 setBlocking(boolean);
|
||||||
method @NonNull public android.net.VpnService.Builder setConfigureIntent(@NonNull android.app.PendingIntent);
|
method @NonNull public android.net.VpnService.Builder setConfigureIntent(@NonNull android.app.PendingIntent);
|
||||||
method @NonNull public android.net.VpnService.Builder setHttpProxy(@NonNull android.net.ProxyInfo);
|
method @NonNull public android.net.VpnService.Builder setHttpProxy(@NonNull android.net.ProxyInfo);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import android.os.RemoteException;
|
|||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.net.NetworkUtilsInternal;
|
import com.android.internal.net.NetworkUtilsInternal;
|
||||||
import com.android.internal.net.VpnConfig;
|
import com.android.internal.net.VpnConfig;
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ import java.net.Inet6Address;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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
|
* Helper class to create a VPN interface. This class should be always
|
||||||
* used within the scope of the outer {@link VpnService}.
|
* used within the scope of the outer {@link VpnService}.
|
||||||
@@ -481,9 +490,9 @@ public class VpnService extends Service {
|
|||||||
|
|
||||||
private final VpnConfig mConfig = new VpnConfig();
|
private final VpnConfig mConfig = new VpnConfig();
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private final List<LinkAddress> mAddresses = new ArrayList<LinkAddress>();
|
private final List<LinkAddress> mAddresses = new ArrayList<>();
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private final List<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
|
private final List<RouteInfo> mRoutes = new ArrayList<>();
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
mConfig.user = VpnService.this.getClass().getName();
|
mConfig.user = VpnService.this.getClass().getName();
|
||||||
@@ -555,7 +564,6 @@ public class VpnService extends Service {
|
|||||||
throw new IllegalArgumentException("Bad address");
|
throw new IllegalArgumentException("Bad address");
|
||||||
}
|
}
|
||||||
mAddresses.add(new LinkAddress(address, prefixLength));
|
mAddresses.add(new LinkAddress(address, prefixLength));
|
||||||
mConfig.updateAllowedFamilies(address);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,6 +583,32 @@ public class VpnService extends Service {
|
|||||||
return addAddress(InetAddress.parseNumericAddress(address), prefixLength);
|
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
|
* Add a network route to the VPN interface. Both IPv4 and IPv6
|
||||||
* routes are supported.
|
* routes are supported.
|
||||||
@@ -582,25 +616,39 @@ public class VpnService extends Service {
|
|||||||
* Adding a route implicitly allows traffic from that address family
|
* Adding a route implicitly allows traffic from that address family
|
||||||
* (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
|
* (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.
|
* @throws IllegalArgumentException if the route is invalid.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder addRoute(@NonNull InetAddress address, int prefixLength) {
|
public Builder addRoute(@NonNull InetAddress address, int prefixLength) {
|
||||||
check(address, prefixLength);
|
checkNonPrefixBytes(address, prefixLength);
|
||||||
|
|
||||||
int offset = prefixLength / 8;
|
return addRoute(new IpPrefix(address, prefixLength), RouteInfo.RTN_UNICAST);
|
||||||
byte[] bytes = address.getAddress();
|
}
|
||||||
if (offset < bytes.length) {
|
|
||||||
for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) {
|
/**
|
||||||
if (bytes[offset] != 0) {
|
* Add a network route to the VPN interface. Both IPv4 and IPv6
|
||||||
throw new IllegalArgumentException("Bad address");
|
* 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
|
||||||
mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null, null,
|
*
|
||||||
RouteInfo.RTN_UNICAST));
|
* Calling this method overrides previous calls to {@link #excludeRoute} for the same
|
||||||
mConfig.updateAllowedFamilies(address);
|
* destination.
|
||||||
return this;
|
*
|
||||||
|
* 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
|
* Adding a route implicitly allows traffic from that address family
|
||||||
* (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
|
* (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.
|
* @throws IllegalArgumentException if the route is invalid.
|
||||||
* @see #addRoute(InetAddress, int)
|
* @see #addRoute(InetAddress, int)
|
||||||
*/
|
*/
|
||||||
@@ -619,6 +673,23 @@ public class VpnService extends Service {
|
|||||||
return addRoute(InetAddress.parseNumericAddress(address), prefixLength);
|
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
|
* Add a DNS server to the VPN connection. Both IPv4 and IPv6
|
||||||
* addresses are supported. If none is set, the DNS servers of
|
* addresses are supported. If none is set, the DNS servers of
|
||||||
@@ -900,5 +971,23 @@ public class VpnService extends Service {
|
|||||||
throw new IllegalStateException(e);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ import android.os.Parcel;
|
|||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import java.net.Inet4Address;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -93,8 +91,8 @@ public class VpnConfig implements Parcelable {
|
|||||||
public String interfaze;
|
public String interfaze;
|
||||||
public String session;
|
public String session;
|
||||||
public int mtu = -1;
|
public int mtu = -1;
|
||||||
public List<LinkAddress> addresses = new ArrayList<LinkAddress>();
|
public List<LinkAddress> addresses = new ArrayList<>();
|
||||||
public List<RouteInfo> routes = new ArrayList<RouteInfo>();
|
public List<RouteInfo> routes = new ArrayList<>();
|
||||||
public List<String> dnsServers;
|
public List<String> dnsServers;
|
||||||
public List<String> searchDomains;
|
public List<String> searchDomains;
|
||||||
public List<String> allowedApplications;
|
public List<String> allowedApplications;
|
||||||
@@ -114,12 +112,32 @@ public class VpnConfig implements Parcelable {
|
|||||||
public VpnConfig() {
|
public VpnConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAllowedFamilies(InetAddress address) {
|
public VpnConfig(VpnConfig other) {
|
||||||
if (address instanceof Inet4Address) {
|
user = other.user;
|
||||||
allowIPv4 = true;
|
interfaze = other.interfaze;
|
||||||
} else {
|
session = other.session;
|
||||||
allowIPv6 = true;
|
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) {
|
public void addLegacyRoutes(String routesStr) {
|
||||||
@@ -131,7 +149,6 @@ public class VpnConfig implements Parcelable {
|
|||||||
//each route is ip/prefix
|
//each route is ip/prefix
|
||||||
RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
|
RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
|
||||||
this.routes.add(info);
|
this.routes.add(info);
|
||||||
updateAllowedFamilies(info.getDestination().getAddress());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +161,6 @@ public class VpnConfig implements Parcelable {
|
|||||||
//each address is ip/prefix
|
//each address is ip/prefix
|
||||||
LinkAddress addr = new LinkAddress(address);
|
LinkAddress addr = new LinkAddress(address);
|
||||||
this.addresses.add(addr);
|
this.addresses.add(addr);
|
||||||
updateAllowedFamilies(addr.getAddress());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1208,8 +1208,11 @@ public class Vpn {
|
|||||||
for (RouteInfo route : mConfig.routes) {
|
for (RouteInfo route : mConfig.routes) {
|
||||||
lp.addRoute(route);
|
lp.addRoute(route);
|
||||||
InetAddress address = route.getDestination().getAddress();
|
InetAddress address = route.getDestination().getAddress();
|
||||||
allowIPv4 |= address instanceof Inet4Address;
|
|
||||||
allowIPv6 |= address instanceof Inet6Address;
|
if (route.getType() == RouteInfo.RTN_UNICAST) {
|
||||||
|
allowIPv4 |= address instanceof Inet4Address;
|
||||||
|
allowIPv6 |= address instanceof Inet6Address;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user