From 4c195ab20e7f5e58042285c026a99512b6092014 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Thu, 9 Mar 2023 14:01:29 +0000 Subject: Read preferred IKE protocol from carrier config Bug: 269714970 Test: atest FrameworksNetTests Change-Id: I3f256c4b86baad3cab14cf1f9ad1a38e337e9a96 --- .../java/com/android/server/connectivity/Vpn.java | 174 +++++++++++++++++---- 1 file changed, 146 insertions(+), 28 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 6d3f8fd77232..4d6c97854126 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -31,6 +31,7 @@ import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO; import static android.os.PowerWhitelistManager.REASON_VPN; import static android.os.UserHandle.PER_USER_RANGE; import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT; +import static android.telephony.CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT; import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU; import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER; @@ -269,6 +270,42 @@ public class Vpn { @VisibleForTesting static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60; + /** + * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_AUTO} and + * {@link IkeSessionParams.ESP_ENCAP_TYPE_AUTO} for ESP packets. + * + * This is one of the possible customization values for + * CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT. + */ + @VisibleForTesting + public static final int PREFERRED_IKE_PROTOCOL_AUTO = 0; + /** + * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_IPV4} and + * {@link IkeSessionParams.ESP_ENCAP_TYPE_UDP} for ESP packets. + * + * This is one of the possible customization values for + * CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT. + */ + @VisibleForTesting + public static final int PREFERRED_IKE_PROTOCOL_IPV4_UDP = 40; + /** + * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_IPV6} and + * {@link IkeSessionParams.ESP_ENCAP_TYPE_UDP} for ESP packets. + * + * Do not use this value for production code. Its numeric value will change in future versions. + */ + @VisibleForTesting + public static final int PREFERRED_IKE_PROTOCOL_IPV6_UDP = 60; + /** + * Prefer using {@link IkeSessionParams.ESP_IP_VERSION_IPV6} and + * {@link IkeSessionParams.ESP_ENCAP_TYPE_NONE} for ESP packets. + * + * This is one of the possible customization values for + * CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT. + */ + @VisibleForTesting + public static final int PREFERRED_IKE_PROTOCOL_IPV6_ESP = 61; + // TODO: create separate trackers for each unique VPN to support // automated reconnection @@ -326,12 +363,13 @@ public class Vpn { private final LocalLog mVpnManagerEvents = new LocalLog(MAX_EVENTS_LOGS); /** - * Cached Map of since retrieving the PersistableBundle + * Cached Map of since retrieving the PersistableBundle * and the target value from CarrierConfigManager is somewhat expensive as it has hundreds of * fields. This cache is cleared when the carrier config changes to ensure data freshness. */ @GuardedBy("this") - private final SparseArray mCachedKeepalivePerSubId = new SparseArray<>(); + private final SparseArray mCachedCarrierConfigInfoPerSubId = + new SparseArray<>(); /** * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This @@ -378,6 +416,28 @@ public class Vpn { void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException; } + private static class CarrierConfigInfo { + public final String mccMnc; + public final int keepaliveDelayMs; + public final int encapType; + public final int ipVersion; + + CarrierConfigInfo(String mccMnc, int keepaliveDelayMs, + int encapType, + int ipVersion) { + this.mccMnc = mccMnc; + this.keepaliveDelayMs = keepaliveDelayMs; + this.encapType = encapType; + this.ipVersion = ipVersion; + } + + @Override + public String toString() { + return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelayMs=" + keepaliveDelayMs + + ", encapType=" + encapType + ", ipVersion=" + ipVersion + "]"; + } + } + @VisibleForTesting public static class Dependencies { public boolean isCallerSystem() { @@ -2923,7 +2983,7 @@ public class Vpn { public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId, int specificCarrierId) { synchronized (Vpn.this) { - mCachedKeepalivePerSubId.remove(subId); + mCachedCarrierConfigInfoPerSubId.remove(subId); // Ignore stale runner. if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return; @@ -3388,47 +3448,105 @@ public class Vpn { } private int guessEspIpVersionForNetwork() { - // TODO : guess the IP version based on carrier if auto IP version selection is enabled - return ESP_IP_VERSION_AUTO; + final CarrierConfigInfo carrierconfig = getCarrierConfig(); + final int ipVersion = (carrierconfig != null) + ? carrierconfig.ipVersion : ESP_IP_VERSION_AUTO; + if (carrierconfig != null) { + Log.d(TAG, "Get customized IP version(" + ipVersion + ") on SIM(" + + carrierconfig.mccMnc + ")"); + } + return ipVersion; } private int guessEspEncapTypeForNetwork() { - // TODO : guess the ESP encap type based on carrier if auto IP version selection is - // enabled - return ESP_ENCAP_TYPE_AUTO; + final CarrierConfigInfo carrierconfig = getCarrierConfig(); + final int encapType = (carrierconfig != null) + ? carrierconfig.encapType : ESP_ENCAP_TYPE_AUTO; + if (carrierconfig != null) { + Log.d(TAG, "Get customized encap type(" + encapType + ") on SIM(" + + carrierconfig.mccMnc + ")"); + } + return encapType; } private int guessNattKeepaliveTimerForNetwork() { + final CarrierConfigInfo carrierconfig = getCarrierConfig(); + final int natKeepalive = (carrierconfig != null) + ? carrierconfig.keepaliveDelayMs : AUTOMATIC_KEEPALIVE_DELAY_SECONDS; + if (carrierconfig != null) { + Log.d(TAG, "Get customized keepalive(" + natKeepalive + ") on SIM(" + + carrierconfig.mccMnc + ")"); + } + return natKeepalive; + } + + private CarrierConfigInfo getCarrierConfig() { final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities); if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { Log.d(TAG, "Underlying network is not a cellular network"); - return AUTOMATIC_KEEPALIVE_DELAY_SECONDS; + return null; } synchronized (Vpn.this) { - if (mCachedKeepalivePerSubId.contains(subId)) { - Log.d(TAG, "Get cached keepalive config"); - return mCachedKeepalivePerSubId.get(subId); + if (mCachedCarrierConfigInfoPerSubId.contains(subId)) { + Log.d(TAG, "Get cached config"); + return mCachedCarrierConfigInfoPerSubId.get(subId); } + } - final TelephonyManager perSubTm = mTelephonyManager.createForSubscriptionId(subId); - if (perSubTm.getSimApplicationState() != TelephonyManager.SIM_STATE_LOADED) { - Log.d(TAG, "SIM card is not ready on sub " + subId); - return AUTOMATIC_KEEPALIVE_DELAY_SECONDS; - } + final TelephonyManager perSubTm = mTelephonyManager.createForSubscriptionId(subId); + if (perSubTm.getSimApplicationState() != TelephonyManager.SIM_STATE_LOADED) { + Log.d(TAG, "SIM card is not ready on sub " + subId); + return null; + } - final PersistableBundle carrierConfig = - mCarrierConfigManager.getConfigForSubId(subId); - if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { - return AUTOMATIC_KEEPALIVE_DELAY_SECONDS; - } + final PersistableBundle carrierConfig = + mCarrierConfigManager.getConfigForSubId(subId); + if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { + return null; + } + + final int natKeepalive = + carrierConfig.getInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT); + final int preferredIpPortocol = + carrierConfig.getInt(KEY_PREFERRED_IKE_PROTOCOL_INT); + final String mccMnc = perSubTm.getSimOperator(subId); + final CarrierConfigInfo info = + buildCarrierConfigInfo(mccMnc, natKeepalive, preferredIpPortocol); + synchronized (Vpn.this) { + mCachedCarrierConfigInfoPerSubId.put(subId, info); + } + + return info; + } - final int natKeepalive = - carrierConfig.getInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT); - mCachedKeepalivePerSubId.put(subId, natKeepalive); - Log.d(TAG, "Get customized keepalive=" + natKeepalive); - return natKeepalive; + private CarrierConfigInfo buildCarrierConfigInfo(String mccMnc, + int natKeepalive, int preferredIpPortocol) { + final int ipVersion; + final int encapType; + switch (preferredIpPortocol) { + case PREFERRED_IKE_PROTOCOL_AUTO: + ipVersion = IkeSessionParams.ESP_IP_VERSION_AUTO; + encapType = IkeSessionParams.ESP_ENCAP_TYPE_AUTO; + break; + case PREFERRED_IKE_PROTOCOL_IPV4_UDP: + ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV4; + encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP; + break; + case PREFERRED_IKE_PROTOCOL_IPV6_UDP: + ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV6; + encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP; + break; + case PREFERRED_IKE_PROTOCOL_IPV6_ESP: + ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV6; + encapType = IkeSessionParams.ESP_ENCAP_TYPE_NONE; + break; + default: + ipVersion = IkeSessionParams.ESP_IP_VERSION_AUTO; + encapType = IkeSessionParams.ESP_ENCAP_TYPE_AUTO; + break; } + return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion); } boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) { @@ -4884,7 +5002,7 @@ public class Vpn { pw.println("Reset session scheduled"); } } - pw.println("mCachedKeepalivePerSubId=" + mCachedKeepalivePerSubId); + pw.println("mCachedCarrierConfigInfoPerSubId=" + mCachedCarrierConfigInfoPerSubId); pw.println("mUnderlyNetworkChanges (most recent first):"); pw.increaseIndent(); -- cgit v1.2.3-59-g8ed1b From 454fbe188d6ec39328e761bcb7df5a698545b82b Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Sat, 11 Mar 2023 07:15:57 +0000 Subject: Honor IP protocol set by client in non-auto IP selection mode If automatic IP version selection is not enabled and VPN clients set the IP version and encap type in the IkeSessionParams, VPN should use the value set by clients instead of always setting them to auto. Test: atest FrameworksNetTests Change-Id: Icd76b06cb9155b0d1fc62811daeafe89d2e45149 --- .../java/com/android/server/connectivity/Vpn.java | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 4d6c97854126..1e9352d10956 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -3558,10 +3558,22 @@ public class Vpn { + mCurrentToken + " to network " + underlyingNetwork); - final int ipVersion = mProfile.isAutomaticIpVersionSelectionEnabled() - ? guessEspIpVersionForNetwork() : ESP_IP_VERSION_AUTO; - final int encapType = mProfile.isAutomaticIpVersionSelectionEnabled() - ? guessEspEncapTypeForNetwork() : ESP_ENCAP_TYPE_AUTO; + + final int ipVersion; + final int encapType; + if (mProfile.isAutomaticIpVersionSelectionEnabled()) { + ipVersion = guessEspIpVersionForNetwork(); + encapType = guessEspEncapTypeForNetwork(); + } else if (mProfile.getIkeTunnelConnectionParams() != null) { + ipVersion = mProfile.getIkeTunnelConnectionParams() + .getIkeSessionParams().getIpVersion(); + encapType = mProfile.getIkeTunnelConnectionParams() + .getIkeSessionParams().getEncapType(); + } else { + ipVersion = ESP_IP_VERSION_AUTO; + encapType = ESP_ENCAP_TYPE_AUTO; + } + final int keepaliveDelaySeconds; if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) { keepaliveDelaySeconds = guessNattKeepaliveTimerForNetwork(); -- cgit v1.2.3-59-g8ed1b