#include <TCPSerializer.h>
Public Member Functions | |
| TCPSerializer () | |
| int | serialize (const TCPSegment *source, unsigned char *destbuf, unsigned int bufsize) |
| int | serialize (const TCPSegment *source, unsigned char *destbuf, unsigned int bufsize, const IPvXAddress &srcIp, const IPvXAddress &destIp) |
| void | parse (const unsigned char *srcbuf, unsigned int bufsize, TCPSegment *dest) |
Static Public Member Functions | |
| static uint16_t | checksum (const void *addr, unsigned int count, const IPvXAddress &srcIp, const IPvXAddress &destIp) |
Converts between TCPSegment and binary (network byte order) TCP header.
Definition at line 34 of file TCPSerializer.h.
| TCPSerializer::TCPSerializer | ( | ) | [inline] |
Definition at line 37 of file TCPSerializer.h.
{}
| uint16_t TCPSerializer::checksum | ( | const void * | addr, | |
| unsigned int | count, | |||
| const IPvXAddress & | srcIp, | |||
| const IPvXAddress & | destIp | |||
| ) | [static] |
Calculate checksum with pseudo header.
Definition at line 241 of file TCPSerializer.cc.
Referenced by serialize().
{
uint32_t sum = TCPIPchecksum::_checksum(addr, count);
ASSERT(srcIp.wordCount() == destIp.wordCount());
//sum += srcip;
sum += htons(TCPIPchecksum::_checksum(srcIp.words(), sizeof(uint32)*srcIp.wordCount()));
//sum += destip;
sum += htons(TCPIPchecksum::_checksum(destIp.words(), sizeof(uint32)*destIp.wordCount()));
sum += htons(count); // TCP length
sum += htons(IP_PROT_TCP); // PTCL
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
return (uint16_t)~sum;
}
| void TCPSerializer::parse | ( | const unsigned char * | srcbuf, | |
| unsigned int | bufsize, | |||
| TCPSegment * | dest | |||
| ) |
Puts a packet sniffed from the wire into a TCPSegment. TODO dest why not reference?
Definition at line 157 of file TCPSerializer.cc.
{
ASSERT(buf);
ASSERT(tcpseg);
struct tcphdr const * const tcp = (struct tcphdr * const ) (buf);
// fill TCP header structure
tcpseg->setSrcPort(ntohs(tcp->th_sport));
tcpseg->setDestPort(ntohs(tcp->th_dport));
tcpseg->setSequenceNo(ntohl(tcp->th_seq));
tcpseg->setAckNo(ntohl(tcp->th_ack));
unsigned short hdrLength =tcp->th_offs * 4;
tcpseg->setHeaderLength(hdrLength);
// set flags
unsigned char flags = tcp->th_flags;
if ((flags & TH_FIN) == TH_FIN)
tcpseg->setFinBit(true);
if ((flags & TH_SYN) == TH_SYN)
tcpseg->setSynBit(true);
if ((flags & TH_RST) == TH_RST)
tcpseg->setRstBit(true);
if ((flags & TH_PUSH) == TH_PUSH)
tcpseg->setPshBit(true);
if ((flags & TH_ACK) == TH_ACK)
tcpseg->setAckBit(true);
if ((flags & TH_URG) == TH_URG)
tcpseg->setUrgBit(true);
tcpseg->setWindow(ntohs(tcp->th_win));
// Checksum (header checksum): modelled by cMessage::hasBitError()
tcpseg->setUrgentPointer(ntohs(tcp->th_urp));
if (hdrLength > TCP_HEADER_OCTETS) // options present?
{
unsigned short optionBytes = hdrLength - TCP_HEADER_OCTETS; // TCP_HEADER_OCTETS = 20
unsigned short optionsCounter = 0; // index for tcpseg->setOptions[]
unsigned short length = 0;
for (unsigned short j=0; j<optionBytes; j+=length)
{
unsigned char * options = ((unsigned char * )tcp->th_options)+j;
unsigned short kind = options[0];
length = options[1];
TCPOption tmpOption;
switch(kind)
{
case TCPOPTION_END_OF_OPTION_LIST: // EOL
case TCPOPTION_NO_OPERATION: // NOP
length = 1;
break;
default:
break;
} // switch
// kind
tmpOption.setKind(kind);
// length
tmpOption.setLength(length);
// value
int optlen = (length+1)/4;
tmpOption.setValuesArraySize(optlen);
for (short int k=0; k<optlen; k++)
{
unsigned int value = 0;
for (short int l=2+4*k; l<length && l<6+4*k; l++)
{
value = (value << 8) + options[l];
}
tmpOption.setValues(k, value);
}
// write option to tcp header
tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
tcpseg->setOptions(optionsCounter,tmpOption);
optionsCounter++;
} // for j
} // if options present
tcpseg->setByteLength(bufsize);
tcpseg->setPayloadLength(bufsize - tcpseg->getHeaderLength());
}
| int TCPSerializer::serialize | ( | const TCPSegment * | source, | |
| unsigned char * | destbuf, | |||
| unsigned int | bufsize | |||
| ) |
Serializes a TCPSegment for transmission on the wire. The checksum is NOT filled in. Returns the length of data written into buffer. TODO msg why not a const reference?
Definition at line 43 of file TCPSerializer.cc.
Referenced by serialize().
{
ASSERT(buf);
ASSERT(tcpseg);
//cMessage* cmsg;
struct tcphdr *tcp = (struct tcphdr*) (buf);
//int writtenbytes = sizeof(struct tcphdr)+tcpseg->payloadLength();
int writtenbytes = tcpseg->getByteLength();
// fill TCP header structure
tcp->th_sum = 0;
tcp->th_sport = htons(tcpseg->getSrcPort());
tcp->th_dport = htons(tcpseg->getDestPort());
tcp->th_seq = htonl(tcpseg->getSequenceNo());
tcp->th_ack = htonl(tcpseg->getAckNo());
tcp->th_offs = TCP_HEADER_OCTETS / 4;
// set flags
unsigned char flags = 0;
if(tcpseg->getFinBit())
flags |= TH_FIN;
if(tcpseg->getSynBit())
flags |= TH_SYN;
if(tcpseg->getRstBit())
flags |= TH_RST;
if(tcpseg->getPshBit())
flags |= TH_PUSH;
if(tcpseg->getAckBit())
flags |= TH_ACK;
if(tcpseg->getUrgBit())
flags |= TH_URG;
tcp->th_flags = (TH_FLAGS & flags);
tcp->th_win = htons(tcpseg->getWindow());
tcp->th_urp = htons(tcpseg->getUrgentPointer());
unsigned short numOptions = tcpseg->getOptionsArraySize();
unsigned int lengthCounter = 0;
unsigned char * options = (unsigned char * )tcp->th_options;
if (numOptions > 0) // options present?
{
unsigned int maxOptLength = tcpseg->getHeaderLength()-TCP_HEADER_OCTETS;
for (unsigned short i=0; i < numOptions; i++)
{
TCPOption option = tcpseg->getOptions(i);
unsigned short kind = option.getKind();
unsigned short length = option.getLength(); // length >= 1
options = ((unsigned char * )tcp->th_options)+lengthCounter;
lengthCounter += length;
ASSERT(lengthCounter <= maxOptLength);
options[0] = kind;
if(length>1)
{
options[1] = length;
}
unsigned int optlen = option.getValuesArraySize();
for(unsigned int k=0; k<optlen; k++)
{
unsigned int value = option.getValues(k);
unsigned int p0 = 2 + 4*k;
for (unsigned int p = std::min((unsigned int)length-1, 5 + 4*k); p >= p0; p--)
{
options[p] = value & 0xFF;
value = value >> 8;
}
}
} // for
//padding:
options = (unsigned char * )(tcp->th_options);
while (lengthCounter % 4)
options[lengthCounter++] = 0;
ASSERT(TCP_HEADER_OCTETS+lengthCounter <= TCP_MAX_HEADER_OCTETS);
tcp->th_offs = (TCP_HEADER_OCTETS+lengthCounter)/4; // TCP_HEADER_OCTETS = 20
} // if options present
// write data
if (tcpseg->getByteLength() > tcpseg->getHeaderLength()) // data present? FIXME TODO: || tcpseg->getEncapsulatedMsg()!=NULL
{
unsigned int dataLength = tcpseg->getByteLength() - tcpseg->getHeaderLength();
// TCPPayloadMessage *tcpP = check_and_cast<TCPPayloadMessage* >(tcpseg->getEncapsulatedMsg()); // FIXME
char *tcpData = (char *)options+lengthCounter;
memset(tcpData, 't', dataLength); // fill data part with 't'
/*
for (unsigned int i=0; i < dataLength; i++)
{
if (i < tcpseg->getPayloadArraySize())
{
// tcpData[i] = (unsigned char) tcpP.msg; // FIXME
tcpData[i] = 't'; // FIXME - write 't' as dummy data
}
else
{tcpData[i] = 't';} // write 't' as dummy data
}
*/
}
return writtenbytes;
}
| int TCPSerializer::serialize | ( | const TCPSegment * | source, | |
| unsigned char * | destbuf, | |||
| unsigned int | bufsize, | |||
| const IPvXAddress & | srcIp, | |||
| const IPvXAddress & | destIp | |||
| ) |
Serializes a TCPSegment for transmission on the wire. The checksum is NOT filled in. (The kernel does that when sending the frame over a raw socket.) Returns the length of data written into buffer. TODO msg why not a const reference? TODO pseudoheader vs IPv6, pseudoheder.len should calculated by the serialize(), etc
Definition at line 146 of file TCPSerializer.cc.
1.7.1