diff options
author | Hung-ying Tyan <tyanh@google.com> | 2009-06-27 15:59:44 +0800 |
---|---|---|
committer | Hung-ying Tyan <tyanh@google.com> | 2009-06-27 16:08:01 +0800 |
commit | 2b04d2980aca13c47211e857fc95787122c0fe91 (patch) | |
tree | 2786efe89f966303fadb0a063f540ca9bdbd67d7 | |
parent | 5c7d9e8194900a2b1699cd57f95b22ca5f7b9be2 (diff) | |
download | frameworks_base-2b04d2980aca13c47211e857fc95787122c0fe91.zip frameworks_base-2b04d2980aca13c47211e857fc95787122c0fe91.tar.gz frameworks_base-2b04d2980aca13c47211e857fc95787122c0fe91.tar.bz2 |
Revise VpnService to use new vpn.* properties.
* Changes
+ Make VpnService get dns info from vpn.dns1/dns2 and set
net.dns1/dns2.
+ Make VpnService wait on vpn.up instead of monitoring on ip-up-vpn.
+ Change commands sent to racoon.
+ Remove original sendCommand() from AndroidServiceProxy and rename
sendCommand2() to sendCommand().
+ Add L2tpIpsecPskService.java.
+ Add short stop after sending ipsec command.
5 files changed, 103 insertions, 198 deletions
diff --git a/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java b/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java index 2ad218f..7dd9d9e 100644 --- a/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java +++ b/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java @@ -78,20 +78,10 @@ public class AndroidServiceProxy extends ProcessProxy { /** * Sends a command with arguments to the service through the control socket. - * Each argument is sent as a C-style zero-terminated string. */ public void sendCommand(String ...args) throws IOException { OutputStream out = getControlSocketOutput(); for (String arg : args) outputString(out, arg); - checkSocketResult(); - } - - /** - * Sends a command with arguments to the service through the control socket. - */ - public void sendCommand2(String ...args) throws IOException { - OutputStream out = getControlSocketOutput(); - for (String arg : args) outputString2(out, arg); out.write(END_OF_ARGUMENTS); out.flush(); checkSocketResult(); @@ -128,8 +118,9 @@ public class AndroidServiceProxy extends ProcessProxy { if (data == 0) { // re-establish the connection: - // synchronized here so that checkSocketResult() returns - // when new mKeepaliveSocket is available for next cmd + // synchronized here so that checkSocketResult() + // returns when new mKeepaliveSocket is available for + // next cmd synchronized (this) { setResultAndCloseControlSocket((byte) data); s = mKeepaliveSocket = createServiceSocket(); @@ -244,12 +235,6 @@ public class AndroidServiceProxy extends ProcessProxy { } private void outputString(OutputStream out, String s) throws IOException { - out.write(s.getBytes()); - out.write(0); - out.flush(); - } - - private void outputString2(OutputStream out, String s) throws IOException { byte[] bytes = s.getBytes(); out.write(bytes.length); out.write(bytes); diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java new file mode 100644 index 0000000..6abf81c --- /dev/null +++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vpn; + +import android.net.vpn.L2tpIpsecPskProfile; + +import java.io.IOException; + +/** + * The service that manages the preshared key based L2TP-over-IPSec VPN + * connection. + */ +class L2tpIpsecPskService extends VpnService<L2tpIpsecPskProfile> { + private static final String IPSEC_DAEMON = "racoon"; + + @Override + protected void connect(String serverIp, String username, String password) + throws IOException { + String hostIp = getHostIp(); + L2tpIpsecPskProfile p = getProfile(); + + // IPSEC + AndroidServiceProxy ipsecService = startService(IPSEC_DAEMON); + ipsecService.sendCommand(hostIp, serverIp, L2tpService.L2TP_PORT, + p.getPresharedKey()); + + sleep(2000); // 2 seconds + + // L2TP + MtpdHelper.sendCommand(this, L2tpService.L2TP_DAEMON, serverIp, + L2tpService.L2TP_PORT, + (p.isSecretEnabled() ? p.getSecretString() : null), + username, password); + } +} diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java index 877fa6b..bd14110 100644 --- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java +++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java @@ -22,7 +22,7 @@ import android.security.Keystore; import java.io.IOException; /** - * The service that manages the L2TP-over-IPSec VPN connection. + * The service that manages the certificate based L2TP-over-IPSec VPN connection. */ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> { private static final String IPSEC_DAEMON = "racoon"; @@ -34,11 +34,10 @@ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> { // IPSEC AndroidServiceProxy ipsecService = startService(IPSEC_DAEMON); - ipsecService.sendCommand( - String.format("SETKEY %s %s", hostIp, serverIp)); - ipsecService.sendCommand(String.format("SET_CERTS %s %s %s %s", - serverIp, getCaCertPath(), getUserCertPath(), - getUserkeyPath())); + ipsecService.sendCommand(hostIp, serverIp, L2tpService.L2TP_PORT, + getUserkeyPath(), getUserCertPath(), getCaCertPath()); + + sleep(2000); // 2 seconds // L2TP L2tpIpsecProfile p = getProfile(); diff --git a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java index 6160900..16d253a 100644 --- a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java +++ b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java @@ -38,7 +38,7 @@ class MtpdHelper { addPppArguments(vpnService, args, serverIp, username, password); AndroidServiceProxy mtpd = vpnService.startService(MTPD_SERVICE); - mtpd.sendCommand2(args.toArray(new String[args.size()])); + mtpd.sendCommand(args.toArray(new String[args.size()])); } private static void addPppArguments(VpnService<?> vpnService, diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java index 44127ff..6e5d46b 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java @@ -24,14 +24,12 @@ import android.net.NetworkUtils; import android.net.vpn.VpnManager; import android.net.vpn.VpnProfile; import android.net.vpn.VpnState; -import android.os.FileObserver; import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; -import java.io.File; import java.io.IOException; import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.Socket; import java.util.ArrayList; @@ -43,21 +41,18 @@ import java.util.List; */ abstract class VpnService<E extends VpnProfile> { private static final int NOTIFICATION_ID = 1; - private static final String PROFILES_ROOT = VpnManager.PROFILES_PATH + "/"; - public static final String DEFAULT_CONFIG_PATH = "/etc"; - private static final int DNS_TIMEOUT = 3000; // ms private static final String DNS1 = "net.dns1"; private static final String DNS2 = "net.dns2"; + private static final String VPN_DNS1 = "vpn.dns1"; + private static final String VPN_DNS2 = "vpn.dns2"; + private static final String VPN_UP = "vpn.up"; + private static final String VPN_IS_UP = "1"; + private static final String VPN_IS_DOWN = "0"; + private static final String REMOTE_IP = "net.ipremote"; private static final String DNS_DOMAIN_SUFFICES = "net.dns.search"; - private static final String SERVER_IP = "net.vpn.server_ip"; - - private static final int VPN_TIMEOUT = 30000; // milliseconds - private static final int ONE_SECOND = 1000; // milliseconds - private static final int FIVE_SECOND = 5000; // milliseconds - private static final String LOGWRAPPER = "/system/bin/logwrapper"; private final String TAG = VpnService.class.getSimpleName(); E mProfile; @@ -76,13 +71,6 @@ abstract class VpnService<E extends VpnProfile> { private long mStartTime; // VPN connection start time - // monitors if the VPN connection is sucessfully established - private FileMonitor mConnectMonitor; - - // watch dog timer; fired up if the connection cannot be established within - // VPN_TIMEOUT - private Object mWatchdog; - // for helping managing multiple Android services private ServiceHelper mServiceHelper = new ServiceHelper(); @@ -110,19 +98,6 @@ abstract class VpnService<E extends VpnProfile> { return mServiceHelper.startService(serviceName); } - protected String getPppOptionFilePath() throws IOException { - String subpath = getProfileSubpath("/ppp/peers"); - String[] kids = new File(subpath).list(); - if ((kids == null) || (kids.length == 0)) { - throw new IOException("no option file found in " + subpath); - } - if (kids.length > 1) { - Log.w(TAG, "more than one option file found in " + subpath - + ", arbitrarily choose " + kids[0]); - } - return subpath + "/" + kids[0]; - } - /** * Returns the VPN profile associated with the connection. */ @@ -131,23 +106,6 @@ abstract class VpnService<E extends VpnProfile> { } /** - * Returns the profile path where configuration files reside. - */ - protected String getProfilePath() throws IOException { - String path = PROFILES_ROOT + mProfile.getId(); - File dir = new File(path); - if (!dir.exists()) throw new IOException("Profile dir does not exist"); - return path; - } - - /** - * Returns the path where default configuration files reside. - */ - protected String getDefaultConfigPath() throws IOException { - return DEFAULT_CONFIG_PATH; - } - - /** * Returns the host IP for establishing the VPN connection. */ protected String getHostIp() throws IOException { @@ -178,14 +136,6 @@ abstract class VpnService<E extends VpnProfile> { } /** - * Returns the path of the script file that is executed when the VPN - * connection is established. - */ - protected String getConnectMonitorFile() { - return "/etc/ppp/ip-up-vpn"; - } - - /** * Sets the system property. The method is blocked until the value is * settled in. * @param name the name of the property @@ -222,10 +172,10 @@ abstract class VpnService<E extends VpnProfile> { broadcastConnectivity(VpnState.CONNECTING); String serverIp = getIp(getProfile().getServerName()); - setSystemProperty(SERVER_IP, serverIp); - onBeforeConnect(); + onBeforeConnect(); connect(serverIp, username, password); + waitUntilConnectedOrTimedout(); } synchronized void onDisconnect(boolean cleanUpServices) { @@ -259,39 +209,36 @@ abstract class VpnService<E extends VpnProfile> { } } - private void createConnectMonitor() { - mConnectMonitor = new FileMonitor(getConnectMonitorFile(), - new Runnable() { - public void run() { - onConnectMonitorTriggered(); - } - }); - } - private void onBeforeConnect() { mNotification.disableNotification(); - createConnectMonitor(); - mConnectMonitor.startWatching(); - saveOriginalDnsProperties(); + SystemProperties.set(VPN_DNS1, "-"); + SystemProperties.set(VPN_DNS2, "-"); + SystemProperties.set(VPN_UP, VPN_IS_DOWN); + Log.d(TAG, " VPN UP: " + SystemProperties.get(VPN_UP)); + } - mWatchdog = startTimer(VPN_TIMEOUT, new Runnable() { - public void run() { - synchronized (VpnService.this) { - if (mState == VpnState.CONNECTING) { - Log.d(TAG, " watchdog timer is fired !!"); - onError(); - } - } + private void waitUntilConnectedOrTimedout() { + sleep(2000); // 2 seconds + for (int i = 0; i < 60; i++) { + if (VPN_IS_UP.equals(SystemProperties.get(VPN_UP))) { + onConnected(); + return; + } + sleep(500); // 0.5 second + } + + synchronized (this) { + if (mState == VpnState.CONNECTING) { + Log.d(TAG, " connecting timed out !!"); + onError(); } - }); + } } - private synchronized void onConnectMonitorTriggered() { - Log.d(TAG, "onConnectMonitorTriggered()"); + private synchronized void onConnected() { + Log.d(TAG, "onConnected()"); - stopTimer(mWatchdog); - mConnectMonitor.stopWatching(); saveVpnDnsProperties(); saveAndSetDomainSuffices(); startConnectivityMonitor(); @@ -310,8 +257,6 @@ abstract class VpnService<E extends VpnProfile> { restoreOriginalDnsProperties(); restoreOriginalDomainSuffices(); - if (mConnectMonitor != null) mConnectMonitor.stopWatching(); - if (mWatchdog != null) stopTimer(mWatchdog); mState = VpnState.IDLE; broadcastConnectivity(VpnState.IDLE); @@ -345,13 +290,6 @@ abstract class VpnService<E extends VpnProfile> { } } - private void saveOriginalDnsProperties() { - mOriginalDns1 = SystemProperties.get(DNS1); - mOriginalDns2 = SystemProperties.get(DNS2); - Log.d(TAG, String.format("save original dns prop: %s, %s", - mOriginalDns1, mOriginalDns2)); - } - private void restoreOriginalDnsProperties() { // restore only if they are not overridden if (mVpnDns1.equals(SystemProperties.get(DNS1))) { @@ -365,15 +303,21 @@ abstract class VpnService<E extends VpnProfile> { } private void saveVpnDnsProperties() { - mVpnDns1 = mVpnDns2 = ""; + mOriginalDns1 = mOriginalDns2 = ""; for (int i = 0; i < 10; i++) { - mVpnDns1 = SystemProperties.get(DNS1); - mVpnDns2 = SystemProperties.get(DNS2); - if (mVpnDns1.equals(mOriginalDns1)) { + mVpnDns1 = SystemProperties.get(VPN_DNS1); + mVpnDns2 = SystemProperties.get(VPN_DNS2); + if (mOriginalDns1.equals(mVpnDns1)) { Log.d(TAG, "wait for vpn dns to settle in..." + i); sleep(500); } else { - Log.d(TAG, String.format("save vpn dns prop: %s, %s", + mOriginalDns1 = SystemProperties.get(DNS1); + mOriginalDns2 = SystemProperties.get(DNS2); + SystemProperties.set(DNS1, mVpnDns1); + SystemProperties.set(DNS2, mVpnDns2); + Log.d(TAG, String.format("save original dns prop: %s, %s", + mOriginalDns1, mOriginalDns2)); + Log.d(TAG, String.format("set vpn dns prop: %s, %s", mVpnDns1, mVpnDns2)); return; } @@ -381,23 +325,11 @@ abstract class VpnService<E extends VpnProfile> { Log.e(TAG, "saveVpnDnsProperties(): DNS not updated??"); } - private void restoreVpnDnsProperties() { - if (isNullOrEmpty(mVpnDns1) && isNullOrEmpty(mVpnDns2)) { - return; - } - Log.d(TAG, String.format("restore vpn dns prop: %s --> %s", - SystemProperties.get(DNS1), mVpnDns1)); - Log.d(TAG, String.format("restore vpn dns prop: %s --> %s", - SystemProperties.get(DNS2), mVpnDns2)); - SystemProperties.set(DNS1, mVpnDns1); - SystemProperties.set(DNS2, mVpnDns2); - } - private void saveAndSetDomainSuffices() { mOriginalDomainSuffices = SystemProperties.get(DNS_DOMAIN_SUFFICES); Log.d(TAG, "save original dns search: " + mOriginalDomainSuffices); String list = mProfile.getDomainSuffices(); - if (!isNullOrEmpty(list)) { + if (!TextUtils.isEmpty(list)) { SystemProperties.set(DNS_DOMAIN_SUFFICES, list); } } @@ -423,7 +355,7 @@ abstract class VpnService<E extends VpnProfile> { if (mState != VpnState.CONNECTED) break; mNotification.update(); checkConnectivity(); - VpnService.this.wait(ONE_SECOND); + VpnService.this.wait(1000); // 1 second } } } catch (InterruptedException e) { @@ -446,32 +378,6 @@ abstract class VpnService<E extends VpnProfile> { } } - private Object startTimer(final int milliseconds, final Runnable task) { - Thread thread = new Thread(new Runnable() { - public void run() { - Log.d(TAG, "watchdog timer started"); - Thread t = Thread.currentThread(); - try { - synchronized (t) { - t.wait(milliseconds); - } - task.run(); - } catch (InterruptedException e) { - // ignored - } - Log.d(TAG, "watchdog timer stopped"); - } - }); - thread.start(); - return thread; - } - - private void stopTimer(Object timer) { - synchronized (timer) { - timer.notify(); - } - } - private String reallyGetHostIp() throws IOException { Enumeration<NetworkInterface> ifces = NetworkInterface.getNetworkInterfaces(); @@ -487,33 +393,13 @@ abstract class VpnService<E extends VpnProfile> { throw new IOException("Host IP is not available"); } - private String getProfileSubpath(String subpath) throws IOException { - String path = getProfilePath() + subpath; - if (new File(path).exists()) { - return path; - } else { - Log.w(TAG, "Profile subpath does not exist: " + path - + ", use default one"); - String path2 = getDefaultConfigPath() + subpath; - if (!new File(path2).exists()) { - throw new IOException("Profile subpath does not exist at " - + path + " or " + path2); - } - return path2; - } - } - - private void sleep(int ms) { + protected void sleep(int ms) { try { Thread.currentThread().sleep(ms); } catch (InterruptedException e) { } } - private static boolean isNullOrEmpty(String message) { - return ((message == null) || (message.length() == 0)); - } - private InetAddress toInetAddress(int addr) throws IOException { byte[] aa = new byte[4]; for (int i= 0; i < aa.length; i++) { @@ -564,20 +450,6 @@ abstract class VpnService<E extends VpnProfile> { } } - private class FileMonitor extends FileObserver { - private Runnable mCallback; - - FileMonitor(String path, Runnable callback) { - super(path, CLOSE_NOWRITE); - mCallback = callback; - } - - @Override - public void onEvent(int event, String path) { - if ((event & CLOSE_NOWRITE) > 0) mCallback.run(); - } - } - // Helper class for showing, updating notification. private class NotificationHelper { void update() { |