Coverage Report

Created: 2025-08-26 07:54

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