blob: ebb1ae4bb795c4aa00d3c9746ed345fac689cc20 [file] [log] [blame]
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -07001/*
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
17package android.net;
18
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -070019import static android.system.OsConstants.AF_INET;
20import static android.system.OsConstants.AF_INET6;
21
Irina Dumitrescu5155a2d2019-02-20 18:17:06 +000022import android.annotation.NonNull;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060023import android.annotation.RequiresPermission;
Jeff Davidson9a1da682014-11-11 13:52:58 -080024import android.annotation.SystemApi;
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010025import android.annotation.UnsupportedAppUsage;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070026import android.app.Activity;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070027import android.app.PendingIntent;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070028import android.app.Service;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070029import android.content.Context;
30import android.content.Intent;
Paul Jensen0784eea2014-08-19 16:00:24 -040031import android.content.pm.IPackageManager;
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -070032import android.content.pm.PackageManager;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070033import android.os.Binder;
34import android.os.IBinder;
35import android.os.Parcel;
36import android.os.ParcelFileDescriptor;
37import android.os.RemoteException;
38import android.os.ServiceManager;
Paul Jensen0784eea2014-08-19 16:00:24 -040039import android.os.UserHandle;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070040
41import com.android.internal.net.VpnConfig;
42
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070043import java.net.DatagramSocket;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070044import java.net.Inet4Address;
45import java.net.Inet6Address;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070046import java.net.InetAddress;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070047import java.net.Socket;
48import java.util.ArrayList;
Chad Brubaker4ca19e82013-06-14 11:16:51 -070049import java.util.List;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070050
51/**
52 * VpnService is a base class for applications to extend and build their
53 * own VPN solutions. In general, it creates a virtual network interface,
54 * configures addresses and routing rules, and returns a file descriptor
55 * to the application. Each read from the descriptor retrieves an outgoing
56 * packet which was routed to the interface. Each write to the descriptor
57 * injects an incoming packet just like it was received from the interface.
58 * The interface is running on Internet Protocol (IP), so packets are
59 * always started with IP headers. The application then completes a VPN
60 * connection by processing and exchanging packets with the remote server
61 * over a tunnel.
62 *
63 * <p>Letting applications intercept packets raises huge security concerns.
64 * A VPN application can easily break the network. Besides, two of them may
65 * conflict with each other. The system takes several actions to address
66 * these issues. Here are some key points:
67 * <ul>
Jeff Davidson6d6ea3b2014-09-11 14:13:22 -070068 * <li>User action is required the first time an application creates a VPN
69 * connection.</li>
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070070 * <li>There can be only one VPN connection running at the same time. The
71 * existing interface is deactivated when a new one is created.</li>
72 * <li>A system-managed notification is shown during the lifetime of a
73 * VPN connection.</li>
74 * <li>A system-managed dialog gives the information of the current VPN
75 * connection. It also provides a button to disconnect.</li>
76 * <li>The network is restored automatically when the file descriptor is
77 * closed. It also covers the cases when a VPN application is crashed
78 * or killed by the system.</li>
79 * </ul>
80 *
81 * <p>There are two primary methods in this class: {@link #prepare} and
82 * {@link Builder#establish}. The former deals with user action and stops
83 * the VPN connection created by another application. The latter creates
84 * a VPN interface using the parameters supplied to the {@link Builder}.
85 * An application must call {@link #prepare} to grant the right to use
86 * other methods in this class, and the right can be revoked at any time.
87 * Here are the general steps to create a VPN connection:
88 * <ol>
Jeff Davidson6d6ea3b2014-09-11 14:13:22 -070089 * <li>When the user presses the button to connect, call {@link #prepare}
90 * and launch the returned intent, if non-null.</li>
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -070091 * <li>When the application becomes prepared, start the service.</li>
92 * <li>Create a tunnel to the remote server and negotiate the network
93 * parameters for the VPN connection.</li>
94 * <li>Supply those parameters to a {@link Builder} and create a VPN
95 * interface by calling {@link Builder#establish}.</li>
96 * <li>Process and exchange packets between the tunnel and the returned
97 * file descriptor.</li>
98 * <li>When {@link #onRevoke} is invoked, close the file descriptor and
99 * shut down the tunnel gracefully.</li>
100 * </ol>
101 *
Benjamin Miller28a3e852017-07-14 17:17:12 +0200102 * <p>Services extending this class need to be declared with an appropriate
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700103 * permission and intent filter. Their access must be secured by
104 * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and
105 * their intent filter must match {@link #SERVICE_INTERFACE} action. Here
106 * is an example of declaring a VPN service in {@code AndroidManifest.xml}:
107 * <pre>
108 * &lt;service android:name=".ExampleVpnService"
109 * android:permission="android.permission.BIND_VPN_SERVICE"&gt;
110 * &lt;intent-filter&gt;
111 * &lt;action android:name="android.net.VpnService"/&gt;
112 * &lt;/intent-filter&gt;
113 * &lt;/service&gt;</pre>
114 *
Benjamin Miller28a3e852017-07-14 17:17:12 +0200115 * <p> The Android system starts a VPN in the background by calling
116 * {@link android.content.Context#startService startService()}. In Android 8.0
117 * (API level 26) and higher, the system places VPN apps on the temporary
118 * whitelist for a short period so the app can start in the background. The VPN
119 * app must promote itself to the foreground after it's launched or the system
120 * will shut down the app.
121 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700122 * @see Builder
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700123 */
124public class VpnService extends Service {
125
126 /**
127 * The action must be matched by the intent filter of this service. It also
128 * needs to require {@link android.Manifest.permission#BIND_VPN_SERVICE}
129 * permission so that other applications cannot abuse it.
130 */
131 public static final String SERVICE_INTERFACE = VpnConfig.SERVICE_INTERFACE;
132
133 /**
Charles He36738632017-05-15 17:07:18 +0100134 * Key for boolean meta-data field indicating whether this VpnService supports always-on mode.
135 *
136 * <p>For a VPN app targeting {@link android.os.Build.VERSION_CODES#N API 24} or above, Android
137 * provides users with the ability to set it as always-on, so that VPN connection is
138 * persisted after device reboot and app upgrade. Always-on VPN can also be enabled by device
139 * owner and profile owner apps through
140 * {@link android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage}.
141 *
142 * <p>VPN apps not supporting this feature should opt out by adding this meta-data field to the
143 * {@code VpnService} component of {@code AndroidManifest.xml}. In case there is more than one
144 * {@code VpnService} component defined in {@code AndroidManifest.xml}, opting out any one of
145 * them will opt out the entire app. For example,
146 * <pre> {@code
147 * <service android:name=".ExampleVpnService"
148 * android:permission="android.permission.BIND_VPN_SERVICE">
149 * <intent-filter>
150 * <action android:name="android.net.VpnService"/>
151 * </intent-filter>
152 * <meta-data android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
153 * android:value=false/>
154 * </service>
155 * } </pre>
156 *
Charles Hec57a01c2017-08-15 15:30:22 +0100157 * <p>This meta-data field defaults to {@code true} if absent. It will only have effect on
158 * {@link android.os.Build.VERSION_CODES#O_MR1} or higher.
Charles He36738632017-05-15 17:07:18 +0100159 */
Charles Hec57a01c2017-08-15 15:30:22 +0100160 public static final String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON =
Charles He36738632017-05-15 17:07:18 +0100161 "android.net.VpnService.SUPPORTS_ALWAYS_ON";
162
163 /**
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700164 * Use IConnectivityManager since those methods are hidden and not
165 * available in ConnectivityManager.
166 */
167 private static IConnectivityManager getService() {
168 return IConnectivityManager.Stub.asInterface(
169 ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
170 }
171
172 /**
173 * Prepare to establish a VPN connection. This method returns {@code null}
Jeff Davidson6d6ea3b2014-09-11 14:13:22 -0700174 * if the VPN application is already prepared or if the user has previously
175 * consented to the VPN application. Otherwise, it returns an
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700176 * {@link Intent} to a system activity. The application should launch the
177 * activity using {@link Activity#startActivityForResult} to get itself
178 * prepared. The activity may pop up a dialog to require user action, and
179 * the result will come back via its {@link Activity#onActivityResult}.
180 * If the result is {@link Activity#RESULT_OK}, the application becomes
181 * prepared and is granted to use other methods in this class.
182 *
183 * <p>Only one application can be granted at the same time. The right
184 * is revoked when another application is granted. The application
185 * losing the right will be notified via its {@link #onRevoke}. Unless
186 * it becomes prepared again, subsequent calls to other methods in this
187 * class will fail.
188 *
Jeff Davidson6d6ea3b2014-09-11 14:13:22 -0700189 * <p>The user may disable the VPN at any time while it is activated, in
190 * which case this method will return an intent the next time it is
191 * executed to obtain the user's consent again.
192 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700193 * @see #onRevoke
194 */
195 public static Intent prepare(Context context) {
196 try {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700197 if (getService().prepareVpn(context.getPackageName(), null, context.getUserId())) {
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700198 return null;
199 }
200 } catch (RemoteException e) {
201 // ignore
202 }
203 return VpnConfig.getIntentForConfirmation();
204 }
205
206 /**
Jeff Davidson9a1da682014-11-11 13:52:58 -0800207 * Version of {@link #prepare(Context)} which does not require user consent.
208 *
209 * <p>Requires {@link android.Manifest.permission#CONTROL_VPN} and should generally not be
210 * used. Only acceptable in situations where user consent has been obtained through other means.
211 *
212 * <p>Once this is run, future preparations may be done with the standard prepare method as this
213 * will authorize the package to prepare the VPN without consent in the future.
214 *
215 * @hide
216 */
217 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -0600218 @RequiresPermission(android.Manifest.permission.CONTROL_VPN)
Jeff Davidson9a1da682014-11-11 13:52:58 -0800219 public static void prepareAndAuthorize(Context context) {
220 IConnectivityManager cm = getService();
221 String packageName = context.getPackageName();
222 try {
223 // Only prepare if we're not already prepared.
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700224 int userId = context.getUserId();
Robin Lee3b3dd942015-05-12 18:14:58 +0100225 if (!cm.prepareVpn(packageName, null, userId)) {
226 cm.prepareVpn(null, packageName, userId);
Jeff Davidson9a1da682014-11-11 13:52:58 -0800227 }
Robin Lee3b3dd942015-05-12 18:14:58 +0100228 cm.setVpnPackageAuthorization(packageName, userId, true);
Jeff Davidson9a1da682014-11-11 13:52:58 -0800229 } catch (RemoteException e) {
230 // ignore
231 }
232 }
233
234 /**
Chad Brubakerbcf12b32014-02-11 14:18:56 -0800235 * Protect a socket from VPN connections. After protecting, data sent
236 * through this socket will go directly to the underlying network,
237 * so its traffic will not be forwarded through the VPN.
238 * This method is useful if some connections need to be kept
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700239 * outside of VPN. For example, a VPN tunnel should protect itself if its
240 * destination is covered by VPN routes. Otherwise its outgoing packets
241 * will be sent back to the VPN interface and cause an infinite loop. This
242 * method will fail if the application is not prepared or is revoked.
243 *
244 * <p class="note">The socket is NOT closed by this method.
245 *
246 * @return {@code true} on success.
247 */
248 public boolean protect(int socket) {
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400249 return NetworkUtils.protectFromVpn(socket);
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700250 }
251
252 /**
253 * Convenience method to protect a {@link Socket} from VPN connections.
254 *
255 * @return {@code true} on success.
256 * @see #protect(int)
257 */
258 public boolean protect(Socket socket) {
259 return protect(socket.getFileDescriptor$().getInt$());
260 }
261
262 /**
263 * Convenience method to protect a {@link DatagramSocket} from VPN
264 * connections.
265 *
266 * @return {@code true} on success.
267 * @see #protect(int)
268 */
269 public boolean protect(DatagramSocket socket) {
270 return protect(socket.getFileDescriptor$().getInt$());
271 }
272
273 /**
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700274 * Adds a network address to the VPN interface.
275 *
276 * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the
277 * address is already in use or cannot be assigned to the interface for any other reason.
278 *
Sreeram Ramachandran13846052014-07-10 12:35:23 -0700279 * Adding an address implicitly allows traffic from that address family (i.e., IPv4 or IPv6) to
280 * be routed over the VPN. @see Builder#allowFamily
281 *
Robin Lee1472c922015-07-29 17:25:06 +0100282 * @throws IllegalArgumentException if the address is invalid.
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700283 *
284 * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface.
285 * @param prefixLength The prefix length of the address.
286 *
287 * @return {@code true} on success.
288 * @see Builder#addAddress
Sreeram Ramachandrana1e06802014-09-11 14:08:25 -0700289 *
290 * @hide
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700291 */
292 public boolean addAddress(InetAddress address, int prefixLength) {
Sreeram Ramachandranf4e0c0c2014-07-27 14:18:26 -0700293 check(address, prefixLength);
294 try {
295 return getService().addVpnAddress(address.getHostAddress(), prefixLength);
296 } catch (RemoteException e) {
297 throw new IllegalStateException(e);
298 }
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700299 }
300
301 /**
302 * Removes a network address from the VPN interface.
303 *
304 * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the
305 * address is not assigned to the VPN interface, or if it is the only address assigned (thus
306 * cannot be removed), or if the address cannot be removed for any other reason.
307 *
Sreeram Ramachandran13846052014-07-10 12:35:23 -0700308 * After removing an address, if there are no addresses, routes or DNS servers of a particular
309 * address family (i.e., IPv4 or IPv6) configured on the VPN, that <b>DOES NOT</b> block that
310 * family from being routed. In other words, once an address family has been allowed, it stays
311 * allowed for the rest of the VPN's session. @see Builder#allowFamily
312 *
Robin Lee1472c922015-07-29 17:25:06 +0100313 * @throws IllegalArgumentException if the address is invalid.
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700314 *
315 * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface.
316 * @param prefixLength The prefix length of the address.
317 *
318 * @return {@code true} on success.
Sreeram Ramachandrana1e06802014-09-11 14:08:25 -0700319 *
320 * @hide
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700321 */
322 public boolean removeAddress(InetAddress address, int prefixLength) {
Sreeram Ramachandranf4e0c0c2014-07-27 14:18:26 -0700323 check(address, prefixLength);
324 try {
325 return getService().removeVpnAddress(address.getHostAddress(), prefixLength);
326 } catch (RemoteException e) {
327 throw new IllegalStateException(e);
328 }
Sreeram Ramachandran81c295e2014-07-09 23:21:25 -0700329 }
330
331 /**
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800332 * Sets the underlying networks used by the VPN for its upstream connections.
333 *
Sreeram Ramachandran9e956e92014-12-03 10:53:35 -0800334 * <p>Used by the system to know the actual networks that carry traffic for apps affected by
335 * this VPN in order to present this information to the user (e.g., via status bar icons).
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800336 *
Sreeram Ramachandran9e956e92014-12-03 10:53:35 -0800337 * <p>This method only needs to be called if the VPN has explicitly bound its underlying
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800338 * communications channels &mdash; such as the socket(s) passed to {@link #protect(int)} &mdash;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800339 * to a {@code Network} using APIs such as {@link Network#bindSocket(Socket)} or
340 * {@link Network#bindSocket(DatagramSocket)}. The VPN should call this method every time
341 * the set of {@code Network}s it is using changes.
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800342 *
Sreeram Ramachandran9e956e92014-12-03 10:53:35 -0800343 * <p>{@code networks} is one of the following:
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800344 * <ul>
345 * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in
346 * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular)
347 * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear
348 * first in the array.</li>
349 * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no
350 * underlying network connection, and thus, app traffic will not be sent or received.</li>
351 * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's
352 * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket}
Sreeram Ramachandran9e956e92014-12-03 10:53:35 -0800353 * APIs mentioned above to send traffic over specific channels.</li>
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800354 * </ul>
355 *
Sreeram Ramachandran9e956e92014-12-03 10:53:35 -0800356 * <p>This call will succeed only if the VPN is currently established. For setting this value
357 * when the VPN has not yet been established, see {@link Builder#setUnderlyingNetworks}.
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800358 *
359 * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers.
360 *
361 * @return {@code true} on success.
362 */
363 public boolean setUnderlyingNetworks(Network[] networks) {
364 try {
365 return getService().setUnderlyingNetworksForVpn(networks);
366 } catch (RemoteException e) {
367 throw new IllegalStateException(e);
368 }
369 }
370
371 /**
Pavel Grafovcb3b8952018-12-14 13:51:07 +0000372 * Returns whether the service is running in always-on VPN mode.
373 */
374 public final boolean isAlwaysOn() {
375 try {
376 return getService().isCallerCurrentAlwaysOnVpnApp();
377 } catch (RemoteException e) {
378 throw e.rethrowFromSystemServer();
379 }
380 }
381
382 /**
383 * Returns whether the service is running in always-on VPN mode blocking connections without
384 * VPN.
385 */
386 public final boolean isLockdownEnabled() {
387 try {
388 return getService().isCallerCurrentAlwaysOnVpnLockdownApp();
389 } catch (RemoteException e) {
390 throw e.rethrowFromSystemServer();
391 }
392 }
393
394 /**
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700395 * Return the communication interface to the service. This method returns
396 * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE}
397 * action. Applications overriding this method must identify the intent
398 * and return the corresponding interface accordingly.
399 *
400 * @see Service#onBind
401 */
402 @Override
403 public IBinder onBind(Intent intent) {
404 if (intent != null && SERVICE_INTERFACE.equals(intent.getAction())) {
405 return new Callback();
406 }
407 return null;
408 }
409
410 /**
411 * Invoked when the application is revoked. At this moment, the VPN
412 * interface is already deactivated by the system. The application should
413 * close the file descriptor and shut down gracefully. The default
414 * implementation of this method is calling {@link Service#stopSelf()}.
415 *
416 * <p class="note">Calls to this method may not happen on the main thread
417 * of the process.
418 *
419 * @see #prepare
420 */
421 public void onRevoke() {
422 stopSelf();
423 }
424
425 /**
426 * Use raw Binder instead of AIDL since now there is only one usage.
427 */
428 private class Callback extends Binder {
429 @Override
430 protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
431 if (code == IBinder.LAST_CALL_TRANSACTION) {
432 onRevoke();
433 return true;
434 }
435 return false;
436 }
437 }
438
439 /**
Sreeram Ramachandranf4e0c0c2014-07-27 14:18:26 -0700440 * Private method to validate address and prefixLength.
441 */
442 private static void check(InetAddress address, int prefixLength) {
443 if (address.isLoopbackAddress()) {
444 throw new IllegalArgumentException("Bad address");
445 }
446 if (address instanceof Inet4Address) {
447 if (prefixLength < 0 || prefixLength > 32) {
448 throw new IllegalArgumentException("Bad prefixLength");
449 }
450 } else if (address instanceof Inet6Address) {
451 if (prefixLength < 0 || prefixLength > 128) {
452 throw new IllegalArgumentException("Bad prefixLength");
453 }
454 } else {
455 throw new IllegalArgumentException("Unsupported family");
456 }
457 }
458
459 /**
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700460 * Helper class to create a VPN interface. This class should be always
461 * used within the scope of the outer {@link VpnService}.
462 *
463 * @see VpnService
464 */
465 public class Builder {
466
467 private final VpnConfig mConfig = new VpnConfig();
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100468 @UnsupportedAppUsage
Chad Brubaker4ca19e82013-06-14 11:16:51 -0700469 private final List<LinkAddress> mAddresses = new ArrayList<LinkAddress>();
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100470 @UnsupportedAppUsage
Chad Brubaker4ca19e82013-06-14 11:16:51 -0700471 private final List<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700472
473 public Builder() {
474 mConfig.user = VpnService.this.getClass().getName();
475 }
476
477 /**
478 * Set the name of this session. It will be displayed in
479 * system-managed dialogs and notifications. This is recommended
480 * not required.
481 */
482 public Builder setSession(String session) {
483 mConfig.session = session;
484 return this;
485 }
486
487 /**
488 * Set the {@link PendingIntent} to an activity for users to
489 * configure the VPN connection. If it is not set, the button
490 * to configure will not be shown in system-managed dialogs.
491 */
492 public Builder setConfigureIntent(PendingIntent intent) {
493 mConfig.configureIntent = intent;
494 return this;
495 }
496
497 /**
498 * Set the maximum transmission unit (MTU) of the VPN interface. If
499 * it is not set, the default value in the operating system will be
500 * used.
501 *
502 * @throws IllegalArgumentException if the value is not positive.
503 */
504 public Builder setMtu(int mtu) {
505 if (mtu <= 0) {
506 throw new IllegalArgumentException("Bad mtu");
507 }
508 mConfig.mtu = mtu;
509 return this;
510 }
511
512 /**
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000513 * Sets an HTTP proxy for the VPN network. This proxy is only a recommendation
514 * and it is possible that some apps will ignore it.
515 */
Irina Dumitrescu5155a2d2019-02-20 18:17:06 +0000516 public Builder setHttpProxy(@NonNull ProxyInfo proxyInfo) {
Irina Dumitrescu044a4362018-12-05 16:19:47 +0000517 mConfig.proxyInfo = proxyInfo;
518 return this;
519 }
520
521 /**
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700522 * Add a network address to the VPN interface. Both IPv4 and IPv6
523 * addresses are supported. At least one address must be set before
524 * calling {@link #establish}.
525 *
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700526 * Adding an address implicitly allows traffic from that address family
527 * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
528 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700529 * @throws IllegalArgumentException if the address is invalid.
530 */
531 public Builder addAddress(InetAddress address, int prefixLength) {
532 check(address, prefixLength);
533
534 if (address.isAnyLocalAddress()) {
535 throw new IllegalArgumentException("Bad address");
536 }
Chad Brubaker4ca19e82013-06-14 11:16:51 -0700537 mAddresses.add(new LinkAddress(address, prefixLength));
Sreeram Ramachandran42065ac2014-07-27 00:37:35 -0700538 mConfig.updateAllowedFamilies(address);
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700539 return this;
540 }
541
542 /**
543 * Convenience method to add a network address to the VPN interface
544 * using a numeric address string. See {@link InetAddress} for the
545 * definitions of numeric address formats.
546 *
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700547 * Adding an address implicitly allows traffic from that address family
548 * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
549 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700550 * @throws IllegalArgumentException if the address is invalid.
551 * @see #addAddress(InetAddress, int)
552 */
553 public Builder addAddress(String address, int prefixLength) {
554 return addAddress(InetAddress.parseNumericAddress(address), prefixLength);
555 }
556
557 /**
558 * Add a network route to the VPN interface. Both IPv4 and IPv6
559 * routes are supported.
560 *
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700561 * Adding a route implicitly allows traffic from that address family
562 * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
563 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700564 * @throws IllegalArgumentException if the route is invalid.
565 */
566 public Builder addRoute(InetAddress address, int prefixLength) {
567 check(address, prefixLength);
568
569 int offset = prefixLength / 8;
570 byte[] bytes = address.getAddress();
571 if (offset < bytes.length) {
572 for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) {
573 if (bytes[offset] != 0) {
574 throw new IllegalArgumentException("Bad address");
575 }
576 }
577 }
Lorenzo Colittib2053112015-01-20 13:40:58 +0900578 mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null));
Sreeram Ramachandran42065ac2014-07-27 00:37:35 -0700579 mConfig.updateAllowedFamilies(address);
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700580 return this;
581 }
582
583 /**
584 * Convenience method to add a network route to the VPN interface
585 * using a numeric address string. See {@link InetAddress} for the
586 * definitions of numeric address formats.
587 *
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700588 * Adding a route implicitly allows traffic from that address family
589 * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
590 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700591 * @throws IllegalArgumentException if the route is invalid.
592 * @see #addRoute(InetAddress, int)
593 */
594 public Builder addRoute(String address, int prefixLength) {
595 return addRoute(InetAddress.parseNumericAddress(address), prefixLength);
596 }
597
598 /**
599 * Add a DNS server to the VPN connection. Both IPv4 and IPv6
600 * addresses are supported. If none is set, the DNS servers of
601 * the default network will be used.
602 *
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700603 * Adding a server implicitly allows traffic from that address family
604 * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
605 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700606 * @throws IllegalArgumentException if the address is invalid.
607 */
608 public Builder addDnsServer(InetAddress address) {
609 if (address.isLoopbackAddress() || address.isAnyLocalAddress()) {
610 throw new IllegalArgumentException("Bad address");
611 }
612 if (mConfig.dnsServers == null) {
613 mConfig.dnsServers = new ArrayList<String>();
614 }
615 mConfig.dnsServers.add(address.getHostAddress());
616 return this;
617 }
618
619 /**
620 * Convenience method to add a DNS server to the VPN connection
621 * using a numeric address string. See {@link InetAddress} for the
622 * definitions of numeric address formats.
623 *
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700624 * Adding a server implicitly allows traffic from that address family
625 * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
626 *
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700627 * @throws IllegalArgumentException if the address is invalid.
628 * @see #addDnsServer(InetAddress)
629 */
630 public Builder addDnsServer(String address) {
631 return addDnsServer(InetAddress.parseNumericAddress(address));
632 }
633
634 /**
635 * Add a search domain to the DNS resolver.
636 */
637 public Builder addSearchDomain(String domain) {
638 if (mConfig.searchDomains == null) {
639 mConfig.searchDomains = new ArrayList<String>();
640 }
641 mConfig.searchDomains.add(domain);
642 return this;
643 }
644
645 /**
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700646 * Allows traffic from the specified address family.
647 *
648 * By default, if no address, route or DNS server of a specific family (IPv4 or IPv6) is
649 * added to this VPN, then all outgoing traffic of that family is blocked. If any address,
650 * route or DNS server is added, that family is allowed.
651 *
652 * This method allows an address family to be unblocked even without adding an address,
653 * route or DNS server of that family. Traffic of that family will then typically
654 * fall-through to the underlying network if it's supported.
655 *
656 * {@code family} must be either {@code AF_INET} (for IPv4) or {@code AF_INET6} (for IPv6).
657 * {@link IllegalArgumentException} is thrown if it's neither.
658 *
659 * @param family The address family ({@code AF_INET} or {@code AF_INET6}) to allow.
660 *
661 * @return this {@link Builder} object to facilitate chaining of method calls.
662 */
663 public Builder allowFamily(int family) {
Sreeram Ramachandran42065ac2014-07-27 00:37:35 -0700664 if (family == AF_INET) {
665 mConfig.allowIPv4 = true;
666 } else if (family == AF_INET6) {
667 mConfig.allowIPv6 = true;
668 } else {
669 throw new IllegalArgumentException(family + " is neither " + AF_INET + " nor " +
670 AF_INET6);
671 }
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700672 return this;
673 }
674
Paul Jensen0784eea2014-08-19 16:00:24 -0400675 private void verifyApp(String packageName) throws PackageManager.NameNotFoundException {
676 IPackageManager pm = IPackageManager.Stub.asInterface(
677 ServiceManager.getService("package"));
678 try {
679 pm.getApplicationInfo(packageName, 0, UserHandle.getCallingUserId());
680 } catch (RemoteException e) {
681 throw new IllegalStateException(e);
682 }
683 }
684
Sreeram Ramachandrand7e71642014-07-09 23:01:30 -0700685 /**
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700686 * Adds an application that's allowed to access the VPN connection.
687 *
688 * If this method is called at least once, only applications added through this method (and
689 * no others) are allowed access. Else (if this method is never called), all applications
Robert Greenwaltfc4f7212014-08-25 12:41:08 -0700690 * are allowed by default. If some applications are added, other, un-added applications
691 * will use networking as if the VPN wasn't running.
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700692 *
693 * A {@link Builder} may have only a set of allowed applications OR a set of disallowed
694 * ones, but not both. Calling this method after {@link #addDisallowedApplication} has
695 * already been called, or vice versa, will throw an {@link UnsupportedOperationException}.
696 *
697 * {@code packageName} must be the canonical name of a currently installed application.
698 * {@link PackageManager.NameNotFoundException} is thrown if there's no such application.
699 *
Robin Lee1472c922015-07-29 17:25:06 +0100700 * @throws PackageManager.NameNotFoundException If the application isn't installed.
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700701 *
702 * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application.
703 *
704 * @return this {@link Builder} object to facilitate chaining method calls.
705 */
706 public Builder addAllowedApplication(String packageName)
707 throws PackageManager.NameNotFoundException {
Paul Jensen0784eea2014-08-19 16:00:24 -0400708 if (mConfig.disallowedApplications != null) {
709 throw new UnsupportedOperationException("addDisallowedApplication already called");
710 }
711 verifyApp(packageName);
712 if (mConfig.allowedApplications == null) {
713 mConfig.allowedApplications = new ArrayList<String>();
714 }
715 mConfig.allowedApplications.add(packageName);
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700716 return this;
717 }
718
719 /**
720 * Adds an application that's denied access to the VPN connection.
721 *
722 * By default, all applications are allowed access, except for those denied through this
Robert Greenwaltfc4f7212014-08-25 12:41:08 -0700723 * method. Denied applications will use networking as if the VPN wasn't running.
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700724 *
725 * A {@link Builder} may have only a set of allowed applications OR a set of disallowed
726 * ones, but not both. Calling this method after {@link #addAllowedApplication} has already
727 * been called, or vice versa, will throw an {@link UnsupportedOperationException}.
728 *
729 * {@code packageName} must be the canonical name of a currently installed application.
730 * {@link PackageManager.NameNotFoundException} is thrown if there's no such application.
731 *
Robin Lee1472c922015-07-29 17:25:06 +0100732 * @throws PackageManager.NameNotFoundException If the application isn't installed.
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700733 *
734 * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application.
735 *
736 * @return this {@link Builder} object to facilitate chaining method calls.
737 */
738 public Builder addDisallowedApplication(String packageName)
739 throws PackageManager.NameNotFoundException {
Paul Jensen0784eea2014-08-19 16:00:24 -0400740 if (mConfig.allowedApplications != null) {
741 throw new UnsupportedOperationException("addAllowedApplication already called");
742 }
743 verifyApp(packageName);
744 if (mConfig.disallowedApplications == null) {
745 mConfig.disallowedApplications = new ArrayList<String>();
746 }
747 mConfig.disallowedApplications.add(packageName);
Sreeram Ramachandran633f0e82014-07-09 21:11:12 -0700748 return this;
749 }
750
751 /**
Sreeram Ramachandrana9294eb2014-07-09 21:43:03 -0700752 * Allows all apps to bypass this VPN connection.
753 *
754 * By default, all traffic from apps is forwarded through the VPN interface and it is not
755 * possible for apps to side-step the VPN. If this method is called, apps may use methods
Paul Jensen72db88e2015-03-10 10:54:12 -0400756 * such as {@link ConnectivityManager#bindProcessToNetwork} to instead send/receive
Sreeram Ramachandrana9294eb2014-07-09 21:43:03 -0700757 * directly over the underlying network or any other network they have permissions for.
758 *
759 * @return this {@link Builder} object to facilitate chaining of method calls.
760 */
761 public Builder allowBypass() {
Sreeram Ramachandran8cd33ed2014-07-23 15:23:15 -0700762 mConfig.allowBypass = true;
Sreeram Ramachandrana9294eb2014-07-09 21:43:03 -0700763 return this;
764 }
765
766 /**
Sreeram Ramachandrancc26b4c2014-07-18 16:41:25 -0700767 * Sets the VPN interface's file descriptor to be in blocking/non-blocking mode.
768 *
769 * By default, the file descriptor returned by {@link #establish} is non-blocking.
770 *
771 * @param blocking True to put the descriptor into blocking mode; false for non-blocking.
772 *
773 * @return this {@link Builder} object to facilitate chaining method calls.
774 */
775 public Builder setBlocking(boolean blocking) {
Jeff Davidson6bbf39c2014-07-23 10:14:53 -0700776 mConfig.blocking = blocking;
Sreeram Ramachandrancc26b4c2014-07-18 16:41:25 -0700777 return this;
778 }
779
780 /**
Sreeram Ramachandranc2c0bea2014-11-11 16:09:21 -0800781 * Sets the underlying networks used by the VPN for its upstream connections.
782 *
783 * @see VpnService#setUnderlyingNetworks
784 *
785 * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers.
786 *
787 * @return this {@link Builder} object to facilitate chaining method calls.
788 */
789 public Builder setUnderlyingNetworks(Network[] networks) {
790 mConfig.underlyingNetworks = networks != null ? networks.clone() : null;
791 return this;
792 }
793
794 /**
Varun Anand1215f092019-01-14 11:45:33 -0800795 * Marks the VPN network as metered. A VPN network is classified as metered when the user is
796 * sensitive to heavy data usage due to monetary costs and/or data limitations. In such
797 * cases, you should set this to {@code true} so that apps on the system can avoid doing
798 * large data transfers. Otherwise, set this to {@code false}. Doing so would cause VPN
799 * network to inherit its meteredness from its underlying networks.
800 *
801 * <p>VPN apps targeting {@link android.os.Build.VERSION_CODES#Q} or above will be
802 * considered metered by default.
803 *
804 * @param isMetered {@code true} if VPN network should be treated as metered regardless of
805 * underlying network meteredness
806 * @return this {@link Builder} object to facilitate chaining method calls
807 * @see #setUnderlyingNetworks(Networks[])
808 * @see ConnectivityManager#isActiveNetworkMetered()
809 */
810 public Builder setMetered(boolean isMetered) {
811 mConfig.isMetered = isMetered;
812 return this;
813 }
814
815 /**
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700816 * Create a VPN interface using the parameters supplied to this
817 * builder. The interface works on IP packets, and a file descriptor
818 * is returned for the application to access them. Each read
819 * retrieves an outgoing packet which was routed to the interface.
820 * Each write injects an incoming packet just like it was received
821 * from the interface. The file descriptor is put into non-blocking
822 * mode by default to avoid blocking Java threads. To use the file
823 * descriptor completely in native space, see
824 * {@link ParcelFileDescriptor#detachFd()}. The application MUST
825 * close the file descriptor when the VPN connection is terminated.
826 * The VPN interface will be removed and the network will be
827 * restored by the system automatically.
828 *
829 * <p>To avoid conflicts, there can be only one active VPN interface
830 * at the same time. Usually network parameters are never changed
831 * during the lifetime of a VPN connection. It is also common for an
832 * application to create a new file descriptor after closing the
833 * previous one. However, it is rare but not impossible to have two
834 * interfaces while performing a seamless handover. In this case, the
835 * old interface will be deactivated when the new one is created
836 * successfully. Both file descriptors are valid but now outgoing
837 * packets will be routed to the new interface. Therefore, after
838 * draining the old file descriptor, the application MUST close it
839 * and start using the new file descriptor. If the new interface
840 * cannot be created, the existing interface and its file descriptor
841 * remain untouched.
842 *
843 * <p>An exception will be thrown if the interface cannot be created
844 * for any reason. However, this method returns {@code null} if the
845 * application is not prepared or is revoked. This helps solve
846 * possible race conditions between other VPN applications.
847 *
848 * @return {@link ParcelFileDescriptor} of the VPN interface, or
849 * {@code null} if the application is not prepared.
850 * @throws IllegalArgumentException if a parameter is not accepted
851 * by the operating system.
852 * @throws IllegalStateException if a parameter cannot be applied
853 * by the operating system.
854 * @throws SecurityException if the service is not properly declared
855 * in {@code AndroidManifest.xml}.
856 * @see VpnService
857 */
858 public ParcelFileDescriptor establish() {
Chad Brubaker4ca19e82013-06-14 11:16:51 -0700859 mConfig.addresses = mAddresses;
860 mConfig.routes = mRoutes;
Chia-chi Yeh199ed6e2011-08-03 17:38:49 -0700861
862 try {
863 return getService().establishVpn(mConfig);
864 } catch (RemoteException e) {
865 throw new IllegalStateException(e);
866 }
867 }
868 }
869}