Loading vpn/java/android/net/vpn/IVpnService.aidl +10 −3 Original line number Diff line number Diff line Loading @@ -24,10 +24,11 @@ import android.net.vpn.VpnProfile; */ interface IVpnService { /** * Sets up the VPN connection. * Sets up a VPN connection. * @param profile the profile object * @param username the username for authentication * @param password the corresponding password for authentication * @return true if VPN is successfully connected */ boolean connect(in VpnProfile profile, String username, String password); Loading @@ -37,7 +38,13 @@ interface IVpnService { void disconnect(); /** * Makes the service broadcast the connectivity state. * Gets the the current connection state. */ void checkStatus(in VpnProfile profile); String getState(in VpnProfile profile); /** * Returns the idle state. * @return true if the system is not connecting/connected to a VPN */ boolean isIdle(); } vpn/java/android/net/vpn/VpnManager.java +72 −34 Original line number Diff line number Diff line Loading @@ -16,17 +16,19 @@ package android.net.vpn; import java.io.File; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Environment; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.util.Log; import com.android.server.vpn.VpnServiceBinder; /** * The class provides interface to manage all VPN-related tasks, including: * <ul> Loading @@ -40,8 +42,6 @@ import android.util.Log; * {@hide} */ public class VpnManager { // Action for broadcasting a connectivity state. private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity"; /** Key to the profile name of a connectivity broadcast event. */ public static final String BROADCAST_PROFILE_NAME = "profile_name"; /** Key to the connectivity state of a connectivity broadcast event. */ Loading Loading @@ -74,8 +74,10 @@ public class VpnManager { private static final String PACKAGE_PREFIX = VpnManager.class.getPackage().getName() + "."; // Action to start VPN service private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE"; // Action for broadcasting a connectivity state. private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity"; private static final String VPN_SERVICE_NAME = "vpn"; // Action to start VPN settings private static final String ACTION_VPN_SETTINGS = Loading @@ -96,13 +98,76 @@ public class VpnManager { return VpnType.values(); } public static void startVpnService(Context c) { ServiceManager.addService(VPN_SERVICE_NAME, new VpnServiceBinder(c)); } private Context mContext; private IVpnService mVpnService; /** * Creates a manager object with the specified context. */ public VpnManager(Context c) { mContext = c; createVpnServiceClient(); } private void createVpnServiceClient() { IBinder b = ServiceManager.getService(VPN_SERVICE_NAME); mVpnService = IVpnService.Stub.asInterface(b); } /** * Sets up a VPN connection. * @param profile the profile object * @param username the username for authentication * @param password the corresponding password for authentication * @return true if VPN is successfully connected */ public boolean connect(VpnProfile p, String username, String password) { try { return mVpnService.connect(p, username, password); } catch (RemoteException e) { Log.e(TAG, "connect()", e); return false; } } /** * Tears down the VPN connection. */ public void disconnect() { try { mVpnService.disconnect(); } catch (RemoteException e) { Log.e(TAG, "disconnect()", e); } } /** * Gets the the current connection state. */ public VpnState getState(VpnProfile p) { try { return Enum.valueOf(VpnState.class, mVpnService.getState(p)); } catch (RemoteException e) { Log.e(TAG, "getState()", e); return VpnState.IDLE; } } /** * Returns the idle state. * @return true if the system is not connecting/connected to a VPN */ public boolean isIdle() { try { return mVpnService.isIdle(); } catch (RemoteException e) { Log.e(TAG, "isIdle()", e); return true; } } /** Loading Loading @@ -134,33 +199,6 @@ public class VpnManager { } } /** * Starts the VPN service to establish VPN connection. */ public void startVpnService() { mContext.startService(new Intent(ACTION_VPN_SERVICE)); } /** * Stops the VPN service. */ public void stopVpnService() { mContext.stopService(new Intent(ACTION_VPN_SERVICE)); } /** * Binds the specified ServiceConnection with the VPN service. */ public boolean bindVpnService(ServiceConnection c) { if (!mContext.bindService(new Intent(ACTION_VPN_SERVICE), c, 0)) { Log.w(TAG, "failed to connect to VPN service"); return false; } else { Log.d(TAG, "succeeded to connect to VPN service"); return true; } } /** Broadcasts the connectivity state of the specified profile. */ public void broadcastConnectivity(String profileName, VpnState s) { broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR); Loading vpn/java/com/android/server/vpn/DaemonProxy.java 0 → 100644 +199 −0 Original line number Diff line number Diff line /* * 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.LocalSocket; import android.net.LocalSocketAddress; import android.net.vpn.VpnManager; import android.os.SystemProperties; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; /** * Proxy to start, stop and interact with a VPN daemon. * The daemon is expected to accept connection through Unix domain socket. * When the proxy successfully starts the daemon, it will establish a socket * connection with the daemon, to both send commands to the daemon and receive * response and connecting error code from the daemon. */ class DaemonProxy implements Serializable { private static final long serialVersionUID = 1L; private static final boolean DBG = true; private static final int WAITING_TIME = 15; // sec private static final String SVC_STATE_CMD_PREFIX = "init.svc."; private static final String SVC_START_CMD = "ctl.start"; private static final String SVC_STOP_CMD = "ctl.stop"; private static final String SVC_STATE_RUNNING = "running"; private static final String SVC_STATE_STOPPED = "stopped"; private static final int END_OF_ARGUMENTS = 255; private String mName; private String mTag; private transient LocalSocket mControlSocket; /** * Creates a proxy of the specified daemon. * @param daemonName name of the daemon */ DaemonProxy(String daemonName) { mName = daemonName; mTag = "SProxy_" + daemonName; } String getName() { return mName; } void start() throws IOException { String svc = mName; Log.i(mTag, "Start VPN daemon: " + svc); SystemProperties.set(SVC_START_CMD, svc); if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) { throw new IOException("cannot start service: " + svc); } else { mControlSocket = createServiceSocket(); } } void sendCommand(String ...args) throws IOException { OutputStream out = getControlSocketOutput(); for (String arg : args) outputString(out, arg); out.write(END_OF_ARGUMENTS); out.flush(); int result = getResultFromSocket(true); if (result != args.length) { throw new IOException("socket error, result from service: " + result); } } // returns 0 if nothing is in the receive buffer int getResultFromSocket() throws IOException { return getResultFromSocket(false); } void closeControlSocket() { if (mControlSocket == null) return; try { mControlSocket.close(); } catch (IOException e) { Log.w(mTag, "close control socket", e); } finally { mControlSocket = null; } } void stop() { String svc = mName; Log.i(mTag, "Stop VPN daemon: " + svc); SystemProperties.set(SVC_STOP_CMD, svc); boolean success = blockUntil(SVC_STATE_STOPPED, 5); if (DBG) Log.d(mTag, "stopping " + svc + ", success? " + success); } boolean isStopped() { String cmd = SVC_STATE_CMD_PREFIX + mName; return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd)); } private int getResultFromSocket(boolean blocking) throws IOException { LocalSocket s = mControlSocket; if (s == null) return 0; InputStream in = s.getInputStream(); if (!blocking && in.available() == 0) return 0; int data = in.read(); Log.i(mTag, "got data from control socket: " + data); return data; } private LocalSocket createServiceSocket() throws IOException { LocalSocket s = new LocalSocket(); LocalSocketAddress a = new LocalSocketAddress(mName, LocalSocketAddress.Namespace.RESERVED); // try a few times in case the service has not listen()ed IOException excp = null; for (int i = 0; i < 10; i++) { try { s.connect(a); return s; } catch (IOException e) { if (DBG) Log.d(mTag, "service not yet listen()ing; try again"); excp = e; sleep(500); } } throw excp; } private OutputStream getControlSocketOutput() throws IOException { if (mControlSocket != null) { return mControlSocket.getOutputStream(); } else { throw new IOException("no control socket available"); } } /** * Waits for the process to be in the expected state. The method returns * false if after the specified duration (in seconds), the process is still * not in the expected state. */ private boolean blockUntil(String expectedState, int waitTime) { String cmd = SVC_STATE_CMD_PREFIX + mName; int sleepTime = 200; // ms int n = waitTime * 1000 / sleepTime; for (int i = 0; i < n; i++) { if (expectedState.equals(SystemProperties.get(cmd))) { if (DBG) { Log.d(mTag, mName + " is " + expectedState + " after " + (i * sleepTime) + " msec"); } break; } sleep(sleepTime); } return expectedState.equals(SystemProperties.get(cmd)); } private void outputString(OutputStream out, String s) throws IOException { byte[] bytes = s.getBytes(); out.write(bytes.length); out.write(bytes); out.flush(); } private void sleep(int msec) { try { Thread.currentThread().sleep(msec); } catch (InterruptedException e) { throw new RuntimeException(e); } } } vpn/java/com/android/server/vpn/L2tpIpsecPskService.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * 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 = "racoon"; @Override protected void connect(String serverIp, String username, String password) throws IOException { L2tpIpsecPskProfile p = getProfile(); VpnDaemons daemons = getDaemons(); // IPSEC daemons.startIpsecForL2tp(serverIp, p.getPresharedKey()) .closeControlSocket(); sleep(2000); // 2 seconds // L2TP daemons.startL2tp(serverIp, (p.isSecretEnabled() ? p.getSecretString() : null), username, password); } } vpn/java/com/android/server/vpn/L2tpIpsecService.java 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * 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.L2tpIpsecProfile; import android.security.Credentials; import java.io.IOException; /** * The service that manages the certificate based L2TP-over-IPSec VPN connection. */ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> { private static final String IPSEC = "racoon"; @Override protected void connect(String serverIp, String username, String password) throws IOException { L2tpIpsecProfile p = getProfile(); VpnDaemons daemons = getDaemons(); // IPSEC DaemonProxy ipsec = daemons.startIpsecForL2tp(serverIp, Credentials.USER_PRIVATE_KEY + p.getUserCertificate(), Credentials.USER_CERTIFICATE + p.getUserCertificate(), Credentials.CA_CERTIFICATE + p.getCaCertificate()); ipsec.closeControlSocket(); sleep(2000); // 2 seconds // L2TP daemons.startL2tp(serverIp, (p.isSecretEnabled() ? p.getSecretString() : null), username, password); } } Loading
vpn/java/android/net/vpn/IVpnService.aidl +10 −3 Original line number Diff line number Diff line Loading @@ -24,10 +24,11 @@ import android.net.vpn.VpnProfile; */ interface IVpnService { /** * Sets up the VPN connection. * Sets up a VPN connection. * @param profile the profile object * @param username the username for authentication * @param password the corresponding password for authentication * @return true if VPN is successfully connected */ boolean connect(in VpnProfile profile, String username, String password); Loading @@ -37,7 +38,13 @@ interface IVpnService { void disconnect(); /** * Makes the service broadcast the connectivity state. * Gets the the current connection state. */ void checkStatus(in VpnProfile profile); String getState(in VpnProfile profile); /** * Returns the idle state. * @return true if the system is not connecting/connected to a VPN */ boolean isIdle(); }
vpn/java/android/net/vpn/VpnManager.java +72 −34 Original line number Diff line number Diff line Loading @@ -16,17 +16,19 @@ package android.net.vpn; import java.io.File; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Environment; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.util.Log; import com.android.server.vpn.VpnServiceBinder; /** * The class provides interface to manage all VPN-related tasks, including: * <ul> Loading @@ -40,8 +42,6 @@ import android.util.Log; * {@hide} */ public class VpnManager { // Action for broadcasting a connectivity state. private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity"; /** Key to the profile name of a connectivity broadcast event. */ public static final String BROADCAST_PROFILE_NAME = "profile_name"; /** Key to the connectivity state of a connectivity broadcast event. */ Loading Loading @@ -74,8 +74,10 @@ public class VpnManager { private static final String PACKAGE_PREFIX = VpnManager.class.getPackage().getName() + "."; // Action to start VPN service private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE"; // Action for broadcasting a connectivity state. private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity"; private static final String VPN_SERVICE_NAME = "vpn"; // Action to start VPN settings private static final String ACTION_VPN_SETTINGS = Loading @@ -96,13 +98,76 @@ public class VpnManager { return VpnType.values(); } public static void startVpnService(Context c) { ServiceManager.addService(VPN_SERVICE_NAME, new VpnServiceBinder(c)); } private Context mContext; private IVpnService mVpnService; /** * Creates a manager object with the specified context. */ public VpnManager(Context c) { mContext = c; createVpnServiceClient(); } private void createVpnServiceClient() { IBinder b = ServiceManager.getService(VPN_SERVICE_NAME); mVpnService = IVpnService.Stub.asInterface(b); } /** * Sets up a VPN connection. * @param profile the profile object * @param username the username for authentication * @param password the corresponding password for authentication * @return true if VPN is successfully connected */ public boolean connect(VpnProfile p, String username, String password) { try { return mVpnService.connect(p, username, password); } catch (RemoteException e) { Log.e(TAG, "connect()", e); return false; } } /** * Tears down the VPN connection. */ public void disconnect() { try { mVpnService.disconnect(); } catch (RemoteException e) { Log.e(TAG, "disconnect()", e); } } /** * Gets the the current connection state. */ public VpnState getState(VpnProfile p) { try { return Enum.valueOf(VpnState.class, mVpnService.getState(p)); } catch (RemoteException e) { Log.e(TAG, "getState()", e); return VpnState.IDLE; } } /** * Returns the idle state. * @return true if the system is not connecting/connected to a VPN */ public boolean isIdle() { try { return mVpnService.isIdle(); } catch (RemoteException e) { Log.e(TAG, "isIdle()", e); return true; } } /** Loading Loading @@ -134,33 +199,6 @@ public class VpnManager { } } /** * Starts the VPN service to establish VPN connection. */ public void startVpnService() { mContext.startService(new Intent(ACTION_VPN_SERVICE)); } /** * Stops the VPN service. */ public void stopVpnService() { mContext.stopService(new Intent(ACTION_VPN_SERVICE)); } /** * Binds the specified ServiceConnection with the VPN service. */ public boolean bindVpnService(ServiceConnection c) { if (!mContext.bindService(new Intent(ACTION_VPN_SERVICE), c, 0)) { Log.w(TAG, "failed to connect to VPN service"); return false; } else { Log.d(TAG, "succeeded to connect to VPN service"); return true; } } /** Broadcasts the connectivity state of the specified profile. */ public void broadcastConnectivity(String profileName, VpnState s) { broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR); Loading
vpn/java/com/android/server/vpn/DaemonProxy.java 0 → 100644 +199 −0 Original line number Diff line number Diff line /* * 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.LocalSocket; import android.net.LocalSocketAddress; import android.net.vpn.VpnManager; import android.os.SystemProperties; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; /** * Proxy to start, stop and interact with a VPN daemon. * The daemon is expected to accept connection through Unix domain socket. * When the proxy successfully starts the daemon, it will establish a socket * connection with the daemon, to both send commands to the daemon and receive * response and connecting error code from the daemon. */ class DaemonProxy implements Serializable { private static final long serialVersionUID = 1L; private static final boolean DBG = true; private static final int WAITING_TIME = 15; // sec private static final String SVC_STATE_CMD_PREFIX = "init.svc."; private static final String SVC_START_CMD = "ctl.start"; private static final String SVC_STOP_CMD = "ctl.stop"; private static final String SVC_STATE_RUNNING = "running"; private static final String SVC_STATE_STOPPED = "stopped"; private static final int END_OF_ARGUMENTS = 255; private String mName; private String mTag; private transient LocalSocket mControlSocket; /** * Creates a proxy of the specified daemon. * @param daemonName name of the daemon */ DaemonProxy(String daemonName) { mName = daemonName; mTag = "SProxy_" + daemonName; } String getName() { return mName; } void start() throws IOException { String svc = mName; Log.i(mTag, "Start VPN daemon: " + svc); SystemProperties.set(SVC_START_CMD, svc); if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) { throw new IOException("cannot start service: " + svc); } else { mControlSocket = createServiceSocket(); } } void sendCommand(String ...args) throws IOException { OutputStream out = getControlSocketOutput(); for (String arg : args) outputString(out, arg); out.write(END_OF_ARGUMENTS); out.flush(); int result = getResultFromSocket(true); if (result != args.length) { throw new IOException("socket error, result from service: " + result); } } // returns 0 if nothing is in the receive buffer int getResultFromSocket() throws IOException { return getResultFromSocket(false); } void closeControlSocket() { if (mControlSocket == null) return; try { mControlSocket.close(); } catch (IOException e) { Log.w(mTag, "close control socket", e); } finally { mControlSocket = null; } } void stop() { String svc = mName; Log.i(mTag, "Stop VPN daemon: " + svc); SystemProperties.set(SVC_STOP_CMD, svc); boolean success = blockUntil(SVC_STATE_STOPPED, 5); if (DBG) Log.d(mTag, "stopping " + svc + ", success? " + success); } boolean isStopped() { String cmd = SVC_STATE_CMD_PREFIX + mName; return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd)); } private int getResultFromSocket(boolean blocking) throws IOException { LocalSocket s = mControlSocket; if (s == null) return 0; InputStream in = s.getInputStream(); if (!blocking && in.available() == 0) return 0; int data = in.read(); Log.i(mTag, "got data from control socket: " + data); return data; } private LocalSocket createServiceSocket() throws IOException { LocalSocket s = new LocalSocket(); LocalSocketAddress a = new LocalSocketAddress(mName, LocalSocketAddress.Namespace.RESERVED); // try a few times in case the service has not listen()ed IOException excp = null; for (int i = 0; i < 10; i++) { try { s.connect(a); return s; } catch (IOException e) { if (DBG) Log.d(mTag, "service not yet listen()ing; try again"); excp = e; sleep(500); } } throw excp; } private OutputStream getControlSocketOutput() throws IOException { if (mControlSocket != null) { return mControlSocket.getOutputStream(); } else { throw new IOException("no control socket available"); } } /** * Waits for the process to be in the expected state. The method returns * false if after the specified duration (in seconds), the process is still * not in the expected state. */ private boolean blockUntil(String expectedState, int waitTime) { String cmd = SVC_STATE_CMD_PREFIX + mName; int sleepTime = 200; // ms int n = waitTime * 1000 / sleepTime; for (int i = 0; i < n; i++) { if (expectedState.equals(SystemProperties.get(cmd))) { if (DBG) { Log.d(mTag, mName + " is " + expectedState + " after " + (i * sleepTime) + " msec"); } break; } sleep(sleepTime); } return expectedState.equals(SystemProperties.get(cmd)); } private void outputString(OutputStream out, String s) throws IOException { byte[] bytes = s.getBytes(); out.write(bytes.length); out.write(bytes); out.flush(); } private void sleep(int msec) { try { Thread.currentThread().sleep(msec); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
vpn/java/com/android/server/vpn/L2tpIpsecPskService.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * 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 = "racoon"; @Override protected void connect(String serverIp, String username, String password) throws IOException { L2tpIpsecPskProfile p = getProfile(); VpnDaemons daemons = getDaemons(); // IPSEC daemons.startIpsecForL2tp(serverIp, p.getPresharedKey()) .closeControlSocket(); sleep(2000); // 2 seconds // L2TP daemons.startL2tp(serverIp, (p.isSecretEnabled() ? p.getSecretString() : null), username, password); } }
vpn/java/com/android/server/vpn/L2tpIpsecService.java 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * 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.L2tpIpsecProfile; import android.security.Credentials; import java.io.IOException; /** * The service that manages the certificate based L2TP-over-IPSec VPN connection. */ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> { private static final String IPSEC = "racoon"; @Override protected void connect(String serverIp, String username, String password) throws IOException { L2tpIpsecProfile p = getProfile(); VpnDaemons daemons = getDaemons(); // IPSEC DaemonProxy ipsec = daemons.startIpsecForL2tp(serverIp, Credentials.USER_PRIVATE_KEY + p.getUserCertificate(), Credentials.USER_CERTIFICATE + p.getUserCertificate(), Credentials.CA_CERTIFICATE + p.getCaCertificate()); ipsec.closeControlSocket(); sleep(2000); // 2 seconds // L2TP daemons.startL2tp(serverIp, (p.isSecretEnabled() ? p.getSecretString() : null), username, password); } }