diff options
author | Chia-chi Yeh <chiachi@android.com> | 2011-07-14 15:05:05 -0700 |
---|---|---|
committer | Chia-chi Yeh <chiachi@android.com> | 2011-07-14 15:07:42 -0700 |
commit | 97a61565ea95472e65899070e64853f8c147bb11 (patch) | |
tree | fed415da0df68c5c06e67ac943d7d4251ba79c64 /services/java/com/android/server/connectivity | |
parent | 1591aa004557859742fb89190ce76cbbf3a1ef12 (diff) | |
download | frameworks_base-97a61565ea95472e65899070e64853f8c147bb11.zip frameworks_base-97a61565ea95472e65899070e64853f8c147bb11.tar.gz frameworks_base-97a61565ea95472e65899070e64853f8c147bb11.tar.bz2 |
VPN: Hook up the new control protocol and network state.
1. No more End-Of-Arguments.
2. Daemons close the control socket after they are initialized.
3. No more system properties.
4. ip-up-vpn now creates state to pass the configuration.
5. JNI methods are split again for legacy VPN.
Change-Id: I02fafdf01d425c965345ef712b2bd5fdee3a0cab
Diffstat (limited to 'services/java/com/android/server/connectivity')
-rw-r--r-- | services/java/com/android/server/connectivity/Vpn.java | 100 |
1 files changed, 69 insertions, 31 deletions
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index c185012..55ba8e2 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -41,6 +41,9 @@ import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.server.ConnectivityService.VpnCallback; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charsets; import java.util.Arrays; @@ -192,10 +195,15 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } // Configure the interface. Abort if any of these steps fails. - ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd( - jniConfigure(config.mtu, config.addresses, config.routes)); + ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); try { String interfaze = jniGetName(tun.getFd()); + if (jniSetAddresses(interfaze, config.addresses) < 1) { + throw new IllegalArgumentException("At least one address must be specified"); + } + if (config.routes != null) { + jniSetRoutes(interfaze, config.routes); + } if (mInterface != null && !mInterface.equals(interfaze)) { jniReset(mInterface); } @@ -279,8 +287,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } } - private native int jniConfigure(int mtu, String addresses, String routes); + private native int jniCreate(int mtu); private native String jniGetName(int tun); + private native int jniSetAddresses(String interfaze, String addresses); + private native int jniSetRoutes(String interfaze, String routes); private native void jniReset(String interfaze); private native int jniCheck(String interfaze); private native void jniProtect(int socket, String interfaze); @@ -323,7 +333,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { */ private class LegacyVpnRunner extends Thread { private static final String TAG = "LegacyVpnRunner"; - private static final String NONE = "--"; private final VpnConfig mConfig; private final String[] mDaemons; @@ -346,10 +355,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { public void exit() { // We assume that everything is reset after the daemons die. + interrupt(); for (String daemon : mDaemons) { SystemProperties.set("ctl.stop", daemon); } - interrupt(); } public LegacyVpnInfo getInfo() { @@ -380,7 +389,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { Thread.sleep(yield ? 200 : 1); } else { mInfo.state = LegacyVpnInfo.STATE_TIMEOUT; - throw new IllegalStateException("time is up"); + throw new IllegalStateException("Time is up"); } } @@ -404,12 +413,11 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } } - // Reset the properties. - SystemProperties.set("vpn.dns", NONE); - SystemProperties.set("vpn.via", NONE); - while (!NONE.equals(SystemProperties.get("vpn.dns")) || - !NONE.equals(SystemProperties.get("vpn.via"))) { - checkpoint(true); + // Clear the previous state. + File state = new File("/data/misc/vpn/state"); + state.delete(); + if (state.exists()) { + throw new IllegalStateException("Cannot delete the state"); } // Check if we need to restart any of the daemons. @@ -461,29 +469,34 @@ public class Vpn extends INetworkManagementEventObserver.Stub { OutputStream out = socket.getOutputStream(); for (String argument : arguments) { byte[] bytes = argument.getBytes(Charsets.UTF_8); - if (bytes.length >= 0xFFFF) { - throw new IllegalArgumentException("argument is too large"); + if (bytes.length > 0xFFFF) { + throw new IllegalArgumentException("Argument is too large"); } out.write(bytes.length >> 8); out.write(bytes.length); out.write(bytes); checkpoint(false); } - - // Send End-Of-Arguments. - out.write(0xFF); - out.write(0xFF); out.flush(); + socket.shutdownOutput(); + + // Wait for End-of-File. + InputStream in = socket.getInputStream(); + while (true) { + try { + if (in.read() == -1) { + break; + } + } catch (Exception e) { + // ignore + } + checkpoint(true); + } socket.close(); } - // Now here is the beast from the old days. We check few - // properties to figure out the current status. Ideally we - // can read things back from the sockets and get rid of the - // properties, but we have no time... - while (NONE.equals(SystemProperties.get("vpn.dns")) || - NONE.equals(SystemProperties.get("vpn.via"))) { - + // Wait for the daemons to create the new state. + while (!state.exists()) { // Check if a running daemon is dead. for (int i = 0; i < mDaemons.length; ++i) { String daemon = mDaemons[i]; @@ -495,20 +508,45 @@ public class Vpn extends INetworkManagementEventObserver.Stub { checkpoint(true); } - // Now we are connected. Get the interface. - mConfig.interfaze = SystemProperties.get("vpn.via"); + // Now we are connected. Read and parse the new state. + byte[] buffer = new byte[(int) state.length()]; + if (new FileInputStream(state).read(buffer) != buffer.length) { + throw new IllegalStateException("Cannot read the state"); + } + String[] parameters = new String(buffer, Charsets.UTF_8).split("\n", -1); + if (parameters.length != 6) { + throw new IllegalStateException("Cannot parse the state"); + } + + // Set the interface and the addresses in the config. + mConfig.interfaze = parameters[0].trim(); + mConfig.addresses = parameters[1].trim(); - // Get the DNS servers if they are not set in config. + // Set the routes if they are not set in the config. + if (mConfig.routes == null || mConfig.routes.isEmpty()) { + mConfig.routes = parameters[2].trim(); + } + + // Set the DNS servers if they are not set in the config. if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { - String dnsServers = SystemProperties.get("vpn.dns").trim(); + String dnsServers = parameters[3].trim(); if (!dnsServers.isEmpty()) { mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); } } - // TODO: support search domains from ISAKMP mode config. + // Set the search domains if they are not set in the config. + if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { + String searchDomains = parameters[4].trim(); + if (!searchDomains.isEmpty()) { + mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); + } + } + + // Set the routes. + jniSetRoutes(mConfig.interfaze, mConfig.routes); - // The final step must be synchronized. + // Here is the last step and it must be done synchronously. synchronized (Vpn.this) { // Check if the thread is interrupted while we are waiting. checkpoint(false); |