/*
* Sun Public License
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is available at http://www.sun.com/
*
* The Original Code is the SLAMD Distributed Load Generation Engine.
* The Initial Developer of the Original Code is Neil A. Wilson.
* Portions created by Neil A. Wilson are Copyright (C) 2004-2010.
* Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): Neil A. Wilson
*/
package com.slamd.tools.ldapdecoder.snoop;
/**
* This class defines a data structure for storing information about the
* Transmission Control Protocol (TCP) header as defined in RFC 793.
*
*
* @author Neil A. Wilson
*/
public class TCPHeader
{
/**
* The IP protocol value that indicates the data contains TCP information.
*/
public static final byte IP_PROTOCOL_TCP = 0x06;
/**
* The bitmask that may be applied to the TCP flags to determine whether the
* urgent pointer field should be considered significant.
*/
public static final byte TCP_FLAG_MASK_URG = 0x20;
/**
* The bitmask that may be applied to the TCP flags to determine whether the
* acknowledgement field should be considered significant.
*/
public static final byte TCP_FLAG_MASK_ACK = 0x10;
/**
* The bitmask that may be applied to the TCP flags to determine whether the
* push flag is set.
*/
public static final byte TCP_FLAG_MASK_PSH = 0x08;
/**
* The bitmask that may be applied to the TCP flags to determine whether the
* reset flag is set, indicating the forceful destruction of a connection.
*/
public static final byte TCP_FLAG_MASK_RST = 0x04;
/**
* The bitmask that may be applied to the TCP flags to determine whether the
* SYN flag is set, indicating a new connection.
*/
public static final byte TCP_FLAG_MASK_SYN = 0x02;
/**
* The bitmask that may be applied to the TCP flags to determine whether the
* FIN flag is set, indicating the connection is being closed.
*/
public static final byte TCP_FLAG_MASK_FIN = 0x01;
// Any data associated with options in this TCP header.
private byte[] optionBytes;
// The acknowledgement number for this TCP header.
private int ackNumber;
// The checksum for this TCP header.
private int checksum;
// The position of the end of this TCP header and the beginning of the data.
private int dataOffset;
// The destination port for this TCP header.
private int destinationPort;
// The sequence number for this TCP header.
private int sequenceNumber;
// The source port for this TCP header.
private int sourcePort;
// The set of flags for this TCP header.
private int tcpFlags;
// The urgent pointer for this TCP header.
private int urgentPointer;
// The window for this TCP header.
private int window;
/**
* Creates a new TCP header with the provided information.
*
* @param sourcePort The source port for this TCP header.
* @param destinationPort The destination port for this TCP header.
* @param sequenceNumber The sequence number for this TCP header.
* @param ackNumber The acknowledgement number for this TCP header.
* @param dataOffset The data offset for this TCP header, measured in
* 32-bit words.
* @param tcpFlags The set of flags associated with this TCP header.
* @param window The window for this TCP header.
* @param checksum The checksum for this TCP header.
* @param urgentPointer The urgent pointer for this TCP header.
* @param optionBytes The raw data associated with any options in this
* TCP header.
*/
public TCPHeader(int sourcePort, int destinationPort, int sequenceNumber,
int ackNumber, int dataOffset, int tcpFlags, int window,
int checksum, int urgentPointer, byte[] optionBytes)
{
this.sourcePort = sourcePort;
this.destinationPort = destinationPort;
this.sequenceNumber = sequenceNumber;
this.ackNumber = ackNumber;
this.dataOffset = dataOffset;
this.tcpFlags = tcpFlags;
this.window = window;
this.checksum = checksum;
this.urgentPointer = urgentPointer;
this.optionBytes = optionBytes;
}
/**
* Decodes information in the provided byte array as a TCP header.
*
* @param headerBytes The byte array containing the header information to
* decode.
* @param offset The position in the byte array at which to begin
* decoding.
*
* @return The decoded TCP header.
*
* @throws SnoopException If a problem occurs while trying to decode the
* TCP header.
*/
public static TCPHeader decodeTCPHeader(byte[] headerBytes, int offset)
throws SnoopException
{
// First, make sure the provided byte array is long enough to hold the
// minimum TCP header length of 20 bytes.
if ((offset+20) > headerBytes.length)
{
throw new SnoopException("Provided byte array is not large enough to " +
"hold the minimum TCP header size of 20 bytes.");
}
int sourcePort = SnoopDecoder.byteArrayToInt(headerBytes, offset, 2);
int destinationPort = SnoopDecoder.byteArrayToInt(headerBytes, offset+2, 2);
int sequenceNumber = SnoopDecoder.byteArrayToInt(headerBytes, offset+4, 4);
int ackNumber = SnoopDecoder.byteArrayToInt(headerBytes, offset+8, 4);
int dataOffset = ((headerBytes[offset+12] >>> 4) & 0x0F);
if ((offset+(dataOffset*4)) > headerBytes.length)
{
throw new SnoopException("Provided byte array is not large enough to " +
"hold the decoded TCP header size of " +
(dataOffset*4) + " bytes.");
}
int tcpFlags = (headerBytes[offset+13] & 0x3F);
int window = SnoopDecoder.byteArrayToInt(headerBytes, offset+14, 2);
int checksum = SnoopDecoder.byteArrayToInt(headerBytes, offset+16, 2);
int urgentPointer = SnoopDecoder.byteArrayToInt(headerBytes, offset+18, 2);
byte[] optionBytes;
if (dataOffset > 5)
{
optionBytes = new byte[(dataOffset - 5) * 4];
System.arraycopy(headerBytes, offset+20, optionBytes, 0,
optionBytes.length);
}
else
{
optionBytes = new byte[0];
}
return new TCPHeader(sourcePort, destinationPort, sequenceNumber, ackNumber,
dataOffset, tcpFlags, window, checksum, urgentPointer,
optionBytes);
}
/**
* Retrieves the source port for this TCP packet. The port will be encoded in
* the lower 16 bits of the returned int value.
*
* @return The source port for this TCP packet.
*/
public int getSourcePort()
{
return sourcePort;
}
/**
* Retrieves the destination port for this TCP packet. The port will be
* encoded in the lower 16 bits of the returned int value.
*
* @return The destination port for this TCP packet.
*/
public int getDestinationPort()
{
return destinationPort;
}
/**
* Retrieves the sequence number for this TCP packet. The value will use all
* 32 bits of the returned int value.
*
* @return The sequence number for this TCP packet.
*/
public int getSequenceNumber()
{
return sequenceNumber;
}
/**
* Retrieves the acknowledgement number for this TCP packet. The value will
* use all 32 bits of the returned int value.
*
* @return The acknowledgement number for this TCP packet.
*/
public int getAcknowledgementNumber()
{
return ackNumber;
}
/**
* Retrieves the data offset for this TCP header. The value will be encoded
* in the lower 4 bits of the provided value and will indicate the number of
* 32-bit words contained in the header.
*
* @return The data offset for this TCP header.
*/
public int getDataOffset()
{
return dataOffset;
}
/**
* Retrieves the length in bytes of this TCP header.
*
* @return The length in bytes of this TCP header.
*/
public int getHeaderLength()
{
return (dataOffset * 4);
}
/**
* Retrieves the set of flags for this TCP header. The flags will be encoded
* in the lower 6 bits of the returned int value, and individual flags may
* be checked by ANDing them with the values of the
* <CODE>TCP_FLAG_MASK_*</CODE> constants.
*
* @return The set of flags for this TCP header.
*/
public int getTCPFlags()
{
return tcpFlags;
}
/**
* Retrieves the window for this TCP header. The value will be encoded in
* the lower 16 bits of the returned int value.
*
* @return The window for this TCP header.
*/
public int getWindow()
{
return window;
}
/**
* Retrieves the checksum for this TCP header. The value will be encoded in
* the lower 16 bits of the returned int value.
*
* @return The checksum for this TCP header.
*/
public int getChecksum()
{
return checksum;
}
/**
* Retrieves the urgent pointer for this TCP header. The window will be
* encoded in the lower 16 bits of the returned int value.
*
* @return The urgent pointer for this TCP header.
*/
public int getUrgentPointer()
{
return urgentPointer;
}
/**
* Retrieves the data for any options associated with this TCP header.
*
* @return The data for any options associated with this TCP header.
*/
public byte[] getOptionBytes()
{
return optionBytes;
}
}