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.InetAddresses; 26 import android.net.IpPrefix; 27 import android.net.IpSecManager; 28 import android.net.IpSecTransform; 29 import android.net.LinkAddress; 30 import android.net.Network; 31 import android.net.eap.EapSessionConfig; 32 import android.net.ipsec.ike.ChildSaProposal; 33 import android.net.ipsec.ike.ChildSessionCallback; 34 import android.net.ipsec.ike.ChildSessionConfiguration; 35 import android.net.ipsec.ike.ChildSessionParams; 36 import android.net.ipsec.ike.IkeFqdnIdentification; 37 import android.net.ipsec.ike.IkeIdentification; 38 import android.net.ipsec.ike.IkeKeyIdIdentification; 39 import android.net.ipsec.ike.IkeRfc822AddrIdentification; 40 import android.net.ipsec.ike.IkeSaProposal; 41 import android.net.ipsec.ike.IkeSession; 42 import android.net.ipsec.ike.IkeSessionCallback; 43 import android.net.ipsec.ike.IkeSessionConfiguration; 44 import android.net.ipsec.ike.IkeSessionConnectionInfo; 45 import android.net.ipsec.ike.IkeSessionParams; 46 import android.net.ipsec.ike.IkeTrafficSelector; 47 import android.net.ipsec.ike.SaProposal; 48 import android.net.ipsec.ike.TunnelModeChildSessionParams; 49 import android.net.ipsec.ike.exceptions.IkeException; 50 import android.net.ipsec.ike.exceptions.IkeProtocolException; 51 import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer; 52 import android.net.ipsec.ike.ike3gpp.Ike3gppData; 53 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension; 54 import android.net.ipsec.ike.ike3gpp.Ike3gppN1ModeInformation; 55 import android.net.ipsec.ike.ike3gpp.Ike3gppParams; 56 import android.os.Handler; 57 import android.os.HandlerThread; 58 import android.os.Looper; 59 import android.os.Message; 60 import android.support.annotation.NonNull; 61 import android.telephony.CarrierConfigManager; 62 import android.telephony.TelephonyManager; 63 import android.telephony.data.ApnSetting; 64 import android.telephony.data.NetworkSliceInfo; 65 import android.util.Log; 66 67 import com.android.internal.annotations.VisibleForTesting; 68 69 import com.google.android.iwlan.ErrorPolicyManager; 70 import com.google.android.iwlan.IwlanError; 71 import com.google.android.iwlan.IwlanHelper; 72 73 import java.io.FileDescriptor; 74 import java.io.IOException; 75 import java.io.PrintWriter; 76 import java.net.Inet4Address; 77 import java.net.Inet6Address; 78 import java.net.InetAddress; 79 import java.nio.charset.StandardCharsets; 80 import java.util.ArrayList; 81 import java.util.Arrays; 82 import java.util.Collections; 83 import java.util.HashSet; 84 import java.util.LinkedList; 85 import java.util.List; 86 import java.util.Map; 87 import java.util.Queue; 88 import java.util.Set; 89 import java.util.concurrent.ConcurrentHashMap; 90 import java.util.concurrent.Executor; 91 import java.util.concurrent.Executors; 92 import java.util.concurrent.TimeUnit; 93 94 public class EpdgTunnelManager { 95 96 private Context mContext; 97 private final int mSlotId; 98 private HandlerThread mHandlerThread; 99 private Handler mHandler; 100 101 private static final int EVENT_TUNNEL_BRINGUP_REQUEST = 0; 102 private static final int EVENT_TUNNEL_BRINGDOWN_REQUEST = 1; 103 private static final int EVENT_CHILD_SESSION_OPENED = 2; 104 private static final int EVENT_CHILD_SESSION_CLOSED = 3; 105 private static final int EVENT_IKE_SESSION_CLOSED = 5; 106 private static final int EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE = 6; 107 private static final int EVENT_IPSEC_TRANSFORM_CREATED = 7; 108 private static final int EVENT_IPSEC_TRANSFORM_DELETED = 8; 109 private static final int EVENT_UPDATE_NETWORK = 9; 110 private static final int IKE_HARD_LIFETIME_SEC_MINIMUM = 300; 111 private static final int IKE_HARD_LIFETIME_SEC_MAXIMUM = 86400; 112 private static final int IKE_SOFT_LIFETIME_SEC_MINIMUM = 120; 113 private static final int CHILD_HARD_LIFETIME_SEC_MINIMUM = 300; 114 private static final int CHILD_HARD_LIFETIME_SEC_MAXIMUM = 14400; 115 private static final int CHILD_SOFT_LIFETIME_SEC_MINIMUM = 120; 116 private static final int LIFETIME_MARGIN_SEC_MINIMUM = (int) TimeUnit.MINUTES.toSeconds(1L); 117 private static final int IKE_RETRANS_TIMEOUT_MS_MIN = 500; 118 119 private static final int IKE_RETRANS_TIMEOUT_MS_MAX = (int) TimeUnit.MINUTES.toMillis(30L); 120 121 private static final int IKE_RETRANS_MAX_ATTEMPTS_MAX = 10; 122 private static final int IKE_DPD_DELAY_SEC_MIN = 20; 123 private static final int IKE_DPD_DELAY_SEC_MAX = 1800; // 30 minutes 124 private static final int NATT_KEEPALIVE_DELAY_SEC_MIN = 10; 125 private static final int NATT_KEEPALIVE_DELAY_SEC_MAX = 120; 126 127 private static final int TRAFFIC_SELECTOR_START_PORT = 0; 128 private static final int TRAFFIC_SELECTOR_END_PORT = 65535; 129 private static final String TRAFFIC_SELECTOR_IPV4_START_ADDR = "0.0.0.0"; 130 private static final String TRAFFIC_SELECTOR_IPV4_END_ADDR = "255.255.255.255"; 131 private static final String TRAFFIC_SELECTOR_IPV6_START_ADDR = "::"; 132 private static final String TRAFFIC_SELECTOR_IPV6_END_ADDR = 133 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; 134 135 private static Map<Integer, EpdgTunnelManager> mTunnelManagerInstances = 136 new ConcurrentHashMap<>(); 137 138 private Queue<TunnelRequestWrapper> mRequestQueue = new LinkedList<>(); 139 140 private EpdgInfo mValidEpdgInfo = new EpdgInfo(); 141 private InetAddress mEpdgAddress; 142 private Network mNetwork; 143 private int mTransactionId = 0; 144 private boolean mIsEpdgAddressSelected; 145 private IkeSessionCreator mIkeSessionCreator; 146 147 private Map<String, TunnelConfig> mApnNameToTunnelConfig = new ConcurrentHashMap<>(); 148 149 private final String TAG; 150 151 private List<InetAddress> mLocalAddresses; 152 153 private static final Set<Integer> VALID_DH_GROUPS; 154 private static final Set<Integer> VALID_KEY_LENGTHS; 155 private static final Set<Integer> VALID_PRF_ALGOS; 156 private static final Set<Integer> VALID_INTEGRITY_ALGOS; 157 private static final Set<Integer> VALID_ENCRYPTION_ALGOS; 158 159 private static final String CONFIG_TYPE_DH_GROUP = "dh group"; 160 private static final String CONFIG_TYPE_KEY_LEN = "alogrithm key length"; 161 private static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm"; 162 private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm"; 163 private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm"; 164 165 static { 166 VALID_DH_GROUPS = 167 Collections.unmodifiableSet( 168 new HashSet<>( 169 Arrays.asList( 170 SaProposal.DH_GROUP_1024_BIT_MODP, 171 SaProposal.DH_GROUP_1536_BIT_MODP, 172 SaProposal.DH_GROUP_2048_BIT_MODP))); 173 VALID_KEY_LENGTHS = 174 Collections.unmodifiableSet( 175 new HashSet<>( 176 Arrays.asList( 177 SaProposal.KEY_LEN_AES_128, 178 SaProposal.KEY_LEN_AES_192, 179 SaProposal.KEY_LEN_AES_256))); 180 181 VALID_ENCRYPTION_ALGOS = 182 Collections.unmodifiableSet( 183 new HashSet<>( 184 Arrays.asList( 185 SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, 186 SaProposal.ENCRYPTION_ALGORITHM_AES_CTR))); 187 188 VALID_INTEGRITY_ALGOS = 189 Collections.unmodifiableSet( 190 new HashSet<>( 191 Arrays.asList( 192 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96, 193 SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96, 194 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, 195 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, 196 SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256))); 197 198 VALID_PRF_ALGOS = 199 Collections.unmodifiableSet( 200 new HashSet<>( 201 Arrays.asList( 202 SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1, 203 SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC, 204 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256, 205 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384, 206 SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512))); 207 } 208 209 private final EpdgSelector.EpdgSelectorCallback mSelectorCallback = 210 new EpdgSelector.EpdgSelectorCallback() { 211 @Override 212 public void onServerListChanged( 213 int transactionId, ArrayList<InetAddress> validIPList) { 214 sendSelectionRequestComplete( 215 validIPList, new IwlanError(IwlanError.NO_ERROR), transactionId); 216 } 217 218 @Override 219 public void onError(int transactionId, IwlanError epdgSelectorError) { 220 sendSelectionRequestComplete(null, epdgSelectorError, transactionId); 221 } 222 }; 223 224 @VisibleForTesting 225 class TunnelConfig { 226 @NonNull final TunnelCallback mTunnelCallback; 227 // TODO: Change this to TunnelLinkProperties after removing autovalue 228 private List<InetAddress> mPcscfAddrList; 229 private List<InetAddress> mDnsAddrList; 230 private List<LinkAddress> mInternalAddrList; 231 232 private InetAddress mSrcIpv6Address; 233 private int mSrcIpv6AddressPrefixLen; 234 private NetworkSliceInfo mSliceInfo; 235 private boolean mIsBackoffTimeValid = false; 236 private long mBackoffTime; 237 getSliceInfo()238 public NetworkSliceInfo getSliceInfo() { 239 return mSliceInfo; 240 } 241 setSliceInfo(NetworkSliceInfo si)242 public void setSliceInfo(NetworkSliceInfo si) { 243 mSliceInfo = si; 244 } 245 isBackoffTimeValid()246 public boolean isBackoffTimeValid() { 247 return mIsBackoffTimeValid; 248 } 249 getBackoffTime()250 public long getBackoffTime() { 251 return mBackoffTime; 252 } 253 setBackoffTime(long backoffTime)254 public void setBackoffTime(long backoffTime) { 255 mIsBackoffTimeValid = true; 256 mBackoffTime = backoffTime; 257 } 258 259 @NonNull final IkeSession mIkeSession; 260 IwlanError mError; 261 private IpSecManager.IpSecTunnelInterface mIface; 262 TunnelConfig( IkeSession ikeSession, TunnelCallback tunnelCallback, InetAddress srcIpv6Addr, int srcIpv6PrefixLength)263 public TunnelConfig( 264 IkeSession ikeSession, 265 TunnelCallback tunnelCallback, 266 InetAddress srcIpv6Addr, 267 int srcIpv6PrefixLength) { 268 mTunnelCallback = tunnelCallback; 269 mIkeSession = ikeSession; 270 mError = new IwlanError(IwlanError.NO_ERROR); 271 mSrcIpv6Address = srcIpv6Addr; 272 mSrcIpv6AddressPrefixLen = srcIpv6PrefixLength; 273 } 274 275 @NonNull getTunnelCallback()276 TunnelCallback getTunnelCallback() { 277 return mTunnelCallback; 278 } 279 getPcscfAddrList()280 List<InetAddress> getPcscfAddrList() { 281 return mPcscfAddrList; 282 } 283 setPcscfAddrList(List<InetAddress> pcscfAddrList)284 void setPcscfAddrList(List<InetAddress> pcscfAddrList) { 285 mPcscfAddrList = pcscfAddrList; 286 } 287 getDnsAddrList()288 public List<InetAddress> getDnsAddrList() { 289 return mDnsAddrList; 290 } 291 setDnsAddrList(List<InetAddress> dnsAddrList)292 public void setDnsAddrList(List<InetAddress> dnsAddrList) { 293 this.mDnsAddrList = dnsAddrList; 294 } 295 getInternalAddrList()296 public List<LinkAddress> getInternalAddrList() { 297 return mInternalAddrList; 298 } 299 isPrefixSameAsSrcIP(LinkAddress laddr)300 boolean isPrefixSameAsSrcIP(LinkAddress laddr) { 301 if (laddr.isIpv6() && (laddr.getPrefixLength() == mSrcIpv6AddressPrefixLen)) { 302 IpPrefix assignedPrefix = new IpPrefix(laddr.getAddress(), laddr.getPrefixLength()); 303 IpPrefix srcPrefix = new IpPrefix(mSrcIpv6Address, mSrcIpv6AddressPrefixLen); 304 if (assignedPrefix.equals(srcPrefix)) { 305 return true; 306 } 307 } 308 return false; 309 } 310 setInternalAddrList(List<LinkAddress> internalAddrList)311 public void setInternalAddrList(List<LinkAddress> internalAddrList) { 312 mInternalAddrList = new ArrayList<LinkAddress>(internalAddrList); 313 if (getSrcIpv6Address() != null) { 314 // check if we can reuse src ipv6 address (i.e if prefix is same) 315 for (LinkAddress assignedAddr : internalAddrList) { 316 if (isPrefixSameAsSrcIP(assignedAddr)) { 317 // the assigned IPv6 address is same as pre-Handover IPv6 318 // addr. Just reuse the pre-Handover Address so the IID is 319 // preserved 320 mInternalAddrList.remove(assignedAddr); 321 322 // add original address 323 mInternalAddrList.add( 324 new LinkAddress(mSrcIpv6Address, mSrcIpv6AddressPrefixLen)); 325 326 Log.d( 327 TAG, 328 "Network assigned IP replaced OLD:" 329 + internalAddrList 330 + " NEW:" 331 + mInternalAddrList); 332 break; 333 } 334 } 335 } 336 } 337 338 @NonNull getIkeSession()339 public IkeSession getIkeSession() { 340 return mIkeSession; 341 } 342 getError()343 public IwlanError getError() { 344 return mError; 345 } 346 setError(IwlanError error)347 public void setError(IwlanError error) { 348 this.mError = error; 349 } 350 getIface()351 public IpSecManager.IpSecTunnelInterface getIface() { 352 return mIface; 353 } 354 setIface(IpSecManager.IpSecTunnelInterface iface)355 public void setIface(IpSecManager.IpSecTunnelInterface iface) { 356 mIface = iface; 357 } 358 getSrcIpv6Address()359 public InetAddress getSrcIpv6Address() { 360 return mSrcIpv6Address; 361 } 362 getSrcIpv6AddressPrefixLen()363 public int getSrcIpv6AddressPrefixLen() { 364 return mSrcIpv6AddressPrefixLen; 365 } 366 addressListString(List<InetAddress> list)367 private String addressListString(List<InetAddress> list) { 368 StringBuilder sb = new StringBuilder(); 369 sb.append("{ "); 370 for (InetAddress addr : list) { 371 sb.append(addr); 372 sb.append(", "); 373 } 374 sb.append(" }"); 375 return sb.toString(); 376 } 377 378 @Override toString()379 public String toString() { 380 StringBuilder sb = new StringBuilder(); 381 sb.append("TunnelConfig { "); 382 /*if (mPcscfAddrList != null) { 383 sb.append("mPcscfAddrList: " + addressListString(mPcscfAddrList)); 384 sb.append(", "); 385 } 386 if (mDnsAddrList != null) { 387 sb.append("mDnsAddrList: " + addressListString(mDnsAddrList)); 388 sb.append(", "); 389 } 390 if (mInternalAddrList != null) { 391 sb.append("mInternalAddrList: { "); 392 for (LinkAddress addr : mInternalAddrList) { 393 sb.append(addr + ", "); 394 } 395 sb.append(" }, "); 396 } 397 398 if (mSrcIpv6Address != null) { 399 sb.append("{mSrcIpv6Address: " + mSrcIpv6Address + "}, "); 400 } else { 401 sb.append("{NULL mSrcIpv6Address}, "); 402 } */ 403 404 if (mSliceInfo != null) { 405 sb.append("mSliceInfo: " + mSliceInfo + ", "); 406 } 407 408 if (mIsBackoffTimeValid) { 409 sb.append("mBackoffTime: " + mBackoffTime + ", "); 410 } 411 sb.append(" }"); 412 return sb.toString(); 413 } 414 } 415 416 @VisibleForTesting 417 class TmIkeSessionCallback implements IkeSessionCallback { 418 419 private final String mApnName; 420 TmIkeSessionCallback(String apnName)421 TmIkeSessionCallback(String apnName) { 422 this.mApnName = apnName; 423 } 424 425 @Override onOpened(IkeSessionConfiguration sessionConfiguration)426 public void onOpened(IkeSessionConfiguration sessionConfiguration) { 427 Log.d(TAG, "Ike session opened for apn: " + mApnName); 428 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 429 tunnelConfig.setPcscfAddrList(sessionConfiguration.getPcscfServers()); 430 } 431 432 @Override onClosed()433 public void onClosed() { 434 Log.d(TAG, "Ike session closed for apn: " + mApnName); 435 mHandler.dispatchMessage(mHandler.obtainMessage(EVENT_IKE_SESSION_CLOSED, mApnName)); 436 } 437 438 @Override onClosedExceptionally(IkeException exception)439 public void onClosedExceptionally(IkeException exception) { 440 Log.d(TAG, "Ike session onClosedExceptionally for apn: " + mApnName); 441 onSessionClosedWithException(exception, mApnName, EVENT_IKE_SESSION_CLOSED); 442 } 443 444 @Override onError(IkeProtocolException exception)445 public void onError(IkeProtocolException exception) { 446 Log.d(TAG, "Ike session onError for apn: " + mApnName); 447 Log.d( 448 TAG, 449 "ErrorType:" 450 + exception.getErrorType() 451 + " ErrorData:" 452 + exception.getMessage()); 453 } 454 455 @Override onIkeSessionConnectionInfoChanged( IkeSessionConnectionInfo ikeSessionConnectionInfo)456 public void onIkeSessionConnectionInfoChanged( 457 IkeSessionConnectionInfo ikeSessionConnectionInfo) { 458 Log.d(TAG, "Ike session connection info changed for apn: " + mApnName); 459 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 460 IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface(); 461 try { 462 tunnelInterface.setUnderlyingNetwork(ikeSessionConnectionInfo.getNetwork()); 463 } catch (IOException e) { 464 Log.e(TAG, "IOException while updating underlying network for apn: " + mApnName); 465 } 466 } 467 } 468 469 @VisibleForTesting 470 class TmIke3gppCallback implements Ike3gppExtension.Ike3gppDataListener { 471 private final String mApnName; 472 TmIke3gppCallback(String apnName)473 private TmIke3gppCallback(String apnName) { 474 mApnName = apnName; 475 } 476 477 @Override onIke3gppDataReceived(List<Ike3gppData> payloads)478 public void onIke3gppDataReceived(List<Ike3gppData> payloads) { 479 if (payloads != null && !payloads.isEmpty()) { 480 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 481 for (Ike3gppData payload : payloads) { 482 if (payload.getDataType() == DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) { 483 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_N1_MODE_INFORMATION"); 484 NetworkSliceInfo si = 485 NetworkSliceSelectionAssistanceInformation.getSliceInfo( 486 ((Ike3gppN1ModeInformation) payload).getSnssai()); 487 if (si != null) { 488 tunnelConfig.setSliceInfo(si); 489 Log.d(TAG, "SliceInfo: " + si); 490 } 491 } else if (payload.getDataType() == DATA_TYPE_NOTIFY_BACKOFF_TIMER) { 492 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_BACKOFF_TIMER"); 493 long backoffTime = 494 decodeBackoffTime( 495 ((Ike3gppBackoffTimer) payload).getBackoffTimer()); 496 if (backoffTime > 0) { 497 tunnelConfig.setBackoffTime(backoffTime); 498 Log.d(TAG, "Backoff Timer: " + backoffTime); 499 } 500 } 501 } 502 } else { 503 Log.e(TAG, "Null or empty payloads received:"); 504 } 505 } 506 } 507 508 private class TmChildSessionCallBack implements ChildSessionCallback { 509 510 private final String mApnName; 511 TmChildSessionCallBack(String apnName)512 TmChildSessionCallBack(String apnName) { 513 this.mApnName = apnName; 514 } 515 516 @Override onOpened(ChildSessionConfiguration sessionConfiguration)517 public void onOpened(ChildSessionConfiguration sessionConfiguration) { 518 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 519 520 tunnelConfig.setDnsAddrList(sessionConfiguration.getInternalDnsServers()); 521 tunnelConfig.setInternalAddrList(sessionConfiguration.getInternalAddresses()); 522 523 IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface(); 524 525 for (LinkAddress address : tunnelConfig.getInternalAddrList()) { 526 try { 527 tunnelInterface.addAddress(address.getAddress(), address.getPrefixLength()); 528 } catch (IOException e) { 529 Log.e(TAG, "Adding internal addresses to interface failed."); 530 } 531 } 532 533 TunnelLinkProperties linkProperties = 534 TunnelLinkProperties.builder() 535 .setInternalAddresses(tunnelConfig.getInternalAddrList()) 536 .setDnsAddresses(tunnelConfig.getDnsAddrList()) 537 .setPcscfAddresses(tunnelConfig.getPcscfAddrList()) 538 .setIfaceName(tunnelConfig.getIface().getInterfaceName()) 539 .setSliceInfo(tunnelConfig.getSliceInfo()) 540 .build(); 541 mHandler.dispatchMessage( 542 mHandler.obtainMessage( 543 EVENT_CHILD_SESSION_OPENED, 544 new TunnelOpenedData(mApnName, linkProperties))); 545 } 546 547 @Override onClosed()548 public void onClosed() { 549 Log.d(TAG, "onClosed child session for apn: " + mApnName); 550 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 551 if (tunnelConfig == null) { 552 Log.d(TAG, "No tunnel callback for apn: " + mApnName); 553 return; 554 } 555 tunnelConfig = mApnNameToTunnelConfig.get(mApnName); 556 tunnelConfig.getIkeSession().close(); 557 } 558 559 @Override onClosedExceptionally(IkeException exception)560 public void onClosedExceptionally(IkeException exception) { 561 Log.d(TAG, "onClosedExceptionally child session for apn: " + mApnName); 562 onSessionClosedWithException(exception, mApnName, EVENT_CHILD_SESSION_CLOSED); 563 } 564 565 @Override onIpSecTransformsMigrated( IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform)566 public void onIpSecTransformsMigrated( 567 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) { 568 // migration is similar to addition 569 Log.d(TAG, "Transforms migrated for apn: + " + mApnName); 570 mHandler.dispatchMessage( 571 mHandler.obtainMessage( 572 EVENT_IPSEC_TRANSFORM_CREATED, 573 new IpsecTransformData( 574 inIpSecTransform, IpSecManager.DIRECTION_IN, mApnName))); 575 mHandler.dispatchMessage( 576 mHandler.obtainMessage( 577 EVENT_IPSEC_TRANSFORM_CREATED, 578 new IpsecTransformData( 579 outIpSecTransform, IpSecManager.DIRECTION_OUT, mApnName))); 580 } 581 582 @Override onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction)583 public void onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction) { 584 Log.d(TAG, "Transform created, direction: " + direction + ", apn:" + mApnName); 585 mHandler.dispatchMessage( 586 mHandler.obtainMessage( 587 EVENT_IPSEC_TRANSFORM_CREATED, 588 new IpsecTransformData(ipSecTransform, direction, mApnName))); 589 } 590 591 @Override onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction)592 public void onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction) { 593 Log.d(TAG, "Transform deleted, direction: " + direction + ", apn:" + mApnName); 594 mHandler.dispatchMessage( 595 mHandler.obtainMessage(EVENT_IPSEC_TRANSFORM_DELETED, ipSecTransform)); 596 } 597 } 598 EpdgTunnelManager(Context context, int slotId)599 private EpdgTunnelManager(Context context, int slotId) { 600 mContext = context; 601 mSlotId = slotId; 602 mIkeSessionCreator = new IkeSessionCreator(); 603 TAG = EpdgTunnelManager.class.getSimpleName() + "[" + mSlotId + "]"; 604 initHandler(); 605 } 606 607 @VisibleForTesting initHandler()608 void initHandler() { 609 mHandler = new TmHandler(getLooper()); 610 } 611 612 @VisibleForTesting getLooper()613 Looper getLooper() { 614 mHandlerThread = new HandlerThread("EpdgTunnelManagerThread"); 615 mHandlerThread.start(); 616 return mHandlerThread.getLooper(); 617 } 618 619 /** 620 * Gets a epdg tunnel manager instance. 621 * 622 * @param context application context 623 * @param subId subscription ID for the tunnel 624 * @return tunnel manager instance corresponding to the sub id 625 */ getInstance(@onNull Context context, int subId)626 public static EpdgTunnelManager getInstance(@NonNull Context context, int subId) { 627 return mTunnelManagerInstances.computeIfAbsent( 628 subId, k -> new EpdgTunnelManager(context, subId)); 629 } 630 631 public interface TunnelCallback { 632 /** 633 * Called when the tunnel is opened. 634 * 635 * @param apnName apn for which the tunnel was opened 636 * @param linkProperties link properties of the tunnel 637 */ onOpened(@onNull String apnName, @NonNull TunnelLinkProperties linkProperties)638 void onOpened(@NonNull String apnName, @NonNull TunnelLinkProperties linkProperties); 639 /** 640 * Called when the tunnel is closed OR if bringup fails 641 * 642 * @param apnName apn for which the tunnel was closed 643 * @param error IwlanError carrying details of the error 644 */ onClosed(@onNull String apnName, @NonNull IwlanError error)645 void onClosed(@NonNull String apnName, @NonNull IwlanError error); 646 } 647 648 /** 649 * Close tunnel for an apn. Confirmation of closing will be delivered in TunnelCallback that was 650 * provided in {@link #bringUpTunnel} 651 * 652 * @param apnName apn name 653 * @param forceClose if true, results in local cleanup of tunnel 654 * @return true if params are valid and tunnel exists. False otherwise. 655 */ closeTunnel(@onNull String apnName, boolean forceClose)656 public boolean closeTunnel(@NonNull String apnName, boolean forceClose) { 657 mHandler.dispatchMessage( 658 mHandler.obtainMessage( 659 EVENT_TUNNEL_BRINGDOWN_REQUEST, 660 forceClose ? 1 : 0, 661 0 /*not used*/, 662 apnName)); 663 return true; 664 } 665 666 /** 667 * Update the local Network. This will trigger a revaluation for every tunnel for which tunnel 668 * manager has state. 669 * 670 * <p>Tunnels in bringup state will be for closed since IKE currently keeps retrying. 671 * 672 * <p>For rest of the tunnels, update IKE session wth new network. This will either result in 673 * MOBIKE callflow or just a rekey over new Network 674 */ updateNetwork(@onNull Network network, String apnName)675 public void updateNetwork(@NonNull Network network, String apnName) { 676 UpdateNetworkWrapper updateNetworkWrapper = new UpdateNetworkWrapper(network, apnName); 677 mHandler.dispatchMessage( 678 mHandler.obtainMessage(EVENT_UPDATE_NETWORK, updateNetworkWrapper)); 679 } 680 /** 681 * Bring up epdg tunnel. Only one bring up request per apn is expected. All active tunnel 682 * requests and tunnels are expected to be on the same network. 683 * 684 * @param setupRequest {@link TunnelSetupRequest} tunnel configurations 685 * @param tunnelCallback {@link TunnelCallback} interface to notify clients about the tunnel 686 * state 687 * @return true if params are valid and no existing tunnel. False otherwise. 688 */ bringUpTunnel( @onNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback)689 public boolean bringUpTunnel( 690 @NonNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback) { 691 String apnName = setupRequest.apnName(); 692 693 if (getTunnelSetupRequestApnName(setupRequest) == null) { 694 Log.e(TAG, "APN is null."); 695 return false; 696 } 697 698 if (isTunnelConfigContainExistApn(apnName)) { 699 Log.e(TAG, "Tunnel exists for apn:" + apnName); 700 return false; 701 } 702 703 if (!isValidApnProtocol(setupRequest.apnIpProtocol())) { 704 Log.e(TAG, "Invalid protocol for APN"); 705 return false; 706 } 707 708 int pduSessionId = setupRequest.pduSessionId(); 709 if (pduSessionId < 0 || pduSessionId > 15) { 710 Log.e(TAG, "Invalid pduSessionId: " + pduSessionId); 711 return false; 712 } 713 714 TunnelRequestWrapper tunnelRequestWrapper = 715 new TunnelRequestWrapper(setupRequest, tunnelCallback); 716 717 mHandler.dispatchMessage( 718 mHandler.obtainMessage(EVENT_TUNNEL_BRINGUP_REQUEST, tunnelRequestWrapper)); 719 720 return true; 721 } 722 onBringUpTunnel(TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback)723 private void onBringUpTunnel(TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback) { 724 String apnName = setupRequest.apnName(); 725 726 Log.d( 727 TAG, 728 "Bringing up tunnel for apn: " 729 + apnName 730 + "ePDG : " 731 + mEpdgAddress.getHostAddress()); 732 733 IkeSession ikeSession = 734 getIkeSessionCreator() 735 .createIkeSession( 736 mContext, 737 buildIkeSessionParams(setupRequest, apnName), 738 buildChildSessionParams(setupRequest), 739 Executors.newSingleThreadExecutor(), 740 getTmIkeSessionCallback(apnName), 741 new TmChildSessionCallBack(apnName)); 742 743 boolean isSrcIpv6Present = setupRequest.srcIpv6Address().isPresent(); 744 putApnNameToTunnelConfig( 745 apnName, 746 ikeSession, 747 tunnelCallback, 748 isSrcIpv6Present ? setupRequest.srcIpv6Address().get() : null, 749 setupRequest.srcIpv6AddressPrefixLength()); 750 } 751 752 /** 753 * Proxy to allow testing 754 * 755 * @hide 756 */ 757 @VisibleForTesting 758 static class IkeSessionCreator { 759 /** Creates a IKE session */ createIkeSession( @onNull Context context, @NonNull IkeSessionParams ikeSessionParams, @NonNull ChildSessionParams firstChildSessionParams, @NonNull Executor userCbExecutor, @NonNull IkeSessionCallback ikeSessionCallback, @NonNull ChildSessionCallback firstChildSessionCallback)760 public IkeSession createIkeSession( 761 @NonNull Context context, 762 @NonNull IkeSessionParams ikeSessionParams, 763 @NonNull ChildSessionParams firstChildSessionParams, 764 @NonNull Executor userCbExecutor, 765 @NonNull IkeSessionCallback ikeSessionCallback, 766 @NonNull ChildSessionCallback firstChildSessionCallback) { 767 return new IkeSession( 768 context, 769 ikeSessionParams, 770 firstChildSessionParams, 771 userCbExecutor, 772 ikeSessionCallback, 773 firstChildSessionCallback); 774 } 775 } 776 buildChildSessionParams(TunnelSetupRequest setupRequest)777 private ChildSessionParams buildChildSessionParams(TunnelSetupRequest setupRequest) { 778 int proto = setupRequest.apnIpProtocol(); 779 int hardTimeSeconds = 780 (int) getConfig(CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT); 781 int softTimeSeconds = 782 (int) getConfig(CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT); 783 if (!isValidChildSessionLifetime(hardTimeSeconds, softTimeSeconds)) { 784 if (hardTimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM 785 && softTimeSeconds > CHILD_SOFT_LIFETIME_SEC_MINIMUM) { 786 hardTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM; 787 softTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM; 788 } else { 789 hardTimeSeconds = 790 (int) 791 IwlanHelper.getDefaultConfig( 792 CarrierConfigManager.Iwlan 793 .KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT); 794 softTimeSeconds = 795 (int) 796 IwlanHelper.getDefaultConfig( 797 CarrierConfigManager.Iwlan 798 .KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT); 799 } 800 Log.d( 801 TAG, 802 "Invalid child session lifetime values, set hard: " 803 + hardTimeSeconds 804 + ", soft: " 805 + softTimeSeconds); 806 } 807 808 TunnelModeChildSessionParams.Builder childSessionParamsBuilder = 809 new TunnelModeChildSessionParams.Builder() 810 .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds); 811 812 childSessionParamsBuilder.addSaProposal(buildChildSaProposal()); 813 814 boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent(); 815 boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent(); 816 if (handoverIPv4Present || handoverIPv6Present) { 817 if (handoverIPv4Present) { 818 childSessionParamsBuilder.addInternalAddressRequest( 819 (Inet4Address) setupRequest.srcIpv4Address().get()); 820 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET); 821 childSessionParamsBuilder.addInboundTrafficSelectors( 822 getDefaultTrafficSelectorIpv4()); 823 childSessionParamsBuilder.addOutboundTrafficSelectors( 824 getDefaultTrafficSelectorIpv4()); 825 } 826 if (handoverIPv6Present) { 827 childSessionParamsBuilder.addInternalAddressRequest( 828 (Inet6Address) setupRequest.srcIpv6Address().get(), 829 setupRequest.srcIpv6AddressPrefixLength()); 830 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6); 831 childSessionParamsBuilder.addInboundTrafficSelectors( 832 getDefaultTrafficSelectorIpv6()); 833 childSessionParamsBuilder.addOutboundTrafficSelectors( 834 getDefaultTrafficSelectorIpv6()); 835 } 836 } else { 837 // non-handover case 838 if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) { 839 childSessionParamsBuilder.addInternalAddressRequest(AF_INET); 840 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET); 841 childSessionParamsBuilder.addInboundTrafficSelectors( 842 getDefaultTrafficSelectorIpv4()); 843 childSessionParamsBuilder.addOutboundTrafficSelectors( 844 getDefaultTrafficSelectorIpv4()); 845 } 846 if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) { 847 childSessionParamsBuilder.addInternalAddressRequest(AF_INET6); 848 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6); 849 childSessionParamsBuilder.addInboundTrafficSelectors( 850 getDefaultTrafficSelectorIpv6()); 851 childSessionParamsBuilder.addOutboundTrafficSelectors( 852 getDefaultTrafficSelectorIpv6()); 853 } 854 } 855 856 return childSessionParamsBuilder.build(); 857 } 858 getDefaultTrafficSelectorIpv4()859 private static IkeTrafficSelector getDefaultTrafficSelectorIpv4() { 860 return new IkeTrafficSelector( 861 TRAFFIC_SELECTOR_START_PORT, 862 TRAFFIC_SELECTOR_END_PORT, 863 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_START_ADDR), 864 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_END_ADDR)); 865 } 866 getDefaultTrafficSelectorIpv6()867 private static IkeTrafficSelector getDefaultTrafficSelectorIpv6() { 868 return new IkeTrafficSelector( 869 TRAFFIC_SELECTOR_START_PORT, 870 TRAFFIC_SELECTOR_END_PORT, 871 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_START_ADDR), 872 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_END_ADDR)); 873 } 874 buildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName)875 private IkeSessionParams buildIkeSessionParams( 876 TunnelSetupRequest setupRequest, String apnName) { 877 int hardTimeSeconds = 878 (int) getConfig(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT); 879 int softTimeSeconds = 880 (int) getConfig(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT); 881 if (!isValidIkeSessionLifetime(hardTimeSeconds, softTimeSeconds)) { 882 if (hardTimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM 883 && softTimeSeconds > IKE_SOFT_LIFETIME_SEC_MINIMUM) { 884 hardTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM; 885 softTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM; 886 } else { 887 hardTimeSeconds = 888 (int) 889 IwlanHelper.getDefaultConfig( 890 CarrierConfigManager.Iwlan 891 .KEY_IKE_REKEY_HARD_TIMER_SEC_INT); 892 softTimeSeconds = 893 (int) 894 IwlanHelper.getDefaultConfig( 895 CarrierConfigManager.Iwlan 896 .KEY_IKE_REKEY_SOFT_TIMER_SEC_INT); 897 } 898 Log.d( 899 TAG, 900 "Invalid ike session lifetime values, set hard: " 901 + hardTimeSeconds 902 + ", soft: " 903 + softTimeSeconds); 904 } 905 906 IkeSessionParams.Builder builder = 907 new IkeSessionParams.Builder(mContext) 908 // permanently hardcode DSCP to 46 (Expedited Forwarding class) 909 // See https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml 910 // This will make WiFi prioritize IKE signallig under WMM AC_VO 911 .setDscp(46) 912 .setServerHostname(mEpdgAddress.getHostAddress()) 913 .setLocalIdentification(getLocalIdentification()) 914 .setRemoteIdentification(getId(setupRequest.apnName(), false)) 915 .setAuthEap(null, getEapConfig()) 916 .addSaProposal(buildIkeSaProposal()) 917 .setNetwork(mNetwork) 918 .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID) 919 .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE) 920 .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds) 921 .setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig()) 922 .setDpdDelaySeconds(getDpdDelayFromConfig()); 923 924 if ((int) getConfig(CarrierConfigManager.Iwlan.KEY_EPDG_AUTHENTICATION_METHOD_INT) 925 == CarrierConfigManager.Iwlan.AUTHENTICATION_METHOD_EAP_ONLY) { 926 builder.addIkeOption(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH); 927 } 928 929 if (setupRequest.requestPcscf()) { 930 int proto = setupRequest.apnIpProtocol(); 931 if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) { 932 builder.addPcscfServerRequest(AF_INET); 933 } 934 if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) { 935 builder.addPcscfServerRequest(AF_INET6); 936 } 937 } 938 939 if (setupRequest.pduSessionId() != 0) { 940 Ike3gppParams extParams = 941 new Ike3gppParams.Builder() 942 .setPduSessionId((byte) setupRequest.pduSessionId()) 943 .build(); 944 Ike3gppExtension extension = 945 new Ike3gppExtension(extParams, new TmIke3gppCallback(apnName)); 946 builder.setIke3gppExtension(extension); 947 } 948 949 int nattKeepAliveTimer = 950 (int) getConfig(CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT); 951 if (nattKeepAliveTimer < NATT_KEEPALIVE_DELAY_SEC_MIN 952 || nattKeepAliveTimer > NATT_KEEPALIVE_DELAY_SEC_MAX) { 953 Log.d(TAG, "Falling back to default natt keep alive timer"); 954 nattKeepAliveTimer = 955 (int) 956 IwlanHelper.getDefaultConfig( 957 CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT); 958 } 959 builder.setNattKeepAliveDelaySeconds(nattKeepAliveTimer); 960 961 return builder.build(); 962 } 963 isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)964 private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { 965 if (hardLifetimeSeconds < CHILD_HARD_LIFETIME_SEC_MINIMUM 966 || hardLifetimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM 967 || softLifetimeSeconds < CHILD_SOFT_LIFETIME_SEC_MINIMUM 968 || hardLifetimeSeconds - softLifetimeSeconds < LIFETIME_MARGIN_SEC_MINIMUM) { 969 return false; 970 } 971 return true; 972 } 973 isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)974 private boolean isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) { 975 if (hardLifetimeSeconds < IKE_HARD_LIFETIME_SEC_MINIMUM 976 || hardLifetimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM 977 || softLifetimeSeconds < IKE_SOFT_LIFETIME_SEC_MINIMUM 978 || hardLifetimeSeconds - softLifetimeSeconds < LIFETIME_MARGIN_SEC_MINIMUM) { 979 return false; 980 } 981 return true; 982 } 983 getConfig(String configKey)984 private <T> T getConfig(String configKey) { 985 return IwlanHelper.getConfig(configKey, mContext, mSlotId); 986 } 987 buildIkeSaProposal()988 private IkeSaProposal buildIkeSaProposal() { 989 IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder(); 990 991 int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 992 for (int dhGroup : dhGroups) { 993 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 994 saProposalBuilder.addDhGroup(dhGroup); 995 } 996 } 997 998 int[] encryptionAlgos = 999 getConfig( 1000 CarrierConfigManager.Iwlan 1001 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1002 for (int encryptionAlgo : encryptionAlgos) { 1003 validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO); 1004 1005 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1006 int[] aesCbcKeyLens = 1007 getConfig( 1008 CarrierConfigManager.Iwlan 1009 .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); 1010 for (int aesCbcKeyLen : aesCbcKeyLens) { 1011 if (validateConfig(aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1012 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLen); 1013 } 1014 } 1015 } 1016 1017 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1018 int[] aesCtrKeyLens = 1019 getConfig( 1020 CarrierConfigManager.Iwlan 1021 .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); 1022 for (int aesCtrKeyLen : aesCtrKeyLens) { 1023 if (validateConfig(aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1024 saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLen); 1025 } 1026 } 1027 } 1028 } 1029 1030 int[] integrityAlgos = 1031 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY); 1032 for (int integrityAlgo : integrityAlgos) { 1033 if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { 1034 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); 1035 } 1036 } 1037 1038 int[] prfAlgos = 1039 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY); 1040 for (int prfAlgo : prfAlgos) { 1041 if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) { 1042 saProposalBuilder.addPseudorandomFunction(prfAlgo); 1043 } 1044 } 1045 1046 return saProposalBuilder.build(); 1047 } 1048 validateConfig(int config, Set<Integer> validConfigValues, String configType)1049 private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) { 1050 if (validConfigValues.contains(config)) { 1051 return true; 1052 } 1053 1054 Log.e(TAG, "Invalid config value for " + configType + ":" + config); 1055 return false; 1056 } 1057 buildChildSaProposal()1058 private ChildSaProposal buildChildSaProposal() { 1059 ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder(); 1060 1061 // IKE library doesn't add KE payload if dh groups are not set in child session params. 1062 // Use the same groups as that of IKE session. 1063 if (getConfig(CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) { 1064 int[] dhGroups = 1065 getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY); 1066 for (int dhGroup : dhGroups) { 1067 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) { 1068 saProposalBuilder.addDhGroup(dhGroup); 1069 } 1070 } 1071 } 1072 1073 int[] encryptionAlgos = 1074 getConfig( 1075 CarrierConfigManager.Iwlan 1076 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY); 1077 for (int encryptionAlgo : encryptionAlgos) { 1078 if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) { 1079 if (ChildSaProposal.getSupportedEncryptionAlgorithms().contains(encryptionAlgo)) { 1080 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) { 1081 int[] aesCbcKeyLens = 1082 getConfig( 1083 CarrierConfigManager.Iwlan 1084 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY); 1085 for (int aesCbcKeyLen : aesCbcKeyLens) { 1086 if (validateConfig( 1087 aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1088 saProposalBuilder.addEncryptionAlgorithm( 1089 encryptionAlgo, aesCbcKeyLen); 1090 } 1091 } 1092 } 1093 1094 if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) { 1095 int[] aesCtrKeyLens = 1096 getConfig( 1097 CarrierConfigManager.Iwlan 1098 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY); 1099 for (int aesCtrKeyLen : aesCtrKeyLens) { 1100 if (validateConfig( 1101 aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) { 1102 saProposalBuilder.addEncryptionAlgorithm( 1103 encryptionAlgo, aesCtrKeyLen); 1104 } 1105 } 1106 } 1107 } else { 1108 Log.w(TAG, "Device does not support encryption alog: " + encryptionAlgo); 1109 } 1110 } 1111 } 1112 1113 int[] integrityAlgos = 1114 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY); 1115 for (int integrityAlgo : integrityAlgos) { 1116 if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) { 1117 if (ChildSaProposal.getSupportedIntegrityAlgorithms().contains(integrityAlgo)) { 1118 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo); 1119 } else { 1120 Log.w(TAG, "Device does not support integrity alog: " + integrityAlgo); 1121 } 1122 } 1123 } 1124 1125 return saProposalBuilder.build(); 1126 } 1127 getLocalIdentification()1128 private IkeIdentification getLocalIdentification() { 1129 String nai = IwlanHelper.getNai(mContext, mSlotId); 1130 1131 if (nai == null) { 1132 throw new IllegalArgumentException("Nai is null."); 1133 } 1134 1135 Log.d(TAG, "getLocalIdentification: Nai: " + nai); 1136 return getId(nai, true); 1137 } 1138 getId(String id, boolean isLocal)1139 private IkeIdentification getId(String id, boolean isLocal) { 1140 String idTypeConfig = 1141 isLocal 1142 ? CarrierConfigManager.Iwlan.KEY_IKE_LOCAL_ID_TYPE_INT 1143 : CarrierConfigManager.Iwlan.KEY_IKE_REMOTE_ID_TYPE_INT; 1144 int idType = getConfig(idTypeConfig); 1145 switch (idType) { 1146 case CarrierConfigManager.Iwlan.ID_TYPE_FQDN: 1147 return new IkeFqdnIdentification(id); 1148 case CarrierConfigManager.Iwlan.ID_TYPE_KEY_ID: 1149 return new IkeKeyIdIdentification(id.getBytes(StandardCharsets.US_ASCII)); 1150 case CarrierConfigManager.Iwlan.ID_TYPE_RFC822_ADDR: 1151 return new IkeRfc822AddrIdentification(id); 1152 default: 1153 throw new IllegalArgumentException("Invalid local Identity type: " + idType); 1154 } 1155 } 1156 getEapConfig()1157 private EapSessionConfig getEapConfig() { 1158 int subId = IwlanHelper.getSubId(mContext, mSlotId); 1159 String nai = IwlanHelper.getNai(mContext, mSlotId); 1160 1161 if (nai == null) { 1162 throw new IllegalArgumentException("Nai is null."); 1163 } 1164 1165 Log.d(TAG, "getEapConfig: Nai: " + nai); 1166 return new EapSessionConfig.Builder() 1167 .setEapAkaConfig(subId, TelephonyManager.APPTYPE_USIM) 1168 .setEapIdentity(nai.getBytes(StandardCharsets.US_ASCII)) 1169 .build(); 1170 } 1171 onSessionClosedWithException( IkeException exception, String apnName, int sessionType)1172 private void onSessionClosedWithException( 1173 IkeException exception, String apnName, int sessionType) { 1174 Log.d( 1175 TAG, 1176 "Closing tunnel with exception for apn: " 1177 + apnName 1178 + " sessionType:" 1179 + sessionType 1180 + " error: " 1181 + new IwlanError(exception)); 1182 exception.printStackTrace(); 1183 1184 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1185 if (tunnelConfig == null) { 1186 Log.d(TAG, "No callback found for apn: " + apnName); 1187 return; 1188 } 1189 1190 tunnelConfig.setError(new IwlanError(exception)); 1191 1192 if (sessionType == EVENT_CHILD_SESSION_CLOSED) { 1193 tunnelConfig.getIkeSession().close(); 1194 return; 1195 } 1196 1197 mHandler.dispatchMessage(mHandler.obtainMessage(sessionType, apnName)); 1198 } 1199 1200 private final class TmHandler extends Handler { 1201 private final String TAG = TmHandler.class.getSimpleName(); 1202 1203 @Override handleMessage(Message msg)1204 public void handleMessage(Message msg) { 1205 Log.d(TAG, "msg.what = " + msg.what); 1206 1207 switch (msg.what) { 1208 case EVENT_TUNNEL_BRINGUP_REQUEST: 1209 TunnelRequestWrapper tunnelRequestWrapper = (TunnelRequestWrapper) msg.obj; 1210 TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest(); 1211 if (!canBringUpTunnel(setupRequest.apnName())) { 1212 Log.d(TAG, "Cannot bring up tunnel as retry time has not passed"); 1213 tunnelRequestWrapper 1214 .getTunnelCallback() 1215 .onClosed( 1216 setupRequest.apnName(), 1217 getLastError(setupRequest.apnName())); 1218 return; 1219 } 1220 1221 // No tunnel bring up in progress and the epdg address is null 1222 if (!mIsEpdgAddressSelected && mApnNameToTunnelConfig.size() == 0) { 1223 mNetwork = setupRequest.network(); 1224 mRequestQueue.add(tunnelRequestWrapper); 1225 selectEpdgAddress(setupRequest); 1226 break; 1227 } 1228 1229 // Service the request immediately when epdg address is available 1230 if (mIsEpdgAddressSelected) { 1231 onBringUpTunnel(setupRequest, tunnelRequestWrapper.getTunnelCallback()); 1232 } else { 1233 mRequestQueue.add(tunnelRequestWrapper); 1234 } 1235 break; 1236 1237 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE: 1238 EpdgSelectorResult selectorResult = (EpdgSelectorResult) msg.obj; 1239 printRequestQueue("EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE"); 1240 1241 if (selectorResult.getTransactionId() != mTransactionId) { 1242 Log.e(TAG, "Mismatched transactionId"); 1243 break; 1244 } 1245 1246 if ((tunnelRequestWrapper = mRequestQueue.peek()) == null) { 1247 Log.d(TAG, "Empty request queue"); 1248 break; 1249 } 1250 1251 if (selectorResult.getEpdgError().getErrorType() == IwlanError.NO_ERROR 1252 && selectorResult.getValidIpList() != null) { 1253 validateAndSetEpdgAddress(selectorResult.getValidIpList()); 1254 onBringUpTunnel( 1255 tunnelRequestWrapper.getSetupRequest(), 1256 tunnelRequestWrapper.getTunnelCallback()); 1257 } else { 1258 IwlanError error = 1259 (selectorResult.getEpdgError().getErrorType() 1260 == IwlanError.NO_ERROR) 1261 ? new IwlanError( 1262 IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED) 1263 : selectorResult.getEpdgError(); 1264 failAllPendingRequests(error); 1265 } 1266 break; 1267 1268 case EVENT_CHILD_SESSION_OPENED: 1269 TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj; 1270 String apnName = tunnelOpenedData.getApnName(); 1271 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1272 tunnelConfig 1273 .getTunnelCallback() 1274 .onOpened(apnName, tunnelOpenedData.getLinkProperties()); 1275 setIsEpdgAddressSelected(true); 1276 mValidEpdgInfo.resetIndex(); 1277 mRequestQueue.poll(); 1278 printRequestQueue("EVENT_CHILD_SESSION_OPENED"); 1279 serviceAllPendingRequests(); 1280 break; 1281 1282 case EVENT_IKE_SESSION_CLOSED: 1283 printRequestQueue("EVENT_IKE_SESSION_CLOSED"); 1284 apnName = (String) msg.obj; 1285 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1286 mApnNameToTunnelConfig.remove(apnName); 1287 IwlanError iwlanError = tunnelConfig.getError(); 1288 IpSecManager.IpSecTunnelInterface iface = tunnelConfig.getIface(); 1289 if (iface != null) { 1290 iface.close(); 1291 } 1292 1293 if (!mIsEpdgAddressSelected) { 1294 // fail all the requests. report back off timer, if present, to the 1295 // current request. 1296 if (tunnelConfig.isBackoffTimeValid()) { 1297 mRequestQueue.poll(); 1298 reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime()); 1299 tunnelConfig.getTunnelCallback().onClosed(apnName, iwlanError); 1300 } 1301 failAllPendingRequests(iwlanError); 1302 } else { 1303 mRequestQueue.poll(); 1304 Log.d(TAG, "Tunnel Closed: " + iwlanError); 1305 if (tunnelConfig.isBackoffTimeValid()) { 1306 reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime()); 1307 } else { 1308 reportIwlanError(apnName, iwlanError); 1309 } 1310 tunnelConfig.getTunnelCallback().onClosed(apnName, iwlanError); 1311 } 1312 1313 if (mApnNameToTunnelConfig.size() == 0 && mRequestQueue.size() == 0) { 1314 resetTunnelManagerState(); 1315 } 1316 break; 1317 1318 case EVENT_UPDATE_NETWORK: 1319 UpdateNetworkWrapper updatedNetwork = (UpdateNetworkWrapper) msg.obj; 1320 apnName = updatedNetwork.getApnName(); 1321 Network network = updatedNetwork.getNetwork(); 1322 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1323 if (tunnelConfig == null) { 1324 Log.d(TAG, "Update Network request: No tunnel exists for apn: " + apnName); 1325 } else { 1326 Log.d(TAG, "Updating Network for apn: " + apnName + " Network: " + network); 1327 tunnelConfig.getIkeSession().setNetwork(network); 1328 } 1329 break; 1330 case EVENT_TUNNEL_BRINGDOWN_REQUEST: 1331 apnName = (String) msg.obj; 1332 int forceClose = msg.arg1; 1333 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1334 if (tunnelConfig == null) { 1335 Log.d( 1336 TAG, 1337 "Bringdown request: No tunnel exists for apn: " 1338 + apnName 1339 + "forced: " 1340 + forceClose); 1341 } else { 1342 if (forceClose == 1) { 1343 tunnelConfig.getIkeSession().kill(); 1344 } else { 1345 tunnelConfig.getIkeSession().close(); 1346 } 1347 closePendingRequestsForApn(apnName); 1348 } 1349 break; 1350 1351 case EVENT_IPSEC_TRANSFORM_CREATED: 1352 IpsecTransformData transformData = (IpsecTransformData) msg.obj; 1353 apnName = transformData.getApnName(); 1354 IpSecManager ipSecManager = mContext.getSystemService(IpSecManager.class); 1355 tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1356 1357 if (tunnelConfig.getIface() == null) { 1358 if (mLocalAddresses.size() == 0 || ipSecManager == null) { 1359 Log.e(TAG, "No local addresses found."); 1360 closeIkeSession( 1361 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 1362 return; 1363 } 1364 1365 try { 1366 InetAddress localAddress = 1367 (mEpdgAddress instanceof Inet4Address) 1368 ? IwlanHelper.getIpv4Address(mLocalAddresses) 1369 : IwlanHelper.getIpv6Address(mLocalAddresses); 1370 tunnelConfig.setIface( 1371 ipSecManager.createIpSecTunnelInterface( 1372 localAddress, mEpdgAddress, mNetwork)); 1373 } catch (IpSecManager.ResourceUnavailableException | IOException e) { 1374 Log.e(TAG, "Failed to create tunnel interface. " + e); 1375 closeIkeSession( 1376 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 1377 return; 1378 } 1379 } 1380 1381 try { 1382 ipSecManager.applyTunnelModeTransform( 1383 tunnelConfig.getIface(), 1384 transformData.getDirection(), 1385 transformData.getTransform()); 1386 } catch (IOException e) { 1387 Log.e(TAG, "Failed to apply tunnel transform."); 1388 closeIkeSession( 1389 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED)); 1390 } 1391 break; 1392 1393 case EVENT_IPSEC_TRANSFORM_DELETED: 1394 IpSecTransform transform = (IpSecTransform) msg.obj; 1395 transform.close(); 1396 break; 1397 1398 case EVENT_CHILD_SESSION_CLOSED: 1399 // no-op - this should not be posted. 1400 // This is never posted since we save the error and close the IKE session 1401 // when child session closes. 1402 default: 1403 throw new IllegalStateException("Unexpected value: " + msg.what); 1404 } 1405 } 1406 TmHandler(Looper looper)1407 TmHandler(Looper looper) { 1408 super(looper); 1409 } 1410 } 1411 closeIkeSession(String apnName, IwlanError error)1412 private void closeIkeSession(String apnName, IwlanError error) { 1413 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName); 1414 tunnelConfig.setError(error); 1415 tunnelConfig.getIkeSession().close(); 1416 } 1417 selectEpdgAddress(TunnelSetupRequest setupRequest)1418 private void selectEpdgAddress(TunnelSetupRequest setupRequest) { 1419 mLocalAddresses = getAddressForNetwork(mNetwork, mContext); 1420 if (mLocalAddresses.size() == 0) { 1421 Log.e(TAG, "No local addresses available."); 1422 failAllPendingRequests( 1423 new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED)); 1424 return; 1425 } 1426 1427 int protoFilter = EpdgSelector.PROTO_FILTER_IPV4V6; 1428 if (!IwlanHelper.hasIpv6Address(mLocalAddresses)) { 1429 protoFilter = EpdgSelector.PROTO_FILTER_IPV4; 1430 } 1431 if (!IwlanHelper.hasIpv4Address(mLocalAddresses)) { 1432 protoFilter = EpdgSelector.PROTO_FILTER_IPV6; 1433 } 1434 1435 EpdgSelector epdgSelector = getEpdgSelector(); 1436 IwlanError epdgError = 1437 epdgSelector.getValidatedServerList( 1438 ++mTransactionId, 1439 protoFilter, 1440 setupRequest.isRoaming(), 1441 setupRequest.isEmergency(), 1442 mNetwork, 1443 mSelectorCallback); 1444 1445 if (epdgError.getErrorType() != IwlanError.NO_ERROR) { 1446 Log.e(TAG, "Epdg address selection failed with error:" + epdgError); 1447 failAllPendingRequests(epdgError); 1448 } 1449 } 1450 1451 @VisibleForTesting getEpdgSelector()1452 EpdgSelector getEpdgSelector() { 1453 return EpdgSelector.getSelectorInstance(mContext, mSlotId); 1454 } 1455 1456 @VisibleForTesting closePendingRequestsForApn(String apnName)1457 void closePendingRequestsForApn(String apnName) { 1458 int queueSize = mRequestQueue.size(); 1459 if (queueSize == 0) { 1460 return; 1461 } 1462 1463 int count = 0; 1464 1465 while (count < queueSize) { 1466 TunnelRequestWrapper requestWrapper = mRequestQueue.poll(); 1467 if (requestWrapper.getSetupRequest().apnName() == apnName) { 1468 requestWrapper 1469 .getTunnelCallback() 1470 .onClosed(apnName, new IwlanError(IwlanError.NO_ERROR)); 1471 } else { 1472 mRequestQueue.add(requestWrapper); 1473 } 1474 count++; 1475 } 1476 } 1477 1478 @VisibleForTesting validateAndSetEpdgAddress(List<InetAddress> selectorResultList)1479 void validateAndSetEpdgAddress(List<InetAddress> selectorResultList) { 1480 List<InetAddress> addrList = mValidEpdgInfo.getAddrList(); 1481 if (addrList == null || !addrList.equals(selectorResultList)) { 1482 Log.d(TAG, "Update ePDG address list."); 1483 mValidEpdgInfo.setAddrList(selectorResultList); 1484 addrList = mValidEpdgInfo.getAddrList(); 1485 } 1486 1487 int index = mValidEpdgInfo.getIndex(); 1488 Log.d( 1489 TAG, 1490 "Valid ePDG Address List: " 1491 + Arrays.toString(addrList.toArray()) 1492 + ", index = " 1493 + index); 1494 mEpdgAddress = addrList.get(index); 1495 mValidEpdgInfo.incrementIndex(); 1496 } 1497 1498 @VisibleForTesting resetTunnelManagerState()1499 void resetTunnelManagerState() { 1500 Log.d(TAG, "resetTunnelManagerState"); 1501 mEpdgAddress = null; 1502 setIsEpdgAddressSelected(false); 1503 mNetwork = null; 1504 mRequestQueue = new LinkedList<>(); 1505 mApnNameToTunnelConfig = new ConcurrentHashMap<>(); 1506 mLocalAddresses = null; 1507 } 1508 serviceAllPendingRequests()1509 private void serviceAllPendingRequests() { 1510 while (mRequestQueue.size() > 0) { 1511 Log.d(TAG, "serviceAllPendingRequests"); 1512 TunnelRequestWrapper request = mRequestQueue.poll(); 1513 onBringUpTunnel(request.getSetupRequest(), request.getTunnelCallback()); 1514 } 1515 } 1516 failAllPendingRequests(IwlanError error)1517 private void failAllPendingRequests(IwlanError error) { 1518 while (mRequestQueue.size() > 0) { 1519 Log.d(TAG, "failAllPendingRequests"); 1520 TunnelRequestWrapper request = mRequestQueue.poll(); 1521 TunnelSetupRequest setupRequest = request.getSetupRequest(); 1522 reportIwlanError(setupRequest.apnName(), error); 1523 request.getTunnelCallback().onClosed(setupRequest.apnName(), error); 1524 } 1525 } 1526 1527 // Prints mRequestQueue printRequestQueue(String info)1528 private void printRequestQueue(String info) { 1529 Log.d(TAG, info); 1530 Log.d(TAG, "mRequestQueue: " + Arrays.toString(mRequestQueue.toArray())); 1531 } 1532 1533 // Update Network wrapper 1534 private static final class UpdateNetworkWrapper { 1535 private final Network mNetwork; 1536 private final String mApnName; 1537 UpdateNetworkWrapper(Network network, String apnName)1538 private UpdateNetworkWrapper(Network network, String apnName) { 1539 mNetwork = network; 1540 mApnName = apnName; 1541 } 1542 getApnName()1543 public String getApnName() { 1544 return mApnName; 1545 } 1546 getNetwork()1547 public Network getNetwork() { 1548 return mNetwork; 1549 } 1550 } 1551 // Tunnel request + tunnel callback 1552 private static final class TunnelRequestWrapper { 1553 private final TunnelSetupRequest mSetupRequest; 1554 1555 private final TunnelCallback mTunnelCallback; 1556 TunnelRequestWrapper( TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback)1557 private TunnelRequestWrapper( 1558 TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback) { 1559 mTunnelCallback = tunnelCallback; 1560 mSetupRequest = setupRequest; 1561 } 1562 getSetupRequest()1563 public TunnelSetupRequest getSetupRequest() { 1564 return mSetupRequest; 1565 } 1566 getTunnelCallback()1567 public TunnelCallback getTunnelCallback() { 1568 return mTunnelCallback; 1569 } 1570 } 1571 1572 private static final class EpdgSelectorResult { 1573 private final List<InetAddress> mValidIpList; 1574 getValidIpList()1575 public List<InetAddress> getValidIpList() { 1576 return mValidIpList; 1577 } 1578 getEpdgError()1579 public IwlanError getEpdgError() { 1580 return mEpdgError; 1581 } 1582 getTransactionId()1583 public int getTransactionId() { 1584 return mTransactionId; 1585 } 1586 1587 private final IwlanError mEpdgError; 1588 private final int mTransactionId; 1589 EpdgSelectorResult( List<InetAddress> validIpList, IwlanError epdgError, int transactionId)1590 private EpdgSelectorResult( 1591 List<InetAddress> validIpList, IwlanError epdgError, int transactionId) { 1592 mValidIpList = validIpList; 1593 mEpdgError = epdgError; 1594 mTransactionId = transactionId; 1595 } 1596 } 1597 1598 private static final class TunnelOpenedData { 1599 private final String mApnName; 1600 private final TunnelLinkProperties mLinkProperties; 1601 TunnelOpenedData(String apnName, TunnelLinkProperties linkProperties)1602 private TunnelOpenedData(String apnName, TunnelLinkProperties linkProperties) { 1603 mApnName = apnName; 1604 mLinkProperties = linkProperties; 1605 } 1606 getApnName()1607 public String getApnName() { 1608 return mApnName; 1609 } 1610 getLinkProperties()1611 public TunnelLinkProperties getLinkProperties() { 1612 return mLinkProperties; 1613 } 1614 } 1615 releaseInstance()1616 public void releaseInstance() { 1617 mHandlerThread.quit(); 1618 mTunnelManagerInstances.remove(mSlotId); 1619 } 1620 1621 private static final class IpsecTransformData { 1622 private final IpSecTransform mTransform; 1623 private final int mDirection; 1624 private final String mApnName; 1625 IpsecTransformData(IpSecTransform transform, int direction, String apnName)1626 private IpsecTransformData(IpSecTransform transform, int direction, String apnName) { 1627 mTransform = transform; 1628 mDirection = direction; 1629 mApnName = apnName; 1630 } 1631 getTransform()1632 public IpSecTransform getTransform() { 1633 return mTransform; 1634 } 1635 getDirection()1636 public int getDirection() { 1637 return mDirection; 1638 } 1639 getApnName()1640 public String getApnName() { 1641 return mApnName; 1642 } 1643 } 1644 1645 private static final class EpdgInfo { 1646 private List<InetAddress> mAddrList; 1647 private int mIndex; 1648 EpdgInfo()1649 private EpdgInfo() { 1650 mAddrList = null; 1651 mIndex = 0; 1652 } 1653 getAddrList()1654 public List<InetAddress> getAddrList() { 1655 return mAddrList; 1656 } 1657 setAddrList(@onNull List<InetAddress> AddrList)1658 public void setAddrList(@NonNull List<InetAddress> AddrList) { 1659 mAddrList = AddrList; 1660 resetIndex(); 1661 } 1662 getIndex()1663 public int getIndex() { 1664 return mIndex; 1665 } 1666 incrementIndex()1667 public void incrementIndex() { 1668 if (getIndex() >= getAddrList().size() - 1) { 1669 resetIndex(); 1670 } else { 1671 mIndex++; 1672 } 1673 } 1674 resetIndex()1675 public void resetIndex() { 1676 mIndex = 0; 1677 } 1678 } 1679 getRetransmissionTimeoutsFromConfig()1680 private int[] getRetransmissionTimeoutsFromConfig() { 1681 int[] timeList = 1682 (int[]) getConfig(CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY); 1683 boolean isValid = true; 1684 if (timeList == null 1685 || timeList.length == 0 1686 || timeList.length > IKE_RETRANS_MAX_ATTEMPTS_MAX) { 1687 isValid = false; 1688 } 1689 for (int time : timeList) { 1690 if (time < IKE_RETRANS_TIMEOUT_MS_MIN || time > IKE_RETRANS_TIMEOUT_MS_MAX) { 1691 isValid = false; 1692 break; 1693 } 1694 } 1695 if (!isValid) { 1696 timeList = 1697 (int[]) 1698 IwlanHelper.getDefaultConfig( 1699 CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY); 1700 } 1701 Log.d(TAG, "getRetransmissionTimeoutsFromConfig: " + Arrays.toString(timeList)); 1702 return timeList; 1703 } 1704 getDpdDelayFromConfig()1705 private int getDpdDelayFromConfig() { 1706 int dpdDelay = (int) getConfig(CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT); 1707 if (dpdDelay < IKE_DPD_DELAY_SEC_MIN || dpdDelay > IKE_DPD_DELAY_SEC_MAX) { 1708 dpdDelay = 1709 (int) 1710 IwlanHelper.getDefaultConfig( 1711 CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT); 1712 } 1713 return dpdDelay; 1714 } 1715 1716 /** 1717 * Decodes backoff time as per TS 124 008 10.5.7.4a Bits 5 to 1 represent the binary coded timer 1718 * value 1719 * 1720 * <p>Bits 6 to 8 defines the timer value unit for the GPRS timer as follows: Bits 8 7 6 0 0 0 1721 * value is incremented in multiples of 10 minutes 0 0 1 value is incremented in multiples of 1 1722 * hour 0 1 0 value is incremented in multiples of 10 hours 0 1 1 value is incremented in 1723 * multiples of 2 seconds 1 0 0 value is incremented in multiples of 30 seconds 1 0 1 value is 1724 * incremented in multiples of 1 minute 1 1 0 value is incremented in multiples of 1 hour 1 1 1 1725 * value indicates that the timer is deactivated. 1726 * 1727 * @param backoffTimerByte Byte value obtained from ike 1728 * @return long time value in seconds. -1 if the timer needs to be deactivated. 1729 */ decodeBackoffTime(byte backoffTimeByte)1730 private static long decodeBackoffTime(byte backoffTimeByte) { 1731 final int BACKOFF_TIME_VALUE_MASK = 0x1F; 1732 final int BACKOFF_TIMER_UNIT_MASK = 0xE0; 1733 final Long[] BACKOFF_TIMER_UNIT_INCREMENT_SECS = { 1734 10L * 60L, // 10 mins 1735 1L * 60L * 60L, // 1 hour 1736 10L * 60L * 60L, // 10 hours 1737 2L, // 2 seconds 1738 30L, // 30 seconds 1739 1L * 60L, // 1 minute 1740 1L * 60L * 60L, // 1 hour 1741 }; 1742 1743 long time = backoffTimeByte & BACKOFF_TIME_VALUE_MASK; 1744 int timerUnit = (backoffTimeByte & BACKOFF_TIMER_UNIT_MASK) >> 5; 1745 if (timerUnit >= BACKOFF_TIMER_UNIT_INCREMENT_SECS.length) { 1746 return -1; 1747 } 1748 time *= BACKOFF_TIMER_UNIT_INCREMENT_SECS[timerUnit]; 1749 return time; 1750 } 1751 1752 @VisibleForTesting getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest)1753 String getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest) { 1754 String apnName = setupRequest.apnName(); 1755 return apnName; 1756 } 1757 1758 @VisibleForTesting putApnNameToTunnelConfig( String apnName, IkeSession ikeSession, TunnelCallback tunnelCallback, InetAddress srcIpv6Addr, int srcIPv6AddrPrefixLen)1759 void putApnNameToTunnelConfig( 1760 String apnName, 1761 IkeSession ikeSession, 1762 TunnelCallback tunnelCallback, 1763 InetAddress srcIpv6Addr, 1764 int srcIPv6AddrPrefixLen) { 1765 mApnNameToTunnelConfig.put( 1766 apnName, 1767 new TunnelConfig(ikeSession, tunnelCallback, srcIpv6Addr, srcIPv6AddrPrefixLen)); 1768 Log.d(TAG, "Added apn: " + apnName + " to TunnelConfig"); 1769 } 1770 1771 @VisibleForTesting isTunnelConfigContainExistApn(String apnName)1772 boolean isTunnelConfigContainExistApn(String apnName) { 1773 boolean ret = mApnNameToTunnelConfig.containsKey(apnName); 1774 return ret; 1775 } 1776 1777 @VisibleForTesting getAddressForNetwork(Network network, Context context)1778 List<InetAddress> getAddressForNetwork(Network network, Context context) { 1779 List<InetAddress> ret = IwlanHelper.getAddressesForNetwork(network, context); 1780 return ret; 1781 } 1782 1783 @VisibleForTesting getSelectorCallback()1784 EpdgSelector.EpdgSelectorCallback getSelectorCallback() { 1785 return mSelectorCallback; 1786 } 1787 1788 @VisibleForTesting getIkeSessionCreator()1789 IkeSessionCreator getIkeSessionCreator() { 1790 return mIkeSessionCreator; 1791 } 1792 1793 @VisibleForTesting sendSelectionRequestComplete( ArrayList<InetAddress> validIPList, IwlanError result, int transactionId)1794 void sendSelectionRequestComplete( 1795 ArrayList<InetAddress> validIPList, IwlanError result, int transactionId) { 1796 EpdgSelectorResult epdgSelectorResult = 1797 new EpdgSelectorResult(validIPList, result, transactionId); 1798 mHandler.dispatchMessage( 1799 mHandler.obtainMessage( 1800 EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE, epdgSelectorResult)); 1801 } 1802 isValidApnProtocol(int proto)1803 static boolean isValidApnProtocol(int proto) { 1804 return (proto == ApnSetting.PROTOCOL_IP 1805 || proto == ApnSetting.PROTOCOL_IPV4V6 1806 || proto == ApnSetting.PROTOCOL_IPV6); 1807 } 1808 1809 @VisibleForTesting getTmIkeSessionCallback(String apnName)1810 TmIkeSessionCallback getTmIkeSessionCallback(String apnName) { 1811 return new TmIkeSessionCallback(apnName); 1812 } 1813 1814 @VisibleForTesting setIsEpdgAddressSelected(boolean value)1815 void setIsEpdgAddressSelected(boolean value) { 1816 mIsEpdgAddressSelected = value; 1817 } 1818 1819 @VisibleForTesting reportIwlanError(String apnName, IwlanError error)1820 long reportIwlanError(String apnName, IwlanError error) { 1821 return ErrorPolicyManager.getInstance(mContext, mSlotId).reportIwlanError(apnName, error); 1822 } 1823 1824 @VisibleForTesting reportIwlanError(String apnName, IwlanError error, long backOffTime)1825 long reportIwlanError(String apnName, IwlanError error, long backOffTime) { 1826 return ErrorPolicyManager.getInstance(mContext, mSlotId) 1827 .reportIwlanError(apnName, error, backOffTime); 1828 } 1829 1830 @VisibleForTesting getLastError(String apnName)1831 IwlanError getLastError(String apnName) { 1832 return ErrorPolicyManager.getInstance(mContext, mSlotId).getLastError(apnName); 1833 } 1834 1835 @VisibleForTesting canBringUpTunnel(String apnName)1836 boolean canBringUpTunnel(String apnName) { 1837 return ErrorPolicyManager.getInstance(mContext, mSlotId).canBringUpTunnel(apnName); 1838 } 1839 dump(FileDescriptor fd, PrintWriter pw, String[] args)1840 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1841 pw.println("---- EpdgTunnelManager ----"); 1842 pw.println("mIsEpdgAddressSelected: " + mIsEpdgAddressSelected); 1843 if (mEpdgAddress != null) { 1844 pw.println("mEpdgAddress: " + mEpdgAddress); 1845 } 1846 pw.println("mApnNameToTunnelConfig:\n"); 1847 for (Map.Entry<String, TunnelConfig> entry : mApnNameToTunnelConfig.entrySet()) { 1848 pw.println("APN: " + entry.getKey()); 1849 pw.println("TunnelConfig: " + entry.getValue()); 1850 pw.println(); 1851 } 1852 pw.println("---------------------------"); 1853 } 1854 } 1855