1330e1089da80cddcd68758512370d217b19f8890Nathan Harold/* 2330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Copyright (C) 2017 The Android Open Source Project 3330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 4330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Licensed under the Apache License, Version 2.0 (the "License"); 5330e1089da80cddcd68758512370d217b19f8890Nathan Harold * you may not use this file except in compliance with the License. 6330e1089da80cddcd68758512370d217b19f8890Nathan Harold * You may obtain a copy of the License at 7330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 8330e1089da80cddcd68758512370d217b19f8890Nathan Harold * http://www.apache.org/licenses/LICENSE-2.0 9330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 10330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Unless required by applicable law or agreed to in writing, software 11330e1089da80cddcd68758512370d217b19f8890Nathan Harold * distributed under the License is distributed on an "AS IS" BASIS, 12330e1089da80cddcd68758512370d217b19f8890Nathan Harold * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13330e1089da80cddcd68758512370d217b19f8890Nathan Harold * See the License for the specific language governing permissions and 14330e1089da80cddcd68758512370d217b19f8890Nathan Harold * limitations under the License. 15330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 16330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpackage android.net; 17330e1089da80cddcd68758512370d217b19f8890Nathan Harold 18330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport static com.android.internal.util.Preconditions.checkNotNull; 19330e1089da80cddcd68758512370d217b19f8890Nathan Harold 2093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull; 21d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService; 22d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context; 2393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder; 24330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor; 2593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException; 26330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException; 278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log; 28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard; 29330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor; 30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException; 31330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket; 32330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress; 33330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket; 34330e1089da80cddcd68758512370d217b19f8890Nathan Harold 35330e1089da80cddcd68758512370d217b19f8890Nathan Harold/** 36330e1089da80cddcd68758512370d217b19f8890Nathan Harold * This class contains methods for managing IPsec sessions, which will perform kernel-space 37330e1089da80cddcd68758512370d217b19f8890Nathan Harold * encryption and decryption of socket or Network traffic. 38330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 39ac11ccb1f66d5dadb6c6fd1d47408e36c48c94ceNathan Harold * @hide 40330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 41d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE) 42330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager { 43330e1089da80cddcd68758512370d217b19f8890Nathan Harold private static final String TAG = "IpSecManager"; 44330e1089da80cddcd68758512370d217b19f8890Nathan Harold 45330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 4693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index. 4793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * 4893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold * <p>No IPsec packet may contain an SPI of 0. 4993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold */ 5093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; 5193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 5293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 5393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public interface Status { 5493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int OK = 0; 5593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int RESOURCE_UNAVAILABLE = 1; 5693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int SPI_UNAVAILABLE = 2; 5793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 5893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 5993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** @hide */ 6093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold public static final int INVALID_RESOURCE_ID = 0; 6193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 6293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold /** 63330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Indicates that the combination of remote InetAddress and SPI was non-unique for a given 64330e1089da80cddcd68758512370d217b19f8890Nathan Harold * request. If encountered, selection of a new SPI is required before a transform may be 65330e1089da80cddcd68758512370d217b19f8890Nathan Harold * created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random 66330e1089da80cddcd68758512370d217b19f8890Nathan Harold * or reserved using reserveSecurityParameterIndex. 67330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 68330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SpiUnavailableException extends AndroidException { 69330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final int mSpi; 70330e1089da80cddcd68758512370d217b19f8890Nathan Harold 71330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 72330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Construct an exception indicating that a transform with the given SPI is already in use 73330e1089da80cddcd68758512370d217b19f8890Nathan Harold * or otherwise unavailable. 74330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 75330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param msg Description indicating the colliding SPI 76330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param spi the SPI that could not be used due to a collision 77330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 78330e1089da80cddcd68758512370d217b19f8890Nathan Harold SpiUnavailableException(String msg, int spi) { 79330e1089da80cddcd68758512370d217b19f8890Nathan Harold super(msg + "(spi: " + spi + ")"); 80330e1089da80cddcd68758512370d217b19f8890Nathan Harold mSpi = spi; 81330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 82330e1089da80cddcd68758512370d217b19f8890Nathan Harold 83330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** Retrieve the SPI that caused a collision */ 84330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 85330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 86330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 87330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 88330e1089da80cddcd68758512370d217b19f8890Nathan Harold 89330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 90330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Indicates that the requested system resource for IPsec, such as a socket or other system 91330e1089da80cddcd68758512370d217b19f8890Nathan Harold * resource is unavailable. If this exception is thrown, try releasing allocated objects of the 92330e1089da80cddcd68758512370d217b19f8890Nathan Harold * type requested. 93330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 94330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class ResourceUnavailableException extends AndroidException { 95330e1089da80cddcd68758512370d217b19f8890Nathan Harold 96330e1089da80cddcd68758512370d217b19f8890Nathan Harold ResourceUnavailableException(String msg) { 97330e1089da80cddcd68758512370d217b19f8890Nathan Harold super(msg); 98330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 99330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 100330e1089da80cddcd68758512370d217b19f8890Nathan Harold 1011afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 102330e1089da80cddcd68758512370d217b19f8890Nathan Harold 103330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class SecurityParameterIndex implements AutoCloseable { 1041afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 105c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold private final InetAddress mRemoteAddress; 106330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 10793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; 10893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private int mResourceId; 109330e1089da80cddcd68758512370d217b19f8890Nathan Harold 110330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** Return the underlying SPI held by this object */ 111330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getSpi() { 112330e1089da80cddcd68758512370d217b19f8890Nathan Harold return mSpi; 113330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 114330e1089da80cddcd68758512370d217b19f8890Nathan Harold 115330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 116330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Release an SPI that was previously reserved. 117330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 118c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is 119c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * applied to an IpSecTransform, it will become unusable for future transforms but should 120c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * still be closed to ensure system resources are released. 121330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 122330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 123330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void close() { 1248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 1258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.releaseSecurityParameterIndex(mResourceId); 1268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 1278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 1288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 129330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.close(); 130330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 131330e1089da80cddcd68758512370d217b19f8890Nathan Harold 132330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 133330e1089da80cddcd68758512370d217b19f8890Nathan Harold protected void finalize() { 134330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 135330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 136330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 137330e1089da80cddcd68758512370d217b19f8890Nathan Harold 138330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 139330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 140330e1089da80cddcd68758512370d217b19f8890Nathan Harold 14193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private SecurityParameterIndex( 14293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi) 14393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throws ResourceUnavailableException, SpiUnavailableException { 14493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mService = service; 14593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mRemoteAddress = remoteAddress; 14693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold try { 1478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecSpiResponse result = 14893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mService.reserveSecurityParameterIndex( 14993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold direction, remoteAddress.getHostAddress(), spi, new Binder()); 15093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 15193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (result == null) { 15293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new NullPointerException("Received null response from IpSecService"); 15393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 15493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 1558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int status = result.status; 15693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold switch (status) { 15793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.OK: 15893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold break; 15993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.RESOURCE_UNAVAILABLE: 16093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new ResourceUnavailableException( 16193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "No more SPIs may be allocated by this requester."); 16293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold case Status.SPI_UNAVAILABLE: 16393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new SpiUnavailableException("Requested SPI is unavailable", spi); 16493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold default: 16593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 16693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Unknown status returned by IpSecService: " + status); 16793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 1688dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mSpi = result.spi; 1698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 17093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 17193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { 17293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); 17393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 17493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 17593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold if (mResourceId == INVALID_RESOURCE_ID) { 17693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw new RuntimeException( 17793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold "Invalid Resource ID returned by IpSecService: " + status); 17893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 17993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold 18093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 18193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 18293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 18393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mCloseGuard.open("open"); 18493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 1858dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 1868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 1878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int getResourceId() { 1888dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 1898dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 19093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 191330e1089da80cddcd68758512370d217b19f8890Nathan Harold 192330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 193c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * Reserve an SPI for traffic bound towards the specified remote address. 194330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 195330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 196330e1089da80cddcd68758512370d217b19f8890Nathan Harold * SecurityParameterIndex#close()}. 197330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 198c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} 199c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. 200330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @return the reserved SecurityParameterIndex 201330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated 202330e1089da80cddcd68758512370d217b19f8890Nathan Harold * for this user 203330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved 204330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 205330e1089da80cddcd68758512370d217b19f8890Nathan Harold public SecurityParameterIndex reserveSecurityParameterIndex( 2068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int direction, InetAddress remoteAddress) throws ResourceUnavailableException { 2076045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold try { 2086045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold return new SecurityParameterIndex( 2096045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold mService, 2106045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold direction, 2116045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold remoteAddress, 2126045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); 2136045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } catch (SpiUnavailableException unlikely) { 2146045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new ResourceUnavailableException("No SPIs available"); 2156045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2166045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 2176045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold 2186045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold /** 2196045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * Reserve an SPI for traffic bound towards the specified remote address. 2206045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 2216045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * <p>If successful, this SPI is guaranteed available until released by a call to {@link 2226045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * SecurityParameterIndex#close()}. 2236045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * 2246045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} 2256045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. 2266045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. 2276045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @return the reserved SecurityParameterIndex 2286045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated 2296045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold * for this user 2306045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold */ 2316045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold public SecurityParameterIndex reserveSecurityParameterIndex( 232c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold int direction, InetAddress remoteAddress, int requestedSpi) 233330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws SpiUnavailableException, ResourceUnavailableException { 2346045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { 2356045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); 2366045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold } 237c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi); 238330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 239330e1089da80cddcd68758512370d217b19f8890Nathan Harold 240330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 241330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec 242330e1089da80cddcd68758512370d217b19f8890Nathan Harold * encapsulation of the traffic flowing between the socket and the remote InetAddress of that 243330e1089da80cddcd68758512370d217b19f8890Nathan Harold * transform. For security reasons, attempts to send traffic to any IP address other than the 244330e1089da80cddcd68758512370d217b19f8890Nathan Harold * address associated with that transform will throw an IOException. In addition, if the 245330e1089da80cddcd68758512370d217b19f8890Nathan Harold * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to 246330e1089da80cddcd68758512370d217b19f8890Nathan Harold * send() or receive() until the transform is removed from the socket by calling {@link 247330e1089da80cddcd68758512370d217b19f8890Nathan Harold * #removeTransportModeTransform(Socket, IpSecTransform)}; 248330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 249330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a stream socket 250330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. 251da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold * @hide 252330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 253330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void applyTransportModeTransform(Socket socket, IpSecTransform transform) 254330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException { 2558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { 2568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold applyTransportModeTransform(pfd, transform); 2578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 258330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 259330e1089da80cddcd68758512370d217b19f8890Nathan Harold 260330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 261330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Apply an active Transport Mode IPsec Transform to a datagram socket to perform IPsec 262330e1089da80cddcd68758512370d217b19f8890Nathan Harold * encapsulation of the traffic flowing between the socket and the remote InetAddress of that 263330e1089da80cddcd68758512370d217b19f8890Nathan Harold * transform. For security reasons, attempts to send traffic to any IP address other than the 264330e1089da80cddcd68758512370d217b19f8890Nathan Harold * address associated with that transform will throw an IOException. In addition, if the 265330e1089da80cddcd68758512370d217b19f8890Nathan Harold * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to 266330e1089da80cddcd68758512370d217b19f8890Nathan Harold * send() or receive() until the transform is removed from the socket by calling {@link 267330e1089da80cddcd68758512370d217b19f8890Nathan Harold * #removeTransportModeTransform(DatagramSocket, IpSecTransform)}; 268330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 269330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a datagram socket 270330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. 271da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold * @hide 272330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 273330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) 274330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException { 2758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { 2768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold applyTransportModeTransform(pfd, transform); 27793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 27893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 279330e1089da80cddcd68758512370d217b19f8890Nathan Harold 280330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 281b64993559b049327365bb63e81e8046a892a1033Nathan Harold * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec 282b64993559b049327365bb63e81e8046a892a1033Nathan Harold * encapsulation of the traffic flowing between the socket and the remote InetAddress of that 283b64993559b049327365bb63e81e8046a892a1033Nathan Harold * transform. For security reasons, attempts to send traffic to any IP address other than the 284b64993559b049327365bb63e81e8046a892a1033Nathan Harold * address associated with that transform will throw an IOException. In addition, if the 285b64993559b049327365bb63e81e8046a892a1033Nathan Harold * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to 286b64993559b049327365bb63e81e8046a892a1033Nathan Harold * send() or receive() until the transform is removed from the socket by calling {@link 287da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold * #removeTransportModeTransform(FileDescriptor, IpSecTransform)}; 288b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 289b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param socket a socket file descriptor 290b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. 291b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 292b64993559b049327365bb63e81e8046a892a1033Nathan Harold public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) 293b64993559b049327365bb63e81e8046a892a1033Nathan Harold throws IOException { 2948dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() 2958dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // constructor takes control and closes the user's FD when we exit the method 2968dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // This is behaviorally the same as the other versions, but the PFD constructor does not 2978dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup(). 2988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 2998dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold applyTransportModeTransform(pfd, transform); 3008dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 3018dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 3028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 3038dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /* Call down to activate a transform */ 3048dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { 3058dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 3068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.applyTransportModeTransform(pfd, transform.getResourceId()); 3078dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 3088dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 3098dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 310b64993559b049327365bb63e81e8046a892a1033Nathan Harold } 311b64993559b049327365bb63e81e8046a892a1033Nathan Harold 312b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 313330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to 314330e1089da80cddcd68758512370d217b19f8890Nathan Harold * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to 315330e1089da80cddcd68758512370d217b19f8890Nathan Harold * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic). 316330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Applications should probably not use this API directly. Instead, they should use {@link 317330e1089da80cddcd68758512370d217b19f8890Nathan Harold * VpnService} to provide VPN capability in a more generic fashion. 318330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 319330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param net a {@link Network} that will be tunneled via IP Sec. 320330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. 321330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 322330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 323330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void applyTunnelModeTransform(Network net, IpSecTransform transform) {} 324330e1089da80cddcd68758512370d217b19f8890Nathan Harold 325330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 326330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Remove a transform from a given stream socket. Once removed, traffic on the socket will not 327330e1089da80cddcd68758512370d217b19f8890Nathan Harold * be encypted. This allows sockets that have been used for IPsec to be reclaimed for 328330e1089da80cddcd68758512370d217b19f8890Nathan Harold * communication in the clear in the event socket reuse is desired. This operation will succeed 329330e1089da80cddcd68758512370d217b19f8890Nathan Harold * regardless of the underlying state of a transform. If a transform is removed, communication 330330e1089da80cddcd68758512370d217b19f8890Nathan Harold * on all sockets to which that transform was applied will fail until this method is called. 331330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 332330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a socket that previously had a transform applied to it. 333330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform the IPsec Transform that was previously applied to the given socket 334da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold * @hide 335330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 3360bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void removeTransportModeTransform(Socket socket, IpSecTransform transform) 3370bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold throws IOException { 3388dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { 3398dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold removeTransportModeTransform(pfd, transform); 3408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 341330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 342330e1089da80cddcd68758512370d217b19f8890Nathan Harold 343330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 344330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Remove a transform from a given datagram socket. Once removed, traffic on the socket will not 345330e1089da80cddcd68758512370d217b19f8890Nathan Harold * be encypted. This allows sockets that have been used for IPsec to be reclaimed for 346330e1089da80cddcd68758512370d217b19f8890Nathan Harold * communication in the clear in the event socket reuse is desired. This operation will succeed 347330e1089da80cddcd68758512370d217b19f8890Nathan Harold * regardless of the underlying state of a transform. If a transform is removed, communication 348330e1089da80cddcd68758512370d217b19f8890Nathan Harold * on all sockets to which that transform was applied will fail until this method is called. 349330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 350330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param socket a socket that previously had a transform applied to it. 351330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform the IPsec Transform that was previously applied to the given socket 352da18b028f85e9a2c969c636aea6abf7f4bac3922Nathan Harold * @hide 353330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 3540bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) 3550bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold throws IOException { 3568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { 3578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold removeTransportModeTransform(pfd, transform); 3588dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 359330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 360330e1089da80cddcd68758512370d217b19f8890Nathan Harold 361b64993559b049327365bb63e81e8046a892a1033Nathan Harold /** 362b64993559b049327365bb63e81e8046a892a1033Nathan Harold * Remove a transform from a given stream socket. Once removed, traffic on the socket will not 363b64993559b049327365bb63e81e8046a892a1033Nathan Harold * be encypted. This allows sockets that have been used for IPsec to be reclaimed for 364b64993559b049327365bb63e81e8046a892a1033Nathan Harold * communication in the clear in the event socket reuse is desired. This operation will succeed 365b64993559b049327365bb63e81e8046a892a1033Nathan Harold * regardless of the underlying state of a transform. If a transform is removed, communication 366b64993559b049327365bb63e81e8046a892a1033Nathan Harold * on all sockets to which that transform was applied will fail until this method is called. 367b64993559b049327365bb63e81e8046a892a1033Nathan Harold * 368b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param socket a socket file descriptor that previously had a transform applied to it. 369b64993559b049327365bb63e81e8046a892a1033Nathan Harold * @param transform the IPsec Transform that was previously applied to the given socket 370b64993559b049327365bb63e81e8046a892a1033Nathan Harold */ 3710bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) 3720bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold throws IOException { 3738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { 3748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold removeTransportModeTransform(pfd, transform); 3758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 376b64993559b049327365bb63e81e8046a892a1033Nathan Harold } 377b64993559b049327365bb63e81e8046a892a1033Nathan Harold 378330e1089da80cddcd68758512370d217b19f8890Nathan Harold /* Call down to activate a transform */ 37993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { 38093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold try { 38193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold mService.removeTransportModeTransform(pfd, transform.getResourceId()); 38293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } catch (RemoteException e) { 38393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold throw e.rethrowFromSystemServer(); 38493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 38593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold } 386330e1089da80cddcd68758512370d217b19f8890Nathan Harold 387330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 388330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of 389330e1089da80cddcd68758512370d217b19f8890Nathan Harold * cleanup if a tunneled Network experiences a change in default route. The Network will drop 390330e1089da80cddcd68758512370d217b19f8890Nathan Harold * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is 391330e1089da80cddcd68758512370d217b19f8890Nathan Harold * lost, all traffic will drop. 392330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 393330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param net a network that currently has transform applied to it. 394330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given 395330e1089da80cddcd68758512370d217b19f8890Nathan Harold * network 396330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 397330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 398330e1089da80cddcd68758512370d217b19f8890Nathan Harold public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} 399330e1089da80cddcd68758512370d217b19f8890Nathan Harold 400330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 401330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Class providing access to a system-provided UDP Encapsulation Socket, which may be used for 402330e1089da80cddcd68758512370d217b19f8890Nathan Harold * IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic. 403330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 404330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>The socket provided by this class cannot be re-bound or closed via the inner 405330e1089da80cddcd68758512370d217b19f8890Nathan Harold * FileDescriptor. Instead, disposing of this socket requires a call to close(). 406330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 407330e1089da80cddcd68758512370d217b19f8890Nathan Harold public static final class UdpEncapsulationSocket implements AutoCloseable { 4088dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final ParcelFileDescriptor mPfd; 4091afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold private final IIpSecService mService; 4108dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final int mResourceId; 4118dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold private final int mPort; 412330e1089da80cddcd68758512370d217b19f8890Nathan Harold private final CloseGuard mCloseGuard = CloseGuard.get(); 413330e1089da80cddcd68758512370d217b19f8890Nathan Harold 41493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) 4158dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throws ResourceUnavailableException, IOException { 4161afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold mService = service; 4178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 4188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold IpSecUdpEncapResponse result = 4198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.openUdpEncapsulationSocket(port, new Binder()); 4208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold switch (result.status) { 4218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.OK: 4228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold break; 4238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold case Status.RESOURCE_UNAVAILABLE: 4248dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new ResourceUnavailableException( 4258dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "No more Sockets may be allocated by this requester."); 4268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold default: 4278dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new RuntimeException( 4288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold "Unknown status returned by IpSecService: " + result.status); 4298dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 4308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mResourceId = result.resourceId; 4318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPort = result.port; 4328dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd = result.fileDescriptor; 4338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 4348dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 4358dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 436330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.open("constructor"); 437330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 438330e1089da80cddcd68758512370d217b19f8890Nathan Harold 439330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** Access the inner UDP Encapsulation Socket */ 440330e1089da80cddcd68758512370d217b19f8890Nathan Harold public FileDescriptor getSocket() { 4418dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (mPfd == null) { 4428dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return null; 4438dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 4448dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPfd.getFileDescriptor(); 445330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 446330e1089da80cddcd68758512370d217b19f8890Nathan Harold 447330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** Retrieve the port number of the inner encapsulation socket */ 448330e1089da80cddcd68758512370d217b19f8890Nathan Harold public int getPort() { 4498dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mPort; 450330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 451330e1089da80cddcd68758512370d217b19f8890Nathan Harold 452330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 453330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 454330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Release the resources that have been reserved for this Socket. 455330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 456330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>This method closes the underlying socket, reducing a user's allocated sockets in the 457330e1089da80cddcd68758512370d217b19f8890Nathan Harold * system. This must be done as part of cleanup following use of a socket. Failure to do so 458330e1089da80cddcd68758512370d217b19f8890Nathan Harold * will cause the socket to count against a total allocation limit for IpSec and eventually 459330e1089da80cddcd68758512370d217b19f8890Nathan Harold * fail due to resource limits. 460330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 461330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param fd a file descriptor previously returned as a UDP Encapsulation socket. 462330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 4630bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold public void close() throws IOException { 4648dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 4658dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mService.closeUdpEncapsulationSocket(mResourceId); 4668dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (RemoteException e) { 4678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e.rethrowFromSystemServer(); 4688dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 4698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 4708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold try { 4718dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold mPfd.close(); 4728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } catch (IOException e) { 4738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); 4748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw e; 4758dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 476330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.close(); 477330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 478330e1089da80cddcd68758512370d217b19f8890Nathan Harold 479330e1089da80cddcd68758512370d217b19f8890Nathan Harold @Override 480330e1089da80cddcd68758512370d217b19f8890Nathan Harold protected void finalize() throws Throwable { 481330e1089da80cddcd68758512370d217b19f8890Nathan Harold if (mCloseGuard != null) { 482330e1089da80cddcd68758512370d217b19f8890Nathan Harold mCloseGuard.warnIfOpen(); 483330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 484330e1089da80cddcd68758512370d217b19f8890Nathan Harold close(); 485330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 4868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold 4878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /** @hide */ 4888dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold int getResourceId() { 4898dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return mResourceId; 4908dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 491330e1089da80cddcd68758512370d217b19f8890Nathan Harold }; 492330e1089da80cddcd68758512370d217b19f8890Nathan Harold 493330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 494330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Open a socket that is bound to a free UDP port on the system. 495330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 496330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by 497330e1089da80cddcd68758512370d217b19f8890Nathan Harold * the caller. This provides safe access to a socket on a port that can later be used as a UDP 498330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Encapsulation port. 499330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 500330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the 501330e1089da80cddcd68758512370d217b19f8890Nathan Harold * socket port. Explicitly opening this port is only necessary if communication is desired on 502330e1089da80cddcd68758512370d217b19f8890Nathan Harold * that port. 503330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 504330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param port a local UDP port to be reserved for UDP Encapsulation. is provided, then this 505330e1089da80cddcd68758512370d217b19f8890Nathan Harold * method will bind to the specified port or fail. To retrieve the port number, call {@link 506330e1089da80cddcd68758512370d217b19f8890Nathan Harold * android.system.Os#getsockname(FileDescriptor)}. 507330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @return a {@link UdpEncapsulationSocket} that is bound to the requested port for the lifetime 508330e1089da80cddcd68758512370d217b19f8890Nathan Harold * of the object. 509330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 510330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 511330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 512330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 513330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 514330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 515330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) 516330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 5178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold /* 5188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * Most range checking is done in the service, but this version of the constructor expects 5198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold * a valid port number, and zero cannot be checked after being passed to the service. 5208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold */ 5218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold if (port == 0) { 5228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold throw new IllegalArgumentException("Specified port must be a valid port number!"); 5238dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold } 5241afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold return new UdpEncapsulationSocket(mService, port); 525330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 526330e1089da80cddcd68758512370d217b19f8890Nathan Harold 527330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 528330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Open a socket that is bound to a port selected by the system. 529330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 530330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by 531330e1089da80cddcd68758512370d217b19f8890Nathan Harold * the caller. This provides safe access to a socket on a port that can later be used as a UDP 532330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Encapsulation port. 533330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 534330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the 535330e1089da80cddcd68758512370d217b19f8890Nathan Harold * socket port. Explicitly opening this port is only necessary if communication is desired on 536330e1089da80cddcd68758512370d217b19f8890Nathan Harold * that port. 537330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 538330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @return a {@link UdpEncapsulationSocket} that is bound to an arbitrarily selected port 539330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 540330e1089da80cddcd68758512370d217b19f8890Nathan Harold // Returning a socket in this fashion that has been created and bound by the system 541330e1089da80cddcd68758512370d217b19f8890Nathan Harold // is the only safe way to ensure that a socket is both accessible to the user and 542330e1089da80cddcd68758512370d217b19f8890Nathan Harold // safely usable for Encapsulation without allowing a user to possibly unbind from/close 543330e1089da80cddcd68758512370d217b19f8890Nathan Harold // the port, which could potentially impact the traffic of the next user who binds to that 544330e1089da80cddcd68758512370d217b19f8890Nathan Harold // socket. 545330e1089da80cddcd68758512370d217b19f8890Nathan Harold public UdpEncapsulationSocket openUdpEncapsulationSocket() 546330e1089da80cddcd68758512370d217b19f8890Nathan Harold throws IOException, ResourceUnavailableException { 5478dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold return new UdpEncapsulationSocket(mService, 0); 548330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 549330e1089da80cddcd68758512370d217b19f8890Nathan Harold 550330e1089da80cddcd68758512370d217b19f8890Nathan Harold /** 551330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Retrieve an instance of an IpSecManager within you application context 552330e1089da80cddcd68758512370d217b19f8890Nathan Harold * 553330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @param context the application context for this manager 554330e1089da80cddcd68758512370d217b19f8890Nathan Harold * @hide 555330e1089da80cddcd68758512370d217b19f8890Nathan Harold */ 5561afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold public IpSecManager(IIpSecService service) { 557330e1089da80cddcd68758512370d217b19f8890Nathan Harold mService = checkNotNull(service, "missing service"); 558330e1089da80cddcd68758512370d217b19f8890Nathan Harold } 559330e1089da80cddcd68758512370d217b19f8890Nathan Harold} 560