Home | History | Annotate | Download | only in connectivity
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.connectivity;
     18 
     19 import static android.Manifest.permission.BIND_VPN_SERVICE;
     20 import static android.os.UserHandle.PER_USER_RANGE;
     21 import static android.net.RouteInfo.RTN_THROW;
     22 import static android.net.RouteInfo.RTN_UNREACHABLE;
     23 import static android.system.OsConstants.AF_INET;
     24 import static android.system.OsConstants.AF_INET6;
     25 
     26 import android.Manifest;
     27 import android.app.AppGlobals;
     28 import android.app.AppOpsManager;
     29 import android.app.PendingIntent;
     30 import android.content.BroadcastReceiver;
     31 import android.content.ComponentName;
     32 import android.content.Context;
     33 import android.content.Intent;
     34 import android.content.IntentFilter;
     35 import android.content.ServiceConnection;
     36 import android.content.pm.ApplicationInfo;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.PackageManager.NameNotFoundException;
     39 import android.content.pm.ResolveInfo;
     40 import android.content.pm.UserInfo;
     41 import android.net.ConnectivityManager;
     42 import android.net.IConnectivityManager;
     43 import android.net.INetworkManagementEventObserver;
     44 import android.net.IpPrefix;
     45 import android.net.LinkAddress;
     46 import android.net.LinkProperties;
     47 import android.net.LocalSocket;
     48 import android.net.LocalSocketAddress;
     49 import android.net.Network;
     50 import android.net.NetworkAgent;
     51 import android.net.NetworkCapabilities;
     52 import android.net.NetworkInfo;
     53 import android.net.NetworkInfo.DetailedState;
     54 import android.net.NetworkMisc;
     55 import android.net.RouteInfo;
     56 import android.net.UidRange;
     57 import android.os.Binder;
     58 import android.os.FileUtils;
     59 import android.os.IBinder;
     60 import android.os.INetworkManagementService;
     61 import android.os.Looper;
     62 import android.os.Parcel;
     63 import android.os.ParcelFileDescriptor;
     64 import android.os.Process;
     65 import android.os.RemoteException;
     66 import android.os.SystemClock;
     67 import android.os.SystemService;
     68 import android.os.UserHandle;
     69 import android.os.UserManager;
     70 import android.security.Credentials;
     71 import android.security.KeyStore;
     72 import android.util.Log;
     73 
     74 import com.android.internal.annotations.GuardedBy;
     75 import com.android.internal.net.LegacyVpnInfo;
     76 import com.android.internal.net.VpnConfig;
     77 import com.android.internal.net.VpnProfile;
     78 import com.android.server.net.BaseNetworkObserver;
     79 
     80 import libcore.io.IoUtils;
     81 
     82 import java.io.File;
     83 import java.io.IOException;
     84 import java.io.InputStream;
     85 import java.io.OutputStream;
     86 import java.net.Inet4Address;
     87 import java.net.Inet6Address;
     88 import java.net.InetAddress;
     89 import java.nio.charset.StandardCharsets;
     90 import java.util.ArrayList;
     91 import java.util.Arrays;
     92 import java.util.List;
     93 import java.util.SortedSet;
     94 import java.util.TreeSet;
     95 import java.util.concurrent.atomic.AtomicInteger;
     96 
     97 /**
     98  * @hide
     99  */
    100 public class Vpn {
    101     private static final String NETWORKTYPE = "VPN";
    102     private static final String TAG = "Vpn";
    103     private static final boolean LOGD = true;
    104 
    105     // TODO: create separate trackers for each unique VPN to support
    106     // automated reconnection
    107 
    108     private Context mContext;
    109     private NetworkInfo mNetworkInfo;
    110     private String mPackage;
    111     private int mOwnerUID;
    112     private String mInterface;
    113     private Connection mConnection;
    114     private LegacyVpnRunner mLegacyVpnRunner;
    115     private PendingIntent mStatusIntent;
    116     private volatile boolean mEnableTeardown = true;
    117     private final IConnectivityManager mConnService;
    118     private final INetworkManagementService mNetd;
    119     private VpnConfig mConfig;
    120     private NetworkAgent mNetworkAgent;
    121     private final Looper mLooper;
    122     private final NetworkCapabilities mNetworkCapabilities;
    123 
    124     /* list of users using this VPN. */
    125     @GuardedBy("this")
    126     private List<UidRange> mVpnUsers = null;
    127     private BroadcastReceiver mUserIntentReceiver = null;
    128 
    129     // Handle of user initiating VPN.
    130     private final int mUserHandle;
    131 
    132     public Vpn(Looper looper, Context context, INetworkManagementService netService,
    133             IConnectivityManager connService, int userHandle) {
    134         mContext = context;
    135         mNetd = netService;
    136         mConnService = connService;
    137         mUserHandle = userHandle;
    138         mLooper = looper;
    139 
    140         mPackage = VpnConfig.LEGACY_VPN;
    141         mOwnerUID = getAppUid(mPackage, mUserHandle);
    142 
    143         try {
    144             netService.registerObserver(mObserver);
    145         } catch (RemoteException e) {
    146             Log.wtf(TAG, "Problem registering observer", e);
    147         }
    148         if (userHandle == UserHandle.USER_OWNER) {
    149             // Owner's VPN also needs to handle restricted users
    150             mUserIntentReceiver = new BroadcastReceiver() {
    151                 @Override
    152                 public void onReceive(Context context, Intent intent) {
    153                     final String action = intent.getAction();
    154                     final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
    155                             UserHandle.USER_NULL);
    156                     if (userHandle == UserHandle.USER_NULL) return;
    157 
    158                     if (Intent.ACTION_USER_ADDED.equals(action)) {
    159                         onUserAdded(userHandle);
    160                     } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
    161                         onUserRemoved(userHandle);
    162                     }
    163                 }
    164             };
    165 
    166             IntentFilter intentFilter = new IntentFilter();
    167             intentFilter.addAction(Intent.ACTION_USER_ADDED);
    168             intentFilter.addAction(Intent.ACTION_USER_REMOVED);
    169             mContext.registerReceiverAsUser(
    170                     mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
    171         }
    172 
    173         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, "");
    174         // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332
    175         mNetworkCapabilities = new NetworkCapabilities();
    176         mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
    177         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
    178     }
    179 
    180     /**
    181      * Set if this object is responsible for watching for {@link NetworkInfo}
    182      * teardown. When {@code false}, teardown is handled externally by someone
    183      * else.
    184      */
    185     public void setEnableTeardown(boolean enableTeardown) {
    186         mEnableTeardown = enableTeardown;
    187     }
    188 
    189     /**
    190      * Update current state, dispaching event to listeners.
    191      */
    192     private void updateState(DetailedState detailedState, String reason) {
    193         if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
    194         mNetworkInfo.setDetailedState(detailedState, reason, null);
    195         if (mNetworkAgent != null) {
    196             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    197         }
    198     }
    199 
    200     /**
    201      * Prepare for a VPN application. This method is designed to solve
    202      * race conditions. It first compares the current prepared package
    203      * with {@code oldPackage}. If they are the same, the prepared
    204      * package is revoked and replaced with {@code newPackage}. If
    205      * {@code oldPackage} is {@code null}, the comparison is omitted.
    206      * If {@code newPackage} is the same package or {@code null}, the
    207      * revocation is omitted. This method returns {@code true} if the
    208      * operation is succeeded.
    209      *
    210      * Legacy VPN is handled specially since it is not a real package.
    211      * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
    212      * it can be revoked by itself.
    213      *
    214      * @param oldPackage The package name of the old VPN application.
    215      * @param newPackage The package name of the new VPN application.
    216      * @return true if the operation is succeeded.
    217      */
    218     public synchronized boolean prepare(String oldPackage, String newPackage) {
    219         if (oldPackage != null && getAppUid(oldPackage, mUserHandle) != mOwnerUID) {
    220             // The package doesn't match. We return false (to obtain user consent) unless the user
    221             // has already consented to that VPN package.
    222             if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
    223                 prepareInternal(oldPackage);
    224                 return true;
    225             }
    226             return false;
    227         }
    228 
    229         // Return true if we do not need to revoke.
    230         if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) &&
    231                 getAppUid(newPackage, mUserHandle) == mOwnerUID)) {
    232             return true;
    233         }
    234 
    235         // Check if the caller is authorized.
    236         enforceControlPermission();
    237 
    238         prepareInternal(newPackage);
    239         return true;
    240     }
    241 
    242     /** Prepare the VPN for the given package. Does not perform permission checks. */
    243     private void prepareInternal(String newPackage) {
    244         long token = Binder.clearCallingIdentity();
    245         try {
    246             // Reset the interface.
    247             if (mInterface != null) {
    248                 mStatusIntent = null;
    249                 agentDisconnect();
    250                 jniReset(mInterface);
    251                 mInterface = null;
    252                 mVpnUsers = null;
    253             }
    254 
    255             // Revoke the connection or stop LegacyVpnRunner.
    256             if (mConnection != null) {
    257                 try {
    258                     mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION,
    259                             Parcel.obtain(), null, IBinder.FLAG_ONEWAY);
    260                 } catch (Exception e) {
    261                     // ignore
    262                 }
    263                 mContext.unbindService(mConnection);
    264                 mConnection = null;
    265             } else if (mLegacyVpnRunner != null) {
    266                 mLegacyVpnRunner.exit();
    267                 mLegacyVpnRunner = null;
    268             }
    269 
    270             try {
    271                 mNetd.denyProtect(mOwnerUID);
    272             } catch (Exception e) {
    273                 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
    274             }
    275 
    276             Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
    277             mPackage = newPackage;
    278             mOwnerUID = getAppUid(newPackage, mUserHandle);
    279             try {
    280                 mNetd.allowProtect(mOwnerUID);
    281             } catch (Exception e) {
    282                 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
    283             }
    284             mConfig = null;
    285 
    286             updateState(DetailedState.IDLE, "prepare");
    287         } finally {
    288             Binder.restoreCallingIdentity(token);
    289         }
    290     }
    291 
    292     /**
    293      * Set whether the current package has the ability to launch VPNs without user intervention.
    294      */
    295     public void setPackageAuthorization(boolean authorized) {
    296         // Check if the caller is authorized.
    297         enforceControlPermission();
    298 
    299         if (mPackage == null || VpnConfig.LEGACY_VPN.equals(mPackage)) {
    300             return;
    301         }
    302 
    303         long token = Binder.clearCallingIdentity();
    304         try {
    305             AppOpsManager appOps =
    306                     (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    307             appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, mOwnerUID, mPackage,
    308                     authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
    309         } catch (Exception e) {
    310             Log.wtf(TAG, "Failed to set app ops for package " + mPackage, e);
    311         } finally {
    312             Binder.restoreCallingIdentity(token);
    313         }
    314     }
    315 
    316     private boolean isVpnUserPreConsented(String packageName) {
    317         AppOpsManager appOps =
    318                 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    319 
    320         // Verify that the caller matches the given package and has permission to activate VPNs.
    321         return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(),
    322                 packageName) == AppOpsManager.MODE_ALLOWED;
    323     }
    324 
    325     private int getAppUid(String app, int userHandle) {
    326         if (VpnConfig.LEGACY_VPN.equals(app)) {
    327             return Process.myUid();
    328         }
    329         PackageManager pm = mContext.getPackageManager();
    330         int result;
    331         try {
    332             result = pm.getPackageUid(app, userHandle);
    333         } catch (NameNotFoundException e) {
    334             result = -1;
    335         }
    336         return result;
    337     }
    338 
    339     public NetworkInfo getNetworkInfo() {
    340         return mNetworkInfo;
    341     }
    342 
    343     private LinkProperties makeLinkProperties() {
    344         boolean allowIPv4 = mConfig.allowIPv4;
    345         boolean allowIPv6 = mConfig.allowIPv6;
    346 
    347         LinkProperties lp = new LinkProperties();
    348 
    349         lp.setInterfaceName(mInterface);
    350 
    351         if (mConfig.addresses != null) {
    352             for (LinkAddress address : mConfig.addresses) {
    353                 lp.addLinkAddress(address);
    354                 allowIPv4 |= address.getAddress() instanceof Inet4Address;
    355                 allowIPv6 |= address.getAddress() instanceof Inet6Address;
    356             }
    357         }
    358 
    359         if (mConfig.routes != null) {
    360             for (RouteInfo route : mConfig.routes) {
    361                 lp.addRoute(route);
    362                 InetAddress address = route.getDestination().getAddress();
    363                 allowIPv4 |= address instanceof Inet4Address;
    364                 allowIPv6 |= address instanceof Inet6Address;
    365             }
    366         }
    367 
    368         if (mConfig.dnsServers != null) {
    369             for (String dnsServer : mConfig.dnsServers) {
    370                 InetAddress address = InetAddress.parseNumericAddress(dnsServer);
    371                 lp.addDnsServer(address);
    372                 allowIPv4 |= address instanceof Inet4Address;
    373                 allowIPv6 |= address instanceof Inet6Address;
    374             }
    375         }
    376 
    377         if (!allowIPv4) {
    378             lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
    379         }
    380         if (!allowIPv6) {
    381             lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
    382         }
    383 
    384         // Concatenate search domains into a string.
    385         StringBuilder buffer = new StringBuilder();
    386         if (mConfig.searchDomains != null) {
    387             for (String domain : mConfig.searchDomains) {
    388                 buffer.append(domain).append(' ');
    389             }
    390         }
    391         lp.setDomains(buffer.toString().trim());
    392 
    393         // TODO: Stop setting the MTU in jniCreate and set it here.
    394 
    395         return lp;
    396     }
    397 
    398     private void agentConnect() {
    399         LinkProperties lp = makeLinkProperties();
    400 
    401         if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) {
    402             mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    403         } else {
    404             mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    405         }
    406 
    407         mNetworkInfo.setIsAvailable(true);
    408         mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
    409 
    410         NetworkMisc networkMisc = new NetworkMisc();
    411         networkMisc.allowBypass = mConfig.allowBypass;
    412 
    413         long token = Binder.clearCallingIdentity();
    414         try {
    415             mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE,
    416                     mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) {
    417                             @Override
    418                             public void unwanted() {
    419                                 // We are user controlled, not driven by NetworkRequest.
    420                             }
    421                         };
    422         } finally {
    423             Binder.restoreCallingIdentity(token);
    424         }
    425 
    426         addVpnUserLocked(mUserHandle);
    427         // If we are owner assign all Restricted Users to this VPN
    428         if (mUserHandle == UserHandle.USER_OWNER) {
    429             token = Binder.clearCallingIdentity();
    430             List<UserInfo> users;
    431             try {
    432                 users = UserManager.get(mContext).getUsers();
    433             } finally {
    434                 Binder.restoreCallingIdentity(token);
    435             }
    436             for (UserInfo user : users) {
    437                 if (user.isRestricted()) {
    438                     addVpnUserLocked(user.id);
    439                 }
    440             }
    441         }
    442         mNetworkAgent.addUidRanges(mVpnUsers.toArray(new UidRange[mVpnUsers.size()]));
    443     }
    444 
    445     private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) {
    446         networkInfo.setIsAvailable(false);
    447         networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
    448         if (networkAgent != null) {
    449             networkAgent.sendNetworkInfo(networkInfo);
    450         }
    451     }
    452 
    453     private void agentDisconnect(NetworkAgent networkAgent) {
    454         NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
    455         agentDisconnect(networkInfo, networkAgent);
    456     }
    457 
    458     private void agentDisconnect() {
    459         if (mNetworkInfo.isConnected()) {
    460             agentDisconnect(mNetworkInfo, mNetworkAgent);
    461             mNetworkAgent = null;
    462         }
    463     }
    464 
    465     /**
    466      * Establish a VPN network and return the file descriptor of the VPN
    467      * interface. This methods returns {@code null} if the application is
    468      * revoked or not prepared.
    469      *
    470      * @param config The parameters to configure the network.
    471      * @return The file descriptor of the VPN interface.
    472      */
    473     public synchronized ParcelFileDescriptor establish(VpnConfig config) {
    474         // Check if the caller is already prepared.
    475         UserManager mgr = UserManager.get(mContext);
    476         if (Binder.getCallingUid() != mOwnerUID) {
    477             return null;
    478         }
    479         // Check if the service is properly declared.
    480         Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
    481         intent.setClassName(mPackage, config.user);
    482         long token = Binder.clearCallingIdentity();
    483         try {
    484             // Restricted users are not allowed to create VPNs, they are tied to Owner
    485             UserInfo user = mgr.getUserInfo(mUserHandle);
    486             if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
    487                 throw new SecurityException("Restricted users cannot establish VPNs");
    488             }
    489 
    490             ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
    491                                                                         null, 0, mUserHandle);
    492             if (info == null) {
    493                 throw new SecurityException("Cannot find " + config.user);
    494             }
    495             if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
    496                 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
    497             }
    498         } catch (RemoteException e) {
    499                 throw new SecurityException("Cannot find " + config.user);
    500         } finally {
    501             Binder.restoreCallingIdentity(token);
    502         }
    503 
    504         // Save the old config in case we need to go back.
    505         VpnConfig oldConfig = mConfig;
    506         String oldInterface = mInterface;
    507         Connection oldConnection = mConnection;
    508         NetworkAgent oldNetworkAgent = mNetworkAgent;
    509         mNetworkAgent = null;
    510         List<UidRange> oldUsers = mVpnUsers;
    511 
    512         // Configure the interface. Abort if any of these steps fails.
    513         ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
    514         try {
    515             updateState(DetailedState.CONNECTING, "establish");
    516             String interfaze = jniGetName(tun.getFd());
    517 
    518             // TEMP use the old jni calls until there is support for netd address setting
    519             StringBuilder builder = new StringBuilder();
    520             for (LinkAddress address : config.addresses) {
    521                 builder.append(" " + address);
    522             }
    523             if (jniSetAddresses(interfaze, builder.toString()) < 1) {
    524                 throw new IllegalArgumentException("At least one address must be specified");
    525             }
    526             Connection connection = new Connection();
    527             if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE,
    528                         new UserHandle(mUserHandle))) {
    529                 throw new IllegalStateException("Cannot bind " + config.user);
    530             }
    531 
    532             mConnection = connection;
    533             mInterface = interfaze;
    534 
    535             // Fill more values.
    536             config.user = mPackage;
    537             config.interfaze = mInterface;
    538             config.startTime = SystemClock.elapsedRealtime();
    539             mConfig = config;
    540 
    541             // Set up forwarding and DNS rules.
    542             mVpnUsers = new ArrayList<UidRange>();
    543 
    544             agentConnect();
    545 
    546             if (oldConnection != null) {
    547                 mContext.unbindService(oldConnection);
    548             }
    549             // Remove the old tun's user forwarding rules
    550             // The new tun's user rules have already been added so they will take over
    551             // as rules are deleted. This prevents data leakage as the rules are moved over.
    552             agentDisconnect(oldNetworkAgent);
    553             if (oldInterface != null && !oldInterface.equals(interfaze)) {
    554                 jniReset(oldInterface);
    555             }
    556 
    557             try {
    558                 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
    559             } catch (IOException e) {
    560                 throw new IllegalStateException(
    561                         "Cannot set tunnel's fd as blocking=" + config.blocking, e);
    562             }
    563         } catch (RuntimeException e) {
    564             IoUtils.closeQuietly(tun);
    565             agentDisconnect();
    566             // restore old state
    567             mConfig = oldConfig;
    568             mConnection = oldConnection;
    569             mVpnUsers = oldUsers;
    570             mNetworkAgent = oldNetworkAgent;
    571             mInterface = oldInterface;
    572             throw e;
    573         }
    574         Log.i(TAG, "Established by " + config.user + " on " + mInterface);
    575         return tun;
    576     }
    577 
    578     private boolean isRunningLocked() {
    579         return mNetworkAgent != null && mInterface != null;
    580     }
    581 
    582     // Returns true if the VPN has been established and the calling UID is its owner. Used to check
    583     // that a call to mutate VPN state is admissible.
    584     private boolean isCallerEstablishedOwnerLocked() {
    585         return isRunningLocked() && Binder.getCallingUid() == mOwnerUID;
    586     }
    587 
    588     // Note: Return type guarantees results are deduped and sorted, which callers require.
    589     private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) {
    590         SortedSet<Integer> uids = new TreeSet<Integer>();
    591         for (String app : packageNames) {
    592             int uid = getAppUid(app, userHandle);
    593             if (uid != -1) uids.add(uid);
    594         }
    595         return uids;
    596     }
    597 
    598     // Note: This function adds to mVpnUsers but does not publish list to NetworkAgent.
    599     private void addVpnUserLocked(int userHandle) {
    600         if (mVpnUsers == null) {
    601             throw new IllegalStateException("VPN is not active");
    602         }
    603 
    604         if (mConfig.allowedApplications != null) {
    605             // Add ranges covering all UIDs for allowedApplications.
    606             int start = -1, stop = -1;
    607             for (int uid : getAppsUids(mConfig.allowedApplications, userHandle)) {
    608                 if (start == -1) {
    609                     start = uid;
    610                 } else if (uid != stop + 1) {
    611                     mVpnUsers.add(new UidRange(start, stop));
    612                     start = uid;
    613                 }
    614                 stop = uid;
    615             }
    616             if (start != -1) mVpnUsers.add(new UidRange(start, stop));
    617         } else if (mConfig.disallowedApplications != null) {
    618             // Add all ranges for user skipping UIDs for disallowedApplications.
    619             final UidRange userRange = UidRange.createForUser(userHandle);
    620             int start = userRange.start;
    621             for (int uid : getAppsUids(mConfig.disallowedApplications, userHandle)) {
    622                 if (uid == start) {
    623                     start++;
    624                 } else {
    625                     mVpnUsers.add(new UidRange(start, uid - 1));
    626                     start = uid + 1;
    627                 }
    628             }
    629             if (start <= userRange.stop) mVpnUsers.add(new UidRange(start, userRange.stop));
    630         } else {
    631             // Add all UIDs for the user.
    632             mVpnUsers.add(UidRange.createForUser(userHandle));
    633         }
    634 
    635         prepareStatusIntent();
    636     }
    637 
    638     // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that
    639     // apply to userHandle.
    640     private List<UidRange> uidRangesForUser(int userHandle) {
    641         final UidRange userRange = UidRange.createForUser(userHandle);
    642         final List<UidRange> ranges = new ArrayList<UidRange>();
    643         for (UidRange range : mVpnUsers) {
    644             if (range.start >= userRange.start && range.stop <= userRange.stop) {
    645                 ranges.add(range);
    646             }
    647         }
    648         return ranges;
    649     }
    650 
    651     private void removeVpnUserLocked(int userHandle) {
    652         if (mVpnUsers == null) {
    653             throw new IllegalStateException("VPN is not active");
    654         }
    655         final List<UidRange> ranges = uidRangesForUser(userHandle);
    656         if (mNetworkAgent != null) {
    657             mNetworkAgent.removeUidRanges(ranges.toArray(new UidRange[ranges.size()]));
    658         }
    659         mVpnUsers.removeAll(ranges);
    660         mStatusIntent = null;
    661     }
    662 
    663     private void onUserAdded(int userHandle) {
    664         // If the user is restricted tie them to the owner's VPN
    665         synchronized(Vpn.this) {
    666             UserManager mgr = UserManager.get(mContext);
    667             UserInfo user = mgr.getUserInfo(userHandle);
    668             if (user.isRestricted()) {
    669                 try {
    670                     addVpnUserLocked(userHandle);
    671                     if (mNetworkAgent != null) {
    672                         final List<UidRange> ranges = uidRangesForUser(userHandle);
    673                         mNetworkAgent.addUidRanges(ranges.toArray(new UidRange[ranges.size()]));
    674                     }
    675                 } catch (Exception e) {
    676                     Log.wtf(TAG, "Failed to add restricted user to owner", e);
    677                 }
    678             }
    679         }
    680     }
    681 
    682     private void onUserRemoved(int userHandle) {
    683         // clean up if restricted
    684         synchronized(Vpn.this) {
    685             UserManager mgr = UserManager.get(mContext);
    686             UserInfo user = mgr.getUserInfo(userHandle);
    687             if (user.isRestricted()) {
    688                 try {
    689                     removeVpnUserLocked(userHandle);
    690                 } catch (Exception e) {
    691                     Log.wtf(TAG, "Failed to remove restricted user to owner", e);
    692                 }
    693             }
    694         }
    695     }
    696 
    697     /**
    698      * Return the configuration of the currently running VPN.
    699      */
    700     public VpnConfig getVpnConfig() {
    701         enforceControlPermission();
    702         return mConfig;
    703     }
    704 
    705     @Deprecated
    706     public synchronized void interfaceStatusChanged(String iface, boolean up) {
    707         try {
    708             mObserver.interfaceStatusChanged(iface, up);
    709         } catch (RemoteException e) {
    710             // ignored; target is local
    711         }
    712     }
    713 
    714     private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() {
    715         @Override
    716         public void interfaceStatusChanged(String interfaze, boolean up) {
    717             synchronized (Vpn.this) {
    718                 if (!up && mLegacyVpnRunner != null) {
    719                     mLegacyVpnRunner.check(interfaze);
    720                 }
    721             }
    722         }
    723 
    724         @Override
    725         public void interfaceRemoved(String interfaze) {
    726             synchronized (Vpn.this) {
    727                 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
    728                     mStatusIntent = null;
    729                     mVpnUsers = null;
    730                     mInterface = null;
    731                     if (mConnection != null) {
    732                         mContext.unbindService(mConnection);
    733                         mConnection = null;
    734                         agentDisconnect();
    735                     } else if (mLegacyVpnRunner != null) {
    736                         mLegacyVpnRunner.exit();
    737                         mLegacyVpnRunner = null;
    738                     }
    739                 }
    740             }
    741         }
    742     };
    743 
    744     private void enforceControlPermission() {
    745         mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller");
    746     }
    747 
    748     private class Connection implements ServiceConnection {
    749         private IBinder mService;
    750 
    751         @Override
    752         public void onServiceConnected(ComponentName name, IBinder service) {
    753             mService = service;
    754         }
    755 
    756         @Override
    757         public void onServiceDisconnected(ComponentName name) {
    758             mService = null;
    759         }
    760     }
    761 
    762     private void prepareStatusIntent() {
    763         final long token = Binder.clearCallingIdentity();
    764         try {
    765             mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
    766         } finally {
    767             Binder.restoreCallingIdentity(token);
    768         }
    769     }
    770 
    771     public synchronized boolean addAddress(String address, int prefixLength) {
    772         if (!isCallerEstablishedOwnerLocked()) {
    773             return false;
    774         }
    775         boolean success = jniAddAddress(mInterface, address, prefixLength);
    776         mNetworkAgent.sendLinkProperties(makeLinkProperties());
    777         return success;
    778     }
    779 
    780     public synchronized boolean removeAddress(String address, int prefixLength) {
    781         if (!isCallerEstablishedOwnerLocked()) {
    782             return false;
    783         }
    784         boolean success = jniDelAddress(mInterface, address, prefixLength);
    785         mNetworkAgent.sendLinkProperties(makeLinkProperties());
    786         return success;
    787     }
    788 
    789     public synchronized boolean setUnderlyingNetworks(Network[] networks) {
    790         if (!isCallerEstablishedOwnerLocked()) {
    791             return false;
    792         }
    793         if (networks == null) {
    794             mConfig.underlyingNetworks = null;
    795         } else {
    796             mConfig.underlyingNetworks = new Network[networks.length];
    797             for (int i = 0; i < networks.length; ++i) {
    798                 if (networks[i] == null) {
    799                     mConfig.underlyingNetworks[i] = null;
    800                 } else {
    801                     mConfig.underlyingNetworks[i] = new Network(networks[i].netId);
    802                 }
    803             }
    804         }
    805         return true;
    806     }
    807 
    808     public synchronized Network[] getUnderlyingNetworks() {
    809         if (!isRunningLocked()) {
    810             return null;
    811         }
    812         return mConfig.underlyingNetworks;
    813     }
    814 
    815     public synchronized boolean appliesToUid(int uid) {
    816         if (!isRunningLocked()) {
    817             return false;
    818         }
    819         for (UidRange uidRange : mVpnUsers) {
    820             if (uidRange.start <= uid && uid <= uidRange.stop) {
    821                 return true;
    822             }
    823         }
    824         return false;
    825     }
    826 
    827     private native int jniCreate(int mtu);
    828     private native String jniGetName(int tun);
    829     private native int jniSetAddresses(String interfaze, String addresses);
    830     private native void jniReset(String interfaze);
    831     private native int jniCheck(String interfaze);
    832     private native boolean jniAddAddress(String interfaze, String address, int prefixLen);
    833     private native boolean jniDelAddress(String interfaze, String address, int prefixLen);
    834 
    835     private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
    836         for (RouteInfo route : prop.getAllRoutes()) {
    837             // Currently legacy VPN only works on IPv4.
    838             if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
    839                 return route;
    840             }
    841         }
    842 
    843         throw new IllegalStateException("Unable to find IPv4 default gateway");
    844     }
    845 
    846     /**
    847      * Start legacy VPN, controlling native daemons as needed. Creates a
    848      * secondary thread to perform connection work, returning quickly.
    849      *
    850      * Should only be called to respond to Binder requests as this enforces caller permission. Use
    851      * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the
    852      * permission check only when the caller is trusted (or the call is initiated by the system).
    853      */
    854     public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
    855         enforceControlPermission();
    856         long token = Binder.clearCallingIdentity();
    857         try {
    858             startLegacyVpnPrivileged(profile, keyStore, egress);
    859         } finally {
    860             Binder.restoreCallingIdentity(token);
    861         }
    862     }
    863 
    864     /**
    865      * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check
    866      * permissions under the assumption that the caller is the system.
    867      *
    868      * Callers are responsible for checking permissions if needed.
    869      */
    870     public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore,
    871             LinkProperties egress) {
    872         if (!keyStore.isUnlocked()) {
    873             throw new IllegalStateException("KeyStore isn't unlocked");
    874         }
    875         UserManager mgr = UserManager.get(mContext);
    876         UserInfo user = mgr.getUserInfo(mUserHandle);
    877         if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
    878             throw new SecurityException("Restricted users cannot establish VPNs");
    879         }
    880 
    881         final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
    882         final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
    883         final String iface = ipv4DefaultRoute.getInterface();
    884 
    885         // Load certificates.
    886         String privateKey = "";
    887         String userCert = "";
    888         String caCert = "";
    889         String serverCert = "";
    890         if (!profile.ipsecUserCert.isEmpty()) {
    891             privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
    892             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
    893             userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
    894         }
    895         if (!profile.ipsecCaCert.isEmpty()) {
    896             byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
    897             caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
    898         }
    899         if (!profile.ipsecServerCert.isEmpty()) {
    900             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
    901             serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
    902         }
    903         if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
    904             throw new IllegalStateException("Cannot load credentials");
    905         }
    906 
    907         // Prepare arguments for racoon.
    908         String[] racoon = null;
    909         switch (profile.type) {
    910             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
    911                 racoon = new String[] {
    912                     iface, profile.server, "udppsk", profile.ipsecIdentifier,
    913                     profile.ipsecSecret, "1701",
    914                 };
    915                 break;
    916             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
    917                 racoon = new String[] {
    918                     iface, profile.server, "udprsa", privateKey, userCert,
    919                     caCert, serverCert, "1701",
    920                 };
    921                 break;
    922             case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
    923                 racoon = new String[] {
    924                     iface, profile.server, "xauthpsk", profile.ipsecIdentifier,
    925                     profile.ipsecSecret, profile.username, profile.password, "", gateway,
    926                 };
    927                 break;
    928             case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
    929                 racoon = new String[] {
    930                     iface, profile.server, "xauthrsa", privateKey, userCert,
    931                     caCert, serverCert, profile.username, profile.password, "", gateway,
    932                 };
    933                 break;
    934             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
    935                 racoon = new String[] {
    936                     iface, profile.server, "hybridrsa",
    937                     caCert, serverCert, profile.username, profile.password, "", gateway,
    938                 };
    939                 break;
    940         }
    941 
    942         // Prepare arguments for mtpd.
    943         String[] mtpd = null;
    944         switch (profile.type) {
    945             case VpnProfile.TYPE_PPTP:
    946                 mtpd = new String[] {
    947                     iface, "pptp", profile.server, "1723",
    948                     "name", profile.username, "password", profile.password,
    949                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
    950                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
    951                     (profile.mppe ? "+mppe" : "nomppe"),
    952                 };
    953                 break;
    954             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
    955             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
    956                 mtpd = new String[] {
    957                     iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
    958                     "name", profile.username, "password", profile.password,
    959                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
    960                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
    961                 };
    962                 break;
    963         }
    964 
    965         VpnConfig config = new VpnConfig();
    966         config.legacy = true;
    967         config.user = profile.key;
    968         config.interfaze = iface;
    969         config.session = profile.name;
    970 
    971         config.addLegacyRoutes(profile.routes);
    972         if (!profile.dnsServers.isEmpty()) {
    973             config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
    974         }
    975         if (!profile.searchDomains.isEmpty()) {
    976             config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
    977         }
    978         startLegacyVpn(config, racoon, mtpd);
    979     }
    980 
    981     private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
    982         stopLegacyVpnPrivileged();
    983 
    984         // Prepare for the new request.
    985         prepareInternal(VpnConfig.LEGACY_VPN);
    986         updateState(DetailedState.CONNECTING, "startLegacyVpn");
    987 
    988         // Start a new LegacyVpnRunner and we are done!
    989         mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
    990         mLegacyVpnRunner.start();
    991     }
    992 
    993     /** Stop legacy VPN. Permissions must be checked by callers. */
    994     public synchronized void stopLegacyVpnPrivileged() {
    995         if (mLegacyVpnRunner != null) {
    996             mLegacyVpnRunner.exit();
    997             mLegacyVpnRunner = null;
    998 
    999             synchronized (LegacyVpnRunner.TAG) {
   1000                 // wait for old thread to completely finish before spinning up
   1001                 // new instance, otherwise state updates can be out of order.
   1002             }
   1003         }
   1004     }
   1005 
   1006     /**
   1007      * Return the information of the current ongoing legacy VPN.
   1008      */
   1009     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
   1010         // Check if the caller is authorized.
   1011         enforceControlPermission();
   1012         if (mLegacyVpnRunner == null) return null;
   1013 
   1014         final LegacyVpnInfo info = new LegacyVpnInfo();
   1015         info.key = mConfig.user;
   1016         info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
   1017         if (mNetworkInfo.isConnected()) {
   1018             info.intent = mStatusIntent;
   1019         }
   1020         return info;
   1021     }
   1022 
   1023     public VpnConfig getLegacyVpnConfig() {
   1024         if (mLegacyVpnRunner != null) {
   1025             return mConfig;
   1026         } else {
   1027             return null;
   1028         }
   1029     }
   1030 
   1031     /**
   1032      * Bringing up a VPN connection takes time, and that is all this thread
   1033      * does. Here we have plenty of time. The only thing we need to take
   1034      * care of is responding to interruptions as soon as possible. Otherwise
   1035      * requests will be piled up. This can be done in a Handler as a state
   1036      * machine, but it is much easier to read in the current form.
   1037      */
   1038     private class LegacyVpnRunner extends Thread {
   1039         private static final String TAG = "LegacyVpnRunner";
   1040 
   1041         private final String[] mDaemons;
   1042         private final String[][] mArguments;
   1043         private final LocalSocket[] mSockets;
   1044         private final String mOuterInterface;
   1045         private final AtomicInteger mOuterConnection =
   1046                 new AtomicInteger(ConnectivityManager.TYPE_NONE);
   1047 
   1048         private long mTimer = -1;
   1049 
   1050         /**
   1051          * Watch for the outer connection (passing in the constructor) going away.
   1052          */
   1053         private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
   1054             @Override
   1055             public void onReceive(Context context, Intent intent) {
   1056                 if (!mEnableTeardown) return;
   1057 
   1058                 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
   1059                     if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
   1060                             ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) {
   1061                         NetworkInfo info = (NetworkInfo)intent.getExtra(
   1062                                 ConnectivityManager.EXTRA_NETWORK_INFO);
   1063                         if (info != null && !info.isConnectedOrConnecting()) {
   1064                             try {
   1065                                 mObserver.interfaceStatusChanged(mOuterInterface, false);
   1066                             } catch (RemoteException e) {}
   1067                         }
   1068                     }
   1069                 }
   1070             }
   1071         };
   1072 
   1073         public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
   1074             super(TAG);
   1075             mConfig = config;
   1076             mDaemons = new String[] {"racoon", "mtpd"};
   1077             // TODO: clear arguments from memory once launched
   1078             mArguments = new String[][] {racoon, mtpd};
   1079             mSockets = new LocalSocket[mDaemons.length];
   1080 
   1081             // This is the interface which VPN is running on,
   1082             // mConfig.interfaze will change to point to OUR
   1083             // internal interface soon. TODO - add inner/outer to mconfig
   1084             // TODO - we have a race - if the outer iface goes away/disconnects before we hit this
   1085             // we will leave the VPN up.  We should check that it's still there/connected after
   1086             // registering
   1087             mOuterInterface = mConfig.interfaze;
   1088 
   1089             try {
   1090                 mOuterConnection.set(
   1091                         mConnService.findConnectionTypeForIface(mOuterInterface));
   1092             } catch (Exception e) {
   1093                 mOuterConnection.set(ConnectivityManager.TYPE_NONE);
   1094             }
   1095 
   1096             IntentFilter filter = new IntentFilter();
   1097             filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
   1098             mContext.registerReceiver(mBroadcastReceiver, filter);
   1099         }
   1100 
   1101         public void check(String interfaze) {
   1102             if (interfaze.equals(mOuterInterface)) {
   1103                 Log.i(TAG, "Legacy VPN is going down with " + interfaze);
   1104                 exit();
   1105             }
   1106         }
   1107 
   1108         public void exit() {
   1109             // We assume that everything is reset after stopping the daemons.
   1110             interrupt();
   1111             for (LocalSocket socket : mSockets) {
   1112                 IoUtils.closeQuietly(socket);
   1113             }
   1114             agentDisconnect();
   1115             try {
   1116                 mContext.unregisterReceiver(mBroadcastReceiver);
   1117             } catch (IllegalArgumentException e) {}
   1118         }
   1119 
   1120         @Override
   1121         public void run() {
   1122             // Wait for the previous thread since it has been interrupted.
   1123             Log.v(TAG, "Waiting");
   1124             synchronized (TAG) {
   1125                 Log.v(TAG, "Executing");
   1126                 execute();
   1127                 monitorDaemons();
   1128             }
   1129         }
   1130 
   1131         private void checkpoint(boolean yield) throws InterruptedException {
   1132             long now = SystemClock.elapsedRealtime();
   1133             if (mTimer == -1) {
   1134                 mTimer = now;
   1135                 Thread.sleep(1);
   1136             } else if (now - mTimer <= 60000) {
   1137                 Thread.sleep(yield ? 200 : 1);
   1138             } else {
   1139                 updateState(DetailedState.FAILED, "checkpoint");
   1140                 throw new IllegalStateException("Time is up");
   1141             }
   1142         }
   1143 
   1144         private void execute() {
   1145             // Catch all exceptions so we can clean up few things.
   1146             boolean initFinished = false;
   1147             try {
   1148                 // Initialize the timer.
   1149                 checkpoint(false);
   1150 
   1151                 // Wait for the daemons to stop.
   1152                 for (String daemon : mDaemons) {
   1153                     while (!SystemService.isStopped(daemon)) {
   1154                         checkpoint(true);
   1155                     }
   1156                 }
   1157 
   1158                 // Clear the previous state.
   1159                 File state = new File("/data/misc/vpn/state");
   1160                 state.delete();
   1161                 if (state.exists()) {
   1162                     throw new IllegalStateException("Cannot delete the state");
   1163                 }
   1164                 new File("/data/misc/vpn/abort").delete();
   1165                 initFinished = true;
   1166 
   1167                 // Check if we need to restart any of the daemons.
   1168                 boolean restart = false;
   1169                 for (String[] arguments : mArguments) {
   1170                     restart = restart || (arguments != null);
   1171                 }
   1172                 if (!restart) {
   1173                     agentDisconnect();
   1174                     return;
   1175                 }
   1176                 updateState(DetailedState.CONNECTING, "execute");
   1177 
   1178                 // Start the daemon with arguments.
   1179                 for (int i = 0; i < mDaemons.length; ++i) {
   1180                     String[] arguments = mArguments[i];
   1181                     if (arguments == null) {
   1182                         continue;
   1183                     }
   1184 
   1185                     // Start the daemon.
   1186                     String daemon = mDaemons[i];
   1187                     SystemService.start(daemon);
   1188 
   1189                     // Wait for the daemon to start.
   1190                     while (!SystemService.isRunning(daemon)) {
   1191                         checkpoint(true);
   1192                     }
   1193 
   1194                     // Create the control socket.
   1195                     mSockets[i] = new LocalSocket();
   1196                     LocalSocketAddress address = new LocalSocketAddress(
   1197                             daemon, LocalSocketAddress.Namespace.RESERVED);
   1198 
   1199                     // Wait for the socket to connect.
   1200                     while (true) {
   1201                         try {
   1202                             mSockets[i].connect(address);
   1203                             break;
   1204                         } catch (Exception e) {
   1205                             // ignore
   1206                         }
   1207                         checkpoint(true);
   1208                     }
   1209                     mSockets[i].setSoTimeout(500);
   1210 
   1211                     // Send over the arguments.
   1212                     OutputStream out = mSockets[i].getOutputStream();
   1213                     for (String argument : arguments) {
   1214                         byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
   1215                         if (bytes.length >= 0xFFFF) {
   1216                             throw new IllegalArgumentException("Argument is too large");
   1217                         }
   1218                         out.write(bytes.length >> 8);
   1219                         out.write(bytes.length);
   1220                         out.write(bytes);
   1221                         checkpoint(false);
   1222                     }
   1223                     out.write(0xFF);
   1224                     out.write(0xFF);
   1225                     out.flush();
   1226 
   1227                     // Wait for End-of-File.
   1228                     InputStream in = mSockets[i].getInputStream();
   1229                     while (true) {
   1230                         try {
   1231                             if (in.read() == -1) {
   1232                                 break;
   1233                             }
   1234                         } catch (Exception e) {
   1235                             // ignore
   1236                         }
   1237                         checkpoint(true);
   1238                     }
   1239                 }
   1240 
   1241                 // Wait for the daemons to create the new state.
   1242                 while (!state.exists()) {
   1243                     // Check if a running daemon is dead.
   1244                     for (int i = 0; i < mDaemons.length; ++i) {
   1245                         String daemon = mDaemons[i];
   1246                         if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
   1247                             throw new IllegalStateException(daemon + " is dead");
   1248                         }
   1249                     }
   1250                     checkpoint(true);
   1251                 }
   1252 
   1253                 // Now we are connected. Read and parse the new state.
   1254                 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
   1255                 if (parameters.length != 7) {
   1256                     throw new IllegalStateException("Cannot parse the state");
   1257                 }
   1258 
   1259                 // Set the interface and the addresses in the config.
   1260                 mConfig.interfaze = parameters[0].trim();
   1261 
   1262                 mConfig.addLegacyAddresses(parameters[1]);
   1263                 // Set the routes if they are not set in the config.
   1264                 if (mConfig.routes == null || mConfig.routes.isEmpty()) {
   1265                     mConfig.addLegacyRoutes(parameters[2]);
   1266                 }
   1267 
   1268                 // Set the DNS servers if they are not set in the config.
   1269                 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
   1270                     String dnsServers = parameters[3].trim();
   1271                     if (!dnsServers.isEmpty()) {
   1272                         mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
   1273                     }
   1274                 }
   1275 
   1276                 // Set the search domains if they are not set in the config.
   1277                 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) {
   1278                     String searchDomains = parameters[4].trim();
   1279                     if (!searchDomains.isEmpty()) {
   1280                         mConfig.searchDomains = Arrays.asList(searchDomains.split(" "));
   1281                     }
   1282                 }
   1283 
   1284                 // Add a throw route for the VPN server endpoint, if one was specified.
   1285                 String endpoint = parameters[5];
   1286                 if (!endpoint.isEmpty()) {
   1287                     try {
   1288                         InetAddress addr = InetAddress.parseNumericAddress(endpoint);
   1289                         if (addr instanceof Inet4Address) {
   1290                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
   1291                         } else if (addr instanceof Inet6Address) {
   1292                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
   1293                         } else {
   1294                             Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
   1295                         }
   1296                     } catch (IllegalArgumentException e) {
   1297                         Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
   1298                     }
   1299                 }
   1300 
   1301                 // Here is the last step and it must be done synchronously.
   1302                 synchronized (Vpn.this) {
   1303                     // Set the start time
   1304                     mConfig.startTime = SystemClock.elapsedRealtime();
   1305 
   1306                     // Check if the thread is interrupted while we are waiting.
   1307                     checkpoint(false);
   1308 
   1309                     // Check if the interface is gone while we are waiting.
   1310                     if (jniCheck(mConfig.interfaze) == 0) {
   1311                         throw new IllegalStateException(mConfig.interfaze + " is gone");
   1312                     }
   1313 
   1314                     // Now INetworkManagementEventObserver is watching our back.
   1315                     mInterface = mConfig.interfaze;
   1316                     mVpnUsers = new ArrayList<UidRange>();
   1317 
   1318                     agentConnect();
   1319 
   1320                     Log.i(TAG, "Connected!");
   1321                 }
   1322             } catch (Exception e) {
   1323                 Log.i(TAG, "Aborting", e);
   1324                 updateState(DetailedState.FAILED, e.getMessage());
   1325                 exit();
   1326             } finally {
   1327                 // Kill the daemons if they fail to stop.
   1328                 if (!initFinished) {
   1329                     for (String daemon : mDaemons) {
   1330                         SystemService.stop(daemon);
   1331                     }
   1332                 }
   1333 
   1334                 // Do not leave an unstable state.
   1335                 if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) {
   1336                     agentDisconnect();
   1337                 }
   1338             }
   1339         }
   1340 
   1341         /**
   1342          * Monitor the daemons we started, moving to disconnected state if the
   1343          * underlying services fail.
   1344          */
   1345         private void monitorDaemons() {
   1346             if (!mNetworkInfo.isConnected()) {
   1347                 return;
   1348             }
   1349 
   1350             try {
   1351                 while (true) {
   1352                     Thread.sleep(2000);
   1353                     for (int i = 0; i < mDaemons.length; i++) {
   1354                         if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
   1355                             return;
   1356                         }
   1357                     }
   1358                 }
   1359             } catch (InterruptedException e) {
   1360                 Log.d(TAG, "interrupted during monitorDaemons(); stopping services");
   1361             } finally {
   1362                 for (String daemon : mDaemons) {
   1363                     SystemService.stop(daemon);
   1364                 }
   1365 
   1366                 agentDisconnect();
   1367             }
   1368         }
   1369     }
   1370 }
   1371