public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
public static final int DHCP_NO_MSG_TYPE = makeErrorCode(DHCP_ERROR, 4);
public static final int DHCP_UNKNOWN_MSG_TYPE = makeErrorCode(DHCP_ERROR, 5);
+ /** {@hide} */
+ public static final int DHCP_NO_COOKIE = makeErrorCode(DHCP_ERROR, 6);
public static final int BUFFER_UNDERFLOW = makeErrorCode(MISC_ERROR, 1);
public static final int RECEIVE_ERROR = makeErrorCode(MISC_ERROR, 2);
+ 64 // skip server host name (64 chars)
+ 128); // skip boot file name (128 chars)
- int dhcpMagicCookie = packet.getInt();
+ // Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211
+ if (packet.remaining() < 4) {
+ throw new ParseException(DhcpErrorEvent.DHCP_NO_COOKIE, "not a DHCP message");
+ }
+ int dhcpMagicCookie = packet.getInt();
if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) {
throw new ParseException(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE,
"Bad magic cookie 0x%08x, should be 0x%08x",
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Random;
import junit.framework.TestCase;
import static android.net.dhcp.DhcpPacket.*;
try {
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
} catch (DhcpPacket.ParseException expected) {
- assertDhcpErrorCodes(DhcpErrorEvent.PARSING_ERROR, expected.errorCode);
+ assertDhcpErrorCodes(DhcpErrorEvent.DHCP_NO_COOKIE, expected.errorCode);
return;
}
fail("Dhcp packet parsing should have failed");
assertEquals(Integer.toHexString(expected), Integer.toHexString(got));
}
+ public void testTruncatedOfferPackets() throws Exception {
+ final byte[] packet = HexDump.hexStringToByteArray(
+ // IP header.
+ "450001518d0600004011144dc0a82b01c0a82bf7" +
+ // UDP header.
+ "00430044013d9ac7" +
+ // BOOTP header.
+ "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+ // MAC address.
+ "30766ff2a90c00000000000000000000" +
+ // Server name.
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ // File.
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ "0000000000000000000000000000000000000000000000000000000000000000" +
+ // Options
+ "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
+ "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff");
+
+ for (int len = 0; len < packet.length; len++) {
+ try {
+ DhcpPacket.decodeFullPacket(packet, len, ENCAP_L3);
+ } catch (ParseException e) {
+ if (e.errorCode == DhcpErrorEvent.PARSING_ERROR) {
+ fail(String.format("bad truncated packet of length %d", len));
+ }
+ }
+ }
+ }
+
+ public void testRandomPackets() throws Exception {
+ final int maxRandomPacketSize = 512;
+ final Random r = new Random();
+ for (int i = 0; i < 10000; i++) {
+ byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
+ r.nextBytes(packet);
+ try {
+ DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
+ } catch (ParseException e) {
+ if (e.errorCode == DhcpErrorEvent.PARSING_ERROR) {
+ fail("bad packet: " + HexDump.toHexString(packet));
+ }
+ }
+ }
+ }
+
private byte[] mtuBytes(int mtu) {
// 0x1a02: option 26, length 2. 0xff: no more options.
if (mtu > Short.MAX_VALUE - Short.MIN_VALUE) {