diff --git a/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java index 007bf23a1c..a9add20239 100644 --- a/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java +++ b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java @@ -25,17 +25,14 @@ import static android.net.InetAddresses.parseNumericAddress; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; import static android.net.TetheringManager.TETHERING_ETHERNET; +import static android.net.TetheringTester.buildTcpPacket; +import static android.net.TetheringTester.buildUdpPacket; +import static android.net.TetheringTester.isAddressIpv4; import static android.net.TetheringTester.isExpectedIcmpPacket; import static android.net.TetheringTester.isExpectedTcpPacket; import static android.net.TetheringTester.isExpectedUdpPacket; -import static android.system.OsConstants.IPPROTO_IP; -import static android.system.OsConstants.IPPROTO_IPV6; -import static android.system.OsConstants.IPPROTO_TCP; -import static android.system.OsConstants.IPPROTO_UDP; import static com.android.net.module.util.HexDump.dumpHexString; -import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4; -import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT; import static com.android.net.module.util.NetworkStackConstants.TCPHDR_ACK; import static com.android.net.module.util.NetworkStackConstants.TCPHDR_SYN; @@ -67,11 +64,9 @@ import android.os.SystemClock; import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.test.platform.app.InstrumentationRegistry; import com.android.modules.utils.build.SdkLevel; -import com.android.net.module.util.PacketBuilder; import com.android.net.module.util.Struct; import com.android.net.module.util.structs.Ipv6Header; import com.android.testutils.HandlerUtils; @@ -128,25 +123,11 @@ public abstract class EthernetTetheringTestBase { (Inet6Address) parseNumericAddress("64:ff9b::808:808"); protected static final IpPrefix TEST_NAT64PREFIX = new IpPrefix("64:ff9b::/96"); - // IPv4 header definition. - protected static final short ID = 27149; - protected static final short FLAGS_AND_FRAGMENT_OFFSET = (short) 0x4000; // flags=DF, offset=0 - protected static final byte TIME_TO_LIVE = (byte) 0x40; - protected static final byte TYPE_OF_SERVICE = 0; - - // IPv6 header definition. - private static final short HOP_LIMIT = 0x40; - // version=6, traffic class=0x0, flowlabel=0x0; - private static final int VERSION_TRAFFICCLASS_FLOWLABEL = 0x60000000; - - // UDP and TCP header definition. // LOCAL_PORT is used by public port and private port. Assume port 9876 has not been used yet // before the testing that public port and private port are the same in the testing. Note that // NAT port forwarding could be different between private port and public port. protected static final short LOCAL_PORT = 9876; protected static final short REMOTE_PORT = 433; - private static final short WINDOW = (short) 0x2000; - private static final short URGENT_POINTER = 0; // Payload definition. protected static final ByteBuffer EMPTY_PAYLOAD = ByteBuffer.wrap(new byte[0]); @@ -654,72 +635,6 @@ public abstract class EthernetTetheringTestBase { return runAsShell(MANAGE_TEST_NETWORKS, () -> initTestNetwork(mContext, lp, TIMEOUT_MS)); } - private short getEthType(@NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp) { - return isAddressIpv4(srcIp, dstIp) ? (short) ETHER_TYPE_IPV4 : (short) ETHER_TYPE_IPV6; - } - - private int getIpProto(@NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp) { - return isAddressIpv4(srcIp, dstIp) ? IPPROTO_IP : IPPROTO_IPV6; - } - - @NonNull - protected ByteBuffer buildUdpPacket( - @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, - @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, - short srcPort, short dstPort, @Nullable final ByteBuffer payload) - throws Exception { - final int ipProto = getIpProto(srcIp, dstIp); - final boolean hasEther = (srcMac != null && dstMac != null); - final int payloadLen = (payload == null) ? 0 : payload.limit(); - final ByteBuffer buffer = PacketBuilder.allocate(hasEther, ipProto, IPPROTO_UDP, - payloadLen); - final PacketBuilder packetBuilder = new PacketBuilder(buffer); - - // [1] Ethernet header - if (hasEther) { - packetBuilder.writeL2Header(srcMac, dstMac, getEthType(srcIp, dstIp)); - } - - // [2] IP header - if (ipProto == IPPROTO_IP) { - packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET, - TIME_TO_LIVE, (byte) IPPROTO_UDP, (Inet4Address) srcIp, (Inet4Address) dstIp); - } else { - packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL, (byte) IPPROTO_UDP, - HOP_LIMIT, (Inet6Address) srcIp, (Inet6Address) dstIp); - } - - // [3] UDP header - packetBuilder.writeUdpHeader(srcPort, dstPort); - - // [4] Payload - if (payload != null) { - buffer.put(payload); - // in case data might be reused by caller, restore the position and - // limit of bytebuffer. - payload.clear(); - } - - return packetBuilder.finalizePacket(); - } - - @NonNull - protected ByteBuffer buildUdpPacket(@NonNull final InetAddress srcIp, - @NonNull final InetAddress dstIp, short srcPort, short dstPort, - @Nullable final ByteBuffer payload) throws Exception { - return buildUdpPacket(null /* srcMac */, null /* dstMac */, srcIp, dstIp, srcPort, - dstPort, payload); - } - - private boolean isAddressIpv4(@NonNull final InetAddress srcIp, - @NonNull final InetAddress dstIp) { - if (srcIp instanceof Inet4Address && dstIp instanceof Inet4Address) return true; - if (srcIp instanceof Inet6Address && dstIp instanceof Inet6Address) return false; - - fail("Unsupported conditions: srcIp " + srcIp + ", dstIp " + dstIp); - return false; // unreachable - } - protected void sendDownloadPacketUdp(@NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, @NonNull final TetheringTester tester, boolean is6To4) throws Exception { @@ -761,45 +676,6 @@ public abstract class EthernetTetheringTestBase { }); } - - @NonNull - private ByteBuffer buildTcpPacket( - @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, - @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, - short srcPort, short dstPort, final short seq, final short ack, - final byte tcpFlags, @NonNull final ByteBuffer payload) throws Exception { - final int ipProto = getIpProto(srcIp, dstIp); - final boolean hasEther = (srcMac != null && dstMac != null); - final ByteBuffer buffer = PacketBuilder.allocate(hasEther, ipProto, IPPROTO_TCP, - payload.limit()); - final PacketBuilder packetBuilder = new PacketBuilder(buffer); - - // [1] Ethernet header - if (hasEther) { - packetBuilder.writeL2Header(srcMac, dstMac, getEthType(srcIp, dstIp)); - } - - // [2] IP header - if (ipProto == IPPROTO_IP) { - packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET, - TIME_TO_LIVE, (byte) IPPROTO_TCP, (Inet4Address) srcIp, (Inet4Address) dstIp); - } else { - packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL, (byte) IPPROTO_TCP, - HOP_LIMIT, (Inet6Address) srcIp, (Inet6Address) dstIp); - } - - // [3] TCP header - packetBuilder.writeTcpHeader(srcPort, dstPort, seq, ack, tcpFlags, WINDOW, URGENT_POINTER); - - // [4] Payload - buffer.put(payload); - // in case data might be reused by caller, restore the position and - // limit of bytebuffer. - payload.clear(); - - return packetBuilder.finalizePacket(); - } - protected void sendDownloadPacketTcp(@NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, short seq, short ack, byte tcpFlags, @NonNull final ByteBuffer payload, @NonNull final TetheringTester tester, diff --git a/Tethering/tests/integration/base/android/net/TetheringTester.java b/Tethering/tests/integration/base/android/net/TetheringTester.java index 1c0803eb82..33baf933dc 100644 --- a/Tethering/tests/integration/base/android/net/TetheringTester.java +++ b/Tethering/tests/integration/base/android/net/TetheringTester.java @@ -17,8 +17,12 @@ package android.net; import static android.net.InetAddresses.parseNumericAddress; +import static android.system.OsConstants.ICMP_ECHO; +import static android.system.OsConstants.ICMP_ECHOREPLY; import static android.system.OsConstants.IPPROTO_ICMP; import static android.system.OsConstants.IPPROTO_ICMPV6; +import static android.system.OsConstants.IPPROTO_IP; +import static android.system.OsConstants.IPPROTO_IPV6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; @@ -27,6 +31,8 @@ import static com.android.net.module.util.DnsPacket.ARSECTION; import static com.android.net.module.util.DnsPacket.NSSECTION; import static com.android.net.module.util.DnsPacket.QDSECTION; import static com.android.net.module.util.HexDump.dumpHexString; +import static com.android.net.module.util.IpUtils.icmpChecksum; +import static com.android.net.module.util.IpUtils.ipChecksum; import static com.android.net.module.util.NetworkStackConstants.ARP_REPLY; import static com.android.net.module.util.NetworkStackConstants.ARP_REQUEST; import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN; @@ -38,6 +44,10 @@ import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT; +import static com.android.net.module.util.NetworkStackConstants.ICMP_CHECKSUM_OFFSET; +import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET; +import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN; +import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET; import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST; import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE; import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED; @@ -58,6 +68,7 @@ import androidx.annotation.Nullable; import com.android.net.module.util.DnsPacket; import com.android.net.module.util.Ipv6Utils; +import com.android.net.module.util.PacketBuilder; import com.android.net.module.util.Struct; import com.android.net.module.util.structs.EthernetHeader; import com.android.net.module.util.structs.Icmpv4Header; @@ -101,6 +112,23 @@ public final class TetheringTester { DhcpPacket.DHCP_LEASE_TIME, }; private static final InetAddress LINK_LOCAL = parseNumericAddress("fe80::1"); + // IPv4 header definition. + protected static final short ID = 27149; + protected static final short FLAGS_AND_FRAGMENT_OFFSET = (short) 0x4000; // flags=DF, offset=0 + protected static final byte TIME_TO_LIVE = (byte) 0x40; + protected static final byte TYPE_OF_SERVICE = 0; + + // IPv6 header definition. + private static final short HOP_LIMIT = 0x40; + // version=6, traffic class=0x0, flowlabel=0x0; + private static final int VERSION_TRAFFICCLASS_FLOWLABEL = 0x60000000; + + // UDP and TCP header definition. + private static final short WINDOW = (short) 0x2000; + private static final short URGENT_POINTER = 0; + + // ICMP definition. + private static final short ICMPECHO_CODE = 0x0; public static final String DHCP_HOSTNAME = "testhostname"; @@ -628,6 +656,190 @@ public final class TetheringTester { return false; } + @NonNull + public static ByteBuffer buildUdpPacket( + @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, + @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, + short srcPort, short dstPort, @Nullable final ByteBuffer payload) + throws Exception { + final int ipProto = getIpProto(srcIp, dstIp); + final boolean hasEther = (srcMac != null && dstMac != null); + final int payloadLen = (payload == null) ? 0 : payload.limit(); + final ByteBuffer buffer = PacketBuilder.allocate(hasEther, ipProto, IPPROTO_UDP, + payloadLen); + final PacketBuilder packetBuilder = new PacketBuilder(buffer); + + // [1] Ethernet header + if (hasEther) { + packetBuilder.writeL2Header(srcMac, dstMac, getEthType(srcIp, dstIp)); + } + + // [2] IP header + if (ipProto == IPPROTO_IP) { + packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET, + TIME_TO_LIVE, (byte) IPPROTO_UDP, (Inet4Address) srcIp, (Inet4Address) dstIp); + } else { + packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL, (byte) IPPROTO_UDP, + HOP_LIMIT, (Inet6Address) srcIp, (Inet6Address) dstIp); + } + + // [3] UDP header + packetBuilder.writeUdpHeader(srcPort, dstPort); + + // [4] Payload + if (payload != null) { + buffer.put(payload); + // in case data might be reused by caller, restore the position and + // limit of bytebuffer. + payload.clear(); + } + + return packetBuilder.finalizePacket(); + } + + @NonNull + public static ByteBuffer buildUdpPacket(@NonNull final InetAddress srcIp, + @NonNull final InetAddress dstIp, short srcPort, short dstPort, + @Nullable final ByteBuffer payload) throws Exception { + return buildUdpPacket(null /* srcMac */, null /* dstMac */, srcIp, dstIp, srcPort, + dstPort, payload); + } + + @NonNull + public static ByteBuffer buildTcpPacket( + @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, + @NonNull final InetAddress srcIp, @NonNull final InetAddress dstIp, + short srcPort, short dstPort, final short seq, final short ack, + final byte tcpFlags, @NonNull final ByteBuffer payload) throws Exception { + final int ipProto = getIpProto(srcIp, dstIp); + final boolean hasEther = (srcMac != null && dstMac != null); + final ByteBuffer buffer = PacketBuilder.allocate(hasEther, ipProto, IPPROTO_TCP, + payload.limit()); + final PacketBuilder packetBuilder = new PacketBuilder(buffer); + + // [1] Ethernet header + if (hasEther) { + packetBuilder.writeL2Header(srcMac, dstMac, getEthType(srcIp, dstIp)); + } + + // [2] IP header + if (ipProto == IPPROTO_IP) { + packetBuilder.writeIpv4Header(TYPE_OF_SERVICE, ID, FLAGS_AND_FRAGMENT_OFFSET, + TIME_TO_LIVE, (byte) IPPROTO_TCP, (Inet4Address) srcIp, (Inet4Address) dstIp); + } else { + packetBuilder.writeIpv6Header(VERSION_TRAFFICCLASS_FLOWLABEL, (byte) IPPROTO_TCP, + HOP_LIMIT, (Inet6Address) srcIp, (Inet6Address) dstIp); + } + + // [3] TCP header + packetBuilder.writeTcpHeader(srcPort, dstPort, seq, ack, tcpFlags, WINDOW, URGENT_POINTER); + + // [4] Payload + buffer.put(payload); + // in case data might be reused by caller, restore the position and + // limit of bytebuffer. + payload.clear(); + + return packetBuilder.finalizePacket(); + } + + // PacketBuilder doesn't support IPv4 ICMP packet. It may need to refactor PacketBuilder first + // because ICMP is a specific layer 3 protocol for PacketBuilder which expects packets always + // have layer 3 (IP) and layer 4 (TCP, UDP) for now. Since we don't use IPv4 ICMP packet too + // much in this test, we just write a ICMP packet builder here. + @NonNull + public static ByteBuffer buildIcmpEchoPacketV4( + @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, + @NonNull final Inet4Address srcIp, @NonNull final Inet4Address dstIp, + int type, short id, short seq) throws Exception { + if (type != ICMP_ECHO && type != ICMP_ECHOREPLY) { + fail("Unsupported ICMP type: " + type); + } + + // Build ICMP echo id and seq fields as payload. Ignore the data field. + final ByteBuffer payload = ByteBuffer.allocate(4); + payload.putShort(id); + payload.putShort(seq); + payload.rewind(); + + final boolean hasEther = (srcMac != null && dstMac != null); + final int etherHeaderLen = hasEther ? Struct.getSize(EthernetHeader.class) : 0; + final int ipv4HeaderLen = Struct.getSize(Ipv4Header.class); + final int Icmpv4HeaderLen = Struct.getSize(Icmpv4Header.class); + final int payloadLen = payload.limit(); + final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv4HeaderLen + + Icmpv4HeaderLen + payloadLen); + + // [1] Ethernet header + if (hasEther) { + final EthernetHeader ethHeader = new EthernetHeader(dstMac, srcMac, ETHER_TYPE_IPV4); + ethHeader.writeToByteBuffer(packet); + } + + // [2] IP header + final Ipv4Header ipv4Header = new Ipv4Header(TYPE_OF_SERVICE, + (short) 0 /* totalLength, calculate later */, ID, + FLAGS_AND_FRAGMENT_OFFSET, TIME_TO_LIVE, (byte) IPPROTO_ICMP, + (short) 0 /* checksum, calculate later */, srcIp, dstIp); + ipv4Header.writeToByteBuffer(packet); + + // [3] ICMP header + final Icmpv4Header icmpv4Header = new Icmpv4Header((byte) type, ICMPECHO_CODE, + (short) 0 /* checksum, calculate later */); + icmpv4Header.writeToByteBuffer(packet); + + // [4] Payload + packet.put(payload); + packet.flip(); + + // [5] Finalize packet + // Used for updating IP header fields. If there is Ehternet header, IPv4 header offset + // in buffer equals ethernet header length because IPv4 header is located next to ethernet + // header. Otherwise, IPv4 header offset is 0. + final int ipv4HeaderOffset = hasEther ? etherHeaderLen : 0; + + // Populate the IPv4 totalLength field. + packet.putShort(ipv4HeaderOffset + IPV4_LENGTH_OFFSET, + (short) (ipv4HeaderLen + Icmpv4HeaderLen + payloadLen)); + + // Populate the IPv4 header checksum field. + packet.putShort(ipv4HeaderOffset + IPV4_CHECKSUM_OFFSET, + ipChecksum(packet, ipv4HeaderOffset /* headerOffset */)); + + // Populate the ICMP checksum field. + packet.putShort(ipv4HeaderOffset + IPV4_HEADER_MIN_LEN + ICMP_CHECKSUM_OFFSET, + icmpChecksum(packet, ipv4HeaderOffset + IPV4_HEADER_MIN_LEN, + Icmpv4HeaderLen + payloadLen)); + return packet; + } + + @NonNull + public static ByteBuffer buildIcmpEchoPacketV4(@NonNull final Inet4Address srcIp, + @NonNull final Inet4Address dstIp, int type, short id, short seq) + throws Exception { + return buildIcmpEchoPacketV4(null /* srcMac */, null /* dstMac */, srcIp, dstIp, + type, id, seq); + } + + private static short getEthType(@NonNull final InetAddress srcIp, + @NonNull final InetAddress dstIp) { + return isAddressIpv4(srcIp, dstIp) ? (short) ETHER_TYPE_IPV4 : (short) ETHER_TYPE_IPV6; + } + + private static int getIpProto(@NonNull final InetAddress srcIp, + @NonNull final InetAddress dstIp) { + return isAddressIpv4(srcIp, dstIp) ? IPPROTO_IP : IPPROTO_IPV6; + } + + public static boolean isAddressIpv4(@NonNull final InetAddress srcIp, + @NonNull final InetAddress dstIp) { + if (srcIp instanceof Inet4Address && dstIp instanceof Inet4Address) return true; + if (srcIp instanceof Inet6Address && dstIp instanceof Inet6Address) return false; + + fail("Unsupported conditions: srcIp " + srcIp + ", dstIp " + dstIp); + return false; // unreachable + } + public void sendUploadPacket(ByteBuffer packet) throws Exception { mDownstreamReader.sendResponse(packet); } diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java index 5d57aa5062..eed308c164 100644 --- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -20,23 +20,17 @@ import static android.net.InetAddresses.parseNumericAddress; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; import static android.net.TetheringManager.TETHERING_ETHERNET; import static android.net.TetheringTester.TestDnsPacket; +import static android.net.TetheringTester.buildIcmpEchoPacketV4; +import static android.net.TetheringTester.buildUdpPacket; import static android.net.TetheringTester.isExpectedIcmpPacket; import static android.net.TetheringTester.isExpectedUdpDnsPacket; import static android.system.OsConstants.ICMP_ECHO; import static android.system.OsConstants.ICMP_ECHOREPLY; -import static android.system.OsConstants.IPPROTO_ICMP; import static com.android.net.module.util.ConnectivityUtils.isIPv6ULA; import static com.android.net.module.util.HexDump.dumpHexString; -import static com.android.net.module.util.IpUtils.icmpChecksum; -import static com.android.net.module.util.IpUtils.ipChecksum; -import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REPLY_TYPE; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE; -import static com.android.net.module.util.NetworkStackConstants.ICMP_CHECKSUM_OFFSET; -import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET; -import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN; -import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -53,14 +47,11 @@ import android.os.SystemProperties; import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.net.module.util.Ipv6Utils; import com.android.net.module.util.Struct; -import com.android.net.module.util.structs.EthernetHeader; -import com.android.net.module.util.structs.Icmpv4Header; import com.android.net.module.util.structs.Ipv4Header; import com.android.net.module.util.structs.UdpHeader; import com.android.testutils.DevSdkIgnoreRule; @@ -96,7 +87,6 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { private static final String TAG = EthernetTetheringTest.class.getSimpleName(); private static final short DNS_PORT = 53; - private static final short ICMPECHO_CODE = 0x0; private static final short ICMPECHO_ID = 0x0; private static final short ICMPECHO_SEQ = 0x0; @@ -564,85 +554,6 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { runClatUdpTest(); } - // PacketBuilder doesn't support IPv4 ICMP packet. It may need to refactor PacketBuilder first - // because ICMP is a specific layer 3 protocol for PacketBuilder which expects packets always - // have layer 3 (IP) and layer 4 (TCP, UDP) for now. Since we don't use IPv4 ICMP packet too - // much in this test, we just write a ICMP packet builder here. - // TODO: move ICMPv4 packet build function to common utilis. - @NonNull - private ByteBuffer buildIcmpEchoPacketV4( - @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac, - @NonNull final Inet4Address srcIp, @NonNull final Inet4Address dstIp, - int type, short id, short seq) throws Exception { - if (type != ICMP_ECHO && type != ICMP_ECHOREPLY) { - fail("Unsupported ICMP type: " + type); - } - - // Build ICMP echo id and seq fields as payload. Ignore the data field. - final ByteBuffer payload = ByteBuffer.allocate(4); - payload.putShort(id); - payload.putShort(seq); - payload.rewind(); - - final boolean hasEther = (srcMac != null && dstMac != null); - final int etherHeaderLen = hasEther ? Struct.getSize(EthernetHeader.class) : 0; - final int ipv4HeaderLen = Struct.getSize(Ipv4Header.class); - final int Icmpv4HeaderLen = Struct.getSize(Icmpv4Header.class); - final int payloadLen = payload.limit(); - final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv4HeaderLen - + Icmpv4HeaderLen + payloadLen); - - // [1] Ethernet header - if (hasEther) { - final EthernetHeader ethHeader = new EthernetHeader(dstMac, srcMac, ETHER_TYPE_IPV4); - ethHeader.writeToByteBuffer(packet); - } - - // [2] IP header - final Ipv4Header ipv4Header = new Ipv4Header(TYPE_OF_SERVICE, - (short) 0 /* totalLength, calculate later */, ID, - FLAGS_AND_FRAGMENT_OFFSET, TIME_TO_LIVE, (byte) IPPROTO_ICMP, - (short) 0 /* checksum, calculate later */, srcIp, dstIp); - ipv4Header.writeToByteBuffer(packet); - - // [3] ICMP header - final Icmpv4Header icmpv4Header = new Icmpv4Header((byte) type, ICMPECHO_CODE, - (short) 0 /* checksum, calculate later */); - icmpv4Header.writeToByteBuffer(packet); - - // [4] Payload - packet.put(payload); - packet.flip(); - - // [5] Finalize packet - // Used for updating IP header fields. If there is Ehternet header, IPv4 header offset - // in buffer equals ethernet header length because IPv4 header is located next to ethernet - // header. Otherwise, IPv4 header offset is 0. - final int ipv4HeaderOffset = hasEther ? etherHeaderLen : 0; - - // Populate the IPv4 totalLength field. - packet.putShort(ipv4HeaderOffset + IPV4_LENGTH_OFFSET, - (short) (ipv4HeaderLen + Icmpv4HeaderLen + payloadLen)); - - // Populate the IPv4 header checksum field. - packet.putShort(ipv4HeaderOffset + IPV4_CHECKSUM_OFFSET, - ipChecksum(packet, ipv4HeaderOffset /* headerOffset */)); - - // Populate the ICMP checksum field. - packet.putShort(ipv4HeaderOffset + IPV4_HEADER_MIN_LEN + ICMP_CHECKSUM_OFFSET, - icmpChecksum(packet, ipv4HeaderOffset + IPV4_HEADER_MIN_LEN, - Icmpv4HeaderLen + payloadLen)); - return packet; - } - - @NonNull - private ByteBuffer buildIcmpEchoPacketV4(@NonNull final Inet4Address srcIp, - @NonNull final Inet4Address dstIp, int type, short id, short seq) - throws Exception { - return buildIcmpEchoPacketV4(null /* srcMac */, null /* dstMac */, srcIp, dstIp, - type, id, seq); - } - @Test public void testIcmpv4Echo() throws Exception { final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),