Remove the meaningless status message in status code option.

status-message is UTF-8 encoded text string suitable for display to the
end user, which is not useful for Dhcp6client's decision on if it should
ignore the current reply, just skip the status-message parsing for the
top level status code option.

Bug: 315069348
Test: atest NetworkStackTests
Change-Id: If231729abf6294acbab4c16b0c7a8665ad588548
diff --git a/src/android/net/dhcp6/Dhcp6Packet.java b/src/android/net/dhcp6/Dhcp6Packet.java
index 4ef3195..9d6d5aa 100644
--- a/src/android/net/dhcp6/Dhcp6Packet.java
+++ b/src/android/net/dhcp6/Dhcp6Packet.java
@@ -32,7 +32,6 @@
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -96,7 +95,6 @@
      */
     public static final byte DHCP6_STATUS_CODE = 13;
     protected short mStatusCode;
-    protected String mStatusMsg;
 
     public static final short STATUS_SUCCESS           = 0;
     public static final short STATUS_UNSPEC_FAIL       = 1;
@@ -374,35 +372,6 @@
     }
 
     /**
-     * Reads a string of specified length from the buffer.
-     *
-     * TODO: move to a common place which can be shared with DhcpClient.
-     */
-    private static String readAsciiString(@NonNull final ByteBuffer buf, int byteCount,
-            boolean isNullOk) {
-        final byte[] bytes = new byte[byteCount];
-        buf.get(bytes);
-        return readAsciiString(bytes, isNullOk);
-    }
-
-    private static String readAsciiString(@NonNull final byte[] payload, boolean isNullOk) {
-        final byte[] bytes = payload;
-        int length = bytes.length;
-        if (!isNullOk) {
-            // Stop at the first null byte. This is because some DHCP options (e.g., the domain
-            // name) are passed to netd via FrameworkListener, which refuses arguments containing
-            // null bytes. We don't do this by default because vendorInfo is an opaque string which
-            // could in theory contain null bytes.
-            for (length = 0; length < bytes.length; length++) {
-                if (bytes[length] == 0) {
-                    break;
-                }
-            }
-        }
-        return new String(bytes, 0, length, StandardCharsets.US_ASCII);
-    }
-
-    /**
      * Creates a concrete Dhcp6Packet from the supplied ByteBuffer.
      *
      * The buffer only starts with a UDP encapsulation (i.e. DHCPv6 message). A subset of the
@@ -426,7 +395,6 @@
         byte[] serverDuid = null;
         byte[] clientDuid = null;
         short statusCode = STATUS_SUCCESS;
-        String statusMsg = null;
         boolean rapidCommit = false;
         int solMaxRt = 0;
         PrefixDelegation pd = null;
@@ -487,7 +455,12 @@
                     case DHCP6_STATUS_CODE:
                         expectedLen = optionLen;
                         statusCode = packet.getShort();
-                        statusMsg = readAsciiString(packet, expectedLen - 2, false /* isNullOk */);
+                        // Skip the status message (if any), which is a UTF-8 encoded text string
+                        // suitable for display to the end user, but is not useful for Dhcp6Client
+                        // to decide how to properly handle the status code.
+                        if (optionLen - 2 > 0) {
+                            packet.position(packet.position() + (optionLen - 2));
+                        }
                         break;
                     case DHCP6_SOL_MAX_RT:
                         expectedLen = 4;
@@ -545,7 +518,6 @@
             throw new ParseException("Missing IA_PD option");
         }
         newPacket.mStatusCode = statusCode;
-        newPacket.mStatusMsg = statusMsg;
         newPacket.mRapidCommit = rapidCommit;
         newPacket.mSolMaxRt =
                 (solMaxRt >= 60 && solMaxRt <= 86400)
diff --git a/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt b/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt
index b5e806f..59cf02e 100644
--- a/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt
+++ b/tests/unit/src/android/net/dhcp6/Dhcp6PacketTest.kt
@@ -220,4 +220,62 @@
         assertEquals(423, packet.prefixDelegation.minimalPreferredLifetime)
         assertEquals(43200, packet.prefixDelegation.minimalValidLifetime)
     }
+
+    @Test
+    fun testStatusCodeOptionWithStatusMessage() {
+        val replyHex =
+            // Reply, Transaction ID
+            "07000A47" +
+            // server identifier option(option_len=10)
+            "0002000A0003000186C9B26AED4D" +
+            // client identifier option(option_len=12)
+            "0001000C0003001B02FBBAFFFEB7BC71" +
+            // SOL_MAX_RT (don't support this option yet)
+            "005200040000003c" +
+            // Rapid Commit
+            "000e0000" +
+            // DNS recursive server (don't support this opton yet)
+            "00170010fdfd9ed6795000000000000000000001" +
+            // IA_PD option (t1=t2=0, empty prefix)
+            "0019000c000000000000000000000000" +
+            // Status code option: status code=NoPrefixAvail
+            "000d00150006" +
+            // Status code option: status message="no prefix available"
+            "6e6f2070726566697820617661696c61626c65"
+        val bytes = HexDump.hexStringToByteArray(replyHex)
+        val packet = Dhcp6Packet.decode(bytes, bytes.size)
+        assertTrue(packet is Dhcp6ReplyPacket)
+        assertEquals(0, packet.mPrefixDelegation.iaid)
+        assertEquals(0, packet.mPrefixDelegation.t1)
+        assertEquals(0, packet.mPrefixDelegation.t2)
+        assertEquals(Dhcp6Packet.STATUS_NO_PREFIX_AVAI, packet.mStatusCode)
+    }
+
+    @Test
+    fun testStatusCodeOptionWithoutStatusMessage() {
+        val replyHex =
+            // Reply, Transaction ID
+            "07000A47" +
+            // server identifier option(option_len=10)
+            "0002000A0003000186C9B26AED4D" +
+            // client identifier option(option_len=12)
+            "0001000C0003001B02FBBAFFFEB7BC71" +
+            // SOL_MAX_RT (don't support this option yet)
+            "005200040000003c" +
+            // Rapid Commit
+            "000e0000" +
+            // DNS recursive server (don't support this opton yet)
+            "00170010fdfd9ed6795000000000000000000001" +
+            // IA_PD option (t1=t2=0, empty prefix)
+            "0019000c000000000000000000000000" +
+            // Status code option: status code=NoPrefixAvail
+            "000d00020006"
+        val bytes = HexDump.hexStringToByteArray(replyHex)
+        val packet = Dhcp6Packet.decode(bytes, bytes.size)
+        assertTrue(packet is Dhcp6ReplyPacket)
+        assertEquals(0, packet.mPrefixDelegation.iaid)
+        assertEquals(0, packet.mPrefixDelegation.t1)
+        assertEquals(0, packet.mPrefixDelegation.t2)
+        assertEquals(Dhcp6Packet.STATUS_NO_PREFIX_AVAI, packet.mStatusCode)
+    }
 }