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)
+ }
}