Home | History | Annotate | Download | only in hostside
      1 /*
      2  * Copyright (C) 2014 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.cts.net.hostside;
     18 
     19 import android.content.Intent;
     20 import android.net.VpnService;
     21 import android.os.ParcelFileDescriptor;
     22 import android.content.pm.PackageManager.NameNotFoundException;
     23 import android.text.TextUtils;
     24 import android.util.Log;
     25 
     26 import java.io.IOException;
     27 import java.net.InetAddress;
     28 import java.net.UnknownHostException;
     29 
     30 public class MyVpnService extends VpnService {
     31 
     32     private static String TAG = "MyVpnService";
     33     private static int MTU = 1799;
     34 
     35     private ParcelFileDescriptor mFd = null;
     36     private PacketReflector mPacketReflector = null;
     37 
     38     @Override
     39     public int onStartCommand(Intent intent, int flags, int startId) {
     40         String packageName = getPackageName();
     41         String cmd = intent.getStringExtra(packageName + ".cmd");
     42         if ("disconnect".equals(cmd)) {
     43             stop();
     44         } else if ("connect".equals(cmd)) {
     45             start(packageName, intent);
     46         }
     47 
     48         return START_NOT_STICKY;
     49     }
     50 
     51     private void start(String packageName, Intent intent) {
     52         Builder builder = new Builder();
     53 
     54         String addresses = intent.getStringExtra(packageName + ".addresses");
     55         if (addresses != null) {
     56             String[] addressArray = addresses.split(",");
     57             for (int i = 0; i < addressArray.length; i++) {
     58                 String[] prefixAndMask = addressArray[i].split("/");
     59                 try {
     60                     InetAddress address = InetAddress.getByName(prefixAndMask[0]);
     61                     int prefixLength = Integer.parseInt(prefixAndMask[1]);
     62                     builder.addAddress(address, prefixLength);
     63                 } catch (UnknownHostException|NumberFormatException|
     64                          ArrayIndexOutOfBoundsException e) {
     65                     continue;
     66                 }
     67             }
     68         }
     69 
     70         String routes = intent.getStringExtra(packageName + ".routes");
     71         if (routes != null) {
     72             String[] routeArray = routes.split(",");
     73             for (int i = 0; i < routeArray.length; i++) {
     74                 String[] prefixAndMask = routeArray[i].split("/");
     75                 try {
     76                     InetAddress address = InetAddress.getByName(prefixAndMask[0]);
     77                     int prefixLength = Integer.parseInt(prefixAndMask[1]);
     78                     builder.addRoute(address, prefixLength);
     79                 } catch (UnknownHostException|NumberFormatException|
     80                          ArrayIndexOutOfBoundsException e) {
     81                     continue;
     82                 }
     83             }
     84         }
     85 
     86         String allowed = intent.getStringExtra(packageName + ".allowedapplications");
     87         if (allowed != null) {
     88             String[] packageArray = allowed.split(",");
     89             for (int i = 0; i < packageArray.length; i++) {
     90                 String allowedPackage = packageArray[i];
     91                 if (!TextUtils.isEmpty(allowedPackage)) {
     92                     try {
     93                         builder.addAllowedApplication(allowedPackage);
     94                     } catch(NameNotFoundException e) {
     95                         continue;
     96                     }
     97                 }
     98             }
     99         }
    100 
    101         String disallowed = intent.getStringExtra(packageName + ".disallowedapplications");
    102         if (disallowed != null) {
    103             String[] packageArray = disallowed.split(",");
    104             for (int i = 0; i < packageArray.length; i++) {
    105                 String disallowedPackage = packageArray[i];
    106                 if (!TextUtils.isEmpty(disallowedPackage)) {
    107                     try {
    108                         builder.addDisallowedApplication(disallowedPackage);
    109                     } catch(NameNotFoundException e) {
    110                         continue;
    111                     }
    112                 }
    113             }
    114         }
    115 
    116         builder.setMtu(MTU);
    117         builder.setBlocking(true);
    118         builder.setSession("MyVpnService");
    119 
    120         Log.i(TAG, "Establishing VPN,"
    121                 + " addresses=" + addresses
    122                 + " routes=" + routes
    123                 + " allowedApplications=" + allowed
    124                 + " disallowedApplications=" + disallowed);
    125 
    126         mFd = builder.establish();
    127         Log.i(TAG, "Established, fd=" + (mFd == null ? "null" : mFd.getFd()));
    128 
    129         mPacketReflector = new PacketReflector(mFd.getFileDescriptor(), MTU);
    130         mPacketReflector.start();
    131     }
    132 
    133     private void stop() {
    134         if (mPacketReflector != null) {
    135             mPacketReflector.interrupt();
    136             mPacketReflector = null;
    137         }
    138         try {
    139             if (mFd != null) {
    140                 Log.i(TAG, "Closing filedescriptor");
    141                 mFd.close();
    142             }
    143         } catch(IOException e) {
    144         } finally {
    145             mFd = null;
    146         }
    147     }
    148 
    149     @Override
    150     public void onDestroy() {
    151         stop();
    152         super.onDestroy();
    153     }
    154 }
    155