[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();