Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | package android.net; |
| 17 | |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 18 | import static android.net.IpSecManager.INVALID_RESOURCE_ID; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 19 | |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 20 | import android.annotation.IntDef; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 21 | import android.annotation.NonNull; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 22 | import android.annotation.SystemApi; |
| 23 | import android.content.Context; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 24 | import android.os.Binder; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 25 | import android.os.IBinder; |
| 26 | import android.os.RemoteException; |
| 27 | import android.os.ServiceManager; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 28 | import android.util.Log; |
Nathan Harold | d999d22 | 2017-09-11 19:53:33 -0700 | [diff] [blame] | 29 | |
ludi | 1a06aa7 | 2017-05-12 09:15:00 -0700 | [diff] [blame] | 30 | import com.android.internal.annotations.VisibleForTesting; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 31 | import com.android.internal.util.Preconditions; |
Nathan Harold | d999d22 | 2017-09-11 19:53:33 -0700 | [diff] [blame] | 32 | |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 33 | import dalvik.system.CloseGuard; |
Nathan Harold | d999d22 | 2017-09-11 19:53:33 -0700 | [diff] [blame] | 34 | |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 35 | import java.io.IOException; |
| 36 | import java.lang.annotation.Retention; |
| 37 | import java.lang.annotation.RetentionPolicy; |
| 38 | import java.net.InetAddress; |
| 39 | |
| 40 | /** |
| 41 | * This class represents an IpSecTransform, which encapsulates both properties and state of IPsec. |
| 42 | * |
| 43 | * <p>IpSecTransforms must be built from an IpSecTransform.Builder, and they must persist throughout |
| 44 | * the lifetime of the underlying transform. If a transform object leaves scope, the underlying |
| 45 | * transform may be disabled automatically, with likely undesirable results. |
| 46 | * |
| 47 | * <p>An IpSecTransform may either represent a tunnel mode transform that operates on a wide array |
| 48 | * of traffic or may represent a transport mode transform operating on a Socket or Sockets. |
| 49 | */ |
| 50 | public final class IpSecTransform implements AutoCloseable { |
| 51 | private static final String TAG = "IpSecTransform"; |
| 52 | |
| 53 | /** |
| 54 | * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies |
| 55 | * to traffic towards the host. |
| 56 | */ |
| 57 | public static final int DIRECTION_IN = 0; |
| 58 | |
| 59 | /** |
| 60 | * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies |
| 61 | * to traffic from the host. |
| 62 | */ |
| 63 | public static final int DIRECTION_OUT = 1; |
| 64 | |
| 65 | /** @hide */ |
| 66 | @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) |
| 67 | @Retention(RetentionPolicy.SOURCE) |
| 68 | public @interface TransformDirection {} |
| 69 | |
| 70 | /** @hide */ |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 71 | public static final int MODE_TRANSPORT = 0; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 72 | |
| 73 | /** @hide */ |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 74 | public static final int MODE_TUNNEL = 1; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 75 | |
| 76 | /** @hide */ |
| 77 | public static final int ENCAP_NONE = 0; |
| 78 | |
| 79 | /** |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 80 | * IpSec traffic will be encapsulated within a UDP header with an additional 8-byte header pad |
| 81 | * (of '0'-value bytes) that prevents traffic from being interpreted as IKE or as ESP over UDP. |
| 82 | * |
| 83 | * @hide |
| 84 | */ |
Nathan Harold | 8dc1fd0 | 2017-04-04 19:37:48 -0700 | [diff] [blame] | 85 | public static final int ENCAP_ESPINUDP_NON_IKE = 1; |
| 86 | |
| 87 | /** |
| 88 | * IpSec traffic will be encapsulated within UDP as per <a |
| 89 | * href="https://tools.ietf.org/html/rfc3948">RFC3498</a>. |
| 90 | * |
| 91 | * @hide |
| 92 | */ |
| 93 | public static final int ENCAP_ESPINUDP = 2; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 94 | |
| 95 | /** @hide */ |
Nathan Harold | 8dc1fd0 | 2017-04-04 19:37:48 -0700 | [diff] [blame] | 96 | @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE}) |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 97 | @Retention(RetentionPolicy.SOURCE) |
| 98 | public @interface EncapType {} |
| 99 | |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 100 | private IpSecTransform(Context context, IpSecConfig config) { |
| 101 | mContext = context; |
| 102 | mConfig = config; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 103 | mResourceId = INVALID_RESOURCE_ID; |
| 104 | } |
| 105 | |
| 106 | private IIpSecService getIpSecService() { |
| 107 | IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE); |
| 108 | if (b == null) { |
| 109 | throw new RemoteException("Failed to connect to IpSecService") |
| 110 | .rethrowAsRuntimeException(); |
| 111 | } |
| 112 | |
| 113 | return IIpSecService.Stub.asInterface(b); |
| 114 | } |
| 115 | |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 116 | /** |
| 117 | * Checks the result status and throws an appropriate exception if |
| 118 | * the status is not Status.OK. |
| 119 | */ |
| 120 | private void checkResultStatus(int status) |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 121 | throws IOException, IpSecManager.ResourceUnavailableException, |
| 122 | IpSecManager.SpiUnavailableException { |
| 123 | switch (status) { |
| 124 | case IpSecManager.Status.OK: |
| 125 | return; |
| 126 | // TODO: Pass Error string back from bundle so that errors can be more specific |
| 127 | case IpSecManager.Status.RESOURCE_UNAVAILABLE: |
| 128 | throw new IpSecManager.ResourceUnavailableException( |
| 129 | "Failed to allocate a new IpSecTransform"); |
| 130 | case IpSecManager.Status.SPI_UNAVAILABLE: |
| 131 | Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved"); |
| 132 | // Fall through |
| 133 | default: |
| 134 | throw new IllegalStateException( |
| 135 | "Failed to Create a Transform with status code " + status); |
| 136 | } |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | private IpSecTransform activate() |
| 140 | throws IOException, IpSecManager.ResourceUnavailableException, |
| 141 | IpSecManager.SpiUnavailableException { |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 142 | synchronized (this) { |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 143 | try { |
| 144 | IIpSecService svc = getIpSecService(); |
Nathan Harold | 8dc1fd0 | 2017-04-04 19:37:48 -0700 | [diff] [blame] | 145 | IpSecTransformResponse result = |
| 146 | svc.createTransportModeTransform(mConfig, new Binder()); |
| 147 | int status = result.status; |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 148 | checkResultStatus(status); |
Nathan Harold | 8dc1fd0 | 2017-04-04 19:37:48 -0700 | [diff] [blame] | 149 | mResourceId = result.resourceId; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 150 | |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 151 | /* Keepalive will silently fail if not needed by the config; but, if needed and |
| 152 | * it fails to start, we need to bail because a transform will not be reliable |
| 153 | * to use if keepalive is expected to offload and fails. |
| 154 | */ |
| 155 | // FIXME: if keepalive fails, we need to fail spectacularly |
| 156 | startKeepalive(mContext); |
| 157 | Log.d(TAG, "Added Transform with Id " + mResourceId); |
| 158 | mCloseGuard.open("build"); |
| 159 | } catch (RemoteException e) { |
| 160 | throw e.rethrowAsRuntimeException(); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 161 | } |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 162 | } |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 163 | |
| 164 | return this; |
| 165 | } |
| 166 | |
| 167 | /** |
| 168 | * Deactivate an IpSecTransform and free all resources for that transform that are managed by |
| 169 | * the system for this Transform. |
| 170 | * |
| 171 | * <p>Deactivating a transform while it is still applied to any Socket will result in sockets |
| 172 | * refusing to send or receive data. This method will silently succeed if the specified |
| 173 | * transform has already been removed; thus, it is always safe to attempt cleanup when a |
| 174 | * transform is no longer needed. |
| 175 | */ |
| 176 | public void close() { |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 177 | Log.d(TAG, "Removing Transform with Id " + mResourceId); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 178 | |
| 179 | // Always safe to attempt cleanup |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 180 | if (mResourceId == INVALID_RESOURCE_ID) { |
| 181 | mCloseGuard.close(); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 182 | return; |
| 183 | } |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 184 | try { |
| 185 | /* Order matters here because the keepalive is best-effort but could fail in some |
| 186 | * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we |
| 187 | * still want to clear out the transform. |
| 188 | */ |
| 189 | IIpSecService svc = getIpSecService(); |
| 190 | svc.deleteTransportModeTransform(mResourceId); |
| 191 | stopKeepalive(); |
| 192 | } catch (RemoteException e) { |
| 193 | throw e.rethrowAsRuntimeException(); |
| 194 | } finally { |
| 195 | mResourceId = INVALID_RESOURCE_ID; |
| 196 | mCloseGuard.close(); |
| 197 | } |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | @Override |
| 201 | protected void finalize() throws Throwable { |
| 202 | if (mCloseGuard != null) { |
| 203 | mCloseGuard.warnIfOpen(); |
| 204 | } |
| 205 | close(); |
| 206 | } |
| 207 | |
| 208 | /* Package */ |
| 209 | IpSecConfig getConfig() { |
| 210 | return mConfig; |
| 211 | } |
| 212 | |
| 213 | private final IpSecConfig mConfig; |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 214 | private int mResourceId; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 215 | private final Context mContext; |
| 216 | private final CloseGuard mCloseGuard = CloseGuard.get(); |
| 217 | private ConnectivityManager.PacketKeepalive mKeepalive; |
| 218 | private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; |
| 219 | private Object mKeepaliveSyncLock = new Object(); |
| 220 | private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback = |
| 221 | new ConnectivityManager.PacketKeepaliveCallback() { |
| 222 | |
| 223 | @Override |
| 224 | public void onStarted() { |
| 225 | synchronized (mKeepaliveSyncLock) { |
| 226 | mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS; |
| 227 | mKeepaliveSyncLock.notifyAll(); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | @Override |
| 232 | public void onStopped() { |
| 233 | synchronized (mKeepaliveSyncLock) { |
| 234 | mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; |
| 235 | mKeepaliveSyncLock.notifyAll(); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | @Override |
| 240 | public void onError(int error) { |
| 241 | synchronized (mKeepaliveSyncLock) { |
| 242 | mKeepaliveStatus = error; |
| 243 | mKeepaliveSyncLock.notifyAll(); |
| 244 | } |
| 245 | } |
| 246 | }; |
| 247 | |
| 248 | /* Package */ |
| 249 | void startKeepalive(Context c) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 250 | if (mConfig.getNattKeepaliveInterval() != 0) { |
| 251 | Log.wtf(TAG, "Keepalive not yet supported."); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 252 | } |
| 253 | } |
| 254 | |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 255 | /** @hide */ |
| 256 | @VisibleForTesting |
| 257 | public int getResourceId() { |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 258 | return mResourceId; |
| 259 | } |
| 260 | |
| 261 | /* Package */ |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 262 | void stopKeepalive() { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 263 | return; |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 264 | } |
| 265 | |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 266 | /** |
| 267 | * Builder object to facilitate the creation of IpSecTransform objects. |
| 268 | * |
| 269 | * <p>Apply additional properties to the transform and then call a build() method to return an |
| 270 | * IpSecTransform object. |
| 271 | * |
| 272 | * @see Builder#buildTransportModeTransform(InetAddress) |
| 273 | */ |
| 274 | public static class Builder { |
| 275 | private Context mContext; |
| 276 | private IpSecConfig mConfig; |
| 277 | |
| 278 | /** |
| 279 | * Add an encryption algorithm to the transform for the given direction. |
| 280 | * |
| 281 | * <p>If encryption is set for a given direction without also providing an SPI for that |
| 282 | * direction, creation of an IpSecTransform will fail upon calling a build() method. |
| 283 | * |
| 284 | * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} |
| 285 | * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. |
| 286 | */ |
| 287 | public IpSecTransform.Builder setEncryption( |
| 288 | @TransformDirection int direction, IpSecAlgorithm algo) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 289 | mConfig.setEncryption(direction, algo); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 290 | return this; |
| 291 | } |
| 292 | |
| 293 | /** |
| 294 | * Add an authentication/integrity algorithm to the transform. |
| 295 | * |
| 296 | * <p>If authentication is set for a given direction without also providing an SPI for that |
| 297 | * direction, creation of an IpSecTransform will fail upon calling a build() method. |
| 298 | * |
| 299 | * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} |
| 300 | * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. |
| 301 | */ |
| 302 | public IpSecTransform.Builder setAuthentication( |
| 303 | @TransformDirection int direction, IpSecAlgorithm algo) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 304 | mConfig.setAuthentication(direction, algo); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 305 | return this; |
| 306 | } |
| 307 | |
| 308 | /** |
| 309 | * Set the SPI, which uniquely identifies a particular IPsec session from others. Because |
| 310 | * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a |
| 311 | * given destination address. |
| 312 | * |
| 313 | * <p>Care should be chosen when selecting an SPI to ensure that is is as unique as |
Nathan Harold | 48b5665 | 2017-03-30 11:01:37 -0700 | [diff] [blame] | 314 | * possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int, |
| 315 | * InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being |
| 316 | * activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}. |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 317 | * |
| 318 | * <p>Unless an SPI is set for a given direction, traffic in that direction will be |
| 319 | * sent/received without any IPsec applied. |
| 320 | * |
| 321 | * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} |
| 322 | * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed |
| 323 | * traffic |
| 324 | */ |
| 325 | public IpSecTransform.Builder setSpi( |
| 326 | @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 327 | mConfig.setSpiResourceId(direction, spi.getResourceId()); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 328 | return this; |
| 329 | } |
| 330 | |
| 331 | /** |
| 332 | * Specify the network on which this transform will emit its traffic; (otherwise it will |
| 333 | * emit on the default network). |
| 334 | * |
| 335 | * <p>Restricts the transformed traffic to a particular {@link Network}. This is required in |
| 336 | * tunnel mode. |
| 337 | * |
| 338 | * @hide |
| 339 | */ |
| 340 | @SystemApi |
| 341 | public IpSecTransform.Builder setUnderlyingNetwork(Network net) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 342 | mConfig.setNetwork(net); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 343 | return this; |
| 344 | } |
| 345 | |
| 346 | /** |
| 347 | * Add UDP encapsulation to an IPv4 transform |
| 348 | * |
| 349 | * <p>This option allows IPsec traffic to pass through NAT. Refer to RFC 3947 and 3948 for |
| 350 | * details on how UDP should be applied to IPsec. |
| 351 | * |
| 352 | * @param localSocket a {@link IpSecManager.UdpEncapsulationSocket} for sending and |
| 353 | * receiving encapsulating traffic. |
| 354 | * @param remotePort the UDP port number of the remote that will send and receive |
| 355 | * encapsulated traffic. In the case of IKE, this is likely port 4500. |
| 356 | */ |
| 357 | public IpSecTransform.Builder setIpv4Encapsulation( |
| 358 | IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 359 | mConfig.setEncapType(ENCAP_ESPINUDP); |
| 360 | mConfig.setEncapSocketResourceId(localSocket.getResourceId()); |
| 361 | mConfig.setEncapRemotePort(remotePort); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 362 | return this; |
| 363 | } |
| 364 | |
| 365 | // TODO: Decrease the minimum keepalive to maybe 10? |
| 366 | // TODO: Probably a better exception to throw for NATTKeepalive failure |
| 367 | // TODO: Specify the needed NATT keepalive permission. |
| 368 | /** |
| 369 | * Send a NATT Keepalive packet with a given maximum interval. This will create an offloaded |
| 370 | * request to do power-efficient NATT Keepalive. If NATT keepalive is requested but cannot |
| 371 | * be activated, then the transform will fail to activate and throw an IOException. |
| 372 | * |
| 373 | * @param intervalSeconds the maximum number of seconds between keepalive packets, no less |
| 374 | * than 20s and no more than 3600s. |
| 375 | * @hide |
| 376 | */ |
| 377 | @SystemApi |
| 378 | public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) { |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 379 | mConfig.setNattKeepaliveInterval(intervalSeconds); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 380 | return this; |
| 381 | } |
| 382 | |
| 383 | /** |
| 384 | * Build and return an active {@link IpSecTransform} object as a Transport Mode Transform. |
| 385 | * Some parameters have interdependencies that are checked at build time. If a well-formed |
| 386 | * transform cannot be created from the supplied parameters, this method will throw an |
| 387 | * Exception. |
| 388 | * |
| 389 | * <p>Upon a successful return from this call, the provided IpSecTransform will be active |
| 390 | * and may be applied to sockets. If too many IpSecTransform objects are active for a given |
| 391 | * user this operation will fail and throw ResourceUnavailableException. To avoid these |
| 392 | * exceptions, unused Transform objects must be cleaned up by calling {@link |
| 393 | * IpSecTransform#close()} when they are no longer needed. |
| 394 | * |
| 395 | * @param remoteAddress the {@link InetAddress} that, when matched on traffic to/from this |
| 396 | * socket will cause the transform to be applied. |
| 397 | * <p>Note that an active transform will not impact any network traffic until it has |
| 398 | * been applied to one or more Sockets. Calling this method is a necessary precondition |
| 399 | * for applying it to a socket, but is not sufficient to actually apply IPsec. |
| 400 | * @throws IllegalArgumentException indicating that a particular combination of transform |
| 401 | * properties is invalid. |
| 402 | * @throws IpSecManager.ResourceUnavailableException in the event that no more Transforms |
| 403 | * may be allocated |
| 404 | * @throws SpiUnavailableException if the SPI collides with an existing transform |
| 405 | * (unlikely). |
| 406 | * @throws ResourceUnavailableException if the current user currently has exceeded the |
| 407 | * number of allowed active transforms. |
| 408 | */ |
| 409 | public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress) |
| 410 | throws IpSecManager.ResourceUnavailableException, |
| 411 | IpSecManager.SpiUnavailableException, IOException { |
| 412 | //FIXME: argument validation here |
| 413 | //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 414 | mConfig.setMode(MODE_TRANSPORT); |
| 415 | mConfig.setRemoteAddress(remoteAddress.getHostAddress()); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 416 | return new IpSecTransform(mContext, mConfig).activate(); |
| 417 | } |
| 418 | |
| 419 | /** |
| 420 | * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some |
| 421 | * parameters have interdependencies that are checked at build time. |
| 422 | * |
| 423 | * @param localAddress the {@link InetAddress} that provides the local endpoint for this |
| 424 | * IPsec tunnel. This is almost certainly an address belonging to the {@link Network} |
| 425 | * that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}. |
| 426 | * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this |
| 427 | * IPsec tunnel. |
| 428 | * @throws IllegalArgumentException indicating that a particular combination of transform |
| 429 | * properties is invalid. |
| 430 | * @hide |
| 431 | */ |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 432 | public IpSecTransform buildTunnelModeTransform( |
| 433 | InetAddress localAddress, InetAddress remoteAddress) { |
| 434 | //FIXME: argument validation here |
| 435 | //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); |
Nathan Harold | a10003d | 2017-08-23 13:46:33 -0700 | [diff] [blame^] | 436 | mConfig.setLocalAddress(localAddress.getHostAddress()); |
| 437 | mConfig.setRemoteAddress(remoteAddress.getHostAddress()); |
| 438 | mConfig.setMode(MODE_TUNNEL); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 439 | return new IpSecTransform(mContext, mConfig); |
| 440 | } |
| 441 | |
| 442 | /** |
| 443 | * Create a new IpSecTransform.Builder to construct an IpSecTransform |
| 444 | * |
| 445 | * @param context current Context |
| 446 | */ |
Nathan Harold | 93962f3 | 2017-03-07 13:23:36 -0800 | [diff] [blame] | 447 | public Builder(@NonNull Context context) { |
| 448 | Preconditions.checkNotNull(context); |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 449 | mContext = context; |
| 450 | mConfig = new IpSecConfig(); |
| 451 | } |
Nathan Harold | 330e108 | 2017-01-12 18:38:57 -0800 | [diff] [blame] | 452 | } |
| 453 | } |