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