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