1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.net.ipsec.ike.net; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 21 import static android.net.ipsec.ike.IkeManager.getIkeLog; 22 import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_NONE; 23 import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_UDP; 24 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO; 25 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV4; 26 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV6; 27 import static android.net.ipsec.ike.IkeSessionParams.IKE_NATT_KEEPALIVE_DELAY_SEC_MAX; 28 import static android.net.ipsec.ike.IkeSessionParams.IKE_NATT_KEEPALIVE_DELAY_SEC_MIN; 29 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION; 30 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES; 31 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_FORCE_PORT_4500; 32 import static android.net.ipsec.ike.exceptions.IkeException.wrapAsIkeException; 33 34 import static com.android.internal.net.ipsec.ike.IkeContext.CONFIG_AUTO_NATT_KEEPALIVES_CELLULAR_TIMEOUT_OVERRIDE_SECONDS; 35 import static com.android.internal.net.ipsec.ike.utils.IkeAlarm.IkeAlarmConfig; 36 import static com.android.internal.net.ipsec.ike.utils.IkeAlarmReceiver.ACTION_KEEPALIVE; 37 38 import android.annotation.IntDef; 39 import android.app.PendingIntent; 40 import android.net.ConnectivityManager; 41 import android.net.IpSecManager; 42 import android.net.IpSecManager.ResourceUnavailableException; 43 import android.net.LinkAddress; 44 import android.net.LinkProperties; 45 import android.net.Network; 46 import android.net.NetworkCapabilities; 47 import android.net.NetworkRequest; 48 import android.net.ipsec.ike.IkeSessionConnectionInfo; 49 import android.net.ipsec.ike.IkeSessionParams; 50 import android.net.ipsec.ike.exceptions.IkeException; 51 import android.os.Handler; 52 import android.os.Message; 53 import android.system.ErrnoException; 54 55 import com.android.internal.annotations.VisibleForTesting; 56 import com.android.internal.net.ipsec.ike.IkeContext; 57 import com.android.internal.net.ipsec.ike.IkeSocket; 58 import com.android.internal.net.ipsec.ike.IkeSocketConfig; 59 import com.android.internal.net.ipsec.ike.IkeUdp4Socket; 60 import com.android.internal.net.ipsec.ike.IkeUdp6Socket; 61 import com.android.internal.net.ipsec.ike.IkeUdp6WithEncapPortSocket; 62 import com.android.internal.net.ipsec.ike.IkeUdpEncapSocket; 63 import com.android.internal.net.ipsec.ike.SaRecord.IkeSaRecord; 64 import com.android.internal.net.ipsec.ike.keepalive.IkeNattKeepalive; 65 import com.android.internal.net.ipsec.ike.keepalive.IkeNattKeepalive.KeepaliveConfig; 66 import com.android.internal.net.ipsec.ike.message.IkeHeader; 67 import com.android.internal.net.ipsec.ike.shim.ShimUtils; 68 import com.android.internal.net.ipsec.ike.utils.IkeAlarm; 69 70 import java.io.IOException; 71 import java.lang.annotation.Retention; 72 import java.lang.annotation.RetentionPolicy; 73 import java.net.Inet4Address; 74 import java.net.Inet6Address; 75 import java.net.InetAddress; 76 import java.net.UnknownHostException; 77 import java.util.ArrayList; 78 import java.util.Arrays; 79 import java.util.Collections; 80 import java.util.HashSet; 81 import java.util.List; 82 import java.util.Set; 83 import java.util.concurrent.TimeUnit; 84 85 /** 86 * IkeConnectionController manages all connectivity events for an IKE Session 87 * 88 * <p>IkeConnectionController's responsibilities include: 89 * 90 * <ul> 91 * <li>Manage IkeSocket for sending and receiving IKE packets 92 * <li>Monitor and handle network and addresses changes 93 * <li>Schedule NAT-T keepalive 94 * </ul> 95 * 96 * An IkeConnectionController should be set up when IKE Session is being established and should be 97 * torn down when the IKE Session is terminated. 98 */ 99 public class IkeConnectionController implements IkeNetworkUpdater, IkeSocket.Callback { 100 private static final String TAG = IkeConnectionController.class.getSimpleName(); 101 102 // The maximum number of attempts allowed for a single DNS resolution. 103 private static final int MAX_DNS_RESOLUTION_ATTEMPTS = 3; 104 105 @VisibleForTesting public static final int AUTO_KEEPALIVE_DELAY_SEC_WIFI = 15; 106 @VisibleForTesting public static final int AUTO_KEEPALIVE_DELAY_SEC_CELL = 150; 107 108 @Retention(RetentionPolicy.SOURCE) 109 @IntDef({ 110 NAT_TRAVERSAL_SUPPORT_NOT_CHECKED, 111 NAT_TRAVERSAL_UNSUPPORTED, 112 NAT_NOT_DETECTED, 113 NAT_DETECTED 114 }) 115 public @interface NatStatus {} 116 117 /** The IKE client has not checked whether the server supports NAT-T */ 118 public static final int NAT_TRAVERSAL_SUPPORT_NOT_CHECKED = 0; 119 /** The IKE server does not support NAT-T */ 120 public static final int NAT_TRAVERSAL_UNSUPPORTED = 1; 121 /** There is no NAT between the IKE client and the server */ 122 public static final int NAT_NOT_DETECTED = 2; 123 /** There is at least a NAT between the IKE client and the server */ 124 public static final int NAT_DETECTED = 3; 125 126 private final IkeContext mIkeContext; 127 private final Config mConfig; 128 private final ConnectivityManager mConnectivityManager; 129 private final IpSecManager mIpSecManager; 130 private final Dependencies mDependencies; 131 private final IkeLocalAddressGenerator mIkeLocalAddressGenerator; 132 private final Callback mCallback; 133 134 private final boolean mForcePort4500; 135 private final boolean mUseCallerConfiguredNetwork; 136 private final String mRemoteHostname; 137 private final int mDscp = 0; 138 private final IkeSessionParams mIkeParams; 139 // Must only be touched on the IkeSessionStateMachine thread. 140 private IkeAlarmConfig mKeepaliveAlarmConfig; 141 142 private IkeSocket mIkeSocket; 143 144 /** Underlying network for this IKE Session. May change if mobility handling is enabled. */ 145 private Network mNetwork; 146 147 /** NetworkCapabilities of the underlying network */ 148 private NetworkCapabilities mNc; 149 150 /** 151 * Network callback used to keep IkeConnectionController aware of network changes when mobility 152 * handling is enabled. 153 */ 154 private IkeNetworkCallbackBase mNetworkCallback; 155 156 private boolean mMobilityEnabled = false; 157 158 /** Local address assigned on device. */ 159 private InetAddress mLocalAddress; 160 /** Remote address resolved from caller configured hostname. */ 161 private InetAddress mRemoteAddress; 162 /** Available remote addresses that are v4. */ 163 private final List<Inet4Address> mRemoteAddressesV4 = new ArrayList<>(); 164 /** Available remote addresses that are v6. */ 165 private final List<Inet6Address> mRemoteAddressesV6 = new ArrayList<>(); 166 167 private final Set<IkeSaRecord> mIkeSaRecords = new HashSet<>(); 168 169 @NatStatus private int mNatStatus; 170 171 // Must only be touched on the IkeSessionStateMachine thread. 172 @IkeSessionParams.EspIpVersion private int mIpVersion; 173 @IkeSessionParams.EspEncapType private int mEncapType; 174 175 //Must only be touched on the IkeSessionStateMachine thread. 176 private Network mUnderpinnedNetwork; 177 178 private IkeNattKeepalive mIkeNattKeepalive; 179 180 /** Constructor of IkeConnectionController */ 181 @VisibleForTesting IkeConnectionController( IkeContext ikeContext, Config config, Dependencies dependencies)182 public IkeConnectionController( 183 IkeContext ikeContext, Config config, Dependencies dependencies) { 184 mIkeContext = ikeContext; 185 mConfig = config; 186 mConnectivityManager = mIkeContext.getContext().getSystemService(ConnectivityManager.class); 187 mIpSecManager = mIkeContext.getContext().getSystemService(IpSecManager.class); 188 mDependencies = dependencies; 189 mIkeLocalAddressGenerator = dependencies.newIkeLocalAddressGenerator(); 190 mCallback = config.callback; 191 192 mIkeParams = config.ikeParams; 193 mForcePort4500 = config.ikeParams.hasIkeOption(IKE_OPTION_FORCE_PORT_4500); 194 mRemoteHostname = config.ikeParams.getServerHostname(); 195 mUseCallerConfiguredNetwork = config.ikeParams.getConfiguredNetwork() != null; 196 mIpVersion = config.ikeParams.getIpVersion(); 197 mEncapType = config.ikeParams.getEncapType(); 198 mUnderpinnedNetwork = null; 199 200 if (mUseCallerConfiguredNetwork) { 201 mNetwork = config.ikeParams.getConfiguredNetwork(); 202 } else { 203 mNetwork = mConnectivityManager.getActiveNetwork(); 204 if (mNetwork == null) { 205 throw new IllegalStateException("No active default network found"); 206 } 207 } 208 209 getIkeLog().d(TAG, "Set up on Network " + mNetwork); 210 211 mNatStatus = NAT_TRAVERSAL_SUPPORT_NOT_CHECKED; 212 } 213 214 /** Constructor of IkeConnectionController */ IkeConnectionController(IkeContext ikeContext, Config config)215 public IkeConnectionController(IkeContext ikeContext, Config config) { 216 this(ikeContext, config, new Dependencies()); 217 } 218 219 /** Config includes all configurations to build an IkeConnectionController */ 220 public static class Config { 221 public final IkeSessionParams ikeParams; 222 public final int ikeSessionId; 223 public final int alarmCmd; 224 public final int sendKeepaliveCmd; 225 public final Callback callback; 226 227 /** Constructor for IkeConnectionController.Config */ Config( IkeSessionParams ikeParams, int ikeSessionId, int alarmCmd, int sendKeepaliveCmd, Callback callback)228 public Config( 229 IkeSessionParams ikeParams, 230 int ikeSessionId, 231 int alarmCmd, 232 int sendKeepaliveCmd, 233 Callback callback) { 234 this.ikeParams = ikeParams; 235 this.ikeSessionId = ikeSessionId; 236 this.alarmCmd = alarmCmd; 237 this.sendKeepaliveCmd = sendKeepaliveCmd; 238 this.callback = callback; 239 } 240 } 241 242 /** Callback to notify status changes of the connection */ 243 public interface Callback { 244 /** Notify the IkeConnectionController caller the underlying network has changed */ onUnderlyingNetworkUpdated()245 void onUnderlyingNetworkUpdated(); 246 247 /** Notify the IkeConnectionController caller that the underlying network died */ onUnderlyingNetworkDied(Network network)248 void onUnderlyingNetworkDied(Network network); 249 250 /** Notify the IkeConnectionController caller of the incoming IKE packet */ onIkePacketReceived(IkeHeader ikeHeader, byte[] ikePackets)251 void onIkePacketReceived(IkeHeader ikeHeader, byte[] ikePackets); 252 253 /** Notify the IkeConnectionController caller of the IKE fatal error */ onError(IkeException exception)254 void onError(IkeException exception); 255 } 256 257 /** External dependencies, for injection in tests */ 258 @VisibleForTesting 259 public static class Dependencies { 260 /** Gets an IkeLocalAddressGenerator */ newIkeLocalAddressGenerator()261 public IkeLocalAddressGenerator newIkeLocalAddressGenerator() { 262 return new IkeLocalAddressGenerator(); 263 } 264 265 /** Builds and starts NATT keepalive */ newIkeNattKeepalive( IkeContext ikeContext, KeepaliveConfig keepaliveConfig)266 public IkeNattKeepalive newIkeNattKeepalive( 267 IkeContext ikeContext, KeepaliveConfig keepaliveConfig) throws IOException { 268 IkeNattKeepalive keepalive = 269 new IkeNattKeepalive( 270 ikeContext, 271 ikeContext.getContext().getSystemService(ConnectivityManager.class), 272 keepaliveConfig); 273 keepalive.start(); 274 return keepalive; 275 } 276 277 /** Builds and returns a new IkeUdp4Socket */ newIkeUdp4Socket( IkeSocketConfig sockConfig, IkeSocket.Callback callback, Handler handler)278 public IkeUdp4Socket newIkeUdp4Socket( 279 IkeSocketConfig sockConfig, IkeSocket.Callback callback, Handler handler) 280 throws ErrnoException, IOException { 281 return IkeUdp4Socket.getInstance(sockConfig, callback, handler); 282 } 283 284 /** Builds and returns a new IkeUdp6Socket */ newIkeUdp6Socket( IkeSocketConfig sockConfig, IkeSocket.Callback callback, Handler handler)285 public IkeUdp6Socket newIkeUdp6Socket( 286 IkeSocketConfig sockConfig, IkeSocket.Callback callback, Handler handler) 287 throws ErrnoException, IOException { 288 return IkeUdp6Socket.getInstance(sockConfig, callback, handler); 289 } 290 291 /** Builds and returns a new IkeUdp6WithEncapPortSocket */ newIkeUdp6WithEncapPortSocket( IkeSocketConfig sockConfig, IkeSocket.Callback callback, Handler handler)292 public IkeUdp6WithEncapPortSocket newIkeUdp6WithEncapPortSocket( 293 IkeSocketConfig sockConfig, IkeSocket.Callback callback, Handler handler) 294 throws ErrnoException, IOException { 295 return IkeUdp6WithEncapPortSocket.getIkeUdpEncapSocket(sockConfig, callback, handler); 296 } 297 298 /** Builds and returns a new IkeUdpEncapSocket */ newIkeUdpEncapSocket( IkeSocketConfig sockConfig, IpSecManager ipSecManager, IkeSocket.Callback callback, Handler handler)299 public IkeUdpEncapSocket newIkeUdpEncapSocket( 300 IkeSocketConfig sockConfig, 301 IpSecManager ipSecManager, 302 IkeSocket.Callback callback, 303 Handler handler) 304 throws ErrnoException, IOException, ResourceUnavailableException { 305 return IkeUdpEncapSocket.getIkeUdpEncapSocket( 306 sockConfig, ipSecManager, callback, handler.getLooper()); 307 } 308 } 309 310 /** 311 * Get the keepalive delay from params, transports and device config. 312 * 313 * If the AUTOMATIC_NATT_KEEPALIVES option is set, look up the transport in the network 314 * capabilities ; if Wi-Fi use the fixed delay, if cell use the device property int 315 * (or a fixed delay in the absence of the permission to read device properties). 316 * For other transports, or if the AUTOMATIC_NATT_KEEPALIVES option is not set, use the 317 * delay from the session params. 318 * 319 * @param ikeContext Context to read the device config, if necessary. 320 * @param ikeParams the session params 321 * @param nc the capabilities of the underlying network 322 * @return the keepalive delay to use, in seconds. 323 */ 324 @VisibleForTesting getKeepaliveDelaySec( IkeContext ikeContext, IkeSessionParams ikeParams, NetworkCapabilities nc)325 public static int getKeepaliveDelaySec( 326 IkeContext ikeContext, IkeSessionParams ikeParams, NetworkCapabilities nc) { 327 int keepaliveDelaySeconds = ikeParams.getNattKeepAliveDelaySeconds(); 328 329 if (ikeParams.hasIkeOption(IKE_OPTION_AUTOMATIC_NATT_KEEPALIVES)) { 330 if (nc.hasTransport(TRANSPORT_WIFI)) { 331 // Most of the time, IKE Session will use shorter keepalive timer on WiFi. Thus 332 // choose the Wifi timer as a more conservative value when the NetworkCapabilities 333 // have both TRANSPORT_WIFI and TRANSPORT_CELLULAR 334 final int autoDelaySeconds = AUTO_KEEPALIVE_DELAY_SEC_WIFI; 335 keepaliveDelaySeconds = Math.min(keepaliveDelaySeconds, autoDelaySeconds); 336 } else if (nc.hasTransport(TRANSPORT_CELLULAR)) { 337 final int autoDelaySeconds = 338 ikeContext.getDeviceConfigPropertyInt( 339 CONFIG_AUTO_NATT_KEEPALIVES_CELLULAR_TIMEOUT_OVERRIDE_SECONDS, 340 IKE_NATT_KEEPALIVE_DELAY_SEC_MIN, 341 IKE_NATT_KEEPALIVE_DELAY_SEC_MAX, 342 AUTO_KEEPALIVE_DELAY_SEC_CELL); 343 keepaliveDelaySeconds = Math.min(keepaliveDelaySeconds, autoDelaySeconds); 344 } 345 } 346 347 return keepaliveDelaySeconds; 348 } 349 buildInitialKeepaliveAlarmConfig( Handler handler, IkeContext ikeContext, Config config, IkeSessionParams ikeParams, NetworkCapabilities nc)350 private static IkeAlarmConfig buildInitialKeepaliveAlarmConfig( 351 Handler handler, 352 IkeContext ikeContext, 353 Config config, 354 IkeSessionParams ikeParams, 355 NetworkCapabilities nc) { 356 final Message keepaliveMsg = handler.obtainMessage( 357 config.alarmCmd /* what */, 358 config.ikeSessionId /* arg1 */, 359 config.sendKeepaliveCmd /* arg2 */); 360 final PendingIntent keepaliveIntent = IkeAlarm.buildIkeAlarmIntent(ikeContext.getContext(), 361 ACTION_KEEPALIVE, getIntentIdentifier(config.ikeSessionId), keepaliveMsg); 362 363 return new IkeAlarmConfig( 364 ikeContext.getContext(), 365 ACTION_KEEPALIVE, 366 TimeUnit.SECONDS.toMillis(getKeepaliveDelaySec(ikeContext, ikeParams, nc)), 367 keepaliveIntent, 368 keepaliveMsg); 369 } 370 getIntentIdentifier(int ikeSessionId)371 private static String getIntentIdentifier(int ikeSessionId) { 372 return TAG + "_" + ikeSessionId; 373 } 374 375 /** Update the IKE NATT keepalive */ setupOrUpdateNattKeeaplive(IkeSocket ikeSocket)376 private void setupOrUpdateNattKeeaplive(IkeSocket ikeSocket) throws IOException { 377 if (!(ikeSocket instanceof IkeUdpEncapSocket)) { 378 if (mIkeNattKeepalive != null) { 379 mIkeNattKeepalive.stop(); 380 mIkeNattKeepalive = null; 381 } 382 return; 383 } 384 385 final KeepaliveConfig keepaliveConfig = 386 new KeepaliveConfig( 387 (Inet4Address) mLocalAddress, 388 (Inet4Address) mRemoteAddress, 389 ((IkeUdpEncapSocket) ikeSocket).getUdpEncapsulationSocket(), 390 mNetwork, 391 mUnderpinnedNetwork, 392 mKeepaliveAlarmConfig, 393 mIkeParams); 394 395 if (mIkeNattKeepalive != null) { 396 mIkeNattKeepalive.restart(keepaliveConfig); 397 } else { 398 mIkeNattKeepalive = mDependencies.newIkeNattKeepalive(mIkeContext, keepaliveConfig); 399 } 400 } 401 getIkeSocket(boolean isIpv4, boolean useEncapPort)402 private IkeSocket getIkeSocket(boolean isIpv4, boolean useEncapPort) throws IkeException { 403 IkeSocketConfig sockConfig = new IkeSocketConfig(this, mDscp); 404 IkeSocket result = null; 405 406 try { 407 if (useEncapPort) { 408 if (isIpv4) { 409 result = mDependencies.newIkeUdpEncapSocket( 410 sockConfig, mIpSecManager, this, new Handler(mIkeContext.getLooper())); 411 } else { 412 result = mDependencies.newIkeUdp6WithEncapPortSocket( 413 sockConfig, this, new Handler(mIkeContext.getLooper())); 414 } 415 } else { 416 if (isIpv4) { 417 result = mDependencies.newIkeUdp4Socket( 418 sockConfig, this, new Handler(mIkeContext.getLooper())); 419 } else { 420 result = mDependencies.newIkeUdp6Socket( 421 sockConfig, this, new Handler(mIkeContext.getLooper())); 422 } 423 } 424 425 if (result == null) { 426 throw new IOException("No socket created"); 427 } 428 429 result.bindToNetwork(mNetwork); 430 return result; 431 } catch (ErrnoException | IOException | ResourceUnavailableException e) { 432 throw wrapAsIkeException(e); 433 } 434 } 435 migrateSpiToIkeSocket(long localSpi, IkeSocket oldSocket, IkeSocket newSocket)436 private void migrateSpiToIkeSocket(long localSpi, IkeSocket oldSocket, IkeSocket newSocket) { 437 newSocket.registerIke(localSpi, this); 438 oldSocket.unregisterIke(localSpi); 439 } 440 getAndSwitchToIkeSocket(boolean isIpv4, boolean useEncapPort)441 private void getAndSwitchToIkeSocket(boolean isIpv4, boolean useEncapPort) throws IkeException { 442 IkeSocket newSocket = getIkeSocket(isIpv4, useEncapPort); 443 444 try { 445 setupOrUpdateNattKeeaplive(newSocket); 446 } catch (IOException e) { 447 throw wrapAsIkeException(e); 448 } 449 450 if (newSocket != mIkeSocket) { 451 for (IkeSaRecord saRecord : mIkeSaRecords) { 452 migrateSpiToIkeSocket(saRecord.getLocalSpi(), mIkeSocket, newSocket); 453 } 454 mIkeSocket.releaseReference(this); 455 mIkeSocket = newSocket; 456 } 457 } 458 459 /** Sets up the IkeConnectionController */ setUp()460 public void setUp() throws IkeException { 461 // Make sure all the resources, especially the NetworkCallback, is released before creating 462 // new one. 463 unregisterResources(); 464 465 // This is call is directly from the IkeSessionStateMachine, and thus cannot be 466 // accidentally called in a NetworkCallback. See 467 // ConnectivityManager.NetworkCallback#onLinkPropertiesChanged() and 468 // ConnectivityManager.NetworkCallback#onCapabilitiesChanged() for discussion of 469 // mixing callbacks and synchronous polling methods. 470 LinkProperties linkProperties = mConnectivityManager.getLinkProperties(mNetwork); 471 mNc = mConnectivityManager.getNetworkCapabilities(mNetwork); 472 mKeepaliveAlarmConfig = buildInitialKeepaliveAlarmConfig( 473 new Handler(mIkeContext.getLooper()), mIkeContext, mConfig, mIkeParams, mNc); 474 try { 475 if (linkProperties == null || mNc == null) { 476 // Throw NPE to preserve the existing behaviour for backward compatibility 477 throw wrapAsIkeException( 478 new NullPointerException( 479 "Attempt setup on network " 480 + mNetwork 481 + " with null LinkProperties or null NetworkCapabilities")); 482 } 483 resolveAndSetAvailableRemoteAddresses(); 484 selectAndSetRemoteAddress(linkProperties); 485 486 int remotePort = 487 mForcePort4500 488 ? IkeSocket.SERVER_PORT_UDP_ENCAPSULATED 489 : IkeSocket.SERVER_PORT_NON_UDP_ENCAPSULATED; 490 boolean isIpv4 = mRemoteAddress instanceof Inet4Address; 491 mLocalAddress = 492 mIkeLocalAddressGenerator.generateLocalAddress( 493 mNetwork, isIpv4, mRemoteAddress, remotePort); 494 mIkeSocket = getIkeSocket(isIpv4, mForcePort4500); 495 496 setupOrUpdateNattKeeaplive(mIkeSocket); 497 } catch (IOException | ErrnoException e) { 498 throw wrapAsIkeException(e); 499 } 500 501 try { 502 if (mUseCallerConfiguredNetwork) { 503 // Caller configured a specific Network - track it 504 // ConnectivityManager does not provide a callback for tracking a specific 505 // Network. In order to do so, create a NetworkRequest without any 506 // capabilities so it will match all Networks. The NetworkCallback will then 507 // filter for the correct (caller-specified) Network. 508 NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); 509 mNetworkCallback = 510 new IkeSpecificNetworkCallback( 511 this, mNetwork, mLocalAddress, linkProperties, mNc); 512 mConnectivityManager.registerNetworkCallback( 513 request, mNetworkCallback, new Handler(mIkeContext.getLooper())); 514 } else { 515 // Caller did not configure a specific Network - track the default 516 mNetworkCallback = 517 new IkeDefaultNetworkCallback( 518 this, mNetwork, mLocalAddress, linkProperties, mNc); 519 mConnectivityManager.registerDefaultNetworkCallback( 520 mNetworkCallback, new Handler(mIkeContext.getLooper())); 521 } 522 } catch (RuntimeException e) { 523 mNetworkCallback = null; 524 throw wrapAsIkeException(e); 525 } 526 } 527 unregisterResources()528 private void unregisterResources() { 529 if (mIkeNattKeepalive != null) { 530 mIkeNattKeepalive.stop(); 531 mIkeNattKeepalive = null; 532 } 533 534 if (mNetworkCallback != null) { 535 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 536 mNetworkCallback = null; 537 } 538 539 if (mIkeSocket != null) { 540 for (IkeSaRecord saRecord : mIkeSaRecords) { 541 mIkeSocket.unregisterIke(saRecord.getLocalSpi()); 542 } 543 544 mIkeSocket.releaseReference(this); 545 mIkeSocket = null; 546 } 547 548 mIkeSaRecords.clear(); 549 } 550 551 /** Tears down the IkeConnectionController */ tearDown()552 public void tearDown() { 553 unregisterResources(); 554 } 555 556 /** Returns the IkeSocket */ getIkeSocket()557 public IkeSocket getIkeSocket() { 558 return mIkeSocket; 559 } 560 561 /** Returns if the IkeSocket is a UDP encapsulation socket */ useUdpEncapSocket()562 public boolean useUdpEncapSocket() { 563 return mIkeSocket instanceof IkeUdpEncapSocket; 564 } 565 566 /** Sends out an IKE packet */ sendIkePacket(byte[] ikePacket)567 public void sendIkePacket(byte[] ikePacket) { 568 mIkeSocket.sendIkePacket(ikePacket, mRemoteAddress); 569 } 570 571 /** Registers the local SPI for an IKE SA waiting for the IKE INIT response */ registerIkeSpi(long ikeSpi)572 public void registerIkeSpi(long ikeSpi) { 573 mIkeSocket.registerIke(ikeSpi, this); 574 } 575 576 /** Unregisters the local SPI for an IKE SA that failed IKE INIT exchange */ unregisterIkeSpi(long ikeSpi)577 public void unregisterIkeSpi(long ikeSpi) { 578 mIkeSocket.unregisterIke(ikeSpi); 579 } 580 581 /** Registers a newly created IKE SA */ registerIkeSaRecord(IkeSaRecord saRecord)582 public void registerIkeSaRecord(IkeSaRecord saRecord) { 583 mIkeSaRecords.add(saRecord); 584 mIkeSocket.registerIke(saRecord.getLocalSpi(), this); 585 } 586 587 /** Unregisters a deleted IKE SA */ unregisterIkeSaRecord(IkeSaRecord saRecord)588 public void unregisterIkeSaRecord(IkeSaRecord saRecord) { 589 mIkeSaRecords.remove(saRecord); 590 mIkeSocket.unregisterIke(saRecord.getLocalSpi()); 591 } 592 593 /** Returns all registered IKE SAs */ 594 @VisibleForTesting getIkeSaRecords()595 public Set<IkeSaRecord> getIkeSaRecords() { 596 return Collections.unmodifiableSet(mIkeSaRecords); 597 } 598 599 /** 600 * Updates the underlying network 601 * 602 * <p>This call is always from IkeSessionStateMachine for migrating IKE to a caller configured 603 * network, or to update the protocol preference or keepalive delay. 604 */ onNetworkSetByUser( Network network, int ipVersion, int encapType, int keepaliveDelaySeconds)605 public void onNetworkSetByUser( 606 Network network, 607 int ipVersion, 608 int encapType, 609 int keepaliveDelaySeconds) 610 throws IkeException { 611 if (!mMobilityEnabled) { 612 // Program error. IkeSessionStateMachine should never call this method before enabling 613 // mobility. 614 getIkeLog().wtf(TAG, "Attempt to update network when mobility is disabled"); 615 return; 616 } 617 618 // This is call is directly from the IkeSessionStateMachine, and thus cannot be 619 // accidentally called in a NetworkCallback. See 620 // ConnectivityManager.NetworkCallback#onLinkPropertiesChanged() and 621 // ConnectivityManager.NetworkCallback#onCapabilitiesChanged() for discussion of 622 // mixing callbacks and synchronous polling methods. 623 final LinkProperties linkProperties = mConnectivityManager.getLinkProperties(network); 624 final NetworkCapabilities networkCapabilities = 625 mConnectivityManager.getNetworkCapabilities(network); 626 627 if (linkProperties == null || networkCapabilities == null) { 628 // Throw NPE to preserve the existing behaviour for backward compatibility 629 throw wrapAsIkeException( 630 new NullPointerException( 631 "Attempt migrating to network " 632 + network 633 + " with null LinkProperties or null NetworkCapabilities")); 634 635 // TODO(b/224686889): Notify caller of failed mobility attempt and keep this IKE Session 636 // alive 637 } 638 639 mIpVersion = ipVersion; 640 mEncapType = encapType; 641 642 if (keepaliveDelaySeconds == IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO) { 643 keepaliveDelaySeconds = getKeepaliveDelaySec(mIkeContext, mIkeParams, mNc); 644 } 645 final long keepaliveDelayMs = TimeUnit.SECONDS.toMillis(keepaliveDelaySeconds); 646 if (keepaliveDelayMs != mKeepaliveAlarmConfig.delayMs) { 647 mKeepaliveAlarmConfig = mKeepaliveAlarmConfig.buildCopyWithDelayMs(keepaliveDelayMs); 648 restartKeepaliveIfRunning(); 649 } 650 651 // Switch to monitor a new network. This call is never expected to trigger a callback 652 mNetworkCallback.setNetwork(network, linkProperties, networkCapabilities); 653 handleUnderlyingNetworkUpdated( 654 network, linkProperties, networkCapabilities, false /* skipIfSameNetwork */); 655 } 656 657 /** Called when the underpinned network is set by the user */ onUnderpinnedNetworkSetByUser(final Network underpinnedNetwork)658 public void onUnderpinnedNetworkSetByUser(final Network underpinnedNetwork) 659 throws IkeException { 660 mUnderpinnedNetwork = underpinnedNetwork; 661 restartKeepaliveIfRunning(); 662 } 663 restartKeepaliveIfRunning()664 private void restartKeepaliveIfRunning() throws IkeException { 665 try { 666 setupOrUpdateNattKeeaplive(mIkeSocket); 667 } catch (IOException e) { 668 throw wrapAsIkeException(e); 669 } 670 } 671 672 /** Gets the underlying network */ getNetwork()673 public Network getNetwork() { 674 return mNetwork; 675 } 676 677 /** Gets the underpinned network */ getUnderpinnedNetwork()678 public Network getUnderpinnedNetwork() { 679 return mUnderpinnedNetwork; 680 } 681 682 /** Check if mobility is enabled */ isMobilityEnabled()683 public boolean isMobilityEnabled() { 684 return mMobilityEnabled; 685 } 686 687 /** 688 * Sets the local address. 689 * 690 * <p>This MUST only be called in a test. 691 */ 692 @VisibleForTesting setLocalAddress(InetAddress address)693 public void setLocalAddress(InetAddress address) { 694 mLocalAddress = address; 695 } 696 697 /** Gets the local address */ getLocalAddress()698 public InetAddress getLocalAddress() { 699 return mLocalAddress; 700 } 701 702 /** 703 * Sets the remote address. 704 * 705 * <p>This MUST only be called in a test. 706 */ 707 @VisibleForTesting setRemoteAddress(InetAddress address)708 public void setRemoteAddress(InetAddress address) { 709 mRemoteAddress = address; 710 addRemoteAddress(address); 711 } 712 713 /** 714 * Adds a remote address. 715 * 716 * <p>This MUST only be called in a test. 717 */ 718 @VisibleForTesting addRemoteAddress(InetAddress address)719 public void addRemoteAddress(InetAddress address) { 720 if (address instanceof Inet4Address) { 721 mRemoteAddressesV4.add((Inet4Address) address); 722 } else { 723 mRemoteAddressesV6.add((Inet6Address) address); 724 } 725 } 726 727 /** Gets the remote addresses */ getRemoteAddress()728 public InetAddress getRemoteAddress() { 729 return mRemoteAddress; 730 } 731 732 /** Gets all the IPv4 remote addresses */ getAllRemoteIpv4Addresses()733 public List<Inet4Address> getAllRemoteIpv4Addresses() { 734 return new ArrayList<>(mRemoteAddressesV4); 735 } 736 737 /** Gets all the IPv6 remote addresses */ getAllRemoteIpv6Addresses()738 public List<Inet6Address> getAllRemoteIpv6Addresses() { 739 return new ArrayList<>(mRemoteAddressesV6); 740 } 741 742 /** Gets the local port */ getLocalPort()743 public int getLocalPort() { 744 try { 745 return mIkeSocket.getLocalPort(); 746 } catch (ErrnoException e) { 747 throw new IllegalStateException("Fail to get local port", e); 748 } 749 } 750 751 /** Gets the remote port */ getRemotePort()752 public int getRemotePort() { 753 return mIkeSocket.getIkeServerPort(); 754 } 755 756 /** Handles NAT detection result in IKE INIT */ handleNatDetectionResultInIkeInit(boolean isNatDetected, long localSpi)757 public void handleNatDetectionResultInIkeInit(boolean isNatDetected, long localSpi) 758 throws IkeException { 759 if (!isNatDetected) { 760 mNatStatus = NAT_NOT_DETECTED; 761 return; 762 } 763 764 mNatStatus = NAT_DETECTED; 765 if (mRemoteAddress instanceof Inet6Address) { 766 throw wrapAsIkeException(new UnsupportedOperationException("IPv6 NAT-T not supported")); 767 } 768 769 getIkeLog().d(TAG, "Switching to send to remote port 4500 if it's not already"); 770 771 IkeSocket newSocket = getIkeSocket(true /* isIpv4 */, true /* useEncapPort */); 772 773 try { 774 setupOrUpdateNattKeeaplive(newSocket); 775 } catch (IOException e) { 776 throw wrapAsIkeException(e); 777 } 778 779 if (newSocket != mIkeSocket) { 780 migrateSpiToIkeSocket(localSpi, mIkeSocket, newSocket); 781 mIkeSocket.releaseReference(this); 782 mIkeSocket = newSocket; 783 } 784 } 785 786 /** Handles NAT detection result in the MOBIKE INFORMATIONAL exchange */ handleNatDetectionResultInMobike(boolean isNatDetected)787 public void handleNatDetectionResultInMobike(boolean isNatDetected) throws IkeException { 788 if (!isNatDetected) { 789 mNatStatus = NAT_NOT_DETECTED; 790 return; 791 } 792 793 mNatStatus = NAT_DETECTED; 794 if (mRemoteAddress instanceof Inet6Address) { 795 throw wrapAsIkeException(new UnsupportedOperationException("IPv6 NAT-T not supported")); 796 } 797 798 getIkeLog().d(TAG, "Switching to send to remote port 4500 if it's not already"); 799 getAndSwitchToIkeSocket(true /* isIpv4 */, true /* useEncapPort */); 800 } 801 802 /** 803 * Marks that the server does not support NAT-T 804 * 805 * <p>This is method should only be called at the first time IKE client sends NAT_DETECTION (in 806 * other words the first time IKE client is using IPv4 address since IKE does not support IPv6 807 * NAT-T) 808 */ markSeverNattUnsupported()809 public void markSeverNattUnsupported() { 810 mNatStatus = NAT_TRAVERSAL_UNSUPPORTED; 811 } 812 813 /** 814 * Clears the knowledge of sever's NAT-T support 815 * 816 * <p>This MUST only be called in a test. 817 */ 818 @VisibleForTesting resetSeverNattSupport()819 public void resetSeverNattSupport() { 820 mNatStatus = NAT_TRAVERSAL_SUPPORT_NOT_CHECKED; 821 } 822 823 /** This MUST only be called in a test. */ 824 @VisibleForTesting setNatDetected(boolean isNatDetected)825 public void setNatDetected(boolean isNatDetected) { 826 if (!isNatDetected) { 827 mNatStatus = NAT_NOT_DETECTED; 828 return; 829 } 830 831 mNatStatus = NAT_DETECTED; 832 } 833 834 /** Returns the NAT status */ 835 @NatStatus getNatStatus()836 public int getNatStatus() { 837 return mNatStatus; 838 } 839 840 /** Returns the IkeNattKeepalive */ getIkeNattKeepalive()841 public IkeNattKeepalive getIkeNattKeepalive() { 842 return mIkeNattKeepalive; 843 } 844 845 /** Fire software keepalive */ fireKeepAlive()846 public void fireKeepAlive() { 847 // Software keepalive alarm is fired. Ignore the alarm whe NAT-T keepalive is no 848 // longer needed (e.g. migrating from IPv4 to IPv6) 849 if (mIkeNattKeepalive != null) { 850 mIkeNattKeepalive.onAlarmFired(); 851 } 852 } 853 resolveAndSetAvailableRemoteAddresses()854 private void resolveAndSetAvailableRemoteAddresses() throws IOException { 855 // TODO(b/149954916): Do DNS resolution asynchronously 856 InetAddress[] allRemoteAddresses = null; 857 858 for (int attempts = 0; 859 attempts < MAX_DNS_RESOLUTION_ATTEMPTS 860 && (allRemoteAddresses == null || allRemoteAddresses.length == 0); 861 attempts++) { 862 try { 863 allRemoteAddresses = mNetwork.getAllByName(mRemoteHostname); 864 } catch (UnknownHostException e) { 865 final boolean willRetry = attempts + 1 < MAX_DNS_RESOLUTION_ATTEMPTS; 866 getIkeLog() 867 .d( 868 TAG, 869 "Failed to look up host for attempt " 870 + (attempts + 1) 871 + ": " 872 + mRemoteHostname 873 + " retrying? " 874 + willRetry, 875 e); 876 } 877 } 878 if (allRemoteAddresses == null || allRemoteAddresses.length == 0) { 879 final String errMsg = 880 "DNS resolution for " 881 + mRemoteHostname 882 + " failed after " 883 + MAX_DNS_RESOLUTION_ATTEMPTS 884 + " attempts"; 885 886 throw ShimUtils.getInstance().getDnsFailedException(errMsg); 887 } 888 889 getIkeLog() 890 .d( 891 TAG, 892 "Resolved addresses for peer: " 893 + Arrays.toString(allRemoteAddresses) 894 + " to replace old addresses: v4=" 895 + mRemoteAddressesV4 896 + " v6=" 897 + mRemoteAddressesV6); 898 899 mRemoteAddressesV4.clear(); 900 mRemoteAddressesV6.clear(); 901 for (InetAddress remoteAddress : allRemoteAddresses) { 902 if (remoteAddress instanceof Inet4Address) { 903 mRemoteAddressesV4.add((Inet4Address) remoteAddress); 904 } else { 905 mRemoteAddressesV6.add((Inet6Address) remoteAddress); 906 } 907 } 908 } 909 hasLocalIpV4Address(LinkProperties linkProperties)910 private static boolean hasLocalIpV4Address(LinkProperties linkProperties) { 911 for (LinkAddress linkAddress : linkProperties.getAllLinkAddresses()) { 912 if (linkAddress.getAddress() instanceof Inet4Address) { 913 return true; 914 } 915 } 916 917 return false; 918 } 919 920 /** 921 * Set the remote address for the peer. 922 * 923 * <p>The selection of IP address is as follows: 924 * 925 * <ul> 926 * <li>If the caller passed in an IP address family, use that address family. 927 * <li>Otherwise, always prefer IPv6 over IPv4. 928 * </ul> 929 * 930 * Otherwise, an IPv4 address will be used. 931 */ 932 @VisibleForTesting selectAndSetRemoteAddress(LinkProperties linkProperties)933 public void selectAndSetRemoteAddress(LinkProperties linkProperties) throws IOException { 934 // TODO(b/175348096): Randomly choose from available addresses when the IP family is 935 // decided. 936 final boolean canConnectWithIpv4 = 937 !mRemoteAddressesV4.isEmpty() && hasLocalIpV4Address(linkProperties); 938 final boolean canConnectWithIpv6 = 939 !mRemoteAddressesV6.isEmpty() && linkProperties.hasGlobalIpv6Address(); 940 941 adjustIpVersionPreference(); 942 943 if (isIpVersionRequired(ESP_IP_VERSION_IPV4)) { 944 if (!canConnectWithIpv4) { 945 throw ShimUtils.getInstance().getDnsFailedException( 946 "IPv4 required but no IPv4 address available"); 947 } 948 mRemoteAddress = mRemoteAddressesV4.get(0); 949 } else if (isIpVersionRequired(ESP_IP_VERSION_IPV6)) { 950 if (!canConnectWithIpv6) { 951 throw ShimUtils.getInstance().getDnsFailedException( 952 "IPv6 required but no global IPv6 address available"); 953 } 954 mRemoteAddress = mRemoteAddressesV6.get(0); 955 } else if (isIpV4Preferred(mIkeParams, mNc) && canConnectWithIpv4) { 956 mRemoteAddress = mRemoteAddressesV4.get(0); 957 } else if (canConnectWithIpv6) { 958 mRemoteAddress = mRemoteAddressesV6.get(0); 959 } else if (canConnectWithIpv4) { 960 mRemoteAddress = mRemoteAddressesV4.get(0); 961 } else { 962 // For backwards compatibility, synchronously throw IAE instead of triggering callback. 963 throw new IllegalArgumentException("No valid IPv4 or IPv6 addresses for peer"); 964 } 965 } 966 adjustIpVersionPreference()967 private void adjustIpVersionPreference() { 968 // As ESP isn't supported on v4 and UDP isn't supported on v6, a request for ENCAP_UDP 969 // should force v4 and a request for ENCAP_NONE should force v6 when the family is set 970 // to auto. 971 // TODO : instead of fudging the arguments here, this should actually be taken into 972 // account when figuring out whether to send the NAT detection packet. 973 int adjustedIpVersion = mIpVersion; 974 if (mIpVersion == ESP_IP_VERSION_AUTO) { 975 if (mEncapType == ESP_ENCAP_TYPE_NONE) { 976 adjustedIpVersion = ESP_IP_VERSION_IPV6; 977 } else if (mEncapType == ESP_ENCAP_TYPE_UDP) { 978 adjustedIpVersion = ESP_IP_VERSION_IPV4; 979 } 980 981 if (adjustedIpVersion != mIpVersion) { 982 getIkeLog().i(TAG, "IP version preference is overridden from " 983 + mIpVersion + " to " + adjustedIpVersion); 984 mIpVersion = adjustedIpVersion; 985 } 986 } 987 } 988 isIpVersionRequired(final int ipVersion)989 private boolean isIpVersionRequired(final int ipVersion) { 990 return ipVersion == mIpVersion; 991 } 992 993 @VisibleForTesting isIpV4Preferred(IkeSessionParams ikeParams, NetworkCapabilities nc)994 public boolean isIpV4Preferred(IkeSessionParams ikeParams, NetworkCapabilities nc) { 995 // Note that in production code mIpVersion can't be == ESP_IP_VERSION_IPV4 because the 996 // only caller, selectAndSetRemoteAddress, would never call this method because 997 // isIpVersionRequired(ESP_IP_VERSION_IPV4) would return true. Still, it makes sense in 998 // this method to accept ESP_IP_VERSION_IPV4. 999 return (mIpVersion == ESP_IP_VERSION_AUTO || mIpVersion == ESP_IP_VERSION_IPV4) 1000 && ikeParams.hasIkeOption(IKE_OPTION_AUTOMATIC_ADDRESS_FAMILY_SELECTION) 1001 && nc.hasTransport(TRANSPORT_WIFI); 1002 } 1003 1004 /** 1005 * Enables IkeConnectionController to handle mobility events 1006 * 1007 * <p>This method will enable IkeConnectionController to monitor and handle changes of the 1008 * underlying network and addresses. 1009 */ enableMobility()1010 public void enableMobility() throws IkeException { 1011 mMobilityEnabled = true; 1012 1013 if (mNatStatus != NAT_TRAVERSAL_UNSUPPORTED 1014 && mIkeSocket.getIkeServerPort() != IkeSocket.SERVER_PORT_UDP_ENCAPSULATED) { 1015 getAndSwitchToIkeSocket( 1016 mRemoteAddress instanceof Inet4Address, true /* useEncapPort */); 1017 } 1018 } 1019 1020 /** Creates a IkeSessionConnectionInfo */ buildIkeSessionConnectionInfo()1021 public IkeSessionConnectionInfo buildIkeSessionConnectionInfo() { 1022 return new IkeSessionConnectionInfo(mLocalAddress, mRemoteAddress, mNetwork); 1023 } 1024 1025 /** 1026 * All the calls that are not initiated from the IkeSessionStateMachine MUST be run in this 1027 * method unless there are mechanisms to guarantee these calls will never crash the process. 1028 */ executeOrSendFatalError(Runnable r)1029 private void executeOrSendFatalError(Runnable r) { 1030 ShimUtils.getInstance().executeOrSendFatalError(r, mCallback); 1031 } 1032 1033 // This method is never expected be called due to the capabilities change of the existing 1034 // underlying network. Only explicit user requests, network changes, addresses changes or 1035 // configuration changes (such as the protocol preference) will call into this method. handleUnderlyingNetworkUpdated( Network network, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, boolean skipIfSameNetwork)1036 private void handleUnderlyingNetworkUpdated( 1037 Network network, 1038 LinkProperties linkProperties, 1039 NetworkCapabilities networkCapabilities, 1040 boolean skipIfSameNetwork) { 1041 if (!mMobilityEnabled) { 1042 getIkeLog().d(TAG, "onUnderlyingNetworkUpdated: Unable to handle network update"); 1043 mCallback.onUnderlyingNetworkDied(mNetwork); 1044 1045 return; 1046 } 1047 1048 Network oldNetwork = mNetwork; 1049 InetAddress oldLocalAddress = mLocalAddress; 1050 InetAddress oldRemoteAddress = mRemoteAddress; 1051 1052 mNetwork = network; 1053 mNc = networkCapabilities; 1054 1055 // If the network changes, perform a new DNS lookup to ensure that the correct remote 1056 // address is used. This ensures that DNS returns addresses for the correct address families 1057 // (important if using a v4/v6-only network). This also ensures that DNS64 is handled 1058 // correctly when switching between networks that may have different IPv6 prefixes. 1059 if (!mNetwork.equals(oldNetwork)) { 1060 try { 1061 resolveAndSetAvailableRemoteAddresses(); 1062 } catch (IOException e) { 1063 mCallback.onError(wrapAsIkeException(e)); 1064 return; 1065 } 1066 } 1067 1068 try { 1069 selectAndSetRemoteAddress(linkProperties); 1070 } catch (IOException e) { 1071 mCallback.onError(wrapAsIkeException(e)); 1072 return; 1073 } 1074 1075 boolean isIpv4 = mRemoteAddress instanceof Inet4Address; 1076 1077 // If it is known that the server supports NAT-T, use port 4500. Otherwise, use port 500. 1078 boolean nattSupported = mNatStatus != NAT_TRAVERSAL_UNSUPPORTED; 1079 int serverPort = 1080 nattSupported 1081 ? IkeSocket.SERVER_PORT_UDP_ENCAPSULATED 1082 : IkeSocket.SERVER_PORT_NON_UDP_ENCAPSULATED; 1083 1084 try { 1085 mLocalAddress = 1086 mIkeLocalAddressGenerator.generateLocalAddress( 1087 mNetwork, isIpv4, mRemoteAddress, serverPort); 1088 1089 if (ShimUtils.getInstance().shouldSkipIfSameNetwork(skipIfSameNetwork) 1090 && mNetwork.equals(oldNetwork) 1091 && mLocalAddress.equals(oldLocalAddress) 1092 && mRemoteAddress.equals(oldRemoteAddress)) { 1093 getIkeLog() 1094 .d( 1095 TAG, 1096 "onUnderlyingNetworkUpdated: None of network, local or remote" 1097 + " address has changed, and the update is skippable. No action" 1098 + " needed here."); 1099 return; 1100 } 1101 1102 if (!mNetwork.equals(oldNetwork)) { 1103 boolean useEncapPort = mForcePort4500 || nattSupported; 1104 getAndSwitchToIkeSocket(mLocalAddress instanceof Inet4Address, useEncapPort); 1105 } 1106 1107 for (IkeSaRecord record : mIkeSaRecords) { 1108 record.migrate(mLocalAddress, mRemoteAddress); 1109 } 1110 } catch (IkeException | ErrnoException | IOException e) { 1111 mCallback.onError(wrapAsIkeException(e)); 1112 return; 1113 } 1114 1115 mNetworkCallback.setAddress(mLocalAddress); 1116 1117 mCallback.onUnderlyingNetworkUpdated(); 1118 } 1119 1120 @Override onUnderlyingNetworkUpdated( Network network, LinkProperties linkProperties, NetworkCapabilities networkCapabilities)1121 public void onUnderlyingNetworkUpdated( 1122 Network network, 1123 LinkProperties linkProperties, 1124 NetworkCapabilities networkCapabilities) { 1125 executeOrSendFatalError( 1126 () -> { 1127 handleUnderlyingNetworkUpdated( 1128 network, 1129 linkProperties, 1130 networkCapabilities, 1131 true /* skipIfSameNetwork */); 1132 }); 1133 } 1134 1135 @Override onCapabilitiesUpdated(NetworkCapabilities networkCapabilities)1136 public void onCapabilitiesUpdated(NetworkCapabilities networkCapabilities) { 1137 executeOrSendFatalError( 1138 () -> { 1139 mNc = networkCapabilities; 1140 1141 // No action. There is no known use case to perform mobility or update keepalive 1142 // timer when NetworkCapabilities changes. 1143 }); 1144 } 1145 1146 @Override onUnderlyingNetworkDied()1147 public void onUnderlyingNetworkDied() { 1148 executeOrSendFatalError( 1149 () -> { 1150 mCallback.onUnderlyingNetworkDied(mNetwork); 1151 }); 1152 } 1153 1154 @Override onIkePacketReceived(IkeHeader ikeHeader, byte[] ikePackets)1155 public void onIkePacketReceived(IkeHeader ikeHeader, byte[] ikePackets) { 1156 executeOrSendFatalError( 1157 () -> { 1158 mCallback.onIkePacketReceived(ikeHeader, ikePackets); 1159 }); 1160 } 1161 } 1162