Coverage Report

Created: 2025-07-11 07:47

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