#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.