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
onStartCommand(Intent intent, int flags, int startId)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 
start(String packageName, Intent intent)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 
stop()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
onDestroy()150     public void onDestroy() {
151         stop();
152         super.onDestroy();
153     }
154 }
155