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
29namespace ns3 {
30
31NS_LOG_COMPONENT_DEFINE ("TcpHeader");
32
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
54std::string
55TcpHeader::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
82void
84{
85 m_calcChecksum = true;
86}
87
88void
90{
92}
93
94void
96{
98}
99
100void
102{
103 m_sequenceNumber = sequenceNumber;
104}
105
106void
108{
109 m_ackNumber = ackNumber;
110}
111
112void
113TcpHeader::SetFlags (uint8_t flags)
114{
115 m_flags = flags;
116}
117
118void
119TcpHeader::SetWindowSize (uint16_t windowSize)
120{
121 m_windowSize = windowSize;
122}
123
124void
125TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
126{
127 m_urgentPointer = urgentPointer;
128}
129
130uint16_t
132{
133 return m_sourcePort;
134}
135
136uint16_t
138{
139 return m_destinationPort;
140}
141
144{
145 return m_sequenceNumber;
146}
147
150{
151 return m_ackNumber;
152}
153
154uint8_t
156{
157 return m_length;
158}
159
160uint8_t
162{
163 return m_optionsLen;
164}
165
166uint8_t
168{
169 return m_maxOptionsLen;
170}
171
172uint8_t
174{
175 return m_flags;
176}
177
178uint16_t
180{
181 return m_windowSize;
182}
183
184uint16_t
186{
187 return m_urgentPointer;
188}
189
190void
192 const Ipv4Address &destination,
193 uint8_t protocol)
194{
195 m_source = source;
196 m_destination = destination;
197 m_protocol = protocol;
198}
199
200void
202 const Ipv6Address &destination,
203 uint8_t protocol)
204{
205 m_source = source;
206 m_destination = destination;
207 m_protocol = protocol;
208}
209
210void
212 const Address &destination,
213 uint8_t protocol)
214{
215 m_source = source;
216 m_destination = destination;
217 m_protocol = protocol;
218}
219
220uint16_t
222{
223 /* Buffer size must be at least as large as the largest IP pseudo-header */
224 /* [per RFC2460, but without consideration for IPv6 extension hdrs] */
225 /* Src address 16 bytes (more generally, Address::MAX_SIZE) */
226 /* Dst address 16 bytes (more generally, Address::MAX_SIZE) */
227 /* Upper layer pkt len 4 bytes */
228 /* Zero 3 bytes */
229 /* Next header 1 byte */
230
231 uint32_t maxHdrSz = (2 * Address::MAX_SIZE) + 8;
232 Buffer buf = Buffer (maxHdrSz);
233 buf.AddAtStart (maxHdrSz);
234 Buffer::Iterator it = buf.Begin ();
235 uint32_t hdrSize = 0;
236
237 WriteTo (it, m_source);
240 {
241 it.WriteU8 (0); /* protocol */
242 it.WriteU8 (m_protocol); /* protocol */
243 it.WriteU8 (size >> 8); /* length */
244 it.WriteU8 (size & 0xff); /* length */
245 hdrSize = 12;
246 }
247 else
248 {
249 it.WriteU16 (0);
250 it.WriteU8 (size >> 8); /* length */
251 it.WriteU8 (size & 0xff); /* length */
252 it.WriteU16 (0);
253 it.WriteU8 (0);
254 it.WriteU8 (m_protocol); /* protocol */
255 hdrSize = 40;
256 }
257
258 it = buf.Begin ();
259 /* we don't CompleteChecksum ( ~ ) now */
260 return ~(it.CalculateIpChecksum (hdrSize));
261}
262
263bool
265{
266 return m_goodChecksum;
267}
268
269TypeId
271{
272 static TypeId tid = TypeId ("ns3::TcpHeader")
273 .SetParent<Header> ()
274 .SetGroupName ("Internet")
275 .AddConstructor<TcpHeader> ()
276 ;
277 return tid;
278}
279
280TypeId
282{
283 return GetTypeId ();
284}
285
286void
287TcpHeader::Print (std::ostream &os) const
288{
289 os << m_sourcePort << " > " << m_destinationPort;
290
291 if (m_flags != 0)
292 {
293 os << " [" << FlagsToString (m_flags) << "]";
294 }
295
296 os << " Seq=" << m_sequenceNumber << " Ack=" << m_ackNumber << " Win=" << m_windowSize;
297
298 TcpOptionList::const_iterator op;
299
300 for (op = m_options.begin (); op != m_options.end (); ++op)
301 {
302 os << " " << (*op)->GetInstanceTypeId ().GetName () << "(";
303 (*op)->Print (os);
304 os << ")";
305 }
306}
307
310{
311 return CalculateHeaderLength () * 4;
312}
313
314void
316{
322 i.WriteHtonU16 (GetLength () << 12 | m_flags); //reserved bits are all zero
324 i.WriteHtonU16 (0);
326
327 // Serialize options if they exist
328 // This implementation does not presently try to align options on word
329 // boundaries using NOP options
330 uint32_t optionLen = 0;
331 TcpOptionList::const_iterator op;
332 for (op = m_options.begin (); op != m_options.end (); ++op)
333 {
334 optionLen += (*op)->GetSerializedSize ();
335 (*op)->Serialize (i);
336 i.Next ((*op)->GetSerializedSize ());
337 }
338
339 // padding to word alignment; add ENDs and/or pad values (they are the same)
340 while (optionLen % 4)
341 {
343 ++optionLen;
344 }
345
346 // Make checksum
347 if (m_calcChecksum)
348 {
349 uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
350 i = start;
351 uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
352
353 i = start;
354 i.Next (16);
355 i.WriteU16 (checksum);
356 }
357}
358
361{
362 m_optionsLen = 0;
368 uint16_t field = i.ReadNtohU16 ();
369 m_flags = field & 0xFF;
370 m_length = field >> 12;
372 i.Next (2);
374
375 // Deserialize options if they exist
376 m_options.clear ();
377 uint32_t optionLen = (m_length - 5) * 4;
378 if (optionLen > m_maxOptionsLen)
379 {
380 NS_LOG_ERROR ("Illegal TCP option length " << optionLen << "; options discarded");
381 return 20;
382 }
383 while (optionLen)
384 {
385 uint8_t kind = i.PeekU8 ();
387 uint32_t optionSize;
388 if (TcpOption::IsKindKnown (kind))
389 {
390 op = TcpOption::CreateOption (kind);
391 }
392 else
393 {
395 NS_LOG_WARN ("Option kind " << static_cast<int> (kind) << " unknown, skipping.");
396 }
397 optionSize = op->Deserialize (i);
398 if (optionSize != op->GetSerializedSize ())
399 {
400 NS_LOG_ERROR ("Option did not deserialize correctly");
401 break;
402 }
403 if (optionLen >= optionSize)
404 {
405 optionLen -= optionSize;
406 i.Next (optionSize);
407 m_options.push_back (op);
408 m_optionsLen += optionSize;
409 }
410 else
411 {
412 NS_LOG_ERROR ("Option exceeds TCP option space; option discarded");
413 break;
414 }
415 if (op->GetKind () == TcpOption::END)
416 {
417 while (optionLen)
418 {
419 // Discard padding bytes without adding to option list
420 i.Next (1);
421 --optionLen;
422 ++m_optionsLen;
423 }
424 }
425 }
426
428 {
429 NS_LOG_ERROR ("Mismatch between calculated length and in-header value");
430 }
431
432 // Do checksum
433 if (m_calcChecksum)
434 {
435 uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
436 i = start;
437 uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
438 m_goodChecksum = (checksum == 0);
439 }
440
441 return GetSerializedSize ();
442}
443
444uint8_t
446{
447 uint32_t len = 20;
448 TcpOptionList::const_iterator i;
449
450 for (i = m_options.begin (); i != m_options.end (); ++i)
451 {
452 len += (*i)->GetSerializedSize ();
453 }
454 // Option list may not include padding; need to pad up to word boundary
455 if (len % 4)
456 {
457 len += 4 - (len % 4);
458 }
459 return len >> 2;
460}
461
462bool
464{
466 {
467 if (!TcpOption::IsKindKnown (option->GetKind ()))
468 {
469 NS_LOG_WARN ("The option kind " << static_cast<int> (option->GetKind ()) << " is unknown");
470 return false;
471 }
472
473 if (option->GetKind () != TcpOption::END)
474 {
475 m_options.push_back (option);
476 m_optionsLen += option->GetSerializedSize ();
477
478 uint32_t totalLen = 20 + 3 + m_optionsLen;
479 m_length = totalLen >> 2;
480 }
481
482 return true;
483 }
484
485 return false;
486}
487
490{
491 return m_options;
492}
493
495TcpHeader::GetOption(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 (*i);
504 }
505 }
506
507 return 0;
508}
509
510bool
511TcpHeader::HasOption (uint8_t kind) const
512{
513 TcpOptionList::const_iterator i;
514
515 for (i = m_options.begin (); i != m_options.end (); ++i)
516 {
517 if ((*i)->GetKind () == kind)
518 {
519 return true;
520 }
521 }
522
523 return false;
524}
525
526bool
527operator== (const TcpHeader &lhs, const TcpHeader &rhs)
528{
529 return (
530 lhs.m_sourcePort == rhs.m_sourcePort
533 && lhs.m_ackNumber == rhs.m_ackNumber
534 && lhs.m_flags == rhs.m_flags
535 && lhs.m_windowSize == rhs.m_windowSize
536 && lhs.m_urgentPointer == rhs.m_urgentPointer
537 );
538}
539
540std::ostream&
541operator<< (std::ostream& os, TcpHeader const & tc)
542{
543 tc.Print (os);
544 return os;
545}
546
547} // namespace ns3
a polymophic address class
Definition: address.h:91
iterator in a Buffer instance
Definition: buffer.h:99
uint16_t ReadNtohU16(void)
Definition: buffer.h:946
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1134
void WriteU8(uint8_t data)
Definition: buffer.h:869
void Next(void)
go forward by one byte
Definition: buffer.h:845
void WriteU16(uint16_t data)
Definition: buffer.cc:871
void WriteHtonU16(uint16_t data)
Definition: buffer.h:905
void WriteHtonU32(uint32_t data)
Definition: buffer.h:924
uint8_t PeekU8(void)
Definition: buffer.h:998
uint32_t ReadNtohU32(void)
Definition: buffer.h:970
automatically resized byte buffer
Definition: buffer.h:93
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
Protocol header serialization and deserialization.
Definition: header.h:43
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static bool IsMatchingType(const Address &address)
Describes an IPv6 address.
Definition: ipv6-address.h:50
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
Header for the Transmission Control Protocol.
Definition: tcp-header.h:45
uint16_t m_urgentPointer
Urgent pointer.
Definition: tcp-header.h:342
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition: tcp-header.cc:125
Address m_source
Source IP address.
Definition: tcp-header.h:344
virtual void Serialize(Buffer::Iterator start) const
Definition: tcp-header.cc:315
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition: tcp-header.cc:95
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition: tcp-header.cc:101
virtual uint32_t GetSerializedSize(void) const
Definition: tcp-header.cc:309
uint8_t m_optionsLen
Tcp options length.
Definition: tcp-header.h:353
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
Definition: tcp-header.cc:143
uint8_t GetLength() const
Get the length in words.
Definition: tcp-header.cc:155
uint8_t GetMaxOptionLength() const
Get maximum option length.
Definition: tcp-header.cc:167
uint16_t m_sourcePort
Source port.
Definition: tcp-header.h:335
uint16_t GetDestinationPort() const
Get the destination port.
Definition: tcp-header.cc:137
uint8_t CalculateHeaderLength() const
Calculates the header length (in words)
Definition: tcp-header.cc:445
uint8_t m_length
Length (really a uint4_t) in words.
Definition: tcp-header.h:339
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-header.cc:270
virtual void Print(std::ostream &os) const
Definition: tcp-header.cc:287
static const uint8_t m_maxOptionsLen
Maximum options length.
Definition: tcp-header.h:351
Ptr< const TcpOption > GetOption(uint8_t kind) const
Get the option specified.
Definition: tcp-header.cc:495
void SetFlags(uint8_t flags)
Set flags of the header.
Definition: tcp-header.cc:113
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition: tcp-header.cc:119
bool m_calcChecksum
Flag to calculate checksum.
Definition: tcp-header.h:348
uint16_t GetWindowSize() const
Get the window size.
Definition: tcp-header.cc:179
void InitializeChecksum(const Ipv4Address &source, const Ipv4Address &destination, uint8_t protocol)
Initialize the TCP checksum.
Definition: tcp-header.cc:191
Address m_destination
Destination IP address.
Definition: tcp-header.h:345
uint8_t m_protocol
Protocol number.
Definition: tcp-header.h:346
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Definition: tcp-header.cc:281
uint8_t GetOptionLength() const
Get the total length of appended options.
Definition: tcp-header.cc:161
SequenceNumber32 m_sequenceNumber
Sequence number.
Definition: tcp-header.h:337
uint16_t CalculateHeaderChecksum(uint16_t size) const
Calculate the header checksum.
Definition: tcp-header.cc:221
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
Definition: tcp-header.cc:463
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
bool IsChecksumOk(void) const
Is the TCP checksum correct ?
Definition: tcp-header.cc:264
const TcpOptionList & GetOptionList(void) const
Get the list of option in this header.
Definition: tcp-header.cc:489
uint16_t m_windowSize
Window size.
Definition: tcp-header.h:341
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
Definition: tcp-header.cc:511
bool m_goodChecksum
Flag to indicate that checksum is correct.
Definition: tcp-header.h:349
std::list< Ptr< const TcpOption > > TcpOptionList
List of TcpOption.
Definition: tcp-header.h:50
virtual uint32_t Deserialize(Buffer::Iterator start)
Definition: tcp-header.cc:360
uint16_t GetSourcePort() const
Get the source port.
Definition: tcp-header.cc:131
void SetSourcePort(uint16_t port)
Set the source port.
Definition: tcp-header.cc:89
SequenceNumber32 m_ackNumber
ACK number.
Definition: tcp-header.h:338
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition: tcp-header.cc:107
uint16_t GetUrgentPointer() const
Get the urgent pointer.
Definition: tcp-header.cc:185
uint8_t GetFlags() const
Get the flags.
Definition: tcp-header.cc:173
SequenceNumber32 GetAckNumber() const
Get the ACK number.
Definition: tcp-header.cc:149
void EnableChecksums(void)
Enable checksum calculation for TCP.
Definition: tcp-header.cc:83
uint8_t m_flags
Flags (really a uint6_t)
Definition: tcp-header.h:340
uint16_t m_destinationPort
Destination port.
Definition: tcp-header.h:336
TcpOptionList m_options
TcpOption present in the header.
Definition: tcp-header.h:352
virtual ~TcpHeader()
Definition: tcp-header.cc:50
virtual uint8_t GetKind(void) const =0
Get the ‘kind’ (as in RFC 793) of this option.
static Ptr< TcpOption > CreateOption(uint8_t kind)
Creates an option.
Definition: tcp-option.cc:65
static bool IsKindKnown(uint8_t kind)
Check if the option is implemented.
Definition: tcp-option.cc:99
@ UNKNOWN
not a standardized value; for unknown recv'd options
Definition: tcp-option.h:64
virtual uint32_t GetSerializedSize(void) const =0
Returns number of bytes required for Option serialization.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
uint16_t port
Definition: dsdv-manet.cc:45
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:158
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
def start()
Definition: core.py:1853