Coverage Report

Created: 2026-10-17 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/Packet.cpp
Line
Count
Source
1
77.4k
#define LOG_MODULE PacketLogModulePacket
2
3
#include "Packet.h"
4
#include "EthLayer.h"
5
#include "EthDot3Layer.h"
6
#include "SllLayer.h"
7
#include "Sll2Layer.h"
8
#include "NflogLayer.h"
9
#include "NullLoopbackLayer.h"
10
#include "IPv4Layer.h"
11
#include "IPv6Layer.h"
12
#include "CiscoHdlcLayer.h"
13
#include "PayloadLayer.h"
14
#include "PacketTrailerLayer.h"
15
#include "Logger.h"
16
#include <numeric>
17
#include <sstream>
18
#include <memory>
19
#ifdef _MSC_VER
20
# include <time.h>
21
# include "SystemUtils.h"
22
#endif
23
24
namespace pcpp
25
{
26
27
  Packet::Packet(size_t maxPacketLen, LinkLayerType linkType)
28
0
      : m_RawPacket(nullptr), m_FirstLayer(nullptr), m_LastLayer(nullptr), m_MaxPacketLen(maxPacketLen),
29
0
        m_FreeRawPacket(true), m_CanReallocateData(true)
30
0
  {
31
0
    timeval time;
32
0
    gettimeofday(&time, nullptr);
33
0
    uint8_t* data = new uint8_t[maxPacketLen];
34
0
    memset(data, 0, maxPacketLen);
35
0
    m_RawPacket = new RawPacket(data, 0, time, true, linkType);
36
0
  }
37
38
  Packet::Packet(uint8_t* buffer, size_t bufferSize, LinkLayerType linkType)
39
0
      : m_RawPacket(nullptr), m_FirstLayer(nullptr), m_LastLayer(nullptr), m_MaxPacketLen(bufferSize),
40
0
        m_FreeRawPacket(true), m_CanReallocateData(false)
41
0
  {
42
0
    timeval time;
43
0
    gettimeofday(&time, nullptr);
44
0
    memset(buffer, 0, bufferSize);
45
0
    m_RawPacket = new RawPacket(buffer, 0, time, false, linkType);
46
0
  }
47
48
  void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil,
49
                            OsiModelLayer parseUntilLayer)
50
191k
  {
51
191k
    destructPacketData();
52
53
191k
    m_FirstLayer = nullptr;
54
191k
    m_LastLayer = nullptr;
55
191k
    m_MaxPacketLen = rawPacket->getRawDataLen();
56
191k
    m_FreeRawPacket = freeRawPacket;
57
191k
    m_RawPacket = rawPacket;
58
191k
    m_CanReallocateData = true;
59
60
191k
    if (m_RawPacket == nullptr)
61
0
      return;
62
63
191k
    parsePacket(PacketParseOptions{ parseUntil, parseUntilLayer });
64
191k
  }
65
66
  void Packet::parsePacket(PacketParseOptions options, bool incrementalParsing)
67
191k
  {
68
191k
    if (m_RawPacket == nullptr)
69
0
    {
70
0
      throw std::runtime_error("Cannot parse packet: RawPacket is null");
71
0
    }
72
73
    // If we aren't doing an incremental parse, destroy all existing layers and start from scratch
74
191k
    if (!incrementalParsing)
75
0
    {
76
0
      destroyAllLayers();
77
0
    }
78
79
    // Flag indicating whether we are currently parsing new layers (as opposed to traversing already parsed ones).
80
191k
    bool parsingNewLayers = false;
81
82
    // If there is no first layer, create it based on the link layer type
83
191k
    if (m_FirstLayer == nullptr)
84
191k
    {
85
191k
      parsingNewLayers = true;
86
87
191k
      LinkLayerType linkType = m_RawPacket->getLinkLayerType();
88
191k
      m_FirstLayer = createFirstLayer(linkType);
89
90
191k
      if (m_FirstLayer == nullptr)
91
1.93k
      {
92
1.93k
        PCPP_LOG_ERROR("Failed to create first layer! Possibly attempting to parse a RawPacket with no data.");
93
1.93k
        return;
94
1.93k
      }
95
96
      // Mark the first layer as allocated in the packet
97
189k
      m_FirstLayer->m_AllocationInfo.ownedByPacket = true;
98
189k
    }
99
100
189k
    Layer* parseStartLayer = m_FirstLayer;
101
102
    // Fast path:
103
    //   If we are doing an incremental parse and we are not searching for a specific protocol type,
104
    //   we can directly start from the last parsed layer.
105
189k
    if (m_LastLayer != nullptr && options.parseUntilProtocol == UnknownProtocol)
106
0
    {
107
      // NOTE: Potential edge case, PacketTrailerLayer is considered DataLinkLayer.
108
      //  If the user requested a higher OSI layer, this condition would not skip the parse.
109
      //  The parse should still do nothing, as the trailer layer doesn't have a next layer,
110
      //  but it will have to go through 1 extra iteration.
111
0
      if (m_LastLayer->getOsiModelLayer() > options.parseUntilLayer)
112
0
      {
113
        // Already past the OSI target layer, nothing to do
114
0
        return;
115
0
      }
116
117
0
      parseStartLayer = m_LastLayer;
118
0
    }
119
120
    // As the stop conditions are inclusive, the parse must go one layer further and then roll back if needed
121
189k
    bool rollbackLastLayer = false;
122
189k
    bool foundTargetProtocol = false;
123
942k
    for (auto* curLayer = parseStartLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
124
752k
    {
125
      // If we are parsing new layers, update the last layer pointer
126
      // Otherwise we are just traversing already parsed layers
127
752k
      if (parsingNewLayers)
128
752k
      {
129
        // Mark the current layer as allocated in the packet, as it was just created
130
752k
        curLayer->m_AllocationInfo.ownedByPacket = true;
131
752k
        m_LastLayer = curLayer;
132
752k
      }
133
134
      // If the current layer is of a higher OSI layer than the target, stop parsing
135
752k
      if (curLayer->getOsiModelLayer() > options.parseUntilLayer)
136
0
      {
137
        // If we are traversing already parsed layers, we don't want to roll back as they must be kept as is.
138
0
        rollbackLastLayer = parsingNewLayers;
139
0
        break;
140
0
      }
141
142
      // If we are searching for a specific layer protocol, record when we find at least one target.
143
752k
      const bool matchesTarget = curLayer->isMemberOfProtocolFamily(options.parseUntilProtocol);
144
752k
      if (options.parseUntilProtocol != UnknownProtocol && matchesTarget)
145
0
      {
146
0
        foundTargetProtocol = true;
147
0
      }
148
149
      // If we have found the target protocol already, we are parsing until we find a different protocol
150
752k
      if (foundTargetProtocol && !matchesTarget)
151
0
      {
152
        // If we are traversing already parsed layers, we don't want to roll back as they must be kept as is.
153
0
        rollbackLastLayer = parsingNewLayers;
154
0
        break;
155
0
      }
156
157
      // If the current layer doesn't have a next layer yet, parse it.
158
      // This is important for the case of a re-parse where some layers may already have been parsed
159
752k
      if (!curLayer->hasNextLayer())
160
752k
      {
161
752k
        parsingNewLayers = true;  // We are now parsing new layers.
162
163
        // Parse the next layer. This will update the next layer pointer of the current layer.
164
752k
        curLayer->parseNextLayer();
165
752k
      }
166
752k
    }
167
168
    // Roll back one layer, if parsing with search condition as the conditions are inclusive.
169
    // Don't delete the first layer. If already past the target layer, treat the same as if the layer was found.
170
189k
    if (rollbackLastLayer && m_LastLayer != m_FirstLayer)
171
0
    {
172
0
      m_LastLayer = m_LastLayer->getPrevLayer();
173
0
      delete m_LastLayer->m_NextLayer;
174
0
      m_LastLayer->m_NextLayer = nullptr;
175
0
    }
176
177
    // If there is data left in the raw packet that doesn't belong to any layer, create a PacketTrailerLayer
178
189k
    if (m_LastLayer != nullptr && options.parseUntilProtocol == UnknownProtocol &&
179
189k
        options.parseUntilLayer == OsiModelLayerUnknown)
180
189k
    {
181
      // find if there is data left in the raw packet that doesn't belong to any layer. In that case it's probably
182
      // a packet trailer. create a PacketTrailerLayer layer and add it at the end of the packet
183
189k
      int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) -
184
189k
                             (m_LastLayer->getData() + m_LastLayer->getDataLen()));
185
189k
      if (trailerLen > 0)
186
19.9k
      {
187
19.9k
        PacketTrailerLayer* trailerLayer =
188
19.9k
            new PacketTrailerLayer(static_cast<uint8_t*>(m_LastLayer->getData() + m_LastLayer->getDataLen()),
189
19.9k
                                   trailerLen, m_LastLayer, this);
190
191
19.9k
        trailerLayer->m_AllocationInfo.ownedByPacket = true;
192
19.9k
        m_LastLayer->setNextLayer(trailerLayer);
193
19.9k
        m_LastLayer = trailerLayer;
194
19.9k
      }
195
189k
    }
196
189k
  }
197
198
  Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
199
191k
      : Packet(rawPacket, freeRawPacket, static_cast<ProtocolTypeFamily>(parseUntil), parseUntilLayer)
200
191k
  {}
201
202
  Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil,
203
                 OsiModelLayer parseUntilLayer)
204
191k
  {
205
191k
    m_FreeRawPacket = false;
206
191k
    m_RawPacket = nullptr;
207
191k
    m_FirstLayer = nullptr;
208
191k
    setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer);
209
191k
  }
210
211
  Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil)
212
0
  {
213
0
    m_FreeRawPacket = false;
214
0
    m_RawPacket = nullptr;
215
0
    m_FirstLayer = nullptr;
216
0
    auto parseUntilFamily = static_cast<ProtocolTypeFamily>(parseUntil);
217
0
    setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown);
218
0
  }
219
220
  Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily)
221
0
  {
222
0
    m_FreeRawPacket = false;
223
0
    m_RawPacket = nullptr;
224
0
    m_FirstLayer = nullptr;
225
0
    setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown);
226
0
  }
227
228
  Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer)
229
0
  {
230
0
    m_FreeRawPacket = false;
231
0
    m_RawPacket = nullptr;
232
0
    m_FirstLayer = nullptr;
233
0
    setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer);
234
0
  }
235
236
  void Packet::destructPacketData()
237
1.15M
  {
238
1.15M
    destroyAllLayers();
239
240
1.15M
    if (m_RawPacket != nullptr && m_FreeRawPacket)
241
772k
    {
242
772k
      delete m_RawPacket;
243
772k
    }
244
1.15M
  }
245
246
  void Packet::destroyAllLayers()
247
1.15M
  {
248
1.15M
    Layer* curLayer = m_FirstLayer;
249
5.55M
    while (curLayer != nullptr)
250
4.40M
    {
251
4.40M
      Layer* nextLayer = curLayer->getNextLayer();
252
4.40M
      if (curLayer->m_AllocationInfo.ownedByPacket)
253
4.40M
      {
254
4.40M
        delete curLayer;
255
4.40M
      }
256
257
4.40M
      curLayer = nextLayer;
258
4.40M
    }
259
260
1.15M
    m_FirstLayer = nullptr;
261
1.15M
    m_LastLayer = nullptr;
262
1.15M
  }
263
264
  Packet& Packet::operator=(const Packet& other)
265
0
  {
266
0
    destructPacketData();
267
268
0
    copyDataFrom(other);
269
270
0
    return *this;
271
0
  }
272
273
  void Packet::copyDataFrom(const Packet& other)
274
772k
  {
275
772k
    m_RawPacket = new RawPacket(*(other.m_RawPacket));
276
772k
    m_FreeRawPacket = true;
277
772k
    m_MaxPacketLen = other.m_MaxPacketLen;
278
772k
    m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType());
279
772k
    m_LastLayer = m_FirstLayer;
280
772k
    m_CanReallocateData = true;
281
772k
    Layer* curLayer = m_FirstLayer;
282
4.40M
    while (curLayer != nullptr)
283
3.62M
    {
284
3.62M
      curLayer->parseNextLayer();
285
3.62M
      curLayer->m_AllocationInfo.ownedByPacket = true;
286
3.62M
      curLayer = curLayer->getNextLayer();
287
3.62M
      if (curLayer != nullptr)
288
2.85M
        m_LastLayer = curLayer;
289
3.62M
    }
290
772k
  }
291
292
  void Packet::reallocateRawData(size_t newSize)
293
13.5k
  {
294
13.5k
    PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize);
295
296
    // allocate a new array with size newSize
297
13.5k
    m_MaxPacketLen = newSize;
298
299
    // set the new array to RawPacket
300
13.5k
    if (!m_RawPacket->reallocateData(m_MaxPacketLen))
301
0
    {
302
0
      PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes");
303
0
      return;
304
0
    }
305
306
    // set all data pointers in layers to the new array address
307
13.5k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
308
309
69.3k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
310
55.7k
    {
311
55.7k
      PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'");
312
55.7k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
313
55.7k
      dataPtr += curLayer->getHeaderLen();
314
55.7k
    }
315
13.5k
  }
316
317
  bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket)
318
0
  {
319
0
    if (newLayer == nullptr)
320
0
    {
321
0
      PCPP_LOG_ERROR("Layer to add is nullptr");
322
0
      return false;
323
0
    }
324
325
0
    if (newLayer->isAllocatedToPacket())
326
0
    {
327
0
      PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet");
328
0
      return false;
329
0
    }
330
331
0
    if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer)
332
0
    {
333
0
      PCPP_LOG_ERROR("Cannot insert layer after packet trailer");
334
0
      return false;
335
0
    }
336
337
0
    size_t newLayerHeaderLen = newLayer->getHeaderLen();
338
0
    if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen)
339
0
    {
340
0
      if (!m_CanReallocateData)
341
0
      {
342
0
        PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: "
343
0
                       << m_MaxPacketLen << " bytes");
344
0
        return false;
345
0
      }
346
      // reallocate to maximum value of: twice the max size of the packet or max size + new required length
347
0
      if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen * 2)
348
0
        reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen);
349
0
      else
350
0
        reallocateRawData(m_MaxPacketLen * 2);
351
0
    }
352
353
    // insert layer data to raw packet
354
0
    int indexToInsertData = 0;
355
0
    if (prevLayer != nullptr)
356
0
      indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData();
357
0
    m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen);
358
359
    // delete previous layer data
360
0
    delete[] newLayer->m_Data;
361
362
    // add layer to layers linked list
363
0
    if (prevLayer != nullptr)
364
0
    {
365
0
      newLayer->setNextLayer(prevLayer->getNextLayer());
366
0
      newLayer->setPrevLayer(prevLayer);
367
0
      prevLayer->setNextLayer(newLayer);
368
0
    }
369
0
    else  // prevLayer == nullptr
370
0
    {
371
0
      newLayer->setNextLayer(m_FirstLayer);
372
0
      if (m_FirstLayer != nullptr)
373
0
        m_FirstLayer->setPrevLayer(newLayer);
374
0
      m_FirstLayer = newLayer;
375
0
    }
376
377
0
    if (newLayer->getNextLayer() == nullptr)
378
0
      m_LastLayer = newLayer;
379
0
    else
380
0
      newLayer->getNextLayer()->setPrevLayer(newLayer);
381
382
    // Attach the layer to this packet. If ownInPacket is true, transfer ownership of the layer to the packet.
383
0
    newLayer->m_AllocationInfo.attachPacket(this, ownInPacket);
384
385
    // re-calculate all layers data ptr and data length
386
387
    // first, get ptr and data length of the raw packet
388
0
    const uint8_t* dataPtr = m_RawPacket->getRawData();
389
0
    size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen());
390
391
    // if a packet trailer exists, get its length
392
0
    size_t packetTrailerLen = 0;
393
0
    if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
394
0
      packetTrailerLen = m_LastLayer->getDataLen();
395
396
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each one
397
0
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
398
0
    {
399
      // set data ptr to layer
400
0
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
401
402
      // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers.
403
      // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the
404
      // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data
405
      // length
406
0
      if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
407
0
        curLayer->m_DataLen = dataLen;
408
0
      else
409
0
        curLayer->m_DataLen = dataLen - packetTrailerLen;
410
411
      // advance data ptr and data length
412
0
      dataPtr += curLayer->getHeaderLen();
413
0
      dataLen -= curLayer->getHeaderLen();
414
0
    }
415
416
0
    return true;
417
0
  }
418
419
  bool Packet::removeLayer(ProtocolType layerType, int index)
420
0
  {
421
0
    Layer* layerToRemove = getLayerOfType(layerType, index);
422
423
0
    if (layerToRemove != nullptr)
424
0
    {
425
0
      return removeLayer(layerToRemove, true);
426
0
    }
427
0
    else
428
0
    {
429
0
      PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
430
0
      return false;
431
0
    }
432
0
  }
433
434
  bool Packet::removeFirstLayer()
435
0
  {
436
0
    Layer* firstLayer = getFirstLayer();
437
0
    if (firstLayer == nullptr)
438
0
    {
439
0
      PCPP_LOG_ERROR("Packet has no layers");
440
0
      return false;
441
0
    }
442
443
0
    return removeLayer(firstLayer, true);
444
0
  }
445
446
  bool Packet::removeLastLayer()
447
0
  {
448
0
    Layer* lastLayer = getLastLayer();
449
0
    if (lastLayer == nullptr)
450
0
    {
451
0
      PCPP_LOG_ERROR("Packet has no layers");
452
0
      return false;
453
0
    }
454
455
0
    return removeLayer(lastLayer, true);
456
0
  }
457
458
  bool Packet::removeAllLayersAfter(Layer* layer)
459
0
  {
460
0
    Layer* curLayer = layer->getNextLayer();
461
0
    while (curLayer != nullptr)
462
0
    {
463
0
      Layer* tempLayer = curLayer->getNextLayer();
464
0
      if (!removeLayer(curLayer, true))
465
0
        return false;
466
0
      curLayer = tempLayer;
467
0
    }
468
469
0
    return true;
470
0
  }
471
472
  Layer* Packet::detachLayer(ProtocolType layerType, int index)
473
0
  {
474
0
    Layer* layerToDetach = getLayerOfType(layerType, index);
475
476
0
    if (layerToDetach != nullptr)
477
0
    {
478
0
      if (removeLayer(layerToDetach, false))
479
0
        return layerToDetach;
480
0
      else
481
0
        return nullptr;
482
0
    }
483
0
    else
484
0
    {
485
0
      PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
486
0
      return nullptr;
487
0
    }
488
0
  }
489
490
  bool Packet::removeLayer(Layer* layer, bool tryToDelete)
491
0
  {
492
0
    if (layer == nullptr)
493
0
    {
494
0
      PCPP_LOG_ERROR("Layer is nullptr");
495
0
      return false;
496
0
    }
497
498
    // verify layer is allocated to a packet
499
0
    if (!layer->isAllocatedToPacket())
500
0
    {
501
0
      PCPP_LOG_ERROR("Layer isn't allocated to any packet");
502
0
      return false;
503
0
    }
504
505
    // verify layer is allocated to *this* packet
506
0
    Layer* curLayer = layer;
507
0
    while (curLayer->m_PrevLayer != nullptr)
508
0
      curLayer = curLayer->m_PrevLayer;
509
0
    if (curLayer != m_FirstLayer)
510
0
    {
511
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
512
0
      return false;
513
0
    }
514
515
    // before removing the layer's data, copy it so it can be later assigned as the removed layer's data
516
0
    size_t headerLen = layer->getHeaderLen();
517
0
    size_t layerOldDataSize = headerLen;
518
0
    auto layerOldData = std::make_unique<uint8_t[]>(layerOldDataSize);
519
0
    memcpy(layerOldData.get(), layer->m_Data, layerOldDataSize);
520
521
    // remove data from raw packet
522
0
    size_t numOfBytesToRemove = headerLen;
523
0
    int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData();
524
0
    if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove))
525
0
    {
526
0
      PCPP_LOG_ERROR("Couldn't remove data from packet");
527
0
      return false;
528
0
    }
529
530
    // remove layer from layers linked list
531
0
    if (layer->m_PrevLayer != nullptr)
532
0
      layer->m_PrevLayer->setNextLayer(layer->m_NextLayer);
533
0
    if (layer->m_NextLayer != nullptr)
534
0
      layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer);
535
536
    // take care of head and tail ptrs
537
0
    if (m_FirstLayer == layer)
538
0
      m_FirstLayer = layer->m_NextLayer;
539
0
    if (m_LastLayer == layer)
540
0
      m_LastLayer = layer->m_PrevLayer;
541
0
    layer->setNextLayer(nullptr);
542
0
    layer->setPrevLayer(nullptr);
543
544
    // get packet trailer len if exists
545
0
    size_t packetTrailerLen = 0;
546
0
    if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
547
0
      packetTrailerLen = m_LastLayer->getDataLen();
548
549
    // re-calculate all layers data ptr and data length
550
551
    // first, get ptr and data length of the raw packet
552
0
    const uint8_t* dataPtr = m_RawPacket->getRawData();
553
0
    size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen());
554
555
0
    curLayer = m_FirstLayer;
556
557
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each one
558
0
    while (curLayer != nullptr)
559
0
    {
560
      // set data ptr to layer
561
0
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
562
563
      // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers.
564
      // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the
565
      // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data
566
      // length
567
0
      if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
568
0
        curLayer->m_DataLen = dataLen;
569
0
      else
570
0
        curLayer->m_DataLen = dataLen - packetTrailerLen;
571
572
      // advance data ptr and data length
573
0
      dataPtr += curLayer->getHeaderLen();
574
0
      dataLen -= curLayer->getHeaderLen();
575
576
      // move to next layer
577
0
      curLayer = curLayer->getNextLayer();
578
0
    }
579
580
    // if layer was allocated by this packet and tryToDelete flag is set, delete it
581
0
    if (tryToDelete && layer->m_AllocationInfo.ownedByPacket)
582
0
    {
583
0
      delete layer;
584
0
    }
585
    // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can
586
    // be reused
587
0
    else
588
0
    {
589
0
      layer->m_AllocationInfo.detach();
590
0
      layer->m_Data = layerOldData.release();
591
0
      layer->m_DataLen = layerOldDataSize;
592
0
    }
593
594
0
    return true;
595
0
  }
596
597
  Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const
598
0
  {
599
0
    int curIndex = 0;
600
0
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
601
0
    {
602
0
      if (curLayer->getProtocol() != layerType)
603
0
        continue;
604
605
0
      if (curIndex == index)
606
0
        return curLayer;
607
608
0
      curIndex++;
609
0
    }
610
611
0
    return nullptr;
612
0
  }
613
614
  bool Packet::isPacketOfType(ProtocolType protocolType) const
615
13.1M
  {
616
73.1M
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
617
60.8M
    {
618
60.8M
      if (curLayer->getProtocol() == protocolType)
619
838k
      {
620
838k
        return true;
621
838k
      }
622
60.8M
    }
623
624
12.2M
    return false;
625
13.1M
  }
626
627
  bool Packet::isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const
628
3.09M
  {
629
3.09M
    Layer* curLayer = getFirstLayer();
630
17.4M
    while (curLayer != nullptr)
631
14.4M
    {
632
14.4M
      if (curLayer->isMemberOfProtocolFamily(protocolTypeFamily))
633
79.2k
      {
634
79.2k
        return true;
635
79.2k
      }
636
14.3M
      curLayer = curLayer->getNextLayer();
637
14.3M
    }
638
639
3.01M
    return false;
640
3.09M
  }
641
642
  bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend)
643
49.2k
  {
644
49.2k
    if (layer == nullptr)
645
0
    {
646
0
      PCPP_LOG_ERROR("Layer is nullptr");
647
0
      return false;
648
0
    }
649
650
    // verify layer is allocated to this packet
651
49.2k
    if (!(layer->getAttachedPacket() == this))
652
0
    {
653
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
654
0
      return false;
655
0
    }
656
657
49.2k
    if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen)
658
13.5k
    {
659
13.5k
      if (!m_CanReallocateData)
660
0
      {
661
0
        PCPP_LOG_ERROR(
662
0
            "With the layer extended size the packet will exceed the size of the pre-allocated buffer: "
663
0
            << m_MaxPacketLen << " bytes");
664
0
        return false;
665
0
      }
666
      // reallocate to maximum value of: twice the max size of the packet or max size + new required length
667
13.5k
      if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen * 2)
668
444
        reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen);
669
13.0k
      else
670
13.0k
        reallocateRawData(m_MaxPacketLen * 2);
671
13.5k
    }
672
673
    // insert layer data to raw packet
674
49.2k
    int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
675
    // passing nullptr to insertData will move the data by numOfBytesToExtend
676
    // no new data has to be created for this insertion which saves at least little time
677
    // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided
678
    // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the
679
    // packet size by numOfBytesToExtend
680
49.2k
    m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend);
681
682
    // re-calculate all layers data ptr and data length
683
49.2k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
684
685
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer
686
49.2k
    bool passedExtendedLayer = false;
687
273k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
688
226k
    {
689
226k
      if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen())
690
1.83k
      {
691
1.83k
        PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary");
692
1.83k
        return false;
693
1.83k
      }
694
695
      // set the data ptr
696
224k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
697
698
      // set a flag if arrived to the layer being extended
699
224k
      if (curLayer->getPrevLayer() == layer)
700
9.78k
        passedExtendedLayer = true;
701
702
      // change the data length only for layers who come before the extended layer. For layers who come after,
703
      // data length isn't changed
704
224k
      if (!passedExtendedLayer)
705
205k
        curLayer->m_DataLen += numOfBytesToExtend;
706
707
      // assuming header length of the layer that requested to be extended hasn't been enlarged yet
708
224k
      size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0);
709
224k
      dataPtr += headerLen;
710
224k
    }
711
712
47.4k
    return true;
713
49.2k
  }
714
715
  bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten)
716
51.6k
  {
717
51.6k
    if (layer == nullptr)
718
0
    {
719
0
      PCPP_LOG_ERROR("Layer is nullptr");
720
0
      return false;
721
0
    }
722
723
    // verify layer is allocated to this packet
724
51.6k
    if (!(layer->getAttachedPacket() == this))
725
0
    {
726
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
727
0
      return false;
728
0
    }
729
730
    // remove data from raw packet
731
51.6k
    int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
732
51.6k
    if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten))
733
6
    {
734
6
      PCPP_LOG_ERROR("Couldn't remove data from packet");
735
6
      return false;
736
6
    }
737
738
    // re-calculate all layers data ptr and data length
739
51.6k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
740
741
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer
742
51.6k
    bool passedExtendedLayer = false;
743
305k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
744
254k
    {
745
254k
      if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen())
746
313
      {
747
313
        PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary");
748
313
        return false;
749
313
      }
750
751
      // set the data ptr
752
253k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
753
754
      // set a flag if arrived to the layer being shortened
755
253k
      if (curLayer->getPrevLayer() == layer)
756
14.7k
        passedExtendedLayer = true;
757
758
253k
      size_t headerLen = curLayer->getHeaderLen();
759
760
      // change the data length only for layers who come before the shortened layer. For layers who come after,
761
      // data length isn't changed
762
253k
      if (!passedExtendedLayer)
763
223k
        curLayer->m_DataLen -= numOfBytesToShorten;
764
765
      // assuming header length of the layer that requested to be extended hasn't been enlarged yet
766
253k
      headerLen -= (curLayer == layer ? numOfBytesToShorten : 0);
767
253k
      dataPtr += headerLen;
768
253k
    }
769
770
51.3k
    return true;
771
51.6k
  }
772
773
  void Packet::computeCalculateFields()
774
191k
  {
775
    // calculated fields should be calculated from top layer to bottom layer
776
964k
    for (Layer* curLayer = m_LastLayer; curLayer != nullptr; curLayer = curLayer->getPrevLayer())
777
772k
    {
778
772k
      curLayer->computeCalculateFields();
779
772k
    }
780
191k
  }
781
782
  std::string Packet::printPacketInfo(bool timeAsLocalTime) const
783
191k
  {
784
191k
    std::ostringstream dataLenStream;
785
191k
    dataLenStream << m_RawPacket->getRawDataLen();
786
787
    // convert raw packet timestamp to printable format
788
191k
    timespec timestamp = m_RawPacket->getPacketTimeStamp();
789
191k
    time_t nowtime = timestamp.tv_sec;
790
191k
    struct tm* nowtm = nullptr;
791
191k
#if __cplusplus > 199711L && !defined(_WIN32)
792
    // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime,
793
    // but they're defined only in newer compilers (>= C++0x).
794
    // on Windows localtime and gmtime are already thread-safe so there is not need
795
    // to use localtime_r and gmtime_r
796
191k
    struct tm nowtm_r;
797
191k
    if (timeAsLocalTime)
798
191k
      nowtm = localtime_r(&nowtime, &nowtm_r);
799
0
    else
800
0
      nowtm = gmtime_r(&nowtime, &nowtm_r);
801
802
191k
    if (nowtm != nullptr)
803
191k
      nowtm = &nowtm_r;
804
#else
805
    // on Window compilers localtime and gmtime are already thread safe.
806
    // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and
807
    // gmtime
808
    if (timeAsLocalTime)
809
      nowtm = localtime(&nowtime);
810
    else
811
      nowtm = gmtime(&nowtime);
812
#endif
813
814
191k
    char buf[128];
815
191k
    if (nowtm != nullptr)
816
191k
    {
817
191k
      char tmbuf[64];
818
191k
      strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
819
191k
      snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec);
820
191k
    }
821
0
    else
822
0
      snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000");
823
824
191k
    return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf);
825
191k
  }
826
827
  Layer* Packet::createFirstLayer(LinkLayerType linkType)
828
964k
  {
829
964k
    size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen();
830
964k
    if (rawDataLen == 0)
831
1.93k
      return nullptr;
832
833
962k
    const uint8_t* rawData = m_RawPacket->getRawData();
834
835
962k
    switch (linkType)
836
962k
    {
837
881k
    case LinkLayerType::LINKTYPE_ETHERNET:
838
881k
    {
839
881k
      if (EthLayer::isDataValid(rawData, rawDataLen))
840
872k
      {
841
872k
        return new EthLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
842
872k
      }
843
9.30k
      if (EthDot3Layer::isDataValid(rawData, rawDataLen))
844
9.22k
      {
845
9.22k
        return new EthDot3Layer(const_cast<uint8_t*>(rawData), rawDataLen, this);
846
9.22k
      }
847
80
      break;
848
9.30k
    }
849
13.3k
    case LinkLayerType::LINKTYPE_LINUX_SLL:
850
13.3k
    {
851
13.3k
      return new SllLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
852
9.30k
    }
853
7.67k
    case LinkLayerType::LINKTYPE_LINUX_SLL2:
854
7.67k
    {
855
7.67k
      if (Sll2Layer::isDataValid(rawData, rawDataLen))
856
7.67k
      {
857
7.67k
        return new Sll2Layer(const_cast<uint8_t*>(rawData), rawDataLen, this);
858
7.67k
      }
859
2
      break;
860
7.67k
    }
861
12.9k
    case LinkLayerType::LINKTYPE_NULL:
862
12.9k
    {
863
12.9k
      if (NullLoopbackLayer::isDataValid(rawData, rawDataLen))
864
12.6k
      {
865
12.6k
        return new NullLoopbackLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
866
12.6k
      }
867
268
      break;
868
12.9k
    }
869
6.97k
    case LinkLayerType::LINKTYPE_RAW:
870
11.7k
    case LinkLayerType::LINKTYPE_DLT_RAW1:
871
13.8k
    case LinkLayerType::LINKTYPE_DLT_RAW2:
872
13.8k
    {
873
13.8k
      uint8_t ipVer = rawData[0] & 0xf0;
874
13.8k
      if (ipVer == 0x40 && IPv4Layer::isDataValid(rawData, rawDataLen))
875
11.0k
      {
876
11.0k
        return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
877
11.0k
      }
878
2.85k
      if (ipVer == 0x60 && IPv6Layer::isDataValid(rawData, rawDataLen))
879
2.35k
      {
880
2.35k
        return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
881
2.35k
      }
882
500
      break;
883
2.85k
    }
884
29.1k
    case LinkLayerType::LINKTYPE_IPV4:
885
29.1k
    {
886
29.1k
      if (IPv4Layer::isDataValid(rawData, rawDataLen))
887
28.9k
      {
888
28.9k
        return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
889
28.9k
      }
890
208
      break;
891
29.1k
    }
892
208
    case LinkLayerType::LINKTYPE_IPV6:
893
128
    {
894
128
      if (IPv6Layer::isDataValid(rawData, rawDataLen))
895
0
      {
896
0
        return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
897
0
      }
898
128
      break;
899
128
    }
900
2.37k
    case LinkLayerType::LINKTYPE_NFLOG:
901
2.37k
    {
902
2.37k
      if (NflogLayer::isDataValid(rawData, rawDataLen))
903
2.37k
      {
904
2.37k
        return new NflogLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
905
2.37k
      }
906
0
      break;
907
2.37k
    }
908
691
    case LinkLayerType::LINKTYPE_C_HDLC:
909
691
    {
910
691
      if (CiscoHdlcLayer::isDataValid(rawData, rawDataLen))
911
531
      {
912
531
        return new CiscoHdlcLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
913
531
      }
914
160
      break;
915
691
    }
916
160
    default:
917
      // For all other link types, we don't have a specific layer. Just break and create a PayloadLayer
918
0
      break;
919
962k
    }
920
921
    // unknown link type
922
1.34k
    return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
923
962k
  }
924
925
  std::string Packet::toString(bool timeAsLocalTime) const
926
191k
  {
927
191k
    std::vector<std::string> stringList;
928
191k
    toStringList(stringList, timeAsLocalTime);
929
191k
    return std::accumulate(stringList.begin(), stringList.end(), std::string(),
930
964k
                           [](std::string a, const std::string& b) { return std::move(a) + b + '\n'; });
931
191k
  }
932
933
  void Packet::toStringList(std::vector<std::string>& result, bool timeAsLocalTime) const
934
191k
  {
935
191k
    result.clear();
936
191k
    result.push_back(printPacketInfo(timeAsLocalTime));
937
938
964k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
939
772k
    {
940
772k
      result.push_back(curLayer->toString());
941
772k
    }
942
191k
  }
943
944
  const FieldDescriptor Packet::SerializedFields::TimestampObject::Sec{ 0, "sec" };
945
  const FieldDescriptor Packet::SerializedFields::TimestampObject::NSec{ 1, "nsec" };
946
  const Packet::SerializedFields::TimestampObject Packet::SerializedFields::Timestamp{ 0, "timestamp" };
947
  const FieldDescriptor Packet::SerializedFields::FrameLength{ 1, "frameLength" };
948
  const FieldDescriptor Packet::SerializedFields::LinkLayer{ 2, "linkLayer" };
949
  const FieldDescriptor Packet::SerializedFields::LinkLayerName{ 3, "linkLayerName" };
950
  const FieldDescriptor Packet::SerializedFields::Layers{ 4, "layers" };
951
  const FieldDescriptor PacketObject{ 0, "packet" };
952
953
  void Packet::serialize(ISerializer& serializer) const
954
0
  {
955
0
    auto rawPacket = getRawPacket();
956
0
    timespec ts = rawPacket->getPacketTimeStamp();
957
958
0
    auto packetObject = serializer.writeObject(PacketObject);
959
0
    {
960
0
      auto timestamp = packetObject.writeObject(SerializedFields::Timestamp);
961
0
      timestamp.writeField(SerializedFields::TimestampObject::Sec, static_cast<uint64_t>(ts.tv_sec));
962
0
      timestamp.writeField(SerializedFields::TimestampObject::NSec, static_cast<uint64_t>(ts.tv_nsec));
963
0
    }
964
0
    packetObject.writeField(SerializedFields::FrameLength, rawPacket->getFrameLength());
965
0
    auto linkLayer = rawPacket->getLinkLayerType();
966
0
    packetObject.writeField(SerializedFields::LinkLayer, static_cast<uint16_t>(linkLayer));
967
0
    packetObject.writeField(SerializedFields::LinkLayerName, linkLayerToString(linkLayer));
968
969
0
    auto layersArray = packetObject.writeArray(SerializedFields::Layers);
970
0
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
971
0
    {
972
0
      curLayer->serialize(layersArray);
973
0
    }
974
0
  }
975
976
}  // namespace pcpp