|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005 Christian Dankbar, Irene Ruengeler, Michael Tuexen, Andras Varga 00003 // Copyright (C) 2009 Thomas Reschka 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 00020 //Define_Module(TCPSerializer); 00021 #include <platdep/sockets.h> 00022 #include "TCPSerializer.h" 00023 00024 #include "IPProtocolId_m.h" 00025 #include "TCPIPchecksum.h" 00026 00027 namespace INETFw // load headers into a namespace, to avoid conflicts with platform definitions of the same stuff 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> // htonl, ntohl, ... 00036 //#include <sys/types.h> 00037 //#include <sys/socket.h> 00038 //#include <arpa/inet.h> 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 //cMessage* cmsg; 00049 struct tcphdr *tcp = (struct tcphdr*) (buf); 00050 //int writtenbytes = sizeof(struct tcphdr)+tcpseg->payloadLength(); 00051 int writtenbytes = tcpseg->getByteLength(); 00052 00053 // fill TCP header structure 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 // set flags 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) // options present? 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(); // length >= 1 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 } // for 00114 //padding: 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; // TCP_HEADER_OCTETS = 20 00121 } // if options present 00122 00123 // write data 00124 if (tcpseg->getByteLength() > tcpseg->getHeaderLength()) // data present? FIXME TODO: || tcpseg->getEncapsulatedPacket()!=NULL 00125 { 00126 unsigned int dataLength = tcpseg->getByteLength() - tcpseg->getHeaderLength(); 00127 // TCPPayloadMessage *tcpP = check_and_cast<TCPPayloadMessage* >(tcpseg->getEncapsulatedPacket()); // FIXME 00128 char *tcpData = (char *)options+lengthCounter; 00129 memset(tcpData, 't', dataLength); // fill data part with 't' 00130 /* 00131 for (unsigned int i=0; i < dataLength; i++) 00132 { 00133 if (i < tcpseg->getPayloadArraySize()) 00134 { 00135 // tcpData[i] = (unsigned char) tcpP.msg; // FIXME 00136 tcpData[i] = 't'; // FIXME - write 't' as dummy data 00137 } 00138 else 00139 {tcpData[i] = 't';} // write 't' as dummy data 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 // fill TCP header structure 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 // set flags 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 // Checksum (header checksum): modelled by cMessage::hasBitError() 00188 tcpseg->setUrgentPointer(ntohs(tcp->th_urp)); 00189 00190 if (hdrLength > TCP_HEADER_OCTETS) // options present? 00191 { 00192 unsigned short optionBytes = hdrLength - TCP_HEADER_OCTETS; // TCP_HEADER_OCTETS = 20 00193 unsigned short optionsCounter = 0; // index for tcpseg->setOptions[] 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: // EOL 00206 case TCPOPTION_NO_OPERATION: // NOP 00207 length = 1; 00208 break; 00209 00210 default: 00211 break; 00212 } // switch 00213 00214 // kind 00215 tmpOption.setKind(kind); 00216 // length 00217 tmpOption.setLength(length); 00218 // value 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 // write option to tcp header 00231 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1); 00232 tcpseg->setOptions(optionsCounter,tmpOption); 00233 optionsCounter++; 00234 } // for j 00235 } // if options present 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 //sum += srcip; 00249 sum += htons(TCPIPchecksum::_checksum(srcIp.words(), sizeof(uint32)*srcIp.wordCount())); 00250 00251 //sum += destip; 00252 sum += htons(TCPIPchecksum::_checksum(destIp.words(), sizeof(uint32)*destIp.wordCount())); 00253 00254 sum += htons(count); // TCP length 00255 00256 sum += htons(IP_PROT_TCP); // PTCL 00257 00258 while (sum >> 16) 00259 sum = (sum & 0xFFFF) + (sum >> 16); 00260 00261 return (uint16_t)~sum; 00262 }