[automerger skipped] Merge "Test that VpnManager events will never be sent to Settings VPNs" into tm-dev am: 395e01957f am: b6d022d834 -s ours

am skip reason: Merged-In I1706ceb129ef95f44d45754665b9dbcf9b6fdfd4 with SHA-1 67e660e537 is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/19415386

Change-Id: Ia1497f4a84a479541b9c739ec0982cb91aea66af
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/bpf_progs/dscp_policy.c b/bpf_progs/dscp_policy.c
index 538a9e4..38e1050 100644
--- a/bpf_progs/dscp_policy.c
+++ b/bpf_progs/dscp_policy.c
@@ -297,7 +297,7 @@
 }
 
 DEFINE_BPF_PROG_KVER("schedcls/set_dscp_ether", AID_ROOT, AID_SYSTEM,
-                     schedcls_set_dscp_ether, KVER(5, 4, 0))
+                     schedcls_set_dscp_ether, KVER(5, 15, 0))
 (struct __sk_buff* skb) {
 
     if (skb->pkt_type != PACKET_HOST) return TC_ACT_PIPE;
@@ -313,7 +313,7 @@
 }
 
 DEFINE_BPF_PROG_KVER("schedcls/set_dscp_raw_ip", AID_ROOT, AID_SYSTEM,
-                     schedcls_set_dscp_raw_ip, KVER(5, 4, 0))
+                     schedcls_set_dscp_raw_ip, KVER(5, 15, 0))
 (struct __sk_buff* skb) {
     if (skb->protocol == htons(ETH_P_IP)) {
         match_policy(skb, true, false);
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index 4a7c77a..3272075 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -17,6 +17,7 @@
 package com.android.server.connectivity;
 
 import static android.net.INetd.IF_STATE_UP;
+import static android.net.INetd.PERMISSION_NETWORK;
 import static android.net.INetd.PERMISSION_SYSTEM;
 import static android.system.OsConstants.ETH_P_IP;
 import static android.system.OsConstants.ETH_P_IPV6;
@@ -353,9 +354,9 @@
     static int getFwmark(int netId) {
         // See union Fwmark in system/netd/include/Fwmark.h
         return (netId & 0xffff)
-                | 0x1 << 16  // protectedFromVpn: true
-                | 0x1 << 17  // explicitlySelected: true
-                | (PERMISSION_SYSTEM & 0x3) << 18;
+                | 0x1 << 16  // explicitlySelected: true
+                | 0x1 << 17  // protectedFromVpn: true
+                | ((PERMISSION_NETWORK | PERMISSION_SYSTEM) & 0x3) << 18;  // 2 permission bits = 3
     }
 
     @VisibleForTesting
diff --git a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
index bbac09b..621b743 100644
--- a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
+++ b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
@@ -136,8 +136,8 @@
 
     @Before
     fun setUp() {
-        // For BPF support kernel needs to be at least 5.4.
-        assumeTrue(kernelIsAtLeast(5, 4))
+        // For BPF support kernel needs to be at least 5.15.
+        assumeTrue(kernelIsAtLeast(5, 15))
 
         runAsShell(MANAGE_TEST_NETWORKS) {
             val tnm = realContext.getSystemService(TestNetworkManager::class.java)
@@ -158,7 +158,7 @@
 
     @After
     fun tearDown() {
-        if (!kernelIsAtLeast(5, 4)) {
+        if (!kernelIsAtLeast(5, 15)) {
             return;
         }
         agentsToCleanUp.forEach { it.unregister() }
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index db39e6f..2cd3310 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -124,6 +124,9 @@
 static const set<string> INTRODUCED_T_5_4 = {
     SHARED "prog_block_bind4_block_port",
     SHARED "prog_block_bind6_block_port",
+};
+
+static const set<string> INTRODUCED_T_5_15 = {
     SHARED "prog_dscp_policy_schedcls_set_dscp_ether",
     SHARED "prog_dscp_policy_schedcls_set_dscp_raw_ip",
 };
@@ -168,6 +171,7 @@
     if (IsAtLeastT()) {
         addAll(expected, INTRODUCED_T);
         if (android::bpf::isAtLeastKernelVersion(5, 4, 0)) addAll(expected, INTRODUCED_T_5_4);
+        if (android::bpf::isAtLeastKernelVersion(5, 15, 0)) addAll(expected, INTRODUCED_T_5_15);
         removeAll(expected, REMOVED_T);
 
         addAll(unexpected, REMOVED_T);
diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
index f84d10f..7c18ecb 100644
--- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
@@ -84,10 +84,10 @@
     private static final int GOOGLE_DNS_4 = 0x08080808;  // 8.8.8.8
     private static final int NETID = 42;
 
-    // The test fwmark means: PERMISSION_SYSTEM (0x2), protectedFromVpn: true,
+    // The test fwmark means: PERMISSION_NETWORK | PERMISSION_SYSTEM (0x3), protectedFromVpn: true,
     // explicitlySelected: true, netid: 42. For bit field structure definition, see union Fwmark in
     // system/netd/include/Fwmark.h
-    private static final int MARK = 0xb002a;
+    private static final int MARK = 0xf002a;
 
     private static final String XLAT_LOCAL_IPV4ADDR_STRING = "192.0.0.46";
     private static final String XLAT_LOCAL_IPV6ADDR_STRING = "2001:db8:0:b11::464";
@@ -483,10 +483,10 @@
 
     @Test
     public void testGetFwmark() throws Exception {
-        assertEquals(0xb0064, ClatCoordinator.getFwmark(100));
-        assertEquals(0xb03e8, ClatCoordinator.getFwmark(1000));
-        assertEquals(0xb2710, ClatCoordinator.getFwmark(10000));
-        assertEquals(0xbffff, ClatCoordinator.getFwmark(65535));
+        assertEquals(0xf0064, ClatCoordinator.getFwmark(100));
+        assertEquals(0xf03e8, ClatCoordinator.getFwmark(1000));
+        assertEquals(0xf2710, ClatCoordinator.getFwmark(10000));
+        assertEquals(0xfffff, ClatCoordinator.getFwmark(65535));
     }
 
     @Test
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 6266d8c..b0440d5 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -207,7 +207,7 @@
     private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345;
     private static final long TEST_TIMEOUT_MS = 500L;
     private static final String PRIMARY_USER_APP_EXCLUDE_KEY =
-            "VPN_APP_EXCLUDED_27_com.testvpn.vpn";
+            "VPNAPPEXCLUDED_27_com.testvpn.vpn";
     /**
      * Names and UIDs for some fake packages. Important points:
      *  - UID is ordered increasing.
@@ -1315,7 +1315,7 @@
                 config -> Arrays.asList(config.flags).contains(flag)));
     }
 
-    private void setupPlatformVpnWithSpecificExceptionAndItsErrorCode(IkeException exception,
+    private void doTestPlatformVpnWithException(IkeException exception,
             String category, int errorType, int errorCode) throws Exception {
         final ArgumentCaptor<IkeSessionCallback> captor =
                 ArgumentCaptor.forClass(IkeSessionCallback.class);
@@ -1333,6 +1333,7 @@
         // state
         verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
                 .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
+        reset(mIkev2SessionCreator);
         final IkeSessionCallback ikeCb = captor.getValue();
         ikeCb.onClosedWithException(exception);
 
@@ -1342,6 +1343,23 @@
         if (errorType == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) {
             verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS))
                     .unregisterNetworkCallback(eq(cb));
+        } else if (errorType == VpnManager.ERROR_CLASS_RECOVERABLE) {
+            // To prevent spending much time to test the retry function, only retry 2 times here.
+            int retryIndex = 0;
+            verify(mIkev2SessionCreator,
+                    timeout(((TestDeps) vpn.mDeps).getNextRetryDelaySeconds(retryIndex++) * 1000
+                            + TEST_TIMEOUT_MS))
+                    .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
+
+            // Capture a new IkeSessionCallback to get the latest token.
+            reset(mIkev2SessionCreator);
+            final IkeSessionCallback ikeCb2 = captor.getValue();
+            ikeCb2.onClosedWithException(exception);
+            verify(mIkev2SessionCreator,
+                    timeout(((TestDeps) vpn.mDeps).getNextRetryDelaySeconds(retryIndex++) * 1000
+                            + TEST_TIMEOUT_MS))
+                    .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
+            reset(mIkev2SessionCreator);
         }
     }
 
@@ -1350,7 +1368,7 @@
         final IkeProtocolException exception = mock(IkeProtocolException.class);
         final int errorCode = IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
         when(exception.getErrorType()).thenReturn(errorCode);
-        setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+        doTestPlatformVpnWithException(exception,
                 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
                 errorCode);
     }
@@ -1360,7 +1378,7 @@
         final IkeProtocolException exception = mock(IkeProtocolException.class);
         final int errorCode = IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;
         when(exception.getErrorType()).thenReturn(errorCode);
-        setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+        doTestPlatformVpnWithException(exception,
                 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, errorCode);
     }
 
@@ -1370,7 +1388,7 @@
         final UnknownHostException unknownHostException = new UnknownHostException();
         final int errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST;
         when(exception.getCause()).thenReturn(unknownHostException);
-        setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+        doTestPlatformVpnWithException(exception,
                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
                 errorCode);
     }
@@ -1382,7 +1400,7 @@
                 new IkeTimeoutException("IkeTimeoutException");
         final int errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT;
         when(exception.getCause()).thenReturn(ikeTimeoutException);
-        setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+        doTestPlatformVpnWithException(exception,
                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
                 errorCode);
     }
@@ -1391,7 +1409,7 @@
     public void testStartPlatformVpnFailedWithIkeNetworkLostException() throws Exception {
         final IkeNetworkLostException exception = new IkeNetworkLostException(
                 new Network(100));
-        setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+        doTestPlatformVpnWithException(exception,
                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
                 VpnManager.ERROR_CODE_NETWORK_LOST);
     }
@@ -1402,7 +1420,7 @@
         final IOException ioException = new IOException();
         final int errorCode = VpnManager.ERROR_CODE_NETWORK_IO;
         when(exception.getCause()).thenReturn(ioException);
-        setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+        doTestPlatformVpnWithException(exception,
                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
                 errorCode);
     }
@@ -1515,6 +1533,16 @@
         startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve
     }
 
+    @Test
+    public void testStartPptp() throws Exception {
+        startPptp(true /* useMppe */);
+    }
+
+    @Test
+    public void testStartPptp_NoMppe() throws Exception {
+        startPptp(false /* useMppe */);
+    }
+
     private void assertTransportInfoMatches(NetworkCapabilities nc, int type) {
         assertNotNull(nc);
         VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo();
@@ -1522,6 +1550,49 @@
         assertEquals(type, ti.getType());
     }
 
+    private void startPptp(boolean useMppe) throws Exception {
+        final VpnProfile profile = new VpnProfile("testProfile" /* key */);
+        profile.type = VpnProfile.TYPE_PPTP;
+        profile.name = "testProfileName";
+        profile.username = "userName";
+        profile.password = "thePassword";
+        profile.server = "192.0.2.123";
+        profile.mppe = useMppe;
+
+        doReturn(new Network[] { new Network(101) }).when(mConnectivityManager).getAllNetworks();
+        doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(any(), any(),
+                any(), any(), any(), any(), anyInt());
+
+        final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile);
+        final TestDeps deps = (TestDeps) vpn.mDeps;
+
+        // TODO: use import when this is merged in all branches and there's no merge conflict
+        com.android.testutils.Cleanup.testAndCleanup(() -> {
+            final String[] mtpdArgs = deps.mtpdArgs.get(10, TimeUnit.SECONDS);
+            final String[] argsPrefix = new String[]{
+                    EGRESS_IFACE, "pptp", profile.server, "1723", "name", profile.username,
+                    "password", profile.password, "linkname", "vpn", "refuse-eap", "nodefaultroute",
+                    "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270"
+            };
+            assertArrayEquals(argsPrefix, Arrays.copyOf(mtpdArgs, argsPrefix.length));
+            if (useMppe) {
+                assertEquals(argsPrefix.length + 2, mtpdArgs.length);
+                assertEquals("+mppe", mtpdArgs[argsPrefix.length]);
+                assertEquals("-pap", mtpdArgs[argsPrefix.length + 1]);
+            } else {
+                assertEquals(argsPrefix.length + 1, mtpdArgs.length);
+                assertEquals("nomppe", mtpdArgs[argsPrefix.length]);
+            }
+
+            verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
+                    any(), any(), any(), any(), anyInt());
+        }, () -> { // Cleanup
+                vpn.mVpnRunner.exitVpnRunner();
+                deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier
+                vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup
+            });
+    }
+
     public void startRacoon(final String serverAddr, final String expectedAddr)
             throws Exception {
         final ConditionVariable legacyRunnerReady = new ConditionVariable();
@@ -1719,6 +1790,11 @@
         public DeviceIdleInternal getDeviceIdleInternal() {
             return mDeviceIdleInternal;
         }
+
+        public long getNextRetryDelaySeconds(int retryCount) {
+            // Simply return retryCount as the delay seconds for retrying.
+            return retryCount;
+        }
     }
 
     /**