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