A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-header.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 Georgia Tech Research Corporation
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Raj Bhattacharjea <raj.b@gatech.edu>
7 */
8
9#include "tcp-header.h"
10
11#include "tcp-option.h"
12
13#include "ns3/address-utils.h"
14#include "ns3/buffer.h"
15#include "ns3/log.h"
16
17#include <iostream>
18#include <stdint.h>
19
20namespace ns3
21{
22
23NS_LOG_COMPONENT_DEFINE("TcpHeader");
24
26
27std::string
28TcpHeader::FlagsToString(uint8_t flags, const std::string& delimiter)
29{
30 static const char* flagNames[8] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECE", "CWR"};
31 std::string flagsDescription = "";
32 for (uint8_t i = 0; i < 8; ++i)
33 {
34 if (flags & (1 << i))
35 {
36 if (!flagsDescription.empty())
37 {
38 flagsDescription += delimiter;
39 }
40 flagsDescription.append(flagNames[i]);
41 }
42 }
43 return flagsDescription;
44}
45
46void
51
52void
57
58void
63
64void
66{
67 m_sequenceNumber = sequenceNumber;
68}
69
70void
72{
73 m_ackNumber = ackNumber;
74}
75
76void
77TcpHeader::SetFlags(uint8_t flags)
78{
79 m_flags = flags;
80}
81
82void
83TcpHeader::SetWindowSize(uint16_t windowSize)
84{
85 m_windowSize = windowSize;
86}
87
88void
89TcpHeader::SetUrgentPointer(uint16_t urgentPointer)
90{
91 m_urgentPointer = urgentPointer;
92}
93
94uint16_t
96{
97 return m_sourcePort;
98}
99
100uint16_t
105
108{
109 return m_sequenceNumber;
110}
111
114{
115 return m_ackNumber;
116}
117
118uint8_t
120{
121 return m_length;
122}
123
124uint8_t
126{
127 return m_optionsLen;
128}
129
130uint8_t
132{
133 return m_maxOptionsLen;
134}
135
136uint8_t
138{
139 return m_flags;
140}
141
142uint16_t
144{
145 return m_windowSize;
146}
147
148uint16_t
150{
151 return m_urgentPointer;
152}
153
154void
156 const Ipv4Address& destination,
157 uint8_t protocol)
158{
159 m_source = source;
160 m_destination = destination;
161 m_protocol = protocol;
162}
163
164void
166 const Ipv6Address& destination,
167 uint8_t protocol)
168{
169 m_source = source;
170 m_destination = destination;
171 m_protocol = protocol;
172}
173
174void
175TcpHeader::InitializeChecksum(const Address& source, const Address& destination, uint8_t protocol)
176{
177 m_source = source;
178 m_destination = destination;
179 m_protocol = protocol;
180}
181
182uint16_t
184{
185 /* Buffer size must be at least as large as the largest IP pseudo-header */
186 /* [per RFC2460, but without consideration for IPv6 extension hdrs] */
187 /* Src address 16 bytes (more generally, Address::MAX_SIZE) */
188 /* Dst address 16 bytes (more generally, Address::MAX_SIZE) */
189 /* Upper layer pkt len 4 bytes */
190 /* Zero 3 bytes */
191 /* Next header 1 byte */
192
193 uint32_t maxHdrSz = (2 * Address::MAX_SIZE) + 8;
194 Buffer buf = Buffer(maxHdrSz);
195 buf.AddAtStart(maxHdrSz);
196 Buffer::Iterator it = buf.Begin();
197 uint32_t hdrSize = 0;
198
199 WriteTo(it, m_source);
202 {
203 it.WriteU8(0); /* protocol */
204 it.WriteU8(m_protocol); /* protocol */
205 it.WriteU8(size >> 8); /* length */
206 it.WriteU8(size & 0xff); /* length */
207 hdrSize = 12;
208 }
209 else
210 {
211 it.WriteU16(0);
212 it.WriteU8(size >> 8); /* length */
213 it.WriteU8(size & 0xff); /* length */
214 it.WriteU16(0);
215 it.WriteU8(0);
216 it.WriteU8(m_protocol); /* protocol */
217 hdrSize = 40;
218 }
219
220 it = buf.Begin();
221 /* we don't CompleteChecksum ( ~ ) now */
222 return ~(it.CalculateIpChecksum(hdrSize));
223}
224
225bool
227{
228 return m_goodChecksum;
229}
230
231TypeId
233{
234 static TypeId tid = TypeId("ns3::TcpHeader")
235 .SetParent<Header>()
236 .SetGroupName("Internet")
237 .AddConstructor<TcpHeader>();
238 return tid;
239}
240
241TypeId
243{
244 return GetTypeId();
245}
246
247void
248TcpHeader::Print(std::ostream& os) const
249{
250 os << m_sourcePort << " > " << m_destinationPort;
251
252 if (m_flags != 0)
253 {
254 os << " [" << FlagsToString(m_flags) << "]";
255 }
256
257 os << " Seq=" << m_sequenceNumber << " Ack=" << m_ackNumber << " Win=" << m_windowSize;
258
259 for (auto op = m_options.begin(); op != m_options.end(); ++op)
260 {
261 os << " " << (*op)->GetInstanceTypeId().GetName() << "(";
262 (*op)->Print(os);
263 os << ")";
264 }
265}
266
269{
270 return CalculateHeaderLength() * 4;
271}
272
273void
275{
276 Buffer::Iterator i = start;
281 i.WriteHtonU16(GetLength() << 12 | m_flags); // reserved bits are all zero
283 i.WriteHtonU16(0);
285
286 // Serialize options if they exist
287 // This implementation does not presently try to align options on word
288 // boundaries using NOP options
289 uint32_t optionLen = 0;
290
291 for (auto op = m_options.begin(); op != m_options.end(); ++op)
292 {
293 optionLen += (*op)->GetSerializedSize();
294 (*op)->Serialize(i);
295 i.Next((*op)->GetSerializedSize());
296 }
297
298 // padding to word alignment; add ENDs and/or pad values (they are the same)
299 while (optionLen % 4)
300 {
302 ++optionLen;
303 }
304
305 // Make checksum
306 if (m_calcChecksum)
307 {
308 uint16_t headerChecksum = CalculateHeaderChecksum(start.GetSize());
309 i = start;
310 uint16_t checksum = i.CalculateIpChecksum(start.GetSize(), headerChecksum);
311
312 i = start;
313 i.Next(16);
314 i.WriteU16(checksum);
315 }
316}
317
320{
321 m_optionsLen = 0;
322 Buffer::Iterator i = start;
327 uint16_t field = i.ReadNtohU16();
328 m_flags = field & 0xFF;
329 m_length = field >> 12;
331 i.Next(2);
333
334 // Deserialize options if they exist
335 m_options.clear();
336 uint32_t optionLen = (m_length - 5) * 4;
337 if (optionLen > m_maxOptionsLen)
338 {
339 NS_LOG_ERROR("Illegal TCP option length " << optionLen << "; options discarded");
340 return 20;
341 }
342 while (optionLen)
343 {
344 uint8_t kind = i.PeekU8();
346 uint32_t optionSize;
347 if (TcpOption::IsKindKnown(kind))
348 {
349 op = TcpOption::CreateOption(kind);
350 }
351 else
352 {
354 NS_LOG_WARN("Option kind " << static_cast<int>(kind) << " unknown, skipping.");
355 }
356 optionSize = op->Deserialize(i);
357 if (optionSize != op->GetSerializedSize())
358 {
359 NS_LOG_ERROR("Option did not deserialize correctly");
360 break;
361 }
362 if (optionLen >= optionSize)
363 {
364 optionLen -= optionSize;
365 i.Next(optionSize);
366 m_options.emplace_back(op);
367 m_optionsLen += optionSize;
368 }
369 else
370 {
371 NS_LOG_ERROR("Option exceeds TCP option space; option discarded");
372 break;
373 }
374 if (op->GetKind() == TcpOption::END)
375 {
376 while (optionLen)
377 {
378 // Discard padding bytes without adding to option list
379 i.Next(1);
380 --optionLen;
381 ++m_optionsLen;
382 }
383 }
384 }
385
387 {
388 NS_LOG_ERROR("Mismatch between calculated length and in-header value");
389 }
390
391 // Do checksum
392 if (m_calcChecksum)
393 {
394 uint16_t headerChecksum = CalculateHeaderChecksum(start.GetSize());
395 i = start;
396 uint16_t checksum = i.CalculateIpChecksum(start.GetSize(), headerChecksum);
397 m_goodChecksum = (checksum == 0);
398 }
399
400 return GetSerializedSize();
401}
402
403uint8_t
405{
406 uint32_t len = 20;
407
408 for (auto i = m_options.begin(); i != m_options.end(); ++i)
409 {
410 len += (*i)->GetSerializedSize();
411 }
412 // Option list may not include padding; need to pad up to word boundary
413 if (len % 4)
414 {
415 len += 4 - (len % 4);
416 }
417 return len >> 2;
418}
419
420bool
422{
423 if (m_optionsLen + option->GetSerializedSize() <= m_maxOptionsLen)
424 {
425 if (!TcpOption::IsKindKnown(option->GetKind()))
426 {
427 NS_LOG_WARN("The option kind " << static_cast<int>(option->GetKind()) << " is unknown");
428 return false;
429 }
430
431 if (option->GetKind() != TcpOption::END)
432 {
433 m_options.push_back(option);
434 m_optionsLen += option->GetSerializedSize();
435
436 uint32_t totalLen = 20 + 3 + m_optionsLen;
437 m_length = totalLen >> 2;
438 }
439
440 return true;
441 }
442
443 return false;
444}
445
448{
449 return m_options;
450}
451
453TcpHeader::GetOption(uint8_t kind) const
454{
455 for (auto i = m_options.begin(); i != m_options.end(); ++i)
456 {
457 if ((*i)->GetKind() == kind)
458 {
459 return (*i);
460 }
461 }
462
463 return nullptr;
464}
465
466bool
467TcpHeader::HasOption(uint8_t kind) const
468{
469 for (auto i = m_options.begin(); i != m_options.end(); ++i)
470 {
471 if ((*i)->GetKind() == kind)
472 {
473 return true;
474 }
475 }
476
477 return false;
478}
479
480bool
481operator==(const TcpHeader& lhs, const TcpHeader& rhs)
482{
483 return (lhs.m_sourcePort == rhs.m_sourcePort &&
485 lhs.m_sequenceNumber == rhs.m_sequenceNumber && lhs.m_ackNumber == rhs.m_ackNumber &&
486 lhs.m_flags == rhs.m_flags && lhs.m_windowSize == rhs.m_windowSize &&
488}
489
490std::ostream&
491operator<<(std::ostream& os, const TcpHeader& tc)
492{
493 tc.Print(os);
494 return os;
495}
496
497} // namespace ns3
a polymophic address class
Definition address.h:90
static constexpr uint32_t MAX_SIZE
The maximum size of a byte buffer which can be stored in an Address instance.
Definition address.h:96
iterator in a Buffer instance
Definition buffer.h:89
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition buffer.cc:1124
void WriteU8(uint8_t data)
Definition buffer.h:870
void WriteU16(uint16_t data)
Definition buffer.cc:848
void WriteHtonU16(uint16_t data)
Definition buffer.h:904
uint32_t ReadNtohU32()
Definition buffer.h:967
void WriteHtonU32(uint32_t data)
Definition buffer.h:922
uint16_t ReadNtohU16()
Definition buffer.h:943
void Next()
go forward by one byte
Definition buffer.h:842
automatically resized byte buffer
Definition buffer.h:83
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1063
Protocol header serialization and deserialization.
Definition header.h:33
Ipv4 addresses are stored in host order in this class.
static bool IsMatchingType(const Address &address)
Describes an IPv6 address.
Smart pointer class similar to boost::intrusive_ptr.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
Header for the Transmission Control Protocol.
Definition tcp-header.h:36
uint16_t m_urgentPointer
Urgent pointer.
Definition tcp-header.h:328
void SetUrgentPointer(uint16_t urgentPointer)
Set the urgent pointer.
Definition tcp-header.cc:89
Address m_source
Source IP address.
Definition tcp-header.h:330
void Print(std::ostream &os) const override
void SetDestinationPort(uint16_t port)
Set the destination port.
Definition tcp-header.cc:59
void SetSequenceNumber(SequenceNumber32 sequenceNumber)
Set the sequence Number.
Definition tcp-header.cc:65
uint8_t m_optionsLen
Tcp options length.
Definition tcp-header.h:339
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
uint8_t GetLength() const
Get the length in words.
uint8_t GetMaxOptionLength() const
Get maximum option length.
uint16_t m_sourcePort
Source port.
Definition tcp-header.h:321
uint16_t GetDestinationPort() const
Get the destination port.
std::list< Ptr< const TcpOption > > TcpOptionList
List of TcpOption.
Definition tcp-header.h:38
uint8_t CalculateHeaderLength() const
Calculates the header length (in words)
uint8_t m_length
Length (really a uint4_t) in words.
Definition tcp-header.h:325
static const uint8_t m_maxOptionsLen
Maximum options length.
Definition tcp-header.h:337
uint32_t Deserialize(Buffer::Iterator start) override
Ptr< const TcpOption > GetOption(uint8_t kind) const
Get the option specified.
void SetFlags(uint8_t flags)
Set flags of the header.
Definition tcp-header.cc:77
void SetWindowSize(uint16_t windowSize)
Set the window size.
Definition tcp-header.cc:83
uint32_t GetSerializedSize() const override
const TcpOptionList & GetOptionList() const
Get the list of option in this header.
bool m_calcChecksum
Flag to calculate checksum.
Definition tcp-header.h:334
uint16_t GetWindowSize() const
Get the window size.
void InitializeChecksum(const Ipv4Address &source, const Ipv4Address &destination, uint8_t protocol)
Initialize the TCP checksum.
Address m_destination
Destination IP address.
Definition tcp-header.h:331
uint8_t m_protocol
Protocol number.
Definition tcp-header.h:332
uint8_t GetOptionLength() const
Get the total length of appended options.
SequenceNumber32 m_sequenceNumber
Sequence number.
Definition tcp-header.h:323
uint16_t CalculateHeaderChecksum(uint16_t size) const
Calculate the header checksum.
bool AppendOption(Ptr< const TcpOption > option)
Append an option to the TCP header.
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:28
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint16_t m_windowSize
Window size.
Definition tcp-header.h:327
bool HasOption(uint8_t kind) const
Check if the header has the option specified.
bool m_goodChecksum
Flag to indicate that checksum is correct.
Definition tcp-header.h:335
void Serialize(Buffer::Iterator start) const override
uint16_t GetSourcePort() const
Get the source port.
Definition tcp-header.cc:95
void SetSourcePort(uint16_t port)
Set the source port.
Definition tcp-header.cc:53
SequenceNumber32 m_ackNumber
ACK number.
Definition tcp-header.h:324
void EnableChecksums()
Enable checksum calculation for TCP.
Definition tcp-header.cc:47
void SetAckNumber(SequenceNumber32 ackNumber)
Set the ACK number.
Definition tcp-header.cc:71
uint16_t GetUrgentPointer() const
Get the urgent pointer.
uint8_t GetFlags() const
Get the flags.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
uint8_t m_flags
Flags (really a uint6_t)
Definition tcp-header.h:326
bool IsChecksumOk() const
Is the TCP checksum correct ?
uint16_t m_destinationPort
Destination port.
Definition tcp-header.h:322
TcpOptionList m_options
TcpOption present in the header.
Definition tcp-header.h:338
static TypeId GetTypeId()
Get the type ID.
static Ptr< TcpOption > CreateOption(uint8_t kind)
Creates an option.
Definition tcp-option.cc:51
static bool IsKindKnown(uint8_t kind)
Check if the option is implemented.
Definition tcp-option.cc:84
@ UNKNOWN
not a standardized value; for unknown recv'd options
Definition tcp-option.h:54
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
uint16_t port
Definition dsdv-manet.cc:33
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
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:155
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.