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.system.OsConstants.AF_INET; 22 import static android.system.OsConstants.AF_INET6; 23 24 import android.content.Context; 25 import android.net.ConnectivityManager; 26 import android.net.InetAddresses; 27 import android.net.IpPrefix; 28 import android.net.IpSecManager; 29 import android.net.IpSecTransform; 30 import android.net.LinkAddress; 31 import android.net.Network; 32 import android.net.eap.EapAkaInfo; 33 import android.net.eap.EapInfo; 34 import android.net.eap.EapSessionConfig; 35 import android.net.ipsec.ike.ChildSaProposal; 36 import android.net.ipsec.ike.ChildSessionCallback; 37 import android.net.ipsec.ike.ChildSessionConfiguration; 38 import android.net.ipsec.ike.ChildSessionParams; 39 import android.net.ipsec.ike.IkeFqdnIdentification; 40 import android.net.ipsec.ike.IkeIdentification; 41 import android.net.ipsec.ike.IkeKeyIdIdentification; 42 import android.net.ipsec.ike.IkeRfc822AddrIdentification; 43 import android.net.ipsec.ike.IkeSaProposal; 44 import android.net.ipsec.ike.IkeSession; 45 import android.net.ipsec.ike.IkeSessionCallback; 46 import android.net.ipsec.ike.IkeSessionConfiguration; 47 import android.net.ipsec.ike.IkeSessionConnectionInfo; 48 import android.net.ipsec.ike.IkeSessionParams; 49 import android.net.ipsec.ike.IkeTrafficSelector; 50 import android.net.ipsec.ike.SaProposal; 51 import android.net.ipsec.ike.TunnelModeChildSessionParams; 52 import android.net.ipsec.ike.exceptions.IkeException; 53 import android.net.ipsec.ike.exceptions.IkeProtocolException; 54 import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer; 55 import android.net.ipsec.ike.ike3gpp.Ike3gppData; 56 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension; 57 import android.net.ipsec.ike.ike3gpp.Ike3gppN1ModeInformation; 58 import android.net.ipsec.ike.ike3gpp.Ike3gppParams; 59 import android.os.Handler; 60 import android.os.HandlerThread; 61 import android.os.Looper; 62 import android.os.Message; 63 import android.support.annotation.NonNull; 64 import android.support.annotation.Nullable; 65 import android.telephony.CarrierConfigManager; 66 import android.telephony.SubscriptionManager; 67 import android.telephony.TelephonyManager; 68 import android.telephony.data.ApnSetting; 69 import android.telephony.data.NetworkSliceInfo; 70 import android.util.Log; 71 72 import com.android.internal.annotations.VisibleForTesting; 73 74 import com.google.android.iwlan.ErrorPolicyManager; 75 import com.google.android.iwlan.IwlanError; 76 import com.google.android.iwlan.IwlanHelper; 77 import com.google.android.iwlan.exceptions.IwlanSimNotReadyException; 78 79 import java.io.FileDescriptor; 80 import java.io.IOException; 81 import java.io.PrintWriter; 82 import java.net.Inet4Address; 83 import java.net.Inet6Address; 84 import java.net.InetAddress; 85 import java.nio.charset.StandardCharsets; 86 import java.util.ArrayList; 87 import java.util.Arrays; 88 import java.util.Collections; 89 import java.util.HashSet; 90 import java.util.LinkedList; 91 import java.util.List; 92 import java.util.Map; 93 import java.util.Queue; 94 import java.util.Set; 95 import java.util.concurrent.ConcurrentHashMap; 96 import java.util.concurrent.Executor; 97 import java.util.concurrent.Executors; 98 import java.util.concurrent.TimeUnit; 99 100 public class EpdgTunnelManager { 101 102 private Context mContext; 103 private final int mSlotId; 104 private HandlerThread mHandlerThread; 105 private Handler mHandler; 106 107 private static final int EVENT_TUNNEL_BRINGUP_REQUEST = 0; 108 private static final int EVENT_TUNNEL_BRINGDOWN_REQUEST = 1; 109 private static final int EVENT_CHILD_SESSION_OPENED = 2; 110 private static final int EVENT_CHILD_SESSION_CLOSED = 3; 111 private static final int EVENT_IKE_SESSION_CLOSED = 5; 112 private static final int EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE = 6; 113 private static final int EVENT_IPSEC_TRANSFORM_CREATED = 7; 114 private static final int EVENT_IPSEC_TRANSFORM_DELETED = 8; 115 private static final int EVENT_UPDATE_NETWORK = 9; 116 private static final int EVENT_IKE_SESSION_OPENED = 10; 117 private static final int EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED = 11; 118 private static final int IKE_HARD_LIFETIME_SEC_MINIMUM = 300; 119 private static final int IKE_HARD_LIFETIME_SEC_MAXIMUM = 86400; 120 private static final int IKE_SOFT_LIFETIME_SEC_MINIMUM = 120; 121 private static final int CHILD_HARD_LIFETIME_SEC_MINIMUM = 300; 122 private static final int CHILD_HARD_LIFETIME_SEC_MAXIMUM = 14400; 123 private static final int CHILD_SOFT_LIFETIME_SEC_MINIMUM = 120; 124 private static final int LIFETIME_MARGIN_SEC_MINIMUM = (int) TimeUnit.MINUTES.toSeconds(1L); 125 private static final int IKE_RETRANS_TIMEOUT_MS_MIN = 500; 126 127 private static final int IKE_RETRANS_TIMEOUT_MS_MAX = (int) TimeUnit.MINUTES.toMillis(30L); 128 129 private static final int IKE_RETRANS_MAX_ATTEMPTS_MAX = 10; 130 private static final int IKE_DPD_DELAY_SEC_MIN = 20; 131 private static final int IKE_DPD_DELAY_SEC_MAX = 1800; // 30 minutes 132 private static final int NATT_KEEPALIVE_DELAY_SEC_MIN = 10; 133 private static final int NATT_KEEPALIVE_DELAY_SEC_MAX = 120; 134 135 private static final int DEVICE_IMEI_LEN = 15; 136 private static final int DEVICE_IMEISV_SUFFIX_LEN = 2; 137 138 private static final int TRAFFIC_SELECTOR_START_PORT = 0; 139 private static final int TRAFFIC_SELECTOR_END_PORT = 65535; 140 private static final String TRAFFIC_SELECTOR_IPV4_START_ADDR = "0.0.0.0"; 141 private static final String TRAFFIC_SELECTOR_IPV4_END_ADDR = "255.255.255.255"; 142 private static final String TRAFFIC_SELECTOR_IPV6_START_ADDR = "::"; 143 private static final String TRAFFIC_SELECTOR_IPV6_END_ADDR = 144 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; 145 146 private static Map<Integer, EpdgTunnelManager> mTunnelManagerInstances = 147 new ConcurrentHashMap<>(); 148 149 private Queue<TunnelRequestWrapper> mPendingBringUpRequests = new LinkedList<>(); 150 151 private EpdgInfo mValidEpdgInfo = new EpdgInfo(); 152 private InetAddress mEpdgAddress; 153 private Network mNetwork; 154 private int mTransactionId = 0; 155 private int mProtoFilter = EpdgSelector.PROTO_FILTER_IPV4V6; 156 private boolean mIsEpdgAddressSelected; 157 private IkeSessionCreator mIkeSessionCreator; 158 159 private Map<String, TunnelConfig> mApnNameToTunnelConfig = new ConcurrentHashMap<>(); 160 private Map<String, Integer> mApnNameToCurrentToken = new ConcurrentHashMap<>(); 161 162 private final String TAG; 163 164 private List<InetAddress> mLocalAddresses; 165 166 @Nullable private byte[] mNextReauthId = null; 167 private long mEpdgServerSelectionDuration = 0; 168 private long mEpdgServerSelectionStartTime = 0; 169 private long mIkeTunnelEstablishmentDuration = 0; 170 private long mIkeTunnelEstablishmentStartTime = 0; 171 172 private static final Set<Integer> VALID_DH_GROUPS; 173 private static final Set<Integer> VALID_KEY_LENGTHS; 174 private static final Set<Integer> VALID_PRF_ALGOS; 175 private static final Set<Integer> VALID_INTEGRITY_ALGOS; 176 private static final Set<Integer> VALID_ENCRYPTION_ALGOS; 177 178 private static final String CONFIG_TYPE_DH_GROUP = "dh group"; 179 private static final String CONFIG_TYPE_KEY_LEN = "alogrithm key length"; 180 private static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm"; 181 private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm"; 182 private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm"; 183 184 static { 185 VALID_DH_GROUPS = 186 Collections.unmodifiableSet( 187 new HashSet<>( 188 Arrays.asList( 189 SaProposal.DH_GROUP_1024_BIT_MODP, 190 SaProposal.DH_GROUP_1536_BIT_MODP, 191 SaProposal.DH_GROUP_2048_BIT_MODP))); 192 VALID_KEY_LENGTHS = 193 Collections.unmodifiableSet( 194 new HashSet<>( 195 Arrays.asList( 196 SaProposal.KEY_LEN_AES_128, 197 SaProposal.KEY_LEN_AES_192, 198 SaProposal.KEY_LEN_AES_256))); 199 200 VALID_ENCRYPTION_ALGOS = 201 Collections.unmodifiableSet( 202 new HashSet<>( 203 Arrays.asList( 204 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, 205 SaProposal.ENCRYPTION_ALGORITHM_AES_CTR))); 206 207 VALID_INTEGRITY_ALGOS = 208 Collections.unmodifiableSet( 209 new HashSet<>( 210 Arrays.asList( 211 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, 212 SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96, 213 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, 214 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, 215 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256))); 216 217 VALID_PRF_ALGOS = 218 Collections.unmodifiableSet( 219 new HashSet<>( 220 Arrays.asList( 221 SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1, 222 SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC, 223 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256, 224 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384, 225 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512))); 226 } 227 228 private final EpdgSelector.EpdgSelectorCallback mSelectorCallback = 229 new EpdgSelector.EpdgSelectorCallback() { 230 @Override 231 public void onServerListChanged( 232 int transactionId, ArrayList<InetAddress> validIPList) { 233 sendSelectionRequestComplete( 234 validIPList, new IwlanError(IwlanError.NO_ERROR), transactionId); 235 } 236 237 @Override 238 public void onError(int transactionId, IwlanError epdgSelectorError) { 239 sendSelectionRequestComplete(null, epdgSelectorError, transactionId); 240 } 241 }; 242 243 @VisibleForTesting 244 class TunnelConfig { 245 @NonNull final TunnelCallback mTunnelCallback; 246 @NonNull final TunnelCallbackMetrics mTunnelCallbackMetrics; 247 // TODO: Change this to TunnelLinkProperties after removing autovalue 248 private List<InetAddress> mPcscfAddrList; 249 private List<InetAddress> mDnsAddrList; 250 private List<LinkAddress> mInternalAddrList; 251 252 private InetAddress mSrcIpv6Address; 253 private int mSrcIpv6AddressPrefixLen; 254 private NetworkSliceInfo mSliceInfo; 255 private boolean mIsBackoffTimeValid = false; 256 private long mBackoffTime; 257 getSliceInfo()258 public NetworkSliceInfo getSliceInfo() { 259 return mSliceInfo; 260 } 261 setSliceInfo(NetworkSliceInfo si)262 public void setSliceInfo(NetworkSliceInfo si) { 263 mSliceInfo = si; 264 } 265 isBackoffTimeValid()266 public boolean isBackoffTimeValid() { 267 return mIsBackoffTimeValid; 268 } 269 getBackoffTime()270 public long getBackoffTime() { 271 return mBackoffTime; 272 } 273 setBackoffTime(long backoffTime)274 public void setBackoffTime(long backoffTime) { 275 mIsBackoffTimeValid = true; 276 mBackoffTime = backoffTime; 277 } 278 279 @NonNull final IkeSession mIkeSession; 280 IwlanError mError; 281 private IpSecManager.IpSecTunnelInterface mIface; 282 TunnelConfig( IkeSession ikeSession, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics, InetAddress srcIpv6Addr, int srcIpv6PrefixLength)283 public TunnelConfig( 284 IkeSession ikeSession, 285 TunnelCallback tunnelCallback, 286 TunnelCallbackMetrics tunnelCallbackMetrics, 287 InetAddress srcIpv6Addr, 288 int srcIpv6PrefixLength) { 289 mTunnelCallback = tunnelCallback; 290 mTunnelCallbackMetrics = tunnelCallbackMetrics; 291 mIkeSession = ikeSession; 292 mError = new IwlanError(IwlanError.NO_ERROR); 293 mSrcIpv6Address = srcIpv6Addr; 294 mSrcIpv6AddressPrefixLen = srcIpv6PrefixLength; 295 } 296 297 @NonNull getTunnelCallback()298 TunnelCallback getTunnelCallback() { 299 return mTunnelCallback; 300 } 301 302 @NonNull getTunnelCallbackMetrics()303 TunnelCallbackMetrics getTunnelCallbackMetrics() { 304 return mTunnelCallbackMetrics; 305 } 306 getPcscfAddrList()307 List<InetAddress> getPcscfAddrList() { 308 return mPcscfAddrList; 309 } 310 setPcscfAddrList(List<InetAddress> pcscfAddrList)311 void setPcscfAddrList(List<InetAddress> pcscfAddrList) { 312 mPcscfAddrList = pcscfAddrList; 313 } 314 getDnsAddrList()315 public List<InetAddress> getDnsAddrList() { 316 return mDnsAddrList; 317 } 318 setDnsAddrList(List<InetAddress> dnsAddrList)319 public void setDnsAddrList(List<InetAddress> dnsAddrList) { 320 this.mDnsAddrList = dnsAddrList; 321 } 322 getInternalAddrList()323 public List<LinkAddress> getInternalAddrList() { 324 return mInternalAddrList; 325 } 326 isPrefixSameAsSrcIP(LinkAddress laddr)327 boolean isPrefixSameAsSrcIP(LinkAddress laddr) { 328 if (laddr.isIpv6() && (laddr.getPrefixLength() == mSrcIpv6AddressPrefixLen)) { 329 IpPrefix assignedPrefix = new IpPrefix(laddr.getAddress(), laddr.getPrefixLength()); 330 IpPrefix srcPrefix = new IpPrefix(mSrcIpv6Address, mSrcIpv6AddressPrefixLen); 331 if (assignedPrefix.equals(srcPrefix)) { 332 return true; 333 } 334 } 335 return false; 336 } 337 setInternalAddrList(List<LinkAddress> internalAddrList)338 public void setInternalAddrList(List<LinkAddress> internalAddrList) { 339 mInternalAddrList = new ArrayList<LinkAddress>(internalAddrList); 340 if (getSrcIpv6Address() != null) { 341 // check if we can reuse src ipv6 address (i.e if prefix is same) 342 for (LinkAddress assignedAddr : internalAddrList) { 343 if (isPrefixSameAsSrcIP(assignedAddr)) { 344 // the assigned IPv6 address is same as pre-Handover IPv6 345 // addr. Just reuse the pre-Handover Address so the IID is 346 // preserved 347 mInternalAddrList.remove(assignedAddr); 348 349 // add original address 350 mInternalAddrList.add( 351 new LinkAddress(mSrcIpv6Address, mSrcIpv6AddressPrefixLen)); 352 353 Log.d( 354 TAG, 355 "Network assigned IP replaced OLD:" 356 + internalAddrList 357 + " NEW:" 358 + mInternalAddrList); 359 break; 360 } 361 } 362 } 363 } 364 365 @NonNull getIkeSession()366 public IkeSession getIkeSession() { 367 return mIkeSession; 368 } 369 getError()370 public IwlanError getError() { 371 return mError; 372 } 373 setError(IwlanError error)374 public void setError(IwlanError error) { 375 this.mError = error; 376 } 377 getIface()378 public IpSecManager.IpSecTunnelInterface getIface() { 379 return mIface; 380 } 381 setIface(IpSecManager.IpSecTunnelInterface iface)382 public void setIface(IpSecManager.IpSecTunnelInterface iface) { 383 mIface = iface; 384 } 385 getSrcIpv6Address()386 public InetAddress getSrcIpv6Address() { 387 return mSrcIpv6Address; 388 } 389 getSrcIpv6AddressPrefixLen()390 public int getSrcIpv6AddressPrefixLen() { 391 return mSrcIpv6AddressPrefixLen; 392 } 393 addressListString(List<InetAddress> list)394 private String addressListString(List<InetAddress> list) { 395 StringBuilder sb = new StringBuilder(); 396 sb.append("{ "); 397 for (InetAddress addr : list) { 398 sb.append(addr); 399 sb.append(", "); 400 } 401 sb.append(" }"); 402 return sb.toString(); 403 } 404 hasTunnelOpened()405 public boolean hasTunnelOpened() { 406 return mInternalAddrList != null 407 && !mInternalAddrList.isEmpty() /* The child session is opened */ 408 && mIface != null; /* The tunnel interface is bring up */ 409 } 410 411 @Override toString()412 public String toString() { 413 StringBuilder sb = new StringBuilder(); 414 sb.append("TunnelConfig { "); 415 /*if (mPcscfAddrList != null) { 416 sb.append("mPcscfAddrList: " + addressListString(mPcscfAddrList)); 417 sb.append(", "); 418 } 419 if (mDnsAddrList != null) { 420 sb.append("mDnsAddrList: " + addressListString(mDnsAddrList)); 421 sb.append(", "); 422 } 423 if (mInternalAddrList != null) { 424 sb.append("mInternalAddrList: { "); 425 for (LinkAddress addr : mInternalAddrList) { 426 sb.append(addr + ", "); 427 } 428 sb.append(" }, "); 429 } 430 431 if (mSrcIpv6Address != null) { 432 sb.append("{mSrcIpv6Address: " + mSrcIpv6Address + "}, "); 433 } else { 434 sb.append("{NULL mSrcIpv6Address}, "); 435 } */ 436 437 if (mSliceInfo != null) { 438 sb.append("mSliceInfo: " + mSliceInfo + ", "); 439 } 440 441 if (mIsBackoffTimeValid) { 442 sb.append("mBackoffTime: " + mBackoffTime + ", "); 443 } 444 sb.append(" }"); 445 return sb.toString(); 446 } 447 } 448 449 @VisibleForTesting 450 class TmIkeSessionCallback implements IkeSessionCallback { 451 452 private final String mApnName; 453 private final int mToken; 454 TmIkeSessionCallback(String apnName, int token)455 TmIkeSessionCallback(String apnName, int token) { 456 this.mApnName = apnName; 457 this.mToken = token; 458 } 459 460 @Override onOpened(IkeSessionConfiguration sessionConfiguration)461 public void onOpened(IkeSessionConfiguration sessionConfiguration) { 462 Log.d(TAG, "Ike session opened for apn: " + mApnName + " with token: " + mToken); 463 mHandler.sendMessage( 464 mHandler.obtainMessage( 465 EVENT_IKE_SESSION_OPENED, 466 new IkeSessionOpenedData(mApnName, mToken, sessionConfiguration))); 467 } 468 469 @Override onClosed()470 public void onClosed() { 471 Log.d(TAG, "Ike session closed for apn: " + mApnName + " with token: " + mToken); 472 mHandler.sendMessage( 473 mHandler.obtainMessage( 474 EVENT_IKE_SESSION_CLOSED, 475 new SessionClosedData( 476 mApnName, mToken, new IwlanError(IwlanError.NO_ERROR)))); 477 } 478 479 @Override onClosedExceptionally(IkeException exception)480 public void onClosedExceptionally(IkeException exception) { 481 mNextReauthId = null; 482 onSessionClosedWithException(exception, mApnName, mToken, EVENT_IKE_SESSION_CLOSED); 483 } 484 485 @Override onError(IkeProtocolException exception)486 public void onError(IkeProtocolException exception) { 487 Log.d(TAG, "Ike session onError for apn: " + mApnName + " with token: " + mToken); 488 489 mNextReauthId = null; 490 491 Log.d( 492 TAG, 493 "ErrorType:" 494 + exception.getErrorType() 495 + " ErrorData:" 496 + exception.getMessage()); 497 } 498 499 @Override onIkeSessionConnectionInfoChanged( IkeSessionConnectionInfo ikeSessionConnectionInfo)500 public void onIkeSessionConnectionInfoChanged( 501 IkeSessionConnectionInfo ikeSessionConnectionInfo) { 502 Network network = ikeSessionConnectionInfo.getNetwork(); 503 Log.d( 504 TAG, 505 "Ike session connection info changed for apn: " 506 + mApnName 507 + " with token: " 508 + mToken 509 + " Network: " 510 + network); 511 mHandler.sendMessage( 512 mHandler.obtainMessage( 513 EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED, 514 new IkeSessionConnectionInfoData( 515 mApnName, mToken, ikeSessionConnectionInfo))); 516 } 517 } 518 519 @VisibleForTesting 520 class TmIke3gppCallback implements Ike3gppExtension.Ike3gppDataListener { 521 private final String mApnName; 522 private final int mToken; 523 TmIke3gppCallback(String apnName, int token)524 private TmIke3gppCallback(String apnName, int token) { 525 mApnName = apnName; 526 mToken = token; 527 } 528 529 @Override onIke3gppDataReceived(List<Ike3gppData> payloads)530 public void onIke3gppDataReceived(List<Ike3gppData> payloads) { 531 if (isObsoleteToken(mApnName, mToken)) { 532 Log.d(TAG, "onIke3gppDataReceived for obsolete token " + mToken); 533 return; 534 } 535 536 if (payloads != null && !payloads.isEmpty()) { 537 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 538 for (Ike3gppData payload : payloads) { 539 if (payload.getDataType() == DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) { 540 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_N1_MODE_INFORMATION"); 541 NetworkSliceInfo si = 542 NetworkSliceSelectionAssistanceInformation.getSliceInfo( 543 ((Ike3gppN1ModeInformation) payload).getSnssai()); 544 if (si != null) { 545 tunnelConfig.setSliceInfo(si); 546 Log.d(TAG, "SliceInfo: " + si); 547 } 548 } else if (payload.getDataType() == DATA_TYPE_NOTIFY_BACKOFF_TIMER) { 549 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_BACKOFF_TIMER"); 550 long backoffTime = 551 decodeBackoffTime( 552 ((Ike3gppBackoffTimer) payload).getBackoffTimer()); 553 if (backoffTime > 0) { 554 tunnelConfig.setBackoffTime(backoffTime); 555 Log.d(TAG, "Backoff Timer: " + backoffTime); 556 } 557 } 558 } 559 } else { 560 Log.e(TAG, "Null or empty payloads received:"); 561 } 562 } 563 } 564 565 @VisibleForTesting 566 class TmChildSessionCallback implements ChildSessionCallback { 567 568 private final String mApnName; 569 private final int mToken; 570 TmChildSessionCallback(String apnName, int token)571 TmChildSessionCallback(String apnName, int token) { 572 this.mApnName = apnName; 573 this.mToken = token; 574 } 575 576 @Override onOpened(ChildSessionConfiguration sessionConfiguration)577 public void onOpened(ChildSessionConfiguration sessionConfiguration) { 578 Log.d(TAG, "onOpened child session for apn: " + mApnName + " with token: " + mToken); 579 mHandler.sendMessage( 580 mHandler.obtainMessage( 581 EVENT_CHILD_SESSION_OPENED, 582 new TunnelOpenedData( 583 mApnName, 584 mToken, 585 sessionConfiguration.getInternalDnsServers(), 586 sessionConfiguration.getInternalAddresses()))); 587 } 588 589 @Override onClosed()590 public void onClosed() { 591 Log.d(TAG, "onClosed child session for apn: " + mApnName + " with token: " + mToken); 592 mHandler.sendMessage( 593 mHandler.obtainMessage( 594 EVENT_CHILD_SESSION_CLOSED, 595 new SessionClosedData( 596 mApnName, mToken, new IwlanError(IwlanError.NO_ERROR)))); 597 } 598 599 @Override onClosedExceptionally(IkeException exception)600 public void onClosedExceptionally(IkeException exception) { 601 onSessionClosedWithException(exception, mApnName, mToken, EVENT_CHILD_SESSION_CLOSED); 602 } 603 604 @Override onIpSecTransformsMigrated( IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform)605 public void onIpSecTransformsMigrated( 606 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) { 607 // migration is similar to addition 608 Log.d(TAG, "Transforms migrated for apn: " + mApnName + " with token: " + mToken); 609 mHandler.sendMessage( 610 mHandler.obtainMessage( 611 EVENT_IPSEC_TRANSFORM_CREATED, 612 new IpsecTransformData( 613 inIpSecTransform, 614 IpSecManager.DIRECTION_IN, 615 mApnName, 616 mToken))); 617 mHandler.sendMessage( 618 mHandler.obtainMessage( 619 EVENT_IPSEC_TRANSFORM_CREATED, 620 new IpsecTransformData( 621 outIpSecTransform, 622 IpSecManager.DIRECTION_OUT, 623 mApnName, 624 mToken))); 625 } 626 627 @Override onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction)628 public void onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction) { 629 Log.d( 630 TAG, 631 "Transform created, direction: " 632 + direction 633 + ", apn: " 634 + mApnName 635 + ", token: " 636 + mToken); 637 mHandler.sendMessage( 638 mHandler.obtainMessage( 639 EVENT_IPSEC_TRANSFORM_CREATED, 640 new IpsecTransformData(ipSecTransform, direction, mApnName, mToken))); 641 } 642 643 @Override onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction)644 public void onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction) { 645 Log.d( 646 TAG, 647 "Transform deleted, direction: " 648 + direction 649 + ", apn: " 650 + mApnName 651 + ", token: " 652 + mToken); 653 mHandler.sendMessage( 654 mHandler.obtainMessage( 655 EVENT_IPSEC_TRANSFORM_DELETED, 656 new IpsecTransformData(ipSecTransform, direction, mApnName, mToken))); 657 } 658 } 659 EpdgTunnelManager(Context context, int slotId)660 private EpdgTunnelManager(Context context, int slotId) { 661 mContext = context; 662 mSlotId = slotId; 663 mIkeSessionCreator = new IkeSessionCreator(); 664 TAG = EpdgTunnelManager.class.getSimpleName() + "[" + mSlotId + "]"; 665 initHandler(); 666 } 667 668 @VisibleForTesting initHandler()669 void initHandler() { 670 mHandler = new TmHandler(getLooper()); 671 } 672 673 @VisibleForTesting getLooper()674 Looper getLooper() { 675 mHandlerThread = new HandlerThread("EpdgTunnelManagerThread"); 676 mHandlerThread.start(); 677 return mHandlerThread.getLooper(); 678 } 679 680 /** 681 * Gets a EpdgTunnelManager instance. 682 * 683 * @param context application context 684 * @param subId subscription ID for the tunnel 685 * @return tunnel manager instance corresponding to the sub id 686 */ getInstance(@onNull Context context, int subId)687 public static EpdgTunnelManager getInstance(@NonNull Context context, int subId) { 688 return mTunnelManagerInstances.computeIfAbsent( 689 subId, k -> new EpdgTunnelManager(context, subId)); 690 } 691 692 @VisibleForTesting resetAllInstances()693 public static void resetAllInstances() { 694 mTunnelManagerInstances.clear(); 695 } 696 697 public interface TunnelCallback { 698 /** 699 * Called when the tunnel is opened. 700 * 701 * @param apnName apn for which the tunnel was opened 702 * @param linkProperties link properties of the tunnel 703 */ onOpened(@onNull String apnName, @NonNull TunnelLinkProperties linkProperties)704 void onOpened(@NonNull String apnName, @NonNull TunnelLinkProperties linkProperties); 705 /** 706 * Called when the tunnel is closed OR if bringup fails 707 * 708 * @param apnName apn for which the tunnel was closed 709 * @param error IwlanError carrying details of the error 710 */ onClosed(@onNull String apnName, @NonNull IwlanError error)711 void onClosed(@NonNull String apnName, @NonNull IwlanError error); 712 } 713 714 public interface TunnelCallbackMetrics { 715 /** 716 * Called for logging the tunnel is opened. 717 * 718 * @param apnName apn for which the tunnel was opened 719 * @param epdgServerAddress epdg server IP address for bringup the tunnel 720 * @param epdgServerSelectionDuration time for EpdgSelector doing FQDN 721 * @param ikeTunnelEstablishmentDuration time for IKE module processing tunnel 722 * establishement 723 */ onOpened( @onNull String apnName, @Nullable String epdgServerAddress, @NonNull int epdgServerSelectionDuration, @NonNull int ikeTunnelEstablishmentDuration)724 void onOpened( 725 @NonNull String apnName, 726 @Nullable String epdgServerAddress, 727 @NonNull int epdgServerSelectionDuration, 728 @NonNull int ikeTunnelEstablishmentDuration); 729 /** 730 * Called for logging the tunnel is closed or bringup failed. 731 * 732 * @param apnName apn for which the tunnel was closed 733 * @param epdgServerAddress epdg server IP address for bringup the tunnel 734 * @param epdgServerSelectionDuration time for EpdgSelector doing FQDN 735 * @param ikeTunnelEstablishmentDuration time for IKE module processing tunnel 736 * establishement 737 */ onClosed( @onNull String apnName, @Nullable String epdgServerAddress, @NonNull int epdgServerSelectionDuration, @NonNull int ikeTunnelEstablishmentDuration)738 void onClosed( 739 @NonNull String apnName, 740 @Nullable String epdgServerAddress, 741 @NonNull int epdgServerSelectionDuration, 742 @NonNull int ikeTunnelEstablishmentDuration); 743 } 744 745 /** 746 * Close tunnel for an apn. Confirmation of closing will be delivered in TunnelCallback that was 747 * provided in {@link #bringUpTunnel} 748 * 749 * @param apnName apn name 750 * @param forceClose if true, results in local cleanup of tunnel 751 * @return true if params are valid and tunnel exists. False otherwise. 752 */ closeTunnel(@onNull String apnName, boolean forceClose)753 public boolean closeTunnel(@NonNull String apnName, boolean forceClose) { 754 mHandler.sendMessage( 755 mHandler.obtainMessage( 756 EVENT_TUNNEL_BRINGDOWN_REQUEST, 757 forceClose ? 1 : 0, 758 0 /*not used*/, 759 apnName)); 760 return true; 761 } 762 763 /** 764 * Update the local Network. This will trigger a revaluation for every tunnel for which tunnel 765 * manager has state. 766 * 767 * <p>Tunnels in bringup state will be for closed since IKE currently keeps retrying. 768 * 769 * <p>For rest of the tunnels, update IKE session wth new network. This will either result in 770 * MOBIKE callflow or just a rekey over new Network 771 */ updateNetwork(@onNull Network network, String apnName)772 public void updateNetwork(@NonNull Network network, String apnName) { 773 UpdateNetworkWrapper updateNetworkWrapper = new UpdateNetworkWrapper(network, apnName); 774 mHandler.sendMessage(mHandler.obtainMessage(EVENT_UPDATE_NETWORK, updateNetworkWrapper)); 775 } 776 /** 777 * Bring up epdg tunnel. Only one bring up request per apn is expected. All active tunnel 778 * requests and tunnels are expected to be on the same network. 779 * 780 * @param setupRequest {@link TunnelSetupRequest} tunnel configurations 781 * @param tunnelCallback {@link TunnelCallback} interface to notify clients about the tunnel 782 * state 783 * @return true if params are valid and no existing tunnel. False otherwise. 784 */ bringUpTunnel( @onNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback, @NonNull TunnelCallbackMetrics tunnelCallbackMetrics)785 public boolean bringUpTunnel( 786 @NonNull TunnelSetupRequest setupRequest, 787 @NonNull TunnelCallback tunnelCallback, 788 @NonNull TunnelCallbackMetrics tunnelCallbackMetrics) { 789 String apnName = setupRequest.apnName(); 790 791 if (getTunnelSetupRequestApnName(setupRequest) == null) { 792 Log.e(TAG, "APN is null."); 793 return false; 794 } 795 796 if (isTunnelConfigContainExistApn(apnName)) { 797 Log.e(TAG, "Tunnel exists for apn:" + apnName); 798 return false; 799 } 800 801 if (!isValidApnProtocol(setupRequest.apnIpProtocol())) { 802 Log.e(TAG, "Invalid protocol for APN"); 803 return false; 804 } 805 806 int pduSessionId = setupRequest.pduSessionId(); 807 if (pduSessionId < 0 || pduSessionId > 15) { 808 Log.e(TAG, "Invalid pduSessionId: " + pduSessionId); 809 return false; 810 } 811 812 TunnelRequestWrapper tunnelRequestWrapper = 813 new TunnelRequestWrapper(setupRequest, tunnelCallback, tunnelCallbackMetrics); 814 815 mHandler.sendMessage( 816 mHandler.obtainMessage(EVENT_TUNNEL_BRINGUP_REQUEST, tunnelRequestWrapper)); 817 818 return true; 819 } 820 onBringUpTunnel( TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics)821 private void onBringUpTunnel( 822 TunnelSetupRequest setupRequest, 823 TunnelCallback tunnelCallback, 824 TunnelCallbackMetrics tunnelCallbackMetrics) { 825 String apnName = setupRequest.apnName(); 826 IkeSessionParams ikeSessionParams = null; 827 828 Log.d( 829 TAG, 830 "Bringing up tunnel for apn: " 831 + apnName 832 + "ePDG : " 833 + mEpdgAddress.getHostAddress()); 834 835 final int token = incrementAndGetCurrentTokenForApn(apnName); 836 837 try { 838 ikeSessionParams = buildIkeSessionParams(setupRequest, apnName, token); 839 } catch (IwlanSimNotReadyException e) { 840 IwlanError iwlanError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION); 841 reportIwlanError(apnName, iwlanError); 842 tunnelCallback.onClosed(apnName, iwlanError); 843 tunnelCallbackMetrics.onClosed(apnName, null, 0, 0); 844 return; 845 } 846 847 mIkeTunnelEstablishmentStartTime = System.currentTimeMillis(); 848 IkeSession ikeSession = 849 getIkeSessionCreator() 850 .createIkeSession( 851 mContext, 852 ikeSessionParams, 853 buildChildSessionParams(setupRequest), 854 Executors.newSingleThreadExecutor(), 855 getTmIkeSessionCallback(apnName, token), 856 new TmChildSessionCallback(apnName, token)); 857 858 boolean isSrcIpv6Present = setupRequest.srcIpv6Address().isPresent(); 859 putApnNameToTunnelConfig( 860 apnName, 861 ikeSession, 862 tunnelCallback, 863 tunnelCallbackMetrics, 864 isSrcIpv6Present ? setupRequest.srcIpv6Address().get() : null, 865 setupRequest.srcIpv6AddressPrefixLength()); 866 } 867 868 /** 869 * Proxy to allow testing 870 * 871 * @hide 872 */ 873 @VisibleForTesting 874 static class IkeSessionCreator { 875 /** Creates a IKE session */ createIkeSession( @onNull Context context, @NonNull IkeSessionParams ikeSessionParams, @NonNull ChildSessionParams firstChildSessionParams, @NonNull Executor userCbExecutor, @NonNull IkeSessionCallback ikeSessionCallback, @NonNull ChildSessionCallback firstChildSessionCallback)876 public IkeSession createIkeSession( 877 @NonNull Context context, 878 @NonNull IkeSessionParams ikeSessionParams, 879 @NonNull ChildSessionParams firstChildSessionParams, 880 @NonNull Executor userCbExecutor, 881 @NonNull IkeSessionCallback ikeSessionCallback, 882 @NonNull ChildSessionCallback firstChildSessionCallback) { 883 return new IkeSession( 884 context, 885 ikeSessionParams, 886 firstChildSessionParams, 887 userCbExecutor, 888 ikeSessionCallback, 889 firstChildSessionCallback); 890 } 891 } 892 buildChildSessionParams(TunnelSetupRequest setupRequest)893 private ChildSessionParams buildChildSessionParams(TunnelSetupRequest setupRequest) { 894 int proto = setupRequest.apnIpProtocol(); 895 int hardTimeSeconds = 896 (int) getConfig(CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT); 897 int softTimeSeconds = 898 (int) getConfig(CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT); 899 if (!isValidChildSessionLifetime(hardTimeSeconds, softTimeSeconds)) { 900 if (hardTimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM 901 && softTimeSeconds > CHILD_SOFT_LIFETIME_SEC_MINIMUM) { 902 hardTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM; 903 softTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM; 904 } else { 905 hardTimeSeconds = 906 (int) 907 IwlanHelper.getDefaultConfig( 908 CarrierConfigManager.Iwlan 909 .KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT); 910 softTimeSeconds = 911 (int) 912 IwlanHelper.getDefaultConfig( 913 CarrierConfigManager.Iwlan 914 .KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT); 915 } 916 Log.d( 917 TAG, 918 "Invalid child session lifetime values, set hard: " 919 + hardTimeSeconds 920 + ", soft: " 921 + softTimeSeconds); 922 } 923 924 TunnelModeChildSessionParams.Builder childSessionParamsBuilder = 925 new TunnelModeChildSessionParams.Builder() 926 .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds); 927 928 childSessionParamsBuilder.addSaProposal(buildChildSaProposal()); 929 930 boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent(); 931 boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent(); 932 if (handoverIPv4Present || handoverIPv6Present) { 933 if (handoverIPv4Present) { 934 childSessionParamsBuilder.addInternalAddressRequest( 935 (Inet4Address) setupRequest.srcIpv4Address().get()); 936 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET); 937 childSessionParamsBuilder.addInboundTrafficSelectors( 938 getDefaultTrafficSelectorIpv4()); 939 childSessionParamsBuilder.addOutboundTrafficSelectors( 940 getDefaultTrafficSelectorIpv4()); 941 } 942 if (handoverIPv6Present) { 943 childSessionParamsBuilder.addInternalAddressRequest( 944 (Inet6Address) setupRequest.srcIpv6Address().get(), 945 setupRequest.srcIpv6AddressPrefixLength()); 946 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6); 947 childSessionParamsBuilder.addInboundTrafficSelectors( 948 getDefaultTrafficSelectorIpv6()); 949 childSessionParamsBuilder.addOutboundTrafficSelectors( 950 getDefaultTrafficSelectorIpv6()); 951 } 952 } else { 953 // non-handover case 954 if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) { 955 childSessionParamsBuilder.addInternalAddressRequest(AF_INET); 956 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET); 957 childSessionParamsBuilder.addInboundTrafficSelectors( 958 getDefaultTrafficSelectorIpv4()); 959 childSessionParamsBuilder.addOutboundTrafficSelectors( 960 getDefaultTrafficSelectorIpv4()); 961 } 962 if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) { 963 childSessionParamsBuilder.addInternalAddressRequest(AF_INET6); 964 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6); 965 childSessionParamsBuilder.addInboundTrafficSelectors( 966 getDefaultTrafficSelectorIpv6()); 967 childSessionParamsBuilder.addOutboundTrafficSelectors( 968 getDefaultTrafficSelectorIpv6()); 969 } 970 } 971 972 return childSessionParamsBuilder.build(); 973 } 974 getDefaultTrafficSelectorIpv4()975 private static IkeTrafficSelector getDefaultTrafficSelectorIpv4() { 976 return new IkeTrafficSelector( 977 TRAFFIC_SELECTOR_START_PORT, 978 TRAFFIC_SELECTOR_END_PORT, 979 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_START_ADDR), 980 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_END_ADDR)); 981 } 982 getDefaultTrafficSelectorIpv6()983 private static IkeTrafficSelector getDefaultTrafficSelectorIpv6() { 984 return new IkeTrafficSelector( 985 TRAFFIC_SELECTOR_START_PORT, 986 TRAFFIC_SELECTOR_END_PORT, 987 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_START_ADDR), 988 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_END_ADDR)); 989 } 990 numPdnTunnels()991 private int numPdnTunnels() { 992 return mApnNameToTunnelConfig.size(); 993 } 994 995 // Returns the IMEISV or device IMEI, in that order of priority. getMobileDeviceIdentity()996 private @Nullable String getMobileDeviceIdentity() { 997 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); 998 telephonyManager = 999 telephonyManager.createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId)); 1000 if (telephonyManager == null) { 1001 return null; 1002 } 1003 // Queries the 15-digit device IMEI. 1004 String imei = telephonyManager.getImei(); 1005 if (imei == null || imei.length() != DEVICE_IMEI_LEN) { 1006 Log.i(TAG, "Unable to query valid Mobile Device Identity (IMEI)!"); 1007 return null; 1008 } 1009 String imeisv_suffix = telephonyManager.getDeviceSoftwareVersion(); 1010 if (imeisv_suffix == null || imeisv_suffix.length() != DEVICE_IMEISV_SUFFIX_LEN) { 1011 // Unable to retrieve 2-digit suffix for IMEISV, so returns device IMEI. 1012 return imei; 1013 } 1014 // Splices the first 14 digit of device IMEI with 2-digit SV suffix to form IMEISV. 1015 return imei.substring(0, imei.length() - 1) + imeisv_suffix; 1016 } 1017 buildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName, int token)1018 private IkeSessionParams buildIkeSessionParams( 1019 TunnelSetupRequest setupRequest, String apnName, int token) 1020 throws IwlanSimNotReadyException { 1021 int hardTimeSeconds = 1022 (int) getConfig(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT); 1023 int softTimeSeconds = 1024 (int) getConfig(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT); 1025 if (!isValidIkeSessionLifetime(hardTimeSeconds, softTimeSeconds)) { 1026 if (hardTimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM 1027 && softTimeSeconds > IKE_SOFT_LIFETIME_SEC_MINIMUM) { 1028 hardTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM; 1029 softTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM; 1030 } else { 1031 hardTimeSeconds = 1032 (int) 1033 IwlanHelper.getDefaultConfig( 1034 CarrierConfigManager.Iwlan 1035 .KEY_IKE_REKEY_HARD_TIMER_SEC_INT); 1036 softTimeSeconds = 1037 (int) 1038 IwlanHelper.getDefaultConfig( 1039 CarrierConfigManager.Iwlan 1040 .KEY_IKE_REKEY_SOFT_TIMER_SEC_INT); 1041 } 1042 Log.d( 1043 TAG, 1044 "Invalid ike session lifetime values, set hard: " 1045 + hardTimeSeconds 1046 + ", soft: " 1047 + softTimeSeconds); 1048 } 1049 1050 IkeSessionParams.Builder builder = 1051 new IkeSessionParams.Builder(mContext) 1052 // permanently hardcode DSCP to 46 (Expedited Forwarding class) 1053 // See https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml 1054 // This will make WiFi prioritize IKE signallig under WMM AC_VO 1055 .setDscp(46) 1056 .setServerHostname(mEpdgAddress.getHostAddress()) 1057 .setLocalIdentification(getLocalIdentification()) 1058 .setRemoteIdentification(getId(setupRequest.apnName(), false)) 1059 .setAuthEap(null, getEapConfig()) 1060 .addSaProposal(buildIkeSaProposal()) 1061 .setNetwork(mNetwork) 1062 .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID) 1063 .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) 1064 .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY) 1065 .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds) 1066 .setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig()) 1067 .setDpdDelaySeconds(getDpdDelayFromConfig()); 1068 1069 if (numPdnTunnels() == 0) { 1070 builder.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT); 1071 Log.d(TAG, "IKE_OPTION_INITIAL_CONTACT"); 1072 } 1073 1074 if ((int) getConfig(CarrierConfigManager.Iwlan.KEY_EPDG_AUTHENTICATION_METHOD_INT) 1075 == CarrierConfigManager.Iwlan.AUTHENTICATION_METHOD_EAP_ONLY) { 1076 builder.addIkeOption(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH); 1077 } 1078 1079 if (setupRequest.requestPcscf()) { 1080 int proto = setupRequest.apnIpProtocol(); 1081 if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) { 1082 builder.addPcscfServerRequest(AF_INET); 1083 } 1084 if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) { 1085 builder.addPcscfServerRequest(AF_INET6); 1086 } 1087 } 1088 1089 Ike3gppParams.Builder builder3gppParams = null; 1090 1091 // TODO(b/239753287): Telus carrier requests DEVICE_IDENTITY, but errors out when parsing 1092 // the response. Temporarily disabled. 1093 if (false) { 1094 String imei = getMobileDeviceIdentity(); 1095 if (imei != null) { 1096 if (builder3gppParams == null) { 1097 builder3gppParams = new Ike3gppParams.Builder(); 1098 } 1099 Log.d(TAG, "DEVICE_IDENTITY set in Ike3gppParams"); 1100 builder3gppParams.setMobileDeviceIdentity(imei); 1101 } 1102 } 1103 1104 if (isN1ModeSupported()) { 1105 if (setupRequest.pduSessionId() != 0) { 1106 // Configures the PduSession ID in N1_MODE_CAPABILITY payload 1107 // to notify the server that UE supports N1_MODE 1108 if (builder3gppParams == null) { 1109 builder3gppParams = new Ike3gppParams.Builder(); 1110 } 1111 builder3gppParams.setPduSessionId((byte) setupRequest.pduSessionId()); 1112 } 1113 } 1114 1115 if (builder3gppParams != null) { 1116 Ike3gppExtension extension = 1117 new Ike3gppExtension( 1118 builder3gppParams.build(), new TmIke3gppCallback(apnName, token)); 1119 builder.setIke3gppExtension(extension); 1120 } 1121 1122 int nattKeepAliveTimer = 1123 (int) getConfig(CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT); 1124 if (nattKeepAliveTimer < NATT_KEEPALIVE_DELAY_SEC_MIN 1125 || nattKeepAliveTimer > NATT_KEEPALIVE_DELAY_SEC_MAX) { 1126 Log.d(TAG, "Falling back to default natt keep alive timer"); 1127 nattKeepAliveTimer = 1128 (int) 1129 IwlanHelper.getDefaultConfig( 1130 CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT); 1131 } 1132 builder.setNattKeepAliveDelaySeconds(nattKeepAliveTimer); 1133 1134 return builder.build(); 1135 } 1136 isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1137 private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { 1138 if (hardLifetimeSeconds < CHILD_HARD_LIFETIME_SEC_MINIMUM 1139 || hardLifetimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM 1140 || softLifetimeSeconds < CHILD_SOFT_LIFETIME_SEC_MINIMUM 1141 || hardLifetimeSeconds - softLifetimeSeconds < LIFETIME_MARGIN_SEC_MINIMUM) { 1142 return false; 1143 } 1144 return true; 1145 } 1146 isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1147 private boolean isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { 1148 if (hardLifetimeSeconds < IKE_HARD_LIFETIME_SEC_MINIMUM 1149 || hardLifetimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM 1150 || softLifetimeSeconds < IKE_SOFT_LIFETIME_SEC_MINIMUM 1151 || hardLifetimeSeconds - softLifetimeSeconds < LIFETIME_MARGIN_SEC_MINIMUM) { 1152 return false; 1153 } 1154 return true; 1155 } 1156 getConfig(String configKey)1157 private <T> T getConfig(String configKey) { 1158 return IwlanHelper.getConfig(configKey, mContext, mSlotId); 1159 } 1160 buildIkeSaProposal()1161 private IkeSaProposal buildIkeSaProposal() { 1162 IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); 1163 1164 int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1165 for (int dhGroup : dhGroups) { 1166 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1167 saProposalBuilder.addDhGroup(dhGroup); 1168 } 1169 } 1170 1171 int[] encryptionAlgos = 1172 getConfig( 1173 CarrierConfigManager.Iwlan 1174 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1175 for (int encryptionAlgo : encryptionAlgos) { 1176 validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO); 1177 1178 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1179 int[] aesCbcKeyLens = 1180 getConfig( 1181 CarrierConfigManager.Iwlan 1182 .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); 1183 for (int aesCbcKeyLen : aesCbcKeyLens) { 1184 if (validateConfig(aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1185 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLen); 1186 } 1187 } 1188 } 1189 1190 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1191 int[] aesCtrKeyLens = 1192 getConfig( 1193 CarrierConfigManager.Iwlan 1194 .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); 1195 for (int aesCtrKeyLen : aesCtrKeyLens) { 1196 if (validateConfig(aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1197 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLen); 1198 } 1199 } 1200 } 1201 } 1202 1203 int[] integrityAlgos = 1204 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY); 1205 for (int integrityAlgo : integrityAlgos) { 1206 if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { 1207 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); 1208 } 1209 } 1210 1211 int[] prfAlgos = 1212 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY); 1213 for (int prfAlgo : prfAlgos) { 1214 if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) { 1215 saProposalBuilder.addPseudorandomFunction(prfAlgo); 1216 } 1217 } 1218 1219 return saProposalBuilder.build(); 1220 } 1221 validateConfig(int config, Set<Integer> validConfigValues, String configType)1222 private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) { 1223 if (validConfigValues.contains(config)) { 1224 return true; 1225 } 1226 1227 Log.e(TAG, "Invalid config value for " + configType + ":" + config); 1228 return false; 1229 } 1230 buildChildSaProposal()1231 private ChildSaProposal buildChildSaProposal() { 1232 ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder(); 1233 1234 // IKE library doesn't add KE payload if dh groups are not set in child session params. 1235 // Use the same groups as that of IKE session. 1236 if (getConfig(CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) { 1237 int[] dhGroups = 1238 getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1239 for (int dhGroup : dhGroups) { 1240 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1241 saProposalBuilder.addDhGroup(dhGroup); 1242 } 1243 } 1244 } 1245 1246 int[] encryptionAlgos = 1247 getConfig( 1248 CarrierConfigManager.Iwlan 1249 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1250 for (int encryptionAlgo : encryptionAlgos) { 1251 if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1252 if (ChildSaProposal.getSupportedEncryptionAlgorithms().contains(encryptionAlgo)) { 1253 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1254 int[] aesCbcKeyLens = 1255 getConfig( 1256 CarrierConfigManager.Iwlan 1257 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); 1258 for (int aesCbcKeyLen : aesCbcKeyLens) { 1259 if (validateConfig( 1260 aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1261 saProposalBuilder.addEncryptionAlgorithm( 1262 encryptionAlgo, aesCbcKeyLen); 1263 } 1264 } 1265 } 1266 1267 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1268 int[] aesCtrKeyLens = 1269 getConfig( 1270 CarrierConfigManager.Iwlan 1271 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); 1272 for (int aesCtrKeyLen : aesCtrKeyLens) { 1273 if (validateConfig( 1274 aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1275 saProposalBuilder.addEncryptionAlgorithm( 1276 encryptionAlgo, aesCtrKeyLen); 1277 } 1278 } 1279 } 1280 } else { 1281 Log.w(TAG, "Device does not support encryption alog: " + encryptionAlgo); 1282 } 1283 } 1284 } 1285 1286 int[] integrityAlgos = 1287 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY); 1288 for (int integrityAlgo : integrityAlgos) { 1289 if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { 1290 if (ChildSaProposal.getSupportedIntegrityAlgorithms().contains(integrityAlgo)) { 1291 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); 1292 } else { 1293 Log.w(TAG, "Device does not support integrity alog: " + integrityAlgo); 1294 } 1295 } 1296 } 1297 1298 return saProposalBuilder.build(); 1299 } 1300 getLocalIdentification()1301 private IkeIdentification getLocalIdentification() throws IwlanSimNotReadyException { 1302 String nai; 1303 1304 nai = IwlanHelper.getNai(mContext, mSlotId, mNextReauthId); 1305 1306 if (nai == null) { 1307 throw new IwlanSimNotReadyException("Nai is null."); 1308 } 1309 1310 Log.d(TAG, "getLocalIdentification: Nai: " + nai); 1311 return getId(nai, true); 1312 } 1313 getId(String id, boolean isLocal)1314 private IkeIdentification getId(String id, boolean isLocal) { 1315 String idTypeConfig = 1316 isLocal 1317 ? CarrierConfigManager.Iwlan.KEY_IKE_LOCAL_ID_TYPE_INT 1318 : CarrierConfigManager.Iwlan.KEY_IKE_REMOTE_ID_TYPE_INT; 1319 int idType = getConfig(idTypeConfig); 1320 switch (idType) { 1321 case CarrierConfigManager.Iwlan.ID_TYPE_FQDN: 1322 return new IkeFqdnIdentification(id); 1323 case CarrierConfigManager.Iwlan.ID_TYPE_KEY_ID: 1324 return new IkeKeyIdIdentification(id.getBytes(StandardCharsets.US_ASCII)); 1325 case CarrierConfigManager.Iwlan.ID_TYPE_RFC822_ADDR: 1326 return new IkeRfc822AddrIdentification(id); 1327 default: 1328 throw new IllegalArgumentException("Invalid local Identity type: " + idType); 1329 } 1330 } 1331 getEapConfig()1332 private EapSessionConfig getEapConfig() throws IwlanSimNotReadyException { 1333 int subId = IwlanHelper.getSubId(mContext, mSlotId); 1334 String nai = IwlanHelper.getNai(mContext, mSlotId, null); 1335 1336 if (nai == null) { 1337 throw new IwlanSimNotReadyException("Nai is null."); 1338 } 1339 1340 EapSessionConfig.EapAkaOption option = null; 1341 if (mNextReauthId != null) { 1342 option = new EapSessionConfig.EapAkaOption.Builder().setReauthId(mNextReauthId).build(); 1343 } 1344 1345 Log.d(TAG, "getEapConfig: Nai: " + nai); 1346 return new EapSessionConfig.Builder() 1347 .setEapAkaConfig(subId, TelephonyManager.APPTYPE_USIM, option) 1348 .setEapIdentity(nai.getBytes(StandardCharsets.US_ASCII)) 1349 .build(); 1350 } 1351 onSessionClosedWithException( IkeException exception, String apnName, int token, int sessionType)1352 private void onSessionClosedWithException( 1353 IkeException exception, String apnName, int token, int sessionType) { 1354 IwlanError error = new IwlanError(exception); 1355 Log.e( 1356 TAG, 1357 "Closing tunnel with exception for apn: " 1358 + apnName 1359 + " with token: " 1360 + token 1361 + " sessionType:" 1362 + sessionType 1363 + " error: " 1364 + error); 1365 exception.printStackTrace(); 1366 1367 mHandler.sendMessage( 1368 mHandler.obtainMessage(sessionType, new SessionClosedData(apnName, token, error))); 1369 } 1370 1371 private final class TmHandler extends Handler { 1372 private final String TAG = TmHandler.class.getSimpleName(); 1373 1374 @Override handleMessage(Message msg)1375 public void handleMessage(Message msg) { 1376 Log.d(TAG, "msg.what = " + eventToString(msg.what)); 1377 1378 String apnName; 1379 TunnelConfig tunnelConfig; 1380 1381 switch (msg.what) { 1382 case EVENT_CHILD_SESSION_OPENED: 1383 case EVENT_IKE_SESSION_CLOSED: 1384 case EVENT_IPSEC_TRANSFORM_CREATED: 1385 case EVENT_IPSEC_TRANSFORM_DELETED: 1386 case EVENT_CHILD_SESSION_CLOSED: 1387 case EVENT_IKE_SESSION_OPENED: 1388 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED: 1389 IkeEventData ikeEventData = (IkeEventData) msg.obj; 1390 if (isObsoleteToken(ikeEventData.mApnName, ikeEventData.mToken)) { 1391 Log.d( 1392 TAG, 1393 eventToString(msg.what) 1394 + " for obsolete token " 1395 + ikeEventData.mToken); 1396 return; 1397 } 1398 } 1399 1400 switch (msg.what) { 1401 case EVENT_TUNNEL_BRINGUP_REQUEST: 1402 TunnelRequestWrapper tunnelRequestWrapper = (TunnelRequestWrapper) msg.obj; 1403 TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest(); 1404 1405 if (IwlanHelper.getSubId(mContext, mSlotId) 1406 == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 1407 Log.e(TAG, "SIM isn't ready"); 1408 IwlanError iwlanError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION); 1409 reportIwlanError(setupRequest.apnName(), iwlanError); 1410 tunnelRequestWrapper 1411 .getTunnelCallback() 1412 .onClosed(setupRequest.apnName(), iwlanError); 1413 tunnelRequestWrapper 1414 .getTunnelCallbackMetrics() 1415 .onClosed(setupRequest.apnName(), null, 0, 0); 1416 return; 1417 } 1418 1419 if (!canBringUpTunnel(setupRequest.apnName())) { 1420 Log.d(TAG, "Cannot bring up tunnel as retry time has not passed"); 1421 tunnelRequestWrapper 1422 .getTunnelCallback() 1423 .onClosed( 1424 setupRequest.apnName(), 1425 getLastError(setupRequest.apnName())); 1426 tunnelRequestWrapper 1427 .getTunnelCallbackMetrics() 1428 .onClosed(setupRequest.apnName(), null, 0, 0); 1429 return; 1430 } 1431 1432 // No tunnel bring up in progress and the epdg address is null 1433 if (!mIsEpdgAddressSelected 1434 && mApnNameToTunnelConfig.size() == 0 1435 && mPendingBringUpRequests.isEmpty()) { 1436 mNetwork = setupRequest.network(); 1437 mPendingBringUpRequests.add(tunnelRequestWrapper); 1438 selectEpdgAddress(setupRequest); 1439 break; 1440 } 1441 1442 // Service the request immediately when epdg address is available 1443 if (mIsEpdgAddressSelected) { 1444 onBringUpTunnel( 1445 setupRequest, 1446 tunnelRequestWrapper.getTunnelCallback(), 1447 tunnelRequestWrapper.getTunnelCallbackMetrics()); 1448 } else { 1449 mPendingBringUpRequests.add(tunnelRequestWrapper); 1450 } 1451 break; 1452 1453 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE: 1454 EpdgSelectorResult selectorResult = (EpdgSelectorResult) msg.obj; 1455 printRequestQueue("EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE"); 1456 1457 if (selectorResult.getTransactionId() != mTransactionId) { 1458 Log.e(TAG, "Mismatched transactionId"); 1459 break; 1460 } 1461 1462 if (mPendingBringUpRequests.isEmpty()) { 1463 Log.d(TAG, "Empty request queue"); 1464 break; 1465 } 1466 1467 if (selectorResult.getEpdgError().getErrorType() == IwlanError.NO_ERROR 1468 && selectorResult.getValidIpList() != null) { 1469 tunnelRequestWrapper = mPendingBringUpRequests.poll(); 1470 validateAndSetEpdgAddress(selectorResult.getValidIpList()); 1471 onBringUpTunnel( 1472 tunnelRequestWrapper.getSetupRequest(), 1473 tunnelRequestWrapper.getTunnelCallback(), 1474 tunnelRequestWrapper.getTunnelCallbackMetrics()); 1475 } else { 1476 IwlanError error = 1477 (selectorResult.getEpdgError().getErrorType() 1478 == IwlanError.NO_ERROR) 1479 ? new IwlanError( 1480 IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED) 1481 : selectorResult.getEpdgError(); 1482 failAllPendingRequests(error); 1483 } 1484 break; 1485 1486 case EVENT_CHILD_SESSION_OPENED: 1487 TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj; 1488 apnName = tunnelOpenedData.mApnName; 1489 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1490 1491 tunnelConfig.setDnsAddrList(tunnelOpenedData.mInternalDnsServers); 1492 tunnelConfig.setInternalAddrList(tunnelOpenedData.mInternalAddresses); 1493 1494 IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface(); 1495 1496 for (LinkAddress address : tunnelConfig.getInternalAddrList()) { 1497 try { 1498 tunnelInterface.addAddress( 1499 address.getAddress(), address.getPrefixLength()); 1500 } catch (IOException e) { 1501 Log.e(TAG, "Adding internal addresses to interface failed."); 1502 } 1503 } 1504 1505 TunnelLinkProperties linkProperties = 1506 TunnelLinkProperties.builder() 1507 .setInternalAddresses(tunnelConfig.getInternalAddrList()) 1508 .setDnsAddresses(tunnelConfig.getDnsAddrList()) 1509 .setPcscfAddresses(tunnelConfig.getPcscfAddrList()) 1510 .setIfaceName(tunnelConfig.getIface().getInterfaceName()) 1511 .setSliceInfo(tunnelConfig.getSliceInfo()) 1512 .build(); 1513 tunnelConfig.getTunnelCallback().onOpened(apnName, linkProperties); 1514 1515 mIkeTunnelEstablishmentDuration = 1516 System.currentTimeMillis() - mIkeTunnelEstablishmentStartTime; 1517 mIkeTunnelEstablishmentStartTime = 0; 1518 tunnelConfig 1519 .getTunnelCallbackMetrics() 1520 .onOpened( 1521 apnName, 1522 mEpdgAddress.getHostAddress(), 1523 (int) mEpdgServerSelectionDuration, 1524 (int) mIkeTunnelEstablishmentDuration); 1525 1526 reportIwlanError(apnName, new IwlanError(IwlanError.NO_ERROR)); 1527 1528 setIsEpdgAddressSelected(true); 1529 mValidEpdgInfo.resetIndex(); 1530 printRequestQueue("EVENT_CHILD_SESSION_OPENED"); 1531 serviceAllPendingRequests(); 1532 break; 1533 1534 case EVENT_IKE_SESSION_CLOSED: 1535 printRequestQueue("EVENT_IKE_SESSION_CLOSED"); 1536 SessionClosedData sessionClosedData = (SessionClosedData) msg.obj; 1537 apnName = sessionClosedData.mApnName; 1538 1539 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1540 if (tunnelConfig == null) { 1541 Log.e(TAG, "No callback found for apn: " + apnName); 1542 return; 1543 } 1544 1545 // If IKE session closed exceptionally, we retrieve IwlanError directly from the 1546 // exception; otherwise, it is still possible that we triggered an IKE session 1547 // close due to an error (eg. IwlanError.TUNNEL_TRANSFORM_FAILED), or because 1548 // the Child session closed exceptionally; in which case, we attempt to retrieve 1549 // the stored error (if any) from TunnelConfig. 1550 IwlanError iwlanError; 1551 if (sessionClosedData.mIwlanError.getErrorType() != IwlanError.NO_ERROR) { 1552 iwlanError = sessionClosedData.mIwlanError; 1553 } else { 1554 // If IKE session setup failed without error cause, Iwlan reports 1555 // NETWORK_FAILURE instead of NO_ERROR 1556 if (!tunnelConfig.hasTunnelOpened()) { 1557 iwlanError = new IwlanError(IwlanError.NETWORK_FAILURE); 1558 } else { 1559 iwlanError = tunnelConfig.getError(); 1560 } 1561 } 1562 1563 IpSecManager.IpSecTunnelInterface iface = tunnelConfig.getIface(); 1564 if (iface != null) { 1565 iface.close(); 1566 } 1567 1568 if (!tunnelConfig.hasTunnelOpened()) { 1569 if (tunnelConfig.isBackoffTimeValid()) { 1570 reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime()); 1571 } else { 1572 reportIwlanError(apnName, iwlanError); 1573 } 1574 } 1575 1576 Log.d(TAG, "Tunnel Closed: " + iwlanError); 1577 tunnelConfig.getTunnelCallback().onClosed(apnName, iwlanError); 1578 1579 if (!mIsEpdgAddressSelected) { 1580 failAllPendingRequests(iwlanError); 1581 tunnelConfig.getTunnelCallbackMetrics().onClosed(apnName, null, 0, 0); 1582 } else { 1583 mIkeTunnelEstablishmentDuration = 1584 mIkeTunnelEstablishmentStartTime > 0 1585 ? System.currentTimeMillis() 1586 - mIkeTunnelEstablishmentStartTime 1587 : 0; 1588 mIkeTunnelEstablishmentStartTime = 0; 1589 1590 tunnelConfig 1591 .getTunnelCallbackMetrics() 1592 .onClosed( 1593 apnName, 1594 mEpdgAddress.getHostAddress(), 1595 (int) mEpdgServerSelectionDuration, 1596 (int) mIkeTunnelEstablishmentDuration); 1597 } 1598 1599 mApnNameToTunnelConfig.remove(apnName); 1600 if (mApnNameToTunnelConfig.size() == 0 && mPendingBringUpRequests.isEmpty()) { 1601 resetTunnelManagerState(); 1602 } 1603 break; 1604 1605 case EVENT_UPDATE_NETWORK: 1606 UpdateNetworkWrapper updatedNetwork = (UpdateNetworkWrapper) msg.obj; 1607 apnName = updatedNetwork.getApnName(); 1608 Network network = updatedNetwork.getNetwork(); 1609 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1610 1611 // Update the global cache if they aren't equal 1612 if (mNetwork == null || !mNetwork.equals(network)) { 1613 Log.d(TAG, "Updating mNetwork to " + network); 1614 mNetwork = network; 1615 } 1616 1617 if (tunnelConfig == null) { 1618 Log.d(TAG, "Update Network request: No tunnel exists for apn: " + apnName); 1619 } else { 1620 Log.d(TAG, "Updating Network for apn: " + apnName + " Network: " + network); 1621 tunnelConfig.getIkeSession().setNetwork(network); 1622 } 1623 break; 1624 1625 case EVENT_TUNNEL_BRINGDOWN_REQUEST: 1626 apnName = (String) msg.obj; 1627 int forceClose = msg.arg1; 1628 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1629 if (tunnelConfig == null) { 1630 Log.d( 1631 TAG, 1632 "Bringdown request: No tunnel exists for apn: " 1633 + apnName 1634 + "forced: " 1635 + forceClose); 1636 } else { 1637 if (forceClose == 1) { 1638 tunnelConfig.getIkeSession().kill(); 1639 } else { 1640 tunnelConfig.getIkeSession().close(); 1641 } 1642 } 1643 int numClosed = closePendingRequestsForApn(apnName); 1644 if (numClosed > 0) { 1645 Log.d(TAG, "Closed " + numClosed + " pending requests for apn: " + apnName); 1646 } 1647 break; 1648 1649 case EVENT_IPSEC_TRANSFORM_CREATED: 1650 IpsecTransformData transformData = (IpsecTransformData) msg.obj; 1651 apnName = transformData.getApnName(); 1652 IpSecManager ipSecManager = mContext.getSystemService(IpSecManager.class); 1653 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1654 1655 if (tunnelConfig.getIface() == null) { 1656 if (mLocalAddresses == null 1657 || mLocalAddresses.size() == 0 1658 || ipSecManager == null) { 1659 Log.e(TAG, "No local addresses found."); 1660 closeIkeSession( 1661 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 1662 return; 1663 } 1664 1665 try { 1666 if (mEpdgAddress instanceof Inet4Address 1667 && mProtoFilter == EpdgSelector.PROTO_FILTER_IPV6) { 1668 mLocalAddresses = 1669 IwlanHelper.getStackedAddressesForNetwork( 1670 mNetwork, mContext); 1671 } 1672 InetAddress localAddress = 1673 (mEpdgAddress instanceof Inet4Address) 1674 ? IwlanHelper.getIpv4Address(mLocalAddresses) 1675 : IwlanHelper.getIpv6Address(mLocalAddresses); 1676 Log.d(TAG, "Local address = " + localAddress); 1677 tunnelConfig.setIface( 1678 ipSecManager.createIpSecTunnelInterface( 1679 localAddress, mEpdgAddress, mNetwork)); 1680 } catch (IpSecManager.ResourceUnavailableException | IOException e) { 1681 Log.e(TAG, "Failed to create tunnel interface. " + e); 1682 closeIkeSession( 1683 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 1684 return; 1685 } 1686 } 1687 1688 try { 1689 ipSecManager.applyTunnelModeTransform( 1690 tunnelConfig.getIface(), 1691 transformData.getDirection(), 1692 transformData.getTransform()); 1693 } catch (IOException | IllegalArgumentException e) { 1694 // If the IKE session was closed before the transform could be applied, the 1695 // IpSecService will throw an IAE on processing the IpSecTunnelInterface id. 1696 Log.e(TAG, "Failed to apply tunnel transform." + e); 1697 closeIkeSession( 1698 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 1699 } 1700 break; 1701 1702 case EVENT_IPSEC_TRANSFORM_DELETED: 1703 transformData = (IpsecTransformData) msg.obj; 1704 IpSecTransform transform = transformData.getTransform(); 1705 transform.close(); 1706 break; 1707 1708 case EVENT_CHILD_SESSION_CLOSED: 1709 sessionClosedData = (SessionClosedData) msg.obj; 1710 apnName = sessionClosedData.mApnName; 1711 1712 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1713 if (tunnelConfig == null) { 1714 Log.d(TAG, "No tunnel callback for apn: " + apnName); 1715 return; 1716 } 1717 tunnelConfig.setError(sessionClosedData.mIwlanError); 1718 tunnelConfig.getIkeSession().close(); 1719 break; 1720 1721 case EVENT_IKE_SESSION_OPENED: 1722 IkeSessionOpenedData ikeSessionOpenedData = (IkeSessionOpenedData) msg.obj; 1723 apnName = ikeSessionOpenedData.mApnName; 1724 IkeSessionConfiguration sessionConfiguration = 1725 ikeSessionOpenedData.mIkeSessionConfiguration; 1726 1727 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1728 tunnelConfig.setPcscfAddrList(sessionConfiguration.getPcscfServers()); 1729 1730 boolean enabledFastReauth = 1731 (boolean) 1732 getConfig( 1733 CarrierConfigManager.Iwlan 1734 .KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL); 1735 Log.d( 1736 TAG, 1737 "CarrierConfigManager.Iwlan.KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL " 1738 + enabledFastReauth); 1739 1740 if (enabledFastReauth) { 1741 EapInfo eapInfo = sessionConfiguration.getEapInfo(); 1742 if (eapInfo != null && eapInfo instanceof EapAkaInfo) { 1743 mNextReauthId = ((EapAkaInfo) eapInfo).getReauthId(); 1744 Log.d(TAG, "Update ReauthId: " + Arrays.toString(mNextReauthId)); 1745 } else { 1746 mNextReauthId = null; 1747 } 1748 } 1749 break; 1750 1751 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED: 1752 IkeSessionConnectionInfoData ikeSessionConnectionInfoData = 1753 (IkeSessionConnectionInfoData) msg.obj; 1754 network = ikeSessionConnectionInfoData.mIkeSessionConnectionInfo.getNetwork(); 1755 apnName = ikeSessionConnectionInfoData.mApnName; 1756 1757 ConnectivityManager connectivityManager = 1758 mContext.getSystemService(ConnectivityManager.class); 1759 if (connectivityManager.getLinkProperties(network) == null) { 1760 Log.e(TAG, "Network " + network + " has null LinkProperties!"); 1761 return; 1762 } 1763 1764 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1765 tunnelInterface = tunnelConfig.getIface(); 1766 try { 1767 tunnelInterface.setUnderlyingNetwork(network); 1768 } catch (IOException | IllegalArgumentException e) { 1769 Log.e( 1770 TAG, 1771 "Failed to update underlying network for apn: " 1772 + apnName 1773 + " exception: " 1774 + e); 1775 } 1776 break; 1777 1778 default: 1779 throw new IllegalStateException("Unexpected value: " + msg.what); 1780 } 1781 } 1782 TmHandler(Looper looper)1783 TmHandler(Looper looper) { 1784 super(looper); 1785 } 1786 } 1787 closeIkeSession(String apnName, IwlanError error)1788 private void closeIkeSession(String apnName, IwlanError error) { 1789 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1790 tunnelConfig.setError(error); 1791 tunnelConfig.getIkeSession().close(); 1792 } 1793 selectEpdgAddress(TunnelSetupRequest setupRequest)1794 private void selectEpdgAddress(TunnelSetupRequest setupRequest) { 1795 mLocalAddresses = getAddressForNetwork(mNetwork, mContext); 1796 if (mLocalAddresses == null || mLocalAddresses.size() == 0) { 1797 Log.e(TAG, "No local addresses available."); 1798 failAllPendingRequests( 1799 new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED)); 1800 return; 1801 } 1802 1803 mProtoFilter = EpdgSelector.PROTO_FILTER_IPV4V6; 1804 if (!IwlanHelper.hasIpv6Address(mLocalAddresses)) { 1805 mProtoFilter = EpdgSelector.PROTO_FILTER_IPV4; 1806 } 1807 if (!IwlanHelper.hasIpv4Address(mLocalAddresses)) { 1808 mProtoFilter = EpdgSelector.PROTO_FILTER_IPV6; 1809 } 1810 1811 mEpdgServerSelectionStartTime = System.currentTimeMillis(); 1812 EpdgSelector epdgSelector = getEpdgSelector(); 1813 IwlanError epdgError = 1814 epdgSelector.getValidatedServerList( 1815 ++mTransactionId, 1816 mProtoFilter, 1817 setupRequest.isRoaming(), 1818 setupRequest.isEmergency(), 1819 mNetwork, 1820 mSelectorCallback); 1821 1822 if (epdgError.getErrorType() != IwlanError.NO_ERROR) { 1823 Log.e(TAG, "Epdg address selection failed with error:" + epdgError); 1824 failAllPendingRequests(epdgError); 1825 } 1826 } 1827 1828 @VisibleForTesting getEpdgSelector()1829 EpdgSelector getEpdgSelector() { 1830 return EpdgSelector.getSelectorInstance(mContext, mSlotId); 1831 } 1832 1833 @VisibleForTesting closePendingRequestsForApn(String apnName)1834 int closePendingRequestsForApn(String apnName) { 1835 int numRequestsClosed = 0; 1836 int queueSize = mPendingBringUpRequests.size(); 1837 if (queueSize == 0) { 1838 return numRequestsClosed; 1839 } 1840 1841 for (int count = 0; count < queueSize; count++) { 1842 TunnelRequestWrapper requestWrapper = mPendingBringUpRequests.poll(); 1843 if (requestWrapper.getSetupRequest().apnName() == apnName) { 1844 requestWrapper 1845 .getTunnelCallback() 1846 .onClosed(apnName, new IwlanError(IwlanError.NO_ERROR)); 1847 1848 requestWrapper 1849 .getTunnelCallbackMetrics() 1850 .onClosed( 1851 apnName, 1852 mEpdgAddress == null ? null : mEpdgAddress.getHostAddress(), 1853 0, 1854 0); 1855 numRequestsClosed++; 1856 } else { 1857 mPendingBringUpRequests.add(requestWrapper); 1858 } 1859 } 1860 return numRequestsClosed; 1861 } 1862 1863 @VisibleForTesting validateAndSetEpdgAddress(List<InetAddress> selectorResultList)1864 void validateAndSetEpdgAddress(List<InetAddress> selectorResultList) { 1865 List<InetAddress> addrList = mValidEpdgInfo.getAddrList(); 1866 if (addrList == null || !addrList.equals(selectorResultList)) { 1867 Log.d(TAG, "Update ePDG address list."); 1868 mValidEpdgInfo.setAddrList(selectorResultList); 1869 addrList = mValidEpdgInfo.getAddrList(); 1870 } 1871 1872 int index = mValidEpdgInfo.getIndex(); 1873 Log.d( 1874 TAG, 1875 "Valid ePDG Address List: " 1876 + Arrays.toString(addrList.toArray()) 1877 + ", index = " 1878 + index); 1879 mEpdgAddress = addrList.get(index); 1880 mValidEpdgInfo.incrementIndex(); 1881 } 1882 1883 @VisibleForTesting resetTunnelManagerState()1884 void resetTunnelManagerState() { 1885 Log.d(TAG, "resetTunnelManagerState"); 1886 mEpdgAddress = null; 1887 setIsEpdgAddressSelected(false); 1888 mNetwork = null; 1889 mPendingBringUpRequests = new LinkedList<>(); 1890 mApnNameToTunnelConfig = new ConcurrentHashMap<>(); 1891 mLocalAddresses = null; 1892 } 1893 serviceAllPendingRequests()1894 private void serviceAllPendingRequests() { 1895 while (!mPendingBringUpRequests.isEmpty()) { 1896 Log.d(TAG, "serviceAllPendingRequests"); 1897 TunnelRequestWrapper request = mPendingBringUpRequests.poll(); 1898 onBringUpTunnel( 1899 request.getSetupRequest(), 1900 request.getTunnelCallback(), 1901 request.getTunnelCallbackMetrics()); 1902 } 1903 } 1904 failAllPendingRequests(IwlanError error)1905 private void failAllPendingRequests(IwlanError error) { 1906 while (!mPendingBringUpRequests.isEmpty()) { 1907 Log.d(TAG, "failAllPendingRequests"); 1908 TunnelRequestWrapper request = mPendingBringUpRequests.poll(); 1909 TunnelSetupRequest setupRequest = request.getSetupRequest(); 1910 reportIwlanError(setupRequest.apnName(), error); 1911 request.getTunnelCallback().onClosed(setupRequest.apnName(), error); 1912 request.getTunnelCallbackMetrics() 1913 .onClosed( 1914 setupRequest.apnName(), 1915 mEpdgAddress == null ? null : mEpdgAddress.getHostAddress(), 1916 0, 1917 0); 1918 } 1919 } 1920 1921 // Prints mPendingBringUpRequests printRequestQueue(String info)1922 private void printRequestQueue(String info) { 1923 Log.d(TAG, info); 1924 Log.d( 1925 TAG, 1926 "mPendingBringUpRequests: " + Arrays.toString(mPendingBringUpRequests.toArray())); 1927 } 1928 1929 // Update Network wrapper 1930 private static final class UpdateNetworkWrapper { 1931 private final Network mNetwork; 1932 private final String mApnName; 1933 UpdateNetworkWrapper(Network network, String apnName)1934 private UpdateNetworkWrapper(Network network, String apnName) { 1935 mNetwork = network; 1936 mApnName = apnName; 1937 } 1938 getApnName()1939 public String getApnName() { 1940 return mApnName; 1941 } 1942 getNetwork()1943 public Network getNetwork() { 1944 return mNetwork; 1945 } 1946 } 1947 // Tunnel request + tunnel callback 1948 private static final class TunnelRequestWrapper { 1949 private final TunnelSetupRequest mSetupRequest; 1950 1951 private final TunnelCallback mTunnelCallback; 1952 private final TunnelCallbackMetrics mTunnelCallbackMetrics; 1953 TunnelRequestWrapper( TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics)1954 private TunnelRequestWrapper( 1955 TunnelSetupRequest setupRequest, 1956 TunnelCallback tunnelCallback, 1957 TunnelCallbackMetrics tunnelCallbackMetrics) { 1958 mTunnelCallback = tunnelCallback; 1959 mSetupRequest = setupRequest; 1960 mTunnelCallbackMetrics = tunnelCallbackMetrics; 1961 } 1962 getSetupRequest()1963 public TunnelSetupRequest getSetupRequest() { 1964 return mSetupRequest; 1965 } 1966 getTunnelCallback()1967 public TunnelCallback getTunnelCallback() { 1968 return mTunnelCallback; 1969 } 1970 getTunnelCallbackMetrics()1971 public TunnelCallbackMetrics getTunnelCallbackMetrics() { 1972 return mTunnelCallbackMetrics; 1973 } 1974 } 1975 1976 private static final class EpdgSelectorResult { 1977 private final List<InetAddress> mValidIpList; 1978 getValidIpList()1979 public List<InetAddress> getValidIpList() { 1980 return mValidIpList; 1981 } 1982 getEpdgError()1983 public IwlanError getEpdgError() { 1984 return mEpdgError; 1985 } 1986 getTransactionId()1987 public int getTransactionId() { 1988 return mTransactionId; 1989 } 1990 1991 private final IwlanError mEpdgError; 1992 private final int mTransactionId; 1993 EpdgSelectorResult( List<InetAddress> validIpList, IwlanError epdgError, int transactionId)1994 private EpdgSelectorResult( 1995 List<InetAddress> validIpList, IwlanError epdgError, int transactionId) { 1996 mValidIpList = validIpList; 1997 mEpdgError = epdgError; 1998 mTransactionId = transactionId; 1999 } 2000 } 2001 2002 // Data received from IkeSessionStateMachine on successful EVENT_CHILD_SESSION_OPENED. 2003 private static final class TunnelOpenedData extends IkeEventData { 2004 final List<InetAddress> mInternalDnsServers; 2005 final List<LinkAddress> mInternalAddresses; 2006 TunnelOpenedData( String apnName, int token, List<InetAddress> internalDnsServers, List<LinkAddress> internalAddresses)2007 private TunnelOpenedData( 2008 String apnName, 2009 int token, 2010 List<InetAddress> internalDnsServers, 2011 List<LinkAddress> internalAddresses) { 2012 super(apnName, token); 2013 mInternalDnsServers = internalDnsServers; 2014 mInternalAddresses = internalAddresses; 2015 } 2016 } 2017 2018 // Data received from IkeSessionStateMachine on successful EVENT_IKE_SESSION_OPENED. 2019 private static final class IkeSessionOpenedData extends IkeEventData { 2020 final IkeSessionConfiguration mIkeSessionConfiguration; 2021 IkeSessionOpenedData( String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration)2022 private IkeSessionOpenedData( 2023 String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration) { 2024 super(apnName, token); 2025 mIkeSessionConfiguration = ikeSessionConfiguration; 2026 } 2027 } 2028 2029 private static final class IkeSessionConnectionInfoData extends IkeEventData { 2030 final IkeSessionConnectionInfo mIkeSessionConnectionInfo; 2031 IkeSessionConnectionInfoData( String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo)2032 private IkeSessionConnectionInfoData( 2033 String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo) { 2034 super(apnName, token); 2035 mIkeSessionConnectionInfo = ikeSessionConnectionInfo; 2036 } 2037 } 2038 2039 // Data received from IkeSessionStateMachine if either IKE session or Child session have been 2040 // closed, normally or exceptionally. 2041 private static final class SessionClosedData extends IkeEventData { 2042 final IwlanError mIwlanError; 2043 SessionClosedData(String apnName, int token, IwlanError iwlanError)2044 private SessionClosedData(String apnName, int token, IwlanError iwlanError) { 2045 super(apnName, token); 2046 mIwlanError = iwlanError; 2047 } 2048 } 2049 releaseInstance()2050 public void releaseInstance() { 2051 mHandlerThread.quit(); 2052 mTunnelManagerInstances.remove(mSlotId); 2053 } 2054 2055 private static final class IpsecTransformData extends IkeEventData { 2056 private final IpSecTransform mTransform; 2057 private final int mDirection; 2058 IpsecTransformData( IpSecTransform transform, int direction, String apnName, int token)2059 private IpsecTransformData( 2060 IpSecTransform transform, int direction, String apnName, int token) { 2061 super(apnName, token); 2062 mTransform = transform; 2063 mDirection = direction; 2064 } 2065 getTransform()2066 public IpSecTransform getTransform() { 2067 return mTransform; 2068 } 2069 getDirection()2070 public int getDirection() { 2071 return mDirection; 2072 } 2073 getApnName()2074 public String getApnName() { 2075 return super.mApnName; 2076 } 2077 } 2078 2079 private abstract static class IkeEventData { 2080 final String mApnName; 2081 final int mToken; 2082 IkeEventData(String apnName, int token)2083 private IkeEventData(String apnName, int token) { 2084 mApnName = apnName; 2085 mToken = token; 2086 } 2087 } 2088 2089 private static final class EpdgInfo { 2090 private List<InetAddress> mAddrList; 2091 private int mIndex; 2092 EpdgInfo()2093 private EpdgInfo() { 2094 mAddrList = null; 2095 mIndex = 0; 2096 } 2097 getAddrList()2098 public List<InetAddress> getAddrList() { 2099 return mAddrList; 2100 } 2101 setAddrList(@onNull List<InetAddress> AddrList)2102 public void setAddrList(@NonNull List<InetAddress> AddrList) { 2103 mAddrList = AddrList; 2104 resetIndex(); 2105 } 2106 getIndex()2107 public int getIndex() { 2108 return mIndex; 2109 } 2110 incrementIndex()2111 public void incrementIndex() { 2112 if (getIndex() >= getAddrList().size() - 1) { 2113 resetIndex(); 2114 } else { 2115 mIndex++; 2116 } 2117 } 2118 resetIndex()2119 public void resetIndex() { 2120 mIndex = 0; 2121 } 2122 } 2123 getRetransmissionTimeoutsFromConfig()2124 private int[] getRetransmissionTimeoutsFromConfig() { 2125 int[] timeList = 2126 (int[]) getConfig(CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY); 2127 boolean isValid = true; 2128 if (timeList == null 2129 || timeList.length == 0 2130 || timeList.length > IKE_RETRANS_MAX_ATTEMPTS_MAX) { 2131 isValid = false; 2132 } 2133 for (int time : timeList) { 2134 if (time < IKE_RETRANS_TIMEOUT_MS_MIN || time > IKE_RETRANS_TIMEOUT_MS_MAX) { 2135 isValid = false; 2136 break; 2137 } 2138 } 2139 if (!isValid) { 2140 timeList = 2141 (int[]) 2142 IwlanHelper.getDefaultConfig( 2143 CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY); 2144 } 2145 Log.d(TAG, "getRetransmissionTimeoutsFromConfig: " + Arrays.toString(timeList)); 2146 return timeList; 2147 } 2148 getDpdDelayFromConfig()2149 private int getDpdDelayFromConfig() { 2150 int dpdDelay = (int) getConfig(CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT); 2151 if (dpdDelay < IKE_DPD_DELAY_SEC_MIN || dpdDelay > IKE_DPD_DELAY_SEC_MAX) { 2152 dpdDelay = 2153 (int) 2154 IwlanHelper.getDefaultConfig( 2155 CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT); 2156 } 2157 return dpdDelay; 2158 } 2159 2160 /** 2161 * Decodes backoff time as per TS 124 008 10.5.7.4a Bits 5 to 1 represent the binary coded timer 2162 * value 2163 * 2164 * <p>Bits 6 to 8 defines the timer value unit for the GPRS timer as follows: Bits 8 7 6 0 0 0 2165 * value is incremented in multiples of 10 minutes 0 0 1 value is incremented in multiples of 1 2166 * hour 0 1 0 value is incremented in multiples of 10 hours 0 1 1 value is incremented in 2167 * multiples of 2 seconds 1 0 0 value is incremented in multiples of 30 seconds 1 0 1 value is 2168 * incremented in multiples of 1 minute 1 1 0 value is incremented in multiples of 1 hour 1 1 1 2169 * value indicates that the timer is deactivated. 2170 * 2171 * @param backoffTimerByte Byte value obtained from ike 2172 * @return long time value in seconds. -1 if the timer needs to be deactivated. 2173 */ decodeBackoffTime(byte backoffTimeByte)2174 private static long decodeBackoffTime(byte backoffTimeByte) { 2175 final int BACKOFF_TIME_VALUE_MASK = 0x1F; 2176 final int BACKOFF_TIMER_UNIT_MASK = 0xE0; 2177 final Long[] BACKOFF_TIMER_UNIT_INCREMENT_SECS = { 2178 10L * 60L, // 10 mins 2179 1L * 60L * 60L, // 1 hour 2180 10L * 60L * 60L, // 10 hours 2181 2L, // 2 seconds 2182 30L, // 30 seconds 2183 1L * 60L, // 1 minute 2184 1L * 60L * 60L, // 1 hour 2185 }; 2186 2187 long time = backoffTimeByte & BACKOFF_TIME_VALUE_MASK; 2188 int timerUnit = (backoffTimeByte & BACKOFF_TIMER_UNIT_MASK) >> 5; 2189 if (timerUnit >= BACKOFF_TIMER_UNIT_INCREMENT_SECS.length) { 2190 return -1; 2191 } 2192 time *= BACKOFF_TIMER_UNIT_INCREMENT_SECS[timerUnit]; 2193 return time; 2194 } 2195 2196 @VisibleForTesting getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest)2197 String getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest) { 2198 String apnName = setupRequest.apnName(); 2199 return apnName; 2200 } 2201 2202 @VisibleForTesting putApnNameToTunnelConfig( String apnName, IkeSession ikeSession, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics, InetAddress srcIpv6Addr, int srcIPv6AddrPrefixLen)2203 void putApnNameToTunnelConfig( 2204 String apnName, 2205 IkeSession ikeSession, 2206 TunnelCallback tunnelCallback, 2207 TunnelCallbackMetrics tunnelCallbackMetrics, 2208 InetAddress srcIpv6Addr, 2209 int srcIPv6AddrPrefixLen) { 2210 mApnNameToTunnelConfig.put( 2211 apnName, 2212 new TunnelConfig( 2213 ikeSession, 2214 tunnelCallback, 2215 tunnelCallbackMetrics, 2216 srcIpv6Addr, 2217 srcIPv6AddrPrefixLen)); 2218 Log.d(TAG, "Added apn: " + apnName + " to TunnelConfig"); 2219 } 2220 2221 @VisibleForTesting incrementAndGetCurrentTokenForApn(String apnName)2222 int incrementAndGetCurrentTokenForApn(String apnName) { 2223 final int currentToken = 2224 mApnNameToCurrentToken.compute( 2225 apnName, (apn, token) -> token == null ? 0 : token + 1); 2226 Log.d(TAG, "Added token: " + currentToken + " for apn: " + apnName); 2227 return currentToken; 2228 } 2229 2230 @VisibleForTesting isN1ModeSupported()2231 boolean isN1ModeSupported() { 2232 int[] nrCarrierCaps = 2233 getConfig(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY); 2234 Log.d(TAG, "KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY : " + Arrays.toString(nrCarrierCaps)); 2235 if (Arrays.stream(nrCarrierCaps) 2236 .anyMatch(cap -> cap == CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA)) { 2237 return true; 2238 } else return false; 2239 } 2240 2241 @VisibleForTesting isTunnelConfigContainExistApn(String apnName)2242 boolean isTunnelConfigContainExistApn(String apnName) { 2243 boolean ret = mApnNameToTunnelConfig.containsKey(apnName); 2244 return ret; 2245 } 2246 2247 @VisibleForTesting getAddressForNetwork(Network network, Context context)2248 List<InetAddress> getAddressForNetwork(Network network, Context context) { 2249 List<InetAddress> ret = IwlanHelper.getAddressesForNetwork(network, context); 2250 return ret; 2251 } 2252 2253 @VisibleForTesting getSelectorCallback()2254 EpdgSelector.EpdgSelectorCallback getSelectorCallback() { 2255 return mSelectorCallback; 2256 } 2257 2258 @VisibleForTesting getIkeSessionCreator()2259 IkeSessionCreator getIkeSessionCreator() { 2260 return mIkeSessionCreator; 2261 } 2262 2263 @VisibleForTesting sendSelectionRequestComplete( ArrayList<InetAddress> validIPList, IwlanError result, int transactionId)2264 void sendSelectionRequestComplete( 2265 ArrayList<InetAddress> validIPList, IwlanError result, int transactionId) { 2266 mEpdgServerSelectionDuration = System.currentTimeMillis() - mEpdgServerSelectionStartTime; 2267 mEpdgServerSelectionStartTime = 0; 2268 EpdgSelectorResult epdgSelectorResult = 2269 new EpdgSelectorResult(validIPList, result, transactionId); 2270 mHandler.sendMessage( 2271 mHandler.obtainMessage( 2272 EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE, epdgSelectorResult)); 2273 } 2274 isValidApnProtocol(int proto)2275 static boolean isValidApnProtocol(int proto) { 2276 return (proto == ApnSetting.PROTOCOL_IP 2277 || proto == ApnSetting.PROTOCOL_IPV4V6 2278 || proto == ApnSetting.PROTOCOL_IPV6); 2279 } 2280 isObsoleteToken(String apnName, int token)2281 boolean isObsoleteToken(String apnName, int token) { 2282 if (!mApnNameToCurrentToken.containsKey(apnName)) { 2283 return true; 2284 } 2285 return token != mApnNameToCurrentToken.get(apnName); 2286 } 2287 eventToString(int event)2288 private static String eventToString(int event) { 2289 switch (event) { 2290 case EVENT_TUNNEL_BRINGUP_REQUEST: 2291 return "EVENT_TUNNEL_BRINGUP_REQUEST"; 2292 case EVENT_TUNNEL_BRINGDOWN_REQUEST: 2293 return "EVENT_TUNNEL_BRINGDOWN_REQUEST"; 2294 case EVENT_CHILD_SESSION_OPENED: 2295 return "EVENT_CHILD_SESSION_OPENED"; 2296 case EVENT_CHILD_SESSION_CLOSED: 2297 return "EVENT_CHILD_SESSION_CLOSED"; 2298 case EVENT_IKE_SESSION_CLOSED: 2299 return "EVENT_IKE_SESSION_CLOSED"; 2300 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE: 2301 return "EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE"; 2302 case EVENT_IPSEC_TRANSFORM_CREATED: 2303 return "EVENT_IPSEC_TRANSFORM_CREATED"; 2304 case EVENT_IPSEC_TRANSFORM_DELETED: 2305 return "EVENT_IPSEC_TRANSFORM_DELETED"; 2306 case EVENT_UPDATE_NETWORK: 2307 return "EVENT_UPDATE_NETWORK"; 2308 case EVENT_IKE_SESSION_OPENED: 2309 return "EVENT_IKE_SESSION_OPENED"; 2310 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED: 2311 return "EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED"; 2312 default: 2313 return "Unknown(" + event + ")"; 2314 } 2315 } 2316 2317 @VisibleForTesting getTmIkeSessionCallback(String apnName, int token)2318 TmIkeSessionCallback getTmIkeSessionCallback(String apnName, int token) { 2319 return new TmIkeSessionCallback(apnName, token); 2320 } 2321 2322 @VisibleForTesting setIsEpdgAddressSelected(boolean value)2323 void setIsEpdgAddressSelected(boolean value) { 2324 mIsEpdgAddressSelected = value; 2325 } 2326 2327 @VisibleForTesting getTunnelConfigForApn(String apnName)2328 TunnelConfig getTunnelConfigForApn(String apnName) { 2329 return mApnNameToTunnelConfig.get(apnName); 2330 } 2331 2332 @VisibleForTesting getCurrentTokenForApn(String apnName)2333 int getCurrentTokenForApn(String apnName) { 2334 if (!mApnNameToCurrentToken.containsKey(apnName)) { 2335 throw new IllegalArgumentException("There is no token for apn: " + apnName); 2336 } 2337 return mApnNameToCurrentToken.get(apnName); 2338 } 2339 2340 @VisibleForTesting reportIwlanError(String apnName, IwlanError error)2341 long reportIwlanError(String apnName, IwlanError error) { 2342 return ErrorPolicyManager.getInstance(mContext, mSlotId).reportIwlanError(apnName, error); 2343 } 2344 2345 @VisibleForTesting reportIwlanError(String apnName, IwlanError error, long backOffTime)2346 long reportIwlanError(String apnName, IwlanError error, long backOffTime) { 2347 return ErrorPolicyManager.getInstance(mContext, mSlotId) 2348 .reportIwlanError(apnName, error, backOffTime); 2349 } 2350 2351 @VisibleForTesting getLastError(String apnName)2352 IwlanError getLastError(String apnName) { 2353 return ErrorPolicyManager.getInstance(mContext, mSlotId).getLastError(apnName); 2354 } 2355 2356 @VisibleForTesting canBringUpTunnel(String apnName)2357 boolean canBringUpTunnel(String apnName) { 2358 return ErrorPolicyManager.getInstance(mContext, mSlotId).canBringUpTunnel(apnName); 2359 } 2360 2361 @VisibleForTesting setEpdgAddress(InetAddress inetAddress)2362 void setEpdgAddress(InetAddress inetAddress) { 2363 mEpdgAddress = inetAddress; 2364 } 2365 dump(FileDescriptor fd, PrintWriter pw, String[] args)2366 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2367 pw.println("---- EpdgTunnelManager ----"); 2368 pw.println("mIsEpdgAddressSelected: " + mIsEpdgAddressSelected); 2369 if (mEpdgAddress != null) { 2370 pw.println("mEpdgAddress: " + mEpdgAddress); 2371 } 2372 pw.println("mApnNameToTunnelConfig:\n"); 2373 for (Map.Entry<String, TunnelConfig> entry : mApnNameToTunnelConfig.entrySet()) { 2374 pw.println("APN: " + entry.getKey()); 2375 pw.println("TunnelConfig: " + entry.getValue()); 2376 pw.println(); 2377 } 2378 pw.println("---------------------------"); 2379 } 2380 } 2381