1199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh/* 2199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Copyright (C) 2011 The Android Open Source Project 3199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 4199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 5199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * you may not use this file except in compliance with the License. 6199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * You may obtain a copy of the License at 7199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 8199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 9199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 10199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Unless required by applicable law or agreed to in writing, software 11199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 12199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * See the License for the specific language governing permissions and 14199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * limitations under the License. 15199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 16199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 17199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehpackage android.net; 18199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 19199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.app.Activity; 20199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.app.Service; 21199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.app.PendingIntent; 22199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.content.Context; 23199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.content.Intent; 24199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.os.Binder; 25199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.os.IBinder; 26199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.os.Parcel; 27199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.os.ParcelFileDescriptor; 28199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.os.RemoteException; 29199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport android.os.ServiceManager; 30199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 31199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport com.android.internal.net.VpnConfig; 32199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 33199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport java.net.InetAddress; 34199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport java.net.Inet4Address; 35199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport java.net.Inet6Address; 36199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport java.net.DatagramSocket; 37199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport java.net.Socket; 38199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehimport java.util.ArrayList; 39199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 40199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh/** 41199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * VpnService is a base class for applications to extend and build their 42199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * own VPN solutions. In general, it creates a virtual network interface, 43199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * configures addresses and routing rules, and returns a file descriptor 44199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * to the application. Each read from the descriptor retrieves an outgoing 45199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * packet which was routed to the interface. Each write to the descriptor 46199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * injects an incoming packet just like it was received from the interface. 47199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * The interface is running on Internet Protocol (IP), so packets are 48199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * always started with IP headers. The application then completes a VPN 49199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * connection by processing and exchanging packets with the remote server 50199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * over a tunnel. 51199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 52199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p>Letting applications intercept packets raises huge security concerns. 53199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * A VPN application can easily break the network. Besides, two of them may 54199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * conflict with each other. The system takes several actions to address 55199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * these issues. Here are some key points: 56199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <ul> 57199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>User action is required to create a VPN connection.</li> 58199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>There can be only one VPN connection running at the same time. The 59199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * existing interface is deactivated when a new one is created.</li> 60199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>A system-managed notification is shown during the lifetime of a 61199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * VPN connection.</li> 62199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>A system-managed dialog gives the information of the current VPN 63199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * connection. It also provides a button to disconnect.</li> 64199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>The network is restored automatically when the file descriptor is 65199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * closed. It also covers the cases when a VPN application is crashed 66199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * or killed by the system.</li> 67199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * </ul> 68199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 69199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p>There are two primary methods in this class: {@link #prepare} and 70199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * {@link Builder#establish}. The former deals with user action and stops 71199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * the VPN connection created by another application. The latter creates 72199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * a VPN interface using the parameters supplied to the {@link Builder}. 73199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * An application must call {@link #prepare} to grant the right to use 74199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * other methods in this class, and the right can be revoked at any time. 75199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Here are the general steps to create a VPN connection: 76199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <ol> 77199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>When the user press the button to connect, call {@link #prepare} 78199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * and launch the returned intent.</li> 79199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>When the application becomes prepared, start the service.</li> 80199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>Create a tunnel to the remote server and negotiate the network 81199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * parameters for the VPN connection.</li> 82199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>Supply those parameters to a {@link Builder} and create a VPN 83199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * interface by calling {@link Builder#establish}.</li> 84199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>Process and exchange packets between the tunnel and the returned 85199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * file descriptor.</li> 86199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <li>When {@link #onRevoke} is invoked, close the file descriptor and 87199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * shut down the tunnel gracefully.</li> 88199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * </ol> 89199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 90199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p>Services extended this class need to be declared with appropriate 91199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * permission and intent filter. Their access must be secured by 92199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and 93199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * their intent filter must match {@link #SERVICE_INTERFACE} action. Here 94199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * is an example of declaring a VPN service in {@code AndroidManifest.xml}: 95199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <pre> 96199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <service android:name=".ExampleVpnService" 97199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * android:permission="android.permission.BIND_VPN_SERVICE"> 98199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <intent-filter> 99199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <action android:name="android.net.VpnService"/> 100199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * </intent-filter> 101199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * </service></pre> 102199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 103199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see Builder 104199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 105199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yehpublic class VpnService extends Service { 106199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 107199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 108199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * The action must be matched by the intent filter of this service. It also 109199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * needs to require {@link android.Manifest.permission#BIND_VPN_SERVICE} 110199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * permission so that other applications cannot abuse it. 111199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 112199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public static final String SERVICE_INTERFACE = VpnConfig.SERVICE_INTERFACE; 113199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 114199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 115199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Use IConnectivityManager since those methods are hidden and not 116199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * available in ConnectivityManager. 117199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 118199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh private static IConnectivityManager getService() { 119199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return IConnectivityManager.Stub.asInterface( 120199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 121199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 122199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 123199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 124199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Prepare to establish a VPN connection. This method returns {@code null} 125199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * if the VPN application is already prepared. Otherwise, it returns an 126199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * {@link Intent} to a system activity. The application should launch the 127199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * activity using {@link Activity#startActivityForResult} to get itself 128199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * prepared. The activity may pop up a dialog to require user action, and 129199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * the result will come back via its {@link Activity#onActivityResult}. 130199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * If the result is {@link Activity#RESULT_OK}, the application becomes 131199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * prepared and is granted to use other methods in this class. 132199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 133199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p>Only one application can be granted at the same time. The right 134199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * is revoked when another application is granted. The application 135199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * losing the right will be notified via its {@link #onRevoke}. Unless 136199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * it becomes prepared again, subsequent calls to other methods in this 137199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * class will fail. 138199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 139199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #onRevoke 140199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 141199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public static Intent prepare(Context context) { 142199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh try { 143199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (getService().prepareVpn(context.getPackageName(), null)) { 144199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return null; 145199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 146199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } catch (RemoteException e) { 147199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh // ignore 148199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 149199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return VpnConfig.getIntentForConfirmation(); 150199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 151199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 152199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 153199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Protect a socket from VPN connections. The socket will be bound to the 154199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * current default network interface, so its traffic will not be forwarded 155199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * through VPN. This method is useful if some connections need to be kept 156199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * outside of VPN. For example, a VPN tunnel should protect itself if its 157199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * destination is covered by VPN routes. Otherwise its outgoing packets 158199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * will be sent back to the VPN interface and cause an infinite loop. This 159199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * method will fail if the application is not prepared or is revoked. 160199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 161199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p class="note">The socket is NOT closed by this method. 162199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 163199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @return {@code true} on success. 164199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 165199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public boolean protect(int socket) { 166199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh ParcelFileDescriptor dup = null; 167199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh try { 168199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh dup = ParcelFileDescriptor.fromFd(socket); 169199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return getService().protectVpn(dup); 170199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } catch (Exception e) { 171199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return false; 172199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } finally { 173199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh try { 174199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh dup.close(); 175199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } catch (Exception e) { 176199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh // ignore 177199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 178199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 179199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 180199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 181199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 182199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Convenience method to protect a {@link Socket} from VPN connections. 183199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 184199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @return {@code true} on success. 185199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #protect(int) 186199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 187199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public boolean protect(Socket socket) { 188199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return protect(socket.getFileDescriptor$().getInt$()); 189199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 190199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 191199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 192199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Convenience method to protect a {@link DatagramSocket} from VPN 193199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * connections. 194199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 195199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @return {@code true} on success. 196199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #protect(int) 197199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 198199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public boolean protect(DatagramSocket socket) { 199199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return protect(socket.getFileDescriptor$().getInt$()); 200199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 201199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 202199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 203199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Return the communication interface to the service. This method returns 204199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE} 205199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * action. Applications overriding this method must identify the intent 206199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * and return the corresponding interface accordingly. 207199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 208199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see Service#onBind 209199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 210199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh @Override 211199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public IBinder onBind(Intent intent) { 212199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (intent != null && SERVICE_INTERFACE.equals(intent.getAction())) { 213199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return new Callback(); 214199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 215199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return null; 216199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 217199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 218199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 219199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Invoked when the application is revoked. At this moment, the VPN 220199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * interface is already deactivated by the system. The application should 221199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * close the file descriptor and shut down gracefully. The default 222199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * implementation of this method is calling {@link Service#stopSelf()}. 223199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 224199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p class="note">Calls to this method may not happen on the main thread 225199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * of the process. 226199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 227199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #prepare 228199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 229199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public void onRevoke() { 230199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh stopSelf(); 231199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 232199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 233199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 234199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Use raw Binder instead of AIDL since now there is only one usage. 235199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 236199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh private class Callback extends Binder { 237199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh @Override 238199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) { 239199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (code == IBinder.LAST_CALL_TRANSACTION) { 240199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh onRevoke(); 241199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return true; 242199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 243199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return false; 244199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 245199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 246199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 247199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 248199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Helper class to create a VPN interface. This class should be always 249199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * used within the scope of the outer {@link VpnService}. 250199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 251199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see VpnService 252199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 253199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public class Builder { 254199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 255199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh private final VpnConfig mConfig = new VpnConfig(); 256199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh private final StringBuilder mAddresses = new StringBuilder(); 257199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh private final StringBuilder mRoutes = new StringBuilder(); 258199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 259199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder() { 260199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.user = VpnService.this.getClass().getName(); 261199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 262199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 263199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 264199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Set the name of this session. It will be displayed in 265199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * system-managed dialogs and notifications. This is recommended 266199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * not required. 267199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 268199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder setSession(String session) { 269199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.session = session; 270199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 271199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 272199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 273199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 274199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Set the {@link PendingIntent} to an activity for users to 275199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * configure the VPN connection. If it is not set, the button 276199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * to configure will not be shown in system-managed dialogs. 277199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 278199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder setConfigureIntent(PendingIntent intent) { 279199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.configureIntent = intent; 280199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 281199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 282199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 283199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 284199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Set the maximum transmission unit (MTU) of the VPN interface. If 285199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * it is not set, the default value in the operating system will be 286199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * used. 287199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 288199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the value is not positive. 289199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 290199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder setMtu(int mtu) { 291199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (mtu <= 0) { 292199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad mtu"); 293199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 294199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.mtu = mtu; 295199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 296199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 297199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 298199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 299199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Private method to validate address and prefixLength. 300199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 301199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh private void check(InetAddress address, int prefixLength) { 302199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (address.isLoopbackAddress()) { 303199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad address"); 304199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 305199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (address instanceof Inet4Address) { 306199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (prefixLength < 0 || prefixLength > 32) { 307199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad prefixLength"); 308199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 309199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } else if (address instanceof Inet6Address) { 310199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (prefixLength < 0 || prefixLength > 128) { 311199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad prefixLength"); 312199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 313199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } else { 314199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Unsupported family"); 315199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 316199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 317199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 318199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 319199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Add a network address to the VPN interface. Both IPv4 and IPv6 320199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * addresses are supported. At least one address must be set before 321199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * calling {@link #establish}. 322199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 323199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the address is invalid. 324199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 325199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addAddress(InetAddress address, int prefixLength) { 326199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh check(address, prefixLength); 327199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 328199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (address.isAnyLocalAddress()) { 329199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad address"); 330199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 331199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 3323cd42dfd50adf8d78a9d4984957a96dec2ba13f4Johan Redestig mAddresses.append(' ' + address.getHostAddress() + '/' + prefixLength); 333199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 334199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 335199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 336199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 337199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Convenience method to add a network address to the VPN interface 338199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * using a numeric address string. See {@link InetAddress} for the 339199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * definitions of numeric address formats. 340199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 341199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the address is invalid. 342199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #addAddress(InetAddress, int) 343199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 344199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addAddress(String address, int prefixLength) { 345199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return addAddress(InetAddress.parseNumericAddress(address), prefixLength); 346199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 347199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 348199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 349199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Add a network route to the VPN interface. Both IPv4 and IPv6 350199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * routes are supported. 351199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 352199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the route is invalid. 353199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 354199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addRoute(InetAddress address, int prefixLength) { 355199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh check(address, prefixLength); 356199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 357199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh int offset = prefixLength / 8; 358199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh byte[] bytes = address.getAddress(); 359199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (offset < bytes.length) { 360199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) { 361199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (bytes[offset] != 0) { 362199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad address"); 363199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 364199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 365199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 366199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 367199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mRoutes.append(String.format(" %s/%d", address.getHostAddress(), prefixLength)); 368199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 369199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 370199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 371199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 372199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Convenience method to add a network route to the VPN interface 373199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * using a numeric address string. See {@link InetAddress} for the 374199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * definitions of numeric address formats. 375199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 376199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the route is invalid. 377199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #addRoute(InetAddress, int) 378199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 379199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addRoute(String address, int prefixLength) { 380199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return addRoute(InetAddress.parseNumericAddress(address), prefixLength); 381199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 382199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 383199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 384199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Add a DNS server to the VPN connection. Both IPv4 and IPv6 385199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * addresses are supported. If none is set, the DNS servers of 386199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * the default network will be used. 387199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 388199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the address is invalid. 389199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 390199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addDnsServer(InetAddress address) { 391199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (address.isLoopbackAddress() || address.isAnyLocalAddress()) { 392199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalArgumentException("Bad address"); 393199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 394199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (mConfig.dnsServers == null) { 395199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.dnsServers = new ArrayList<String>(); 396199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 397199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.dnsServers.add(address.getHostAddress()); 398199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 399199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 400199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 401199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 402199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Convenience method to add a DNS server to the VPN connection 403199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * using a numeric address string. See {@link InetAddress} for the 404199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * definitions of numeric address formats. 405199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 406199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if the address is invalid. 407199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see #addDnsServer(InetAddress) 408199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 409199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addDnsServer(String address) { 410199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return addDnsServer(InetAddress.parseNumericAddress(address)); 411199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 412199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 413199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 414199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Add a search domain to the DNS resolver. 415199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 416199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public Builder addSearchDomain(String domain) { 417199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh if (mConfig.searchDomains == null) { 418199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.searchDomains = new ArrayList<String>(); 419199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 420199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.searchDomains.add(domain); 421199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return this; 422199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 423199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 424199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh /** 425199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Create a VPN interface using the parameters supplied to this 426199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * builder. The interface works on IP packets, and a file descriptor 427199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * is returned for the application to access them. Each read 428199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * retrieves an outgoing packet which was routed to the interface. 429199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * Each write injects an incoming packet just like it was received 430199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * from the interface. The file descriptor is put into non-blocking 431199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * mode by default to avoid blocking Java threads. To use the file 432199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * descriptor completely in native space, see 433199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * {@link ParcelFileDescriptor#detachFd()}. The application MUST 434199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * close the file descriptor when the VPN connection is terminated. 435199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * The VPN interface will be removed and the network will be 436199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * restored by the system automatically. 437199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 438199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p>To avoid conflicts, there can be only one active VPN interface 439199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * at the same time. Usually network parameters are never changed 440199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * during the lifetime of a VPN connection. It is also common for an 441199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * application to create a new file descriptor after closing the 442199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * previous one. However, it is rare but not impossible to have two 443199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * interfaces while performing a seamless handover. In this case, the 444199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * old interface will be deactivated when the new one is created 445199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * successfully. Both file descriptors are valid but now outgoing 446199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * packets will be routed to the new interface. Therefore, after 447199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * draining the old file descriptor, the application MUST close it 448199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * and start using the new file descriptor. If the new interface 449199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * cannot be created, the existing interface and its file descriptor 450199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * remain untouched. 451199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 452199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * <p>An exception will be thrown if the interface cannot be created 453199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * for any reason. However, this method returns {@code null} if the 454199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * application is not prepared or is revoked. This helps solve 455199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * possible race conditions between other VPN applications. 456199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * 457199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @return {@link ParcelFileDescriptor} of the VPN interface, or 458199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * {@code null} if the application is not prepared. 459199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalArgumentException if a parameter is not accepted 460199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * by the operating system. 461199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws IllegalStateException if a parameter cannot be applied 462199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * by the operating system. 463199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @throws SecurityException if the service is not properly declared 464199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * in {@code AndroidManifest.xml}. 465199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh * @see VpnService 466199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh */ 467199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh public ParcelFileDescriptor establish() { 468199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.addresses = mAddresses.toString(); 469199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh mConfig.routes = mRoutes.toString(); 470199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh 471199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh try { 472199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh return getService().establishVpn(mConfig); 473199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } catch (RemoteException e) { 474199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh throw new IllegalStateException(e); 475199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 476199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 477199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh } 478199ed6ef89bd356895534ba09ac43ed340cd9a1aChia-chi Yeh} 479