am eb0bbd45
: Merge changes Id6a0b0de,I5f03b8b2,I62464b92 into mnc-dr-dev
* commit 'eb0bbd45f62fcaff26151b54a7b3ea16bb67e3be': Support DHCP replies with multiple default gateways. Accept DHCP responses from non-67 server source ports Improve logging of DHCP parse errors using exceptions.
This commit is contained in:
@ -46,7 +46,7 @@ class DhcpAckPacket extends DhcpPacket {
|
||||
|
||||
return s + " ACK: your new IP " + mYourIp +
|
||||
", netmask " + mSubnetMask +
|
||||
", gateway " + mGateway + dnsServers +
|
||||
", gateways " + mGateways + dnsServers +
|
||||
", lease time " + mLeaseTime;
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ class DhcpAckPacket extends DhcpPacket {
|
||||
}
|
||||
|
||||
addTlv(buffer, DHCP_SUBNET_MASK, mSubnetMask);
|
||||
addTlv(buffer, DHCP_ROUTER, mGateway);
|
||||
addTlv(buffer, DHCP_ROUTER, mGateways);
|
||||
addTlv(buffer, DHCP_DOMAIN_NAME, mDomainName);
|
||||
addTlv(buffer, DHCP_BROADCAST_ADDRESS, mBroadcastAddress);
|
||||
addTlv(buffer, DHCP_DNS_SERVER, mDnsServers);
|
||||
|
@ -345,21 +345,22 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
||||
public void run() {
|
||||
maybeLog("Receive thread started");
|
||||
while (!stopped) {
|
||||
int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.
|
||||
try {
|
||||
int length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
|
||||
length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
|
||||
DhcpPacket packet = null;
|
||||
packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
|
||||
if (packet != null) {
|
||||
maybeLog("Received packet: " + packet);
|
||||
sendMessage(CMD_RECEIVED_PACKET, packet);
|
||||
} else if (PACKET_DBG) {
|
||||
Log.d(TAG,
|
||||
"Can't parse packet" + HexDump.dumpHexString(mPacket, 0, length));
|
||||
}
|
||||
maybeLog("Received packet: " + packet);
|
||||
sendMessage(CMD_RECEIVED_PACKET, packet);
|
||||
} catch (IOException|ErrnoException e) {
|
||||
if (!stopped) {
|
||||
Log.e(TAG, "Read error", e);
|
||||
}
|
||||
} catch (DhcpPacket.ParseException e) {
|
||||
Log.e(TAG, "Can't parse packet: " + e.getMessage());
|
||||
if (PACKET_DBG) {
|
||||
Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
maybeLog("Receive thread stopped");
|
||||
|
@ -48,7 +48,7 @@ class DhcpOfferPacket extends DhcpPacket {
|
||||
}
|
||||
|
||||
return s + " OFFER, ip " + mYourIp + ", mask " + mSubnetMask +
|
||||
dnsServers + ", gateway " + mGateway +
|
||||
dnsServers + ", gateways " + mGateways +
|
||||
" lease time " + mLeaseTime + ", domain " + mDomainName;
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ class DhcpOfferPacket extends DhcpPacket {
|
||||
}
|
||||
|
||||
addTlv(buffer, DHCP_SUBNET_MASK, mSubnetMask);
|
||||
addTlv(buffer, DHCP_ROUTER, mGateway);
|
||||
addTlv(buffer, DHCP_ROUTER, mGateways);
|
||||
addTlv(buffer, DHCP_DOMAIN_NAME, mDomainName);
|
||||
addTlv(buffer, DHCP_BROADCAST_ADDRESS, mBroadcastAddress);
|
||||
addTlv(buffer, DHCP_DNS_SERVER, mDnsServers);
|
||||
|
@ -113,6 +113,11 @@ abstract class DhcpPacket {
|
||||
*/
|
||||
protected static final int MAX_LENGTH = 1500;
|
||||
|
||||
/**
|
||||
* The magic cookie that identifies this as a DHCP packet instead of BOOTP.
|
||||
*/
|
||||
private static final int DHCP_MAGIC_COOKIE = 0x63825363;
|
||||
|
||||
/**
|
||||
* DHCP Optional Type: DHCP Subnet Mask
|
||||
*/
|
||||
@ -123,7 +128,7 @@ abstract class DhcpPacket {
|
||||
* DHCP Optional Type: DHCP Router
|
||||
*/
|
||||
protected static final byte DHCP_ROUTER = 3;
|
||||
protected Inet4Address mGateway;
|
||||
protected List <Inet4Address> mGateways;
|
||||
|
||||
/**
|
||||
* DHCP Optional Type: DHCP DNS Server
|
||||
@ -403,7 +408,7 @@ abstract class DhcpPacket {
|
||||
(HWADDR_LEN - mClientMac.length) // pad addr to 16 bytes
|
||||
+ 64 // empty server host name (64 bytes)
|
||||
+ 128); // empty boot file name (128 bytes)
|
||||
buf.putInt(0x63825363); // magic number
|
||||
buf.putInt(DHCP_MAGIC_COOKIE); // magic number
|
||||
finishPacket(buf);
|
||||
|
||||
// round up to an even number of octets
|
||||
@ -668,6 +673,20 @@ abstract class DhcpPacket {
|
||||
return new String(bytes, 0, length, StandardCharsets.US_ASCII);
|
||||
}
|
||||
|
||||
private static boolean isPacketToOrFromClient(short udpSrcPort, short udpDstPort) {
|
||||
return (udpSrcPort == DHCP_CLIENT) || (udpDstPort == DHCP_CLIENT);
|
||||
}
|
||||
|
||||
private static boolean isPacketServerToServer(short udpSrcPort, short udpDstPort) {
|
||||
return (udpSrcPort == DHCP_SERVER) && (udpDstPort == DHCP_SERVER);
|
||||
}
|
||||
|
||||
public static class ParseException extends Exception {
|
||||
public ParseException(String msg, Object... args) {
|
||||
super(String.format(msg, args));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a concrete DhcpPacket from the supplied ByteBuffer. The
|
||||
* buffer may have an L2 encapsulation (which is the full EthernetII
|
||||
@ -677,7 +696,7 @@ abstract class DhcpPacket {
|
||||
* A subset of the optional parameters are parsed and are stored
|
||||
* in object fields.
|
||||
*/
|
||||
public static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType)
|
||||
public static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException
|
||||
{
|
||||
// bootp parameters
|
||||
int transactionId;
|
||||
@ -687,8 +706,8 @@ abstract class DhcpPacket {
|
||||
Inet4Address nextIp;
|
||||
Inet4Address relayIp;
|
||||
byte[] clientMac;
|
||||
List<Inet4Address> dnsServers = new ArrayList<Inet4Address>();
|
||||
Inet4Address gateway = null; // aka router
|
||||
List<Inet4Address> dnsServers = new ArrayList<>();
|
||||
List<Inet4Address> gateways = new ArrayList<>(); // aka router
|
||||
Inet4Address serverIdentifier = null;
|
||||
Inet4Address netMask = null;
|
||||
String message = null;
|
||||
@ -720,7 +739,8 @@ abstract class DhcpPacket {
|
||||
// check to see if we need to parse L2, IP, and UDP encaps
|
||||
if (pktType == ENCAP_L2) {
|
||||
if (packet.remaining() < MIN_PACKET_LENGTH_L2) {
|
||||
return null;
|
||||
throw new ParseException("L2 packet too short, %d < %d",
|
||||
packet.remaining(), MIN_PACKET_LENGTH_L2);
|
||||
}
|
||||
|
||||
byte[] l2dst = new byte[6];
|
||||
@ -732,18 +752,20 @@ abstract class DhcpPacket {
|
||||
short l2type = packet.getShort();
|
||||
|
||||
if (l2type != OsConstants.ETH_P_IP)
|
||||
return null;
|
||||
throw new ParseException("Unexpected L2 type 0x%04x, expected 0x%04x",
|
||||
l2type, OsConstants.ETH_P_IP);
|
||||
}
|
||||
|
||||
if (pktType <= ENCAP_L3) {
|
||||
if (packet.remaining() < MIN_PACKET_LENGTH_L3) {
|
||||
return null;
|
||||
throw new ParseException("L3 packet too short, %d < %d",
|
||||
packet.remaining(), MIN_PACKET_LENGTH_L3);
|
||||
}
|
||||
|
||||
byte ipTypeAndLength = packet.get();
|
||||
int ipVersion = (ipTypeAndLength & 0xf0) >> 4;
|
||||
if (ipVersion != 4) {
|
||||
return null;
|
||||
throw new ParseException("Invalid IP version %d", ipVersion);
|
||||
}
|
||||
|
||||
// System.out.println("ipType is " + ipType);
|
||||
@ -759,8 +781,9 @@ abstract class DhcpPacket {
|
||||
ipSrc = readIpAddress(packet);
|
||||
ipDst = readIpAddress(packet);
|
||||
|
||||
if (ipProto != IP_TYPE_UDP) // UDP
|
||||
return null;
|
||||
if (ipProto != IP_TYPE_UDP) {
|
||||
throw new ParseException("Protocol not UDP: %d", ipProto);
|
||||
}
|
||||
|
||||
// Skip options. This cannot cause us to read beyond the end of the buffer because the
|
||||
// IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than
|
||||
@ -776,13 +799,19 @@ abstract class DhcpPacket {
|
||||
short udpLen = packet.getShort();
|
||||
short udpChkSum = packet.getShort();
|
||||
|
||||
if ((udpSrcPort != DHCP_SERVER) && (udpSrcPort != DHCP_CLIENT))
|
||||
// Only accept packets to or from the well-known client port (expressly permitting
|
||||
// packets from ports other than the well-known server port; http://b/24687559), and
|
||||
// server-to-server packets, e.g. for relays.
|
||||
if (!isPacketToOrFromClient(udpSrcPort, udpDstPort) &&
|
||||
!isPacketServerToServer(udpSrcPort, udpDstPort)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length.
|
||||
if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) {
|
||||
return null;
|
||||
throw new ParseException("Invalid type or BOOTP packet too short, %d < %d",
|
||||
packet.remaining(), MIN_PACKET_LENGTH_BOOTP);
|
||||
}
|
||||
|
||||
byte type = packet.get();
|
||||
@ -805,7 +834,7 @@ abstract class DhcpPacket {
|
||||
packet.get(ipv4addr);
|
||||
relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
|
||||
} catch (UnknownHostException ex) {
|
||||
return null;
|
||||
throw new ParseException("Invalid IPv4 address: %s", Arrays.toString(ipv4addr));
|
||||
}
|
||||
|
||||
// Some DHCP servers have been known to announce invalid client hardware address values such
|
||||
@ -828,8 +857,10 @@ abstract class DhcpPacket {
|
||||
|
||||
int dhcpMagicCookie = packet.getInt();
|
||||
|
||||
if (dhcpMagicCookie != 0x63825363)
|
||||
return null;
|
||||
if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) {
|
||||
throw new ParseException("Bad magic cookie 0x%08x, should be 0x%08x", dhcpMagicCookie,
|
||||
DHCP_MAGIC_COOKIE);
|
||||
}
|
||||
|
||||
// parse options
|
||||
boolean notFinishedOptions = true;
|
||||
@ -852,8 +883,9 @@ abstract class DhcpPacket {
|
||||
expectedLen = 4;
|
||||
break;
|
||||
case DHCP_ROUTER:
|
||||
gateway = readIpAddress(packet);
|
||||
expectedLen = 4;
|
||||
for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) {
|
||||
gateways.add(readIpAddress(packet));
|
||||
}
|
||||
break;
|
||||
case DHCP_DNS_SERVER:
|
||||
for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) {
|
||||
@ -937,18 +969,20 @@ abstract class DhcpPacket {
|
||||
}
|
||||
|
||||
if (expectedLen != optionLen) {
|
||||
return null;
|
||||
throw new ParseException("Invalid length %d for option %d, expected %d",
|
||||
optionLen, optionType, expectedLen);
|
||||
}
|
||||
}
|
||||
} catch (BufferUnderflowException e) {
|
||||
return null;
|
||||
throw new ParseException("BufferUnderflowException");
|
||||
}
|
||||
}
|
||||
|
||||
DhcpPacket newPacket;
|
||||
|
||||
switch(dhcpType) {
|
||||
case -1: return null;
|
||||
case (byte) 0xFF:
|
||||
throw new ParseException("No DHCP message type option");
|
||||
case DHCP_MESSAGE_TYPE_DISCOVER:
|
||||
newPacket = new DhcpDiscoverPacket(
|
||||
transactionId, secs, clientMac, broadcast);
|
||||
@ -981,14 +1015,13 @@ abstract class DhcpPacket {
|
||||
clientMac);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unimplemented type: " + dhcpType);
|
||||
return null;
|
||||
throw new ParseException("Unimplemented DHCP type %d", dhcpType);
|
||||
}
|
||||
|
||||
newPacket.mBroadcastAddress = bcAddr;
|
||||
newPacket.mDnsServers = dnsServers;
|
||||
newPacket.mDomainName = domainName;
|
||||
newPacket.mGateway = gateway;
|
||||
newPacket.mGateways = gateways;
|
||||
newPacket.mHostName = hostName;
|
||||
newPacket.mLeaseTime = leaseTime;
|
||||
newPacket.mMessage = message;
|
||||
@ -1009,7 +1042,7 @@ abstract class DhcpPacket {
|
||||
* Parse a packet from an array of bytes, stopping at the given length.
|
||||
*/
|
||||
public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType)
|
||||
{
|
||||
throws ParseException {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN);
|
||||
return decodeFullPacket(buffer, pktType);
|
||||
}
|
||||
@ -1044,7 +1077,11 @@ abstract class DhcpPacket {
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
results.gateway = mGateway;
|
||||
|
||||
if (mGateways.size() > 0) {
|
||||
results.gateway = mGateways.get(0);
|
||||
}
|
||||
|
||||
results.dnsServers.addAll(mDnsServers);
|
||||
results.domains = mDomainName;
|
||||
results.serverAddress = mServerIdentifier;
|
||||
@ -1086,11 +1123,11 @@ abstract class DhcpPacket {
|
||||
public static ByteBuffer buildOfferPacket(int encap, int transactionId,
|
||||
boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr,
|
||||
byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
|
||||
Inet4Address gateway, List<Inet4Address> dnsServers,
|
||||
List<Inet4Address> gateways, List<Inet4Address> dnsServers,
|
||||
Inet4Address dhcpServerIdentifier, String domainName) {
|
||||
DhcpPacket pkt = new DhcpOfferPacket(
|
||||
transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac);
|
||||
pkt.mGateway = gateway;
|
||||
pkt.mGateways = gateways;
|
||||
pkt.mDnsServers = dnsServers;
|
||||
pkt.mLeaseTime = timeout;
|
||||
pkt.mDomainName = domainName;
|
||||
@ -1106,11 +1143,11 @@ abstract class DhcpPacket {
|
||||
public static ByteBuffer buildAckPacket(int encap, int transactionId,
|
||||
boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr,
|
||||
byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
|
||||
Inet4Address gateway, List<Inet4Address> dnsServers,
|
||||
List<Inet4Address> gateways, List<Inet4Address> dnsServers,
|
||||
Inet4Address dhcpServerIdentifier, String domainName) {
|
||||
DhcpPacket pkt = new DhcpAckPacket(
|
||||
transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac);
|
||||
pkt.mGateway = gateway;
|
||||
pkt.mGateways = gateways;
|
||||
pkt.mDnsServers = dnsServers;
|
||||
pkt.mLeaseTime = timeout;
|
||||
pkt.mDomainName = domainName;
|
||||
|
@ -117,7 +117,7 @@ public class DhcpPacketTest extends TestCase {
|
||||
|
||||
private void assertDomainAndVendorInfoParses(
|
||||
String expectedDomain, byte[] domainBytes,
|
||||
String expectedVendorInfo, byte[] vendorInfoBytes) {
|
||||
String expectedVendorInfo, byte[] vendorInfoBytes) throws Exception {
|
||||
ByteBuffer packet = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER)
|
||||
.setDomainBytes(domainBytes)
|
||||
.setVendorInfoBytes(vendorInfoBytes)
|
||||
@ -158,17 +158,25 @@ public class DhcpPacketTest extends TestCase {
|
||||
}
|
||||
|
||||
private void assertLeaseTimeParses(boolean expectValid, Integer rawLeaseTime,
|
||||
long leaseTimeMillis, byte[] leaseTimeBytes) {
|
||||
long leaseTimeMillis, byte[] leaseTimeBytes) throws Exception {
|
||||
TestDhcpPacket testPacket = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER);
|
||||
if (leaseTimeBytes != null) {
|
||||
testPacket.setLeaseTimeBytes(leaseTimeBytes);
|
||||
}
|
||||
ByteBuffer packet = testPacket.build();
|
||||
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
|
||||
DhcpPacket offerPacket = null;
|
||||
|
||||
if (!expectValid) {
|
||||
assertNull(offerPacket);
|
||||
try {
|
||||
offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
|
||||
fail("Invalid packet parsed successfully: " + offerPacket);
|
||||
} catch (ParseException expected) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
|
||||
assertNotNull(offerPacket);
|
||||
assertEquals(rawLeaseTime, offerPacket.mLeaseTime);
|
||||
DhcpResults dhcpResults = offerPacket.toDhcpResults(); // Just check this doesn't crash.
|
||||
assertEquals(leaseTimeMillis, offerPacket.getLeaseTimeMillis());
|
||||
@ -200,14 +208,14 @@ public class DhcpPacketTest extends TestCase {
|
||||
}
|
||||
|
||||
private void checkIpAddress(String expected, Inet4Address clientIp, Inet4Address yourIp,
|
||||
byte[] netmaskBytes) {
|
||||
byte[] netmaskBytes) throws Exception {
|
||||
checkIpAddress(expected, DHCP_MESSAGE_TYPE_OFFER, clientIp, yourIp, netmaskBytes);
|
||||
checkIpAddress(expected, DHCP_MESSAGE_TYPE_ACK, clientIp, yourIp, netmaskBytes);
|
||||
}
|
||||
|
||||
private void checkIpAddress(String expected, byte type,
|
||||
Inet4Address clientIp, Inet4Address yourIp,
|
||||
byte[] netmaskBytes) {
|
||||
byte[] netmaskBytes) throws Exception {
|
||||
ByteBuffer packet = new TestDhcpPacket(type, clientIp, yourIp)
|
||||
.setNetmaskBytes(netmaskBytes)
|
||||
.build();
|
||||
@ -506,4 +514,74 @@ public class DhcpPacketTest extends TestCase {
|
||||
assertDhcpResults("10.32.158.205/20", "10.32.144.1", "148.88.65.52,148.88.65.53",
|
||||
"lancs.ac.uk", "10.32.255.128", null, 7200, false, dhcpResults);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testUdpServerAnySourcePort() throws Exception {
|
||||
final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
|
||||
// Ethernet header.
|
||||
"9cd917000000001c2e0000000800" +
|
||||
// IP header.
|
||||
"45a00148000040003d115087d18194fb0a0f7af2" +
|
||||
// UDP header. TODO: fix invalid checksum (due to MAC address obfuscation).
|
||||
// NOTE: The server source port is not the canonical port 67.
|
||||
"C29F004401341268" +
|
||||
// BOOTP header.
|
||||
"02010600d628ba8200000000000000000a0f7af2000000000a0fc818" +
|
||||
// MAC address.
|
||||
"9cd91700000000000000000000000000" +
|
||||
// Server name.
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
// File.
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
// Options.
|
||||
"6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
|
||||
"d18180060f0777766d2e6564751c040a0fffffff000000"
|
||||
).toCharArray(), false));
|
||||
|
||||
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
|
||||
assertTrue(offerPacket instanceof DhcpOfferPacket);
|
||||
assertEquals("9CD917000000", HexDump.toHexString(offerPacket.getClientMac()));
|
||||
DhcpResults dhcpResults = offerPacket.toDhcpResults();
|
||||
assertDhcpResults("10.15.122.242/16", "10.15.200.23",
|
||||
"209.129.128.3,209.129.148.3,209.129.128.6",
|
||||
"wvm.edu", "10.1.105.252", null, 86400, false, dhcpResults);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testMultipleRouters() throws Exception {
|
||||
final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
|
||||
// Ethernet header.
|
||||
"fc3d93000000" + "081735000000" + "0800" +
|
||||
// IP header.
|
||||
"45000148c2370000ff117ac2c0a8bd02ffffffff" +
|
||||
// UDP header. TODO: fix invalid checksum (due to MAC address obfuscation).
|
||||
"0043004401343beb" +
|
||||
// BOOTP header.
|
||||
"0201060027f518e20000800000000000c0a8bd310000000000000000" +
|
||||
// MAC address.
|
||||
"fc3d9300000000000000000000000000" +
|
||||
// Server name.
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
// File.
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000000000000000000000000000000000000" +
|
||||
// Options.
|
||||
"638253633501023604c0abbd023304000070803a04000038403b04000062700104ffffff00" +
|
||||
"0308c0a8bd01ffffff0006080808080808080404ff000000000000"
|
||||
).toCharArray(), false));
|
||||
|
||||
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
|
||||
assertTrue(offerPacket instanceof DhcpOfferPacket);
|
||||
assertEquals("FC3D93000000", HexDump.toHexString(offerPacket.getClientMac()));
|
||||
DhcpResults dhcpResults = offerPacket.toDhcpResults();
|
||||
assertDhcpResults("192.168.189.49/24", "192.168.189.1", "8.8.8.8,8.8.4.4",
|
||||
null, "192.171.189.2", null, 28800, false, dhcpResults);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user