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