Loading services/core/java/com/android/server/connectivity/Vpn.java +6 −0 Original line number Diff line number Diff line Loading @@ -2992,6 +2992,9 @@ public class Vpn { // The update on VPN and the IPsec tunnel will be done when migration is fully complete // in onChildMigrated mIkeConnectionInfo = ikeConnectionInfo; if (mVpnConnectivityMetrics != null) { mVpnConnectivityMetrics.setServerIpProtocol(ikeConnectionInfo.getRemoteAddress()); } } /** Loading Loading @@ -3061,6 +3064,9 @@ public class Vpn { mConfig.addresses.clear(); mConfig.addresses.addAll(internalAddresses); if (mVpnConnectivityMetrics != null) { mVpnConnectivityMetrics.setVpnNetworkIpProtocol(mConfig.addresses); } mConfig.routes.clear(); mConfig.routes.addAll(newRoutes); Loading services/core/java/com/android/server/connectivity/VpnConnectivityMetrics.java +68 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; import android.net.ConnectivityManager; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkCapabilities; import android.net.VpnManager; Loading @@ -38,6 +39,8 @@ import android.util.SparseArray; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import java.net.Inet4Address; import java.net.InetAddress; import java.util.Arrays; import java.util.List; Loading @@ -50,6 +53,15 @@ public class VpnConnectivityMetrics { public static final int VPN_TYPE_UNKNOWN = 0; public static final int VPN_PROFILE_TYPE_UNKNOWN = 0; private static final int UNKNOWN_UNDERLYING_NETWORK_TYPE = -1; // Copied from corenetworking platform vpn enum @VisibleForTesting static final int IP_PROTOCOL_UNKNOWN = 0; @VisibleForTesting static final int IP_PROTOCOL_IPv4 = 1; @VisibleForTesting static final int IP_PROTOCOL_IPv6 = 2; @VisibleForTesting static final int IP_PROTOCOL_IPv4v6 = 3; private static final SparseArray<String> sAlgorithms = new SparseArray<>(); private final int mUserId; @NonNull Loading @@ -75,6 +87,8 @@ public class VpnConnectivityMetrics { */ @NonNull private int[] mUnderlyingNetworkTypes; private int mVpnNetworkIpProtocol = IP_PROTOCOL_UNKNOWN; private int mServerIpProtocol = IP_PROTOCOL_UNKNOWN; // Static initializer block to populate the sAlgorithms mapping. It associates integer keys // (which also serve as bit positions for the mAllowedAlgorithms bitmask) with their Loading Loading @@ -197,4 +211,58 @@ public class VpnConnectivityMetrics { mUnderlyingNetworkTypes = new int[0]; } } /** * Sets the IP protocol for the vpn network based on a list of {@link LinkAddress} objects. * * @param addresses A list of {@link LinkAddress} objects representing the IP addresses * configured on the VPN network. */ public void setVpnNetworkIpProtocol(@NonNull List<LinkAddress> addresses) { mVpnNetworkIpProtocol = checkIpProtocol(addresses); } /** * Sets the IP protocol for the server based on its {@link InetAddress}. * * @param address The {@link InetAddress} of the server. */ public void setServerIpProtocol(@NonNull InetAddress address) { // Assume that if the address is not IPv4, it is IPv6. It does not consider other cases like // IPv4-mapped IPv6 addresses. if (address instanceof Inet4Address) { mServerIpProtocol = IP_PROTOCOL_IPv4; } else { mServerIpProtocol = IP_PROTOCOL_IPv6; } } /** * Analyzes a list of {@link LinkAddress} objects to determine the overall IP protocol(s) in * use. * * @param addresses A list of {@link LinkAddress} objects to be checked. * @return An integer representing the detected IP protocol. */ @VisibleForTesting static int checkIpProtocol(@NonNull List<LinkAddress> addresses) { boolean hasIpv4 = false; boolean hasIpv6 = false; int ipProtocol = IP_PROTOCOL_UNKNOWN; for (LinkAddress address : addresses) { if (address.isIpv4()) { hasIpv4 = true; } else if (address.isIpv6()) { hasIpv6 = true; } } if (hasIpv4 && hasIpv6) { ipProtocol = IP_PROTOCOL_IPv4v6; } else if (hasIpv4) { ipProtocol = IP_PROTOCOL_IPv4; } else if (hasIpv6) { ipProtocol = IP_PROTOCOL_IPv6; } return ipProtocol; } } services/tests/VpnTests/java/com/android/server/connectivity/VpnConnectivityMetricsTest.java +17 −0 Original line number Diff line number Diff line Loading @@ -28,13 +28,19 @@ import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_IPv4; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_IPv4v6; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_IPv6; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_UNKNOWN; import static com.android.testutils.Cleanup.testAndCleanup; import static com.android.server.connectivity.VpnConnectivityMetrics.buildAllowedAlgorithmsBitmask; import static com.android.server.connectivity.VpnConnectivityMetrics.checkIpProtocol; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.net.Ikev2VpnProfile; import android.net.LinkAddress; import android.util.Log; import androidx.test.ext.junit.runners.AndroidJUnit4; Loading Loading @@ -71,4 +77,15 @@ public class VpnConnectivityMetricsTest { assertTrue(hasFailed.get()); }, () -> Log.setWtfHandler(originalHandler)); } @Test public void testCheckIpProtocol() { final LinkAddress vpnClientIpv4 = new LinkAddress("192.0.2.1/32"); final LinkAddress vpnClientIpv6 = new LinkAddress("2001:db8:1:2::ffe/128"); assertEquals(IP_PROTOCOL_UNKNOWN, checkIpProtocol(List.of())); assertEquals(IP_PROTOCOL_IPv4, checkIpProtocol(List.of(vpnClientIpv4))); assertEquals(IP_PROTOCOL_IPv6, checkIpProtocol(List.of(vpnClientIpv6))); assertEquals(IP_PROTOCOL_IPv4v6, checkIpProtocol(List.of(vpnClientIpv4, vpnClientIpv6))); } } services/tests/VpnTests/java/com/android/server/connectivity/VpnTest.java +8 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.CollectionUtils; import com.android.server.DeviceIdleInternal; import com.android.server.IpSecService; import com.android.server.VpnTestBase; Loading Loading @@ -2219,6 +2220,13 @@ public class VpnTest extends VpnTestBase { any(), any(), anyString(), ncCaptor.capture(), lpCaptor.capture(), any(), nacCaptor.capture(), any(), any()); verify(mIkeSessionWrapper).setUnderpinnedNetwork(TEST_NETWORK); verify(mVpnConnectivityMetrics).setUnderlyingNetwork(any()); verify(mVpnConnectivityMetrics).setVpnNetworkIpProtocol(argThat(addresses -> CollectionUtils.all(List.of( new LinkAddress(TEST_VPN_INTERNAL_IP, IP4_PREFIX_LEN), new LinkAddress(TEST_VPN_INTERNAL_IP6, IP6_PREFIX_LEN)), address -> addresses.contains(address)))); verify(mVpnConnectivityMetrics).setServerIpProtocol(TEST_VPN_SERVER_IP); // Check LinkProperties final LinkProperties lp = lpCaptor.getValue(); final List<RouteInfo> expectedRoutes = Loading Loading
services/core/java/com/android/server/connectivity/Vpn.java +6 −0 Original line number Diff line number Diff line Loading @@ -2992,6 +2992,9 @@ public class Vpn { // The update on VPN and the IPsec tunnel will be done when migration is fully complete // in onChildMigrated mIkeConnectionInfo = ikeConnectionInfo; if (mVpnConnectivityMetrics != null) { mVpnConnectivityMetrics.setServerIpProtocol(ikeConnectionInfo.getRemoteAddress()); } } /** Loading Loading @@ -3061,6 +3064,9 @@ public class Vpn { mConfig.addresses.clear(); mConfig.addresses.addAll(internalAddresses); if (mVpnConnectivityMetrics != null) { mVpnConnectivityMetrics.setVpnNetworkIpProtocol(mConfig.addresses); } mConfig.routes.clear(); mConfig.routes.addAll(newRoutes); Loading
services/core/java/com/android/server/connectivity/VpnConnectivityMetrics.java +68 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; import android.net.ConnectivityManager; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkCapabilities; import android.net.VpnManager; Loading @@ -38,6 +39,8 @@ import android.util.SparseArray; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import java.net.Inet4Address; import java.net.InetAddress; import java.util.Arrays; import java.util.List; Loading @@ -50,6 +53,15 @@ public class VpnConnectivityMetrics { public static final int VPN_TYPE_UNKNOWN = 0; public static final int VPN_PROFILE_TYPE_UNKNOWN = 0; private static final int UNKNOWN_UNDERLYING_NETWORK_TYPE = -1; // Copied from corenetworking platform vpn enum @VisibleForTesting static final int IP_PROTOCOL_UNKNOWN = 0; @VisibleForTesting static final int IP_PROTOCOL_IPv4 = 1; @VisibleForTesting static final int IP_PROTOCOL_IPv6 = 2; @VisibleForTesting static final int IP_PROTOCOL_IPv4v6 = 3; private static final SparseArray<String> sAlgorithms = new SparseArray<>(); private final int mUserId; @NonNull Loading @@ -75,6 +87,8 @@ public class VpnConnectivityMetrics { */ @NonNull private int[] mUnderlyingNetworkTypes; private int mVpnNetworkIpProtocol = IP_PROTOCOL_UNKNOWN; private int mServerIpProtocol = IP_PROTOCOL_UNKNOWN; // Static initializer block to populate the sAlgorithms mapping. It associates integer keys // (which also serve as bit positions for the mAllowedAlgorithms bitmask) with their Loading Loading @@ -197,4 +211,58 @@ public class VpnConnectivityMetrics { mUnderlyingNetworkTypes = new int[0]; } } /** * Sets the IP protocol for the vpn network based on a list of {@link LinkAddress} objects. * * @param addresses A list of {@link LinkAddress} objects representing the IP addresses * configured on the VPN network. */ public void setVpnNetworkIpProtocol(@NonNull List<LinkAddress> addresses) { mVpnNetworkIpProtocol = checkIpProtocol(addresses); } /** * Sets the IP protocol for the server based on its {@link InetAddress}. * * @param address The {@link InetAddress} of the server. */ public void setServerIpProtocol(@NonNull InetAddress address) { // Assume that if the address is not IPv4, it is IPv6. It does not consider other cases like // IPv4-mapped IPv6 addresses. if (address instanceof Inet4Address) { mServerIpProtocol = IP_PROTOCOL_IPv4; } else { mServerIpProtocol = IP_PROTOCOL_IPv6; } } /** * Analyzes a list of {@link LinkAddress} objects to determine the overall IP protocol(s) in * use. * * @param addresses A list of {@link LinkAddress} objects to be checked. * @return An integer representing the detected IP protocol. */ @VisibleForTesting static int checkIpProtocol(@NonNull List<LinkAddress> addresses) { boolean hasIpv4 = false; boolean hasIpv6 = false; int ipProtocol = IP_PROTOCOL_UNKNOWN; for (LinkAddress address : addresses) { if (address.isIpv4()) { hasIpv4 = true; } else if (address.isIpv6()) { hasIpv6 = true; } } if (hasIpv4 && hasIpv6) { ipProtocol = IP_PROTOCOL_IPv4v6; } else if (hasIpv4) { ipProtocol = IP_PROTOCOL_IPv4; } else if (hasIpv6) { ipProtocol = IP_PROTOCOL_IPv6; } return ipProtocol; } }
services/tests/VpnTests/java/com/android/server/connectivity/VpnConnectivityMetricsTest.java +17 −0 Original line number Diff line number Diff line Loading @@ -28,13 +28,19 @@ import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512; import static android.net.IpSecAlgorithm.CRYPT_AES_CBC; import static android.net.IpSecAlgorithm.CRYPT_AES_CTR; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_IPv4; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_IPv4v6; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_IPv6; import static com.android.server.connectivity.VpnConnectivityMetrics.IP_PROTOCOL_UNKNOWN; import static com.android.testutils.Cleanup.testAndCleanup; import static com.android.server.connectivity.VpnConnectivityMetrics.buildAllowedAlgorithmsBitmask; import static com.android.server.connectivity.VpnConnectivityMetrics.checkIpProtocol; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.net.Ikev2VpnProfile; import android.net.LinkAddress; import android.util.Log; import androidx.test.ext.junit.runners.AndroidJUnit4; Loading Loading @@ -71,4 +77,15 @@ public class VpnConnectivityMetricsTest { assertTrue(hasFailed.get()); }, () -> Log.setWtfHandler(originalHandler)); } @Test public void testCheckIpProtocol() { final LinkAddress vpnClientIpv4 = new LinkAddress("192.0.2.1/32"); final LinkAddress vpnClientIpv6 = new LinkAddress("2001:db8:1:2::ffe/128"); assertEquals(IP_PROTOCOL_UNKNOWN, checkIpProtocol(List.of())); assertEquals(IP_PROTOCOL_IPv4, checkIpProtocol(List.of(vpnClientIpv4))); assertEquals(IP_PROTOCOL_IPv6, checkIpProtocol(List.of(vpnClientIpv6))); assertEquals(IP_PROTOCOL_IPv4v6, checkIpProtocol(List.of(vpnClientIpv4, vpnClientIpv6))); } }
services/tests/VpnTests/java/com/android/server/connectivity/VpnTest.java +8 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.CollectionUtils; import com.android.server.DeviceIdleInternal; import com.android.server.IpSecService; import com.android.server.VpnTestBase; Loading Loading @@ -2219,6 +2220,13 @@ public class VpnTest extends VpnTestBase { any(), any(), anyString(), ncCaptor.capture(), lpCaptor.capture(), any(), nacCaptor.capture(), any(), any()); verify(mIkeSessionWrapper).setUnderpinnedNetwork(TEST_NETWORK); verify(mVpnConnectivityMetrics).setUnderlyingNetwork(any()); verify(mVpnConnectivityMetrics).setVpnNetworkIpProtocol(argThat(addresses -> CollectionUtils.all(List.of( new LinkAddress(TEST_VPN_INTERNAL_IP, IP4_PREFIX_LEN), new LinkAddress(TEST_VPN_INTERNAL_IP6, IP6_PREFIX_LEN)), address -> addresses.contains(address)))); verify(mVpnConnectivityMetrics).setServerIpProtocol(TEST_VPN_SERVER_IP); // Check LinkProperties final LinkProperties lp = lpCaptor.getValue(); final List<RouteInfo> expectedRoutes = Loading