1 /* 2 * Copyright 2020 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.google.android.iwlan.epdg; 18 19 import static android.net.ipsec.ike.ike3gpp.Ike3gppData.DATA_TYPE_NOTIFY_BACKOFF_TIMER; 20 import static android.net.ipsec.ike.ike3gpp.Ike3gppData.DATA_TYPE_NOTIFY_N1_MODE_INFORMATION; 21 import static android.net.ipsec.ike.ike3gpp.Ike3gppParams.PDU_SESSION_ID_UNSET; 22 import static android.system.OsConstants.AF_INET; 23 import static android.system.OsConstants.AF_INET6; 24 import static android.telephony.PreciseDataConnectionState.NetworkValidationStatus; 25 26 import static com.google.android.iwlan.proto.MetricsAtom.*; 27 28 import android.content.Context; 29 import android.net.ConnectivityDiagnosticsManager; 30 import android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback; 31 import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; 32 import android.net.ConnectivityManager; 33 import android.net.InetAddresses; 34 import android.net.IpPrefix; 35 import android.net.IpSecManager; 36 import android.net.IpSecTransform; 37 import android.net.LinkAddress; 38 import android.net.LinkProperties; 39 import android.net.Network; 40 import android.net.NetworkCapabilities; 41 import android.net.NetworkRequest; 42 import android.net.eap.EapAkaInfo; 43 import android.net.eap.EapInfo; 44 import android.net.eap.EapSessionConfig; 45 import android.net.ipsec.ike.ChildSaProposal; 46 import android.net.ipsec.ike.ChildSessionCallback; 47 import android.net.ipsec.ike.ChildSessionConfiguration; 48 import android.net.ipsec.ike.ChildSessionParams; 49 import android.net.ipsec.ike.IkeFqdnIdentification; 50 import android.net.ipsec.ike.IkeIdentification; 51 import android.net.ipsec.ike.IkeKeyIdIdentification; 52 import android.net.ipsec.ike.IkeRfc822AddrIdentification; 53 import android.net.ipsec.ike.IkeSaProposal; 54 import android.net.ipsec.ike.IkeSession; 55 import android.net.ipsec.ike.IkeSessionCallback; 56 import android.net.ipsec.ike.IkeSessionConfiguration; 57 import android.net.ipsec.ike.IkeSessionConnectionInfo; 58 import android.net.ipsec.ike.IkeSessionParams; 59 import android.net.ipsec.ike.IkeTrafficSelector; 60 import android.net.ipsec.ike.SaProposal; 61 import android.net.ipsec.ike.TunnelModeChildSessionParams; 62 import android.net.ipsec.ike.exceptions.IkeException; 63 import android.net.ipsec.ike.exceptions.IkeIOException; 64 import android.net.ipsec.ike.exceptions.IkeProtocolException; 65 import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer; 66 import android.net.ipsec.ike.ike3gpp.Ike3gppData; 67 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension; 68 import android.net.ipsec.ike.ike3gpp.Ike3gppN1ModeInformation; 69 import android.net.ipsec.ike.ike3gpp.Ike3gppParams; 70 import android.os.Handler; 71 import android.os.HandlerExecutor; 72 import android.os.HandlerThread; 73 import android.os.Looper; 74 import android.os.Message; 75 import android.support.annotation.IntDef; 76 import android.support.annotation.NonNull; 77 import android.support.annotation.Nullable; 78 import android.telephony.CarrierConfigManager; 79 import android.telephony.PreciseDataConnectionState; 80 import android.telephony.SubscriptionManager; 81 import android.telephony.TelephonyManager; 82 import android.telephony.data.ApnSetting; 83 import android.telephony.data.NetworkSliceInfo; 84 import android.util.Log; 85 86 import com.android.internal.annotations.VisibleForTesting; 87 88 import com.google.android.iwlan.ErrorPolicyManager; 89 import com.google.android.iwlan.IwlanCarrierConfig; 90 import com.google.android.iwlan.IwlanError; 91 import com.google.android.iwlan.IwlanHelper; 92 import com.google.android.iwlan.IwlanStatsLog; 93 import com.google.android.iwlan.TunnelMetricsInterface.OnClosedMetrics; 94 import com.google.android.iwlan.TunnelMetricsInterface.OnOpenedMetrics; 95 import com.google.android.iwlan.exceptions.IwlanSimNotReadyException; 96 import com.google.android.iwlan.flags.FeatureFlags; 97 import com.google.android.iwlan.flags.FeatureFlagsImpl; 98 import com.google.android.iwlan.proto.MetricsAtom; 99 100 import java.io.IOException; 101 import java.io.PrintWriter; 102 import java.net.Inet4Address; 103 import java.net.Inet6Address; 104 import java.net.InetAddress; 105 import java.nio.charset.StandardCharsets; 106 import java.util.ArrayDeque; 107 import java.util.ArrayList; 108 import java.util.Arrays; 109 import java.util.List; 110 import java.util.Map; 111 import java.util.Objects; 112 import java.util.Queue; 113 import java.util.Set; 114 import java.util.concurrent.ConcurrentHashMap; 115 import java.util.concurrent.Executor; 116 import java.util.concurrent.Executors; 117 import java.util.concurrent.TimeUnit; 118 119 public class EpdgTunnelManager { 120 private final FeatureFlags mFeatureFlags; 121 private final Context mContext; 122 private final int mSlotId; 123 private Handler mHandler; 124 private ConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback; 125 126 private static final int EVENT_TUNNEL_BRINGUP_REQUEST = 0; 127 private static final int EVENT_TUNNEL_BRINGDOWN_REQUEST = 1; 128 private static final int EVENT_CHILD_SESSION_OPENED = 2; 129 private static final int EVENT_CHILD_SESSION_CLOSED = 3; 130 private static final int EVENT_IKE_SESSION_CLOSED = 5; 131 private static final int EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE = 6; 132 private static final int EVENT_IPSEC_TRANSFORM_CREATED = 7; 133 private static final int EVENT_IPSEC_TRANSFORM_DELETED = 8; 134 private static final int EVENT_UPDATE_NETWORK = 9; 135 private static final int EVENT_IKE_SESSION_OPENED = 10; 136 private static final int EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED = 11; 137 private static final int EVENT_IKE_3GPP_DATA_RECEIVED = 12; 138 private static final int EVENT_IKE_LIVENESS_STATUS_CHANGED = 13; 139 private static final int EVENT_REQUEST_NETWORK_VALIDATION_CHECK = 14; 140 private static final int IKE_HARD_LIFETIME_SEC_MINIMUM = 300; 141 private static final int IKE_HARD_LIFETIME_SEC_MAXIMUM = 86400; 142 private static final int IKE_SOFT_LIFETIME_SEC_MINIMUM = 120; 143 private static final int CHILD_HARD_LIFETIME_SEC_MINIMUM = 300; 144 private static final int CHILD_HARD_LIFETIME_SEC_MAXIMUM = 14400; 145 private static final int CHILD_SOFT_LIFETIME_SEC_MINIMUM = 120; 146 private static final int LIFETIME_MARGIN_SEC_MINIMUM = (int) TimeUnit.MINUTES.toSeconds(1L); 147 private static final int IKE_RETRANS_TIMEOUT_MS_MIN = 500; 148 149 private static final int IKE_RETRANS_TIMEOUT_MS_MAX = (int) TimeUnit.MINUTES.toMillis(30L); 150 151 private static final int IKE_RETRANS_MAX_ATTEMPTS_MAX = 10; 152 private static final int IKE_DPD_DELAY_SEC_MIN = 20; 153 private static final int IKE_DPD_DELAY_SEC_MAX = 1800; // 30 minutes 154 private static final int NATT_KEEPALIVE_DELAY_SEC_MIN = 10; 155 private static final int NATT_KEEPALIVE_DELAY_SEC_MAX = 120; 156 157 private static final int DEVICE_IMEI_LEN = 15; 158 private static final int DEVICE_IMEISV_SUFFIX_LEN = 2; 159 160 private static final int TRAFFIC_SELECTOR_START_PORT = 0; 161 private static final int TRAFFIC_SELECTOR_END_PORT = 65535; 162 private static final String TRAFFIC_SELECTOR_IPV4_START_ADDR = "0.0.0.0"; 163 private static final String TRAFFIC_SELECTOR_IPV4_END_ADDR = "255.255.255.255"; 164 private static final String TRAFFIC_SELECTOR_IPV6_START_ADDR = "::"; 165 private static final String TRAFFIC_SELECTOR_IPV6_END_ADDR = 166 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; 167 168 private static final int NETWORK_VALIDATION_MIN_INTERVAL_MS = 10000; 169 170 private static long sLastUnderlyingNetworkValidationMs = 0; 171 private static final Object sLastUnderlyingNetworkValidationLock = new Object(); 172 173 // "192.0.2.0" is selected from RFC5737, "IPv4 Address Blocks Reserved for Documentation" 174 private static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0"); 175 176 private static final Map<Integer, EpdgTunnelManager> mTunnelManagerInstances = 177 new ConcurrentHashMap<>(); 178 private final Map<Network, MetricsAtom> mMetricsAtomForNetwork = new ConcurrentHashMap<>(); 179 180 private final Queue<TunnelRequestWrapper> mPendingBringUpRequests = new ArrayDeque<>(); 181 182 private final EpdgInfo mValidEpdgInfo = new EpdgInfo(); 183 184 // The most recently updated system default network as seen by IwlanDataService. 185 @Nullable private Network mDefaultNetwork; 186 // The latest Network provided to the IKE session. Only for debugging purposes. 187 @Nullable private Network mIkeSessionNetwork; 188 189 private int mTransactionId = 0; 190 private boolean mHasConnectedToEpdg; 191 private final IkeSessionCreator mIkeSessionCreator; 192 private final IpSecManager mIpSecManager; 193 private final EpdgSelector mEpdgSelector; 194 195 private final Map<String, TunnelConfig> mApnNameToTunnelConfig = new ConcurrentHashMap<>(); 196 private final Map<String, IpsecTransformData> mApnNameToIpsecTransform = 197 new ConcurrentHashMap<>(); 198 private final Map<String, Integer> mApnNameToCurrentToken = new ConcurrentHashMap<>(); 199 200 private final String TAG; 201 202 @Nullable private byte[] mNextReauthId = null; 203 private long mEpdgServerSelectionDuration = 0; 204 private long mEpdgServerSelectionStartTime = 0; 205 private long mIkeTunnelEstablishmentStartTime = 0; 206 207 private static final Set<Integer> VALID_DH_GROUPS; 208 private static final Set<Integer> VALID_KEY_LENGTHS; 209 private static final Set<Integer> VALID_PRF_ALGOS; 210 private static final Set<Integer> VALID_INTEGRITY_ALGOS; 211 private static final Set<Integer> VALID_ENCRYPTION_ALGOS; 212 private static final Set<Integer> VALID_AEAD_ALGOS; 213 214 private static final String CONFIG_TYPE_DH_GROUP = "dh group"; 215 private static final String CONFIG_TYPE_KEY_LEN = "algorithm key length"; 216 private static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm"; 217 private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm"; 218 private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm"; 219 220 static { 221 VALID_DH_GROUPS = 222 Set.of( 223 SaProposal.DH_GROUP_1024_BIT_MODP, 224 SaProposal.DH_GROUP_1536_BIT_MODP, 225 SaProposal.DH_GROUP_2048_BIT_MODP, 226 SaProposal.DH_GROUP_3072_BIT_MODP, 227 SaProposal.DH_GROUP_4096_BIT_MODP); 228 VALID_KEY_LENGTHS = 229 Set.of( 230 SaProposal.KEY_LEN_AES_128, 231 SaProposal.KEY_LEN_AES_192, 232 SaProposal.KEY_LEN_AES_256); 233 234 VALID_ENCRYPTION_ALGOS = 235 Set.of( 236 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, 237 SaProposal.ENCRYPTION_ALGORITHM_AES_CTR); 238 239 VALID_INTEGRITY_ALGOS = 240 Set.of( 241 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, 242 SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96, 243 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, 244 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, 245 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); 246 247 VALID_AEAD_ALGOS = 248 Set.of( 249 SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8, 250 SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12, 251 SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16); 252 253 VALID_PRF_ALGOS = 254 Set.of( 255 SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1, 256 SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC, 257 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256, 258 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384, 259 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512); 260 } 261 262 @VisibleForTesting protected EpdgMonitor mEpdgMonitor = new EpdgMonitor(); 263 264 public static final int BRINGDOWN_REASON_UNKNOWN = 0; 265 public static final int BRINGDOWN_REASON_DISABLE_N1_MODE = 1; 266 public static final int BRINGDOWN_REASON_ENABLE_N1_MODE = 2; 267 public static final int BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC = 3; 268 public static final int BRINGDOWN_REASON_IN_DEACTIVATING_STATE = 4; 269 public static final int BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP = 5; 270 public static final int BRINGDOWN_REASON_DEACTIVATE_DATA_CALL = 6; 271 272 @IntDef({ 273 BRINGDOWN_REASON_UNKNOWN, 274 BRINGDOWN_REASON_DISABLE_N1_MODE, 275 BRINGDOWN_REASON_ENABLE_N1_MODE, 276 BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC, 277 BRINGDOWN_REASON_IN_DEACTIVATING_STATE, 278 BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP, 279 BRINGDOWN_REASON_DEACTIVATE_DATA_CALL, 280 }) 281 public @interface TunnelBringDownReason {} 282 bringdownReasonToString(@unnelBringDownReason int reason)283 private static String bringdownReasonToString(@TunnelBringDownReason int reason) { 284 return switch (reason) { 285 case BRINGDOWN_REASON_UNKNOWN -> "BRINGDOWN_REASON_UNKNOWN"; 286 case BRINGDOWN_REASON_DISABLE_N1_MODE -> "BRINGDOWN_REASON_DISABLE_N1_MODE"; 287 case BRINGDOWN_REASON_ENABLE_N1_MODE -> "BRINGDOWN_REASON_ENABLE_N1_MODE"; 288 case BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC -> "BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC"; 289 case BRINGDOWN_REASON_IN_DEACTIVATING_STATE -> "BRINGDOWN_REASON_IN_DEACTIVATING_STATE"; 290 case BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP -> 291 "BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP"; 292 case BRINGDOWN_REASON_DEACTIVATE_DATA_CALL -> "BRINGDOWN_REASON_DEACTIVATE_DATA_CALL"; 293 default -> "Unknown(" + reason + ")"; 294 }; 295 } 296 297 private final EpdgSelector.EpdgSelectorCallback mSelectorCallback = 298 new EpdgSelector.EpdgSelectorCallback() { 299 @Override 300 public void onServerListChanged(int transactionId, List<InetAddress> validIPList) { 301 sendSelectionRequestComplete( 302 validIPList, new IwlanError(IwlanError.NO_ERROR), transactionId); 303 } 304 305 @Override 306 public void onError(int transactionId, IwlanError epdgSelectorError) { 307 sendSelectionRequestComplete(null, epdgSelectorError, transactionId); 308 } 309 }; 310 311 @VisibleForTesting 312 class TunnelConfig { 313 @NonNull final TunnelCallback mTunnelCallback; 314 // TODO: Change this to TunnelLinkProperties after removing autovalue 315 private List<InetAddress> mPcscfAddrList; 316 private List<InetAddress> mDnsAddrList; 317 private List<LinkAddress> mInternalAddrList; 318 319 private final InetAddress mSrcIpv6Address; 320 private final int mSrcIpv6AddressPrefixLen; 321 private NetworkSliceInfo mSliceInfo; 322 private boolean mIsBackoffTimeValid = false; 323 private long mBackoffTime; 324 325 @NonNull final IkeSession mIkeSession; 326 327 IwlanError mError; 328 private final IpSecManager.IpSecTunnelInterface mIface; 329 private IkeSessionState mIkeSessionState; 330 private final boolean mIsEmergency; 331 private final InetAddress mEpdgAddress; 332 TunnelConfig( IkeSession ikeSession, TunnelCallback tunnelCallback, IpSecManager.IpSecTunnelInterface iface, InetAddress srcIpv6Addr, int srcIpv6PrefixLength, boolean isEmergency, InetAddress epdgAddress)333 public TunnelConfig( 334 IkeSession ikeSession, 335 TunnelCallback tunnelCallback, 336 IpSecManager.IpSecTunnelInterface iface, 337 InetAddress srcIpv6Addr, 338 int srcIpv6PrefixLength, 339 boolean isEmergency, 340 InetAddress epdgAddress) { 341 mTunnelCallback = tunnelCallback; 342 mIkeSession = ikeSession; 343 mError = new IwlanError(IwlanError.NO_ERROR); 344 mSrcIpv6Address = srcIpv6Addr; 345 mSrcIpv6AddressPrefixLen = srcIpv6PrefixLength; 346 mIface = iface; 347 setIkeSessionState(IkeSessionState.IKE_SESSION_INIT_IN_PROGRESS); 348 mIsEmergency = isEmergency; 349 mEpdgAddress = epdgAddress; 350 } 351 getIkeSessionState()352 public IkeSessionState getIkeSessionState() { 353 return mIkeSessionState; 354 } 355 setIkeSessionState(IkeSessionState ikeSessionState)356 public void setIkeSessionState(IkeSessionState ikeSessionState) { 357 mIkeSessionState = ikeSessionState; 358 } 359 getSliceInfo()360 public NetworkSliceInfo getSliceInfo() { 361 return mSliceInfo; 362 } 363 setSliceInfo(NetworkSliceInfo si)364 public void setSliceInfo(NetworkSliceInfo si) { 365 mSliceInfo = si; 366 } 367 isBackoffTimeValid()368 public boolean isBackoffTimeValid() { 369 return mIsBackoffTimeValid; 370 } 371 getBackoffTime()372 public long getBackoffTime() { 373 return mBackoffTime; 374 } 375 setBackoffTime(long backoffTime)376 public void setBackoffTime(long backoffTime) { 377 mIsBackoffTimeValid = true; 378 mBackoffTime = backoffTime; 379 } 380 381 @NonNull getTunnelCallback()382 TunnelCallback getTunnelCallback() { 383 return mTunnelCallback; 384 } 385 getPcscfAddrList()386 List<InetAddress> getPcscfAddrList() { 387 return mPcscfAddrList; 388 } 389 setPcscfAddrList(List<InetAddress> pcscfAddrList)390 void setPcscfAddrList(List<InetAddress> pcscfAddrList) { 391 mPcscfAddrList = pcscfAddrList; 392 } 393 getDnsAddrList()394 public List<InetAddress> getDnsAddrList() { 395 return mDnsAddrList; 396 } 397 setDnsAddrList(List<InetAddress> dnsAddrList)398 public void setDnsAddrList(List<InetAddress> dnsAddrList) { 399 this.mDnsAddrList = dnsAddrList; 400 } 401 getInternalAddrList()402 public List<LinkAddress> getInternalAddrList() { 403 return mInternalAddrList; 404 } 405 isPrefixSameAsSrcIP(LinkAddress laddr)406 boolean isPrefixSameAsSrcIP(LinkAddress laddr) { 407 if (laddr.isIpv6() && (laddr.getPrefixLength() == mSrcIpv6AddressPrefixLen)) { 408 IpPrefix assignedPrefix = new IpPrefix(laddr.getAddress(), laddr.getPrefixLength()); 409 IpPrefix srcPrefix = new IpPrefix(mSrcIpv6Address, mSrcIpv6AddressPrefixLen); 410 return assignedPrefix.equals(srcPrefix); 411 } 412 return false; 413 } 414 setInternalAddrList(List<LinkAddress> internalAddrList)415 public void setInternalAddrList(List<LinkAddress> internalAddrList) { 416 mInternalAddrList = new ArrayList<LinkAddress>(internalAddrList); 417 if (getSrcIpv6Address() != null) { 418 // check if we can reuse src ipv6 address (i.e. if prefix is same) 419 for (LinkAddress assignedAddr : internalAddrList) { 420 if (isPrefixSameAsSrcIP(assignedAddr)) { 421 // the assigned IPv6 address is same as pre-Handover IPv6 422 // addr. Just reuse the pre-Handover Address so the IID is 423 // preserved 424 mInternalAddrList.remove(assignedAddr); 425 426 // add original address 427 mInternalAddrList.add( 428 new LinkAddress(mSrcIpv6Address, mSrcIpv6AddressPrefixLen)); 429 430 Log.d( 431 TAG, 432 "Network assigned IP replaced OLD:" 433 + internalAddrList 434 + " NEW:" 435 + mInternalAddrList); 436 break; 437 } 438 } 439 } 440 } 441 442 @NonNull getIkeSession()443 public IkeSession getIkeSession() { 444 return mIkeSession; 445 } 446 getError()447 public IwlanError getError() { 448 return mError; 449 } 450 setError(IwlanError error)451 public void setError(IwlanError error) { 452 this.mError = error; 453 } 454 getIface()455 public IpSecManager.IpSecTunnelInterface getIface() { 456 return mIface; 457 } 458 getSrcIpv6Address()459 public InetAddress getSrcIpv6Address() { 460 return mSrcIpv6Address; 461 } 462 isEmergency()463 public boolean isEmergency() { 464 return mIsEmergency; 465 } 466 getEpdgAddress()467 public InetAddress getEpdgAddress() { 468 return mEpdgAddress; 469 } 470 hasTunnelOpened()471 public boolean hasTunnelOpened() { 472 return mInternalAddrList != null 473 && !mInternalAddrList.isEmpty() /* The child session is opened */ 474 && mIface != null; /* The tunnel interface is bring up */ 475 } 476 477 @Override toString()478 public String toString() { 479 StringBuilder sb = new StringBuilder(); 480 sb.append("TunnelConfig { "); 481 482 if (mSliceInfo != null) { 483 sb.append("mSliceInfo: ").append(mSliceInfo).append(", "); 484 } 485 486 if (mIsBackoffTimeValid) { 487 sb.append("mBackoffTime: ").append(mBackoffTime).append(", "); 488 } 489 sb.append(" }"); 490 return sb.toString(); 491 } 492 } 493 494 @VisibleForTesting 495 class TmIkeSessionCallback implements IkeSessionCallback { 496 497 private final String mApnName; 498 private final int mToken; 499 TmIkeSessionCallback(String apnName, int token)500 TmIkeSessionCallback(String apnName, int token) { 501 this.mApnName = apnName; 502 this.mToken = token; 503 } 504 505 @Override onOpened(IkeSessionConfiguration sessionConfiguration)506 public void onOpened(IkeSessionConfiguration sessionConfiguration) { 507 if (mHandler == null) { 508 Log.d(TAG, "Handler unavailable"); 509 return; 510 } 511 Log.d(TAG, "Ike session opened for apn: " + mApnName + " with token: " + mToken); 512 mHandler.obtainMessage( 513 EVENT_IKE_SESSION_OPENED, 514 new IkeSessionOpenedData(mApnName, mToken, sessionConfiguration)) 515 .sendToTarget(); 516 } 517 518 @Override onClosed()519 public void onClosed() { 520 if (mHandler == null) { 521 Log.d(TAG, "Handler unavailable"); 522 return; 523 } 524 Log.d(TAG, "Ike session closed for apn: " + mApnName + " with token: " + mToken); 525 mHandler.obtainMessage( 526 EVENT_IKE_SESSION_CLOSED, 527 new SessionClosedData(mApnName, mToken, null /* ikeException */)) 528 .sendToTarget(); 529 } 530 531 @Override onClosedWithException(IkeException exception)532 public void onClosedWithException(IkeException exception) { 533 mNextReauthId = null; 534 onSessionClosedWithException(exception, mApnName, mToken, EVENT_IKE_SESSION_CLOSED); 535 } 536 537 @Override onError(IkeProtocolException exception)538 public void onError(IkeProtocolException exception) { 539 Log.d(TAG, "Ike session onError for apn: " + mApnName + " with token: " + mToken); 540 541 mNextReauthId = null; 542 543 Log.d( 544 TAG, 545 "ErrorType:" 546 + exception.getErrorType() 547 + " ErrorData:" 548 + exception.getMessage()); 549 } 550 551 @Override onIkeSessionConnectionInfoChanged( IkeSessionConnectionInfo ikeSessionConnectionInfo)552 public void onIkeSessionConnectionInfoChanged( 553 IkeSessionConnectionInfo ikeSessionConnectionInfo) { 554 if (mHandler == null) { 555 Log.d(TAG, "Handler unavailable"); 556 return; 557 } 558 Network network = ikeSessionConnectionInfo.getNetwork(); 559 Log.d( 560 TAG, 561 "Ike session connection info changed for apn: " 562 + mApnName 563 + " with token: " 564 + mToken 565 + " Network: " 566 + network); 567 mHandler.obtainMessage( 568 EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED, 569 new IkeSessionConnectionInfoData( 570 mApnName, mToken, ikeSessionConnectionInfo)) 571 .sendToTarget(); 572 } 573 574 @Override onLivenessStatusChanged(int status)575 public void onLivenessStatusChanged(int status) { 576 if (mHandler == null) { 577 Log.d(TAG, "Handler unavailable"); 578 return; 579 } 580 Log.d( 581 TAG, 582 "Ike liveness status changed for apn: " + mApnName + " with status: " + status); 583 @NetworkValidationStatus int validationStatus; 584 switch (status) { 585 case IkeSessionCallback.LIVENESS_STATUS_ON_DEMAND_STARTED: 586 case IkeSessionCallback.LIVENESS_STATUS_BACKGROUND_STARTED: 587 case IkeSessionCallback.LIVENESS_STATUS_ON_DEMAND_ONGOING: 588 case IkeSessionCallback.LIVENESS_STATUS_BACKGROUND_ONGOING: 589 validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS; 590 break; 591 case IkeSessionCallback.LIVENESS_STATUS_SUCCESS: 592 validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS; 593 break; 594 case IkeSessionCallback.LIVENESS_STATUS_FAILURE: 595 validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE; 596 break; 597 default: 598 validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS; 599 } 600 601 mHandler.obtainMessage( 602 EVENT_IKE_LIVENESS_STATUS_CHANGED, 603 new IkeSessionValidationStatusData(mApnName, mToken, validationStatus)) 604 .sendToTarget(); 605 } 606 } 607 608 @VisibleForTesting 609 class TmIke3gppCallback implements Ike3gppExtension.Ike3gppDataListener { 610 private final String mApnName; 611 private final int mToken; 612 TmIke3gppCallback(String apnName, int token)613 private TmIke3gppCallback(String apnName, int token) { 614 mApnName = apnName; 615 mToken = token; 616 } 617 618 @Override onIke3gppDataReceived(List<Ike3gppData> payloads)619 public void onIke3gppDataReceived(List<Ike3gppData> payloads) { 620 if (mHandler == null) { 621 Log.d(TAG, "Handler unavailable"); 622 return; 623 } 624 mHandler.obtainMessage( 625 EVENT_IKE_3GPP_DATA_RECEIVED, 626 new Ike3gppDataReceived(mApnName, mToken, payloads)) 627 .sendToTarget(); 628 } 629 } 630 631 @VisibleForTesting 632 class TmChildSessionCallback implements ChildSessionCallback { 633 634 private final String mApnName; 635 private final int mToken; 636 TmChildSessionCallback(String apnName, int token)637 TmChildSessionCallback(String apnName, int token) { 638 this.mApnName = apnName; 639 this.mToken = token; 640 } 641 642 @Override onOpened(ChildSessionConfiguration sessionConfiguration)643 public void onOpened(ChildSessionConfiguration sessionConfiguration) { 644 if (mHandler == null) { 645 Log.d(TAG, "Handler unavailable"); 646 return; 647 } 648 Log.d(TAG, "onOpened child session for apn: " + mApnName + " with token: " + mToken); 649 mHandler.obtainMessage( 650 EVENT_CHILD_SESSION_OPENED, 651 new TunnelOpenedData( 652 mApnName, 653 mToken, 654 sessionConfiguration.getInternalDnsServers(), 655 sessionConfiguration.getInternalAddresses())) 656 .sendToTarget(); 657 } 658 659 @Override onClosed()660 public void onClosed() { 661 if (mHandler == null) { 662 Log.d(TAG, "Handler unavailable"); 663 return; 664 } 665 Log.d(TAG, "onClosed child session for apn: " + mApnName + " with token: " + mToken); 666 mHandler.obtainMessage( 667 EVENT_CHILD_SESSION_CLOSED, 668 new SessionClosedData(mApnName, mToken, null /* ikeException */)) 669 .sendToTarget(); 670 } 671 672 @Override onClosedWithException(IkeException exception)673 public void onClosedWithException(IkeException exception) { 674 onSessionClosedWithException(exception, mApnName, mToken, EVENT_CHILD_SESSION_CLOSED); 675 } 676 677 @Override onIpSecTransformsMigrated( IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform)678 public void onIpSecTransformsMigrated( 679 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) { 680 if (mHandler == null) { 681 Log.d(TAG, "Handler unavailable"); 682 return; 683 } 684 // migration is similar to addition 685 Log.d(TAG, "Transforms migrated for apn: " + mApnName + " with token: " + mToken); 686 mHandler.obtainMessage( 687 EVENT_IPSEC_TRANSFORM_CREATED, 688 new IpsecTransformData( 689 inIpSecTransform, IpSecManager.DIRECTION_IN, mApnName, mToken)) 690 .sendToTarget(); 691 mHandler.obtainMessage( 692 EVENT_IPSEC_TRANSFORM_CREATED, 693 new IpsecTransformData( 694 outIpSecTransform, 695 IpSecManager.DIRECTION_OUT, 696 mApnName, 697 mToken)) 698 .sendToTarget(); 699 } 700 701 @Override onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction)702 public void onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction) { 703 if (mHandler == null) { 704 Log.d(TAG, "Handler unavailable"); 705 return; 706 } 707 Log.d( 708 TAG, 709 "Transform created, direction: " 710 + direction 711 + ", apn: " 712 + mApnName 713 + ", token: " 714 + mToken); 715 mHandler.obtainMessage( 716 EVENT_IPSEC_TRANSFORM_CREATED, 717 new IpsecTransformData(ipSecTransform, direction, mApnName, mToken)) 718 .sendToTarget(); 719 } 720 721 @Override onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction)722 public void onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction) { 723 if (mHandler == null) { 724 Log.d(TAG, "Handler unavailable"); 725 return; 726 } 727 Log.d( 728 TAG, 729 "Transform deleted, direction: " 730 + direction 731 + ", apn: " 732 + mApnName 733 + ", token: " 734 + mToken); 735 mHandler.obtainMessage( 736 EVENT_IPSEC_TRANSFORM_DELETED, 737 new IpsecTransformData(ipSecTransform, direction, mApnName, mToken)) 738 .sendToTarget(); 739 } 740 } 741 EpdgTunnelManager(Context context, int slotId, FeatureFlags featureFlags)742 private EpdgTunnelManager(Context context, int slotId, FeatureFlags featureFlags) { 743 this( 744 context, 745 slotId, 746 featureFlags, 747 new IkeSessionCreator(), 748 new EpdgSelector(context, slotId, featureFlags)); 749 } 750 751 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) EpdgTunnelManager( Context context, int slotIndex, FeatureFlags featureFlags, IkeSessionCreator ikeSessionCreator, EpdgSelector epdgSelector)752 EpdgTunnelManager( 753 Context context, 754 int slotIndex, 755 FeatureFlags featureFlags, 756 IkeSessionCreator ikeSessionCreator, 757 EpdgSelector epdgSelector) { 758 mContext = context; 759 mSlotId = slotIndex; 760 mFeatureFlags = featureFlags; 761 mIkeSessionCreator = ikeSessionCreator; 762 mIpSecManager = mContext.getSystemService(IpSecManager.class); 763 // Adding this here is necessary because we need to initialize EpdgSelector at the beginning 764 // to ensure no broadcasts are missed. 765 mEpdgSelector = epdgSelector; 766 TAG = EpdgTunnelManager.class.getSimpleName() + "[" + mSlotId + "]"; 767 initHandler(); 768 registerConnectivityDiagnosticsCallback(); 769 } 770 registerConnectivityDiagnosticsCallback()771 private void registerConnectivityDiagnosticsCallback() { 772 ConnectivityDiagnosticsManager connectivityDiagnosticsManager = 773 Objects.requireNonNull(mContext) 774 .getSystemService(ConnectivityDiagnosticsManager.class); 775 NetworkRequest networkRequest = 776 new NetworkRequest.Builder() 777 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 778 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 779 .build(); 780 mConnectivityDiagnosticsCallback = 781 new ConnectivityDiagnosticsCallback() { 782 @Override 783 public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) { 784 Network network = report.getNetwork(); 785 int mNetworkValidationResult = 786 report.getAdditionalInfo() 787 .getInt(ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT); 788 if (!mMetricsAtomForNetwork.containsKey(network)) { 789 return; 790 } 791 reportValidationMetricsAtom( 792 network, 793 getMetricsValidationResult(mNetworkValidationResult), 794 /* validationTriggered */ true); 795 } 796 }; 797 connectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback( 798 networkRequest, new HandlerExecutor(mHandler), mConnectivityDiagnosticsCallback); 799 } 800 reportValidationMetricsAtom( @onNull Network network, int validationResult, boolean validationTriggered)801 private void reportValidationMetricsAtom( 802 @NonNull Network network, int validationResult, boolean validationTriggered) { 803 if (!mMetricsAtomForNetwork.containsKey(network)) { 804 return; 805 } 806 MetricsAtom metricsAtom = mMetricsAtomForNetwork.get(network); 807 metricsAtom.setValidationResult(validationResult); 808 metricsAtom.setValidationTriggered(validationTriggered); 809 metricsAtom.setValidationDurationMills( 810 validationTriggered 811 ? (int) 812 (IwlanHelper.elapsedRealtime() 813 - metricsAtom.getValidationStartTimeMills()) 814 : 0); 815 Log.d( 816 TAG, 817 "reportValidationMetricsAtom: reason=" 818 + metricsAtom.getTriggerReason() 819 + " validationResult=" 820 + metricsAtom.getValidationResult() 821 + " transportType=" 822 + metricsAtom.getValidationTransportType() 823 + " duration=" 824 + metricsAtom.getValidationDurationMills() 825 + " validationTriggered=" 826 + metricsAtom.getValidationTriggered()); 827 metricsAtom.sendMetricsData(); 828 mMetricsAtomForNetwork.remove(network); 829 } 830 831 @VisibleForTesting getValidationMetricsAtom(Network network)832 MetricsAtom getValidationMetricsAtom(Network network) { 833 return mMetricsAtomForNetwork.get(network); 834 } 835 unregisterConnectivityDiagnosticsCallback()836 private void unregisterConnectivityDiagnosticsCallback() { 837 ConnectivityDiagnosticsManager connectivityDiagnosticsManager = 838 Objects.requireNonNull(mContext) 839 .getSystemService(ConnectivityDiagnosticsManager.class); 840 if (connectivityDiagnosticsManager != null) { 841 connectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback( 842 mConnectivityDiagnosticsCallback); 843 } 844 } 845 846 @VisibleForTesting initHandler()847 void initHandler() { 848 mHandler = new TmHandler(getLooper()); 849 } 850 851 @VisibleForTesting getLooper()852 Looper getLooper() { 853 HandlerThread handlerThread = new HandlerThread("EpdgTunnelManagerThread"); 854 handlerThread.start(); 855 return handlerThread.getLooper(); 856 } 857 858 /** 859 * Gets a EpdgTunnelManager instance. 860 * 861 * @param context the context at which EpdgTunnelManager instance to be created 862 * @param slotId the slot index at which EpdgTunnelManager instance to be created 863 * @return EpdgTunnelManager instance for the specified slot id 864 */ getInstance(@onNull Context context, int slotId)865 public static EpdgTunnelManager getInstance(@NonNull Context context, int slotId) { 866 return mTunnelManagerInstances.computeIfAbsent( 867 slotId, k -> new EpdgTunnelManager(context, slotId, new FeatureFlagsImpl())); 868 } 869 870 @VisibleForTesting resetAllInstances()871 public static void resetAllInstances() { 872 mTunnelManagerInstances.clear(); 873 sLastUnderlyingNetworkValidationMs = 0; 874 } 875 reset()876 private void reset() { 877 if (mHandler != null) { 878 mHandler.getLooper().quit(); 879 mHandler = null; 880 } 881 882 mApnNameToTunnelConfig.forEach( 883 (apn, config) -> { 884 config.getIkeSession().kill(); 885 IpSecManager.IpSecTunnelInterface iface = config.getIface(); 886 if (iface != null) { 887 iface.close(); 888 } 889 IpsecTransformData transformData = mApnNameToIpsecTransform.get(apn); 890 if (transformData != null) { 891 transformData.getTransform().close(); 892 mApnNameToIpsecTransform.remove(apn); 893 } 894 }); 895 896 mApnNameToTunnelConfig.clear(); 897 } 898 deinit()899 public static void deinit() { 900 mTunnelManagerInstances.values().forEach(EpdgTunnelManager::reset); 901 } 902 903 public interface TunnelCallback { 904 /** 905 * Called when the tunnel is opened. 906 * 907 * @param apnName apn for which the tunnel was opened 908 * @param linkProperties link properties of the tunnel 909 * @param onOpenedMetrics metrics for the tunnel 910 */ onOpened( @onNull String apnName, @NonNull TunnelLinkProperties linkProperties, OnOpenedMetrics onOpenedMetrics)911 void onOpened( 912 @NonNull String apnName, 913 @NonNull TunnelLinkProperties linkProperties, 914 OnOpenedMetrics onOpenedMetrics); 915 916 /** 917 * Called when the tunnel is closed OR if bring up fails 918 * 919 * @param apnName apn for which the tunnel was closed 920 * @param error IwlanError carrying details of the error 921 * @param onClosedMetrics metrics for the tunnel 922 */ onClosed( @onNull String apnName, @NonNull IwlanError error, OnClosedMetrics onClosedMetrics)923 void onClosed( 924 @NonNull String apnName, 925 @NonNull IwlanError error, 926 OnClosedMetrics onClosedMetrics); 927 928 /** 929 * Called when updates upon network validation status change. 930 * 931 * @param apnName APN affected. 932 * @param status The updated validation status of the network. 933 */ onNetworkValidationStatusChanged( @onNull String apnName, @NetworkValidationStatus int status)934 void onNetworkValidationStatusChanged( 935 @NonNull String apnName, @NetworkValidationStatus int status); 936 } 937 938 /** 939 * Close tunnel for an apn. Confirmation of closing will be delivered in TunnelCallback that was 940 * provided in {@link #bringUpTunnel}. If no tunnel was available, callback will be delivered 941 * using client-provided provided tunnelCallback and iwlanTunnelMetrics 942 * 943 * @param apnName APN name 944 * @param forceClose if {@code true}, triggers a local cleanup of the tunnel; if {@code false}, 945 * performs a normal closure procedure 946 * @param tunnelCallback The tunnelCallback for tunnel to be closed 947 * @param reason The reason for tunnel to be closed 948 */ closeTunnel( @onNull String apnName, boolean forceClose, @NonNull TunnelCallback tunnelCallback, @TunnelBringDownReason int reason)949 public void closeTunnel( 950 @NonNull String apnName, 951 boolean forceClose, 952 @NonNull TunnelCallback tunnelCallback, 953 @TunnelBringDownReason int reason) { 954 mHandler.obtainMessage( 955 EVENT_TUNNEL_BRINGDOWN_REQUEST, 956 new TunnelBringdownRequest(apnName, forceClose, tunnelCallback, reason)) 957 .sendToTarget(); 958 } 959 960 /** 961 * Update the local Network. This will trigger a revaluation for every tunnel for which tunnel 962 * manager has state. 963 * 964 * @param network the network to be updated 965 * @param linkProperties the linkProperties to be updated 966 */ updateNetwork(Network network, LinkProperties linkProperties)967 public void updateNetwork(Network network, LinkProperties linkProperties) { 968 UpdateNetworkWrapper updateNetworkWrapper = 969 new UpdateNetworkWrapper(network, linkProperties); 970 mHandler.obtainMessage(EVENT_UPDATE_NETWORK, updateNetworkWrapper).sendToTarget(); 971 } 972 973 /** 974 * Bring up epdg tunnel. Only one bring up request per apn is expected. All active tunnel 975 * requests and tunnels are expected to be on the same network. 976 * 977 * @param setupRequest {@link TunnelSetupRequest} tunnel configurations 978 * @param tunnelCallback {@link TunnelCallback} interface to notify clients about the tunnel 979 * state 980 * @return true if params are valid and no existing tunnel. False otherwise. 981 */ bringUpTunnel( @onNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback)982 public boolean bringUpTunnel( 983 @NonNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback) { 984 String apnName = setupRequest.apnName(); 985 986 if (getTunnelSetupRequestApnName(setupRequest) == null) { 987 Log.e(TAG, "APN is null."); 988 return false; 989 } 990 991 if (isTunnelConfigContainExistApn(apnName)) { 992 Log.e(TAG, "Tunnel exists for apn:" + apnName); 993 return false; 994 } 995 996 if (!isValidApnProtocol(setupRequest.apnIpProtocol())) { 997 Log.e(TAG, "Invalid protocol for APN"); 998 return false; 999 } 1000 1001 int pduSessionId = setupRequest.pduSessionId(); 1002 if (pduSessionId < 0 || pduSessionId > 15) { 1003 Log.e(TAG, "Invalid pduSessionId: " + pduSessionId); 1004 return false; 1005 } 1006 1007 TunnelRequestWrapper tunnelRequestWrapper = 1008 new TunnelRequestWrapper(setupRequest, tunnelCallback); 1009 1010 mHandler.obtainMessage(EVENT_TUNNEL_BRINGUP_REQUEST, tunnelRequestWrapper).sendToTarget(); 1011 1012 return true; 1013 } 1014 tryBuildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress)1015 private IkeSessionParams tryBuildIkeSessionParams( 1016 TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress) { 1017 try { 1018 return buildIkeSessionParams(setupRequest, apnName, token, epdgAddress); 1019 } catch (IwlanSimNotReadyException e) { 1020 return null; 1021 } 1022 } 1023 tryCreateIpSecTunnelInterface()1024 private IpSecManager.IpSecTunnelInterface tryCreateIpSecTunnelInterface() { 1025 try { 1026 return mIpSecManager.createIpSecTunnelInterface( 1027 DUMMY_ADDR /* unused */, DUMMY_ADDR /* unused */, mDefaultNetwork); 1028 } catch (IpSecManager.ResourceUnavailableException | IOException e) { 1029 Log.e(TAG, "Failed to create tunnel interface. " + e); 1030 return null; 1031 } 1032 } 1033 onBringUpTunnel( TunnelRequestWrapper tunnelRequestWrapper, InetAddress epdgAddress)1034 private void onBringUpTunnel( 1035 TunnelRequestWrapper tunnelRequestWrapper, InetAddress epdgAddress) { 1036 TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest(); 1037 TunnelCallback tunnelCallback = tunnelRequestWrapper.getTunnelCallback(); 1038 String apnName = setupRequest.apnName(); 1039 IkeSessionParams ikeSessionParams; 1040 IpSecManager.IpSecTunnelInterface iface; 1041 1042 Log.d( 1043 TAG, 1044 "Bringing up tunnel for apn: " 1045 + apnName 1046 + " ePDG: " 1047 + epdgAddress.getHostAddress()); 1048 1049 final int token = incrementAndGetCurrentTokenForApn(apnName); 1050 1051 ikeSessionParams = tryBuildIkeSessionParams(setupRequest, apnName, token, epdgAddress); 1052 if (Objects.isNull(ikeSessionParams)) { 1053 IwlanError iwlanError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION); 1054 reportIwlanError(apnName, iwlanError); 1055 tunnelCallback.onClosed( 1056 apnName, iwlanError, new OnClosedMetrics.Builder().setApnName(apnName).build()); 1057 return; 1058 } 1059 1060 iface = tryCreateIpSecTunnelInterface(); 1061 if (Objects.isNull(iface)) { 1062 IwlanError iwlanError = new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED); 1063 reportIwlanError(apnName, iwlanError); 1064 tunnelCallback.onClosed( 1065 apnName, iwlanError, new OnClosedMetrics.Builder().setApnName(apnName).build()); 1066 return; 1067 } 1068 1069 mIkeTunnelEstablishmentStartTime = System.currentTimeMillis(); 1070 IkeSession ikeSession = 1071 getIkeSessionCreator() 1072 .createIkeSession( 1073 mContext, 1074 ikeSessionParams, 1075 buildChildSessionParams(setupRequest), 1076 Executors.newSingleThreadExecutor(), 1077 getTmIkeSessionCallback(apnName, token), 1078 new TmChildSessionCallback(apnName, token)); 1079 1080 boolean isSrcIpv6Present = setupRequest.srcIpv6Address().isPresent(); 1081 putApnNameToTunnelConfig( 1082 apnName, 1083 ikeSession, 1084 tunnelCallback, 1085 iface, 1086 isSrcIpv6Present ? setupRequest.srcIpv6Address().get() : null, 1087 setupRequest.srcIpv6AddressPrefixLength(), 1088 setupRequest.isEmergency(), 1089 epdgAddress); 1090 } 1091 1092 /** 1093 * Proxy to allow testing 1094 * 1095 * @hide 1096 */ 1097 @VisibleForTesting 1098 static class IkeSessionCreator { 1099 /** Creates a IKE session */ createIkeSession( @onNull Context context, @NonNull IkeSessionParams ikeSessionParams, @NonNull ChildSessionParams firstChildSessionParams, @NonNull Executor userCbExecutor, @NonNull IkeSessionCallback ikeSessionCallback, @NonNull ChildSessionCallback firstChildSessionCallback)1100 public IkeSession createIkeSession( 1101 @NonNull Context context, 1102 @NonNull IkeSessionParams ikeSessionParams, 1103 @NonNull ChildSessionParams firstChildSessionParams, 1104 @NonNull Executor userCbExecutor, 1105 @NonNull IkeSessionCallback ikeSessionCallback, 1106 @NonNull ChildSessionCallback firstChildSessionCallback) { 1107 return new IkeSession( 1108 context, 1109 ikeSessionParams, 1110 firstChildSessionParams, 1111 userCbExecutor, 1112 ikeSessionCallback, 1113 firstChildSessionCallback); 1114 } 1115 } 1116 buildChildSessionParams(TunnelSetupRequest setupRequest)1117 private ChildSessionParams buildChildSessionParams(TunnelSetupRequest setupRequest) { 1118 int proto = setupRequest.apnIpProtocol(); 1119 int hardTimeSeconds = 1120 IwlanCarrierConfig.getConfigInt( 1121 mContext, 1122 mSlotId, 1123 CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT); 1124 int softTimeSeconds = 1125 IwlanCarrierConfig.getConfigInt( 1126 mContext, 1127 mSlotId, 1128 CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT); 1129 if (!isValidChildSessionLifetime(hardTimeSeconds, softTimeSeconds)) { 1130 if (hardTimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM 1131 && softTimeSeconds > CHILD_SOFT_LIFETIME_SEC_MINIMUM) { 1132 hardTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM; 1133 softTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM; 1134 } else { 1135 hardTimeSeconds = 1136 IwlanCarrierConfig.getDefaultConfigInt( 1137 CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT); 1138 softTimeSeconds = 1139 IwlanCarrierConfig.getDefaultConfigInt( 1140 CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT); 1141 } 1142 Log.d( 1143 TAG, 1144 "Invalid child session lifetime values, set hard: " 1145 + hardTimeSeconds 1146 + ", soft: " 1147 + softTimeSeconds); 1148 } 1149 1150 TunnelModeChildSessionParams.Builder childSessionParamsBuilder = 1151 new TunnelModeChildSessionParams.Builder() 1152 .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds); 1153 1154 // Else block and it's related functionality can be removed once 1155 // multipleSaProposals, highSecureTransformsPrioritized and aeadAlgosEnabled feature flags 1156 // related functionality becomes stable and gets instruction to remove feature flags. 1157 if (mFeatureFlags.multipleSaProposals() 1158 || mFeatureFlags.highSecureTransformsPrioritized()) { 1159 EpdgChildSaProposal epdgChildSaProposal = createEpdgChildSaProposal(); 1160 1161 if (IwlanCarrierConfig.getConfigBoolean( 1162 mContext, 1163 mSlotId, 1164 CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) { 1165 epdgChildSaProposal.enableAddChildSessionRekeyKePayload(); 1166 } 1167 // Adds single SA proposal, priority is for AEAD if configured else non-AEAD proposal. 1168 if (isChildSessionAeadAlgosAvailable()) { 1169 childSessionParamsBuilder.addChildSaProposal( 1170 epdgChildSaProposal.buildProposedChildSaAeadProposal()); 1171 } else { 1172 childSessionParamsBuilder.addChildSaProposal( 1173 epdgChildSaProposal.buildProposedChildSaProposal()); 1174 } 1175 // Adds multiple proposals. If AEAD proposal already added then adds 1176 // configured non-AEAD proposal followed by supported AEAD and non-AEAD proposals. 1177 if (IwlanCarrierConfig.getConfigBoolean( 1178 mContext, 1179 mSlotId, 1180 CarrierConfigManager.Iwlan 1181 .KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) { 1182 if (isChildSessionAeadAlgosAvailable() && isChildSessionNonAeadAlgosAvailable()) { 1183 childSessionParamsBuilder.addChildSaProposal( 1184 epdgChildSaProposal.buildProposedChildSaProposal()); 1185 } 1186 childSessionParamsBuilder.addChildSaProposal( 1187 epdgChildSaProposal.buildSupportedChildSaAeadProposal()); 1188 childSessionParamsBuilder.addChildSaProposal( 1189 epdgChildSaProposal.buildSupportedChildSaProposal()); 1190 } 1191 } else { 1192 if (isChildSessionAeadAlgosAvailable()) { 1193 childSessionParamsBuilder.addChildSaProposal(buildAeadChildSaProposal()); 1194 } else { 1195 childSessionParamsBuilder.addChildSaProposal(buildChildSaProposal()); 1196 } 1197 } 1198 1199 boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent(); 1200 boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent(); 1201 if (handoverIPv4Present || handoverIPv6Present) { 1202 if (handoverIPv4Present) { 1203 childSessionParamsBuilder.addInternalAddressRequest( 1204 (Inet4Address) setupRequest.srcIpv4Address().get()); 1205 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET); 1206 childSessionParamsBuilder.addInboundTrafficSelectors( 1207 getDefaultTrafficSelectorIpv4()); 1208 childSessionParamsBuilder.addOutboundTrafficSelectors( 1209 getDefaultTrafficSelectorIpv4()); 1210 } 1211 if (handoverIPv6Present) { 1212 childSessionParamsBuilder.addInternalAddressRequest( 1213 (Inet6Address) setupRequest.srcIpv6Address().get(), 1214 setupRequest.srcIpv6AddressPrefixLength()); 1215 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6); 1216 childSessionParamsBuilder.addInboundTrafficSelectors( 1217 getDefaultTrafficSelectorIpv6()); 1218 childSessionParamsBuilder.addOutboundTrafficSelectors( 1219 getDefaultTrafficSelectorIpv6()); 1220 } 1221 } else { 1222 // non-handover case 1223 if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) { 1224 childSessionParamsBuilder.addInternalAddressRequest(AF_INET); 1225 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET); 1226 childSessionParamsBuilder.addInboundTrafficSelectors( 1227 getDefaultTrafficSelectorIpv4()); 1228 childSessionParamsBuilder.addOutboundTrafficSelectors( 1229 getDefaultTrafficSelectorIpv4()); 1230 } 1231 if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) { 1232 childSessionParamsBuilder.addInternalAddressRequest(AF_INET6); 1233 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6); 1234 childSessionParamsBuilder.addInboundTrafficSelectors( 1235 getDefaultTrafficSelectorIpv6()); 1236 childSessionParamsBuilder.addOutboundTrafficSelectors( 1237 getDefaultTrafficSelectorIpv6()); 1238 } 1239 } 1240 1241 return childSessionParamsBuilder.build(); 1242 } 1243 getDefaultTrafficSelectorIpv4()1244 private static IkeTrafficSelector getDefaultTrafficSelectorIpv4() { 1245 return new IkeTrafficSelector( 1246 TRAFFIC_SELECTOR_START_PORT, 1247 TRAFFIC_SELECTOR_END_PORT, 1248 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_START_ADDR), 1249 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_END_ADDR)); 1250 } 1251 getDefaultTrafficSelectorIpv6()1252 private static IkeTrafficSelector getDefaultTrafficSelectorIpv6() { 1253 return new IkeTrafficSelector( 1254 TRAFFIC_SELECTOR_START_PORT, 1255 TRAFFIC_SELECTOR_END_PORT, 1256 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_START_ADDR), 1257 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_END_ADDR)); 1258 } 1259 needIncludeInitialContact(InetAddress epdgAddress)1260 private boolean needIncludeInitialContact(InetAddress epdgAddress) { 1261 return !mEpdgMonitor.isConnectedEpdg(epdgAddress); 1262 } 1263 1264 // Returns the IMEISV or device IMEI, in that order of priority. getMobileDeviceIdentity()1265 private @Nullable String getMobileDeviceIdentity() { 1266 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); 1267 telephonyManager = 1268 Objects.requireNonNull(telephonyManager) 1269 .createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId)); 1270 if (telephonyManager == null) { 1271 return null; 1272 } 1273 // Queries the 15-digit device IMEI. 1274 String imei = telephonyManager.getImei(); 1275 if (imei == null || imei.length() != DEVICE_IMEI_LEN) { 1276 Log.i(TAG, "Unable to query valid Mobile Device Identity (IMEI)!"); 1277 return null; 1278 } 1279 String imeisv_suffix = telephonyManager.getDeviceSoftwareVersion(); 1280 if (imeisv_suffix == null || imeisv_suffix.length() != DEVICE_IMEISV_SUFFIX_LEN) { 1281 // Unable to retrieve 2-digit suffix for IMEISV, so returns device IMEI. 1282 return imei; 1283 } 1284 // Splices the first 14 digit of device IMEI with 2-digit SV suffix to form IMEISV. 1285 return imei.substring(0, imei.length() - 1) + imeisv_suffix; 1286 } 1287 buildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress)1288 private IkeSessionParams buildIkeSessionParams( 1289 TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress) 1290 throws IwlanSimNotReadyException { 1291 int hardTimeSeconds = 1292 IwlanCarrierConfig.getConfigInt( 1293 mContext, 1294 mSlotId, 1295 CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT); 1296 int softTimeSeconds = 1297 IwlanCarrierConfig.getConfigInt( 1298 mContext, 1299 mSlotId, 1300 CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT); 1301 if (!isValidIkeSessionLifetime(hardTimeSeconds, softTimeSeconds)) { 1302 if (hardTimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM 1303 && softTimeSeconds > IKE_SOFT_LIFETIME_SEC_MINIMUM) { 1304 hardTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM; 1305 softTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM; 1306 } else { 1307 hardTimeSeconds = 1308 IwlanCarrierConfig.getDefaultConfigInt( 1309 CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT); 1310 softTimeSeconds = 1311 IwlanCarrierConfig.getDefaultConfigInt( 1312 CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT); 1313 } 1314 Log.d( 1315 TAG, 1316 "Invalid ike session lifetime values, set hard: " 1317 + hardTimeSeconds 1318 + ", soft: " 1319 + softTimeSeconds); 1320 } 1321 1322 IkeSessionParams.Builder builder = 1323 new IkeSessionParams.Builder() 1324 // permanently hardcode DSCP to 46 (Expedited Forwarding class) 1325 // See https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml 1326 // This will make WiFi prioritize IKE signallig under WMM AC_VO 1327 .setDscp(46) 1328 .setServerHostname(epdgAddress.getHostAddress()) 1329 .setLocalIdentification(getLocalIdentification()) 1330 .setRemoteIdentification(getId(setupRequest.apnName(), false)) 1331 .setAuthEap(null, getEapConfig()) 1332 .setNetwork(mDefaultNetwork) 1333 .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID) 1334 .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) 1335 .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY) 1336 .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds) 1337 .setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig()) 1338 .setDpdDelaySeconds(getDpdDelayFromConfig()); 1339 1340 // Else block and it's related functionality can be removed once 1341 // multipleSaProposals, highSecureTransformsPrioritized and aeadAlgosEnabled feature flags 1342 // related functionality becomes stable and gets instruction to remove feature flags. 1343 if (mFeatureFlags.multipleSaProposals() 1344 || mFeatureFlags.highSecureTransformsPrioritized()) { 1345 EpdgIkeSaProposal epdgIkeSaProposal = createEpdgIkeSaProposal(); 1346 1347 // Adds single SA proposal, priority is for AEAD if configured else non-AEAD proposal. 1348 if (isIkeSessionAeadAlgosAvailable()) { 1349 builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaAeadProposal()); 1350 } else { 1351 builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaProposal()); 1352 } 1353 // Adds multiple proposals. If AEAD proposal already added then adds 1354 // configured non-AEAD proposal followed by supported AEAD and non-AEAD proposals. 1355 if (IwlanCarrierConfig.getConfigBoolean( 1356 mContext, 1357 mSlotId, 1358 CarrierConfigManager.Iwlan 1359 .KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) { 1360 if (isIkeSessionAeadAlgosAvailable() && isIkeSessionNonAeadAlgosAvailable()) { 1361 builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaProposal()); 1362 } 1363 builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaAeadProposal()); 1364 builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaProposal()); 1365 } 1366 } else { 1367 if (isIkeSessionAeadAlgosAvailable()) { 1368 builder.addIkeSaProposal(buildIkeSaAeadProposal()); 1369 } else { 1370 builder.addIkeSaProposal(buildIkeSaProposal()); 1371 } 1372 } 1373 1374 if (needIncludeInitialContact(epdgAddress)) { 1375 builder.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT); 1376 Log.d(TAG, "IKE_OPTION_INITIAL_CONTACT"); 1377 } 1378 1379 if (IwlanCarrierConfig.getConfigInt( 1380 mContext, 1381 mSlotId, 1382 CarrierConfigManager.Iwlan.KEY_EPDG_AUTHENTICATION_METHOD_INT) 1383 == CarrierConfigManager.Iwlan.AUTHENTICATION_METHOD_EAP_ONLY) { 1384 builder.addIkeOption(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH); 1385 } 1386 1387 if (setupRequest.requestPcscf()) { 1388 int proto = setupRequest.apnIpProtocol(); 1389 if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) { 1390 builder.addPcscfServerRequest(AF_INET); 1391 } 1392 if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) { 1393 builder.addPcscfServerRequest(AF_INET6); 1394 } 1395 } 1396 1397 // If MOBIKE is configured, ePDGs may force IPv6 UDP encapsulation- as specified by 1398 // RFC 4555- which Android connectivity stack presently does not support. 1399 if (epdgAddress instanceof Inet6Address) { 1400 builder.removeIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE); 1401 } 1402 1403 builder.setIke3gppExtension(buildIke3gppExtension(setupRequest, apnName, token)); 1404 1405 int nattKeepAliveTimer = 1406 IwlanCarrierConfig.getConfigInt( 1407 mContext, 1408 mSlotId, 1409 CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT); 1410 if (nattKeepAliveTimer < NATT_KEEPALIVE_DELAY_SEC_MIN 1411 || nattKeepAliveTimer > NATT_KEEPALIVE_DELAY_SEC_MAX) { 1412 Log.d(TAG, "Falling back to default natt keep alive timer" + nattKeepAliveTimer); 1413 nattKeepAliveTimer = 1414 IwlanCarrierConfig.getDefaultConfigInt( 1415 CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT); 1416 } 1417 builder.setNattKeepAliveDelaySeconds(nattKeepAliveTimer); 1418 1419 return builder.build(); 1420 } 1421 buildIke3gppExtension( TunnelSetupRequest setupRequest, String apnName, int token)1422 private Ike3gppExtension buildIke3gppExtension( 1423 TunnelSetupRequest setupRequest, String apnName, int token) { 1424 Ike3gppParams.Builder builder3gppParams = new Ike3gppParams.Builder(); 1425 1426 if (IwlanCarrierConfig.getConfigBoolean( 1427 mContext, mSlotId, IwlanCarrierConfig.KEY_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL)) { 1428 String imei = getMobileDeviceIdentity(); 1429 if (imei != null) { 1430 Log.d(TAG, "DEVICE_IDENTITY set in Ike3gppParams"); 1431 builder3gppParams.setMobileDeviceIdentity(imei); 1432 } 1433 } 1434 1435 if (setupRequest.pduSessionId() != PDU_SESSION_ID_UNSET) { 1436 // Includes N1_MODE_CAPABILITY NOTIFY payload in IKE_AUTH exchange when PDU session ID 1437 // is set; otherwise, do not include. 1438 builder3gppParams.setPduSessionId((byte) setupRequest.pduSessionId()); 1439 } 1440 1441 return new Ike3gppExtension( 1442 builder3gppParams.build(), new TmIke3gppCallback(apnName, token)); 1443 } 1444 isChildSessionAeadAlgosAvailable()1445 private boolean isChildSessionAeadAlgosAvailable() { 1446 if (!mFeatureFlags.aeadAlgosEnabled()) { 1447 return false; 1448 } 1449 1450 int[] encryptionAlgos = 1451 IwlanCarrierConfig.getConfigIntArray( 1452 mContext, 1453 mSlotId, 1454 CarrierConfigManager.Iwlan 1455 .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY); 1456 for (int encryptionAlgo : encryptionAlgos) { 1457 if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1458 return true; 1459 } 1460 } 1461 return false; 1462 } 1463 isChildSessionNonAeadAlgosAvailable()1464 private boolean isChildSessionNonAeadAlgosAvailable() { 1465 int[] encryptionAlgos = 1466 IwlanCarrierConfig.getConfigIntArray( 1467 mContext, 1468 mSlotId, 1469 CarrierConfigManager.Iwlan 1470 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1471 for (int encryptionAlgo : encryptionAlgos) { 1472 if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1473 return true; 1474 } 1475 } 1476 return false; 1477 } 1478 isIkeSessionAeadAlgosAvailable()1479 private boolean isIkeSessionAeadAlgosAvailable() { 1480 if (!mFeatureFlags.aeadAlgosEnabled()) { 1481 return false; 1482 } 1483 1484 int[] encryptionAlgos = 1485 IwlanCarrierConfig.getConfigIntArray( 1486 mContext, 1487 mSlotId, 1488 CarrierConfigManager.Iwlan 1489 .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY); 1490 for (int encryptionAlgo : encryptionAlgos) { 1491 if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1492 return true; 1493 } 1494 } 1495 return false; 1496 } 1497 isIkeSessionNonAeadAlgosAvailable()1498 private boolean isIkeSessionNonAeadAlgosAvailable() { 1499 int[] encryptionAlgos = 1500 IwlanCarrierConfig.getConfigIntArray( 1501 mContext, 1502 mSlotId, 1503 CarrierConfigManager.Iwlan 1504 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1505 for (int encryptionAlgo : encryptionAlgos) { 1506 if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1507 return true; 1508 } 1509 } 1510 return false; 1511 } 1512 isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1513 private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { 1514 return hardLifetimeSeconds >= CHILD_HARD_LIFETIME_SEC_MINIMUM 1515 && hardLifetimeSeconds <= CHILD_HARD_LIFETIME_SEC_MAXIMUM 1516 && softLifetimeSeconds >= CHILD_SOFT_LIFETIME_SEC_MINIMUM 1517 && hardLifetimeSeconds - softLifetimeSeconds >= LIFETIME_MARGIN_SEC_MINIMUM; 1518 } 1519 isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1520 private boolean isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { 1521 return hardLifetimeSeconds >= IKE_HARD_LIFETIME_SEC_MINIMUM 1522 && hardLifetimeSeconds <= IKE_HARD_LIFETIME_SEC_MAXIMUM 1523 && softLifetimeSeconds >= IKE_SOFT_LIFETIME_SEC_MINIMUM 1524 && hardLifetimeSeconds - softLifetimeSeconds >= LIFETIME_MARGIN_SEC_MINIMUM; 1525 } 1526 createEpdgSaProposal(EpdgSaProposal epdgSaProposal, boolean isChildProposal)1527 private void createEpdgSaProposal(EpdgSaProposal epdgSaProposal, boolean isChildProposal) { 1528 epdgSaProposal.addProposedDhGroups( 1529 IwlanCarrierConfig.getConfigIntArray( 1530 mContext, 1531 mSlotId, 1532 CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY)); 1533 1534 String encryptionAlgosConfigKey = 1535 isChildProposal 1536 ? CarrierConfigManager.Iwlan 1537 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY 1538 : CarrierConfigManager.Iwlan 1539 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY; 1540 1541 int[] encryptionAlgos = 1542 IwlanCarrierConfig.getConfigIntArray(mContext, mSlotId, encryptionAlgosConfigKey); 1543 1544 for (int encryptionAlgo : encryptionAlgos) { 1545 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1546 String aesCbcKeyLensConfigKey = 1547 isChildProposal 1548 ? CarrierConfigManager.Iwlan 1549 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY 1550 : CarrierConfigManager.Iwlan 1551 .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY; 1552 1553 int[] aesCbcKeyLens = 1554 IwlanCarrierConfig.getConfigIntArray( 1555 mContext, mSlotId, aesCbcKeyLensConfigKey); 1556 epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLens); 1557 } 1558 1559 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1560 String aesCtrKeyLensConfigKey = 1561 isChildProposal 1562 ? CarrierConfigManager.Iwlan 1563 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY 1564 : CarrierConfigManager.Iwlan 1565 .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY; 1566 int[] aesCtrKeyLens = 1567 IwlanCarrierConfig.getConfigIntArray( 1568 mContext, mSlotId, aesCtrKeyLensConfigKey); 1569 epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLens); 1570 } 1571 } 1572 1573 if (encryptionAlgos.length > 0) { 1574 epdgSaProposal.addProposedIntegrityAlgorithm( 1575 IwlanCarrierConfig.getConfigIntArray( 1576 mContext, 1577 mSlotId, 1578 CarrierConfigManager.Iwlan 1579 .KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY)); 1580 } 1581 1582 String aeadAlgosConfigKey = 1583 isChildProposal 1584 ? CarrierConfigManager.Iwlan 1585 .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY 1586 : CarrierConfigManager.Iwlan 1587 .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY; 1588 int[] aeadAlgos = 1589 IwlanCarrierConfig.getConfigIntArray(mContext, mSlotId, aeadAlgosConfigKey); 1590 for (int aeadAlgo : aeadAlgos) { 1591 if (!validateConfig(aeadAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1592 continue; 1593 } 1594 if ((aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8) 1595 || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) 1596 || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) { 1597 String aesGcmKeyLensConfigKey = 1598 isChildProposal 1599 ? CarrierConfigManager.Iwlan 1600 .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY 1601 : CarrierConfigManager.Iwlan 1602 .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY; 1603 int[] aesGcmKeyLens = 1604 IwlanCarrierConfig.getConfigIntArray( 1605 mContext, mSlotId, aesGcmKeyLensConfigKey); 1606 epdgSaProposal.addProposedAeadAlgorithm(aeadAlgo, aesGcmKeyLens); 1607 } 1608 } 1609 1610 if (IwlanCarrierConfig.getConfigBoolean( 1611 mContext, mSlotId, IwlanCarrierConfig.KEY_IKE_SA_TRANSFORMS_REORDER_BOOL)) { 1612 epdgSaProposal.enableReorderingSaferProposals(); 1613 } 1614 } 1615 createEpdgChildSaProposal()1616 private EpdgChildSaProposal createEpdgChildSaProposal() { 1617 EpdgChildSaProposal epdgChildSaProposal = new EpdgChildSaProposal(); 1618 createEpdgSaProposal(epdgChildSaProposal, true); 1619 return epdgChildSaProposal; 1620 } 1621 createEpdgIkeSaProposal()1622 private EpdgIkeSaProposal createEpdgIkeSaProposal() { 1623 EpdgIkeSaProposal epdgIkeSaProposal = new EpdgIkeSaProposal(); 1624 1625 createEpdgSaProposal(epdgIkeSaProposal, false); 1626 1627 epdgIkeSaProposal.addProposedPrfAlgorithm( 1628 IwlanCarrierConfig.getConfigIntArray( 1629 mContext, 1630 mSlotId, 1631 CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY)); 1632 return epdgIkeSaProposal; 1633 } 1634 buildIkeSaProposal()1635 private IkeSaProposal buildIkeSaProposal() { 1636 IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); 1637 1638 int[] dhGroups = 1639 IwlanCarrierConfig.getConfigIntArray( 1640 mContext, 1641 mSlotId, 1642 CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1643 for (int dhGroup : dhGroups) { 1644 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1645 saProposalBuilder.addDhGroup(dhGroup); 1646 } 1647 } 1648 1649 int[] encryptionAlgos = 1650 IwlanCarrierConfig.getConfigIntArray( 1651 mContext, 1652 mSlotId, 1653 CarrierConfigManager.Iwlan 1654 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1655 for (int encryptionAlgo : encryptionAlgos) { 1656 validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO); 1657 1658 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1659 int[] aesCbcKeyLens = 1660 IwlanCarrierConfig.getConfigIntArray( 1661 mContext, 1662 mSlotId, 1663 CarrierConfigManager.Iwlan 1664 .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); 1665 for (int aesCbcKeyLen : aesCbcKeyLens) { 1666 if (validateConfig(aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1667 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLen); 1668 } 1669 } 1670 } 1671 1672 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1673 int[] aesCtrKeyLens = 1674 IwlanCarrierConfig.getConfigIntArray( 1675 mContext, 1676 mSlotId, 1677 CarrierConfigManager.Iwlan 1678 .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); 1679 for (int aesCtrKeyLen : aesCtrKeyLens) { 1680 if (validateConfig(aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1681 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLen); 1682 } 1683 } 1684 } 1685 } 1686 1687 int[] integrityAlgos = 1688 IwlanCarrierConfig.getConfigIntArray( 1689 mContext, 1690 mSlotId, 1691 CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY); 1692 for (int integrityAlgo : integrityAlgos) { 1693 if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { 1694 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); 1695 } 1696 } 1697 1698 int[] prfAlgos = 1699 IwlanCarrierConfig.getConfigIntArray( 1700 mContext, 1701 mSlotId, 1702 CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY); 1703 for (int prfAlgo : prfAlgos) { 1704 if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) { 1705 saProposalBuilder.addPseudorandomFunction(prfAlgo); 1706 } 1707 } 1708 1709 return saProposalBuilder.build(); 1710 } 1711 buildIkeSaAeadProposal()1712 private IkeSaProposal buildIkeSaAeadProposal() { 1713 IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); 1714 1715 int[] dhGroups = 1716 IwlanCarrierConfig.getConfigIntArray( 1717 mContext, 1718 mSlotId, 1719 CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1720 for (int dhGroup : dhGroups) { 1721 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1722 saProposalBuilder.addDhGroup(dhGroup); 1723 } 1724 } 1725 1726 int[] encryptionAlgos = 1727 IwlanCarrierConfig.getConfigIntArray( 1728 mContext, 1729 mSlotId, 1730 CarrierConfigManager.Iwlan 1731 .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY); 1732 for (int encryptionAlgo : encryptionAlgos) { 1733 if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1734 continue; 1735 } 1736 if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8) 1737 || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) 1738 || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) { 1739 int[] aesGcmKeyLens = 1740 IwlanCarrierConfig.getConfigIntArray( 1741 mContext, 1742 mSlotId, 1743 CarrierConfigManager.Iwlan 1744 .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY); 1745 for (int aesGcmKeyLen : aesGcmKeyLens) { 1746 if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1747 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen); 1748 } 1749 } 1750 } 1751 } 1752 1753 int[] prfAlgos = 1754 IwlanCarrierConfig.getConfigIntArray( 1755 mContext, 1756 mSlotId, 1757 CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY); 1758 for (int prfAlgo : prfAlgos) { 1759 if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) { 1760 saProposalBuilder.addPseudorandomFunction(prfAlgo); 1761 } 1762 } 1763 1764 return saProposalBuilder.build(); 1765 } 1766 validateConfig(int config, Set<Integer> validConfigValues, String configType)1767 private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) { 1768 if (validConfigValues.contains(config)) { 1769 return true; 1770 } 1771 1772 Log.e(TAG, "Invalid config value for " + configType + ":" + config); 1773 return false; 1774 } 1775 buildChildSaProposal()1776 private ChildSaProposal buildChildSaProposal() { 1777 ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder(); 1778 1779 // IKE library doesn't add KE payload if dh groups are not set in child session params. 1780 // Use the same groups as that of IKE session. 1781 if (IwlanCarrierConfig.getConfigBoolean( 1782 mContext, 1783 mSlotId, 1784 CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) { 1785 int[] dhGroups = 1786 IwlanCarrierConfig.getConfigIntArray( 1787 mContext, 1788 mSlotId, 1789 CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1790 for (int dhGroup : dhGroups) { 1791 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1792 saProposalBuilder.addDhGroup(dhGroup); 1793 } 1794 } 1795 } 1796 1797 int[] encryptionAlgos = 1798 IwlanCarrierConfig.getConfigIntArray( 1799 mContext, 1800 mSlotId, 1801 CarrierConfigManager.Iwlan 1802 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1803 for (int encryptionAlgo : encryptionAlgos) { 1804 if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1805 if (ChildSaProposal.getSupportedEncryptionAlgorithms().contains(encryptionAlgo)) { 1806 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1807 int[] aesCbcKeyLens = 1808 IwlanCarrierConfig.getConfigIntArray( 1809 mContext, 1810 mSlotId, 1811 CarrierConfigManager.Iwlan 1812 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); 1813 for (int aesCbcKeyLen : aesCbcKeyLens) { 1814 if (validateConfig( 1815 aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1816 saProposalBuilder.addEncryptionAlgorithm( 1817 encryptionAlgo, aesCbcKeyLen); 1818 } 1819 } 1820 } 1821 1822 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1823 int[] aesCtrKeyLens = 1824 IwlanCarrierConfig.getConfigIntArray( 1825 mContext, 1826 mSlotId, 1827 CarrierConfigManager.Iwlan 1828 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); 1829 for (int aesCtrKeyLen : aesCtrKeyLens) { 1830 if (validateConfig( 1831 aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1832 saProposalBuilder.addEncryptionAlgorithm( 1833 encryptionAlgo, aesCtrKeyLen); 1834 } 1835 } 1836 } 1837 } else { 1838 Log.w(TAG, "Device does not support encryption algo: " + encryptionAlgo); 1839 } 1840 } 1841 } 1842 1843 int[] integrityAlgos = 1844 IwlanCarrierConfig.getConfigIntArray( 1845 mContext, 1846 mSlotId, 1847 CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY); 1848 for (int integrityAlgo : integrityAlgos) { 1849 if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { 1850 if (ChildSaProposal.getSupportedIntegrityAlgorithms().contains(integrityAlgo)) { 1851 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); 1852 } else { 1853 Log.w(TAG, "Device does not support integrity algo: " + integrityAlgo); 1854 } 1855 } 1856 } 1857 1858 return saProposalBuilder.build(); 1859 } 1860 buildAeadChildSaProposal()1861 private ChildSaProposal buildAeadChildSaProposal() { 1862 ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder(); 1863 1864 int[] dhGroups = 1865 IwlanCarrierConfig.getConfigIntArray( 1866 mContext, 1867 mSlotId, 1868 CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1869 for (int dhGroup : dhGroups) { 1870 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1871 saProposalBuilder.addDhGroup(dhGroup); 1872 } 1873 } 1874 1875 int[] encryptionAlgos = 1876 IwlanCarrierConfig.getConfigIntArray( 1877 mContext, 1878 mSlotId, 1879 CarrierConfigManager.Iwlan 1880 .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY); 1881 for (int encryptionAlgo : encryptionAlgos) { 1882 if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1883 continue; 1884 } 1885 if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8) 1886 || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12) 1887 || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) { 1888 int[] aesGcmKeyLens = 1889 IwlanCarrierConfig.getConfigIntArray( 1890 mContext, 1891 mSlotId, 1892 CarrierConfigManager.Iwlan 1893 .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY); 1894 for (int aesGcmKeyLen : aesGcmKeyLens) { 1895 if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1896 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen); 1897 } 1898 } 1899 } 1900 } 1901 1902 return saProposalBuilder.build(); 1903 } 1904 getLocalIdentification()1905 private IkeIdentification getLocalIdentification() throws IwlanSimNotReadyException { 1906 String nai; 1907 1908 nai = IwlanHelper.getNai(mContext, mSlotId, mNextReauthId); 1909 1910 if (nai == null) { 1911 throw new IwlanSimNotReadyException("Nai is null."); 1912 } 1913 1914 Log.d(TAG, "getLocalIdentification: Nai: " + nai); 1915 return getId(nai, true); 1916 } 1917 getId(String id, boolean isLocal)1918 private IkeIdentification getId(String id, boolean isLocal) { 1919 String idTypeConfig = 1920 isLocal 1921 ? CarrierConfigManager.Iwlan.KEY_IKE_LOCAL_ID_TYPE_INT 1922 : CarrierConfigManager.Iwlan.KEY_IKE_REMOTE_ID_TYPE_INT; 1923 int idType = IwlanCarrierConfig.getConfigInt(mContext, mSlotId, idTypeConfig); 1924 return switch (idType) { 1925 case CarrierConfigManager.Iwlan.ID_TYPE_FQDN -> new IkeFqdnIdentification(id); 1926 case CarrierConfigManager.Iwlan.ID_TYPE_KEY_ID -> 1927 new IkeKeyIdIdentification(id.getBytes(StandardCharsets.US_ASCII)); 1928 case CarrierConfigManager.Iwlan.ID_TYPE_RFC822_ADDR -> 1929 new IkeRfc822AddrIdentification(id); 1930 default -> throw new IllegalArgumentException("Invalid local Identity type: " + idType); 1931 }; 1932 } 1933 1934 private EapSessionConfig getEapConfig() throws IwlanSimNotReadyException { 1935 int subId = IwlanHelper.getSubId(mContext, mSlotId); 1936 String nai = IwlanHelper.getNai(mContext, mSlotId, null); 1937 1938 if (nai == null) { 1939 throw new IwlanSimNotReadyException("Nai is null."); 1940 } 1941 1942 EapSessionConfig.EapAkaOption option = null; 1943 if (mNextReauthId != null) { 1944 option = new EapSessionConfig.EapAkaOption.Builder().setReauthId(mNextReauthId).build(); 1945 } 1946 1947 Log.d(TAG, "getEapConfig: Nai: " + nai); 1948 return new EapSessionConfig.Builder() 1949 .setEapAkaConfig(subId, TelephonyManager.APPTYPE_USIM, option) 1950 .setEapIdentity(nai.getBytes(StandardCharsets.US_ASCII)) 1951 .build(); 1952 } 1953 1954 private void onSessionClosedWithException( 1955 IkeException exception, String apnName, int token, int sessionType) { 1956 Log.e( 1957 TAG, 1958 "Closing tunnel with exception for apn: " 1959 + apnName 1960 + " with token: " 1961 + token 1962 + " sessionType:" 1963 + sessionType); 1964 exception.printStackTrace(); 1965 1966 mHandler.obtainMessage(sessionType, new SessionClosedData(apnName, token, exception)) 1967 .sendToTarget(); 1968 } 1969 1970 private boolean isEpdgSelectionOrFirstTunnelBringUpInProgress() { 1971 // Tunnel config is created but not connected to an ePDG. i.e., The first bring-up request 1972 // in progress. 1973 // No bring-up request in progress but pending queue is not empty. i.e. ePDG selection in 1974 // progress 1975 return (!mHasConnectedToEpdg && !mApnNameToTunnelConfig.isEmpty()) 1976 || !mPendingBringUpRequests.isEmpty(); 1977 } 1978 1979 private IwlanError getErrorFromIkeException( 1980 IkeException ikeException, IkeSessionState ikeSessionState) { 1981 IwlanError error; 1982 if (ikeException instanceof IkeIOException) { 1983 error = new IwlanError(ikeSessionState.getErrorType(), ikeException); 1984 } else { 1985 error = new IwlanError(ikeException); 1986 } 1987 Log.e(TAG, "Closing tunnel: error: " + error + " state: " + ikeSessionState); 1988 return error; 1989 } 1990 1991 private final class TmHandler extends Handler { 1992 1993 @Override 1994 public void handleMessage(Message msg) { 1995 Log.d(TAG, "msg.what = " + eventToString(msg.what)); 1996 1997 String apnName; 1998 TunnelConfig tunnelConfig; 1999 OnClosedMetrics.Builder onClosedMetricsBuilder; 2000 TunnelRequestWrapper tunnelRequestWrapper; 2001 ConnectivityManager connectivityManager; 2002 boolean isNetworkValidated; 2003 switch (msg.what) { 2004 case EVENT_CHILD_SESSION_OPENED: 2005 case EVENT_IKE_SESSION_CLOSED: 2006 case EVENT_IPSEC_TRANSFORM_CREATED: 2007 case EVENT_IPSEC_TRANSFORM_DELETED: 2008 case EVENT_CHILD_SESSION_CLOSED: 2009 case EVENT_IKE_SESSION_OPENED: 2010 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED: 2011 case EVENT_IKE_3GPP_DATA_RECEIVED: 2012 case EVENT_IKE_LIVENESS_STATUS_CHANGED: 2013 IkeEventData ikeEventData = (IkeEventData) msg.obj; 2014 if (isObsoleteToken(ikeEventData.mApnName, ikeEventData.mToken)) { 2015 Log.d( 2016 TAG, 2017 eventToString(msg.what) 2018 + " for obsolete token " 2019 + ikeEventData.mToken); 2020 return; 2021 } 2022 } 2023 2024 long mIkeTunnelEstablishmentDuration; 2025 switch (msg.what) { 2026 case EVENT_TUNNEL_BRINGUP_REQUEST: 2027 handleTunnelBringUpRequest((TunnelRequestWrapper) msg.obj); 2028 break; 2029 2030 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE: 2031 EpdgSelectorResult selectorResult = (EpdgSelectorResult) msg.obj; 2032 printRequestQueue("EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE"); 2033 2034 if (selectorResult.getTransactionId() != mTransactionId) { 2035 Log.e(TAG, "Mismatched transactionId"); 2036 break; 2037 } 2038 2039 if (mPendingBringUpRequests.isEmpty()) { 2040 Log.d(TAG, "Empty request queue"); 2041 break; 2042 } 2043 2044 if (selectorResult.getEpdgError().getErrorType() == IwlanError.NO_ERROR 2045 && selectorResult.getValidIpList() != null) { 2046 tunnelRequestWrapper = mPendingBringUpRequests.remove(); 2047 onBringUpTunnel( 2048 tunnelRequestWrapper, 2049 validateAndSetEpdgAddress(selectorResult.getValidIpList())); 2050 } else { 2051 IwlanError error = 2052 (selectorResult.getEpdgError().getErrorType() 2053 == IwlanError.NO_ERROR) 2054 ? new IwlanError( 2055 IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED) 2056 : selectorResult.getEpdgError(); 2057 failAllPendingRequests(error); 2058 } 2059 break; 2060 2061 case EVENT_CHILD_SESSION_OPENED: 2062 TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj; 2063 apnName = tunnelOpenedData.mApnName; 2064 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2065 2066 tunnelConfig.setDnsAddrList(tunnelOpenedData.mInternalDnsServers); 2067 tunnelConfig.setInternalAddrList(tunnelOpenedData.mInternalAddresses); 2068 2069 IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface(); 2070 2071 for (LinkAddress address : tunnelConfig.getInternalAddrList()) { 2072 try { 2073 tunnelInterface.addAddress( 2074 address.getAddress(), address.getPrefixLength()); 2075 } catch (IOException e) { 2076 Log.e(TAG, "Adding internal addresses to interface failed."); 2077 } 2078 } 2079 2080 TunnelLinkProperties linkProperties = 2081 TunnelLinkProperties.builder() 2082 .setInternalAddresses(tunnelConfig.getInternalAddrList()) 2083 .setDnsAddresses(tunnelConfig.getDnsAddrList()) 2084 .setPcscfAddresses(tunnelConfig.getPcscfAddrList()) 2085 .setIfaceName(tunnelConfig.getIface().getInterfaceName()) 2086 .setSliceInfo(tunnelConfig.getSliceInfo()) 2087 .build(); 2088 2089 mIkeTunnelEstablishmentDuration = 2090 System.currentTimeMillis() - mIkeTunnelEstablishmentStartTime; 2091 mIkeTunnelEstablishmentStartTime = 0; 2092 isNetworkValidated = isUnderlyingNetworkValidated(mIkeSessionNetwork); 2093 OnOpenedMetrics onOpenedMetrics = 2094 new OnOpenedMetrics.Builder() 2095 .setApnName(apnName) 2096 .setEpdgServerAddress(tunnelConfig.getEpdgAddress()) 2097 .setEpdgServerSelectionDuration( 2098 (int) mEpdgServerSelectionDuration) 2099 .setIkeTunnelEstablishmentDuration( 2100 (int) mIkeTunnelEstablishmentDuration) 2101 .setIsNetworkValidated(isNetworkValidated) 2102 .build(); 2103 tunnelConfig 2104 .getTunnelCallback() 2105 .onOpened(apnName, linkProperties, onOpenedMetrics); 2106 2107 reportIwlanError(apnName, new IwlanError(IwlanError.NO_ERROR)); 2108 mEpdgSelector.onEpdgConnectedSuccessfully(); 2109 2110 mEpdgMonitor.onApnConnectToEpdg(apnName, tunnelConfig.getEpdgAddress()); 2111 onConnectedToEpdg(true); 2112 mValidEpdgInfo.resetIndex(); 2113 printRequestQueue("EVENT_CHILD_SESSION_OPENED"); 2114 serviceAllPendingRequests(); 2115 tunnelConfig.setIkeSessionState(IkeSessionState.CHILD_SESSION_OPENED); 2116 break; 2117 2118 case EVENT_IKE_SESSION_CLOSED: 2119 printRequestQueue("EVENT_IKE_SESSION_CLOSED"); 2120 SessionClosedData sessionClosedData = (SessionClosedData) msg.obj; 2121 apnName = sessionClosedData.mApnName; 2122 2123 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2124 if (tunnelConfig == null) { 2125 Log.e(TAG, "No callback found for apn: " + apnName); 2126 return; 2127 } 2128 2129 // If IKE session closed exceptionally, we retrieve IwlanError directly from the 2130 // exception; otherwise, it is still possible that we triggered an IKE session 2131 // close due to an error (e.g. IwlanError.TUNNEL_TRANSFORM_FAILED), or because 2132 // the Child session closed exceptionally; in which case, we attempt to retrieve 2133 // the stored error (if any) from TunnelConfig. 2134 IwlanError iwlanError; 2135 if (sessionClosedData.mIkeException != null) { 2136 iwlanError = 2137 getErrorFromIkeException( 2138 sessionClosedData.mIkeException, 2139 tunnelConfig.getIkeSessionState()); 2140 } else { 2141 // If IKE session opened, then closed before child session (and IWLAN 2142 // tunnel) opened. 2143 // Iwlan reports IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED 2144 // instead of NO_ERROR 2145 if (!tunnelConfig.hasTunnelOpened()) { 2146 int errorType = 2147 IwlanError.IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED; 2148 iwlanError = new IwlanError(errorType); 2149 } else { 2150 iwlanError = tunnelConfig.getError(); 2151 } 2152 } 2153 2154 IpSecManager.IpSecTunnelInterface iface = tunnelConfig.getIface(); 2155 if (iface != null) { 2156 iface.close(); 2157 } 2158 2159 if (!tunnelConfig.hasTunnelOpened()) { 2160 if (tunnelConfig.isBackoffTimeValid()) { 2161 reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime()); 2162 } else { 2163 reportIwlanError(apnName, iwlanError); 2164 } 2165 mEpdgMonitor.onEpdgConnectionFailed( 2166 tunnelConfig.isEmergency(), tunnelConfig.getEpdgAddress()); 2167 if (sessionClosedData.mIkeException != null) { 2168 mEpdgSelector.onEpdgConnectionFailed( 2169 tunnelConfig.getEpdgAddress(), sessionClosedData.mIkeException); 2170 } 2171 } else { 2172 /* PDN disconnected case */ 2173 triggerUnderlyingNetworkValidationOnError(iwlanError); 2174 } 2175 2176 Log.d(TAG, "Tunnel Closed: " + iwlanError); 2177 tunnelConfig.setIkeSessionState(IkeSessionState.NO_IKE_SESSION); 2178 2179 onClosedMetricsBuilder = new OnClosedMetrics.Builder().setApnName(apnName); 2180 if (!mEpdgMonitor.hasEpdgConnected()) { 2181 failAllPendingRequests(iwlanError); 2182 } else { 2183 mIkeTunnelEstablishmentDuration = 2184 mIkeTunnelEstablishmentStartTime > 0 2185 ? System.currentTimeMillis() 2186 - mIkeTunnelEstablishmentStartTime 2187 : 0; 2188 mIkeTunnelEstablishmentStartTime = 0; 2189 2190 isNetworkValidated = isUnderlyingNetworkValidated(mIkeSessionNetwork); 2191 onClosedMetricsBuilder 2192 .setEpdgServerAddress(tunnelConfig.getEpdgAddress()) 2193 .setEpdgServerSelectionDuration((int) mEpdgServerSelectionDuration) 2194 .setIkeTunnelEstablishmentDuration( 2195 (int) mIkeTunnelEstablishmentDuration) 2196 .setIsNetworkValidated(isNetworkValidated); 2197 } 2198 tunnelConfig 2199 .getTunnelCallback() 2200 .onClosed(apnName, iwlanError, onClosedMetricsBuilder.build()); 2201 2202 mApnNameToTunnelConfig.remove(apnName); 2203 mEpdgMonitor.onApnDisconnectFromEpdg(apnName); 2204 if (mApnNameToTunnelConfig.isEmpty() && mPendingBringUpRequests.isEmpty()) { 2205 onConnectedToEpdg(false); 2206 } 2207 break; 2208 2209 case EVENT_UPDATE_NETWORK: 2210 UpdateNetworkWrapper updatedNetwork = (UpdateNetworkWrapper) msg.obj; 2211 mDefaultNetwork = updatedNetwork.getNetwork(); 2212 LinkProperties defaultLinkProperties = updatedNetwork.getLinkProperties(); 2213 String paraString = "Network: " + mDefaultNetwork; 2214 2215 if (mEpdgMonitor.hasEpdgConnected()) { 2216 if (Objects.isNull(mDefaultNetwork)) { 2217 Log.w(TAG, "The default network has been removed."); 2218 } else if (Objects.isNull(defaultLinkProperties)) { 2219 Log.w( 2220 TAG, 2221 "The default network's LinkProperties is not ready ." 2222 + paraString); 2223 } else if (Objects.equals(mDefaultNetwork, mIkeSessionNetwork)) { 2224 Log.w( 2225 TAG, 2226 "The default network has not changed from the IKE session" 2227 + " network. " 2228 + paraString); 2229 } else { 2230 for (var entry : mApnNameToTunnelConfig.entrySet()) { 2231 String apn = entry.getKey(); 2232 TunnelConfig config = entry.getValue(); 2233 if (!defaultLinkProperties.isReachable(config.getEpdgAddress())) { 2234 Log.w( 2235 TAG, 2236 "The default network link " 2237 + defaultLinkProperties 2238 + " doesn't have a route to the ePDG " 2239 + config.getEpdgAddress() 2240 + paraString); 2241 } else { 2242 Log.d( 2243 TAG, 2244 "The Underlying Network is updating for APN (+" 2245 + apn 2246 + "). " 2247 + paraString); 2248 config.getIkeSession().setNetwork(mDefaultNetwork); 2249 config.setIkeSessionState( 2250 IkeSessionState.IKE_MOBILITY_IN_PROGRESS); 2251 mIkeSessionNetwork = mDefaultNetwork; 2252 } 2253 } 2254 } 2255 } 2256 break; 2257 2258 case EVENT_TUNNEL_BRINGDOWN_REQUEST: 2259 TunnelBringdownRequest bringdownRequest = (TunnelBringdownRequest) msg.obj; 2260 apnName = bringdownRequest.mApnName; 2261 boolean forceClose = bringdownRequest.mForceClose; 2262 int reason = bringdownRequest.mBringDownReason; 2263 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2264 if (tunnelConfig == null) { 2265 Log.w( 2266 TAG, 2267 "Bringdown request: No tunnel exists for apn: " 2268 + apnName 2269 + ", forced: " 2270 + forceClose 2271 + ", bringdown reason: " 2272 + bringdownReasonToString(reason)); 2273 } else { 2274 if (forceClose) { 2275 tunnelConfig.getIkeSession().kill(); 2276 } else { 2277 tunnelConfig.getIkeSession().close(); 2278 } 2279 } 2280 // TODO(b/309867892): Include tunnel bring down reason in metrics. 2281 int numClosed = closePendingRequestsForApn(apnName); 2282 if (numClosed > 0) { 2283 Log.d( 2284 TAG, 2285 "Closed " 2286 + numClosed 2287 + " pending requests for apn: " 2288 + apnName 2289 + ", bringdown reason: " 2290 + bringdownReasonToString(reason)); 2291 } 2292 if (tunnelConfig == null && numClosed == 0) { 2293 // IwlanDataService expected to close a (pending or up) tunnel but was not 2294 // found. Recovers state in IwlanDataService through TunnelCallback. 2295 iwlanError = new IwlanError(IwlanError.TUNNEL_NOT_FOUND); 2296 reportIwlanError(apnName, iwlanError); 2297 bringdownRequest.mTunnelCallback.onClosed( 2298 apnName, 2299 iwlanError, 2300 new OnClosedMetrics.Builder().setApnName(apnName).build()); 2301 } 2302 break; 2303 2304 case EVENT_IPSEC_TRANSFORM_CREATED: 2305 IpsecTransformData transformData = (IpsecTransformData) msg.obj; 2306 apnName = transformData.getApnName(); 2307 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2308 2309 try { 2310 mIpSecManager.applyTunnelModeTransform( 2311 tunnelConfig.getIface(), 2312 transformData.getDirection(), 2313 transformData.getTransform()); 2314 } catch (IOException | IllegalArgumentException e) { 2315 // If the IKE session was closed before the transform could be applied, the 2316 // IpSecService will throw an IAE on processing the IpSecTunnelInterface id. 2317 Log.e(TAG, "Failed to apply tunnel transform." + e); 2318 closeIkeSession( 2319 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 2320 } 2321 mApnNameToIpsecTransform.put(apnName, transformData); 2322 if (tunnelConfig.getIkeSessionState() 2323 == IkeSessionState.IKE_MOBILITY_IN_PROGRESS) { 2324 tunnelConfig.setIkeSessionState(IkeSessionState.CHILD_SESSION_OPENED); 2325 } 2326 break; 2327 2328 case EVENT_IPSEC_TRANSFORM_DELETED: 2329 transformData = (IpsecTransformData) msg.obj; 2330 IpSecTransform transform = transformData.getTransform(); 2331 transform.close(); 2332 mApnNameToIpsecTransform.remove(transformData.getApnName()); 2333 break; 2334 2335 case EVENT_CHILD_SESSION_CLOSED: 2336 sessionClosedData = (SessionClosedData) msg.obj; 2337 apnName = sessionClosedData.mApnName; 2338 2339 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2340 if (tunnelConfig == null) { 2341 Log.d(TAG, "No tunnel callback for apn: " + apnName); 2342 return; 2343 } 2344 if (sessionClosedData.mIkeException != null) { 2345 tunnelConfig.setError( 2346 getErrorFromIkeException( 2347 sessionClosedData.mIkeException, 2348 tunnelConfig.getIkeSessionState())); 2349 } 2350 tunnelConfig.getIkeSession().close(); 2351 break; 2352 2353 case EVENT_IKE_SESSION_OPENED: 2354 IkeSessionOpenedData ikeSessionOpenedData = (IkeSessionOpenedData) msg.obj; 2355 apnName = ikeSessionOpenedData.mApnName; 2356 IkeSessionConfiguration sessionConfiguration = 2357 ikeSessionOpenedData.mIkeSessionConfiguration; 2358 2359 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2360 tunnelConfig.setPcscfAddrList(sessionConfiguration.getPcscfServers()); 2361 2362 boolean enabledFastReauth = 2363 IwlanCarrierConfig.getConfigBoolean( 2364 mContext, 2365 mSlotId, 2366 CarrierConfigManager.Iwlan 2367 .KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL); 2368 Log.d( 2369 TAG, 2370 "CarrierConfigManager.Iwlan.KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL " 2371 + enabledFastReauth); 2372 2373 if (enabledFastReauth) { 2374 EapInfo eapInfo = sessionConfiguration.getEapInfo(); 2375 if (eapInfo instanceof EapAkaInfo eapAkaInfo) { 2376 mNextReauthId = eapAkaInfo.getReauthId(); 2377 Log.d(TAG, "Update ReauthId: " + Arrays.toString(mNextReauthId)); 2378 } else { 2379 mNextReauthId = null; 2380 } 2381 } 2382 break; 2383 2384 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED: 2385 IkeSessionConnectionInfoData ikeSessionConnectionInfoData = 2386 (IkeSessionConnectionInfoData) msg.obj; 2387 Network network = 2388 ikeSessionConnectionInfoData.mIkeSessionConnectionInfo.getNetwork(); 2389 apnName = ikeSessionConnectionInfoData.mApnName; 2390 2391 connectivityManager = mContext.getSystemService(ConnectivityManager.class); 2392 if (Objects.requireNonNull(connectivityManager).getLinkProperties(network) 2393 == null) { 2394 Log.e(TAG, "Network " + network + " has null LinkProperties!"); 2395 return; 2396 } 2397 2398 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2399 tunnelInterface = tunnelConfig.getIface(); 2400 try { 2401 tunnelInterface.setUnderlyingNetwork(network); 2402 } catch (IOException | IllegalArgumentException e) { 2403 Log.e( 2404 TAG, 2405 "Failed to update underlying network for apn: " 2406 + apnName 2407 + " exception: " 2408 + e); 2409 } 2410 break; 2411 2412 case EVENT_IKE_3GPP_DATA_RECEIVED: 2413 Ike3gppDataReceived ike3gppDataReceived = (Ike3gppDataReceived) msg.obj; 2414 apnName = ike3gppDataReceived.mApnName; 2415 List<Ike3gppData> ike3gppData = ike3gppDataReceived.mIke3gppData; 2416 if (ike3gppData != null && !ike3gppData.isEmpty()) { 2417 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2418 for (Ike3gppData payload : ike3gppData) { 2419 if (payload.getDataType() == DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) { 2420 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_N1_MODE_INFORMATION"); 2421 NetworkSliceInfo si = 2422 NetworkSliceSelectionAssistanceInformation.getSliceInfo( 2423 ((Ike3gppN1ModeInformation) payload).getSnssai()); 2424 if (si != null) { 2425 tunnelConfig.setSliceInfo(si); 2426 Log.d(TAG, "SliceInfo: " + si); 2427 } 2428 } else if (payload.getDataType() == DATA_TYPE_NOTIFY_BACKOFF_TIMER) { 2429 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_BACKOFF_TIMER"); 2430 long backoffTime = 2431 decodeBackoffTime( 2432 ((Ike3gppBackoffTimer) payload).getBackoffTimer()); 2433 if (backoffTime > 0) { 2434 tunnelConfig.setBackoffTime(backoffTime); 2435 Log.d(TAG, "Backoff Timer: " + backoffTime); 2436 } 2437 } 2438 } 2439 } else { 2440 Log.e(TAG, "Null or empty payloads received:"); 2441 } 2442 break; 2443 2444 case EVENT_IKE_LIVENESS_STATUS_CHANGED: 2445 IkeSessionValidationStatusData ikeLivenessData = 2446 (IkeSessionValidationStatusData) msg.obj; 2447 @NetworkValidationStatus int validationStatus = ikeLivenessData.mStatus; 2448 apnName = ikeLivenessData.mApnName; 2449 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2450 if (tunnelConfig == null) { 2451 Log.e(TAG, "No tunnel config found for apn: " + apnName); 2452 return; 2453 } 2454 tunnelConfig 2455 .getTunnelCallback() 2456 .onNetworkValidationStatusChanged(apnName, validationStatus); 2457 break; 2458 2459 case EVENT_REQUEST_NETWORK_VALIDATION_CHECK: 2460 apnName = (String) msg.obj; 2461 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2462 if (tunnelConfig == null) { 2463 Log.e(TAG, "No tunnel config found for apn: " + apnName); 2464 return; 2465 } 2466 tunnelConfig.getIkeSession().requestLivenessCheck(); 2467 break; 2468 2469 default: 2470 throw new IllegalStateException("Unexpected value: " + msg.what); 2471 } 2472 } 2473 2474 private void handleTunnelBringUpRequest(TunnelRequestWrapper tunnelRequestWrapper) { 2475 TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest(); 2476 String apnName = setupRequest.apnName(); 2477 2478 IwlanError bringUpError = canBringUpTunnel(apnName, setupRequest.isEmergency()); 2479 if (Objects.nonNull(bringUpError)) { 2480 tunnelRequestWrapper 2481 .getTunnelCallback() 2482 .onClosed( 2483 apnName, 2484 bringUpError, 2485 new OnClosedMetrics.Builder().setApnName(apnName).build()); 2486 return; 2487 } 2488 serviceTunnelBringUpRequest(tunnelRequestWrapper); 2489 } 2490 2491 private void serviceTunnelBringUpRequest(TunnelRequestWrapper tunnelRequestWrapper) { 2492 if (mEpdgMonitor.hasEpdgConnected()) { 2493 InetAddress epdgAddress = selectConnectedEpdgForTunnelBringUp(tunnelRequestWrapper); 2494 if (epdgAddress != null) { 2495 onBringUpTunnel(tunnelRequestWrapper, epdgAddress); 2496 return; 2497 } 2498 } 2499 2500 if (!isEpdgSelectionOrFirstTunnelBringUpInProgress()) { 2501 // No tunnel bring-up in progress Or emergency request has attempted ePDG for normal 2502 // session but failed, select the ePDG address. 2503 selectEpdgAddress(tunnelRequestWrapper.getSetupRequest()); 2504 } 2505 2506 // Another bring-up or ePDG selection is in progress, pending this request. 2507 mPendingBringUpRequests.add(tunnelRequestWrapper); 2508 } 2509 2510 private InetAddress selectConnectedEpdgForTunnelBringUp( 2511 TunnelRequestWrapper tunnelRequestWrapper) { 2512 if (!mFeatureFlags.distinctEpdgSelectionForEmergencySessions() 2513 || !IwlanCarrierConfig.getConfigBoolean( 2514 mContext, 2515 mSlotId, 2516 IwlanCarrierConfig.KEY_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL)) { 2517 // Attempt on ePDG for normal session since feature not enabled 2518 return mEpdgMonitor.getEpdgAddressForNormalSession(); 2519 } 2520 2521 if (!tunnelRequestWrapper.getSetupRequest().isEmergency()) { 2522 if (mEpdgMonitor.hasSeparateEpdgConnectedForEmergencySession()) { 2523 // Attempt on ePDG for emergency session 2524 return mEpdgMonitor.getEpdgAddressForEmergencySession(); 2525 } else { 2526 // Attempt on ePDG for normal session. 2527 return mEpdgMonitor.getEpdgAddressForNormalSession(); 2528 } 2529 } 2530 2531 if (!mEpdgMonitor.hasEmergencyPdnFailedWithConnectedEpdg()) { 2532 // First emergnecy attempt on ePDG for normal session. 2533 return mEpdgMonitor.getEpdgAddressForNormalSession(); 2534 } 2535 return null; // no suitable ePDG address found. Select new ePDG address needed. 2536 } 2537 2538 TmHandler(Looper looper) { 2539 super(looper); 2540 } 2541 } 2542 2543 private void closeIkeSession(String apnName, IwlanError error) { 2544 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName); 2545 tunnelConfig.setError(error); 2546 tunnelConfig.getIkeSession().close(); 2547 } 2548 2549 private void selectEpdgAddress(TunnelSetupRequest setupRequest) { 2550 ++mTransactionId; 2551 mEpdgServerSelectionStartTime = System.currentTimeMillis(); 2552 2553 final int ipPreference = 2554 IwlanCarrierConfig.getConfigInt( 2555 mContext, 2556 mSlotId, 2557 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT); 2558 2559 IpPreferenceConflict ipPreferenceConflict = 2560 isIpPreferenceConflictsWithNetwork(ipPreference); 2561 if (ipPreferenceConflict.mIsConflict) { 2562 sendSelectionRequestComplete( 2563 null, new IwlanError(ipPreferenceConflict.mErrorType), mTransactionId); 2564 return; 2565 } 2566 2567 int protoFilter = EpdgSelector.PROTO_FILTER_IPV4V6; 2568 int epdgAddressOrder = EpdgSelector.SYSTEM_PREFERRED; 2569 switch (ipPreference) { 2570 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_PREFERRED: 2571 epdgAddressOrder = EpdgSelector.IPV4_PREFERRED; 2572 break; 2573 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_PREFERRED: 2574 epdgAddressOrder = EpdgSelector.IPV6_PREFERRED; 2575 break; 2576 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_ONLY: 2577 protoFilter = EpdgSelector.PROTO_FILTER_IPV4; 2578 break; 2579 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_ONLY: 2580 protoFilter = EpdgSelector.PROTO_FILTER_IPV6; 2581 break; 2582 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_SYSTEM_PREFERRED: 2583 break; 2584 default: 2585 Log.w(TAG, "Invalid Ip preference : " + ipPreference); 2586 } 2587 2588 IwlanError epdgError = 2589 mEpdgSelector.getValidatedServerList( 2590 mTransactionId, 2591 protoFilter, 2592 epdgAddressOrder, 2593 setupRequest.isRoaming(), 2594 setupRequest.isEmergency(), 2595 mDefaultNetwork, 2596 mSelectorCallback); 2597 2598 if (epdgError.getErrorType() != IwlanError.NO_ERROR) { 2599 Log.e(TAG, "Epdg address selection failed with error:" + epdgError); 2600 sendSelectionRequestComplete(null, epdgError, mTransactionId); 2601 } 2602 } 2603 2604 @VisibleForTesting 2605 int closePendingRequestsForApn(String apnName) { 2606 int numRequestsClosed = 0; 2607 int queueSize = mPendingBringUpRequests.size(); 2608 if (queueSize == 0) { 2609 return numRequestsClosed; 2610 } 2611 2612 for (int count = 0; count < queueSize; count++) { 2613 TunnelRequestWrapper requestWrapper = mPendingBringUpRequests.remove(); 2614 if (requestWrapper.getSetupRequest().apnName().equals(apnName)) { 2615 requestWrapper 2616 .getTunnelCallback() 2617 .onClosed( 2618 apnName, 2619 new IwlanError(IwlanError.NO_ERROR), 2620 new OnClosedMetrics.Builder() 2621 .setApnName(apnName) 2622 .setEpdgServerAddress(null) 2623 .build()); 2624 numRequestsClosed++; 2625 } else { 2626 mPendingBringUpRequests.add(requestWrapper); 2627 } 2628 } 2629 return numRequestsClosed; 2630 } 2631 2632 InetAddress validateAndSetEpdgAddressLegacy(List<InetAddress> selectorResultList) { 2633 List<InetAddress> addrList = mValidEpdgInfo.getAddrList(); 2634 if (addrList == null || !addrList.equals(selectorResultList)) { 2635 Log.d(TAG, "Update ePDG address list."); 2636 mValidEpdgInfo.setAddrList(selectorResultList); 2637 addrList = mValidEpdgInfo.getAddrList(); 2638 } 2639 2640 int index = mValidEpdgInfo.getIndex(); 2641 Log.d( 2642 TAG, 2643 "Valid ePDG Address List: " 2644 + Arrays.toString(addrList.toArray()) 2645 + ", index = " 2646 + index); 2647 mValidEpdgInfo.incrementIndex(); 2648 return addrList.get(index); 2649 } 2650 2651 @VisibleForTesting 2652 InetAddress validateAndSetEpdgAddress(List<InetAddress> selectorResultList) { 2653 if (!mFeatureFlags.epdgSelectionExcludeFailedIpAddress()) { 2654 return validateAndSetEpdgAddressLegacy(selectorResultList); 2655 } 2656 2657 if (mEpdgMonitor.hasEmergencyPdnFailedWithConnectedEpdg() 2658 && selectorResultList 2659 .get(0) 2660 .equals(mEpdgMonitor.getEpdgAddressForNormalSession())) { 2661 List<InetAddress> sublist = selectorResultList.subList(1, selectorResultList.size()); 2662 Log.d( 2663 TAG, 2664 "Selected separate ePDG address for emergency session " 2665 + sublist.get(0) 2666 + " from available ePDG address list: " 2667 + Arrays.toString(selectorResultList.toArray())); 2668 mValidEpdgInfo.setAddrList(sublist); 2669 return sublist.get(0); 2670 } 2671 2672 Log.d( 2673 TAG, 2674 "Selected first ePDG address " 2675 + selectorResultList.get(0) 2676 + " from available ePDG address list: " 2677 + Arrays.toString(selectorResultList.toArray())); 2678 mValidEpdgInfo.setAddrList(selectorResultList); 2679 return selectorResultList.get(0); 2680 } 2681 2682 private void serviceAllPendingRequests() { 2683 while (!mPendingBringUpRequests.isEmpty()) { 2684 Log.d(TAG, "serviceAllPendingRequests"); 2685 TunnelRequestWrapper requestWrapper = mPendingBringUpRequests.remove(); 2686 onBringUpTunnel(requestWrapper, mEpdgMonitor.getEpdgAddressForNormalSession()); 2687 } 2688 } 2689 2690 private void failAllPendingRequests(IwlanError error) { 2691 while (!mPendingBringUpRequests.isEmpty()) { 2692 Log.d(TAG, "failAllPendingRequests"); 2693 TunnelRequestWrapper request = mPendingBringUpRequests.remove(); 2694 TunnelSetupRequest setupRequest = request.getSetupRequest(); 2695 String apnName = setupRequest.apnName(); 2696 reportIwlanError(apnName, error); 2697 request.getTunnelCallback() 2698 .onClosed( 2699 apnName, 2700 error, 2701 new OnClosedMetrics.Builder() 2702 .setApnName(apnName) 2703 .setEpdgServerAddress(null) 2704 .build()); 2705 } 2706 } 2707 2708 // Prints mPendingBringUpRequests 2709 private void printRequestQueue(String info) { 2710 Log.d(TAG, info); 2711 Log.d( 2712 TAG, 2713 "mPendingBringUpRequests: " + Arrays.toString(mPendingBringUpRequests.toArray())); 2714 } 2715 2716 // Update Network wrapper 2717 private static final class UpdateNetworkWrapper { 2718 private final Network mNetwork; 2719 private final LinkProperties mLinkProperties; 2720 2721 private UpdateNetworkWrapper(Network network, LinkProperties linkProperties) { 2722 mNetwork = network; 2723 mLinkProperties = linkProperties; 2724 } 2725 2726 public Network getNetwork() { 2727 return mNetwork; 2728 } 2729 2730 public LinkProperties getLinkProperties() { 2731 return mLinkProperties; 2732 } 2733 } 2734 2735 // Tunnel request + tunnel callback 2736 private static final class TunnelRequestWrapper { 2737 private final TunnelSetupRequest mSetupRequest; 2738 private final TunnelCallback mTunnelCallback; 2739 2740 private TunnelRequestWrapper( 2741 TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback) { 2742 mTunnelCallback = tunnelCallback; 2743 mSetupRequest = setupRequest; 2744 } 2745 2746 public TunnelSetupRequest getSetupRequest() { 2747 return mSetupRequest; 2748 } 2749 2750 public TunnelCallback getTunnelCallback() { 2751 return mTunnelCallback; 2752 } 2753 } 2754 2755 private static final class TunnelBringdownRequest { 2756 final String mApnName; 2757 final boolean mForceClose; 2758 final TunnelCallback mTunnelCallback; 2759 final int mBringDownReason; 2760 2761 private TunnelBringdownRequest( 2762 String apnName, 2763 boolean forceClose, 2764 TunnelCallback tunnelCallback, 2765 @TunnelBringDownReason int reason) { 2766 mApnName = apnName; 2767 mForceClose = forceClose; 2768 mTunnelCallback = tunnelCallback; 2769 mBringDownReason = reason; 2770 } 2771 } 2772 2773 private static final class EpdgSelectorResult { 2774 private final List<InetAddress> mValidIpList; 2775 2776 public List<InetAddress> getValidIpList() { 2777 return mValidIpList; 2778 } 2779 2780 public IwlanError getEpdgError() { 2781 return mEpdgError; 2782 } 2783 2784 public int getTransactionId() { 2785 return mTransactionId; 2786 } 2787 2788 private final IwlanError mEpdgError; 2789 private final int mTransactionId; 2790 2791 private EpdgSelectorResult( 2792 List<InetAddress> validIpList, IwlanError epdgError, int transactionId) { 2793 mValidIpList = validIpList; 2794 mEpdgError = epdgError; 2795 mTransactionId = transactionId; 2796 } 2797 } 2798 2799 // Data received from IkeSessionStateMachine on successful EVENT_CHILD_SESSION_OPENED. 2800 private static final class TunnelOpenedData extends IkeEventData { 2801 final List<InetAddress> mInternalDnsServers; 2802 final List<LinkAddress> mInternalAddresses; 2803 2804 private TunnelOpenedData( 2805 String apnName, 2806 int token, 2807 List<InetAddress> internalDnsServers, 2808 List<LinkAddress> internalAddresses) { 2809 super(apnName, token); 2810 mInternalDnsServers = internalDnsServers; 2811 mInternalAddresses = internalAddresses; 2812 } 2813 } 2814 2815 // Data received from IkeSessionStateMachine on successful EVENT_IKE_SESSION_OPENED. 2816 private static final class IkeSessionOpenedData extends IkeEventData { 2817 final IkeSessionConfiguration mIkeSessionConfiguration; 2818 2819 private IkeSessionOpenedData( 2820 String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration) { 2821 super(apnName, token); 2822 mIkeSessionConfiguration = ikeSessionConfiguration; 2823 } 2824 } 2825 2826 private static final class IkeSessionConnectionInfoData extends IkeEventData { 2827 final IkeSessionConnectionInfo mIkeSessionConnectionInfo; 2828 2829 private IkeSessionConnectionInfoData( 2830 String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo) { 2831 super(apnName, token); 2832 mIkeSessionConnectionInfo = ikeSessionConnectionInfo; 2833 } 2834 } 2835 2836 private static final class Ike3gppDataReceived extends IkeEventData { 2837 final List<Ike3gppData> mIke3gppData; 2838 2839 private Ike3gppDataReceived(String apnName, int token, List<Ike3gppData> ike3gppData) { 2840 super(apnName, token); 2841 mIke3gppData = ike3gppData; 2842 } 2843 } 2844 2845 // Data received from IkeSessionStateMachine if either IKE session or Child session have been 2846 // closed, normally or exceptionally. 2847 private static final class SessionClosedData extends IkeEventData { 2848 final IkeException mIkeException; 2849 2850 private SessionClosedData(String apnName, int token, IkeException ikeException) { 2851 super(apnName, token); 2852 mIkeException = ikeException; 2853 } 2854 } 2855 2856 private static final class IkeSessionValidationStatusData extends IkeEventData { 2857 @NetworkValidationStatus final int mStatus; 2858 2859 private IkeSessionValidationStatusData(String apnName, int token, int status) { 2860 super(apnName, token); 2861 mStatus = status; 2862 } 2863 } 2864 2865 private static final class IpsecTransformData extends IkeEventData { 2866 private final IpSecTransform mTransform; 2867 private final int mDirection; 2868 2869 private IpsecTransformData( 2870 IpSecTransform transform, int direction, String apnName, int token) { 2871 super(apnName, token); 2872 mTransform = transform; 2873 mDirection = direction; 2874 } 2875 2876 public IpSecTransform getTransform() { 2877 return mTransform; 2878 } 2879 2880 public int getDirection() { 2881 return mDirection; 2882 } 2883 2884 public String getApnName() { 2885 return super.mApnName; 2886 } 2887 } 2888 2889 private abstract static class IkeEventData { 2890 final String mApnName; 2891 final int mToken; 2892 2893 private IkeEventData(String apnName, int token) { 2894 mApnName = apnName; 2895 mToken = token; 2896 } 2897 } 2898 2899 private static final class EpdgInfo { 2900 private List<InetAddress> mAddrList; 2901 private int mIndex; 2902 2903 private EpdgInfo() { 2904 mAddrList = null; 2905 mIndex = 0; 2906 } 2907 2908 public List<InetAddress> getAddrList() { 2909 return mAddrList; 2910 } 2911 2912 public void setAddrList(@NonNull List<InetAddress> AddrList) { 2913 mAddrList = AddrList; 2914 resetIndex(); 2915 } 2916 2917 public int getIndex() { 2918 return mIndex; 2919 } 2920 2921 public void incrementIndex() { 2922 if (getIndex() >= getAddrList().size() - 1) { 2923 resetIndex(); 2924 } else { 2925 mIndex++; 2926 } 2927 } 2928 2929 public void resetIndex() { 2930 mIndex = 0; 2931 } 2932 } 2933 2934 private static class IpPreferenceConflict { 2935 final boolean mIsConflict; 2936 final int mErrorType; 2937 2938 private IpPreferenceConflict(boolean isConflict, int errorType) { 2939 mIsConflict = isConflict; 2940 mErrorType = errorType; 2941 } 2942 2943 private IpPreferenceConflict() { 2944 mIsConflict = false; 2945 mErrorType = IwlanError.NO_ERROR; 2946 } 2947 } 2948 2949 private int[] getRetransmissionTimeoutsFromConfig() { 2950 int[] timeList = 2951 IwlanCarrierConfig.getConfigIntArray( 2952 mContext, 2953 mSlotId, 2954 CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY); 2955 boolean isValid = 2956 timeList != null 2957 && timeList.length != 0 2958 && timeList.length <= IKE_RETRANS_MAX_ATTEMPTS_MAX; 2959 for (int time : Objects.requireNonNull(timeList)) { 2960 if (time < IKE_RETRANS_TIMEOUT_MS_MIN || time > IKE_RETRANS_TIMEOUT_MS_MAX) { 2961 isValid = false; 2962 break; 2963 } 2964 } 2965 if (!isValid) { 2966 timeList = 2967 IwlanCarrierConfig.getDefaultConfigIntArray( 2968 CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY); 2969 } 2970 Log.d(TAG, "getRetransmissionTimeoutsFromConfig: " + Arrays.toString(timeList)); 2971 return timeList; 2972 } 2973 2974 private int getDpdDelayFromConfig() { 2975 int dpdDelay = 2976 IwlanCarrierConfig.getConfigInt( 2977 mContext, mSlotId, CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT); 2978 if (dpdDelay < IKE_DPD_DELAY_SEC_MIN || dpdDelay > IKE_DPD_DELAY_SEC_MAX) { 2979 dpdDelay = 2980 IwlanCarrierConfig.getDefaultConfigInt( 2981 CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT); 2982 } 2983 return dpdDelay; 2984 } 2985 2986 /** 2987 * Decodes backoff time as per TS 124 008 10.5.7.4a Bits 5 to 1 represent the binary coded timer 2988 * value 2989 * 2990 * <p>Bits 6 to 8 defines the timer value unit for the GPRS timer as follows: Bits 8 7 6 0 0 0 2991 * value is incremented in multiples of 10 minutes 0 0 1 value is incremented in multiples of 1 2992 * hour 0 1 0 value is incremented in multiples of 10 hours 0 1 1 value is incremented in 2993 * multiples of 2 seconds 1 0 0 value is incremented in multiples of 30 seconds 1 0 1 value is 2994 * incremented in multiples of 1 minute 1 1 0 value is incremented in multiples of 1 hour 1 1 1 2995 * value indicates that the timer is deactivated. 2996 * 2997 * @param backoffTimeByte Byte value obtained from ike 2998 * @return long time value in seconds. -1 if the timer needs to be deactivated. 2999 */ 3000 private static long decodeBackoffTime(byte backoffTimeByte) { 3001 final int BACKOFF_TIME_VALUE_MASK = 0x1F; 3002 final int BACKOFF_TIMER_UNIT_MASK = 0xE0; 3003 final Long[] BACKOFF_TIMER_UNIT_INCREMENT_SECS = { 3004 10L * 60L, // 10 minutes 3005 60L * 60L, // 1 hour 3006 10L * 60L * 60L, // 10 hours 3007 2L, // 2 seconds 3008 30L, // 30 seconds 3009 60L, // 1 minute 3010 60L * 60L, // 1 hour 3011 }; 3012 3013 long time = backoffTimeByte & BACKOFF_TIME_VALUE_MASK; 3014 int timerUnit = (backoffTimeByte & BACKOFF_TIMER_UNIT_MASK) >> 5; 3015 if (timerUnit >= BACKOFF_TIMER_UNIT_INCREMENT_SECS.length) { 3016 return -1; 3017 } 3018 time *= BACKOFF_TIMER_UNIT_INCREMENT_SECS[timerUnit]; 3019 return time; 3020 } 3021 3022 @VisibleForTesting 3023 String getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest) { 3024 return setupRequest.apnName(); 3025 } 3026 3027 @VisibleForTesting 3028 void putApnNameToTunnelConfig( 3029 String apnName, 3030 IkeSession ikeSession, 3031 TunnelCallback tunnelCallback, 3032 IpSecManager.IpSecTunnelInterface iface, 3033 InetAddress srcIpv6Addr, 3034 int srcIPv6AddrPrefixLen, 3035 boolean isEmergency, 3036 InetAddress epdgAddress) { 3037 mApnNameToTunnelConfig.put( 3038 apnName, 3039 new TunnelConfig( 3040 ikeSession, 3041 tunnelCallback, 3042 iface, 3043 srcIpv6Addr, 3044 srcIPv6AddrPrefixLen, 3045 isEmergency, 3046 epdgAddress)); 3047 Log.d(TAG, "Added APN: " + apnName + " to TunnelConfig"); 3048 } 3049 3050 @VisibleForTesting 3051 int incrementAndGetCurrentTokenForApn(String apnName) { 3052 final int currentToken = 3053 mApnNameToCurrentToken.compute( 3054 apnName, (apn, token) -> token == null ? 0 : token + 1); 3055 Log.d(TAG, "Added token: " + currentToken + " for apn: " + apnName); 3056 return currentToken; 3057 } 3058 3059 @VisibleForTesting 3060 boolean isTunnelConfigContainExistApn(String apnName) { 3061 return mApnNameToTunnelConfig.containsKey(apnName); 3062 } 3063 3064 @VisibleForTesting 3065 List<InetAddress> getAddressForNetwork(Network network) { 3066 return IwlanHelper.getAllAddressesForNetwork(mContext, network); 3067 } 3068 3069 @VisibleForTesting 3070 IkeSessionCreator getIkeSessionCreator() { 3071 return mIkeSessionCreator; 3072 } 3073 3074 @VisibleForTesting 3075 void sendSelectionRequestComplete( 3076 List<InetAddress> validIPList, IwlanError result, int transactionId) { 3077 mEpdgServerSelectionDuration = System.currentTimeMillis() - mEpdgServerSelectionStartTime; 3078 mEpdgServerSelectionStartTime = 0; 3079 EpdgSelectorResult epdgSelectorResult = 3080 new EpdgSelectorResult(validIPList, result, transactionId); 3081 mHandler.obtainMessage(EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE, epdgSelectorResult) 3082 .sendToTarget(); 3083 } 3084 3085 static boolean isValidApnProtocol(int proto) { 3086 return (proto == ApnSetting.PROTOCOL_IP 3087 || proto == ApnSetting.PROTOCOL_IPV4V6 3088 || proto == ApnSetting.PROTOCOL_IPV6); 3089 } 3090 3091 boolean isObsoleteToken(String apnName, int token) { 3092 if (!mApnNameToCurrentToken.containsKey(apnName)) { 3093 return true; 3094 } 3095 return token != mApnNameToCurrentToken.get(apnName); 3096 } 3097 3098 private static String eventToString(int event) { 3099 return switch (event) { 3100 case EVENT_TUNNEL_BRINGUP_REQUEST -> "EVENT_TUNNEL_BRINGUP_REQUEST"; 3101 case EVENT_TUNNEL_BRINGDOWN_REQUEST -> "EVENT_TUNNEL_BRINGDOWN_REQUEST"; 3102 case EVENT_CHILD_SESSION_OPENED -> "EVENT_CHILD_SESSION_OPENED"; 3103 case EVENT_CHILD_SESSION_CLOSED -> "EVENT_CHILD_SESSION_CLOSED"; 3104 case EVENT_IKE_SESSION_CLOSED -> "EVENT_IKE_SESSION_CLOSED"; 3105 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE -> 3106 "EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE"; 3107 case EVENT_IPSEC_TRANSFORM_CREATED -> "EVENT_IPSEC_TRANSFORM_CREATED"; 3108 case EVENT_IPSEC_TRANSFORM_DELETED -> "EVENT_IPSEC_TRANSFORM_DELETED"; 3109 case EVENT_UPDATE_NETWORK -> "EVENT_UPDATE_NETWORK"; 3110 case EVENT_IKE_SESSION_OPENED -> "EVENT_IKE_SESSION_OPENED"; 3111 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED -> 3112 "EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED"; 3113 case EVENT_IKE_3GPP_DATA_RECEIVED -> "EVENT_IKE_3GPP_DATA_RECEIVED"; 3114 case EVENT_IKE_LIVENESS_STATUS_CHANGED -> "EVENT_IKE_LIVENESS_STATUS_CHANGED"; 3115 case EVENT_REQUEST_NETWORK_VALIDATION_CHECK -> "EVENT_REQUEST_NETWORK_VALIDATION_CHECK"; 3116 default -> "Unknown(" + event + ")"; 3117 }; 3118 } 3119 3120 @VisibleForTesting 3121 TmIkeSessionCallback getTmIkeSessionCallback(String apnName, int token) { 3122 return new TmIkeSessionCallback(apnName, token); 3123 } 3124 3125 @VisibleForTesting 3126 void onConnectedToEpdg(boolean hasConnected) { 3127 mHasConnectedToEpdg = hasConnected; 3128 if (mHasConnectedToEpdg) { 3129 mIkeSessionNetwork = mDefaultNetwork; 3130 } else { 3131 mIkeSessionNetwork = null; 3132 } 3133 } 3134 3135 @VisibleForTesting 3136 TunnelConfig getTunnelConfigForApn(String apnName) { 3137 return mApnNameToTunnelConfig.get(apnName); 3138 } 3139 3140 @VisibleForTesting 3141 int getCurrentTokenForApn(String apnName) { 3142 if (!mApnNameToCurrentToken.containsKey(apnName)) { 3143 throw new IllegalArgumentException("There is no token for apn: " + apnName); 3144 } 3145 return mApnNameToCurrentToken.get(apnName); 3146 } 3147 3148 @VisibleForTesting 3149 long reportIwlanError(String apnName, IwlanError error) { 3150 triggerUnderlyingNetworkValidationOnError(error); 3151 return ErrorPolicyManager.getInstance(mContext, mSlotId).reportIwlanError(apnName, error); 3152 } 3153 3154 @VisibleForTesting 3155 long reportIwlanError(String apnName, IwlanError error, long backOffTime) { 3156 triggerUnderlyingNetworkValidationOnError(error); 3157 return ErrorPolicyManager.getInstance(mContext, mSlotId) 3158 .reportIwlanError(apnName, error, backOffTime); 3159 } 3160 3161 @VisibleForTesting 3162 IwlanError getLastError(String apnName) { 3163 return ErrorPolicyManager.getInstance(mContext, mSlotId).getLastError(apnName); 3164 } 3165 3166 @VisibleForTesting 3167 IwlanError canBringUpTunnel(String apnName, boolean isEmergency) { 3168 IwlanError bringUpError = null; 3169 if (IwlanHelper.getSubId(mContext, mSlotId) 3170 == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 3171 Log.e(TAG, "SIM isn't ready"); 3172 bringUpError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION); 3173 reportIwlanError(apnName, bringUpError); 3174 } else if (Objects.isNull(mDefaultNetwork)) { 3175 Log.e(TAG, "The default network is not ready"); 3176 bringUpError = new IwlanError(IwlanError.IKE_INTERNAL_IO_EXCEPTION); 3177 reportIwlanError(apnName, bringUpError); 3178 } else if (!isEmergency 3179 && !ErrorPolicyManager.getInstance(mContext, mSlotId).canBringUpTunnel(apnName)) { 3180 // TODO(b/343962773): Need to refactor emergency condition into ErrorPolicyManager 3181 Log.d(TAG, "Cannot bring up tunnel as retry time has not passed"); 3182 bringUpError = getLastError(apnName); 3183 } 3184 return bringUpError; 3185 } 3186 3187 @VisibleForTesting 3188 IpPreferenceConflict isIpPreferenceConflictsWithNetwork( 3189 @CarrierConfigManager.Iwlan.EpdgAddressIpPreference int ipPreference) { 3190 List<InetAddress> localAddresses = getAddressForNetwork(mDefaultNetwork); 3191 if (localAddresses == null || localAddresses.size() == 0) { 3192 Log.e(TAG, "No local addresses available for Network " + mDefaultNetwork); 3193 return new IpPreferenceConflict(true, IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED); 3194 } else if (!IwlanHelper.hasIpv6Address(localAddresses) 3195 && ipPreference == CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_ONLY) { 3196 Log.e( 3197 TAG, 3198 "ePDG IP preference: " 3199 + ipPreference 3200 + " conflicts with source IP type: " 3201 + EpdgSelector.PROTO_FILTER_IPV4); 3202 return new IpPreferenceConflict(true, IwlanError.EPDG_ADDRESS_ONLY_IPV6_ALLOWED); 3203 } else if (!IwlanHelper.hasIpv4Address(localAddresses) 3204 && ipPreference == CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_ONLY) { 3205 // b/209938719 allows Iwlan to support VoWiFi for IPv4 ePDG server while on IPv6 WiFi. 3206 // Iwlan will receive a IPv4 address which is embedded in stacked IPv6 address. By using 3207 // this IPv4 address, UE will connect to IPv4 ePDG server through XLAT. However, there 3208 // are issues on connecting ePDG server through XLAT. Will allow IPV4_ONLY on IPv6 WiFi 3209 // after the issues are resolved. 3210 Log.e( 3211 TAG, 3212 "ePDG IP preference: " 3213 + ipPreference 3214 + " conflicts with source IP type: " 3215 + EpdgSelector.PROTO_FILTER_IPV6); 3216 return new IpPreferenceConflict(true, IwlanError.EPDG_ADDRESS_ONLY_IPV4_ALLOWED); 3217 } 3218 return new IpPreferenceConflict(); 3219 } 3220 3221 private boolean isUnderlyingNetworkValidated(Network network) { 3222 if (network == null) return false; 3223 3224 ConnectivityManager connectivityManager = 3225 Objects.requireNonNull(mContext).getSystemService(ConnectivityManager.class); 3226 NetworkCapabilities networkCapabilities = 3227 connectivityManager.getNetworkCapabilities(network); 3228 return (networkCapabilities != null) 3229 && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); 3230 } 3231 3232 /** 3233 * Trigger network validation on the underlying network if needed to possibly update validation 3234 * status and cause system switch default network. 3235 */ 3236 void triggerUnderlyingNetworkValidationOnError(IwlanError error) { 3237 if (!isUnderlyingNetworkValidationRequired(error.getErrorType())) { 3238 return; 3239 } 3240 3241 Log.d(TAG, "On triggering underlying network validation. Cause: " + error); 3242 validateUnderlyingNetwork(IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_NO_RESPONSE); 3243 } 3244 3245 public void validateUnderlyingNetwork(@IwlanCarrierConfig.NetworkValidationEvent int event) { 3246 int[] networkValidationEvents = 3247 IwlanCarrierConfig.getConfigIntArray( 3248 mContext, 3249 mSlotId, 3250 IwlanCarrierConfig.KEY_UNDERLYING_NETWORK_VALIDATION_EVENTS_INT_ARRAY); 3251 if (Arrays.stream(networkValidationEvents) 3252 .noneMatch(validationEvent -> validationEvent == event)) { 3253 return; 3254 } 3255 synchronized (sLastUnderlyingNetworkValidationLock) { 3256 long now = IwlanHelper.elapsedRealtime(); 3257 // TODO (b/356791418): Consolidate underlying network handling into a single centralized 3258 // subcomponent to prevent duplicate processing across different threads and classes 3259 // . Until then, we will prevent sending duplicate network validations by checking 3260 // the recent trigger time. 3261 if (now - sLastUnderlyingNetworkValidationMs > NETWORK_VALIDATION_MIN_INTERVAL_MS) { 3262 sLastUnderlyingNetworkValidationMs = now; 3263 Log.d( 3264 TAG, 3265 "On triggering underlying network validation. Event: " 3266 + IwlanCarrierConfig.getUnderlyingNetworkValidationEventString( 3267 event)); 3268 mHandler.post(() -> onTriggerUnderlyingNetworkValidation(event)); 3269 } 3270 } 3271 } 3272 3273 private void onTriggerUnderlyingNetworkValidation(int event) { 3274 if (mDefaultNetwork == null) return; 3275 3276 setupValidationMetricsAtom(mDefaultNetwork, event); 3277 3278 if (!isUnderlyingNetworkValidated(mDefaultNetwork)) { 3279 Log.d(TAG, "Network " + mDefaultNetwork + " is already not validated."); 3280 reportValidationMetricsAtom( 3281 mDefaultNetwork, 3282 NETWORK_VALIDATION_RESULT_INVALID, 3283 /* validationTriggered */ false); 3284 return; 3285 } 3286 3287 ConnectivityManager connectivityManager = 3288 Objects.requireNonNull(mContext).getSystemService(ConnectivityManager.class); 3289 Log.d(TAG, "Trigger underlying network validation on network: " + mDefaultNetwork); 3290 Objects.requireNonNull(connectivityManager) 3291 .reportNetworkConnectivity(mDefaultNetwork, false); 3292 } 3293 3294 private void setupValidationMetricsAtom(@NonNull Network network, int event) { 3295 MetricsAtom metricsAtom = new MetricsAtom(); 3296 metricsAtom.setMessageId(IwlanStatsLog.IWLAN_UNDERLYING_NETWORK_VALIDATION_RESULT_REPORTED); 3297 metricsAtom.setTriggerReason(getMetricsTriggerReason(event)); 3298 3299 ConnectivityManager connectivityManager = 3300 Objects.requireNonNull(mContext).getSystemService(ConnectivityManager.class); 3301 NetworkCapabilities networkCapabilities = 3302 Objects.requireNonNull(connectivityManager).getNetworkCapabilities(mDefaultNetwork); 3303 int validationTransportType = NETWORK_VALIDATION_TRANSPORT_TYPE_UNSPECIFIED; 3304 if (networkCapabilities != null) { 3305 if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 3306 validationTransportType = NETWORK_VALIDATION_TRANSPORT_TYPE_CELLULAR; 3307 } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 3308 validationTransportType = NETWORK_VALIDATION_TRANSPORT_TYPE_WIFI; 3309 } 3310 } 3311 metricsAtom.setValidationTransportType(validationTransportType); 3312 3313 metricsAtom.setValidationStartTimeMills(IwlanHelper.elapsedRealtime()); 3314 mMetricsAtomForNetwork.put(network, metricsAtom); 3315 } 3316 3317 boolean isUnderlyingNetworkValidationRequired(int error) { 3318 return switch (error) { 3319 case IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED, 3320 IwlanError.IKE_NETWORK_LOST_EXCEPTION, 3321 IwlanError.IKE_INIT_TIMEOUT, 3322 IwlanError.IKE_MOBILITY_TIMEOUT, 3323 IwlanError.IKE_DPD_TIMEOUT -> 3324 true; 3325 default -> false; 3326 }; 3327 } 3328 3329 private int getMetricsValidationResult(int validationResult) { 3330 return switch (validationResult) { 3331 case ConnectivityReport.NETWORK_VALIDATION_RESULT_INVALID -> 3332 NETWORK_VALIDATION_RESULT_INVALID; 3333 case ConnectivityReport.NETWORK_VALIDATION_RESULT_VALID -> 3334 NETWORK_VALIDATION_RESULT_VALID; 3335 case ConnectivityReport.NETWORK_VALIDATION_RESULT_PARTIALLY_VALID -> 3336 NETWORK_VALIDATION_RESULT_PARTIALLY_VALID; 3337 case ConnectivityReport.NETWORK_VALIDATION_RESULT_SKIPPED -> 3338 NETWORK_VALIDATION_RESULT_SKIPPED; 3339 default -> NETWORK_VALIDATION_RESULT_UNSPECIFIED; 3340 }; 3341 } 3342 3343 private int getMetricsTriggerReason(int reason) { 3344 return switch (reason) { 3345 case IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_MAKING_CALL -> 3346 NETWORK_VALIDATION_EVENT_MAKING_CALL; 3347 case IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_SCREEN_ON -> 3348 NETWORK_VALIDATION_EVENT_SCREEN_ON; 3349 case IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_NO_RESPONSE -> 3350 NETWORK_VALIDATION_EVENT_NO_RESPONSE; 3351 default -> NETWORK_VALIDATION_EVENT_UNSPECIFIED; 3352 }; 3353 } 3354 3355 /** 3356 * Performs network validation check 3357 * 3358 * @param apnName APN for which to perform validation check 3359 */ 3360 public void requestNetworkValidationForApn(String apnName) { 3361 mHandler.obtainMessage(EVENT_REQUEST_NETWORK_VALIDATION_CHECK, apnName).sendToTarget(); 3362 } 3363 3364 @VisibleForTesting 3365 protected void removeApnNameInTunnelConfig(String apnName) { 3366 mApnNameToTunnelConfig.remove(apnName); 3367 } 3368 3369 public void prefetchEpdgServerList(Network network, boolean isRoaming) { 3370 mEpdgSelector.getValidatedServerList( 3371 0 /* transactionId */, 3372 EpdgSelector.PROTO_FILTER_IPV4V6, 3373 EpdgSelector.SYSTEM_PREFERRED, 3374 isRoaming, 3375 false /* isEmergency */, 3376 network, 3377 null /* selectorCallback */); 3378 mEpdgSelector.getValidatedServerList( 3379 0 /* transactionId */, 3380 EpdgSelector.PROTO_FILTER_IPV4V6, 3381 EpdgSelector.SYSTEM_PREFERRED, 3382 isRoaming, 3383 true /* isEmergency */, 3384 network, 3385 null /* selectorCallback */); 3386 } 3387 3388 public void close() { 3389 mTunnelManagerInstances.remove(mSlotId); 3390 unregisterConnectivityDiagnosticsCallback(); 3391 } 3392 3393 public void dump(PrintWriter pw) { 3394 pw.println("---- EpdgTunnelManager ----"); 3395 pw.println( 3396 "Has ePDG connected for normal session: " 3397 + mEpdgMonitor.hasEpdgConnectedForNormalSession()); 3398 pw.println( 3399 "Has Separate ePDG connected for emergency session: " 3400 + mEpdgMonitor.hasSeparateEpdgConnectedForEmergencySession()); 3401 pw.println("mIkeSessionNetwork: " + mIkeSessionNetwork); 3402 if (mEpdgMonitor.getEpdgAddressForNormalSession() != null) { 3403 pw.println( 3404 "EpdgAddressForNormalSession: " 3405 + mEpdgMonitor.getEpdgAddressForNormalSession()); 3406 } 3407 if (mEpdgMonitor.getEpdgAddressForEmergencySession() != null) { 3408 pw.println( 3409 "SeparateEpdgAddressForEmergencySession: " 3410 + mEpdgMonitor.getEpdgAddressForEmergencySession()); 3411 } 3412 pw.println("mApnNameToTunnelConfig:\n"); 3413 for (Map.Entry<String, TunnelConfig> entry : mApnNameToTunnelConfig.entrySet()) { 3414 pw.println("APN: " + entry.getKey()); 3415 pw.println("TunnelConfig: " + entry.getValue()); 3416 pw.println(); 3417 } 3418 pw.println("---------------------------"); 3419 } 3420 } 3421