private static final String DIP = "DestinationIPAddress";
private static final String OPTIONS = "Options";
+ private static final int UNIT_SIZE_SHIFT = 2;
+ private static final int UNIT_SIZE = (1 << UNIT_SIZE_SHIFT);
+ private static final int MIN_HEADER_SIZE = 20;
+
public static final Map<Byte, Class<? extends Packet>> protocolClassMap;
static {
protocolClassMap = new HashMap<Byte, Class<? extends Packet>>();
public int getHeaderSize() {
int headerLen = this.getHeaderLen();
if (headerLen == 0) {
- headerLen = 20;
- }
-
- byte[] options = hdrFieldsMap.get(OPTIONS);
- if (options != null) {
- headerLen += options.length;
+ headerLen = MIN_HEADER_SIZE;
}
return headerLen * NetUtils.NumBitsInAByte;
public void setHeaderField(String headerField, byte[] readValue) {
if (headerField.equals(PROTOCOL)) {
payloadClass = protocolClassMap.get(readValue[0]);
+ } else if (headerField.equals(OPTIONS) &&
+ (readValue == null || readValue.length == 0)) {
+ hdrFieldsMap.remove(headerField);
+ return;
}
hdrFieldsMap.put(headerField, readValue);
}
}
/**
- * Stores the length of IP header in words (2 bytes)
+ * Stores the length of IP header in words (4 bytes)
* @param headerLength the headerLength to set
* @return IPv4
*/
* @param checksum the checksum to set
*/
/*public IPv4 setChecksum() {
- short ipChecksum = computeChecksum();
+ short ipChecksum = computeChecksum();
byte[] checksum = BitBufferHelper.toByteArray(ipChecksum);
- fieldValues.put(CHECKSUM, checksum);
+ fieldValues.put(CHECKSUM, checksum);
return this;
}*/
* @return IPv4
*/
public IPv4 setOptions(byte[] options) {
- fieldValues.put(OPTIONS, options);
- byte newIHL = (byte) (5 + options.length);
+ byte newIHL = (byte)(MIN_HEADER_SIZE >>> UNIT_SIZE_SHIFT);
+ if (options == null || options.length == 0) {
+ fieldValues.remove(OPTIONS);
+ } else {
+ int len = options.length;
+ int rlen = (len + (UNIT_SIZE - 1)) & ~(UNIT_SIZE - 1);
+ if (rlen > len) {
+ // Padding is required.
+ byte[] newopt = new byte[rlen];
+ System.arraycopy(options, 0, newopt, 0, len);
+ options = newopt;
+ len = rlen;
+ }
+ fieldValues.put(OPTIONS, options);
+ newIHL += (len >>> UNIT_SIZE_SHIFT);
+ }
+
setHeaderLength(newIHL);
return this;
/**
* Computes the IPv4 header checksum on the passed stream of bytes
* representing the packet
- *
+ *
* @param data
* The byte stream
* @param offset
int end = start + getHeaderLen();
short checkSum = (short) 0;
int sum = 0, carry = 0, finalSum = 0;
- int parsedHex = 0;
+ int wordData;
int checksumStart = start
+ (getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte);
if (i == checksumStart) {
continue;
}
- StringBuffer sbuffer = new StringBuffer();
- sbuffer.append(String.format("%02X", data[i]));
- if (i < (data.length - 1)) {
- sbuffer.append(String.format("%02X", data[i + 1]));
- }
-
- parsedHex = Integer.valueOf(sbuffer.toString(), 16);
- sum += parsedHex;
+ wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
+ sum = sum + wordData;
}
carry = (sum >> 16) & 0xFF;
finalSum = (sum & 0xFFFF) + carry;
@Override
/**
* Gets the number of bits for the fieldname specified
- * If the fieldname has variable length like "Options", then this value is computed using the
- * options length and the header length
+ * If the fieldname has variable length like "Options", then this value is computed using the header length
* @param fieldname - String
* @return number of bits for fieldname - int
*/
public int getfieldnumBits(String fieldName) {
if (fieldName.equals(OPTIONS)) {
- byte[] options = getOptions();
- return ((options == null) ? 0 : (options.length - getHeaderLen()));
+ return (getHeaderLen() - MIN_HEADER_SIZE) * NetUtils.NumBitsInAByte;
}
return hdrFieldCoordMap.get(fieldName).getRight();
}