Coverage Report

Created: 2026-10-17 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/TcpLayer.h
Line
Count
Source
1
#pragma once
2
3
#include "DeprecationUtils.h"
4
#include "Layer.h"
5
#include "TLVData.h"
6
#include <string.h>
7
#include <algorithm>
8
#include <iterator>
9
10
#define PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG                                                                    \
11
  "enum TcpOptionType is deprecated; Use enum class TcpOptionEnumType instead"
12
13
/// @file
14
15
/// @namespace pcpp
16
/// @brief The main namespace for the PcapPlusPlus lib
17
namespace pcpp
18
{
19
  /// @struct tcphdr
20
  /// Represents an TCP protocol header
21
#pragma pack(push, 1)
22
  struct tcphdr
23
  {
24
    /// Source TCP port
25
    uint16_t portSrc;
26
    /// Destination TCP port
27
    uint16_t portDst;
28
    /// Sequence number
29
    uint32_t sequenceNumber;
30
    /// Acknowledgment number
31
    uint32_t ackNumber;
32
#if (BYTE_ORDER == LITTLE_ENDIAN)
33
    /// Accurate ECN flag
34
    uint16_t accurateEcnFlag : 1;
35
    /// Reserved bits
36
    uint16_t reserved : 3;
37
    /// Specifies the size of the TCP header in 32-bit words
38
    uint16_t dataOffset : 4;
39
    /// FIN flag
40
    uint16_t finFlag : 1;
41
    /// SYN flag
42
    uint16_t synFlag : 1;
43
    /// RST flag
44
    uint16_t rstFlag : 1;
45
    /// PSH flag
46
    uint16_t pshFlag : 1;
47
    /// ACK flag
48
    uint16_t ackFlag : 1;
49
    /// URG flag
50
    uint16_t urgFlag : 1;
51
    /// ECE flag
52
    uint16_t eceFlag : 1;
53
    /// CWR flag
54
    uint16_t cwrFlag : 1;
55
#elif (BYTE_ORDER == BIG_ENDIAN)
56
    /// Specifies the size of the TCP header in 32-bit words
57
    uint16_t dataOffset : 4;
58
    /// Reserved
59
    uint16_t reserved : 3;
60
    /// Accurate ECN flag
61
    uint16_t accurateEcnFlag : 1;
62
    /// CWR flag
63
    uint16_t cwrFlag : 1;
64
    /// ECE flag
65
    uint16_t eceFlag : 1;
66
    /// URG flag
67
    uint16_t urgFlag : 1;
68
    /// ACK flag
69
    uint16_t ackFlag : 1;
70
    /// PSH flag
71
    uint16_t pshFlag : 1;
72
    /// RST flag
73
    uint16_t rstFlag : 1;
74
    /// SYN flag
75
    uint16_t synFlag : 1;
76
    /// FIN flag
77
    uint16_t finFlag : 1;
78
#else
79
# error "Endian is not LE nor BE..."
80
#endif
81
    /// The size of the receive window, which specifies the number of window size units (by default, bytes)
82
    uint16_t windowSize;
83
    /// The 16-bit checksum field is used for error-checking of the header and data
84
    uint16_t headerChecksum;
85
    /// If the URG flag (@ref tcphdr#urgFlag) is set, then this 16-bit field is an offset from the sequence number
86
    /// indicating the last urgent data byte
87
    uint16_t urgentPointer;
88
  };
89
#pragma pack(pop)
90
  static_assert(sizeof(tcphdr) == 20, "tcphdr size is not 20 bytes");
91
92
  /// TCP options types
93
  enum TcpOptionType : uint8_t
94
  {
95
    /// Padding
96
    PCPP_TCPOPT_NOP = 1,
97
    /// End of options
98
    PCPP_TCPOPT_EOL = 0,
99
    /// Segment size negotiating
100
    TCPOPT_MSS = 2,
101
    /// Window scaling
102
    PCPP_TCPOPT_WINDOW = 3,
103
    /// SACK Permitted
104
    TCPOPT_SACK_PERM = 4,
105
    /// SACK Block
106
    PCPP_TCPOPT_SACK = 5,
107
    /// Echo (obsoleted by option TcpOptionType::PCPP_TCPOPT_TIMESTAMP)
108
    TCPOPT_ECHO = 6,
109
    /// Echo Reply (obsoleted by option TcpOptionType::PCPP_TCPOPT_TIMESTAMP)
110
    TCPOPT_ECHOREPLY = 7,
111
    /// TCP Timestamps
112
    PCPP_TCPOPT_TIMESTAMP = 8,
113
    /// CC (obsolete)
114
    TCPOPT_CC = 11,
115
    /// CC.NEW (obsolete)
116
    TCPOPT_CCNEW = 12,
117
    /// CC.ECHO(obsolete)
118
    TCPOPT_CCECHO = 13,
119
    /// MD5 Signature Option
120
    TCPOPT_MD5 = 19,
121
    /// Multipath TCP
122
    TCPOPT_MPTCP = 0x1e,
123
    /// SCPS Capabilities
124
    TCPOPT_SCPS = 20,
125
    /// SCPS SNACK
126
    TCPOPT_SNACK = 21,
127
    /// SCPS Record Boundary
128
    TCPOPT_RECBOUND = 22,
129
    /// SCPS Corruption Experienced
130
    TCPOPT_CORREXP = 23,
131
    /// Quick-Start Response
132
    TCPOPT_QS = 27,
133
    /// User Timeout Option (also, other known unauthorized use)
134
    TCPOPT_USER_TO = 28,
135
    /// RFC3692-style Experiment 1 (also improperly used for shipping products)
136
    TCPOPT_EXP_FD = 0xfd,
137
    /// RFC3692-style Experiment 2 (also improperly used for shipping products)
138
    TCPOPT_EXP_FE = 0xfe,
139
    /// Riverbed probe option, non IANA registered option number
140
    TCPOPT_RVBD_PROBE = 76,
141
    /// Riverbed transparency option, non IANA registered option number
142
    TCPOPT_RVBD_TRPY = 78,
143
    /// Unknown option
144
    TCPOPT_Unknown = 255
145
  };
146
147
  /// TCP options types
148
  enum class TcpOptionEnumType : uint8_t
149
  {
150
    /// Padding
151
    Nop = 1,
152
    /// End of options
153
    Eol = 0,
154
    /// Segment size negotiating
155
    Mss = 2,
156
    /// Window scaling
157
    Window = 3,
158
    /// SACK Permitted
159
    SackPerm = 4,
160
    /// SACK Block
161
    Sack = 5,
162
    /// Echo (obsoleted by option TcpOptionEnumType::Timestamp)
163
    Echo = 6,
164
    /// Echo Reply (obsoleted by option TcpOptionEnumType::Timestamp)
165
    EchoReply = 7,
166
    /// TCP Timestamps
167
    Timestamp = 8,
168
    /// CC (obsolete)
169
    Cc = 11,
170
    /// CC.NEW (obsolete)
171
    CcNew = 12,
172
    /// CC.ECHO(obsolete)
173
    CcEcho = 13,
174
    /// MD5 Signature Option
175
    Md5 = 19,
176
    /// Multipath TCP
177
    MpTcp = 0x1e,
178
    /// SCPS Capabilities
179
    Scps = 20,
180
    /// SCPS SNACK
181
    Snack = 21,
182
    /// SCPS Record Boundary
183
    RecBound = 22,
184
    /// SCPS Corruption Experienced
185
    CorrExp = 23,
186
    /// Quick-Start Response
187
    Qs = 27,
188
    /// User Timeout Option (also, other known unauthorized use)
189
    UserTo = 28,
190
    /// RFC3692-style Experiment 1 (also improperly used for shipping products)
191
    ExpFd = 0xfd,
192
    /// RFC3692-style Experiment 2 (also improperly used for shipping products)
193
    ExpFe = 0xfe,
194
    /// Riverbed probe option, non IANA registered option number
195
    RvbdProbe = 76,
196
    /// Riverbed transparency option, non IANA registered option number
197
    RvbdTrpy = 78,
198
    /// Unknown option
199
    Unknown = 255
200
  };
201
202
  // TCP option lengths
203
204
  /// pcpp::TcpOptionEnumType::Nop length
205
#define PCPP_TCPOLEN_NOP 1
206
  /// pcpp::TcpOptionEnumType::Eol length
207
#define PCPP_TCPOLEN_EOL 1
208
  /// pcpp::TcpOptionEnumType::Mss length
209
#define PCPP_TCPOLEN_MSS 4
210
  /// pcpp::TcpOptionEnumType::Window length
211
#define PCPP_TCPOLEN_WINDOW 3
212
  /// pcpp::TcpOptionEnumType::SackPerm length
213
#define PCPP_TCPOLEN_SACK_PERM 2
214
  /// pcpp::TcpOptionEnumType::Sack length
215
#define PCPP_TCPOLEN_SACK_MIN 2
216
  /// pcpp::TcpOptionEnumType::Echo length
217
#define PCPP_TCPOLEN_ECHO 6
218
  /// pcpp::TcpOptionEnumType::EchoReply length
219
#define PCPP_TCPOLEN_ECHOREPLY 6
220
  /// pcpp::TcpOptionEnumType::Timestamp length
221
#define PCPP_TCPOLEN_TIMESTAMP 10
222
  /// pcpp::TcpOptionEnumType::Cc length
223
#define PCPP_TCPOLEN_CC 6
224
  /// pcpp::TcpOptionEnumType::CcNew length
225
#define PCPP_TCPOLEN_CCNEW 6
226
  /// pcpp::TcpOptionEnumType::CcEcho length
227
#define PCPP_TCPOLEN_CCECHO 6
228
  /// pcpp::TcpOptionEnumType::Md5 length
229
#define PCPP_TCPOLEN_MD5 18
230
  /// pcpp::TcpOptionEnumType::MpTcp length
231
#define PCPP_TCPOLEN_MPTCP_MIN 8
232
  /// pcpp::TcpOptionEnumType::Scps length
233
#define PCPP_TCPOLEN_SCPS 4
234
  /// pcpp::TcpOptionEnumType::Snack length
235
#define PCPP_TCPOLEN_SNACK 6
236
  /// pcpp::TcpOptionEnumType::RecBound length
237
#define PCPP_TCPOLEN_RECBOUND 2
238
  /// pcpp::TcpOptionEnumType::CorrExp length
239
#define PCPP_TCPOLEN_CORREXP 2
240
  /// pcpp::TcpOptionEnumType::Qs length
241
#define PCPP_TCPOLEN_QS 8
242
  /// pcpp::TcpOptionEnumType::UserTo length
243
#define PCPP_TCPOLEN_USER_TO 4
244
  /// pcpp::TcpOptionEnumType::RvbdProbe length
245
#define PCPP_TCPOLEN_RVBD_PROBE_MIN 3
246
  /// pcpp::TcpOptionEnumType::RvbdTrpy length
247
#define PCPP_TCPOLEN_RVBD_TRPY_MIN 16
248
  /// pcpp::TcpOptionEnumType::ExpFd and pcpp::TcpOptionEnumType::ExpFe length
249
#define PCPP_TCPOLEN_EXP_MIN 2
250
251
  /// @class TcpOption
252
  /// A wrapper class for TCP options. This class does not create or modify TCP option records, but rather
253
  /// serves as a wrapper and provides useful methods for retrieving data from them
254
  class TcpOption : public TLVRecord<uint8_t, uint8_t>
255
  {
256
  public:
257
    /// A c'tor for this class that gets a pointer to the option raw data (byte array)
258
    /// @param[in] optionRawData A pointer to the TCP option raw data
259
504k
    explicit TcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData)
260
504k
    {}
261
262
    /// A d'tor for this class, currently does nothing
263
    ~TcpOption() override = default;
264
265
    /// @deprecated This method is deprecated, please use getTcpOptionEnumType()
266
    PCPP_DEPRECATED("Use getTcpOptionEnumType instead")
267
    TcpOptionType getTcpOptionType() const
268
0
    {
269
0
      return getTcpOptionType(m_Data);
270
0
    }
271
272
    /// @return TCP option type casted as pcpp::TcpOptionEnumType enum. If the data is null a value
273
    /// of TcpOptionEnumType::Unknown is returned
274
    TcpOptionEnumType getTcpOptionEnumType() const
275
0
    {
276
0
      return getTcpOptionEnumType(m_Data);
277
0
    }
278
279
    /// Check if a pointer can be assigned to the TLV record data
280
    /// @param[in] recordRawData A pointer to the TLV record raw data
281
    /// @param[in] tlvDataLen The size of the TLV record raw data
282
    /// @return True if data is valid and can be assigned
283
    static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
284
347k
    {
285
347k
      const auto* data = reinterpret_cast<const TLVRawData*>(recordRawData);
286
347k
      if (data == nullptr)
287
0
        return false;
288
289
347k
      if (tlvDataLen < sizeof(TLVRawData::recordType))
290
103k
        return false;
291
292
244k
      const auto recordType = getTcpOptionEnumType(data);
293
244k
      if (recordType == TcpOptionEnumType::Nop || recordType == TcpOptionEnumType::Eol)
294
168k
        return true;
295
296
75.7k
      return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen);
297
244k
    }
298
299
    // implement abstract methods
300
301
    size_t getTotalSize() const override
302
1.36M
    {
303
1.36M
      if (m_Data == nullptr)
304
0
        return 0;
305
306
1.36M
      const auto recordType = getTcpOptionEnumType(m_Data);
307
1.36M
      if (recordType == TcpOptionEnumType::Nop || recordType == TcpOptionEnumType::Eol)
308
1.00M
        return sizeof(uint8_t);
309
310
364k
      return static_cast<size_t>(m_Data->recordLen);
311
1.36M
    }
312
313
    size_t getDataSize() const override
314
0
    {
315
0
      if (m_Data == nullptr)
316
0
        return 0;
317
318
0
      const auto recordType = getTcpOptionEnumType(m_Data);
319
0
      if (recordType == TcpOptionEnumType::Nop || recordType == TcpOptionEnumType::Eol)
320
0
        return 0;
321
322
0
      return static_cast<size_t>(m_Data->recordLen) - (2 * sizeof(uint8_t));
323
0
    }
324
325
  private:
326
    static TcpOptionType getTcpOptionType(const TLVRawData* optionRawData)
327
0
    {
328
0
      if (optionRawData == nullptr)
329
0
        return TcpOptionType::TCPOPT_Unknown;
330
0
331
0
      return static_cast<TcpOptionType>(optionRawData->recordType);
332
0
    }
333
334
    static TcpOptionEnumType getTcpOptionEnumType(const TLVRawData* optionRawData)
335
1.60M
    {
336
1.60M
      if (optionRawData == nullptr)
337
0
        return TcpOptionEnumType::Unknown;
338
339
1.60M
      return static_cast<TcpOptionEnumType>(optionRawData->recordType);
340
1.60M
    }
341
  };
342
343
  /// @class TcpOptionBuilder
344
  /// A class for building TCP option records. This builder receives the TCP option parameters in its c'tor,
345
  /// builds the TCP option raw buffer and provides a build() method to get a TcpOption object out of it
346
  class TcpOptionBuilder : public TLVRecordBuilder
347
  {
348
349
  public:
350
    /// An enum to describe NOP and EOL TCP options. Used in one of this class's c'tors
351
    enum NopEolOptionTypes : uint8_t
352
    {
353
      /// NOP TCP option
354
      NOP,
355
      /// EOL TCP option
356
      EOL
357
    };
358
359
    /// An enum to describe NOP and EOL TCP options. Used in one of this class's c'tors
360
    enum class NopEolOptionEnumType : uint8_t
361
    {
362
      /// NOP TCP option
363
      Nop,
364
      /// EOL TCP option
365
      Eol
366
    };
367
368
    /// @deprecated This method is deprecated, please use constructor with TcpOptionEnumType
369
    PCPP_DEPRECATED(PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG)
370
    TcpOptionBuilder(TcpOptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen)
371
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue, optionValueLen)
372
0
    {}
373
374
    /// A c'tor for building TCP options which their value is a byte array. The TcpOption object can be later
375
    /// retrieved by calling build()
376
    /// @param[in] optionType TCP option type
377
    /// @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in
378
    /// any way.
379
    /// @param[in] optionValueLen Option value length in bytes
380
    TcpOptionBuilder(TcpOptionEnumType optionType, const uint8_t* optionValue, uint8_t optionValueLen)
381
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue, optionValueLen)
382
0
    {}
383
384
    /// @deprecated This method is deprecated, please use constructor with TcpOptionEnumType
385
    PCPP_DEPRECATED(PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG)
386
    TcpOptionBuilder(TcpOptionType optionType, uint8_t optionValue)
387
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue)
388
0
    {}
389
390
    /// A c'tor for building TCP options which have a 1-byte value. The TcpOption object can be later retrieved
391
    /// by calling build()
392
    /// @param[in] optionType TCP option type
393
    /// @param[in] optionValue A 1-byte option value
394
    TcpOptionBuilder(TcpOptionEnumType optionType, uint8_t optionValue)
395
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue)
396
0
    {}
397
398
    /// @deprecated This method is deprecated, please use constructor with TcpOptionEnumType
399
    PCPP_DEPRECATED(PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG)
400
    TcpOptionBuilder(TcpOptionType optionType, uint16_t optionValue)
401
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue)
402
0
    {}
403
404
    /// A c'tor for building TCP options which have a 2-byte value. The TcpOption object can be later retrieved
405
    /// by calling build()
406
    /// @param[in] optionType TCP option type
407
    /// @param[in] optionValue A 2-byte option value
408
    TcpOptionBuilder(TcpOptionEnumType optionType, uint16_t optionValue)
409
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue)
410
0
    {}
411
412
    /// @deprecated This method is deprecated, please use constructor with TcpOptionEnumType
413
    PCPP_DEPRECATED(PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG)
414
    TcpOptionBuilder(TcpOptionType optionType, uint32_t optionValue)
415
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue)
416
0
    {}
417
418
    /// A c'tor for building TCP options which have a 4-byte value. The TcpOption object can be later retrieved
419
    /// by calling build()
420
    /// @param[in] optionType TCP option type
421
    /// @param[in] optionValue A 4-byte option value
422
    TcpOptionBuilder(TcpOptionEnumType optionType, uint32_t optionValue)
423
        : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue)
424
0
    {}
425
426
    /// @deprecated This method is deprecated, please use constructor with NopEolOptionEnumType
427
    PCPP_DEPRECATED("enum NopEolOptionTypes is deprecated; Use enum class NopEolOptionEnumType instead")
428
    explicit TcpOptionBuilder(NopEolOptionTypes optionType);
429
430
    /// A c'tor for building TCP NOP and EOL options. These option types are special in that they contain only 1
431
    /// byte which is the TCP option type (NOP or EOL). The TcpOption object can be later retrieved by calling
432
    /// build()
433
    /// @param[in] optionType An enum value indicating which option type to build (NOP or EOL)
434
    explicit TcpOptionBuilder(NopEolOptionEnumType optionType);
435
436
    /// Build the TcpOption object out of the parameters defined in the c'tor
437
    /// @return The TcpOption object
438
    TcpOption build() const;
439
  };
440
441
  /// @class TcpLayer
442
  /// Represents a TCP (Transmission Control Protocol) protocol layer
443
  class TcpLayer : public Layer
444
  {
445
  public:
446
    /// A constructor that creates the layer from an existing packet raw data
447
    /// @param[in] data A pointer to the raw data (will be casted to @ref tcphdr)
448
    /// @param[in] dataLen Size of the data in bytes
449
    /// @param[in] prevLayer A pointer to the previous layer
450
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
451
    TcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
452
453
    /// A constructor that allocates a new TCP header with zero TCP options
454
    TcpLayer();
455
456
    /// A constructor that allocates a new TCP header with source port and destination port and zero TCP options
457
    /// @param[in] portSrc Source port
458
    /// @param[in] portDst Destination port
459
    TcpLayer(uint16_t portSrc, uint16_t portDst);
460
461
687k
    ~TcpLayer() override = default;
462
463
    /// A copy constructor that copy the entire header from the other TcpLayer (including TCP options)
464
    TcpLayer(const TcpLayer& other);
465
466
    /// An assignment operator that first delete all data from current layer and then copy the entire header from
467
    /// the other TcpLayer (including TCP options)
468
    TcpLayer& operator=(const TcpLayer& other);
469
470
    /// Get a pointer to the TCP header. Notice this points directly to the data, so every change will change the
471
    /// actual packet data
472
    /// @return A pointer to the @ref tcphdr
473
    tcphdr* getTcpHeader() const
474
3.24M
    {
475
3.24M
      return reinterpret_cast<tcphdr*>(m_Data);
476
3.24M
    }
477
478
    /// @return TCP source port
479
    uint16_t getSrcPort() const;
480
481
    /// @return TCP destination port
482
    uint16_t getDstPort() const;
483
484
    /// @deprecated This method is deprecated, please use getTcpOption(TcpOptionEnumType option)
485
    PCPP_DEPRECATED(PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG)
486
    TcpOption getTcpOption(TcpOptionType option) const;
487
488
    /// Get a TCP option by type
489
    /// @param[in] option TCP option type to retrieve
490
    /// @return An TcpOption object that contains the first option that matches this type, or logical null
491
    /// (TcpOption#isNull() == true) if no such option found
492
    TcpOption getTcpOption(TcpOptionEnumType option) const;
493
494
    /// @return The first TCP option in the packet. If the current layer contains no options the returned value will
495
    /// contain a logical null (TcpOption#isNull() == true)
496
    TcpOption getFirstTcpOption() const;
497
498
    /// Get the TCP option that comes after a given option. If the given option was the last one, the
499
    /// returned value will contain a logical null (TcpOption#isNull() == true)
500
    /// @param[in] tcpOption A TCP option object that exists in the current layer
501
    /// @return A TcpOption object that contains the TCP option data that comes next, or logical null if the given
502
    /// TCP option: (1) was the last one; or (2) contains a logical null; or (3) doesn't belong to this packet
503
    TcpOption getNextTcpOption(TcpOption& tcpOption) const;
504
505
    /// @return The number of TCP options in this layer
506
    size_t getTcpOptionCount() const;
507
508
    /// Add a new TCP option at the end of the layer (after the last TCP option)
509
    /// @param[in] optionBuilder A TcpOptionBuilder object that contains the TCP option data to be added
510
    /// @return A TcpOption object that contains the newly added TCP option data or logical null
511
    /// (TcpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be
512
    /// printed to log
513
    TcpOption addTcpOption(const TcpOptionBuilder& optionBuilder);
514
515
    /// @deprecated This method is deprecated, please use insertTcpOptionAfter(const TcpOptionBuilder&
516
    /// optionBuilder, TcpOptionEnumType prevOptionType = TcpOptionEnumType::Unknown)
517
    PCPP_DEPRECATED("Use insertTcpOptionAfter instead")
518
    TcpOption addTcpOptionAfter(const TcpOptionBuilder& optionBuilder,
519
                                TcpOptionType prevOptionType = TcpOptionType::TCPOPT_Unknown);
520
521
    /// Insert a new TCP option after an existing one
522
    /// @param[in] optionBuilder A TcpOptionBuilder object that contains the requested TCP option data to be
523
    /// inserted
524
    /// @param[in] prevOptionType The TCP option which the newly inserted option should come after. This is an
525
    /// optional parameter which gets a default value of TcpOptionType::Unknown if omitted, which means the new
526
    /// option will be inserted as the first option in the layer
527
    /// @return A TcpOption object containing the newly inserted TCP option data or logical null
528
    /// (TcpOption#isNull() == true) if insertion failed. In case of a failure a corresponding error message will be
529
    /// printed to log
530
    TcpOption insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder,
531
                                   TcpOptionEnumType prevOptionType = TcpOptionEnumType::Unknown);
532
533
    /// @deprecated This method is deprecated, please use removeTcpOption(TcpOptionEnumType)
534
    PCPP_DEPRECATED(PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG)
535
    bool removeTcpOption(TcpOptionType optionType);
536
537
    /// Remove an existing TCP option from the layer. TCP option is found by type
538
    /// @param[in] optionType The TCP option type to remove
539
    /// @return True if TCP option was removed or false if type wasn't found or if removal failed (in each case a
540
    /// proper error will be written to log)
541
    bool removeTcpOption(TcpOptionEnumType optionType);
542
543
    /// Remove all TCP options in this layer
544
    /// @return True if all TCP options were successfully removed or false if removal failed for some reason
545
    /// (a proper error will be written to log)
546
    bool removeAllTcpOptions();
547
548
    /// Calculate the checksum from header and data and possibly write the result to @ref tcphdr#headerChecksum
549
    /// @param[in] writeResultToPacket If set to true then checksum result will be written to @ref
550
    /// tcphdr#headerChecksum
551
    /// @return The checksum result
552
    uint16_t calculateChecksum(bool writeResultToPacket);
553
554
    /// The static method makes validation of input data
555
    /// @param[in] data The pointer to the beginning of byte stream of TCP packet
556
    /// @param[in] dataLen The length of byte stream
557
    /// @return True if the data is valid and can represent a TCP packet
558
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
559
560
    // implement abstract methods
561
562
    /// Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets
563
    /// PayloadLayer
564
    void parseNextLayer() override;
565
566
    /// @return Size of @ref tcphdr + all TCP options
567
    size_t getHeaderLen() const override
568
1.27M
    {
569
1.27M
      return getTcpHeader()->dataOffset * 4;
570
1.27M
    }
571
572
    /// Calculate @ref tcphdr#headerChecksum field
573
    void computeCalculateFields() override;
574
575
    std::string toString() const override;
576
577
    OsiModelLayer getOsiModelLayer() const override
578
110k
    {
579
110k
      return OsiModelTransportLayer;
580
110k
    }
581
582
    /// @struct SerializedFields
583
    /// Fields written by TcpLayer's serializeLayer(), in addition to
584
    /// Layer::SerializedFields.
585
    struct SerializedFields : Layer::SerializedFields
586
    {
587
      /// @return All field descriptors for TcpLayer
588
      static std::vector<FieldDescriptor> all()
589
0
      {
590
0
        auto result = Layer::SerializedFields::all();
591
0
        std::initializer_list<FieldDescriptor> extra{ SrcPort,    DstPort,  SequenceNumber, TcpFlags,
592
0
                                                    WindowSize, Checksum, Options };
593
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
594
0
        return result;
595
0
      }
596
597
      /// @brief Source port, in host byte order
598
      static const FieldDescriptor SrcPort;
599
600
      /// @brief Destination port, in host byte order
601
      static const FieldDescriptor DstPort;
602
603
      /// @brief Sequence number, in host byte order
604
      static const FieldDescriptor SequenceNumber;
605
606
      /// @brief Array of set flag names (e.g. "SYN", "ACK"); elements described by TcpFlag
607
      static const FieldDescriptor TcpFlags;
608
609
      /// @brief One set flag's name; a TcpFlags element, not in all()
610
      static const FieldDescriptor TcpFlag;
611
612
      /// @brief Window size, in host byte order
613
      static const FieldDescriptor WindowSize;
614
615
      /// @brief Checksum, as a hex string
616
      static const FieldDescriptor Checksum;
617
618
      /// @brief Array of header options; elements described by Option
619
      static const FieldDescriptor Options;
620
621
      /// One option's type name (e.g. "Mss"); an Options element,
622
      /// not included in all()
623
      static const FieldDescriptor Option;
624
    };
625
626
  protected:
627
    void serializeLayer(ObjectScope& serializer) const override;
628
629
  private:
630
    TLVRecordReader<TcpOption> m_OptionReader;
631
    int m_NumOfTrailingBytes;
632
633
    void initLayer();
634
    uint8_t* getOptionsBasePtr() const
635
323k
    {
636
323k
      return m_Data + sizeof(tcphdr);
637
323k
    }
638
    TcpOption addTcpOptionAt(const TcpOptionBuilder& optionBuilder, int offset);
639
    void adjustTcpOptionTrailer(size_t totalOptSize);
640
    void copyLayerData(const TcpLayer& other);
641
  };
642
643
  // implementation of inline methods
644
645
  bool TcpLayer::isDataValid(const uint8_t* data, size_t dataLen)
646
579k
  {
647
579k
    const tcphdr* hdr = reinterpret_cast<const tcphdr*>(data);
648
579k
    return dataLen >= sizeof(tcphdr) && hdr->dataOffset >= 5 /* the minimum TCP header size */
649
577k
           && dataLen >= hdr->dataOffset * sizeof(uint32_t);
650
579k
  }
651
}  // namespace pcpp
652
653
#undef PCPP_INTERNAL_DEPRECATE_TCP_OPTION_TYPE_MSG