Loading tests/integration/src/android/net/util/NetworkStackUtilsIntegrationTest.kt +70 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.net.util import android.Manifest.permission.MANAGE_TEST_NETWORKS import android.content.Context import android.net.InetAddresses.parseNumericAddress import android.net.IpPrefix import android.net.MacAddress import android.net.TestNetworkInterface import android.net.TestNetworkManager Loading @@ -26,12 +27,22 @@ import android.net.dhcp.DhcpPacket import android.os.HandlerThread import android.system.Os import android.system.OsConstants.AF_INET import android.system.OsConstants.AF_PACKET import android.system.OsConstants.ARPHRD_ETHER import android.system.OsConstants.ETH_P_IPV6 import android.system.OsConstants.IPPROTO_UDP import android.system.OsConstants.SOCK_DGRAM import android.system.OsConstants.SOCK_NONBLOCK import androidx.test.platform.app.InstrumentationRegistry import android.system.OsConstants.SOCK_RAW import android.system.OsConstants.SOL_SOCKET import android.system.OsConstants.SO_RCVTIMEO import android.system.StructTimeval import com.android.net.module.util.Ipv6Utils import com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN import com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY import com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST import com.android.net.module.util.structs.PrefixInformationOption import com.android.testutils.ArpRequestFilter import com.android.testutils.ETHER_HEADER_LENGTH import com.android.testutils.IPV4_HEADER_LENGTH Loading @@ -42,9 +53,13 @@ import org.junit.After import org.junit.Assert.assertArrayEquals import org.junit.Before import org.junit.Test import java.io.FileDescriptor import java.net.Inet4Address import kotlin.reflect.KClass import java.net.Inet6Address import java.nio.ByteBuffer import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail class NetworkStackUtilsIntegrationTest { Loading @@ -52,8 +67,12 @@ class NetworkStackUtilsIntegrationTest { private val context by lazy { inst.context } private val TEST_TIMEOUT_MS = 10_000L private val TEST_MTU = 1500 private val TEST_TARGET_IPV4_ADDR = parseNumericAddress("192.0.2.42") as Inet4Address private val TEST_SRC_MAC = MacAddress.fromString("BA:98:76:54:32:10") private val TEST_TARGET_MAC = MacAddress.fromString("01:23:45:67:89:0A") private val TEST_INET6ADDR_1 = parseNumericAddress("2001:db8::1") as Inet6Address private val TEST_INET6ADDR_2 = parseNumericAddress("2001:db8::2") as Inet6Address private val readerHandler = HandlerThread( NetworkStackUtilsIntegrationTest::class.java.simpleName) Loading Loading @@ -103,8 +122,7 @@ class NetworkStackUtilsIntegrationTest { null /* hostname */, false /* metered */, 1500 /* mtu */, null /* captivePortalUrl */) // Not using .array as per errorprone "ByteBufferBackingArray" recommendation val originalPacket = ByteArray(buffer.limit()) buffer.get(originalPacket) val originalPacket = buffer.readAsArray() Os.sendto(socket, originalPacket, 0 /* bytesOffset */, originalPacket.size /* bytesCount */, 0 /* flags */, TEST_TARGET_IPV4_ADDR, DhcpPacket.DHCP_CLIENT.toInt() /* port */) Loading @@ -112,7 +130,7 @@ class NetworkStackUtilsIntegrationTest { // Verify the packet was sent to the mac address specified in the ARP entry // Also accept ARP requests, but expect that none is sent before the UDP packet // IPv6 NS may be sent on the interface but will be filtered out val sentPacket = reader.popPacket(TEST_TIMEOUT_MS, IPv4UdpFilter().or(ArpRequestFilter())) val sentPacket = reader.poll(TEST_TIMEOUT_MS, IPv4UdpFilter().or(ArpRequestFilter())) ?: fail("Packet was not sent on the interface") val sentTargetAddr = MacAddress.fromBytes(sentPacket.copyOfRange(0, ETHER_ADDR_LEN)) Loading @@ -123,6 +141,54 @@ class NetworkStackUtilsIntegrationTest { assertArrayEquals("Sent packet != original packet", originalPacket, sentDhcpPacket) } @Test fun testAttachRaFilter() { val socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6) val ifParams = InterfaceParams.getByName(iface.interfaceName) ?: fail("Could not obtain interface params for ${iface.interfaceName}") val socketAddr = SocketUtils.makePacketSocketAddress(ETH_P_IPV6, ifParams.index) Os.bind(socket, socketAddr) Os.setsockoptTimeval(socket, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(TEST_TIMEOUT_MS)) // Verify that before setting any filter, the socket receives pings val echo = Ipv6Utils.buildEchoRequestPacket(TEST_SRC_MAC, TEST_TARGET_MAC, TEST_INET6ADDR_1, TEST_INET6ADDR_2) reader.sendResponse(echo) echo.rewind() assertNextPacketEquals(socket, echo.readAsArray(), "ICMPv6 echo") NetworkStackUtils.attachRaFilter(socket, ARPHRD_ETHER) // Send another echo, then an RA. After setting the filter expect only the RA. echo.rewind() reader.sendResponse(echo) val pio = PrefixInformationOption.build(IpPrefix("2001:db8:1::/64"), 0.toByte() /* flags */, 3600 /* validLifetime */, 1800 /* preferredLifetime */) val ra = Ipv6Utils.buildRaPacket(TEST_SRC_MAC, TEST_TARGET_MAC, TEST_INET6ADDR_1 /* routerAddr */, IPV6_ADDR_ALL_NODES_MULTICAST, 0.toByte() /* flags */, 1800 /* lifetime */, 0 /* reachableTime */, 0 /* retransTimer */, pio) reader.sendResponse(ra) ra.rewind() assertNextPacketEquals(socket, ra.readAsArray(), "ICMPv6 RA") } private fun assertNextPacketEquals(socket: FileDescriptor, expected: ByteArray, descr: String) { val buffer = ByteArray(TEST_MTU) val readPacket = Os.read(socket, buffer, 0 /* byteOffset */, buffer.size) assertTrue(readPacket > 0, "$descr not received") assertEquals(expected.size, readPacket, "Received packet size does not match for $descr") assertArrayEquals("Received packet != expected $descr", expected, buffer.copyOfRange(0, readPacket)) } } private fun ByteBuffer.readAsArray(): ByteArray { val out = ByteArray(remaining()) get(out) return out } private fun <T : Any> Context.assertHasService(manager: KClass<T>) = getSystemService(manager.java) Loading Loading
tests/integration/src/android/net/util/NetworkStackUtilsIntegrationTest.kt +70 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.net.util import android.Manifest.permission.MANAGE_TEST_NETWORKS import android.content.Context import android.net.InetAddresses.parseNumericAddress import android.net.IpPrefix import android.net.MacAddress import android.net.TestNetworkInterface import android.net.TestNetworkManager Loading @@ -26,12 +27,22 @@ import android.net.dhcp.DhcpPacket import android.os.HandlerThread import android.system.Os import android.system.OsConstants.AF_INET import android.system.OsConstants.AF_PACKET import android.system.OsConstants.ARPHRD_ETHER import android.system.OsConstants.ETH_P_IPV6 import android.system.OsConstants.IPPROTO_UDP import android.system.OsConstants.SOCK_DGRAM import android.system.OsConstants.SOCK_NONBLOCK import androidx.test.platform.app.InstrumentationRegistry import android.system.OsConstants.SOCK_RAW import android.system.OsConstants.SOL_SOCKET import android.system.OsConstants.SO_RCVTIMEO import android.system.StructTimeval import com.android.net.module.util.Ipv6Utils import com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN import com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY import com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST import com.android.net.module.util.structs.PrefixInformationOption import com.android.testutils.ArpRequestFilter import com.android.testutils.ETHER_HEADER_LENGTH import com.android.testutils.IPV4_HEADER_LENGTH Loading @@ -42,9 +53,13 @@ import org.junit.After import org.junit.Assert.assertArrayEquals import org.junit.Before import org.junit.Test import java.io.FileDescriptor import java.net.Inet4Address import kotlin.reflect.KClass import java.net.Inet6Address import java.nio.ByteBuffer import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail class NetworkStackUtilsIntegrationTest { Loading @@ -52,8 +67,12 @@ class NetworkStackUtilsIntegrationTest { private val context by lazy { inst.context } private val TEST_TIMEOUT_MS = 10_000L private val TEST_MTU = 1500 private val TEST_TARGET_IPV4_ADDR = parseNumericAddress("192.0.2.42") as Inet4Address private val TEST_SRC_MAC = MacAddress.fromString("BA:98:76:54:32:10") private val TEST_TARGET_MAC = MacAddress.fromString("01:23:45:67:89:0A") private val TEST_INET6ADDR_1 = parseNumericAddress("2001:db8::1") as Inet6Address private val TEST_INET6ADDR_2 = parseNumericAddress("2001:db8::2") as Inet6Address private val readerHandler = HandlerThread( NetworkStackUtilsIntegrationTest::class.java.simpleName) Loading Loading @@ -103,8 +122,7 @@ class NetworkStackUtilsIntegrationTest { null /* hostname */, false /* metered */, 1500 /* mtu */, null /* captivePortalUrl */) // Not using .array as per errorprone "ByteBufferBackingArray" recommendation val originalPacket = ByteArray(buffer.limit()) buffer.get(originalPacket) val originalPacket = buffer.readAsArray() Os.sendto(socket, originalPacket, 0 /* bytesOffset */, originalPacket.size /* bytesCount */, 0 /* flags */, TEST_TARGET_IPV4_ADDR, DhcpPacket.DHCP_CLIENT.toInt() /* port */) Loading @@ -112,7 +130,7 @@ class NetworkStackUtilsIntegrationTest { // Verify the packet was sent to the mac address specified in the ARP entry // Also accept ARP requests, but expect that none is sent before the UDP packet // IPv6 NS may be sent on the interface but will be filtered out val sentPacket = reader.popPacket(TEST_TIMEOUT_MS, IPv4UdpFilter().or(ArpRequestFilter())) val sentPacket = reader.poll(TEST_TIMEOUT_MS, IPv4UdpFilter().or(ArpRequestFilter())) ?: fail("Packet was not sent on the interface") val sentTargetAddr = MacAddress.fromBytes(sentPacket.copyOfRange(0, ETHER_ADDR_LEN)) Loading @@ -123,6 +141,54 @@ class NetworkStackUtilsIntegrationTest { assertArrayEquals("Sent packet != original packet", originalPacket, sentDhcpPacket) } @Test fun testAttachRaFilter() { val socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6) val ifParams = InterfaceParams.getByName(iface.interfaceName) ?: fail("Could not obtain interface params for ${iface.interfaceName}") val socketAddr = SocketUtils.makePacketSocketAddress(ETH_P_IPV6, ifParams.index) Os.bind(socket, socketAddr) Os.setsockoptTimeval(socket, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(TEST_TIMEOUT_MS)) // Verify that before setting any filter, the socket receives pings val echo = Ipv6Utils.buildEchoRequestPacket(TEST_SRC_MAC, TEST_TARGET_MAC, TEST_INET6ADDR_1, TEST_INET6ADDR_2) reader.sendResponse(echo) echo.rewind() assertNextPacketEquals(socket, echo.readAsArray(), "ICMPv6 echo") NetworkStackUtils.attachRaFilter(socket, ARPHRD_ETHER) // Send another echo, then an RA. After setting the filter expect only the RA. echo.rewind() reader.sendResponse(echo) val pio = PrefixInformationOption.build(IpPrefix("2001:db8:1::/64"), 0.toByte() /* flags */, 3600 /* validLifetime */, 1800 /* preferredLifetime */) val ra = Ipv6Utils.buildRaPacket(TEST_SRC_MAC, TEST_TARGET_MAC, TEST_INET6ADDR_1 /* routerAddr */, IPV6_ADDR_ALL_NODES_MULTICAST, 0.toByte() /* flags */, 1800 /* lifetime */, 0 /* reachableTime */, 0 /* retransTimer */, pio) reader.sendResponse(ra) ra.rewind() assertNextPacketEquals(socket, ra.readAsArray(), "ICMPv6 RA") } private fun assertNextPacketEquals(socket: FileDescriptor, expected: ByteArray, descr: String) { val buffer = ByteArray(TEST_MTU) val readPacket = Os.read(socket, buffer, 0 /* byteOffset */, buffer.size) assertTrue(readPacket > 0, "$descr not received") assertEquals(expected.size, readPacket, "Received packet size does not match for $descr") assertArrayEquals("Received packet != expected $descr", expected, buffer.copyOfRange(0, readPacket)) } } private fun ByteBuffer.readAsArray(): ByteArray { val out = ByteArray(remaining()) get(out) return out } private fun <T : Any> Context.assertHasService(manager: KClass<T>) = getSystemService(manager.java) Loading