A Discrete-Event Network Simulator
API
tcp-header.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 Georgia Tech Research Corporation
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Raj Bhattacharjea <raj.b@gatech.edu>
19  */
20 
21 #include <stdint.h>
22 #include <iostream>
23 #include "tcp-header.h"
24 #include "tcp-option.h"
25 #include "ns3/buffer.h"
26 #include "ns3/address-utils.h"
27 #include "ns3/log.h"
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("TcpHeader");
32 
33 NS_OBJECT_ENSURE_REGISTERED (TcpHeader);
34 
36  : m_sourcePort (0),
37  m_destinationPort (0),
38  m_sequenceNumber (0),
39  m_ackNumber (0),
40  m_length (5),
41  m_flags (0),
42  m_windowSize (0xffff),
43  m_urgentPointer (0),
44  m_calcChecksum (false),
45  m_goodChecksum (true),
46  m_optionsLen (0)
47 {
48 }
49 
51 {
52 }
53 
54 std::string
55 TcpHeader::FlagsToString (uint8_t flags, const std::string& delimiter)
56 {
57  static const char* flagNames[8] = {
58  "FIN",
59  "SYN",
60  "RST",
61  "PSH",
62  "ACK",
63  "URG",
64  "ECE",
65  "CWR"
66  };
67  std::string flagsDescription = "";
68  for (uint8_t i = 0; i < 8; ++i)
69  {
70  if (flags & (1 << i))
71  {
72  if (flagsDescription.length() > 0)
73  {
74  flagsDescription += delimiter;
75  }
76  flagsDescription.append (flagNames[i]);
77  }
78  }
79  return flagsDescription;
80 }
81 
82 void
84 {
85  m_calcChecksum = true;
86 }
87 
88 void
90 {
92 }
93 
94 void
96 {
98 }
99 
100 void
102 {
103  m_sequenceNumber = sequenceNumber;
104 }
105 
106 void
108 {
109  m_ackNumber = ackNumber;
110 }
111 
112 void
113 TcpHeader::SetFlags (uint8_t flags)
114 {
115  m_flags = flags;
116 }
117 
118 void
119 TcpHeader::SetWindowSize (uint16_t windowSize)
120 {
121  m_windowSize = windowSize;
122 }
123 
124 void
125 TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
126 {
127  m_urgentPointer = urgentPointer;
128 }
129 
130 uint16_t
132 {
133  return m_sourcePort;
134 }
135 
136 uint16_t
138 {
139  return m_destinationPort;
140 }
141 
144 {
145  return m_sequenceNumber;
146 }
147 
150 {
151  return m_ackNumber;
152 }
153 
154 uint8_t
156 {
157  return m_length;
158 }
159 
160 uint8_t
162 {
163  return m_flags;
164 }
165 
166 uint16_t
168 {
169  return m_windowSize;
170 }
171 
172 uint16_t
174 {
175  return m_urgentPointer;
176 }
177 
178 void
180  Ipv4Address destination,
181  uint8_t protocol)
182 {
183  m_source = source;
184  m_destination = destination;
185  m_protocol = protocol;
186 }
187 
188 void
190  Ipv6Address destination,
191  uint8_t protocol)
192 {
193  m_source = source;
194  m_destination = destination;
195  m_protocol = protocol;
196 }
197 
198 void
200  Address destination,
201  uint8_t protocol)
202 {
203  m_source = source;
204  m_destination = destination;
205  m_protocol = protocol;
206 }
207 
208 uint16_t
210 {
211  /* Buffer size must be at least as large as the largest IP pseudo-header */
212  /* [per RFC2460, but without consideration for IPv6 extension hdrs] */
213  /* Src address 16 bytes (more generally, Address::MAX_SIZE) */
214  /* Dst address 16 bytes (more generally, Address::MAX_SIZE) */
215  /* Upper layer pkt len 4 bytes */
216  /* Zero 3 bytes */
217  /* Next header 1 byte */
218 
219  uint32_t maxHdrSz = (2 * Address::MAX_SIZE) + 8;
220  Buffer buf = Buffer (maxHdrSz);
221  buf.AddAtStart (maxHdrSz);
222  Buffer::Iterator it = buf.Begin ();
223  uint32_t hdrSize = 0;
224 
225  WriteTo (it, m_source);
226  WriteTo (it, m_destination);
228  {
229  it.WriteU8 (0); /* protocol */
230  it.WriteU8 (m_protocol); /* protocol */
231  it.WriteU8 (size >> 8); /* length */
232  it.WriteU8 (size & 0xff); /* length */
233  hdrSize = 12;
234  }
235  else
236  {
237  it.WriteU16 (0);
238  it.WriteU8 (size >> 8); /* length */
239  it.WriteU8 (size & 0xff); /* length */
240  it.WriteU16 (0);
241  it.WriteU8 (0);
242  it.WriteU8 (m_protocol); /* protocol */
243  hdrSize = 40;
244  }
245 
246  it = buf.Begin ();
247  /* we don't CompleteChecksum ( ~ ) now */
248  return ~(it.CalculateIpChecksum (hdrSize));
249 }
250 
251 bool
253 {
254  return m_goodChecksum;
255 }
256 
257 TypeId
259 {
260  static TypeId tid = TypeId ("ns3::TcpHeader")
261  .SetParent<Header> ()
262  .SetGroupName ("Internet")
263  .AddConstructor<TcpHeader> ()
264  ;
265  return tid;
266 }
267 
268 TypeId
270 {
271  return GetTypeId ();
272 }
273 
274 void
275 TcpHeader::Print (std::ostream &os) const
276 {
277  os << m_sourcePort << " > " << m_destinationPort;
278 
279  if (m_flags != 0)
280  {
281  os<<" [" << FlagsToString(m_flags) <<"]";
282  }
283 
284  os<<" Seq="<<m_sequenceNumber<<" Ack="<<m_ackNumber<<" Win="<<m_windowSize;
285 
286  TcpOptionList::const_iterator op;
287 
288  for (op = m_options.begin (); op != m_options.end (); ++op)
289  {
290  os << " " << (*op)->GetInstanceTypeId ().GetName () << "(";
291  (*op)->Print (os);
292  os << ")";
293  }
294 }
295 
296 uint32_t
298 {
299  return CalculateHeaderLength () * 4;
300 }
301 
302 void
304 {
310  i.WriteHtonU16 (GetLength () << 12 | m_flags); //reserved bits are all zero
312  i.WriteHtonU16 (0);
314 
315  // Serialize options if they exist
316  // This implementation does not presently try to align options on word
317  // boundaries using NOP options
318  uint32_t optionLen = 0;
319  TcpOptionList::const_iterator op;
320  for (op = m_options.begin (); op != m_options.end (); ++op)
321  {
322  optionLen += (*op)->GetSerializedSize ();
323  (*op)->Serialize (i);
324  i.Next ((*op)->GetSerializedSize ());
325  }
326 
327  // padding to word alignment; add ENDs and/or pad values (they are the same)
328  while (optionLen % 4)
329  {
331  ++optionLen;
332  }
333 
334  // Make checksum
335  if(m_calcChecksum)
336  {
337  uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
338  i = start;
339  uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
340 
341  i = start;
342  i.Next (16);
343  i.WriteU16 (checksum);
344  }
345 }
346 
347 uint32_t
349 {
351  m_sourcePort = i.ReadNtohU16 ();
354  m_ackNumber = i.ReadNtohU32 ();
355  uint16_t field = i.ReadNtohU16 ();
356  m_flags = field & 0x3F;
357  m_length = field>>12;
358  m_windowSize = i.ReadNtohU16 ();
359  i.Next (2);
361 
362  // Deserialize options if they exist
363  m_options.clear ();
364  uint32_t optionLen = (m_length - 5) * 4;
365  if (optionLen > 40)
366  {
367  NS_LOG_ERROR ("Illegal TCP option length " << optionLen << "; options discarded");
368  return 20;
369  }
370  while (optionLen)
371  {
372  uint8_t kind = i.PeekU8 ();
373  Ptr<TcpOption> op;
374  uint32_t optionSize;
375  if (TcpOption::IsKindKnown (kind))
376  {
377  op = TcpOption::CreateOption (kind);
378  }
379  else
380  {
382  NS_LOG_WARN ("Option kind " << static_cast<int> (kind) << " unknown, skipping.");
383  }
384  optionSize = op->Deserialize (i);
385  if (optionSize != op->GetSerializedSize ())
386  {
387  NS_LOG_ERROR ("Option did not deserialize correctly");
388  break;
389  }
390  if (optionLen >= optionSize)
391  {
392  optionLen -= optionSize;
393  i.Next (optionSize);
394  m_options.push_back (op);
395  }
396  else
397  {
398  NS_LOG_ERROR ("Option exceeds TCP option space; option discarded");
399  break;
400  }
401  if (op->GetKind () == TcpOption::END)
402  {
403  while (optionLen)
404  {
405  // Discard padding bytes without adding to option list
406  i.Next (1);
407  --optionLen;
408  }
409  }
410  }
411 
413  {
414  NS_LOG_ERROR ("Mismatch between calculated length and in-header value");
415  }
416 
417  // Do checksum
418  if(m_calcChecksum)
419  {
420  uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
421  i = start;
422  uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
423  m_goodChecksum = (checksum == 0);
424  }
425 
426  return GetSerializedSize ();
427 }
428 
429 uint8_t
431 {
432  uint32_t len = 20;
433  TcpOptionList::const_iterator i;
434 
435  for (i = m_options.begin (); i != m_options.end (); ++i)
436  {
437  len += (*i)->GetSerializedSize ();
438  }
439  // Option list may not include padding; need to pad up to word boundary
440  if (len % 4)
441  {
442  len += 4 - (len % 4);
443  }
444  return len >> 2;
445 }
446 
447 bool
449 {
450  if (m_optionsLen + option->GetSerializedSize () <= m_maxOptionsLen)
451  {
452  if (!TcpOption::IsKindKnown (option->GetKind ()))
453  {
454  NS_LOG_WARN ("The option kind " << static_cast<int> (option->GetKind ()) << " is unknown");
455  return false;
456  }
457 
458  if (option->GetKind () != TcpOption::END)
459  {
460  m_options.push_back (option);
461  m_optionsLen += option->GetSerializedSize ();
462 
463  uint32_t totalLen = 20 + 3 + m_optionsLen;
464  m_length = totalLen >> 2;
465  }
466 
467  return true;
468  }
469 
470  return false;
471 }
472 
474 TcpHeader::GetOption (uint8_t kind) const
475 {
476  TcpOptionList::const_iterator i;
477 
478  for (i = m_options.begin (); i != m_options.end (); ++i)
479  {
480  if ((*i)->GetKind () == kind)
481  {
482  return (*i);
483  }
484  }
485 
486  return 0;
487 }
488 
489 bool
490 TcpHeader::HasOption (uint8_t kind) const
491 {
492  TcpOptionList::const_iterator i;
493 
494  for (i = m_options.begin (); i != m_options.end (); ++i)
495  {
496  if ((*i)->GetKind () == kind)
497  {
498  return true;
499  }
500  }
501 
502  return false;
503 }
504 
505 bool
506 operator== (const TcpHeader &lhs, const TcpHeader &rhs)
507 {
508  return (
509  lhs.m_sourcePort == rhs.m_sourcePort &&
511  lhs.m_sequenceNumber == rhs.m_sequenceNumber &&
512  lhs.m_ackNumber == rhs.m_ackNumber &&
513  lhs.m_flags == rhs.m_flags &&
514  lhs.m_windowSize == rhs.m_windowSize &&
516  );
517 }
518 
519 } // namespace ns3
Protocol header serialization and deserialization.
Definition: header.h:42
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1162
static std::string FlagsToString(uint8_t flags, const std::string &delimiter="|")
Converts an integer into a human readable list of Tcp flags.
Definition: tcp-header.cc:55
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
void InitializeChecksum(Ipv4Address source, Ipv4Address destination, uint8_t protocol)
Initialize the TCP checksum.
Definition: tcp-header.cc:179
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:161
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
automatically resized byte buffer
Definition: buffer.h:92
static const uint8_t m_maxOptionsLen
Maximum options length.
Definition: tcp-header.h:326
def start()
Definition: core.py:1482
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Address m_source
Source IP address.
Definition: tcp-header.h:315
uint32_t ReadNtohU32(void)
Definition: buffer.h:977
uint16_t m_destinationPort
Destination port.
Definition: tcp-header.h:307
uint8_t CalculateHeaderLength() const
Calculates the header length (in words)
Definition: tcp-header.cc:430
bool m_calcChecksum
Flag to calculate checksum.
Definition: tcp-header.h:319
uint16_t port
Definition: dsdv-manet.cc:44
iterator in a Buffer instance
Definition: buffer.h:98
a polymophic address class
Definition: address.h:90
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the Option from a buffer iterator.
virtual void Print(std::ostream &os) const
Definition: tcp-header.cc:275
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:448
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:167
void WriteU16(uint16_t data)
Definition: buffer.cc:899
void WriteHtonU16(uint16_t data)
Definition: buffer.h:912
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Definition: tcp-header.cc:269
uint16_t CalculateHeaderChecksum(uint16_t size) const
Calculate the header checksum.
Definition: tcp-header.cc:209
void Next(void)
go forward by one byte
Definition: buffer.h:852
static bool IsMatchingType(const Address &address)
Buffer::Iterator Begin(void) const
Definition: buffer.h:1076
bool m_goodChecksum
Flag to indicate that checksum is correct.
Definition: tcp-header.h:320
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
uint16_t m_windowSize
Window size.
Definition: tcp-header.h:312
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t m_sourcePort
Source port.
Definition: tcp-header.h:306
uint8_t m_optionsLen
Tcp options length.
Definition: tcp-header.h:325
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
virtual ~TcpHeader()
Definition: tcp-header.cc:50
Address m_destination
Destination IP address.
Definition: tcp-header.h:316
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:125
void WriteHtonU32(uint32_t data)
Definition: buffer.h:931
not a standardized value; for unknown recv'd options
Definition: tcp-option.h:60
virtual uint32_t GetSerializedSize(void) const
Definition: tcp-header.cc:297
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:155
uint8_t m_protocol
Protocol number.
Definition: tcp-header.h:317
Ptr< TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:474
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:348
uint16_t m_urgentPointer
Urgent pointer.
Definition: tcp-header.h:313
Describes an IPv6 address.
Definition: ipv6-address.h:47
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
SequenceNumber32 m_ackNumber
ACK number.
Definition: tcp-header.h:309
uint8_t m_flags
Flags (really a uint6_t)
Definition: tcp-header.h:311
void WriteU8(uint8_t data)
Definition: buffer.h:876
static bool IsKindKnown(uint8_t kind)
Check if the option is implemented.
Definition: tcp-option.cc:95
uint8_t m_length
Length (really a uint4_t) in words.
Definition: tcp-header.h:310
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
virtual uint8_t GetKind(void) const =0
Get the `kind' (as in RFC 793) of this option.
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.cc:95
uint8_t PeekU8(void)
Definition: buffer.h:1005
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:220
bool AddAtStart(uint32_t start)
Definition: buffer.cc:309
bool IsChecksumOk(void) const
Is the TCP checksum correct ?
Definition: tcp-header.cc:252
void EnableChecksums(void)
Enable checksum calculation for TCP.
Definition: tcp-header.cc:83
TcpOptionList m_options
TcpOption present in the header.
Definition: tcp-header.h:324
uint16_t ReadNtohU16(void)
Definition: buffer.h:953
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:490
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
uint32_t GetSize(void) const
Definition: buffer.cc:1187
a unique identifier for an interface.
Definition: type-id.h:57
static Ptr< TcpOption > CreateOption(uint8_t kind)
Creates an option.
Definition: tcp-option.cc:63
TypeId SetParent(TypeId tid)
Definition: type-id.cc:638
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:173
virtual uint32_t GetSerializedSize(void) const =0
Returns number of bytes required for Option serialization.
virtual void Serialize(Buffer::Iterator start) const
Definition: tcp-header.cc:303
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-header.cc:258
SequenceNumber32 m_sequenceNumber
Sequence number.
Definition: tcp-header.h:308