A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("TcpHeader");
30 
31 namespace ns3 {
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 void
56 {
57  m_calcChecksum = true;
58 }
59 
60 void
62 {
64 }
65 
66 void
68 {
70 }
71 
72 void
74 {
75  m_sequenceNumber = sequenceNumber;
76 }
77 
78 void
80 {
81  m_ackNumber = ackNumber;
82 }
83 
84 void
85 TcpHeader::SetFlags (uint8_t flags)
86 {
87  m_flags = flags;
88 }
89 
90 void
91 TcpHeader::SetWindowSize (uint16_t windowSize)
92 {
93  m_windowSize = windowSize;
94 }
95 
96 void
97 TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
98 {
99  m_urgentPointer = urgentPointer;
100 }
101 
102 uint16_t
104 {
105  return m_sourcePort;
106 }
107 
108 uint16_t
110 {
111  return m_destinationPort;
112 }
113 
116 {
117  return m_sequenceNumber;
118 }
119 
122 {
123  return m_ackNumber;
124 }
125 
126 uint8_t
128 {
129  return m_length;
130 }
131 
132 uint8_t
134 {
135  return m_flags;
136 }
137 
138 uint16_t
140 {
141  return m_windowSize;
142 }
143 
144 uint16_t
146 {
147  return m_urgentPointer;
148 }
149 
150 void
152  Ipv4Address destination,
153  uint8_t protocol)
154 {
155  m_source = source;
156  m_destination = destination;
157  m_protocol = protocol;
158 }
159 
160 void
162  Ipv6Address destination,
163  uint8_t protocol)
164 {
165  m_source = source;
166  m_destination = destination;
167  m_protocol = protocol;
168 }
169 
170 void
172  Address destination,
173  uint8_t protocol)
174 {
175  m_source = source;
176  m_destination = destination;
177  m_protocol = protocol;
178 }
179 
180 uint16_t
182 {
183  /* Buffer size must be at least as large as the largest IP pseudo-header */
184  /* [per RFC2460, but without consideration for IPv6 extension hdrs] */
185  /* Src address 16 bytes (more generally, Address::MAX_SIZE) */
186  /* Dst address 16 bytes (more generally, Address::MAX_SIZE) */
187  /* Upper layer pkt len 4 bytes */
188  /* Zero 3 bytes */
189  /* Next header 1 byte */
190 
191  uint32_t maxHdrSz = (2 * Address::MAX_SIZE) + 8;
192  Buffer buf = Buffer (maxHdrSz);
193  buf.AddAtStart (maxHdrSz);
194  Buffer::Iterator it = buf.Begin ();
195  uint32_t hdrSize = 0;
196 
197  WriteTo (it, m_source);
198  WriteTo (it, m_destination);
200  {
201  it.WriteU8 (0); /* protocol */
202  it.WriteU8 (m_protocol); /* protocol */
203  it.WriteU8 (size >> 8); /* length */
204  it.WriteU8 (size & 0xff); /* length */
205  hdrSize = 12;
206  }
207  else
208  {
209  it.WriteU16 (0);
210  it.WriteU8 (size >> 8); /* length */
211  it.WriteU8 (size & 0xff); /* length */
212  it.WriteU16 (0);
213  it.WriteU8 (0);
214  it.WriteU8 (m_protocol); /* protocol */
215  hdrSize = 40;
216  }
217 
218  it = buf.Begin ();
219  /* we don't CompleteChecksum ( ~ ) now */
220  return ~(it.CalculateIpChecksum (hdrSize));
221 }
222 
223 bool
225 {
226  return m_goodChecksum;
227 }
228 
229 TypeId
231 {
232  static TypeId tid = TypeId ("ns3::TcpHeader")
233  .SetParent<Header> ()
234  .AddConstructor<TcpHeader> ()
235  ;
236  return tid;
237 }
238 
239 TypeId
241 {
242  return GetTypeId ();
243 }
244 
245 void
246 TcpHeader::Print (std::ostream &os) const
247 {
248  os << m_sourcePort << " > " << m_destinationPort;
249 
250  if (m_flags != 0)
251  {
252  os<<" [";
253  if ((m_flags & FIN) != 0)
254  {
255  os<<" FIN ";
256  }
257  if ((m_flags & SYN) != 0)
258  {
259  os<<" SYN ";
260  }
261  if ((m_flags & RST) != 0)
262  {
263  os<<" RST ";
264  }
265  if ((m_flags & PSH) != 0)
266  {
267  os<<" PSH ";
268  }
269  if ((m_flags & ACK) != 0)
270  {
271  os<<" ACK ";
272  }
273  if ((m_flags & URG) != 0)
274  {
275  os<<" URG ";
276  }
277  if ((m_flags & ECE) != 0)
278  {
279  os<<" ECE ";
280  }
281  if ((m_flags & CWR) != 0)
282  {
283  os<<" CWR ";
284  }
285 
286  os<<"]";
287  }
288 
289  os<<" Seq="<<m_sequenceNumber<<" Ack="<<m_ackNumber<<" Win="<<m_windowSize;
290 
291  TcpOptionList::const_iterator op;
292 
293  for (op = m_options.begin (); op != m_options.end (); ++op)
294  {
295  os << " " << (*op)->GetInstanceTypeId ().GetName () << "(";
296  (*op)->Print (os);
297  os << ")";
298  }
299 }
300 
301 uint32_t
303 {
304  return CalculateHeaderLength () * 4;
305 }
306 
307 void
309 {
315  i.WriteHtonU16 (GetLength () << 12 | m_flags); //reserved bits are all zero
317  i.WriteHtonU16 (0);
319 
320  // Serialize options if they exist
321  // This implementation does not presently try to align options on word
322  // boundaries using NOP options
323  uint32_t optionLen = 0;
324  TcpOptionList::const_iterator op;
325  for (op = m_options.begin (); op != m_options.end (); ++op)
326  {
327  optionLen += (*op)->GetSerializedSize ();
328  (*op)->Serialize (i);
329  i.Next ((*op)->GetSerializedSize ());
330  }
331 
332  // padding to word alignment; add ENDs and/or pad values (they are the same)
333  while (optionLen % 4)
334  {
336  ++optionLen;
337  }
338 
339  // Make checksum
340  if(m_calcChecksum)
341  {
342  uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
343  i = start;
344  uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
345 
346  i = start;
347  i.Next (16);
348  i.WriteU16 (checksum);
349  }
350 }
351 
352 uint32_t
354 {
356  m_sourcePort = i.ReadNtohU16 ();
359  m_ackNumber = i.ReadNtohU32 ();
360  uint16_t field = i.ReadNtohU16 ();
361  m_flags = field & 0x3F;
362  m_length = field>>12;
363  m_windowSize = i.ReadNtohU16 ();
364  i.Next (2);
366 
367  // Deserialize options if they exist
368  m_options.clear ();
369  uint32_t optionLen = (m_length - 5) * 4;
370  if (optionLen > 40)
371  {
372  NS_LOG_ERROR ("Illegal TCP option length " << optionLen << "; options discarded");
373  return 20;
374  }
375  while (optionLen)
376  {
377  uint8_t kind = i.PeekU8 ();
378  Ptr<TcpOption> op;
379  uint32_t optionSize;
380  if (TcpOption::IsKindKnown (kind))
381  {
382  op = TcpOption::CreateOption (kind);
383  }
384  else
385  {
387  NS_LOG_WARN ("Option kind " << static_cast<int> (kind) << " unknown, skipping.");
388  }
389  optionSize = op->Deserialize (i);
390  if (optionSize != op->GetSerializedSize ())
391  {
392  NS_LOG_ERROR ("Option did not deserialize correctly");
393  break;
394  }
395  if (optionLen >= optionSize)
396  {
397  optionLen -= optionSize;
398  i.Next (optionSize);
399  m_options.push_back (op);
400  }
401  else
402  {
403  NS_LOG_ERROR ("Option exceeds TCP option space; option discarded");
404  break;
405  }
406  if (op->GetKind () == TcpOption::END)
407  {
408  while (optionLen)
409  {
410  // Discard padding bytes without adding to option list
411  i.Next (1);
412  --optionLen;
413  }
414  }
415  }
416 
418  {
419  NS_LOG_ERROR ("Mismatch between calculated length and in-header value");
420  }
421 
422  // Do checksum
423  if(m_calcChecksum)
424  {
425  uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
426  i = start;
427  uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
428  m_goodChecksum = (checksum == 0);
429  }
430 
431  return GetSerializedSize ();
432 }
433 
434 uint8_t
436 {
437  uint32_t len = 20;
438  TcpOptionList::const_iterator i;
439 
440  for (i = m_options.begin (); i != m_options.end (); ++i)
441  {
442  len += (*i)->GetSerializedSize ();
443  }
444  // Option list may not include padding; need to pad up to word boundary
445  if (len % 4)
446  {
447  len += 4 - (len % 4);
448  }
449  return len >> 2;
450 }
451 
452 bool
454 {
455  if (m_optionsLen + option->GetSerializedSize () <= m_maxOptionsLen)
456  {
457  if (!TcpOption::IsKindKnown (option->GetKind ()))
458  {
459  NS_LOG_WARN ("The option kind " << static_cast<int> (option->GetKind ()) << " is unknown");
460  return false;
461  }
462 
463  if (option->GetKind () != TcpOption::END)
464  {
465  m_options.push_back (option);
466  m_optionsLen += option->GetSerializedSize ();
467 
468  uint32_t totalLen = 20 + 3 + m_optionsLen;
469  m_length = totalLen >> 2;
470  }
471 
472  return true;
473  }
474 
475  return false;
476 }
477 
479 TcpHeader::GetOption (uint8_t kind) const
480 {
481  TcpOptionList::const_iterator i;
482 
483  for (i = m_options.begin (); i != m_options.end (); ++i)
484  {
485  if ((*i)->GetKind () == kind)
486  {
487  return (*i);
488  }
489  }
490 
491  return 0;
492 }
493 
494 bool
495 TcpHeader::HasOption (uint8_t kind) const
496 {
497  TcpOptionList::const_iterator i;
498 
499  for (i = m_options.begin (); i != m_options.end (); ++i)
500  {
501  if ((*i)->GetKind () == kind)
502  {
503  return true;
504  }
505  }
506 
507  return false;
508 }
509 
510 bool
511 operator== (const TcpHeader &lhs, const TcpHeader &rhs)
512 {
513  return (
514  lhs.m_sourcePort == rhs.m_sourcePort &&
516  lhs.m_sequenceNumber == rhs.m_sequenceNumber &&
517  lhs.m_ackNumber == rhs.m_ackNumber &&
518  lhs.m_flags == rhs.m_flags &&
519  lhs.m_windowSize == rhs.m_windowSize &&
521  );
522 }
523 
524 } // namespace ns3
Protocol header serialization and deserialization.
Definition: header.h:42
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1162
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:109
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:115
void InitializeChecksum(Ipv4Address source, Ipv4Address destination, uint8_t protocol)
Initialize the TCP checksum.
Definition: tcp-header.cc:151
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:133
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:121
automatically resized byte buffer
Definition: buffer.h:92
static const uint8_t m_maxOptionsLen
Maximum options length.
Definition: tcp-header.h:302
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:170
Address m_source
Source IP address.
Definition: tcp-header.h:291
uint32_t ReadNtohU32(void)
Definition: buffer.h:977
uint16_t m_destinationPort
Destination port.
Definition: tcp-header.h:283
uint8_t CalculateHeaderLength() const
Calculates the header length (in words)
Definition: tcp-header.cc:435
bool m_calcChecksum
Flag to calculate checksum.
Definition: tcp-header.h:295
uint16_t port
Definition: dsdv-manet.cc:44
iterator in a Buffer instance
Definition: buffer.h:98
a polymophic address class
Definition: address.h:86
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:246
bool AppendOption(Ptr< TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:453
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:73
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:139
void WriteU16(uint16_t data)
Definition: buffer.cc:899
void WriteHtonU16(uint16_t data)
Definition: buffer.h:912
virtual TypeId GetInstanceTypeId(void) const
Definition: tcp-header.cc:240
uint16_t CalculateHeaderChecksum(uint16_t size) const
Calculate the header checksum.
Definition: tcp-header.cc:181
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:296
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:67
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:85
uint16_t m_windowSize
Window size.
Definition: tcp-header.h:288
uint16_t m_sourcePort
Source port.
Definition: tcp-header.h:282
uint8_t m_optionsLen
Tcp options length.
Definition: tcp-header.h:301
Header for the Transmission Control Protocol.
Definition: tcp-header.h:44
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:61
virtual ~TcpHeader()
Definition: tcp-header.cc:50
Address m_destination
Destination IP address.
Definition: tcp-header.h:292
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:97
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:302
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:127
uint8_t m_protocol
Protocol number.
Definition: tcp-header.h:293
Ptr< TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:479
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:353
uint16_t m_urgentPointer
Urgent pointer.
Definition: tcp-header.h:289
Describes an IPv6 address.
Definition: ipv6-address.h:46
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
SequenceNumber32 m_ackNumber
ACK number.
Definition: tcp-header.h:285
uint8_t m_flags
Flags (really a uint6_t)
Definition: tcp-header.h:287
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:94
uint8_t m_length
Length (really a uint4_t) in words.
Definition: tcp-header.h:286
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:203
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:79
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:89
uint8_t PeekU8(void)
Definition: buffer.h:1005
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:103
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:193
bool AddAtStart(uint32_t start)
Definition: buffer.cc:309
bool IsChecksumOk(void) const
Is the TCP checksum correct ?
Definition: tcp-header.cc:224
void EnableChecksums(void)
Enable checksum calculation for TCP.
Definition: tcp-header.cc:55
TcpOptionList m_options
TcpOption present in the header.
Definition: tcp-header.h:300
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:495
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:91
uint32_t GetSize(void) const
Definition: buffer.cc:1187
a unique identifier for an interface.
Definition: type-id.h:49
static Ptr< TcpOption > CreateOption(uint8_t kind)
Creates an option.
Definition: tcp-option.cc:62
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:145
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:308
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-header.cc:230
SequenceNumber32 m_sequenceNumber
Sequence number.
Definition: tcp-header.h:284