Coverage Report

Created: 2026-06-10 07:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/TcpLayer.cpp
Line
Count
Source
1
283k
#define LOG_MODULE PacketLogModuleTcpLayer
2
3
#include "EndianPortable.h"
4
#include "TcpLayer.h"
5
#include "IPv4Layer.h"
6
#include "IPv6Layer.h"
7
#include "PayloadLayer.h"
8
#include "HttpLayer.h"
9
#include "SSLLayer.h"
10
#include "SipLayer.h"
11
#include "BgpLayer.h"
12
#include "SSHLayer.h"
13
#include "DnsLayer.h"
14
#include "DoIpLayer.h"
15
#include "TelnetLayer.h"
16
#include "TpktLayer.h"
17
#include "FtpLayer.h"
18
#include "SomeIpLayer.h"
19
#include "SmtpLayer.h"
20
#include "LdapLayer.h"
21
#include "PostgresLayer.h"
22
#include "MySqlLayer.h"
23
#include "GtpLayer.h"
24
#include "ModbusLayer.h"
25
#include "PacketUtils.h"
26
#include "Logger.h"
27
#include "DeprecationUtils.h"
28
#include <sstream>
29
30
namespace pcpp
31
{
32
33
295k
#define TCPOPT_DUMMY 0xff
34
35
  /// ~~~~~~~~~~~~~~~~
36
  /// TcpOptionBuilder
37
  /// ~~~~~~~~~~~~~~~~
38
39
  TcpOptionBuilder::TcpOptionBuilder(NopEolOptionTypes optionType)
40
0
  {
41
0
    switch (optionType)
42
0
    {
43
0
    case EOL:
44
0
      init(static_cast<uint8_t>(PCPP_TCPOPT_EOL), nullptr, 0);
45
0
      break;
46
0
    case NOP:
47
0
    default:
48
0
      init(static_cast<uint8_t>(PCPP_TCPOPT_NOP), nullptr, 0);
49
0
      break;
50
0
    }
51
0
  }
52
53
  TcpOptionBuilder::TcpOptionBuilder(const NopEolOptionEnumType optionType)
54
102k
  {
55
102k
    switch (optionType)
56
102k
    {
57
0
    case NopEolOptionEnumType::Eol:
58
0
      init(static_cast<uint8_t>(TcpOptionEnumType::Eol), nullptr, 0);
59
0
      break;
60
102k
    case NopEolOptionEnumType::Nop:
61
102k
    default:
62
102k
      init(static_cast<uint8_t>(TcpOptionEnumType::Nop), nullptr, 0);
63
102k
      break;
64
102k
    }
65
102k
  }
66
67
  TcpOption TcpOptionBuilder::build() const
68
63.3k
  {
69
63.3k
    uint8_t recType = static_cast<uint8_t>(m_RecType);
70
63.3k
    size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t);
71
72
63.3k
    if (recType == static_cast<uint8_t>(TcpOptionEnumType::Eol) ||
73
63.3k
        recType == static_cast<uint8_t>(TcpOptionEnumType::Nop))
74
63.3k
    {
75
63.3k
      if (m_RecValueLen != 0)
76
0
      {
77
0
        PCPP_LOG_ERROR(
78
0
            "TCP NOP and TCP EOL options are 1-byte long and don't have option value. Tried to set option value of size "
79
0
            << m_RecValueLen);
80
0
        return TcpOption(nullptr);
81
0
      }
82
83
63.3k
      optionSize = 1;
84
63.3k
    }
85
86
63.3k
    uint8_t* recordBuffer = new uint8_t[optionSize];
87
63.3k
    memset(recordBuffer, 0, optionSize);
88
63.3k
    recordBuffer[0] = recType;
89
63.3k
    if (optionSize > 1)
90
0
    {
91
0
      recordBuffer[1] = static_cast<uint8_t>(optionSize);
92
0
      if (optionSize > 2 && m_RecValue != nullptr)
93
0
        memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen);
94
0
    }
95
96
63.3k
    return TcpOption(recordBuffer);
97
63.3k
  }
98
99
  /// ~~~~~~~~
100
  /// TcpLayer
101
  /// ~~~~~~~~
102
103
  uint16_t TcpLayer::getSrcPort() const
104
670k
  {
105
670k
    return be16toh(getTcpHeader()->portSrc);
106
670k
  }
107
108
  uint16_t TcpLayer::getDstPort() const
109
670k
  {
110
670k
    return be16toh(getTcpHeader()->portDst);
111
670k
  }
112
113
  TcpOption TcpLayer::getTcpOption(const TcpOptionEnumType option) const
114
102k
  {
115
102k
    return m_OptionReader.getTLVRecord(static_cast<uint8_t>(option), getOptionsBasePtr(),
116
102k
                                       getHeaderLen() - sizeof(tcphdr));
117
102k
  }
118
119
  TcpOption TcpLayer::getFirstTcpOption() const
120
63.3k
  {
121
63.3k
    return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr));
122
63.3k
  }
123
124
  TcpOption TcpLayer::getNextTcpOption(TcpOption& tcpOption) const
125
202k
  {
126
202k
    TcpOption nextOpt =
127
202k
        m_OptionReader.getNextTLVRecord(tcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr));
128
202k
    if (nextOpt.isNotNull() && nextOpt.getType() == TCPOPT_DUMMY)
129
152
      return TcpOption(nullptr);
130
131
202k
    return nextOpt;
132
202k
  }
133
134
  size_t TcpLayer::getTcpOptionCount() const
135
0
  {
136
0
    return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr));
137
0
  }
138
139
  TcpOption TcpLayer::addTcpOption(const TcpOptionBuilder& optionBuilder)
140
0
  {
141
0
    return addTcpOptionAt(optionBuilder, getHeaderLen() - m_NumOfTrailingBytes);
142
0
  }
143
144
  TcpOption TcpLayer::insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder,
145
                                           const TcpOptionEnumType prevOptionType)
146
102k
  {
147
102k
    int offset = 0;
148
149
102k
    if (prevOptionType == TcpOptionEnumType::Unknown)
150
0
    {
151
0
      offset = sizeof(tcphdr);
152
0
    }
153
102k
    else
154
102k
    {
155
102k
      const TcpOption prevOpt = getTcpOption(prevOptionType);
156
102k
      if (prevOpt.isNull())
157
39.2k
      {
158
39.2k
        PCPP_LOG_ERROR("Previous option of type " << static_cast<int>(prevOptionType)
159
39.2k
                                                  << " not found, cannot add a new TCP option");
160
39.2k
        return TcpOption(nullptr);
161
39.2k
      }
162
163
63.3k
      offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data;
164
63.3k
    }
165
166
63.3k
    return addTcpOptionAt(optionBuilder, offset);
167
102k
  }
168
169
  bool TcpLayer::removeTcpOption(const TcpOptionEnumType optionType)
170
0
  {
171
0
    const TcpOption opt = getTcpOption(optionType);
172
0
    if (opt.isNull())
173
0
    {
174
0
      return false;
175
0
    }
176
177
    // calculate total TCP option size
178
0
    TcpOption curOpt = getFirstTcpOption();
179
0
    size_t totalOptSize = 0;
180
0
    while (!curOpt.isNull())
181
0
    {
182
0
      totalOptSize += curOpt.getTotalSize();
183
0
      curOpt = getNextTcpOption(curOpt);
184
0
    }
185
0
    totalOptSize -= opt.getTotalSize();
186
187
0
    int offset = opt.getRecordBasePtr() - m_Data;
188
189
0
    if (!shortenLayer(offset, opt.getTotalSize()))
190
0
    {
191
0
      return false;
192
0
    }
193
194
0
    adjustTcpOptionTrailer(totalOptSize);
195
196
0
    m_OptionReader.changeTLVRecordCount(-1);
197
198
0
    return true;
199
0
  }
200
201
  bool TcpLayer::removeAllTcpOptions()
202
0
  {
203
0
    const int offset = sizeof(tcphdr);
204
205
0
    if (!shortenLayer(offset, getHeaderLen() - offset))
206
0
      return false;
207
208
0
    getTcpHeader()->dataOffset = sizeof(tcphdr) / 4;
209
0
    m_NumOfTrailingBytes = 0;
210
0
    m_OptionReader.changeTLVRecordCount(0 - getTcpOptionCount());
211
0
    return true;
212
0
  }
213
214
  TcpOption TcpLayer::addTcpOptionAt(const TcpOptionBuilder& optionBuilder, const int offset)
215
63.3k
  {
216
63.3k
    TcpOption newOption = optionBuilder.build();
217
63.3k
    if (newOption.isNull())
218
0
      return newOption;
219
220
    // calculate total TCP option size
221
63.3k
    TcpOption curOpt = getFirstTcpOption();
222
63.3k
    size_t totalOptSize = 0;
223
265k
    while (!curOpt.isNull())
224
202k
    {
225
202k
      totalOptSize += curOpt.getTotalSize();
226
202k
      curOpt = getNextTcpOption(curOpt);
227
202k
    }
228
63.3k
    totalOptSize += newOption.getTotalSize();
229
230
63.3k
    size_t sizeToExtend = newOption.getTotalSize();
231
232
63.3k
    if (!extendLayer(offset, sizeToExtend))
233
0
    {
234
0
      PCPP_LOG_ERROR("Could not extend TcpLayer in [" << sizeToExtend << "] bytes");
235
0
      newOption.purgeRecordData();
236
0
      return TcpOption(nullptr);
237
0
    }
238
239
63.3k
    memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize());
240
241
63.3k
    newOption.purgeRecordData();
242
243
63.3k
    adjustTcpOptionTrailer(totalOptSize);
244
245
63.3k
    m_OptionReader.changeTLVRecordCount(1);
246
247
63.3k
    uint8_t* newOptPtr = m_Data + offset;
248
249
63.3k
    return TcpOption(newOptPtr);
250
63.3k
  }
251
252
  void TcpLayer::adjustTcpOptionTrailer(const size_t totalOptSize)
253
63.3k
  {
254
63.3k
    int newNumberOfTrailingBytes = 0;
255
219k
    while ((totalOptSize + newNumberOfTrailingBytes) % 4 != 0)
256
156k
      newNumberOfTrailingBytes++;
257
258
63.3k
    if (newNumberOfTrailingBytes < m_NumOfTrailingBytes)
259
0
      shortenLayer(sizeof(tcphdr) + totalOptSize, m_NumOfTrailingBytes - newNumberOfTrailingBytes - 1);
260
63.3k
    else if (newNumberOfTrailingBytes > m_NumOfTrailingBytes)
261
54.0k
      extendLayer(sizeof(tcphdr) + totalOptSize, newNumberOfTrailingBytes - m_NumOfTrailingBytes);
262
263
63.3k
    m_NumOfTrailingBytes = newNumberOfTrailingBytes;
264
265
219k
    for (int i = 0; i < m_NumOfTrailingBytes; i++)
266
156k
      m_Data[sizeof(tcphdr) + totalOptSize + i] = TCPOPT_DUMMY;
267
268
63.3k
    getTcpHeader()->dataOffset = (sizeof(tcphdr) + totalOptSize + m_NumOfTrailingBytes) / 4;
269
63.3k
  }
270
271
  uint16_t TcpLayer::calculateChecksum(const bool writeResultToPacket)
272
102k
  {
273
102k
    tcphdr* tcpHdr = getTcpHeader();
274
102k
    uint16_t checksumRes = 0;
275
102k
    const uint16_t currChecksumValue = tcpHdr->headerChecksum;
276
277
102k
    if (m_PrevLayer != nullptr)
278
102k
    {
279
102k
      tcpHdr->headerChecksum = 0;
280
102k
      PCPP_LOG_DEBUG("TCP data len = " << m_DataLen);
281
282
102k
      if (m_PrevLayer->getProtocol() == IPv4)
283
84.0k
      {
284
84.0k
        const IPv4Address srcIP = static_cast<IPv4Layer*>(m_PrevLayer)->getSrcIPv4Address();
285
84.0k
        const IPv4Address dstIP = static_cast<IPv4Layer*>(m_PrevLayer)->getDstIPv4Address();
286
287
84.0k
        checksumRes =
288
84.0k
            pcpp::computePseudoHdrChecksum(reinterpret_cast<uint8_t*>(tcpHdr), getDataLen(),
289
84.0k
                                           IPAddress::IPv4AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP);
290
291
84.0k
        PCPP_LOG_DEBUG("calculated IPv4 TCP checksum = 0x" << std::uppercase << std::hex << checksumRes);
292
84.0k
      }
293
18.5k
      else if (m_PrevLayer->getProtocol() == IPv6)
294
18.5k
      {
295
18.5k
        const IPv6Address srcIP = static_cast<IPv6Layer*>(m_PrevLayer)->getSrcIPv6Address();
296
18.5k
        const IPv6Address dstIP = static_cast<IPv6Layer*>(m_PrevLayer)->getDstIPv6Address();
297
298
18.5k
        checksumRes = computePseudoHdrChecksum(reinterpret_cast<uint8_t*>(tcpHdr), getDataLen(),
299
18.5k
                                               IPAddress::IPv6AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP);
300
301
18.5k
        PCPP_LOG_DEBUG("calculated IPv6 TCP checksum = 0xX" << std::uppercase << std::hex << checksumRes);
302
18.5k
      }
303
102k
    }
304
305
102k
    if (writeResultToPacket)
306
102k
      tcpHdr->headerChecksum = htobe16(checksumRes);
307
0
    else
308
0
      tcpHdr->headerChecksum = currChecksumValue;
309
310
102k
    return checksumRes;
311
102k
  }
312
313
  void TcpLayer::initLayer()
314
0
  {
315
0
    m_DataLen = sizeof(tcphdr);
316
0
    m_Data = new uint8_t[m_DataLen];
317
0
    memset(m_Data, 0, m_DataLen);
318
0
    m_Protocol = TCP;
319
0
    m_NumOfTrailingBytes = 0;
320
0
    getTcpHeader()->dataOffset = sizeof(tcphdr) / 4;
321
0
  }
322
323
  TcpLayer::TcpLayer(uint8_t* data, const size_t dataLen, Layer* prevLayer, Packet* packet)
324
560k
      : Layer(data, dataLen, prevLayer, packet, TCP)
325
560k
  {
326
560k
    m_NumOfTrailingBytes = 0;
327
560k
  }
328
329
  TcpLayer::TcpLayer()
330
0
  {
331
0
    initLayer();
332
0
  }
333
334
  TcpLayer::TcpLayer(const uint16_t portSrc, const uint16_t portDst)
335
0
  {
336
0
    initLayer();
337
0
    getTcpHeader()->portDst = htobe16(portDst);
338
0
    getTcpHeader()->portSrc = htobe16(portSrc);
339
0
  }
340
341
  void TcpLayer::copyLayerData(const TcpLayer& other)
342
102k
  {
343
102k
    m_OptionReader = other.m_OptionReader;
344
102k
    m_NumOfTrailingBytes = other.m_NumOfTrailingBytes;
345
102k
  }
346
347
102k
  TcpLayer::TcpLayer(const TcpLayer& other) : Layer(other)
348
102k
  {
349
102k
    copyLayerData(other);
350
102k
  }
351
352
  TcpLayer& TcpLayer::operator=(const TcpLayer& other)
353
0
  {
354
0
    Layer::operator=(other);
355
356
0
    copyLayerData(other);
357
358
0
    return *this;
359
0
  }
360
361
  void TcpLayer::parseNextLayer()
362
560k
  {
363
560k
    const size_t headerLen = getHeaderLen();
364
560k
    if (m_DataLen <= headerLen)
365
95.1k
      return;
366
367
465k
    uint8_t* payload = m_Data + headerLen;
368
465k
    const size_t payloadLen = m_DataLen - headerLen;
369
465k
    const uint16_t portDst = getDstPort();
370
465k
    const uint16_t portSrc = getSrcPort();
371
465k
    const char* payloadChar = reinterpret_cast<const char*>(payload);
372
373
465k
    if (HttpMessage::isHttpPort(portDst) &&
374
18.8k
        HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown)
375
6.58k
    {
376
6.58k
      constructNextLayer<HttpRequestLayer>(payload, payloadLen, getAttachedPacket());
377
6.58k
    }
378
458k
    else if (HttpMessage::isHttpPort(portSrc) &&
379
37.7k
             HttpResponseFirstLine::parseVersion(payloadChar, payloadLen) != HttpVersion::HttpVersionUnknown &&
380
12.7k
             !HttpResponseFirstLine::parseStatusCode(payloadChar, payloadLen).isUnsupportedCode())
381
11.4k
    {
382
11.4k
      constructNextLayer<HttpResponseLayer>(payload, payloadLen, getAttachedPacket());
383
11.4k
    }
384
447k
    else if (SSLLayer::IsSSLMessage(portSrc, portDst, payload, payloadLen))
385
124k
    {
386
124k
      constructNextLayerFromFactory(SSLLayer::createSSLMessage, payload, payloadLen);
387
124k
    }
388
322k
    else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc))
389
33
    {
390
33
      if (SipRequestFirstLine::parseMethod(payloadChar, payloadLen) != SipRequestLayer::SipMethodUnknown)
391
0
      {
392
0
        constructNextLayer<SipRequestLayer>(payload, payloadLen, getAttachedPacket());
393
0
      }
394
33
      else if (SipResponseFirstLine::parseStatusCode(payloadChar, payloadLen) !=
395
33
               SipResponseLayer::SipStatusCodeUnknown)
396
0
      {
397
0
        constructNextLayer<SipResponseLayer>(payload, payloadLen, getAttachedPacket());
398
0
      }
399
33
      else
400
33
      {
401
33
        constructNextLayer<PayloadLayer>(payload, payloadLen, getAttachedPacket());
402
33
      }
403
33
    }
404
322k
    else if (BgpLayer::isBgpPort(portSrc, portDst))
405
54.8k
    {
406
54.8k
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(BgpLayer::parseBgpLayer, payload, payloadLen);
407
54.8k
    }
408
267k
    else if (SSHLayer::isSSHPort(portSrc, portDst))
409
15.7k
    {
410
15.7k
      constructNextLayerFromFactory(SSHLayer::createSSHMessage, payload, payloadLen);
411
15.7k
    }
412
251k
    else if (DnsLayer::isDataValid(payload, payloadLen, true) &&
413
223k
             (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc)))
414
20.6k
    {
415
20.6k
      constructNextLayer<DnsOverTcpLayer>(payload, payloadLen, getAttachedPacket());
416
20.6k
    }
417
230k
    else if (TelnetLayer::isDataValid(payload, payloadLen) &&
418
230k
             (TelnetLayer::isTelnetPort(portDst) || TelnetLayer::isTelnetPort(portSrc)))
419
61.7k
    {
420
61.7k
      constructNextLayer<TelnetLayer>(payload, payloadLen, getAttachedPacket());
421
61.7k
    }
422
169k
    else if (FtpLayer::isFtpPort(portSrc) && FtpLayer::isDataValid(payload, payloadLen))
423
11.0k
    {
424
11.0k
      constructNextLayer<FtpResponseLayer>(payload, payloadLen, getAttachedPacket());
425
11.0k
    }
426
158k
    else if (FtpLayer::isFtpPort(portDst) && FtpLayer::isDataValid(payload, payloadLen))
427
0
    {
428
0
      constructNextLayer<FtpRequestLayer>(payload, payloadLen, getAttachedPacket());
429
0
    }
430
158k
    else if (FtpLayer::isFtpDataPort(portSrc) || FtpLayer::isFtpDataPort(portDst))
431
3.45k
    {
432
3.45k
      constructNextLayer<FtpDataLayer>(payload, payloadLen, getAttachedPacket());
433
3.45k
    }
434
154k
    else if ((DoIpLayer::isDoIpPort(portSrc) || DoIpLayer::isDoIpPort(portDst)) &&
435
18.0k
             (DoIpLayer::isDataValid(payload, payloadLen)))
436
14.0k
    {
437
14.0k
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(DoIpLayer::parseDoIpLayer, payload, payloadLen);
438
14.0k
    }
439
140k
    else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst))
440
75
    {
441
75
      constructNextLayerFromFactory(SomeIpLayer::parseSomeIpLayer, payload, payloadLen);
442
75
    }
443
140k
    else if (TpktLayer::isDataValid(payload, payloadLen) && TpktLayer::isTpktPort(portSrc, portDst))
444
25.3k
    {
445
25.3k
      constructNextLayer<TpktLayer>(payload, payloadLen, getAttachedPacket());
446
25.3k
    }
447
115k
    else if (SmtpLayer::isSmtpPort(portSrc) && SmtpLayer::isDataValid(payload, payloadLen))
448
131
    {
449
131
      constructNextLayer<SmtpResponseLayer>(payload, payloadLen, getAttachedPacket());
450
131
    }
451
115k
    else if (SmtpLayer::isSmtpPort(portDst) && SmtpLayer::isDataValid(payload, payloadLen))
452
243
    {
453
243
      constructNextLayer<SmtpRequestLayer>(payload, payloadLen, getAttachedPacket());
454
243
    }
455
114k
    else if (LdapLayer::isLdapPort(portDst) || LdapLayer::isLdapPort(portSrc))
456
39.9k
    {
457
39.9k
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(LdapLayer::parseLdapMessage, payload,
458
39.9k
                                                                 payloadLen);
459
39.9k
    }
460
74.8k
    else if (PostgresLayer::isPostgresPort(portDst))
461
39
    {
462
39
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(PostgresLayer::parsePostgresFrontendMessages,
463
39
                                                                 payload, payloadLen);
464
39
    }
465
74.8k
    else if (PostgresLayer::isPostgresPort(portSrc))
466
65
    {
467
65
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(PostgresLayer::parsePostgresBackendMessages,
468
65
                                                                 payload, payloadLen);
469
65
    }
470
74.7k
    else if (MySqlLayer::isMySqlPort(portSrc))
471
515
    {
472
515
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(MySqlLayer::parseMySqlServerMessage, payload,
473
515
                                                                 payloadLen);
474
515
    }
475
74.2k
    else if (MySqlLayer::isMySqlPort(portDst))
476
855
    {
477
855
      tryConstructNextLayerFromFactoryWithFallback<PayloadLayer>(MySqlLayer::parseMySqlClientMessage, payload,
478
855
                                                                 payloadLen);
479
855
    }
480
73.3k
    else if ((GtpV2Layer::isGTPv2Port(portDst) || GtpV2Layer::isGTPv2Port(portSrc)) &&
481
0
             GtpV2Layer::isDataValid(payload, payloadLen))
482
0
    {
483
0
      constructNextLayer<GtpV2Layer>(payload, payloadLen, getAttachedPacket());
484
0
    }
485
73.3k
    else if (ModbusLayer::isModbusPort(portDst))
486
0
    {
487
0
      constructNextLayer<ModbusLayer>(payload, payloadLen, getAttachedPacket());
488
0
    }
489
73.3k
    else
490
73.3k
    {
491
73.3k
      constructNextLayer<PayloadLayer>(payload, payloadLen, getAttachedPacket());
492
73.3k
    }
493
465k
  }
494
495
  void TcpLayer::computeCalculateFields()
496
102k
  {
497
102k
    tcphdr* tcpHdr = getTcpHeader();
498
499
102k
    tcpHdr->dataOffset = getHeaderLen() >> 2;
500
102k
    calculateChecksum(true);
501
102k
  }
502
503
  std::string TcpLayer::toString() const
504
205k
  {
505
205k
    const tcphdr* hdr = getTcpHeader();
506
205k
    std::string result = "TCP Layer, ";
507
205k
    if (hdr->synFlag)
508
17.7k
    {
509
17.7k
      if (hdr->ackFlag)
510
7.91k
        result += "[SYN, ACK], ";
511
9.85k
      else
512
9.85k
        result += "[SYN], ";
513
17.7k
    }
514
187k
    else if (hdr->finFlag)
515
10.4k
    {
516
10.4k
      if (hdr->ackFlag)
517
9.03k
        result += "[FIN, ACK], ";
518
1.41k
      else
519
1.41k
        result += "[FIN], ";
520
10.4k
    }
521
177k
    else if (hdr->ackFlag)
522
175k
      result += "[ACK], ";
523
524
205k
    std::ostringstream srcPortStream;
525
205k
    srcPortStream << getSrcPort();
526
205k
    std::ostringstream dstPortStream;
527
205k
    dstPortStream << getDstPort();
528
205k
    result += "Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str();
529
530
205k
    return result;
531
205k
  }
532
533
  /// ~~~~~~~~
534
  /// TcpLayer Deprecated Code
535
  /// ~~~~~~~~
536
537
  DISABLE_WARNING_PUSH
538
  DISABLE_WARNING_DEPRECATED
539
  TcpOption TcpLayer::addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType)
540
0
  {
541
0
    int offset = 0;
542
543
0
    if (prevOptionType == TcpOptionType::TCPOPT_Unknown)
544
0
    {
545
0
      offset = sizeof(tcphdr);
546
0
    }
547
0
    else
548
0
    {
549
0
      TcpOption prevOpt = getTcpOption(prevOptionType);
550
0
      if (prevOpt.isNull())
551
0
      {
552
0
        PCPP_LOG_ERROR("Previous option of type " << static_cast<int>(prevOptionType)
553
0
                                                  << " not found, cannot add a new TCP option");
554
0
        return TcpOption(nullptr);
555
0
      }
556
557
0
      offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data;
558
0
    }
559
560
0
    return addTcpOptionAt(optionBuilder, offset);
561
0
  }
562
563
  TcpOption TcpLayer::getTcpOption(TcpOptionType option) const
564
0
  {
565
0
    return m_OptionReader.getTLVRecord(static_cast<uint8_t>(option), getOptionsBasePtr(),
566
0
                                       getHeaderLen() - sizeof(tcphdr));
567
0
  }
568
569
  bool TcpLayer::removeTcpOption(TcpOptionType optionType)
570
0
  {
571
0
    TcpOption opt = getTcpOption(optionType);
572
0
    if (opt.isNull())
573
0
    {
574
0
      return false;
575
0
    }
576
577
    // calculate total TCP option size
578
0
    TcpOption curOpt = getFirstTcpOption();
579
0
    size_t totalOptSize = 0;
580
0
    while (!curOpt.isNull())
581
0
    {
582
0
      totalOptSize += curOpt.getTotalSize();
583
0
      curOpt = getNextTcpOption(curOpt);
584
0
    }
585
0
    totalOptSize -= opt.getTotalSize();
586
587
0
    int offset = opt.getRecordBasePtr() - m_Data;
588
589
0
    if (!shortenLayer(offset, opt.getTotalSize()))
590
0
    {
591
0
      return false;
592
0
    }
593
594
0
    adjustTcpOptionTrailer(totalOptSize);
595
596
0
    m_OptionReader.changeTLVRecordCount(-1);
597
598
0
    return true;
599
0
  }
600
  DISABLE_WARNING_POP
601
602
}  // namespace pcpp