Coverage Report

Created: 2026-02-14 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/Packet.cpp
Line
Count
Source
1
141k
#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
255k
  {
51
255k
    destructPacketData();
52
53
255k
    m_FirstLayer = nullptr;
54
255k
    m_LastLayer = nullptr;
55
255k
    m_MaxPacketLen = rawPacket->getRawDataLen();
56
255k
    m_FreeRawPacket = freeRawPacket;
57
255k
    m_RawPacket = rawPacket;
58
255k
    m_CanReallocateData = true;
59
60
255k
    if (m_RawPacket == nullptr)
61
0
      return;
62
63
255k
    parsePacket(PacketParseOptions{ parseUntil, parseUntilLayer });
64
255k
  }
65
66
  void Packet::parsePacket(PacketParseOptions options, bool incrementalParsing)
67
255k
  {
68
255k
    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
255k
    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
255k
    bool parsingNewLayers = false;
81
82
    // If there is no first layer, create it based on the link layer type
83
255k
    if (m_FirstLayer == nullptr)
84
255k
    {
85
255k
      parsingNewLayers = true;
86
87
255k
      LinkLayerType linkType = m_RawPacket->getLinkLayerType();
88
255k
      m_FirstLayer = createFirstLayer(linkType);
89
90
255k
      if (m_FirstLayer == nullptr)
91
3.41k
      {
92
3.41k
        PCPP_LOG_ERROR("Failed to create first layer! Possibly attempting to parse a RawPacket with no data.");
93
3.41k
        return;
94
3.41k
      }
95
96
      // Mark the first layer as allocated in the packet
97
251k
      m_FirstLayer->m_AllocationInfo.ownedByPacket = true;
98
251k
    }
99
100
251k
    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
251k
    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
251k
    bool rollbackLastLayer = false;
122
251k
    bool foundTargetProtocol = false;
123
1.26M
    for (auto* curLayer = parseStartLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
124
1.01M
    {
125
      // If we are parsing new layers, update the last layer pointer
126
      // Otherwise we are just traversing already parsed layers
127
1.01M
      if (parsingNewLayers)
128
1.01M
      {
129
        // Mark the current layer as allocated in the packet, as it was just created
130
1.01M
        curLayer->m_AllocationInfo.ownedByPacket = true;
131
1.01M
        m_LastLayer = curLayer;
132
1.01M
      }
133
134
      // If the current layer is of a higher OSI layer than the target, stop parsing
135
1.01M
      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
1.01M
      const bool matchesTarget = curLayer->isMemberOfProtocolFamily(options.parseUntilProtocol);
144
1.01M
      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
1.01M
      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
1.01M
      if (!curLayer->hasNextLayer())
160
1.01M
      {
161
1.01M
        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
1.01M
        curLayer->parseNextLayer();
165
1.01M
      }
166
1.01M
    }
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
251k
    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
251k
    if (m_LastLayer != nullptr && options.parseUntilProtocol == UnknownProtocol &&
179
251k
        options.parseUntilLayer == OsiModelLayerUnknown)
180
251k
    {
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
251k
      int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) -
184
251k
                             (m_LastLayer->getData() + m_LastLayer->getDataLen()));
185
251k
      if (trailerLen > 0)
186
23.9k
      {
187
23.9k
        PacketTrailerLayer* trailerLayer =
188
23.9k
            new PacketTrailerLayer(static_cast<uint8_t*>(m_LastLayer->getData() + m_LastLayer->getDataLen()),
189
23.9k
                                   trailerLen, m_LastLayer, this);
190
191
23.9k
        trailerLayer->m_AllocationInfo.ownedByPacket = true;
192
23.9k
        m_LastLayer->setNextLayer(trailerLayer);
193
23.9k
        m_LastLayer = trailerLayer;
194
23.9k
      }
195
251k
    }
196
251k
  }
197
198
  Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
199
255k
  {
200
255k
    m_FreeRawPacket = false;
201
255k
    m_RawPacket = nullptr;
202
255k
    m_FirstLayer = nullptr;
203
255k
    setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer);
204
255k
  }
205
206
  Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil)
207
0
  {
208
0
    m_FreeRawPacket = false;
209
0
    m_RawPacket = nullptr;
210
0
    m_FirstLayer = nullptr;
211
0
    auto parseUntilFamily = static_cast<ProtocolTypeFamily>(parseUntil);
212
0
    setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown);
213
0
  }
214
215
  Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily)
216
0
  {
217
0
    m_FreeRawPacket = false;
218
0
    m_RawPacket = nullptr;
219
0
    m_FirstLayer = nullptr;
220
0
    setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown);
221
0
  }
222
223
  Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer)
224
0
  {
225
0
    m_FreeRawPacket = false;
226
0
    m_RawPacket = nullptr;
227
0
    m_FirstLayer = nullptr;
228
0
    setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer);
229
0
  }
230
231
  void Packet::destructPacketData()
232
1.54M
  {
233
1.54M
    destroyAllLayers();
234
235
1.54M
    if (m_RawPacket != nullptr && m_FreeRawPacket)
236
1.03M
    {
237
1.03M
      delete m_RawPacket;
238
1.03M
    }
239
1.54M
  }
240
241
  void Packet::destroyAllLayers()
242
1.54M
  {
243
1.54M
    Layer* curLayer = m_FirstLayer;
244
8.13M
    while (curLayer != nullptr)
245
6.59M
    {
246
6.59M
      Layer* nextLayer = curLayer->getNextLayer();
247
6.59M
      if (curLayer->m_AllocationInfo.ownedByPacket)
248
6.59M
      {
249
6.59M
        delete curLayer;
250
6.59M
      }
251
252
6.59M
      curLayer = nextLayer;
253
6.59M
    }
254
255
1.54M
    m_FirstLayer = nullptr;
256
1.54M
    m_LastLayer = nullptr;
257
1.54M
  }
258
259
  Packet& Packet::operator=(const Packet& other)
260
0
  {
261
0
    destructPacketData();
262
263
0
    copyDataFrom(other);
264
265
0
    return *this;
266
0
  }
267
268
  void Packet::copyDataFrom(const Packet& other)
269
1.03M
  {
270
1.03M
    m_RawPacket = new RawPacket(*(other.m_RawPacket));
271
1.03M
    m_FreeRawPacket = true;
272
1.03M
    m_MaxPacketLen = other.m_MaxPacketLen;
273
1.03M
    m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType());
274
1.03M
    m_LastLayer = m_FirstLayer;
275
1.03M
    m_CanReallocateData = true;
276
1.03M
    Layer* curLayer = m_FirstLayer;
277
6.59M
    while (curLayer != nullptr)
278
5.55M
    {
279
5.55M
      curLayer->parseNextLayer();
280
5.55M
      curLayer->m_AllocationInfo.ownedByPacket = true;
281
5.55M
      curLayer = curLayer->getNextLayer();
282
5.55M
      if (curLayer != nullptr)
283
4.51M
        m_LastLayer = curLayer;
284
5.55M
    }
285
1.03M
  }
286
287
  void Packet::reallocateRawData(size_t newSize)
288
25.7k
  {
289
25.7k
    PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize);
290
291
    // allocate a new array with size newSize
292
25.7k
    m_MaxPacketLen = newSize;
293
294
    // set the new array to RawPacket
295
25.7k
    if (!m_RawPacket->reallocateData(m_MaxPacketLen))
296
0
    {
297
0
      PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes");
298
0
      return;
299
0
    }
300
301
    // set all data pointers in layers to the new array address
302
25.7k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
303
304
132k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
305
106k
    {
306
106k
      PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'");
307
106k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
308
106k
      dataPtr += curLayer->getHeaderLen();
309
106k
    }
310
25.7k
  }
311
312
  bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket)
313
0
  {
314
0
    if (newLayer == nullptr)
315
0
    {
316
0
      PCPP_LOG_ERROR("Layer to add is nullptr");
317
0
      return false;
318
0
    }
319
320
0
    if (newLayer->isAllocatedToPacket())
321
0
    {
322
0
      PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet");
323
0
      return false;
324
0
    }
325
326
0
    if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer)
327
0
    {
328
0
      PCPP_LOG_ERROR("Cannot insert layer after packet trailer");
329
0
      return false;
330
0
    }
331
332
0
    size_t newLayerHeaderLen = newLayer->getHeaderLen();
333
0
    if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen)
334
0
    {
335
0
      if (!m_CanReallocateData)
336
0
      {
337
0
        PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: "
338
0
                       << m_MaxPacketLen << " bytes");
339
0
        return false;
340
0
      }
341
      // reallocate to maximum value of: twice the max size of the packet or max size + new required length
342
0
      if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen * 2)
343
0
        reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen);
344
0
      else
345
0
        reallocateRawData(m_MaxPacketLen * 2);
346
0
    }
347
348
    // insert layer data to raw packet
349
0
    int indexToInsertData = 0;
350
0
    if (prevLayer != nullptr)
351
0
      indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData();
352
0
    m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen);
353
354
    // delete previous layer data
355
0
    delete[] newLayer->m_Data;
356
357
    // add layer to layers linked list
358
0
    if (prevLayer != nullptr)
359
0
    {
360
0
      newLayer->setNextLayer(prevLayer->getNextLayer());
361
0
      newLayer->setPrevLayer(prevLayer);
362
0
      prevLayer->setNextLayer(newLayer);
363
0
    }
364
0
    else  // prevLayer == nullptr
365
0
    {
366
0
      newLayer->setNextLayer(m_FirstLayer);
367
0
      if (m_FirstLayer != nullptr)
368
0
        m_FirstLayer->setPrevLayer(newLayer);
369
0
      m_FirstLayer = newLayer;
370
0
    }
371
372
0
    if (newLayer->getNextLayer() == nullptr)
373
0
      m_LastLayer = newLayer;
374
0
    else
375
0
      newLayer->getNextLayer()->setPrevLayer(newLayer);
376
377
    // Attach the layer to this packet. If ownInPacket is true, transfer ownership of the layer to the packet.
378
0
    newLayer->m_AllocationInfo.attachPacket(this, ownInPacket);
379
380
    // re-calculate all layers data ptr and data length
381
382
    // first, get ptr and data length of the raw packet
383
0
    const uint8_t* dataPtr = m_RawPacket->getRawData();
384
0
    size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen());
385
386
    // if a packet trailer exists, get its length
387
0
    size_t packetTrailerLen = 0;
388
0
    if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
389
0
      packetTrailerLen = m_LastLayer->getDataLen();
390
391
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each one
392
0
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
393
0
    {
394
      // set data ptr to layer
395
0
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
396
397
      // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers.
398
      // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the
399
      // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data
400
      // length
401
0
      if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
402
0
        curLayer->m_DataLen = dataLen;
403
0
      else
404
0
        curLayer->m_DataLen = dataLen - packetTrailerLen;
405
406
      // advance data ptr and data length
407
0
      dataPtr += curLayer->getHeaderLen();
408
0
      dataLen -= curLayer->getHeaderLen();
409
0
    }
410
411
0
    return true;
412
0
  }
413
414
  bool Packet::removeLayer(ProtocolType layerType, int index)
415
0
  {
416
0
    Layer* layerToRemove = getLayerOfType(layerType, index);
417
418
0
    if (layerToRemove != nullptr)
419
0
    {
420
0
      return removeLayer(layerToRemove, true);
421
0
    }
422
0
    else
423
0
    {
424
0
      PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
425
0
      return false;
426
0
    }
427
0
  }
428
429
  bool Packet::removeFirstLayer()
430
0
  {
431
0
    Layer* firstLayer = getFirstLayer();
432
0
    if (firstLayer == nullptr)
433
0
    {
434
0
      PCPP_LOG_ERROR("Packet has no layers");
435
0
      return false;
436
0
    }
437
438
0
    return removeLayer(firstLayer, true);
439
0
  }
440
441
  bool Packet::removeLastLayer()
442
0
  {
443
0
    Layer* lastLayer = getLastLayer();
444
0
    if (lastLayer == nullptr)
445
0
    {
446
0
      PCPP_LOG_ERROR("Packet has no layers");
447
0
      return false;
448
0
    }
449
450
0
    return removeLayer(lastLayer, true);
451
0
  }
452
453
  bool Packet::removeAllLayersAfter(Layer* layer)
454
0
  {
455
0
    Layer* curLayer = layer->getNextLayer();
456
0
    while (curLayer != nullptr)
457
0
    {
458
0
      Layer* tempLayer = curLayer->getNextLayer();
459
0
      if (!removeLayer(curLayer, true))
460
0
        return false;
461
0
      curLayer = tempLayer;
462
0
    }
463
464
0
    return true;
465
0
  }
466
467
  Layer* Packet::detachLayer(ProtocolType layerType, int index)
468
0
  {
469
0
    Layer* layerToDetach = getLayerOfType(layerType, index);
470
471
0
    if (layerToDetach != nullptr)
472
0
    {
473
0
      if (removeLayer(layerToDetach, false))
474
0
        return layerToDetach;
475
0
      else
476
0
        return nullptr;
477
0
    }
478
0
    else
479
0
    {
480
0
      PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
481
0
      return nullptr;
482
0
    }
483
0
  }
484
485
  bool Packet::removeLayer(Layer* layer, bool tryToDelete)
486
0
  {
487
0
    if (layer == nullptr)
488
0
    {
489
0
      PCPP_LOG_ERROR("Layer is nullptr");
490
0
      return false;
491
0
    }
492
493
    // verify layer is allocated to a packet
494
0
    if (!layer->isAllocatedToPacket())
495
0
    {
496
0
      PCPP_LOG_ERROR("Layer isn't allocated to any packet");
497
0
      return false;
498
0
    }
499
500
    // verify layer is allocated to *this* packet
501
0
    Layer* curLayer = layer;
502
0
    while (curLayer->m_PrevLayer != nullptr)
503
0
      curLayer = curLayer->m_PrevLayer;
504
0
    if (curLayer != m_FirstLayer)
505
0
    {
506
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
507
0
      return false;
508
0
    }
509
510
    // before removing the layer's data, copy it so it can be later assigned as the removed layer's data
511
0
    size_t headerLen = layer->getHeaderLen();
512
0
    size_t layerOldDataSize = headerLen;
513
0
    auto layerOldData = std::make_unique<uint8_t[]>(layerOldDataSize);
514
0
    memcpy(layerOldData.get(), layer->m_Data, layerOldDataSize);
515
516
    // remove data from raw packet
517
0
    size_t numOfBytesToRemove = headerLen;
518
0
    int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData();
519
0
    if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove))
520
0
    {
521
0
      PCPP_LOG_ERROR("Couldn't remove data from packet");
522
0
      return false;
523
0
    }
524
525
    // remove layer from layers linked list
526
0
    if (layer->m_PrevLayer != nullptr)
527
0
      layer->m_PrevLayer->setNextLayer(layer->m_NextLayer);
528
0
    if (layer->m_NextLayer != nullptr)
529
0
      layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer);
530
531
    // take care of head and tail ptrs
532
0
    if (m_FirstLayer == layer)
533
0
      m_FirstLayer = layer->m_NextLayer;
534
0
    if (m_LastLayer == layer)
535
0
      m_LastLayer = layer->m_PrevLayer;
536
0
    layer->setNextLayer(nullptr);
537
0
    layer->setPrevLayer(nullptr);
538
539
    // get packet trailer len if exists
540
0
    size_t packetTrailerLen = 0;
541
0
    if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
542
0
      packetTrailerLen = m_LastLayer->getDataLen();
543
544
    // re-calculate all layers data ptr and data length
545
546
    // first, get ptr and data length of the raw packet
547
0
    const uint8_t* dataPtr = m_RawPacket->getRawData();
548
0
    size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen());
549
550
0
    curLayer = m_FirstLayer;
551
552
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each one
553
0
    while (curLayer != nullptr)
554
0
    {
555
      // set data ptr to layer
556
0
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
557
558
      // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers.
559
      // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the
560
      // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data
561
      // length
562
0
      if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
563
0
        curLayer->m_DataLen = dataLen;
564
0
      else
565
0
        curLayer->m_DataLen = dataLen - packetTrailerLen;
566
567
      // advance data ptr and data length
568
0
      dataPtr += curLayer->getHeaderLen();
569
0
      dataLen -= curLayer->getHeaderLen();
570
571
      // move to next layer
572
0
      curLayer = curLayer->getNextLayer();
573
0
    }
574
575
    // if layer was allocated by this packet and tryToDelete flag is set, delete it
576
0
    if (tryToDelete && layer->m_AllocationInfo.ownedByPacket)
577
0
    {
578
0
      delete layer;
579
0
    }
580
    // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can
581
    // be reused
582
0
    else
583
0
    {
584
0
      layer->m_AllocationInfo.detach();
585
0
      layer->m_Data = layerOldData.release();
586
0
      layer->m_DataLen = layerOldDataSize;
587
0
    }
588
589
0
    return true;
590
0
  }
591
592
  Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const
593
0
  {
594
0
    int curIndex = 0;
595
0
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
596
0
    {
597
0
      if (curLayer->getProtocol() != layerType)
598
0
        continue;
599
600
0
      if (curIndex == index)
601
0
        return curLayer;
602
603
0
      curIndex++;
604
0
    }
605
606
0
    return nullptr;
607
0
  }
608
609
  bool Packet::isPacketOfType(ProtocolType protocolType) const
610
17.6M
  {
611
110M
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
612
93.5M
    {
613
93.5M
      if (curLayer->getProtocol() == protocolType)
614
1.08M
      {
615
1.08M
        return true;
616
1.08M
      }
617
93.5M
    }
618
619
16.5M
    return false;
620
17.6M
  }
621
622
  bool Packet::isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const
623
4.14M
  {
624
4.14M
    Layer* curLayer = getFirstLayer();
625
26.2M
    while (curLayer != nullptr)
626
22.1M
    {
627
22.1M
      if (curLayer->isMemberOfProtocolFamily(protocolTypeFamily))
628
50.4k
      {
629
50.4k
        return true;
630
50.4k
      }
631
22.1M
      curLayer = curLayer->getNextLayer();
632
22.1M
    }
633
634
4.09M
    return false;
635
4.14M
  }
636
637
  bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend)
638
98.1k
  {
639
98.1k
    if (layer == nullptr)
640
0
    {
641
0
      PCPP_LOG_ERROR("Layer is nullptr");
642
0
      return false;
643
0
    }
644
645
    // verify layer is allocated to this packet
646
98.1k
    if (!(layer->getAttachedPacket() == this))
647
0
    {
648
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
649
0
      return false;
650
0
    }
651
652
98.1k
    if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen)
653
25.7k
    {
654
25.7k
      if (!m_CanReallocateData)
655
0
      {
656
0
        PCPP_LOG_ERROR(
657
0
            "With the layer extended size the packet will exceed the size of the pre-allocated buffer: "
658
0
            << m_MaxPacketLen << " bytes");
659
0
        return false;
660
0
      }
661
      // reallocate to maximum value of: twice the max size of the packet or max size + new required length
662
25.7k
      if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen * 2)
663
19
        reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen);
664
25.7k
      else
665
25.7k
        reallocateRawData(m_MaxPacketLen * 2);
666
25.7k
    }
667
668
    // insert layer data to raw packet
669
98.1k
    int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
670
    // passing nullptr to insertData will move the data by numOfBytesToExtend
671
    // no new data has to be created for this insertion which saves at least little time
672
    // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided
673
    // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the
674
    // packet size by numOfBytesToExtend
675
98.1k
    m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend);
676
677
    // re-calculate all layers data ptr and data length
678
98.1k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
679
680
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer
681
98.1k
    bool passedExtendedLayer = false;
682
504k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
683
407k
    {
684
407k
      if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen())
685
1.20k
      {
686
1.20k
        PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary");
687
1.20k
        return false;
688
1.20k
      }
689
690
      // set the data ptr
691
405k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
692
693
      // set a flag if arrived to the layer being extended
694
405k
      if (curLayer->getPrevLayer() == layer)
695
7.48k
        passedExtendedLayer = true;
696
697
      // change the data length only for layers who come before the extended layer. For layers who come after,
698
      // data length isn't changed
699
405k
      if (!passedExtendedLayer)
700
396k
        curLayer->m_DataLen += numOfBytesToExtend;
701
702
      // assuming header length of the layer that requested to be extended hasn't been enlarged yet
703
405k
      size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0);
704
405k
      dataPtr += headerLen;
705
405k
    }
706
707
96.9k
    return true;
708
98.1k
  }
709
710
  bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten)
711
98.6k
  {
712
98.6k
    if (layer == nullptr)
713
0
    {
714
0
      PCPP_LOG_ERROR("Layer is nullptr");
715
0
      return false;
716
0
    }
717
718
    // verify layer is allocated to this packet
719
98.6k
    if (!(layer->getAttachedPacket() == this))
720
0
    {
721
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
722
0
      return false;
723
0
    }
724
725
    // remove data from raw packet
726
98.6k
    int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
727
98.6k
    if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten))
728
0
    {
729
0
      PCPP_LOG_ERROR("Couldn't remove data from packet");
730
0
      return false;
731
0
    }
732
733
    // re-calculate all layers data ptr and data length
734
98.6k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
735
736
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer
737
98.6k
    Layer* curLayer = m_FirstLayer;
738
98.6k
    bool passedExtendedLayer = false;
739
508k
    while (curLayer != nullptr)
740
409k
    {
741
409k
      if (dataPtr > m_RawPacket->getRawData() + m_RawPacket->getRawDataLen())
742
125
      {
743
125
        PCPP_LOG_ERROR("Layer data pointer exceeds packet's boundary");
744
125
        return false;
745
125
      }
746
747
      // set the data ptr
748
409k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
749
750
      // set a flag if arrived to the layer being shortened
751
409k
      if (curLayer->getPrevLayer() == layer)
752
8.35k
        passedExtendedLayer = true;
753
754
409k
      size_t headerLen = curLayer->getHeaderLen();
755
756
      // change the data length only for layers who come before the shortened layer. For layers who come after,
757
      // data length isn't changed
758
409k
      if (!passedExtendedLayer)
759
399k
        curLayer->m_DataLen -= numOfBytesToShorten;
760
761
      // assuming header length of the layer that requested to be extended hasn't been enlarged yet
762
409k
      headerLen -= (curLayer == layer ? numOfBytesToShorten : 0);
763
409k
      dataPtr += headerLen;
764
409k
      curLayer = curLayer->getNextLayer();
765
409k
    }
766
767
98.5k
    return true;
768
98.6k
  }
769
770
  void Packet::computeCalculateFields()
771
255k
  {
772
    // calculated fields should be calculated from top layer to bottom layer
773
1.29M
    for (Layer* curLayer = m_LastLayer; curLayer != nullptr; curLayer = curLayer->getPrevLayer())
774
1.03M
    {
775
1.03M
      curLayer->computeCalculateFields();
776
1.03M
    }
777
255k
  }
778
779
  std::string Packet::printPacketInfo(bool timeAsLocalTime) const
780
255k
  {
781
255k
    std::ostringstream dataLenStream;
782
255k
    dataLenStream << m_RawPacket->getRawDataLen();
783
784
    // convert raw packet timestamp to printable format
785
255k
    timespec timestamp = m_RawPacket->getPacketTimeStamp();
786
255k
    time_t nowtime = timestamp.tv_sec;
787
255k
    struct tm* nowtm = nullptr;
788
255k
#if __cplusplus > 199711L && !defined(_WIN32)
789
    // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime,
790
    // but they're defined only in newer compilers (>= C++0x).
791
    // on Windows localtime and gmtime are already thread-safe so there is not need
792
    // to use localtime_r and gmtime_r
793
255k
    struct tm nowtm_r;
794
255k
    if (timeAsLocalTime)
795
255k
      nowtm = localtime_r(&nowtime, &nowtm_r);
796
0
    else
797
0
      nowtm = gmtime_r(&nowtime, &nowtm_r);
798
799
255k
    if (nowtm != nullptr)
800
255k
      nowtm = &nowtm_r;
801
#else
802
    // on Window compilers localtime and gmtime are already thread safe.
803
    // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and
804
    // gmtime
805
    if (timeAsLocalTime)
806
      nowtm = localtime(&nowtime);
807
    else
808
      nowtm = gmtime(&nowtime);
809
#endif
810
811
255k
    char buf[128];
812
255k
    if (nowtm != nullptr)
813
255k
    {
814
255k
      char tmbuf[64];
815
255k
      strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
816
255k
      snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec);
817
255k
    }
818
0
    else
819
0
      snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000");
820
821
255k
    return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf);
822
255k
  }
823
824
  Layer* Packet::createFirstLayer(LinkLayerType linkType)
825
1.29M
  {
826
1.29M
    size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen();
827
1.29M
    if (rawDataLen == 0)
828
3.41k
      return nullptr;
829
830
1.28M
    const uint8_t* rawData = m_RawPacket->getRawData();
831
832
1.28M
    switch (linkType)
833
1.28M
    {
834
1.23M
    case LinkLayerType::LINKTYPE_ETHERNET:
835
1.23M
    {
836
1.23M
      if (EthLayer::isDataValid(rawData, rawDataLen))
837
1.21M
      {
838
1.21M
        return new EthLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
839
1.21M
      }
840
11.3k
      if (EthDot3Layer::isDataValid(rawData, rawDataLen))
841
10.9k
      {
842
10.9k
        return new EthDot3Layer(const_cast<uint8_t*>(rawData), rawDataLen, this);
843
10.9k
      }
844
348
      break;
845
11.3k
    }
846
23.2k
    case LinkLayerType::LINKTYPE_LINUX_SLL:
847
23.2k
    {
848
23.2k
      return new SllLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
849
11.3k
    }
850
8.25k
    case LinkLayerType::LINKTYPE_LINUX_SLL2:
851
8.25k
    {
852
8.25k
      if (Sll2Layer::isDataValid(rawData, rawDataLen))
853
8.02k
      {
854
8.02k
        return new Sll2Layer(const_cast<uint8_t*>(rawData), rawDataLen, this);
855
8.02k
      }
856
230
      break;
857
8.25k
    }
858
7.87k
    case LinkLayerType::LINKTYPE_NULL:
859
7.87k
    {
860
7.87k
      if (NullLoopbackLayer::isDataValid(rawData, rawDataLen))
861
7.54k
      {
862
7.54k
        return new NullLoopbackLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
863
7.54k
      }
864
332
      break;
865
7.87k
    }
866
5.15k
    case LinkLayerType::LINKTYPE_RAW:
867
6.84k
    case LinkLayerType::LINKTYPE_DLT_RAW1:
868
8.24k
    case LinkLayerType::LINKTYPE_DLT_RAW2:
869
8.24k
    {
870
8.24k
      uint8_t ipVer = rawData[0] & 0xf0;
871
8.24k
      if (ipVer == 0x40 && IPv4Layer::isDataValid(rawData, rawDataLen))
872
4.44k
      {
873
4.44k
        return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
874
4.44k
      }
875
3.80k
      if (ipVer == 0x60 && IPv6Layer::isDataValid(rawData, rawDataLen))
876
3.43k
      {
877
3.43k
        return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
878
3.43k
      }
879
372
      break;
880
3.80k
    }
881
4.48k
    case LinkLayerType::LINKTYPE_IPV4:
882
4.48k
    {
883
4.48k
      if (IPv4Layer::isDataValid(rawData, rawDataLen))
884
4.21k
      {
885
4.21k
        return new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
886
4.21k
      }
887
266
      break;
888
4.48k
    }
889
266
    case LinkLayerType::LINKTYPE_IPV6:
890
188
    {
891
188
      if (IPv6Layer::isDataValid(rawData, rawDataLen))
892
106
      {
893
106
        return new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
894
106
      }
895
82
      break;
896
188
    }
897
2.06k
    case LinkLayerType::LINKTYPE_NFLOG:
898
2.06k
    {
899
2.06k
      if (NflogLayer::isDataValid(rawData, rawDataLen))
900
2.05k
      {
901
2.05k
        return new NflogLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
902
2.05k
      }
903
10
      break;
904
2.06k
    }
905
1.92k
    case LinkLayerType::LINKTYPE_C_HDLC:
906
1.92k
    {
907
1.92k
      if (CiscoHdlcLayer::isDataValid(rawData, rawDataLen))
908
1.73k
      {
909
1.73k
        return new CiscoHdlcLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
910
1.73k
      }
911
192
      break;
912
1.92k
    }
913
682
    default:
914
      // For all other link types, we don't have a specific layer. Just break and create a PayloadLayer
915
682
      break;
916
1.28M
    }
917
918
    // unknown link type
919
2.51k
    return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
920
1.28M
  }
921
922
  std::string Packet::toString(bool timeAsLocalTime) const
923
255k
  {
924
255k
    std::vector<std::string> stringList;
925
255k
    toStringList(stringList, timeAsLocalTime);
926
255k
    return std::accumulate(stringList.begin(), stringList.end(), std::string(),
927
1.29M
                           [](std::string a, const std::string& b) { return std::move(a) + b + '\n'; });
928
255k
  }
929
930
  void Packet::toStringList(std::vector<std::string>& result, bool timeAsLocalTime) const
931
255k
  {
932
255k
    result.clear();
933
255k
    result.push_back(printPacketInfo(timeAsLocalTime));
934
935
1.29M
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
936
1.03M
    {
937
1.03M
      result.push_back(curLayer->toString());
938
1.03M
    }
939
255k
  }
940
941
}  // namespace pcpp