Merge "Support seamless handover between VPN fds." into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f35fd8653c
@@ -117,6 +117,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
@@ -895,6 +896,42 @@ public class Vpn {
|
|||||||
.compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
|
.compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to perform a seamless handover of VPNs by only updating LinkProperties without
|
||||||
|
* registering a new NetworkAgent. This is not always possible if the new VPN configuration
|
||||||
|
* has certain changes, in which case this method would just return {@code false}.
|
||||||
|
*/
|
||||||
|
private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) {
|
||||||
|
// NetworkMisc cannot be updated without registering a new NetworkAgent.
|
||||||
|
if (oldConfig.allowBypass != mConfig.allowBypass) {
|
||||||
|
Log.i(TAG, "Handover not possible due to changes to allowBypass");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we currently do not support seamless handover if the allowed or disallowed
|
||||||
|
// applications have changed. Consider diffing UID ranges and only applying the delta.
|
||||||
|
if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) ||
|
||||||
|
!Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) {
|
||||||
|
Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkProperties lp = makeLinkProperties();
|
||||||
|
final boolean hadInternetCapability = mNetworkCapabilities.hasCapability(
|
||||||
|
NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||||
|
final boolean willHaveInternetCapability = providesRoutesToMostDestinations(lp);
|
||||||
|
if (hadInternetCapability != willHaveInternetCapability) {
|
||||||
|
// A seamless handover would have led to a change to INTERNET capability, which
|
||||||
|
// is supposed to be immutable for a given network. In this case bail out and do not
|
||||||
|
// perform handover.
|
||||||
|
Log.i(TAG, "Handover not possible due to changes to INTERNET capability");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
agent.sendLinkProperties(lp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void agentConnect() {
|
private void agentConnect() {
|
||||||
LinkProperties lp = makeLinkProperties();
|
LinkProperties lp = makeLinkProperties();
|
||||||
|
|
||||||
@@ -1003,13 +1040,11 @@ public class Vpn {
|
|||||||
String oldInterface = mInterface;
|
String oldInterface = mInterface;
|
||||||
Connection oldConnection = mConnection;
|
Connection oldConnection = mConnection;
|
||||||
NetworkAgent oldNetworkAgent = mNetworkAgent;
|
NetworkAgent oldNetworkAgent = mNetworkAgent;
|
||||||
mNetworkAgent = null;
|
|
||||||
Set<UidRange> oldUsers = mNetworkCapabilities.getUids();
|
Set<UidRange> oldUsers = mNetworkCapabilities.getUids();
|
||||||
|
|
||||||
// Configure the interface. Abort if any of these steps fails.
|
// Configure the interface. Abort if any of these steps fails.
|
||||||
ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
|
ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
|
||||||
try {
|
try {
|
||||||
updateState(DetailedState.CONNECTING, "establish");
|
|
||||||
String interfaze = jniGetName(tun.getFd());
|
String interfaze = jniGetName(tun.getFd());
|
||||||
|
|
||||||
// TEMP use the old jni calls until there is support for netd address setting
|
// TEMP use the old jni calls until there is support for netd address setting
|
||||||
@@ -1036,16 +1071,27 @@ public class Vpn {
|
|||||||
config.startTime = SystemClock.elapsedRealtime();
|
config.startTime = SystemClock.elapsedRealtime();
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
|
|
||||||
|
// Set up forwarding and DNS rules.
|
||||||
|
// First attempt to do a seamless handover that only changes the interface name and
|
||||||
|
// parameters. If that fails, disconnect.
|
||||||
|
if (oldConfig != null
|
||||||
|
&& updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) {
|
||||||
|
// Keep mNetworkAgent unchanged
|
||||||
|
} else {
|
||||||
|
mNetworkAgent = null;
|
||||||
|
updateState(DetailedState.CONNECTING, "establish");
|
||||||
// Set up forwarding and DNS rules.
|
// Set up forwarding and DNS rules.
|
||||||
agentConnect();
|
agentConnect();
|
||||||
|
// Remove the old tun's user forwarding rules
|
||||||
|
// The new tun's user rules have already been added above so they will take over
|
||||||
|
// as rules are deleted. This prevents data leakage as the rules are moved over.
|
||||||
|
agentDisconnect(oldNetworkAgent);
|
||||||
|
}
|
||||||
|
|
||||||
if (oldConnection != null) {
|
if (oldConnection != null) {
|
||||||
mContext.unbindService(oldConnection);
|
mContext.unbindService(oldConnection);
|
||||||
}
|
}
|
||||||
// Remove the old tun's user forwarding rules
|
|
||||||
// The new tun's user rules have already been added so they will take over
|
|
||||||
// as rules are deleted. This prevents data leakage as the rules are moved over.
|
|
||||||
agentDisconnect(oldNetworkAgent);
|
|
||||||
if (oldInterface != null && !oldInterface.equals(interfaze)) {
|
if (oldInterface != null && !oldInterface.equals(interfaze)) {
|
||||||
jniReset(oldInterface);
|
jniReset(oldInterface);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user