Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <platdep/sockets.h>
00022 #include "TCPSerializer.h"
00023
00024 #include "IPProtocolId_m.h"
00025 #include "TCPIPchecksum.h"
00026
00027 namespace INETFw
00028 {
00029 #include "headers/bsdint.h"
00030 #include "headers/in.h"
00031 #include "headers/in_systm.h"
00032 };
00033
00034 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64)
00035 #include <netinet/in.h>
00036
00037
00038
00039 #endif
00040
00041 using namespace INETFw;
00042
00043 int TCPSerializer::serialize(const TCPSegment *tcpseg,
00044 unsigned char *buf, unsigned int bufsize)
00045 {
00046 ASSERT(buf);
00047 ASSERT(tcpseg);
00048
00049 struct tcphdr *tcp = (struct tcphdr*) (buf);
00050
00051 int writtenbytes = tcpseg->getByteLength();
00052
00053
00054 tcp->th_sum = 0;
00055 tcp->th_sport = htons(tcpseg->getSrcPort());
00056 tcp->th_dport = htons(tcpseg->getDestPort());
00057 tcp->th_seq = htonl(tcpseg->getSequenceNo());
00058 tcp->th_ack = htonl(tcpseg->getAckNo());
00059 tcp->th_offs = TCP_HEADER_OCTETS / 4;
00060
00061
00062 unsigned char flags = 0;
00063 if(tcpseg->getFinBit())
00064 flags |= TH_FIN;
00065 if(tcpseg->getSynBit())
00066 flags |= TH_SYN;
00067 if(tcpseg->getRstBit())
00068 flags |= TH_RST;
00069 if(tcpseg->getPshBit())
00070 flags |= TH_PUSH;
00071 if(tcpseg->getAckBit())
00072 flags |= TH_ACK;
00073 if(tcpseg->getUrgBit())
00074 flags |= TH_URG;
00075 tcp->th_flags = (TH_FLAGS & flags);
00076 tcp->th_win = htons(tcpseg->getWindow());
00077 tcp->th_urp = htons(tcpseg->getUrgentPointer());
00078
00079 unsigned short numOptions = tcpseg->getOptionsArraySize();
00080 unsigned int lengthCounter = 0;
00081 unsigned char * options = (unsigned char * )tcp->th_options;
00082 if (numOptions > 0)
00083 {
00084 unsigned int maxOptLength = tcpseg->getHeaderLength()-TCP_HEADER_OCTETS;
00085
00086 for (unsigned short i=0; i < numOptions; i++)
00087 {
00088 TCPOption option = tcpseg->getOptions(i);
00089 unsigned short kind = option.getKind();
00090 unsigned short length = option.getLength();
00091 options = ((unsigned char * )tcp->th_options)+lengthCounter;
00092
00093 lengthCounter += length;
00094
00095 ASSERT(lengthCounter <= maxOptLength);
00096
00097 options[0] = kind;
00098 if(length>1)
00099 {
00100 options[1] = length;
00101 }
00102 unsigned int optlen = option.getValuesArraySize();
00103 for(unsigned int k=0; k<optlen; k++)
00104 {
00105 unsigned int value = option.getValues(k);
00106 unsigned int p0 = 2 + 4*k;
00107 for (unsigned int p = std::min((unsigned int)length-1, 5 + 4*k); p >= p0; p--)
00108 {
00109 options[p] = value & 0xFF;
00110 value = value >> 8;
00111 }
00112 }
00113 }
00114
00115 options = (unsigned char * )(tcp->th_options);
00116 while (lengthCounter % 4)
00117 options[lengthCounter++] = 0;
00118
00119 ASSERT(TCP_HEADER_OCTETS+lengthCounter <= TCP_MAX_HEADER_OCTETS);
00120 tcp->th_offs = (TCP_HEADER_OCTETS+lengthCounter)/4;
00121 }
00122
00123
00124 if (tcpseg->getByteLength() > tcpseg->getHeaderLength())
00125 {
00126 unsigned int dataLength = tcpseg->getByteLength() - tcpseg->getHeaderLength();
00127
00128 char *tcpData = (char *)options+lengthCounter;
00129 memset(tcpData, 't', dataLength);
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 }
00143 return writtenbytes;
00144 }
00145
00146 int TCPSerializer::serialize(const TCPSegment *tcpseg,
00147 unsigned char *buf, unsigned int bufsize,
00148 const IPvXAddress &srcIp, const IPvXAddress &destIp)
00149 {
00150 int writtenbytes = serialize(tcpseg, buf, bufsize);
00151 struct tcphdr *tcp = (struct tcphdr*) (buf);
00152 tcp->th_sum = checksum(tcp, writtenbytes, srcIp, destIp);
00153
00154 return writtenbytes;
00155 }
00156
00157 void TCPSerializer::parse(const unsigned char *buf, unsigned int bufsize, TCPSegment *tcpseg)
00158 {
00159 ASSERT(buf);
00160 ASSERT(tcpseg);
00161 struct tcphdr const * const tcp = (struct tcphdr * const ) (buf);
00162
00163
00164 tcpseg->setSrcPort(ntohs(tcp->th_sport));
00165 tcpseg->setDestPort(ntohs(tcp->th_dport));
00166 tcpseg->setSequenceNo(ntohl(tcp->th_seq));
00167 tcpseg->setAckNo(ntohl(tcp->th_ack));
00168 unsigned short hdrLength =tcp->th_offs * 4;
00169 tcpseg->setHeaderLength(hdrLength);
00170
00171
00172 unsigned char flags = tcp->th_flags;
00173 if ((flags & TH_FIN) == TH_FIN)
00174 tcpseg->setFinBit(true);
00175 if ((flags & TH_SYN) == TH_SYN)
00176 tcpseg->setSynBit(true);
00177 if ((flags & TH_RST) == TH_RST)
00178 tcpseg->setRstBit(true);
00179 if ((flags & TH_PUSH) == TH_PUSH)
00180 tcpseg->setPshBit(true);
00181 if ((flags & TH_ACK) == TH_ACK)
00182 tcpseg->setAckBit(true);
00183 if ((flags & TH_URG) == TH_URG)
00184 tcpseg->setUrgBit(true);
00185
00186 tcpseg->setWindow(ntohs(tcp->th_win));
00187
00188 tcpseg->setUrgentPointer(ntohs(tcp->th_urp));
00189
00190 if (hdrLength > TCP_HEADER_OCTETS)
00191 {
00192 unsigned short optionBytes = hdrLength - TCP_HEADER_OCTETS;
00193 unsigned short optionsCounter = 0;
00194
00195 unsigned short length = 0;
00196 for (unsigned short j=0; j<optionBytes; j+=length)
00197 {
00198 unsigned char * options = ((unsigned char * )tcp->th_options)+j;
00199 unsigned short kind = options[0];
00200 length = options[1];
00201
00202 TCPOption tmpOption;
00203 switch(kind)
00204 {
00205 case TCPOPTION_END_OF_OPTION_LIST:
00206 case TCPOPTION_NO_OPERATION:
00207 length = 1;
00208 break;
00209
00210 default:
00211 break;
00212 }
00213
00214
00215 tmpOption.setKind(kind);
00216
00217 tmpOption.setLength(length);
00218
00219 int optlen = (length+1)/4;
00220 tmpOption.setValuesArraySize(optlen);
00221 for (short int k=0; k<optlen; k++)
00222 {
00223 unsigned int value = 0;
00224 for (short int l=2+4*k; l<length && l<6+4*k; l++)
00225 {
00226 value = (value << 8) + options[l];
00227 }
00228 tmpOption.setValues(k, value);
00229 }
00230
00231 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
00232 tcpseg->setOptions(optionsCounter,tmpOption);
00233 optionsCounter++;
00234 }
00235 }
00236
00237 tcpseg->setByteLength(bufsize);
00238 tcpseg->setPayloadLength(bufsize - tcpseg->getHeaderLength());
00239 }
00240
00241 uint16_t TCPSerializer::checksum(const void *addr, unsigned int count,
00242 const IPvXAddress &srcIp, const IPvXAddress &destIp)
00243 {
00244 uint32_t sum = TCPIPchecksum::_checksum(addr, count);
00245
00246 ASSERT(srcIp.wordCount() == destIp.wordCount());
00247
00248
00249 sum += htons(TCPIPchecksum::_checksum(srcIp.words(), sizeof(uint32)*srcIp.wordCount()));
00250
00251
00252 sum += htons(TCPIPchecksum::_checksum(destIp.words(), sizeof(uint32)*destIp.wordCount()));
00253
00254 sum += htons(count);
00255
00256 sum += htons(IP_PROT_TCP);
00257
00258 while (sum >> 16)
00259 sum = (sum & 0xFFFF) + (sum >> 16);
00260
00261 return (uint16_t)~sum;
00262 }