Merge "[ST02] Add methods for synthesizing DNS packets"
diff --git a/staticlibs/framework/com/android/net/module/util/IpUtils.java b/staticlibs/framework/com/android/net/module/util/IpUtils.java
index dbc2285..569733e 100644
--- a/staticlibs/framework/com/android/net/module/util/IpUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/IpUtils.java
@@ -39,7 +39,7 @@
 
     /**
      * Performs an IP checksum (used in IP header and across UDP
-     * payload) on the specified portion of a ByteBuffer.  The seed
+     * payload) or ICMP checksum on the specified portion of a ByteBuffer.  The seed
      * allows the checksum to commence with a specified value.
      */
     private static int checksum(ByteBuffer buf, int seed, int start, int end) {
@@ -145,6 +145,14 @@
     }
 
     /**
+     * Calculate the ICMP checksum for an ICMPv4 packet.
+     */
+    public static short icmpChecksum(ByteBuffer buf, int transportOffset, int transportLen) {
+        // ICMP checksum doesn't include pseudo-header. See RFC 792.
+        return (short) checksum(buf, 0, transportOffset, transportOffset + transportLen);
+    }
+
+    /**
      * Calculate the ICMPv6 checksum for an ICMPv6 packet.
      */
     public static short icmpv6Checksum(ByteBuffer buf, int ipOffset, int transportOffset,
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
index 1ad9c35..ebef155 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
@@ -127,6 +127,14 @@
             (Inet6Address) InetAddresses.parseNumericAddress("ff02::3");
 
     /**
+     * ICMP constants.
+     *
+     * See also:
+     *     - https://tools.ietf.org/html/rfc792
+     */
+    public static final int ICMP_CHECKSUM_OFFSET = 2;
+
+    /**
      * ICMPv6 constants.
      *
      * See also:
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/IpUtilsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/IpUtilsTest.java
index 3468309..20555b3 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/IpUtilsTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/IpUtilsTest.java
@@ -16,6 +16,9 @@
 
 package com.android.net.module.util;
 
+import static com.android.net.module.util.NetworkStackConstants.ICMP_CHECKSUM_OFFSET;
+import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET;
+
 import static org.junit.Assert.assertEquals;
 
 import androidx.test.filters.SmallTest;
@@ -34,7 +37,6 @@
     private static final int IPV6_HEADER_LENGTH = 40;
     private static final int TCP_HEADER_LENGTH = 20;
     private static final int UDP_HEADER_LENGTH = 8;
-    private static final int IP_CHECKSUM_OFFSET = 10;
     private static final int TCP_CHECKSUM_OFFSET = 16;
     private static final int UDP_CHECKSUM_OFFSET = 6;
 
@@ -141,7 +143,7 @@
         assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
 
         // Check that we can calculate the checksums from scratch.
-        final int ipSumOffset = IP_CHECKSUM_OFFSET;
+        final int ipSumOffset = IPV4_CHECKSUM_OFFSET;
         final int ipSum = getChecksum(packet, ipSumOffset);
         assertEquals(0xf68b, ipSum);
 
@@ -163,4 +165,47 @@
         assertEquals(0, IpUtils.ipChecksum(packet, 0));
         assertEquals((short) 0xffff, IpUtils.udpChecksum(packet, 0, IPV4_HEADER_LENGTH));
     }
+
+    @Test
+    public void testIpv4IcmpChecksum() throws Exception {
+        // packet = (scapy.IP(src="192.0.2.1", dst="192.0.2.2", tos=0x40) /
+        //           scapy.ICMP(type=0x8, id=0x1234, seq=0x5678) /
+        //           "hello, world")
+        ByteBuffer packet = ByteBuffer.wrap(new byte[] {
+            /* IPv4 */
+            (byte) 0x45, (byte) 0x40, (byte) 0x00, (byte) 0x28,
+            (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+            (byte) 0x40, (byte) 0x01, (byte) 0xf6, (byte) 0x90,
+            (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01,
+            (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02,
+            /* ICMP */
+            (byte) 0x08,                                         /* type: echo-request */
+            (byte) 0x00,                                         /* code: 0 */
+            (byte) 0x4f, (byte) 0x07,                            /* chksum: 0x4f07 */
+            (byte) 0x12, (byte) 0x34,                            /* id: 0x1234 */
+            (byte) 0x56, (byte) 0x78,                            /* seq: 0x5678 */
+            (byte) 0x68, (byte) 0x65, (byte) 0x6c, (byte) 0x6c,  /* data: hello, world */
+            (byte) 0x6f, (byte) 0x2c, (byte) 0x20, (byte) 0x77,
+            (byte) 0x6f, (byte) 0x72, (byte) 0x6c, (byte) 0x64
+        });
+
+        // Check that a valid packet has checksum 0.
+        int transportLen = packet.limit() - IPV4_HEADER_LENGTH;
+        assertEquals(0, IpUtils.icmpChecksum(packet, IPV4_HEADER_LENGTH, transportLen));
+
+        // Check that we can calculate the checksum from scratch.
+        int sumOffset = IPV4_HEADER_LENGTH + ICMP_CHECKSUM_OFFSET;
+        int sum = getUnsignedByte(packet, sumOffset) * 256 + getUnsignedByte(packet, sumOffset + 1);
+        assertEquals(0x4f07, sum);
+
+        packet.put(sumOffset, (byte) 0);
+        packet.put(sumOffset + 1, (byte) 0);
+        assertChecksumEquals(sum, IpUtils.icmpChecksum(packet, IPV4_HEADER_LENGTH, transportLen));
+
+        // Check that writing the checksum back into the packet results in a valid packet.
+        packet.putShort(
+            sumOffset,
+            IpUtils.icmpChecksum(packet, IPV4_HEADER_LENGTH, transportLen));
+        assertEquals(0, IpUtils.icmpChecksum(packet, IPV4_HEADER_LENGTH, transportLen));
+    }
 }
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/NetlinkSocketTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/NetlinkSocketTest.java
index 33ea602..f4073b6 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/NetlinkSocketTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/NetlinkSocketTest.java
@@ -236,7 +236,7 @@
         @Field(order = 3, type = Type.U8)
         public short scope;
 
-        @Field(order = 4, type = Type.U32)
-        public long index;
+        @Field(order = 4, type = Type.S32)
+        public int index;
     }
 }