summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Brubaker <cbrubaker@google.com>2014-03-21 20:52:14 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-03-21 20:52:14 +0000
commit1aad3ad4ec2137c5aa043f96ccc621a4faffeb56 (patch)
tree2377a1fdeedba349c553e03817ad68cbb053461e
parentde4e7b4947998638e0345ab9a181bf35a8827bef (diff)
parent4c5c33e5e6fb37f85977c70a0baba4e1ed51fe0d (diff)
downloadbase-1aad3ad4ec2137c5aa043f96ccc621a4faffeb56.tar.gz
Merge "Fix support for simultaneous VPN tuns" into klp-dev
-rw-r--r--services/java/com/android/server/connectivity/Vpn.java77
1 files changed, 51 insertions, 26 deletions
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 03405e7c0cbc..8f25860172de 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -352,6 +352,12 @@ public class Vpn extends BaseNetworkStateTracker {
Binder.restoreCallingIdentity(token);
}
+ // Save the old config in case we need to go back.
+ VpnConfig oldConfig = mConfig;
+ String oldInterface = mInterface;
+ Connection oldConnection = mConnection;
+ SparseBooleanArray oldUsers = mVpnUsers;
+
// Configure the interface. Abort if any of these steps fails.
ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
try {
@@ -371,12 +377,7 @@ public class Vpn extends BaseNetworkStateTracker {
new UserHandle(mUserId))) {
throw new IllegalStateException("Cannot bind " + config.user);
}
- if (mConnection != null) {
- mContext.unbindService(mConnection);
- }
- if (mInterface != null && !mInterface.equals(interfaze)) {
- jniReset(mInterface);
- }
+
mConnection = connection;
mInterface = interfaze;
@@ -385,50 +386,74 @@ public class Vpn extends BaseNetworkStateTracker {
config.interfaze = mInterface;
config.startTime = SystemClock.elapsedRealtime();
mConfig = config;
+
// Set up forwarding and DNS rules.
mVpnUsers = new SparseBooleanArray();
token = Binder.clearCallingIdentity();
try {
mCallback.setMarkedForwarding(mInterface);
- mCallback.setRoutes(interfaze, config.routes);
+ mCallback.setRoutes(mInterface, config.routes);
mCallback.override(mInterface, config.dnsServers, config.searchDomains);
addVpnUserLocked(mUserId);
-
+ // If we are owner assign all Restricted Users to this VPN
+ if (mUserId == UserHandle.USER_OWNER) {
+ for (UserInfo user : mgr.getUsers()) {
+ if (user.isRestricted()) {
+ try {
+ addVpnUserLocked(user.id);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Failed to add user " + user.id + " to owner's VPN");
+ }
+ }
+ }
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
+ if (oldConnection != null) {
+ mContext.unbindService(oldConnection);
+ }
+ if (oldInterface != null && !oldInterface.equals(interfaze)) {
+ // 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.
+ token = Binder.clearCallingIdentity();
+ try {
+ final int size = oldUsers.size();
+ final boolean forwardDns = (oldConfig.dnsServers != null &&
+ oldConfig.dnsServers.size() != 0);
+ for (int i = 0; i < size; i++) {
+ int user = oldUsers.keyAt(i);
+ mCallback.clearUserForwarding(oldInterface, user, forwardDns);
+ }
+ mCallback.clearMarkedForwarding(oldInterface);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ jniReset(oldInterface);
+ }
} catch (RuntimeException e) {
updateState(DetailedState.FAILED, "establish");
IoUtils.closeQuietly(tun);
// make sure marked forwarding is cleared if it was set
+ token = Binder.clearCallingIdentity();
try {
mCallback.clearMarkedForwarding(mInterface);
} catch (Exception ingored) {
// ignored
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
+ // restore old state
+ mConfig = oldConfig;
+ mConnection = oldConnection;
+ mVpnUsers = oldUsers;
+ mInterface = oldInterface;
throw e;
}
Log.i(TAG, "Established by " + config.user + " on " + mInterface);
-
- // If we are owner assign all Restricted Users to this VPN
- if (mUserId == UserHandle.USER_OWNER) {
- token = Binder.clearCallingIdentity();
- try {
- for (UserInfo user : mgr.getUsers()) {
- if (user.isRestricted()) {
- try {
- addVpnUserLocked(user.id);
- } catch (Exception e) {
- Log.wtf(TAG, "Failed to add user " + user.id + " to owner's VPN");
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
// TODO: ensure that contract class eventually marks as connected
updateState(DetailedState.AUTHENTICATING, "establish");
return tun;