Merge "Add test for dropping packets to VPN address from non VPN-interface" into main
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index df2e7a6..f81a03d 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -24,6 +24,7 @@
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
@@ -72,6 +73,7 @@
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.InetAddresses;
import android.net.IpSecManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -91,6 +93,7 @@
import android.net.cts.util.CtsNetUtils;
import android.net.util.KeepaliveUtils;
import android.net.wifi.WifiManager;
+import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -249,6 +252,7 @@
@Before
public void setUp() throws Exception {
+ assumeTrue(supportedHardware());
mNetwork = null;
mTestContext = getInstrumentation().getContext();
mTargetContext = getInstrumentation().getTargetContext();
@@ -879,7 +883,6 @@
@Test @IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
public void testChangeUnderlyingNetworks() throws Exception {
- assumeTrue(supportedHardware());
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY));
final TestableNetworkCallback callback = new TestableNetworkCallback();
@@ -938,7 +941,6 @@
@Test
public void testDefault() throws Exception {
- assumeTrue(supportedHardware());
if (!SdkLevel.isAtLeastS() && (
SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
|| SystemProperties.getInt("service.adb.tcp.port", -1) > -1)) {
@@ -1033,8 +1035,6 @@
@Test
public void testAppAllowed() throws Exception {
- assumeTrue(supportedHardware());
-
FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
// Shell app must not be put in here or it would kill the ADB-over-network use case
@@ -1142,8 +1142,6 @@
}
private void doTestAutomaticOnOffKeepaliveMode(final boolean closeSocket) throws Exception {
- assumeTrue(supportedHardware());
-
// Get default network first before starting VPN
final Network defaultNetwork = mCM.getActiveNetwork();
final TestableNetworkCallback cb = new TestableNetworkCallback();
@@ -1231,8 +1229,6 @@
@Test
public void testAppDisallowed() throws Exception {
- assumeTrue(supportedHardware());
-
FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS);
FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
@@ -1265,8 +1261,6 @@
@Test
public void testSocketClosed() throws Exception {
- assumeTrue(supportedHardware());
-
final FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS);
final List<FileDescriptor> remoteFds = new ArrayList<>();
@@ -1290,7 +1284,6 @@
@Test
public void testExcludedRoutes() throws Exception {
- assumeTrue(supportedHardware());
assumeTrue(SdkLevel.isAtLeastT());
// Shell app must not be put in here or it would kill the ADB-over-network use case
@@ -1311,8 +1304,6 @@
@Test
public void testIncludedRoutes() throws Exception {
- assumeTrue(supportedHardware());
-
// Shell app must not be put in here or it would kill the ADB-over-network use case
String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
startVpn(new String[]{"192.0.2.2/32", "2001:db8:1:2::ffe/128"} /* addresses */,
@@ -1330,7 +1321,6 @@
@Test
public void testInterleavedRoutes() throws Exception {
- assumeTrue(supportedHardware());
assumeTrue(SdkLevel.isAtLeastT());
// Shell app must not be put in here or it would kill the ADB-over-network use case
@@ -1358,8 +1348,6 @@
@Test
public void testGetConnectionOwnerUidSecurity() throws Exception {
- assumeTrue(supportedHardware());
-
DatagramSocket s;
InetAddress address = InetAddress.getByName("localhost");
s = new DatagramSocket();
@@ -1380,7 +1368,6 @@
@Test
public void testSetProxy() throws Exception {
- assumeTrue(supportedHardware());
ProxyInfo initialProxy = mCM.getDefaultProxy();
// Receiver for the proxy change broadcast.
BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
@@ -1420,7 +1407,6 @@
@Test
public void testSetProxyDisallowedApps() throws Exception {
- assumeTrue(supportedHardware());
ProxyInfo initialProxy = mCM.getDefaultProxy();
String disallowedApps = mPackageName;
@@ -1446,7 +1432,6 @@
@Test
public void testNoProxy() throws Exception {
- assumeTrue(supportedHardware());
ProxyInfo initialProxy = mCM.getDefaultProxy();
BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
proxyBroadcastReceiver.register();
@@ -1481,7 +1466,6 @@
@Test
public void testBindToNetworkWithProxy() throws Exception {
- assumeTrue(supportedHardware());
String allowedApps = mPackageName;
Network initialNetwork = mCM.getActiveNetwork();
ProxyInfo initialProxy = mCM.getDefaultProxy();
@@ -1506,9 +1490,6 @@
@Test
public void testVpnMeterednessWithNoUnderlyingNetwork() throws Exception {
- if (!supportedHardware()) {
- return;
- }
// VPN is not routing any traffic i.e. its underlying networks is an empty array.
ArrayList<Network> underlyingNetworks = new ArrayList<>();
String allowedApps = mPackageName;
@@ -1538,9 +1519,6 @@
@Test
public void testVpnMeterednessWithNullUnderlyingNetwork() throws Exception {
- if (!supportedHardware()) {
- return;
- }
Network underlyingNetwork = mCM.getActiveNetwork();
if (underlyingNetwork == null) {
Log.i(TAG, "testVpnMeterednessWithNullUnderlyingNetwork cannot execute"
@@ -1567,9 +1545,6 @@
@Test
public void testVpnMeterednessWithNonNullUnderlyingNetwork() throws Exception {
- if (!supportedHardware()) {
- return;
- }
Network underlyingNetwork = mCM.getActiveNetwork();
if (underlyingNetwork == null) {
Log.i(TAG, "testVpnMeterednessWithNonNullUnderlyingNetwork cannot execute"
@@ -1609,9 +1584,6 @@
@Test
public void testAlwaysMeteredVpnWithNullUnderlyingNetwork() throws Exception {
- if (!supportedHardware()) {
- return;
- }
Network underlyingNetwork = mCM.getActiveNetwork();
if (underlyingNetwork == null) {
Log.i(TAG, "testAlwaysMeteredVpnWithNullUnderlyingNetwork cannot execute"
@@ -1636,9 +1608,6 @@
@Test
public void testAlwaysMeteredVpnWithNonNullUnderlyingNetwork() throws Exception {
- if (!supportedHardware()) {
- return;
- }
Network underlyingNetwork = mCM.getActiveNetwork();
if (underlyingNetwork == null) {
Log.i(TAG, "testAlwaysMeteredVpnWithNonNullUnderlyingNetwork cannot execute"
@@ -1676,9 +1645,6 @@
@Test
public void testB141603906() throws Exception {
- if (!supportedHardware()) {
- return;
- }
final InetSocketAddress src = new InetSocketAddress(0);
final InetSocketAddress dst = new InetSocketAddress(0);
final int NUM_THREADS = 8;
@@ -1786,8 +1752,6 @@
*/
@Test
public void testDownloadWithDownloadManagerDisallowed() throws Exception {
- assumeTrue(supportedHardware());
-
// Start a VPN with DownloadManager package in disallowed list.
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
new String[] {"192.0.2.0/24", "2001:db8::/32"},
@@ -1843,7 +1807,6 @@
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
public void testBlockIncomingPackets() throws Exception {
- assumeTrue(supportedHardware());
final Network network = mCM.getActiveNetwork();
assertNotNull("Requires a working Internet connection", network);
@@ -1912,7 +1875,6 @@
@Test
public void testSetVpnDefaultForUids() throws Exception {
- assumeTrue(supportedHardware());
assumeTrue(SdkLevel.isAtLeastU());
final Network defaultNetwork = mCM.getActiveNetwork();
@@ -1958,6 +1920,81 @@
});
}
+ /**
+ * Check if packets to a VPN interface's IP arriving on a non-VPN interface are dropped or not.
+ * If the test interface has a different address from the VPN interface, packets must be dropped
+ * If the test interface has the same address as the VPN interface, packets must not be
+ * dropped
+ *
+ * @param duplicatedAddress true to bring up the test interface with the same address as the VPN
+ * interface
+ */
+ private void doTestDropPacketToVpnAddress(final boolean duplicatedAddress)
+ throws Exception {
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .addTransportType(TRANSPORT_TEST)
+ .build();
+ final CtsNetUtils.TestNetworkCallback callback = new CtsNetUtils.TestNetworkCallback();
+ mCM.requestNetwork(request, callback);
+ final FileDescriptor srcTunFd = runWithShellPermissionIdentity(() -> {
+ final TestNetworkManager tnm = mTestContext.getSystemService(TestNetworkManager.class);
+ List<LinkAddress> linkAddresses = duplicatedAddress
+ ? List.of(new LinkAddress("192.0.2.2/24"),
+ new LinkAddress("2001:db8:1:2::ffe/64")) :
+ List.of(new LinkAddress("198.51.100.2/24"),
+ new LinkAddress("2001:db8:3:4::ffe/64"));
+ final TestNetworkInterface iface = tnm.createTunInterface(linkAddresses);
+ tnm.setupTestNetwork(iface.getInterfaceName(), new Binder());
+ return iface.getFileDescriptor().getFileDescriptor();
+ }, MANAGE_TEST_NETWORKS);
+ final Network testNetwork = callback.waitForAvailable();
+ assertNotNull(testNetwork);
+ final DatagramSocket dstSock = new DatagramSocket();
+
+ testAndCleanup(() -> {
+ startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"} /* addresses */,
+ new String[]{"0.0.0.0/0", "::/0"} /* routes */,
+ "" /* allowedApplications */, "" /* disallowedApplications */,
+ null /* proxyInfo */, null /* underlyingNetworks */,
+ false /* isAlwaysMetered */);
+
+ final FileDescriptor dstUdpFd = dstSock.getFileDescriptor$();
+ checkBlockUdp(srcTunFd, dstUdpFd,
+ InetAddresses.parseNumericAddress("192.0.2.2") /* dstAddress */,
+ InetAddresses.parseNumericAddress("192.0.2.1") /* srcAddress */,
+ duplicatedAddress ? EXPECT_PASS : EXPECT_BLOCK);
+ checkBlockUdp(srcTunFd, dstUdpFd,
+ InetAddresses.parseNumericAddress("2001:db8:1:2::ffe") /* dstAddress */,
+ InetAddresses.parseNumericAddress("2001:db8:1:2::ffa") /* srcAddress */,
+ duplicatedAddress ? EXPECT_PASS : EXPECT_BLOCK);
+
+ // Traffic on VPN should not be affected
+ checkTrafficOnVpn();
+ }, /* cleanup */ () -> {
+ Os.close(srcTunFd);
+ dstSock.close();
+ }, /* cleanup */ () -> {
+ runWithShellPermissionIdentity(() -> {
+ mTestContext.getSystemService(TestNetworkManager.class)
+ .teardownTestNetwork(testNetwork);
+ }, MANAGE_TEST_NETWORKS);
+ }, /* cleanup */ () -> {
+ mCM.unregisterNetworkCallback(callback);
+ });
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testDropPacketToVpnAddress_WithoutDuplicatedAddress() throws Exception {
+ doTestDropPacketToVpnAddress(false /* duplicatedAddress */);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testDropPacketToVpnAddress_WithDuplicatedAddress() throws Exception {
+ doTestDropPacketToVpnAddress(true /* duplicatedAddress */);
+ }
+
private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr,
final short dstPort, final short srcPort, final byte[] payload) throws IOException {
@@ -2001,7 +2038,8 @@
private void checkBlockUdp(
final FileDescriptor srcTunFd,
final FileDescriptor dstUdpFd,
- final boolean ipv6,
+ final InetAddress dstAddress,
+ final InetAddress srcAddress,
final boolean expectBlock) throws Exception {
final Random random = new Random();
final byte[] sendData = new byte[100];
@@ -2009,15 +2047,15 @@
final short dstPort = (short) ((InetSocketAddress) Os.getsockname(dstUdpFd)).getPort();
ByteBuffer buf;
- if (ipv6) {
+ if (dstAddress instanceof Inet6Address) {
buf = buildIpv6UdpPacket(
- (Inet6Address) TEST_IP6_DST_ADDR.getAddress(),
- (Inet6Address) TEST_IP6_SRC_ADDR.getAddress(),
+ (Inet6Address) dstAddress,
+ (Inet6Address) srcAddress,
dstPort, TEST_SRC_PORT, sendData);
} else {
buf = buildIpv4UdpPacket(
- (Inet4Address) TEST_IP4_DST_ADDR.getAddress(),
- (Inet4Address) TEST_IP4_SRC_ADDR.getAddress(),
+ (Inet4Address) dstAddress,
+ (Inet4Address) srcAddress,
dstPort, TEST_SRC_PORT, sendData);
}
@@ -2043,8 +2081,10 @@
final FileDescriptor srcTunFd,
final FileDescriptor dstUdpFd,
final boolean expectBlock) throws Exception {
- checkBlockUdp(srcTunFd, dstUdpFd, false /* ipv6 */, expectBlock);
- checkBlockUdp(srcTunFd, dstUdpFd, true /* ipv6 */, expectBlock);
+ checkBlockUdp(srcTunFd, dstUdpFd, TEST_IP4_DST_ADDR.getAddress(),
+ TEST_IP4_SRC_ADDR.getAddress(), expectBlock);
+ checkBlockUdp(srcTunFd, dstUdpFd, TEST_IP6_DST_ADDR.getAddress(),
+ TEST_IP6_SRC_ADDR.getAddress(), expectBlock);
}
private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
index 4f21af7..f0a87af 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -171,4 +171,16 @@
public void testSetVpnDefaultForUids() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetVpnDefaultForUids");
}
+
+ @Test
+ public void testDropPacketToVpnAddress_WithoutDuplicatedAddress() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest",
+ "testDropPacketToVpnAddress_WithoutDuplicatedAddress");
+ }
+
+ @Test
+ public void testDropPacketToVpnAddress_WithDuplicatedAddress() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest",
+ "testDropPacketToVpnAddress_WithDuplicatedAddress");
+ }
}