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