[CORD-1664] Fix errors when parsing DHCP packets
Change-Id: Ifa9cd3ba04b31f2b7de60fd63dc655978042dbce
diff --git a/utils/misc/src/main/java/org/onlab/packet/DHCP6.java b/utils/misc/src/main/java/org/onlab/packet/DHCP6.java
index fe6debd..924d181 100644
--- a/utils/misc/src/main/java/org/onlab/packet/DHCP6.java
+++ b/utils/misc/src/main/java/org/onlab/packet/DHCP6.java
@@ -39,6 +39,7 @@
* Base on RFC-3315.
*/
public class DHCP6 extends BasePacket {
+ private static final int UNSIGNED_SHORT_MASK = 0xffff;
// size of different field of option
private static final int OPT_CODE_SIZE = 2;
private static final int OPT_LEN_SIZE = 2;
@@ -87,7 +88,7 @@
RELAY_MSG((short) 9), AUTH((short) 11), UNICAST((short) 12),
STATUS_CODE((short) 13), RAPID_COMMIT((short) 14), USER_CLASS((short) 15),
VENDOR_CLASS((short) 16), VENDOR_OPTS((short) 17), INTERFACE_ID((short) 18),
- RECONF_MSG((short) 19), RECONF_ACCEPT((short) 20);
+ RECONF_MSG((short) 19), RECONF_ACCEPT((short) 20), SUBSCRIBER_ID((short) 38);
protected short value;
OptionCode(final short value) {
@@ -183,7 +184,7 @@
}
// peek message type
- dhcp6.msgType = (byte) (0xff & bb.array()[offset]);
+ dhcp6.msgType = bb.array()[offset];
if (RELAY_MSG_TYPES.contains(dhcp6.msgType)) {
bb.get(); // drop message type
dhcp6.hopCount = bb.get();
@@ -202,9 +203,9 @@
while (bb.remaining() >= Dhcp6Option.DEFAULT_LEN) {
// create temporary byte buffer for reading code and length
ByteBuffer optByteBuffer =
- ByteBuffer.wrap(data, bb.position(), length - bb.position());
+ ByteBuffer.wrap(data, bb.position(), bb.limit() - bb.position());
short code = optByteBuffer.getShort();
- short optionLen = (short) (0xffff & optByteBuffer.getShort());
+ int optionLen = UNSIGNED_SHORT_MASK & optByteBuffer.getShort();
if (optByteBuffer.remaining() < optionLen) {
throw new DeserializationException(
"Buffer underflow while reading DHCPv6 option");
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6ClientIdOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6ClientIdOption.java
index 0063bf6..5623e71 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6ClientIdOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6ClientIdOption.java
@@ -17,6 +17,7 @@
package org.onlab.packet.dhcp;
+import com.google.common.base.MoreObjects;
import org.onlab.packet.DHCP6;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Deserializer;
@@ -87,4 +88,13 @@
bb.put(payload.serialize());
return bb.array();
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("code", getCode())
+ .add("length", getLength())
+ .add("duid", getDuid().toString())
+ .toString();
+ }
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Duid.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Duid.java
index e8926ce..df5e4d4 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Duid.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Duid.java
@@ -17,11 +17,14 @@
package org.onlab.packet.dhcp;
+import com.google.common.base.MoreObjects;
import org.onlab.packet.BasePacket;
+import org.onlab.packet.DeserializationException;
import org.onlab.packet.Deserializer;
import org.onlab.packet.IPacket;
import java.nio.ByteBuffer;
+import java.util.Arrays;
public class Dhcp6Duid extends BasePacket {
private static final int DEFAULT_LLT_LEN = 8;
@@ -145,7 +148,11 @@
@Override
public IPacket deserialize(byte[] data, int offset, int length) {
- return null;
+ try {
+ return deserializer().deserialize(data, offset, length);
+ } catch (DeserializationException e) {
+ throw new RuntimeException("Can't deserialize duid due to {}", e);
+ }
}
public static Deserializer<Dhcp6Duid> deserializer() {
@@ -178,4 +185,31 @@
return duid;
};
}
+
+ @Override
+ public String toString() {
+ MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(getClass());
+
+ switch (duidType) {
+ case DUID_LLT:
+ helper.add("type", "DUID_LLT");
+ helper.add("hardwareType", hardwareType);
+ helper.add("duidTime", duidTime);
+ helper.add("linkLayerAddress", Arrays.toString(linkLayerAddress));
+ break;
+ case DUID_EN:
+ helper.add("type", "DUID_EN");
+ helper.add("enterpriseNumber", enterpriseNumber);
+ helper.add("id", Arrays.toString(identifier));
+ break;
+ case DUID_LL:
+ helper.add("type", "DUID_LL");
+ helper.add("hardwareType", hardwareType);
+ helper.add("linkLayerAddress", Arrays.toString(linkLayerAddress));
+ break;
+ default:
+ helper.add("type", "Unknown");
+ }
+ return helper.toString();
+ }
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaNaOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaNaOption.java
index 578a2f9..f71de3a 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaNaOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaNaOption.java
@@ -174,7 +174,8 @@
optionData.length - bb.position());
short code = optByteBuffer.getShort();
short len = optByteBuffer.getShort();
- byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + len];
+ int optLen = UNSIGNED_SHORT_MASK & len;
+ byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + optLen];
bb.get(subOptData);
// TODO: put more sub-options?
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaTaOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaTaOption.java
index e5eb211..e8fdba6 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaTaOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6IaTaOption.java
@@ -119,7 +119,8 @@
optionData.length - bb.position());
short code = optByteBuffer.getShort();
short len = optByteBuffer.getShort();
- byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + len];
+ int optLen = UNSIGNED_SHORT_MASK & len;
+ byte[] subOptData = new byte[Dhcp6Option.DEFAULT_LEN + optLen];
bb.get(subOptData);
// TODO: put more sub-options?
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Option.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Option.java
index aaf3f66..597732d 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Option.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6Option.java
@@ -34,6 +34,7 @@
*/
public class Dhcp6Option extends BasePacket {
public static final int DEFAULT_LEN = 4;
+ protected static final int UNSIGNED_SHORT_MASK = 0xffff;
private short code;
private short length;
// XXX: use "payload" from BasePacket for option data.
@@ -50,8 +51,8 @@
* @param dhcp6Option other DHCPv6 option
*/
public Dhcp6Option(Dhcp6Option dhcp6Option) {
- this.code = (short) (0xffff & dhcp6Option.code);
- this.length = (short) (0xffff & dhcp6Option.length);
+ this.code = dhcp6Option.code;
+ this.length = dhcp6Option.length;
this.payload = dhcp6Option.payload;
this.payload.setParent(this);
}
@@ -127,9 +128,10 @@
"should be at least 4 bytes");
}
ByteBuffer bb = ByteBuffer.wrap(data, offset, len);
- dhcp6Option.code = (short) (0xff & bb.getShort());
- dhcp6Option.length = (short) (0xff & bb.getShort());
- byte[] optData = new byte[dhcp6Option.length];
+ dhcp6Option.code = bb.getShort();
+ dhcp6Option.length = bb.getShort();
+ int optionLen = UNSIGNED_SHORT_MASK & dhcp6Option.length;
+ byte[] optData = new byte[optionLen];
bb.get(optData);
dhcp6Option.setData(optData);
return dhcp6Option;
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6RelayOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6RelayOption.java
index 9707f98..4133049 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6RelayOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/Dhcp6RelayOption.java
@@ -17,6 +17,7 @@
package org.onlab.packet.dhcp;
+import com.google.common.base.MoreObjects;
import org.onlab.packet.DHCP6;
import org.onlab.packet.Deserializer;
import org.onlab.packet.IPacket;
@@ -36,6 +37,11 @@
return (short) payload.serialize().length;
}
+ @Override
+ public byte[] getData() {
+ return this.payload.serialize();
+ }
+
/**
* Default constructor.
*/
@@ -67,4 +73,13 @@
return relayOption;
};
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("code", getCode())
+ .add("length", getLength())
+ .add("data", payload.toString())
+ .toString();
+ }
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpOption.java
index e54d6b1..76f768f 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpOption.java
@@ -34,6 +34,7 @@
public class DhcpOption extends BasePacket {
public static final int OPT_CODE_LEN = 1;
public static final int DEFAULT_LEN = 2;
+ protected static final int UNSIGNED_BYTE_MASK = 0xff;
private final Logger log = getLogger(getClass());
protected byte code;
protected byte length;
@@ -76,7 +77,8 @@
dhcpOption.code = byteBuffer.get();
if (byteBuffer.hasRemaining()) {
dhcpOption.length = byteBuffer.get();
- dhcpOption.data = new byte[dhcpOption.length];
+ int optionLen = UNSIGNED_BYTE_MASK & dhcpOption.length;
+ dhcpOption.data = new byte[optionLen];
byteBuffer.get(dhcpOption.data);
} else {
dhcpOption.length = 0;
diff --git a/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpRelayAgentOption.java b/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpRelayAgentOption.java
index e60df53..adda088 100644
--- a/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpRelayAgentOption.java
+++ b/utils/misc/src/main/java/org/onlab/packet/dhcp/DhcpRelayAgentOption.java
@@ -102,7 +102,8 @@
while (byteBuffer.remaining() >= DEFAULT_LEN) {
byte subOptCode = byteBuffer.get();
byte subOptLen = byteBuffer.get();
- byte[] subOptData = new byte[subOptLen];
+ int subOptLenInt = UNSIGNED_BYTE_MASK & subOptLen;
+ byte[] subOptData = new byte[subOptLenInt];
byteBuffer.get(subOptData);
DhcpOption subOption = new DhcpOption();
diff --git a/utils/misc/src/test/java/org/onlab/packet/DhcpTest.java b/utils/misc/src/test/java/org/onlab/packet/DhcpTest.java
deleted file mode 100644
index 85b1cfa..0000000
--- a/utils/misc/src/test/java/org/onlab/packet/DhcpTest.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2015-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onlab.packet;
-
-import com.google.common.base.Charsets;
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.dhcp.DhcpOption;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Unit tests for DHCP class.
- */
-public class DhcpTest {
-
- // For serialize test
- private static final int TRANSACTION_ID = 1000;
- private static final MacAddress CLIENT1_HOST_MAC = MacAddress.valueOf("1a:1a:1a:1a:1a:1a");
- private static final Ip4Address REQ_IP = Ip4Address.valueOf("10.2.0.2");
- private static final byte[] EXPECTED_SERIALIZED = ByteBuffer.allocate(300)
- .put((byte) 0x01) // op code
- .put((byte) 0x01) // hardware type
- .put((byte) 0x06) // hardware address len
- .put((byte) 0x00) // hops
- .putInt(0x3e8) // transaction id
- .putShort((short) 0x0) // seconds
- .putShort((short) 0x0) // flags
- .putInt(0) // client ip
- .putInt(0) // your ip
- .putInt(0) // server ip
- .putInt(0) // gateway ip
- .put(CLIENT1_HOST_MAC.toBytes()) // client hardware address
- .put(new byte[10]) // pad
- .put(new byte[64]) // server name
- .put(new byte[128]) // boot file name
- .putInt(0x63825363) // magic cookie
- .put(new byte[]{0x35, 0x1, 0x3}) // msg type
- .put(new byte[]{0x32, 0x4, 0xa, 0x2, 0x0, 0x2}) // requested ip
- .put((byte) 0xff) // end of options
- .put(new byte[50]) // pad
- .array();
-
- private Deserializer<DHCP> deserializer = DHCP.deserializer();
-
- private byte opCode = 1;
- private byte hardwareType = 1;
- private byte hardwareAddressLength = Ethernet.DATALAYER_ADDRESS_LENGTH;
- private byte hops = 0;
- private int transactionId = 0x2ed4eb50;
- private short seconds = 0;
- private short flags = 0;
- private int clientIpAddress = 1;
- private int yourIpAddress = 2;
- private int serverIpAddress = 3;
- private int gatewayIpAddress = 4;
- private byte[] clientHardwareAddress = MacAddress.valueOf(500).toBytes();
- private String serverName = "test-server";
- private String bootFileName = "test-file";
-
- private String hostName = "test-host";
- private DhcpOption hostNameOption = new DhcpOption();
-
- private byte[] byteHeader;
-
- @Before
- public void setUp() {
- hostNameOption.setCode((byte) 55);
- hostNameOption.setLength((byte) hostName.length());
- hostNameOption.setData(hostName.getBytes(Charsets.US_ASCII));
-
- // Packet length is the fixed DHCP header plus option length plus an
- // extra byte to indicate 'end of options'.
- ByteBuffer bb = ByteBuffer.allocate(DHCP.MIN_HEADER_LENGTH +
- 2 + hostNameOption.getLength() + 1);
-
- bb.put(opCode);
- bb.put(hardwareType);
- bb.put(hardwareAddressLength);
- bb.put(hops);
- bb.putInt(transactionId);
- bb.putShort(seconds);
- bb.putShort(flags);
- bb.putInt(clientIpAddress);
- bb.putInt(yourIpAddress);
- bb.putInt(serverIpAddress);
- bb.putInt(gatewayIpAddress);
- bb.put(clientHardwareAddress);
-
- // need 16 bytes of zeros to pad out the client hardware address field
- bb.put(new byte[16 - hardwareAddressLength]);
-
- // Put server name and pad out to 64 bytes
- bb.put(serverName.getBytes(Charsets.US_ASCII));
- bb.put(new byte[64 - serverName.length()]);
-
- // Put boot file name and pad out to 128 bytes
- bb.put(bootFileName.getBytes(Charsets.US_ASCII));
- bb.put(new byte[128 - bootFileName.length()]);
-
- // Magic cookie
- bb.put("DHCP".getBytes(Charsets.US_ASCII));
-
- bb.put(hostNameOption.getCode());
- bb.put(hostNameOption.getLength());
- bb.put(hostNameOption.getData());
-
- // End of options marker
- bb.put((DHCP.DHCPOptionCode.OptionCode_END.getValue()));
-
- byteHeader = bb.array();
- }
-
- @Test
- public void testDeserializeBadInput() throws Exception {
- PacketTestUtils.testDeserializeBadInput(deserializer);
- }
-
- @Test
- public void testDeserializeTruncated() throws Exception {
- PacketTestUtils.testDeserializeTruncated(deserializer, byteHeader);
- }
-
- /**
- * Tests deserialize and getters.
- */
- @Test
- public void testDeserialize() throws Exception {
- DHCP dhcp = deserializer.deserialize(byteHeader, 0, byteHeader.length);
-
- assertEquals(opCode, dhcp.opCode);
- assertEquals(hardwareType, dhcp.hardwareType);
- assertEquals(hardwareAddressLength, dhcp.hardwareAddressLength);
- assertEquals(hops, dhcp.hops);
- assertEquals(transactionId, dhcp.transactionId);
- assertEquals(seconds, dhcp.seconds);
- assertEquals(flags, dhcp.flags);
- assertEquals(clientIpAddress, dhcp.clientIPAddress);
- assertEquals(yourIpAddress, dhcp.yourIPAddress);
- assertEquals(serverIpAddress, dhcp.serverIPAddress);
- assertEquals(gatewayIpAddress, dhcp.gatewayIPAddress);
- assertTrue(Arrays.equals(clientHardwareAddress, dhcp.clientHardwareAddress));
-
- assertEquals(serverName, dhcp.serverName);
- assertEquals(bootFileName, dhcp.bootFileName);
- assertEquals(2, dhcp.options.size());
- assertEquals(hostNameOption, dhcp.options.get(0));
- }
-
- /**
- * Tests toString.
- */
- @Test
- public void testToStringDhcp() throws Exception {
- DHCP dhcp = deserializer.deserialize(byteHeader, 0, byteHeader.length);
- String str = dhcp.toString();
-
- assertTrue(StringUtils.contains(str, "opCode=" + opCode));
- assertTrue(StringUtils.contains(str, "hardwareType=" + hardwareType));
- assertTrue(StringUtils.contains(str, "hardwareAddressLength=" + hardwareAddressLength));
- assertTrue(StringUtils.contains(str, "hops=" + hops));
- assertTrue(StringUtils.contains(str, "transactionId=" + transactionId));
- assertTrue(StringUtils.contains(str, "seconds=" + seconds));
- assertTrue(StringUtils.contains(str, "flags=" + flags));
- assertTrue(StringUtils.contains(str, "clientIPAddress=" + clientIpAddress));
- assertTrue(StringUtils.contains(str, "yourIPAddress=" + yourIpAddress));
- assertTrue(StringUtils.contains(str, "serverIPAddress=" + serverIpAddress));
- assertTrue(StringUtils.contains(str, "gatewayIPAddress=" + gatewayIpAddress));
- assertTrue(StringUtils.contains(str, "clientHardwareAddress=" + Arrays.toString(clientHardwareAddress)));
- assertTrue(StringUtils.contains(str, "serverName=" + serverName));
- assertTrue(StringUtils.contains(str, "bootFileName=" + bootFileName));
- // TODO: add option unit test
- }
-
-
-
- @Test
- public void testSerialize() throws Exception {
- DHCP dhcpReply = new DHCP();
- dhcpReply.setOpCode(DHCP.OPCODE_REQUEST);
-
- dhcpReply.setYourIPAddress(0);
- dhcpReply.setServerIPAddress(0);
-
- dhcpReply.setTransactionId(TRANSACTION_ID);
- dhcpReply.setClientHardwareAddress(CLIENT1_HOST_MAC.toBytes());
- dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
- dhcpReply.setHardwareAddressLength((byte) 6);
-
- // DHCP Options.
- DhcpOption option = new DhcpOption();
- List<DhcpOption> optionList = new ArrayList<>();
-
- // DHCP Message Type.
- option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
- option.setLength((byte) 1);
- byte[] optionData = {(byte) DHCP.MsgType.DHCPREQUEST.getValue()};
- option.setData(optionData);
- optionList.add(option);
-
- // DHCP Requested IP.
- option = new DhcpOption();
- option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
- option.setLength((byte) 4);
- optionData = REQ_IP.toOctets();
- option.setData(optionData);
- optionList.add(option);
-
- // End Option.
- option = new DhcpOption();
- option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
- option.setLength((byte) 1);
- optionList.add(option);
-
- dhcpReply.setOptions(optionList);
-
- assertArrayEquals(EXPECTED_SERIALIZED, dhcpReply.serialize());
- }
-}
diff --git a/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6RelayTest.java b/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6RelayTest.java
index 245a100..79b9a46 100644
--- a/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6RelayTest.java
+++ b/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6RelayTest.java
@@ -21,12 +21,15 @@
import com.google.common.collect.Lists;
import com.google.common.io.Resources;
+import org.apache.commons.io.Charsets;
import org.junit.Test;
import org.onlab.packet.DHCP6;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv6;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.UDP;
-import java.util.Collections;
import java.util.List;
import static org.junit.Assert.*;
@@ -42,9 +45,9 @@
private static final int HOP_COUNT = 0;
private static final Ip6Address LINK_ADDRESS = Ip6Address.valueOf("2000::2ff");
- private static final Ip6Address PEER_ADDRESS = Ip6Address.valueOf("fe80::1");
- private static final int XID_1 = 13346301;
- private static final int XID_2 = 9807588;
+ private static final Ip6Address PEER_ADDRESS = Ip6Address.valueOf("fe80::2bb:ff:fe00:1");
+ private static final int XID_1 = 8135067;
+ private static final int XID_2 = 14742082;
private static final int IA_ID = 1;
private static final int T1_CLIENT = 3600;
private static final int T2_CLIENT = 5400;
@@ -54,9 +57,18 @@
private static final int PREFFERRED_LT_SERVER = 375;
private static final int VALID_LT_SERVER = 600;
private static final int PREFFERRED_LT_REQ = 7200;
- private static final int VALID_LT_REQ = 7500;
+ private static final int VALID_LT_REQ = 10800;
+ private static final int VALID_LT_REQ_2 = 7500;
+ private static final MacAddress DOWNSTREAM_MAC = MacAddress.valueOf("4a:c0:c2:78:92:34");
private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:bb:00:00:00:01");
- private static final int CLIENT_DUID_TIME = 0x210016b4;
+ private static final int CLIENT_DUID_TIME = 555636143;
+ private static final MacAddress IPV6_MCAST = MacAddress.valueOf("33:33:00:01:00:03");
+ private static final Ip6Address DOWNSTREAM_LL = Ip6Address.valueOf("fe80::48c0:c2ff:fe78:9234");
+ private static final Ip6Address DHCP6_BRC = Ip6Address.valueOf("ff05::1:3");
+ private static final Ip6Address SERVER_IP = Ip6Address.valueOf("2000::9903");
+ private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:99:66:00:00:01");
+ private static final Ip6Address SERVER_LL = Ip6Address.valueOf("fe80::299:66ff:fe00:1");
+
/**
* Test deserialize relay message with solicit message.
@@ -66,16 +78,22 @@
@Test
public void deserializeSolicit() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(SOLICIT));
- DHCP6 relayMsg = DHCP6.deserializer().deserialize(data, 0, data.length);
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_FORW.value());
assertEquals(relayMsg.getHopCount(), HOP_COUNT);
assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
assertEquals(relayMsg.getIp6PeerAddress(), PEER_ADDRESS);
- assertEquals(relayMsg.getOptions().size(), 1);
+ assertEquals(relayMsg.getOptions().size(), 2);
Dhcp6Option option = relayMsg.getOptions().get(0);
+ assertEquals(option.getCode(), DHCP6.OptionCode.SUBSCRIBER_ID.value());
+ assertEquals(option.getLength(), 10);
+ assertArrayEquals(option.getData(), SERVER_IP.toString().getBytes(Charsets.US_ASCII));
+
+ option = relayMsg.getOptions().get(1);
assertEquals(option.getCode(), DHCP6.OptionCode.RELAY_MSG.value());
- assertEquals(option.getLength(), 56);
+ assertEquals(option.getLength(), 84);
assertTrue(option.getPayload() instanceof DHCP6);
DHCP6 relaiedDhcp6 = (DHCP6) option.getPayload();
@@ -113,13 +131,17 @@
assertTrue(option instanceof Dhcp6IaNaOption);
Dhcp6IaNaOption iaNaOption = (Dhcp6IaNaOption) option;
assertEquals(iaNaOption.getCode(), DHCP6.OptionCode.IA_NA.value());
- assertEquals(iaNaOption.getLength(), 12);
+ assertEquals(iaNaOption.getLength(), 40);
assertEquals(iaNaOption.getIaId(), IA_ID);
assertEquals(iaNaOption.getT1(), T1_CLIENT);
assertEquals(iaNaOption.getT2(), T2_CLIENT);
- assertEquals(iaNaOption.getOptions().size(), 0);
+ assertEquals(iaNaOption.getOptions().size(), 1);
+ Dhcp6IaAddressOption subOption = (Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
+ assertEquals(subOption.getIp6Address(), IA_ADDRESS);
+ assertEquals(subOption.getPreferredLifetime(), PREFFERRED_LT_REQ);
+ assertEquals(subOption.getValidLifetime(), VALID_LT_REQ);
- assertArrayEquals(data, relayMsg.serialize());
+ assertArrayEquals(data, eth.serialize());
}
/**
@@ -169,17 +191,47 @@
iaNaOption.setIaId(IA_ID);
iaNaOption.setT1(T1_CLIENT);
iaNaOption.setT2(T2_CLIENT);
- iaNaOption.setOptions(Collections.emptyList());
+ Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
+ iaAddressOption.setIp6Address(IA_ADDRESS);
+ iaAddressOption.setPreferredLifetime(PREFFERRED_LT_REQ);
+ iaAddressOption.setValidLifetime(VALID_LT_REQ);
+ iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
options.add(iaNaOption);
relaiedDhcp6.setOptions(options);
-
Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
relayOption.setPayload(relaiedDhcp6);
- relayMsg.setOptions(ImmutableList.of(relayOption));
+ Dhcp6Option subscriberId = new Dhcp6Option();
+ subscriberId.setCode(DHCP6.OptionCode.SUBSCRIBER_ID.value());
+ subscriberId.setLength((short) 10);
+ subscriberId.setData(SERVER_IP.toString().getBytes(Charsets.US_ASCII));
+
+ relayMsg.setOptions(ImmutableList.of(subscriberId, relayOption));
+
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setPayload(relayMsg);
+ udp.setChecksum((short) 0x9a99);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 32);
+ ipv6.setSourceAddress(DOWNSTREAM_LL.toOctets());
+ ipv6.setDestinationAddress(DHCP6_BRC.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000cbf64);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(IPV6_MCAST);
+ eth.setSourceMACAddress(DOWNSTREAM_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
+
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(SOLICIT)),
- relayMsg.serialize());
+ eth.serialize());
}
/**
@@ -190,8 +242,8 @@
@Test
public void deserializeAdvertise() throws Exception {
byte[] data = Resources.toByteArray(getClass().getResource(ADVERTISE));
- DHCP6 relayMsg = DHCP6.deserializer().deserialize(data, 0, data.length);
-
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_REPL.value());
assertEquals(relayMsg.getHopCount(), HOP_COUNT);
assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
@@ -243,10 +295,13 @@
option = relaiedDhcp6.getOptions().get(2);
assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
assertEquals(option.getLength(), 14);
- assertArrayEquals(option.getData(),
- new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
-
- assertArrayEquals(data, relayMsg.serialize());
+ Dhcp6Duid serverDuid =
+ Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
+ assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
+ assertEquals(serverDuid.getDuidTime(), 0x211e5340);
+ assertEquals(serverDuid.getHardwareType(), 1);
+ assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
+ assertArrayEquals(data, eth.serialize());
}
/**
@@ -295,7 +350,12 @@
Dhcp6Option option = new Dhcp6Option();
option.setCode(DHCP6.OptionCode.SERVERID.value());
option.setLength((short) 14);
- option.setData(new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid = new Dhcp6Duid();
+ serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
+ serverDuid.setHardwareType((short) 1);
+ serverDuid.setDuidTime(0x211e5340);
+ option.setData(serverDuid.serialize());
options.add(option);
relaiedDhcp6.setOptions(options);
@@ -305,8 +365,28 @@
relayMsg.setOptions(ImmutableList.of(relayOption));
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setPayload(relayMsg);
+ udp.setChecksum((short) 0x0000019d);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 64);
+ ipv6.setSourceAddress(SERVER_LL.toOctets());
+ ipv6.setDestinationAddress(DOWNSTREAM_LL.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000c72ef);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(DOWNSTREAM_MAC);
+ eth.setSourceMACAddress(SERVER_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(ADVERTISE)),
- relayMsg.serialize());
+ eth.serialize());
}
/**
@@ -317,15 +397,20 @@
@Test
public void deserializeRequest() throws Exception {
byte[] data = Resources.toByteArray(getClass().getResource(REQUEST));
- DHCP6 relayMsg = DHCP6.deserializer().deserialize(data, 0, data.length);
-
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_FORW.value());
assertEquals(relayMsg.getHopCount(), HOP_COUNT);
assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
assertEquals(relayMsg.getIp6PeerAddress(), PEER_ADDRESS);
- assertEquals(relayMsg.getOptions().size(), 1);
+ assertEquals(relayMsg.getOptions().size(), 2);
Dhcp6Option option = relayMsg.getOptions().get(0);
+ assertEquals(option.getCode(), DHCP6.OptionCode.SUBSCRIBER_ID.value());
+ assertEquals(option.getLength(), 10);
+ assertArrayEquals(option.getData(), SERVER_IP.toString().getBytes(Charsets.US_ASCII));
+
+ option = relayMsg.getOptions().get(1);
assertEquals(option.getCode(), DHCP6.OptionCode.RELAY_MSG.value());
assertEquals(option.getLength(), 102);
assertTrue(option.getPayload() instanceof DHCP6);
@@ -350,8 +435,12 @@
option = relaiedDhcp6.getOptions().get(1);
assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
assertEquals(option.getLength(), 14);
- assertArrayEquals(option.getData(),
- new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid =
+ Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
+ assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
+ assertEquals(serverDuid.getDuidTime(), 0x211e5340);
+ assertEquals(serverDuid.getHardwareType(), 1);
+ assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
// Option Request
option = relaiedDhcp6.getOptions().get(2);
@@ -363,8 +452,7 @@
option = relaiedDhcp6.getOptions().get(3);
assertEquals(option.getCode(), DHCP6.OptionCode.ELAPSED_TIME.value());
assertEquals(option.getLength(), 2);
- assertArrayEquals(option.getData(),
- new byte[]{0, 0});
+ assertArrayEquals(option.getData(), new byte[]{0, 0});
// IA NA
option = relaiedDhcp6.getOptions().get(4);
@@ -383,10 +471,10 @@
(Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
assertEquals(iaAddressOption.getIp6Address(), IA_ADDRESS);
assertEquals(iaAddressOption.getPreferredLifetime(), PREFFERRED_LT_REQ);
- assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_REQ);
+ assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_REQ_2);
assertNull(iaAddressOption.getOptions());
- assertArrayEquals(data, relayMsg.serialize());
+ assertArrayEquals(data, eth.serialize());
}
/**
@@ -421,7 +509,12 @@
Dhcp6Option option = new Dhcp6Option();
option.setCode(DHCP6.OptionCode.SERVERID.value());
option.setLength((short) 14);
- option.setData(new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid = new Dhcp6Duid();
+ serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
+ serverDuid.setHardwareType((short) 1);
+ serverDuid.setDuidTime(0x211e5340);
+ option.setData(serverDuid.serialize());
options.add(option);
// Option request
@@ -442,7 +535,7 @@
Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
iaAddressOption.setIp6Address(IA_ADDRESS);
iaAddressOption.setPreferredLifetime(PREFFERRED_LT_REQ);
- iaAddressOption.setValidLifetime(VALID_LT_REQ);
+ iaAddressOption.setValidLifetime(VALID_LT_REQ_2);
// IA NA
Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
@@ -454,13 +547,39 @@
relaiedDhcp6.setOptions(options);
+ Dhcp6Option subscriberId = new Dhcp6Option();
+ subscriberId.setCode(DHCP6.OptionCode.SUBSCRIBER_ID.value());
+ subscriberId.setLength((short) 10);
+ subscriberId.setData(SERVER_IP.toString().getBytes(Charsets.US_ASCII));
+
Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
relayOption.setPayload(relaiedDhcp6);
- relayMsg.setOptions(ImmutableList.of(relayOption));
+ relayMsg.setOptions(ImmutableList.of(subscriberId, relayOption));
+
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setPayload(relayMsg);
+ udp.setChecksum((short) 0x9aab);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 32);
+ ipv6.setSourceAddress(DOWNSTREAM_LL.toOctets());
+ ipv6.setDestinationAddress(DHCP6_BRC.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000cbf64);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(IPV6_MCAST);
+ eth.setSourceMACAddress(DOWNSTREAM_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(REQUEST)),
- relayMsg.serialize());
+ eth.serialize());
}
/**
@@ -471,8 +590,8 @@
@Test
public void deserializeReply() throws Exception {
byte[] data = Resources.toByteArray(getClass().getResource(REPLY));
- DHCP6 relayMsg = DHCP6.deserializer().deserialize(data, 0, data.length);
-
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_REPL.value());
assertEquals(relayMsg.getHopCount(), HOP_COUNT);
assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
@@ -524,10 +643,14 @@
option = relaiedDhcp6.getOptions().get(2);
assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
assertEquals(option.getLength(), 14);
- assertArrayEquals(option.getData(),
- new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid =
+ Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
+ assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
+ assertEquals(serverDuid.getDuidTime(), 0x211e5340);
+ assertEquals(serverDuid.getHardwareType(), 1);
+ assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
- assertArrayEquals(data, relayMsg.serialize());
+ assertArrayEquals(data, eth.serialize());
}
@Test
@@ -571,7 +694,12 @@
Dhcp6Option option = new Dhcp6Option();
option.setCode(DHCP6.OptionCode.SERVERID.value());
option.setLength((short) 14);
- option.setData(new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid = new Dhcp6Duid();
+ serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
+ serverDuid.setHardwareType((short) 1);
+ serverDuid.setDuidTime(0x211e5340);
+ option.setData(serverDuid.serialize());
options.add(option);
relaiedDhcp6.setOptions(options);
@@ -581,7 +709,28 @@
relayMsg.setOptions(ImmutableList.of(relayOption));
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setPayload(relayMsg);
+ udp.setChecksum((short) 0x019d);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 64);
+ ipv6.setSourceAddress(SERVER_LL.toOctets());
+ ipv6.setDestinationAddress(DOWNSTREAM_LL.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000c72ef);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(DOWNSTREAM_MAC);
+ eth.setSourceMACAddress(SERVER_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
+
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(REPLY)),
- relayMsg.serialize());
+ eth.serialize());
}
}
diff --git a/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6Test.java b/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6Test.java
index ecfbd4c..795c8aa 100644
--- a/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6Test.java
+++ b/utils/misc/src/test/java/org/onlab/packet/dhcp/Dhcp6Test.java
@@ -23,12 +23,14 @@
import org.junit.Test;
import org.onlab.packet.DHCP6;
import org.onlab.packet.Deserializer;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv6;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.PacketTestUtils;
+import org.onlab.packet.UDP;
import java.nio.ByteBuffer;
-import java.util.Collections;
import java.util.List;
import static org.junit.Assert.*;
@@ -40,8 +42,8 @@
private static final String REQUEST = "dhcp6_request.bin";
private static final String REPLY = "dhcp6_reply.bin";
- private static final int XID_1 = 13346301;
- private static final int XID_2 = 9807588;
+ private static final int XID_1 = 13938541;
+ private static final int XID_2 = 11359587;
private static final int IA_ID = 1;
private static final int T1_CLIENT = 3600;
private static final int T2_CLIENT = 5400;
@@ -51,9 +53,16 @@
private static final int PREFFERRED_LT_SERVER = 375;
private static final int VALID_LT_SERVER = 600;
private static final int PREFFERRED_LT_REQ = 7200;
- private static final int VALID_LT_REQ = 7500;
+ private static final int VALID_LT_REQ = 10800;
+ private static final int VALID_LT_REQ_2 = 7500;
private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:bb:00:00:00:01");
- private static final int CLIENT_DUID_TIME = 0x210016b4;
+ private static final int CLIENT_DUID_TIME = 555636143;
+ private static final MacAddress IPV6_MCAST = MacAddress.valueOf("33:33:00:01:00:02");
+ private static final Ip6Address CLIENT_LL = Ip6Address.valueOf("fe80::2bb:ff:fe00:1");
+ private static final Ip6Address DHCP6_BRC = Ip6Address.valueOf("ff02::1:2");
+ private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:99:66:00:00:01");
+ private static final MacAddress UPSTREAM_MAC = MacAddress.valueOf("de:15:19:e4:d7:35");
+ private static final Ip6Address UPSTREAM_LL = Ip6Address.valueOf("fe80::dc15:19ff:fee4:d735");
private Deserializer<DHCP6> deserializer = DHCP6.deserializer();
@@ -83,7 +92,8 @@
@Test
public void testDeserializeSolicit() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(SOLICIT));
- DHCP6 dhcp6 = DHCP6.deserializer().deserialize(data, 0, data.length);
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 dhcp6 = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(dhcp6.getMsgType(), DHCP6.MsgType.SOLICIT.value());
assertEquals(dhcp6.getTransactionId(), XID_1);
assertEquals(dhcp6.getOptions().size(), 4);
@@ -118,13 +128,17 @@
assertTrue(option instanceof Dhcp6IaNaOption);
Dhcp6IaNaOption iaNaOption = (Dhcp6IaNaOption) option;
assertEquals(iaNaOption.getCode(), DHCP6.OptionCode.IA_NA.value());
- assertEquals(iaNaOption.getLength(), 12);
+ assertEquals(iaNaOption.getLength(), 40);
assertEquals(iaNaOption.getIaId(), IA_ID);
assertEquals(iaNaOption.getT1(), T1_CLIENT);
assertEquals(iaNaOption.getT2(), T2_CLIENT);
- assertEquals(iaNaOption.getOptions().size(), 0);
+ assertEquals(iaNaOption.getOptions().size(), 1);
+ Dhcp6IaAddressOption subOption = (Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
+ assertEquals(subOption.getIp6Address(), IA_ADDRESS);
+ assertEquals(subOption.getPreferredLifetime(), PREFFERRED_LT_REQ);
+ assertEquals(subOption.getValidLifetime(), VALID_LT_REQ);
- assertArrayEquals(data, dhcp6.serialize());
+ assertArrayEquals(data, eth.serialize());
}
/**
@@ -168,16 +182,40 @@
iaNaOption.setIaId(IA_ID);
iaNaOption.setT1(T1_CLIENT);
iaNaOption.setT2(T2_CLIENT);
- iaNaOption.setOptions(Collections.emptyList());
+ Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
+ iaAddressOption.setIp6Address(IA_ADDRESS);
+ iaAddressOption.setPreferredLifetime(PREFFERRED_LT_REQ);
+ iaAddressOption.setValidLifetime(VALID_LT_REQ);
+ iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
options.add(iaNaOption);
dhcp6.setOptions(options);
-
Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
relayOption.setPayload(dhcp6);
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setPayload(dhcp6);
+ udp.setChecksum((short) 0xffaf);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 1);
+ ipv6.setSourceAddress(CLIENT_LL.toOctets());
+ ipv6.setDestinationAddress(DHCP6_BRC.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000322ad);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(IPV6_MCAST);
+ eth.setSourceMACAddress(CLIENT_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
+
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(SOLICIT)),
- dhcp6.serialize());
+ eth.serialize());
}
/**
@@ -188,9 +226,8 @@
@Test
public void deserializeAdvertise() throws Exception {
byte[] data = Resources.toByteArray(getClass().getResource(ADVERTISE));
-
-
- DHCP6 dhcp6 = DHCP6.deserializer().deserialize(data, 0, data.length);
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 dhcp6 = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(dhcp6.getMsgType(), DHCP6.MsgType.ADVERTISE.value());
assertEquals(dhcp6.getTransactionId(), XID_1);
assertEquals(dhcp6.getOptions().size(), 3);
@@ -230,10 +267,13 @@
option = dhcp6.getOptions().get(2);
assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
assertEquals(option.getLength(), 14);
- assertArrayEquals(option.getData(),
- new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
-
- assertArrayEquals(data, dhcp6.serialize());
+ Dhcp6Duid serverDuid =
+ Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
+ assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
+ assertEquals(serverDuid.getDuidTime(), 0x211e5340);
+ assertEquals(serverDuid.getHardwareType(), 1);
+ assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
+ assertArrayEquals(data, eth.serialize());
}
/**
@@ -276,7 +316,12 @@
Dhcp6Option option = new Dhcp6Option();
option.setCode(DHCP6.OptionCode.SERVERID.value());
option.setLength((short) 14);
- option.setData(new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid = new Dhcp6Duid();
+ serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
+ serverDuid.setHardwareType((short) 1);
+ serverDuid.setDuidTime(0x211e5340);
+ option.setData(serverDuid.serialize());
options.add(option);
dhcp6.setOptions(options);
@@ -284,8 +329,29 @@
Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
relayOption.setPayload(dhcp6);
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_CLIENT_PORT);
+ udp.setPayload(dhcp6);
+ udp.setChecksum((short) 0xcb5a);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 64);
+ ipv6.setSourceAddress(UPSTREAM_LL.toOctets());
+ ipv6.setDestinationAddress(CLIENT_LL.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000d935f);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(CLIENT_MAC);
+ eth.setSourceMACAddress(UPSTREAM_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
+
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(ADVERTISE)),
- dhcp6.serialize());
+ eth.serialize());
}
/**
@@ -296,7 +362,8 @@
@Test
public void deserializeRequest() throws Exception {
byte[] data = Resources.toByteArray(getClass().getResource(REQUEST));
- DHCP6 dhcp6 = DHCP6.deserializer().deserialize(data, 0, data.length);
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 dhcp6 = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(dhcp6.getMsgType(), DHCP6.MsgType.REQUEST.value());
assertEquals(dhcp6.getTransactionId(), XID_2);
assertEquals(dhcp6.getOptions().size(), 5);
@@ -316,8 +383,12 @@
option = dhcp6.getOptions().get(1);
assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
assertEquals(option.getLength(), 14);
- assertArrayEquals(option.getData(),
- new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid =
+ Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
+ assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
+ assertEquals(serverDuid.getDuidTime(), 0x211e5340);
+ assertEquals(serverDuid.getHardwareType(), 1);
+ assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
// Option Request
option = dhcp6.getOptions().get(2);
@@ -349,10 +420,10 @@
(Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
assertEquals(iaAddressOption.getIp6Address(), IA_ADDRESS);
assertEquals(iaAddressOption.getPreferredLifetime(), PREFFERRED_LT_REQ);
- assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_REQ);
+ assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_REQ_2);
assertNull(iaAddressOption.getOptions());
- assertArrayEquals(data, dhcp6.serialize());
+ assertArrayEquals(data, eth.serialize());
}
/**
@@ -381,7 +452,12 @@
Dhcp6Option option = new Dhcp6Option();
option.setCode(DHCP6.OptionCode.SERVERID.value());
option.setLength((short) 14);
- option.setData(new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid = new Dhcp6Duid();
+ serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
+ serverDuid.setHardwareType((short) 1);
+ serverDuid.setDuidTime(0x211e5340);
+ option.setData(serverDuid.serialize());
options.add(option);
// Option request
@@ -402,7 +478,7 @@
Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
iaAddressOption.setIp6Address(IA_ADDRESS);
iaAddressOption.setPreferredLifetime(PREFFERRED_LT_REQ);
- iaAddressOption.setValidLifetime(VALID_LT_REQ);
+ iaAddressOption.setValidLifetime(VALID_LT_REQ_2);
// IA NA
Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
@@ -417,8 +493,29 @@
Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
relayOption.setPayload(dhcp6);
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setPayload(dhcp6);
+ udp.setChecksum((short) 0xffc1);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 1);
+ ipv6.setSourceAddress(CLIENT_LL.toOctets());
+ ipv6.setDestinationAddress(DHCP6_BRC.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000322ad);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(IPV6_MCAST);
+ eth.setSourceMACAddress(CLIENT_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
+
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(REQUEST)),
- dhcp6.serialize());
+ eth.serialize());
}
/**
@@ -429,8 +526,8 @@
@Test
public void deserializeReply() throws Exception {
byte[] data = Resources.toByteArray(getClass().getResource(REPLY));
-
- DHCP6 dhcp6 = DHCP6.deserializer().deserialize(data, 0, data.length);
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP6 dhcp6 = (DHCP6) eth.getPayload().getPayload().getPayload();
assertEquals(dhcp6.getMsgType(), DHCP6.MsgType.REPLY.value());
assertEquals(dhcp6.getTransactionId(), XID_2);
assertEquals(dhcp6.getOptions().size(), 3);
@@ -470,10 +567,14 @@
option = dhcp6.getOptions().get(2);
assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
assertEquals(option.getLength(), 14);
- assertArrayEquals(option.getData(),
- new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid =
+ Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
+ assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
+ assertEquals(serverDuid.getDuidTime(), 0x211e5340);
+ assertEquals(serverDuid.getHardwareType(), 1);
+ assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
- assertArrayEquals(data, dhcp6.serialize());
+ assertArrayEquals(data, eth.serialize());
}
@Test
@@ -511,7 +612,12 @@
Dhcp6Option option = new Dhcp6Option();
option.setCode(DHCP6.OptionCode.SERVERID.value());
option.setLength((short) 14);
- option.setData(new byte[]{0, 1, 0, 1, 32, -1, -8, -17, 0, -103, 102, 0, 0, 1});
+ Dhcp6Duid serverDuid = new Dhcp6Duid();
+ serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
+ serverDuid.setHardwareType((short) 1);
+ serverDuid.setDuidTime(0x211e5340);
+ option.setData(serverDuid.serialize());
options.add(option);
dhcp6.setOptions(options);
@@ -519,7 +625,28 @@
Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
relayOption.setPayload(dhcp6);
+ UDP udp = new UDP();
+ udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_V6_CLIENT_PORT);
+ udp.setPayload(dhcp6);
+ udp.setChecksum((short) 0xcb5a);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setHopLimit((byte) 64);
+ ipv6.setSourceAddress(UPSTREAM_LL.toOctets());
+ ipv6.setDestinationAddress(CLIENT_LL.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
+ ipv6.setTrafficClass((byte) 0);
+ ipv6.setFlowLabel(0x000d935f);
+ ipv6.setPayload(udp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(CLIENT_MAC);
+ eth.setSourceMACAddress(UPSTREAM_MAC);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setPayload(ipv6);
+
assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(REPLY)),
- dhcp6.serialize());
+ eth.serialize());
}
}
diff --git a/utils/misc/src/test/java/org/onlab/packet/dhcp/DhcpTest.java b/utils/misc/src/test/java/org/onlab/packet/dhcp/DhcpTest.java
new file mode 100644
index 0000000..c2bbeb6
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/dhcp/DhcpTest.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.packet.dhcp;
+
+import com.google.common.io.Resources;
+import org.apache.commons.io.Charsets;
+import org.apache.commons.lang.ArrayUtils;
+import org.junit.Test;
+import org.onlab.packet.DHCP;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.PacketTestUtils;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.*;
+
+/**
+ * Unit tests for DHCP class.
+ */
+public class DhcpTest {
+ private static final String DISCOVER = "dhcp_discover.bin";
+ private static final String OFFER = "dhcp_offer.bin";
+ private static final String REQUEST = "dhcp_request.bin";
+ private static final String ACK = "dhcp_ack.bin";
+ private static final String LONG_OPT = "dhcp_long_opt.bin";
+ private static final String EMPTY = "";
+ private static final byte HW_TYPE = 1;
+ private static final byte HW_ADDR_LEN = 6;
+ private static final byte HOPS = 1;
+ private static final int XID = 0x8f5a186c;
+ private static final short SECS = 0;
+ private static final short FLAGS = 0;
+ private static final int NO_IP = 0;
+ private static final Ip4Address GW_IP = Ip4Address.valueOf("10.0.4.254");
+ private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.99.3");
+ private static final MacAddress CLIENT_HW_ADDR = MacAddress.valueOf("00:aa:00:00:00:01");
+ private static final Ip4Address CLIENT_IP = Ip4Address.valueOf("10.0.4.1");
+ private static final Ip4Address DNS_1 = Ip4Address.valueOf("8.8.8.8");
+ private static final Ip4Address DNS_2 = Ip4Address.valueOf("8.8.4.4");
+ private static final Ip4Address SUBNET_MASK = Ip4Address.valueOf("255.255.255.0");
+ private static final String HOSTNAME = "charlie-n";
+ private static final String CIRCUIT_ID = "relay-eth0";
+ private static final String DOMAIN_NAME = "trellis.local";
+
+ @Test
+ public void testDeserializeBadInput() throws Exception {
+ PacketTestUtils.testDeserializeBadInput(DHCP.deserializer());
+ }
+
+ @Test
+ public void testDeserializeTruncated() throws Exception {
+ byte[] byteHeader = ByteBuffer.allocate(241)
+ .put((byte) 0x01) // op code
+ .put((byte) 0x01) // hardware type
+ .put((byte) 0x06) // hardware address len
+ .put((byte) 0x00) // hops
+ .putInt(0x3e8) // transaction id
+ .putShort((short) 0x0) // seconds
+ .putShort((short) 0x0) // flags
+ .putInt(0) // client ip
+ .putInt(0) // your ip
+ .putInt(0) // server ip
+ .putInt(0) // gateway ip
+ .put(MacAddress.valueOf("1a:1a:1a:1a:1a:1a").toBytes()) // client hardware address
+ .put(new byte[10]) // pad
+ .put(new byte[64]) // server name
+ .put(new byte[128]) // boot file name
+ .putInt(0x63825363) // magic cookie
+ .put((byte) 0xff) // end of options
+ .array();
+ PacketTestUtils.testDeserializeTruncated(DHCP.deserializer(), byteHeader);
+ }
+
+ /**
+ * Tests deserialize discover packet.
+ */
+ @Test
+ public void testDeserializeDiscover() throws Exception {
+ byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(DISCOVER));
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
+
+ assertEquals(DHCP.OPCODE_REQUEST, dhcp.getOpCode());
+ assertEquals(HW_TYPE, dhcp.getHardwareType());
+ assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
+ assertEquals(HOPS, dhcp.getHops());
+ assertEquals(XID, dhcp.getTransactionId());
+ assertEquals(SECS, dhcp.getSeconds());
+ assertEquals(FLAGS, dhcp.getFlags());
+ assertEquals(NO_IP, dhcp.getClientIPAddress());
+ assertEquals(NO_IP, dhcp.getYourIPAddress());
+ assertEquals(NO_IP, dhcp.getServerIPAddress());
+ assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
+ assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
+ assertEquals(EMPTY, dhcp.getServerName());
+ assertEquals(EMPTY, dhcp.getBootFileName());
+ assertEquals(6, dhcp.getOptions().size());
+
+ DhcpOption option = dhcp.getOptions().get(0);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
+ assertEquals(1, option.length);
+ assertEquals(DHCP.MsgType.DHCPDISCOVER.getValue(), (int) option.getData()[0]);
+
+ option = dhcp.getOptions().get(1);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(CLIENT_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(2);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_HostName.getValue(), option.code);
+ assertEquals(9, option.length);
+ assertArrayEquals(HOSTNAME.getBytes(Charsets.US_ASCII), option.getData());
+
+ option = dhcp.getOptions().get(3);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedParameters.getValue(),
+ option.code);
+ assertEquals(13, option.length);
+ assertArrayEquals(new byte[]{1, 28, 2, 3, 15, 6, 119, 12, 44, 47, 26, 121, 42},
+ option.getData());
+
+ option = dhcp.getOptions().get(4);
+ assertTrue(option instanceof DhcpRelayAgentOption);
+ DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
+ assertEquals(12, relayAgentOption.length);
+ DhcpOption subOption = relayAgentOption
+ .getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
+ assertEquals(10, subOption.getLength());
+ assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
+
+ option = dhcp.getOptions().get(5);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
+ assertEquals(0, option.length);
+ }
+
+ /**
+ * Tests deserialize discover packet.
+ */
+ @Test
+ public void testDeserializeOffer() throws Exception {
+ byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(OFFER));
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
+
+ assertEquals(DHCP.OPCODE_REPLY, dhcp.getOpCode());
+ assertEquals(HW_TYPE, dhcp.getHardwareType());
+ assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
+ assertEquals(HOPS, dhcp.getHops());
+ assertEquals(XID, dhcp.getTransactionId());
+ assertEquals(SECS, dhcp.getSeconds());
+ assertEquals(FLAGS, dhcp.getFlags());
+ assertEquals(NO_IP, dhcp.getClientIPAddress());
+ assertEquals(CLIENT_IP.toInt(), dhcp.getYourIPAddress());
+ assertEquals(SERVER_IP.toInt(), dhcp.getServerIPAddress());
+ assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
+ assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
+ assertEquals(EMPTY, dhcp.getServerName());
+ assertEquals(EMPTY, dhcp.getBootFileName());
+ assertEquals(9, dhcp.getOptions().size());
+
+ DhcpOption option = dhcp.getOptions().get(0);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
+ assertEquals(1, option.length);
+ assertEquals(DHCP.MsgType.DHCPOFFER.getValue(), (int) option.getData()[0]);
+
+ option = dhcp.getOptions().get(1);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(SERVER_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(2);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(new byte[]{0, 0, 2, 88}, option.getData());
+
+ option = dhcp.getOptions().get(3);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_SubnetMask.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(SUBNET_MASK.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(4);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(GW_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(5);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainName.getValue(), option.code);
+ assertEquals(13, option.length);
+ assertArrayEquals(DOMAIN_NAME.getBytes(Charsets.US_ASCII), option.getData());
+
+ option = dhcp.getOptions().get(6);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue(), option.code);
+ assertEquals(8, option.length);
+ assertArrayEquals(ArrayUtils.addAll(DNS_1.toOctets(), DNS_2.toOctets()),
+ option.getData());
+
+ option = dhcp.getOptions().get(7);
+ assertTrue(option instanceof DhcpRelayAgentOption);
+ DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
+ assertEquals(12, relayAgentOption.length);
+ DhcpOption subOption = relayAgentOption
+ .getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
+ assertEquals(10, subOption.getLength());
+ assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
+
+ option = dhcp.getOptions().get(8);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
+ assertEquals(0, option.length);
+ }
+
+ /**
+ * Tests deserialize discover packet.
+ */
+ @Test
+ public void testDeserializeRequest() throws Exception {
+ byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(REQUEST));
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
+
+ assertEquals(DHCP.OPCODE_REQUEST, dhcp.getOpCode());
+ assertEquals(HW_TYPE, dhcp.getHardwareType());
+ assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
+ assertEquals(HOPS, dhcp.getHops());
+ assertEquals(XID, dhcp.getTransactionId());
+ assertEquals(SECS, dhcp.getSeconds());
+ assertEquals(FLAGS, dhcp.getFlags());
+ assertEquals(NO_IP, dhcp.getClientIPAddress());
+ assertEquals(NO_IP, dhcp.getYourIPAddress());
+ assertEquals(NO_IP, dhcp.getServerIPAddress());
+ assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
+ assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
+ assertEquals(EMPTY, dhcp.getServerName());
+ assertEquals(EMPTY, dhcp.getBootFileName());
+ assertEquals(7, dhcp.getOptions().size());
+
+ DhcpOption option = dhcp.getOptions().get(0);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
+ assertEquals(1, option.length);
+ assertEquals(DHCP.MsgType.DHCPREQUEST.getValue(), (int) option.getData()[0]);
+
+ option = dhcp.getOptions().get(1);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(SERVER_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(2);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(CLIENT_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(3);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_HostName.getValue(), option.code);
+ assertEquals(9, option.length);
+ assertArrayEquals(HOSTNAME.getBytes(Charsets.US_ASCII), option.getData());
+
+ option = dhcp.getOptions().get(4);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedParameters.getValue(),
+ option.code);
+ assertEquals(13, option.length);
+ assertArrayEquals(new byte[]{1, 28, 2, 3, 15, 6, 119, 12, 44, 47, 26, 121, 42},
+ option.getData());
+
+ option = dhcp.getOptions().get(5);
+ assertTrue(option instanceof DhcpRelayAgentOption);
+ DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
+ assertEquals(12, relayAgentOption.length);
+ DhcpOption subOption = relayAgentOption
+ .getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
+ assertEquals(10, subOption.getLength());
+ assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
+
+ option = dhcp.getOptions().get(6);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
+ assertEquals(0, option.length);
+ }
+
+ /**
+ * Tests deserialize discover packet.
+ */
+ @Test
+ public void testDeserializeAck() throws Exception {
+ byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(ACK));
+ Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
+ DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
+
+ assertEquals(DHCP.OPCODE_REPLY, dhcp.getOpCode());
+ assertEquals(HW_TYPE, dhcp.getHardwareType());
+ assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
+ assertEquals(HOPS, dhcp.getHops());
+ assertEquals(XID, dhcp.getTransactionId());
+ assertEquals(SECS, dhcp.getSeconds());
+ assertEquals(FLAGS, dhcp.getFlags());
+ assertEquals(NO_IP, dhcp.getClientIPAddress());
+ assertEquals(CLIENT_IP.toInt(), dhcp.getYourIPAddress());
+ assertEquals(SERVER_IP.toInt(), dhcp.getServerIPAddress());
+ assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
+ assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
+ assertEquals(EMPTY, dhcp.getServerName());
+ assertEquals(EMPTY, dhcp.getBootFileName());
+ assertEquals(9, dhcp.getOptions().size());
+
+ DhcpOption option = dhcp.getOptions().get(0);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
+ assertEquals(1, option.length);
+ assertEquals(DHCP.MsgType.DHCPACK.getValue(), (int) option.getData()[0]);
+
+ option = dhcp.getOptions().get(1);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(SERVER_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(2);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(new byte[]{0, 0, 2, 88}, option.getData());
+
+ option = dhcp.getOptions().get(3);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_SubnetMask.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(SUBNET_MASK.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(4);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue(), option.code);
+ assertEquals(4, option.length);
+ assertArrayEquals(GW_IP.toOctets(), option.getData());
+
+ option = dhcp.getOptions().get(5);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainName.getValue(), option.code);
+ assertEquals(13, option.length);
+ assertArrayEquals(DOMAIN_NAME.getBytes(Charsets.US_ASCII), option.getData());
+
+ option = dhcp.getOptions().get(6);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue(), option.code);
+ assertEquals(8, option.length);
+ assertArrayEquals(ArrayUtils.addAll(DNS_1.toOctets(), DNS_2.toOctets()),
+ option.getData());
+
+ option = dhcp.getOptions().get(7);
+ assertTrue(option instanceof DhcpRelayAgentOption);
+ DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
+ assertEquals(12, relayAgentOption.length);
+ DhcpOption subOption = relayAgentOption
+ .getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
+ assertEquals(10, subOption.getLength());
+ assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
+
+ option = dhcp.getOptions().get(8);
+ assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
+ assertEquals(0, option.length);
+ }
+
+ /**
+ * Test option with option length > 128.
+ */
+ @Test
+ public void longOptionTest() throws Exception {
+ byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(LONG_OPT));
+ DHCP dhcp = DHCP.deserializer().deserialize(data, 0, data.length);
+ assertEquals(2, dhcp.getOptions().size());
+ DhcpOption hostnameOption = dhcp.getOption(DHCP.DHCPOptionCode.OptionCode_HostName);
+ DhcpOption endOption = dhcp.getOption(DHCP.DHCPOptionCode.OptionCode_END);
+ assertNotNull(hostnameOption);
+ assertNotNull(endOption);
+
+ // Host name contains 200 "A"
+ StringBuilder hostnameBuilder = new StringBuilder();
+ IntStream.range(0, 200).forEach(i -> hostnameBuilder.append("A"));
+ String hostname = hostnameBuilder.toString();
+
+ assertEquals((byte) 200, hostnameOption.getLength());
+ assertArrayEquals(hostname.getBytes(Charsets.US_ASCII), hostnameOption.getData());
+ }
+}
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_advertise.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_advertise.bin
index edc32db..5ebba12 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_advertise.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_advertise.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_advertise.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_advertise.bin
index 8ea7fa1..e30948c 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_advertise.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_advertise.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_reply.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_reply.bin
index b08ac4a..8b4fcff 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_reply.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_reply.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_request.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_request.bin
index bbaeb48..18d80ae 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_request.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_request.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_solicit.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_solicit.bin
index 0890d69..08938e5 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_solicit.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_relay_solicit.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_reply.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_reply.bin
index 3d63acc..f8758e0 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_reply.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_reply.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_request.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_request.bin
index a8ec6bf..104d949 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_request.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_request.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_solicit.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_solicit.bin
index 9ab2d29..be8b2ca 100644
--- a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_solicit.bin
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp6_solicit.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_ack.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_ack.bin
new file mode 100644
index 0000000..3ffb65b
--- /dev/null
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_ack.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_discover.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_discover.bin
new file mode 100644
index 0000000..e486eea
--- /dev/null
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_discover.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_long_opt.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_long_opt.bin
new file mode 100644
index 0000000..0ed8ba8
--- /dev/null
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_long_opt.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_offer.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_offer.bin
new file mode 100644
index 0000000..2bf10f7
--- /dev/null
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_offer.bin
Binary files differ
diff --git a/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_request.bin b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_request.bin
new file mode 100644
index 0000000..38111c9
--- /dev/null
+++ b/utils/misc/src/test/resources/org/onlab/packet/dhcp/dhcp_request.bin
Binary files differ