1 
2 /***************************************************************************
3  * TCPHeader.cc -- The TCPHeader Class represents a TCP packet. It         *
4  * contains methods to set the different header fields. These methods      *
5  * tipically perform the necessary error checks and byte order             *
6  * conversions.                                                            *
7  *                                                                         *
8  ***********************IMPORTANT NMAP LICENSE TERMS************************
9  *                                                                         *
10  * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap  *
11  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
12  *                                                                         *
13  * This program is distributed under the terms of the Nmap Public Source   *
14  * License (NPSL). The exact license text applying to a particular Nmap    *
15  * release or source code control revision is contained in the LICENSE     *
16  * file distributed with that version of Nmap or source code control       *
17  * revision. More Nmap copyright/legal information is available from       *
18  * https://nmap.org/book/man-legal.html, and further information on the    *
19  * NPSL license itself can be found at https://nmap.org/npsl. This header  *
20  * summarizes some key points from the Nmap license, but is no substitute  *
21  * for the actual license text.                                            *
22  *                                                                         *
23  * Nmap is generally free for end users to download and use themselves,    *
24  * including commercial use. It is available from https://nmap.org.        *
25  *                                                                         *
26  * The Nmap license generally prohibits companies from using and           *
27  * redistributing Nmap in commercial products, but we sell a special Nmap  *
28  * OEM Edition with a more permissive license and special features for     *
29  * this purpose. See https://nmap.org/oem                                  *
30  *                                                                         *
31  * If you have received a written Nmap license agreement or contract       *
32  * stating terms other than these (such as an Nmap OEM license), you may   *
33  * choose to use and redistribute Nmap under those terms instead.          *
34  *                                                                         *
35  * The official Nmap Windows builds include the Npcap software             *
36  * (https://npcap.org) for packet capture and transmission. It is under    *
37  * separate license terms which forbid redistribution without special      *
38  * permission. So the official Nmap Windows builds may not be              *
39  * redistributed without special permission (such as an Nmap OEM           *
40  * license).                                                               *
41  *                                                                         *
42  * Source is provided to this software because we believe users have a     *
43  * right to know exactly what a program is going to do before they run it. *
44  * This also allows you to audit the software for security holes.          *
45  *                                                                         *
46  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
47  * and add new features.  You are highly encouraged to submit your         *
48  * changes as a Github PR or by email to the dev@nmap.org mailing list     *
49  * for possible incorporation into the main distribution. Unless you       *
50  * specify otherwise, it is understood that you are offering us very       *
51  * broad rights to use your submissions as described in the Nmap Public    *
52  * Source License Contributor Agreement. This is important because we      *
53  * fund the project by selling licenses with various terms, and also       *
54  * because the inability to relicense code has caused devastating          *
55  * problems for other Free Software projects (such as KDE and NASM).       *
56  *                                                                         *
57  * The free version of Nmap is distributed in the hope that it will be     *
58  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  *
59  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,        *
60  * indemnification and commercial support are all available through the    *
61  * Npcap OEM program--see https://nmap.org/oem.                            *
62  *                                                                         *
63  ***************************************************************************/
64 /* This code was originally part of the Nping tool.                        */
65 
66 #include "TCPHeader.h"
67 #include <assert.h>
68 /******************************************************************************/
69 /* CONTRUCTORS, DESTRUCTORS AND INITIALIZATION METHODS                        */
70 /******************************************************************************/
TCPHeader()71 TCPHeader::TCPHeader(){
72   this->reset();
73 } /* End of TCPHeader constructor */
74 
75 
~TCPHeader()76 TCPHeader::~TCPHeader(){
77 
78 } /* End of TCPHeader destructor */
79 
80 /** Sets every attribute to its default value */
reset()81 void TCPHeader::reset(){
82   memset(&this->h, 0, sizeof(nping_tcp_hdr_t));
83   this->length=TCP_HEADER_LEN; /* Initial value 20. This will be incremented if options are used */
84   this->tcpoptlen=0;
85   this->setSourcePort(TCP_DEFAULT_SPORT);
86   this->setDestinationPort(TCP_DEFAULT_DPORT);
87   this->setSeq(TCP_DEFAULT_SEQ);
88   this->setAck(TCP_DEFAULT_ACK);
89   this->setFlags(TCP_DEFAULT_FLAGS);
90   this->setWindow(TCP_DEFAULT_WIN);
91   this->setUrgPointer(TCP_DEFAULT_URP);
92   this->setOffset();
93 } /* End of reset() */
94 
95 
96 /******************************************************************************/
97 /* PacketElement:: OVERWRITTEN METHODS                                        */
98 /******************************************************************************/
99 
100 /** @warning This method is essential for the superclass getBinaryBuffer()
101  *  method to work. Do NOT change a thing unless you know what you're doing  */
getBufferPointer()102 u8 * TCPHeader::getBufferPointer(){
103   return (u8*)(&h);
104 } /* End of getBufferPointer() */
105 
106 
107 /** Stores supplied packet in the internal buffer so the information
108   * can be accessed using the standard get & set methods.
109   * @warning  The TCPHeader class is able to hold a maximum of 60 bytes. If the
110   * supplied buffer is longer than that, only the first 60 bytes will be stored
111   * in the internal buffer.
112   * @warning Supplied len MUST be at least 20 bytes (min TCP header length).
113   * @return OP_SUCCESS on success and OP_FAILURE in case of error */
storeRecvData(const u8 * buf,size_t len)114 int TCPHeader::storeRecvData(const u8 *buf, size_t len){
115   if(buf==NULL || len<TCP_HEADER_LEN){
116     return OP_FAILURE;
117   }else{
118     int stored_len = MIN((TCP_HEADER_LEN + MAX_TCP_OPTIONS_LEN), len);
119     this->reset(); /* Re-init the object, just in case the caller had used it already */
120     this->length=stored_len;
121     if(stored_len>TCP_HEADER_LEN)
122         this->tcpoptlen=stored_len-TCP_HEADER_LEN;
123     memcpy(&(this->h), buf, stored_len);
124   }
125  return OP_SUCCESS;
126 } /* End of storeRecvData() */
127 
128 
129 /* Returns a protocol identifier. This is used by packet parsing funtions
130  * that return linked lists of PacketElement objects, to determine the protocol
131  * the object represents. */
protocol_id() const132 int TCPHeader::protocol_id() const {
133   return HEADER_TYPE_TCP;
134 } /* End of protocol_id() */
135 
136 
137 /** Determines if the data stored in the object after an storeRecvData() call
138   * is valid and safe to use. This mainly checks the length of the data but may
139   * also test the value of certain protocol fields to ensure their correctness.
140   * @warning If the information stored in the object has been set through a
141   * call to storeRecvData(), the object's internal length count may be updated
142   * if the validation is successful.
143   * @return the length, in bytes, of the header, if its found to be valid or
144   * OP_FAILURE (-1) otherwise. */
validate()145 int TCPHeader::validate(){
146   if(this->getOffset()<5)
147     return OP_FAILURE;
148   else if(this->getOffset()*4 > this->length)
149     return OP_FAILURE;
150   this->length=this->getOffset()*4;
151   return this->length;
152 } /* End of validate() */
153 
154 
155 /** Prints the contents of the header and calls print() on the next protocol
156   * header in the chain (if there is any).
157   * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
print(FILE * output,int detail) const158 int TCPHeader::print(FILE *output, int detail) const {
159   char optinfo[256];
160   fprintf(output, "TCP[");
161   fprintf(output, "%d", this->getSourcePort());
162   fprintf(output, " >");
163   fprintf(output, " %d", this->getDestinationPort());
164   fprintf(output, " %s%s%s%s%s%s%s%s",
165           !this->getSYN() ? "" : "S",
166           !this->getFIN() ? "" : "F",
167           !this->getRST() ? "" : "R",
168           !this->getPSH() ? "" : "P",
169           !this->getACK() ? "" : "A",
170           !this->getURG() ? "" : "U",
171           !this->getECN() ? "" : "E",
172           !this->getCWR() ? "" : "C"
173          );
174   fprintf(output, " seq=%lu", (long unsigned int)this->getSeq() );
175   if(detail>=PRINT_DETAIL_HIGH){
176     fprintf(output, " ack=%lu", (long unsigned int)this->getAck() );
177     fprintf(output, " off=%d", this->getOffset() );
178     fprintf(output, " res=%d", this->h.th_x2);
179   }
180   fprintf(output, " win=%hu", this->getWindow() );
181   if(detail>=PRINT_DETAIL_MED)
182     fprintf(output, " csum=0x%04X", ntohs( this->getSum() ));
183   if(detail>=PRINT_DETAIL_HIGH)
184     fprintf(output, " urp=%d", this->getUrgPointer() );
185 
186   if(this->tcpoptlen>0 && (this->length >= TCP_HEADER_LEN+this->tcpoptlen) && this->tcpoptlen<=MAX_TCP_OPTIONS_LEN){
187     this->__tcppacketoptinfo(this->h.options, this->tcpoptlen, optinfo, sizeof(optinfo)-1);
188     optinfo[255]='\0';
189     fprintf(output, " %s", optinfo);
190   }
191   fprintf(output, "]");
192 
193   if(this->next!=NULL){
194     print_separator(output, detail);
195     next->print(output, detail);
196   }
197   return OP_SUCCESS;
198 } /* End of print() */
199 
200 
201 /* Get an ASCII information about a tcp option which is pointed by
202    optp, with a length of len. The result is stored in the result
203    buffer. The result may look like "<mss 1452,sackOK,timestamp
204    45848914 0,nop,wscale 7>" */
__tcppacketoptinfo(const u8 * optp,int len,char * result,int bufsize) const205 void TCPHeader::__tcppacketoptinfo(const u8 *optp, int len, char *result, int bufsize) const {
206   assert(optp);
207   assert(result);
208   char *p, ch;
209   const u8 *q;
210   int opcode;
211   u16 tmpshort;
212   u32 tmpword1, tmpword2;
213   unsigned int i=0;
214 
215   p = result;
216   *p = '\0';
217   q = optp;
218   ch = '<';
219 
220   while (len > 0 && bufsize > 2) {
221     Snprintf(p, bufsize, "%c", ch);
222     bufsize--;
223     p++;
224     opcode = *q++;
225     if (!opcode) { /* End of List */
226 
227       Snprintf(p, bufsize, "eol");
228       bufsize -= strlen(p);
229       p += strlen(p);
230 
231       len--;
232 
233     } else if (opcode == 1) { /* No Op */
234       Snprintf(p, bufsize, "nop");
235       bufsize -= strlen(p);
236       p += strlen(p);
237 
238       len--;
239     } else if (opcode == 2) { /* MSS */
240       if (len < 4)
241         break; /* MSS has 4 bytes */
242 
243       q++;
244       memcpy(&tmpshort, q, 2);
245 
246       Snprintf(p, bufsize, "mss %u", ntohs(tmpshort));
247       bufsize -= strlen(p);
248       p += strlen(p);
249 
250       q += 2;
251       len -= 4;
252     } else if (opcode == 3) { /* Window Scale */
253       if (len < 3)
254         break; /* Window Scale option has 3 bytes */
255 
256       q++;
257 
258       Snprintf(p, bufsize, "wscale %u", *q);
259       bufsize -= strlen(p);
260       p += strlen(p);
261 
262       q++;
263       len -= 3;
264     } else if (opcode == 4) { /* SACK permitted */
265       if (len < 2)
266         break; /* SACK permitted option has 2 bytes */
267 
268       Snprintf(p, bufsize, "sackOK");
269       bufsize -= strlen(p);
270       p += strlen(p);
271 
272       q++;
273       len -= 2;
274     } else if (opcode == 5) { /* SACK */
275       unsigned sackoptlen = *q;
276       if ((unsigned) len < sackoptlen)
277         break;
278 
279       /* This would break parsing, so it's best to just give up */
280       if (sackoptlen < 2)
281         break;
282 
283       q++;
284 
285       if ((sackoptlen - 2) == 0 || ((sackoptlen - 2) % 8 != 0)) {
286         Snprintf(p, bufsize, "malformed sack");
287         bufsize -= strlen(p);
288         p += strlen(p);
289       } else {
290         Snprintf(p, bufsize, "sack %d ", (sackoptlen - 2) / 8);
291         bufsize -= strlen(p);
292         p += strlen(p);
293         for (i = 0; i < sackoptlen - 2; i += 8) {
294           memcpy(&tmpword1, q + i, 4);
295           memcpy(&tmpword2, q + i + 4, 4);
296           Snprintf(p, bufsize, "{%u:%u}", tmpword1, tmpword2);
297           bufsize -= strlen(p);
298           p += strlen(p);
299         }
300       }
301 
302       q += sackoptlen - 2;
303       len -= sackoptlen;
304     } else if (opcode == 8) { /* Timestamp */
305       if (len < 10)
306         break; /* Timestamp option has 10 bytes */
307 
308       q++;
309       memcpy(&tmpword1, q, 4);
310       memcpy(&tmpword2, q + 4, 4);
311 
312       Snprintf(p, bufsize, "timestamp %u %u", ntohl(tmpword1),
313                ntohl(tmpword2));
314       bufsize -= strlen(p);
315       p += strlen(p);
316 
317       q += 8;
318       len -= 10;
319     }
320 
321     ch = ',';
322   }
323 
324   if (len > 0) {
325     *result = '\0';
326     return;
327   }
328 
329   Snprintf(p, bufsize, ">");
330 }
331 
332 
333 
334 /******************************************************************************/
335 /* PROTOCOL-SPECIFIC METHODS                                                  */
336 /******************************************************************************/
337 
338 /** Sets source port.
339  *  @warning Port must be supplied in host byte order. This method performs
340  *  byte order conversion using htons() */
setSourcePort(u16 p)341 int TCPHeader::setSourcePort(u16 p){
342   h.th_sport = htons(p);
343   return OP_SUCCESS;
344 } /* End of setSourcePort() */
345 
346 
347 /** Returns source port in HOST byte order */
getSourcePort() const348 u16 TCPHeader::getSourcePort() const {
349   return ntohs(h.th_sport);
350 } /* End of getSourcePort() */
351 
352 
353 /** Sets destination port.
354  *  @warning Port must be supplied in host byte order. This method performs
355  *  byte order conversion using htons() */
setDestinationPort(u16 p)356 int TCPHeader::setDestinationPort(u16 p){
357   h.th_dport = htons(p);
358   return OP_SUCCESS;
359 } /* End of setDestinationPort() */
360 
361 
362 /** Returns destination port in HOST byte order  */
getDestinationPort() const363 u16 TCPHeader::getDestinationPort() const {
364   return ntohs(h.th_dport);
365 } /* End of getDestinationPort() */
366 
367 
368 /** Sets sequence number.
369  *  @warning Seq number must be supplied in host byte order. This method
370  *  performs byte order conversion using htonl() */
setSeq(u32 p)371 int TCPHeader::setSeq(u32 p){
372   h.th_seq = htonl(p);
373   return OP_SUCCESS;
374 } /* End of setSeq() */
375 
376 
377 /** Returns sequence number in HOST byte order */
getSeq() const378 u32 TCPHeader::getSeq() const {
379   return ntohl(h.th_seq);
380 } /* End of getSeq() */
381 
382 
383 /** Sets acknowledgement number.
384  *  @warning ACK number must be supplied in host byte order. This method
385  *  performs byte order conversion using htonl() */
setAck(u32 p)386 int TCPHeader::setAck(u32 p){
387   h.th_ack = htonl(p);
388   return OP_SUCCESS;
389 } /* End of setAck() */
390 
391 
392 /** Returns ACK number in HOST byte order */
getAck() const393 u32 TCPHeader::getAck() const {
394   return ntohl(h.th_ack);
395 } /* End of getAck() */
396 
397 
398 /* TODO: Test this method. It may not work becuasse th_off is supposed to
399  * be 4 bits long and arg o is 8.
400  * UPDATE: It seems to work just fine. However, let's keep this note just
401  * in case problems arise. */
setOffset(u8 o)402 int TCPHeader::setOffset(u8 o){
403   h.th_off = o;
404   return OP_SUCCESS;
405 } /* End of setOffset() */
406 
407 
setOffset()408 int TCPHeader::setOffset(){
409   h.th_off = 5 + tcpoptlen/4;
410   return OP_SUCCESS;
411 } /* End of setOffset() */
412 
413 
414 /** Returns offset value */
getOffset() const415 u8 TCPHeader::getOffset() const {
416   return h.th_off;
417 } /* End of getOffset() */
418 
419 
420 /* Sets the 4-bit reserved field (Note that there are not 4 reserved bits anymore
421  * as RFC 3540 introduces a new TCP flag, so calling this will overwrite
422  * the value of such flag. */
setReserved(u8 r)423 int TCPHeader::setReserved(u8 r){
424   h.th_x2 = r;
425   return OP_SUCCESS;
426 }
427 
428 
getReserved() const429 u8 TCPHeader::getReserved() const {
430   return h.th_x2;
431 }
432 
433 
434 /** Sets TCP flags */
setFlags(u8 f)435 int TCPHeader::setFlags(u8 f){
436   h.th_flags = f;
437   return OP_SUCCESS;
438 } /* End of setFlags() */
439 
440 
441 /** Returns the 8bit flags field of the TCP header */
getFlags() const442 u8 TCPHeader::getFlags() const {
443   return h.th_flags;
444 } /* End of getFlags() */
445 
446 
447 /* Returns the 16bit flags field of the TCP header. As RFC 3540 defines a new
448  * flag (NS), we no longer can store all TCP flags in a single octet, so
449  * this method returns the flags as a two-octet unsigned integer. */
getFlags16() const450 u16 TCPHeader::getFlags16() const {
451   /* Obtain the value of dataoff+reserved+flags in host byte order */
452   u16 field=ntohs(*(u16 *)(((u8 *)&this->h)+12));
453   /* Erase the contents of the data offset field */
454   field = field & 0x0FFF;
455   return field;
456 } /* End of getFlags16() */
457 
458 
459 /** Sets flag CWR
460  *  @return Previous state of the flag */
setCWR()461 bool TCPHeader::setCWR(){
462   u8 prev = h.th_flags & TH_CWR;
463   h.th_flags |= TH_CWR;
464   return prev;
465 } /* End of setCWR() */
466 
467 
468 /** Unsets flag CWR
469  *  @return Previous state of the flag */
unsetCWR()470 bool TCPHeader::unsetCWR(){
471   u8 prev = h.th_flags & TH_CWR;
472   h.th_flags ^= TH_CWR;
473   return prev;
474 } /* End of unsetCWR() */
475 
476 
477 /** Get CWR flag */
getCWR() const478 bool TCPHeader::getCWR() const {
479   return h.th_flags & TH_CWR;
480 } /* End of getCWR() */
481 
482 
483 /** Sets flag ECE/ECN
484  *  @return Previous state of the flag */
setECE()485 bool TCPHeader::setECE(){
486   u8 prev = h.th_flags & TH_ECN;
487   h.th_flags |= TH_ECN;
488   return prev;
489 } /* End of setECE() */
490 
491 
492 /** Unsets flag ECE/ECN
493  *  @return Previous state of the flag */
unsetECE()494 bool TCPHeader::unsetECE(){
495   u8 prev = h.th_flags & TH_ECN;
496   h.th_flags ^= TH_ECN;
497   return prev;
498 } /* End of unsetECE() */
499 
500 
501 /** Get CWR flag */
getECE() const502 bool TCPHeader::getECE() const {
503   return  h.th_flags & TH_ECN;
504 } /* End of getECE() */
505 
506 
507 /** Same as setECE() but with a different name since there are two possible
508  *  ways to call this flag
509  *  @return Previous state of the flag */
setECN()510 bool TCPHeader::setECN(){
511   u8 prev = h.th_flags & TH_ECN;
512   h.th_flags |= TH_ECN;
513   return prev;
514 } /* End of setECN() */
515 
516 
517 /** Unsets flag ECE/ECN
518  *  @return Previous state of the flag */
unsetECN()519 bool TCPHeader::unsetECN(){
520   u8 prev = h.th_flags & TH_ECN;
521   h.th_flags ^= TH_ECN;
522   return prev;
523 } /* End of unsetECN() */
524 
525 
526 /** Get ECN flag */
getECN() const527 bool TCPHeader::getECN() const {
528   return  h.th_flags & TH_ECN;
529 } /* End of getECN() */
530 
531 
532 /** Sets flag URG
533  *  @return Previous state of the flag */
setURG()534 bool TCPHeader::setURG(){
535   u8 prev = h.th_flags & TH_URG;
536   h.th_flags |= TH_URG;
537   return prev;
538 } /* End of setURG() */
539 
540 
541 /** Unsets flag URG
542  *  @return Previous state of the flag */
unsetURG()543 bool TCPHeader::unsetURG(){
544   u8 prev = h.th_flags & TH_URG;
545   h.th_flags ^= TH_URG;
546   return prev;
547 } /* End of unsetURG() */
548 
549 
550 /** Get URG flag */
getURG() const551 bool TCPHeader::getURG() const {
552   return  h.th_flags & TH_URG;
553 } /* End of getURG() */
554 
555 
556 /** Sets flag ACK
557  *  @return Previous state of the flag */
setACK()558 bool TCPHeader::setACK(){
559   u8 prev = h.th_flags & TH_ACK;
560   h.th_flags |= TH_ACK;
561   return prev;
562 } /* End of setACK() */
563 
564 
565 /** Unsets flag ACK
566  *  @return Previous state of the flag */
unsetACK()567 bool TCPHeader::unsetACK(){
568   u8 prev = h.th_flags & TH_ACK;
569   h.th_flags ^= TH_ACK;
570   return prev;
571 } /* End of unsetACK() */
572 
573 
574 /** Get ACK flag */
getACK() const575 bool TCPHeader::getACK() const {
576   return  h.th_flags & TH_ACK;
577 } /* End of getACK() */
578 
579 
580 /** Sets flag PSH
581  *  @return Previous state of the flag */
setPSH()582 bool TCPHeader::setPSH(){
583   u8 prev = h.th_flags & TH_PSH;
584   h.th_flags |= TH_PSH;
585   return prev;
586 } /* End of setPSH() */
587 
588 
589 /** Unsets flag PSH
590  *  @return Previous state of the flag */
unsetPSH()591 bool TCPHeader::unsetPSH(){
592   u8 prev = h.th_flags & TH_PSH;
593   h.th_flags ^= TH_PSH;
594   return prev;
595 } /* End of unsetPSH() */
596 
597 
598 /** Get PSH flag */
getPSH() const599 bool TCPHeader::getPSH() const {
600   return  h.th_flags & TH_PSH;
601 } /* End of getPSH() */
602 
603 
604 /** Sets flag RST
605  *  @return Previous state of the flag */
setRST()606 bool TCPHeader::setRST(){
607   u8 prev = h.th_flags & TH_RST;
608   h.th_flags |= TH_RST;
609   return prev;
610 } /* End of setRST() */
611 
612 
613 /** Unsets flag RST
614  *  @return Previous state of the flag */
unsetRST()615 bool TCPHeader::unsetRST(){
616   u8 prev = h.th_flags & TH_RST;
617   h.th_flags ^= TH_RST;
618   return prev;
619 } /* End of unsetRST() */
620 
621 
622 /** Get RST flag */
getRST() const623 bool TCPHeader::getRST() const {
624   return  h.th_flags & TH_RST;
625 } /* End of getRST() */
626 
627 
628 /** Sets flag SYN
629  *  @return Previous state of the flag */
setSYN()630 bool TCPHeader::setSYN(){
631   u8 prev = h.th_flags & TH_SYN;
632   h.th_flags |= TH_SYN;
633   return prev;
634 } /* End of setSYN() */
635 
636 
637 /** Unsets flag SYN
638  *  @return Previous state of the flag */
unsetSYN()639 bool TCPHeader::unsetSYN(){
640   u8 prev = h.th_flags & TH_SYN;
641   h.th_flags ^= TH_SYN;
642   return prev;
643 } /* End of unsetSYN() */
644 
645 
646 /** Get SYN flag */
getSYN() const647 bool TCPHeader::getSYN() const {
648   return  h.th_flags & TH_SYN;
649 } /* End of getSYN() */
650 
651 
652 /** Sets flag FIN
653  *  @return Previous state of the flag */
setFIN()654 bool TCPHeader::setFIN(){
655   u8 prev = h.th_flags & TH_FIN;
656   h.th_flags |= TH_FIN;
657   return prev;
658 } /* End of setFIN() */
659 
660 
661 /** Unsets flag FIN
662  *  @return Previous state of the flag */
unsetFIN()663 bool TCPHeader::unsetFIN(){
664   u8 prev = h.th_flags & TH_FIN;
665   h.th_flags ^= TH_FIN;
666   return prev;
667 } /* End of unsetFIN() */
668 
669 
670 /** Get FIN flag */
getFIN() const671 bool TCPHeader::getFIN() const {
672   return  h.th_flags & TH_FIN;
673 } /* End of getFIN() */
674 
675 
676 /** Sets window size.
677  *  @warning Win number must be supplied in host byte order. This method
678  *  performs byte order conversion using htons() */
setWindow(u16 p)679 int TCPHeader::setWindow(u16 p){
680    h.th_win = htons(p);
681   return OP_SUCCESS;
682 } /* End of setWindow() */
683 
684 
685 /** Returns window size in HOST byte order. */
getWindow() const686 u16 TCPHeader::getWindow() const {
687   return ntohs(h.th_win);
688 } /* End of getWindow() */
689 
690 
691 /** Sets urgent pointer.
692  *  @warning Pointer must be supplied in host byte order. This method
693  *  performs byte order conversion using htons() */
setUrgPointer(u16 l)694 int TCPHeader::setUrgPointer(u16 l){
695   h.th_urp = htons(l);
696   return OP_SUCCESS;
697 } /* End of setUrgPointer() */
698 
699 
700 /** Returns Urgent Pointer in HOST byte order. */
getUrgPointer() const701 u16 TCPHeader::getUrgPointer() const {
702   return ntohs(h.th_urp);
703 } /* End of getUrgPointer() */
704 
705 
setSum(struct in_addr src,struct in_addr dst)706 int TCPHeader::setSum(struct in_addr src, struct in_addr dst){
707   int bufflen;
708   u8 aux[ MAX_TCP_PAYLOAD_LEN ];
709   /* FROM: RFC 1323: TCP Extensions for High Performance, March 4, 2009
710    *
711    * "With IP Version 4, the largest amount of TCP data that can be sent in
712    *  a single packet is 65495 bytes (64K - 1 - size of fixed IP and TCP
713    *  headers)".
714    *
715    *  In theory TCP should not worry about the practical max payload length
716    *  because it is supposed to be independent of the network layer. However,
717    *  since TCP does not have any length field and we need to allocate a
718    *  buffer, we are using that value. (Note htat in UDPHeader.cc we do just
719    *  the opposite, forget about the practical limitation and allow the
720    *  theorical limit for the payload.                                       */
721   h.th_sum = 0;
722 
723   /* Copy packet contents to a buffer */
724   bufflen=dumpToBinaryBuffer(aux, MAX_TCP_PAYLOAD_LEN);
725 
726   /* Compute checksum */
727   h.th_sum = ipv4_pseudoheader_cksum(&src, &dst, IPPROTO_TCP, bufflen, (char *)aux);
728 
729   return OP_SUCCESS;
730 } /* End of setSum() */
731 
732 
733 /** @warning Sum is set to supplied value with NO byte ordering conversion
734  *  performed. */
setSum(u16 s)735 int TCPHeader::setSum(u16 s){
736   h.th_sum = s;
737   return OP_SUCCESS;
738 } /* End of setSum() */
739 
740 
setSum()741 int TCPHeader::setSum(){
742   this->h.th_sum=0;
743   this->h.th_sum = this->compute_checksum();
744   return OP_SUCCESS;
745 } /* End of setSum() */
746 
747 
748 /** Set the TCP checksum field to a random value, which may accidentally
749   * match the correct checksum */
setSumRandom()750 int TCPHeader::setSumRandom(){
751   h.th_sum=get_random_u16();
752   return OP_SUCCESS;
753 } /* End of setSumRandom() */
754 
755 /** Set the TCP checksum field to a random value. It takes the source and
756   * destination address to make sure the random generated sum does not
757   * accidentally match the correct checksum. This function only handles
758   * IPv4 address. */
setSumRandom(struct in_addr source,struct in_addr destination)759 int TCPHeader::setSumRandom(struct in_addr source, struct in_addr destination){
760   u16 correct_csum=0;
761   /* Compute the correct checksum */
762   this->setSum(source, destination);
763   correct_csum=this->getSum();
764   /* Generate numbers until one does not match the correct sum */
765   while( (h.th_sum=get_random_u16())==correct_csum);
766   return OP_SUCCESS;
767 } /* End of setSumRandom() */
768 
769 
770 /** Returns the TCP checksum field in NETWORK byte order */
getSum() const771 u16 TCPHeader::getSum() const {
772   return h.th_sum;
773 } /* End of getSum() */
774 
775 
776 /* Copies the supplied buffer into the TCP options field. Note that the supplied
777  * buffer MUST NOT exceed MAX_TCP_OPTIONS_LEN octets and should be a multiple of
778  * four. If it is not a multiple of four, no error will be returned but the
779  * behaviour is unspecified. If this method is called passing NULL and zero
780  * ( t.setOptions(NULL, 0), any existing options are cleared, and the object's
781  * internal length is updated accordingly. Also, note that a call to setOptions()
782  * involves an automatic call to setOffset(), which updates the Offset field
783  * to take into account the new header length. If you need to set a bogus
784  * data offset, you can do so after calling setOptions(), but not before.
785  * It returns OP_SUCCESS on success and OP_FAILURE in case of error */
setOptions(const u8 * optsbuff,size_t optslen)786 int TCPHeader::setOptions(const u8 *optsbuff, size_t optslen){
787   /* NULL and length=0 means delete existing options */
788   if(optsbuff==NULL && optslen==0){
789     this->tcpoptlen=0;
790     this->length=TCP_HEADER_LEN;
791     memset(this->h.options, 0, MAX_TCP_OPTIONS_LEN);
792     return OP_SUCCESS;
793 
794   /* Make sure params are safe to use */
795   }else if(optsbuff==NULL || optslen==0 || optslen>MAX_TCP_OPTIONS_LEN){
796     return OP_FAILURE;
797 
798   /* Copy supplied buffer into the options field, and update the offset field. */
799   }else{
800     memcpy(this->h.options, optsbuff, optslen);
801     this->tcpoptlen=optslen;
802     this->length=TCP_HEADER_LEN+optslen;
803     this->setOffset();
804     return OP_SUCCESS;
805   }
806 } /* End of setOptions() */
807 
808 
809 /* Returns a pointer to the start of the TCP options field. If the supplied
810  * "optslen" pointer is not NULL, the length of the options will be stored
811  * there. */
getOptions(size_t * optslen) const812 const u8 *TCPHeader::getOptions(size_t *optslen) const {
813   if(optslen!=NULL)
814     *optslen=this->tcpoptlen;
815   return this->h.options;
816 } /* End of getOptions() */
817 
818 
819 /* Returns the index-th option in the TCP header. On success it returns a
820  * structure filled with option information. If there is no index-th option,
821  * it returns a structure with st.value==NULL. Note that this function does
822  * not perform strict validity checking. It does check that the length claimed
823  * by the options does not exceed the available buffer but it does not check,
824  * for example, that the MSS option always contains a length of 4. Also,
825  * if the returned option type is TCPOPT_EOL or TCPOPT_NOOP, the len field
826  * would be set to zero and the "value" field should NOT be accessed, as it
827  * will not contain reliable information. */
getOption(unsigned int index) const828 nping_tcp_opt_t TCPHeader::getOption(unsigned int index) const {
829   nping_tcp_opt_t *curr_opt=NULL;
830   u8 *curr_pnt=(u8 *)this->h.options;
831   int bytes_left=this->length - TCP_HEADER_LEN;
832   assert((this->length - TCP_HEADER_LEN) == this->tcpoptlen);
833   unsigned int optsfound=0;
834   nping_tcp_opt_t result;
835   memset(&result, 0, sizeof(nping_tcp_opt_t));
836 
837   while(bytes_left>0){
838       /* Use the opts structure as a template to access current option. It is
839        * OK to use it because we only access the first two elements. */
840       curr_opt=(nping_tcp_opt_t *)curr_pnt;
841 
842       /* If we are right in the option that the caller wants, just return it */
843       if(optsfound==index){
844         result.type=curr_opt->type;
845         if(result.type==TCPOPT_EOL || result.type==TCPOPT_NOOP)
846           result.len=1;
847         else
848           result.len=curr_opt->len;
849         result.value=(u8 *)curr_pnt+2;
850         return result;
851       }
852 
853       /* Otherwise, we have to parse it, so we can skip it and access the next
854        * option */
855       switch(curr_opt->type){
856 
857         /* EOL or NOOP
858         +-+-+-+-+-+-+-+-+
859         |       X       |
860         +-+-+-+-+-+-+-+-+  */
861         case TCPOPT_EOL:
862           goto out;
863 
864         case TCPOPT_NOOP:
865           curr_pnt++; /* Skip one octet */
866           bytes_left--;
867         break;
868 
869         /* TLV encoded option */
870         default:
871           /* If we don't have as many octets as the option advertises, the
872            * option is bogus. Return failure. */
873           if(bytes_left<curr_opt->len)
874             return result;
875           curr_pnt+=curr_opt->len;
876           bytes_left-=curr_opt->len;
877         break;
878       }
879       optsfound++;
880   }
881 
882 out:
883   return result;
884 }
885 
886 
887 /* Returns a textual representation of a TCP Options code */
optcode2str(u8 optcode)888 const char *TCPHeader::optcode2str(u8 optcode){
889   switch(optcode){
890     case TCPOPT_EOL:
891       return "EOL";
892     case TCPOPT_NOOP:
893       return "NOOP";
894     case TCPOPT_MSS:
895       return "MSS";
896     case TCPOPT_WSCALE:
897       return "WScale";
898     case TCPOPT_SACKOK:
899      return "SAckOK";
900     case TCPOPT_SACK:
901       return "SAck";
902     case TCPOPT_ECHOREQ:
903      return "EchoReq";
904     case TCPOPT_ECHOREP:
905      return "EchoRep";
906     case TCPOPT_TSTAMP:
907      return "TStamp";
908     case TCPOPT_POCP:
909       return "POCP";
910     case TCPOPT_POSP:
911      return "POSP";
912     case TCPOPT_CC:
913      return "CC";
914     case TCPOPT_CCNEW:
915      return "CC.NEW";
916     case TCPOPT_CCECHO:
917      return "CC.ECHO";
918     case TCPOPT_ALTCSUMREQ:
919       return "AltSumReq";
920     case TCPOPT_ALTCSUMDATA:
921      return "AltSumData";
922     case TCPOPT_MD5:
923       return "MD5";
924     case TCPOPT_SCPS:
925       return "SCPS";
926     case TCPOPT_SNACK:
927       return "SNAck";
928     case TCPOPT_QSRES:
929      return "QStart";
930     case TCPOPT_UTO:
931      return "UTO";
932     case TCPOPT_AO:
933      return "AO";
934     default:
935       return "Unknown";
936   }
937 } /* End of optcode2str() */
938 
939 
940