Coverage Report

Created: 2025-10-10 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/Packet.cpp
Line
Count
Source
1
118k
#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
159k
  {
51
159k
    destructPacketData();
52
53
159k
    m_FirstLayer = nullptr;
54
159k
    m_LastLayer = nullptr;
55
159k
    m_MaxPacketLen = rawPacket->getRawDataLen();
56
159k
    m_FreeRawPacket = freeRawPacket;
57
159k
    m_RawPacket = rawPacket;
58
159k
    m_CanReallocateData = true;
59
159k
    if (m_RawPacket == nullptr)
60
0
      return;
61
62
159k
    LinkLayerType linkType = m_RawPacket->getLinkLayerType();
63
64
159k
    m_FirstLayer = createFirstLayer(linkType);
65
66
    // As the stop conditions are inclusive, the parse must go one layer further and then roll back if needed
67
159k
    bool rollbackLastLayer = false;
68
159k
    bool foundTargetProtocol = false;
69
816k
    for (auto* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
70
657k
    {
71
      // Mark the current layer as allocated in the packet
72
657k
      curLayer->m_IsAllocatedInPacket = true;
73
657k
      m_LastLayer = curLayer;  // Update last layer to current layer
74
75
      // If the current layer is of a higher OSI layer than the target, stop parsing
76
657k
      if (curLayer->getOsiModelLayer() > parseUntilLayer)
77
0
      {
78
0
        rollbackLastLayer = true;
79
0
        break;
80
0
      }
81
82
      // If we are searching for a specific layer protocol, record when we find at least one target.
83
657k
      const bool matchesTarget = curLayer->isMemberOfProtocolFamily(parseUntil);
84
657k
      if (parseUntil != UnknownProtocol && matchesTarget)
85
0
      {
86
0
        foundTargetProtocol = true;
87
0
      }
88
89
      // If we have found the target protocol already, we are parsing until we find a different protocol
90
657k
      if (foundTargetProtocol && !matchesTarget)
91
0
      {
92
0
        rollbackLastLayer = true;
93
0
        break;
94
0
      }
95
96
      // Parse the next layer. This will update the next layer pointer of the current layer.
97
657k
      curLayer->parseNextLayer();
98
657k
    }
99
100
    // Roll back one layer, if parsing with search condition as the conditions are inclusive.
101
    // Don't delete the first layer. If already past the target layer, treat the same as if the layer was found.
102
159k
    if (rollbackLastLayer && m_LastLayer != m_FirstLayer)
103
0
    {
104
0
      m_LastLayer = m_LastLayer->getPrevLayer();
105
0
      delete m_LastLayer->m_NextLayer;
106
0
      m_LastLayer->m_NextLayer = nullptr;
107
0
    }
108
109
    // If there is data left in the raw packet that doesn't belong to any layer, create a PacketTrailerLayer
110
159k
    if (m_LastLayer != nullptr && parseUntil == UnknownProtocol && parseUntilLayer == OsiModelLayerUnknown)
111
159k
    {
112
      // find if there is data left in the raw packet that doesn't belong to any layer. In that case it's probably
113
      // a packet trailer. create a PacketTrailerLayer layer and add it at the end of the packet
114
159k
      int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) -
115
159k
                             (m_LastLayer->getData() + m_LastLayer->getDataLen()));
116
159k
      if (trailerLen > 0)
117
35.7k
      {
118
35.7k
        PacketTrailerLayer* trailerLayer =
119
35.7k
            new PacketTrailerLayer(static_cast<uint8_t*>(m_LastLayer->getData() + m_LastLayer->getDataLen()),
120
35.7k
                                   trailerLen, m_LastLayer, this);
121
122
35.7k
        trailerLayer->m_IsAllocatedInPacket = true;
123
35.7k
        m_LastLayer->setNextLayer(trailerLayer);
124
35.7k
        m_LastLayer = trailerLayer;
125
35.7k
      }
126
159k
    }
127
159k
  }
128
129
  Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer)
130
159k
  {
131
159k
    m_FreeRawPacket = false;
132
159k
    m_RawPacket = nullptr;
133
159k
    m_FirstLayer = nullptr;
134
159k
    setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer);
135
159k
  }
136
137
  Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil)
138
0
  {
139
0
    m_FreeRawPacket = false;
140
0
    m_RawPacket = nullptr;
141
0
    m_FirstLayer = nullptr;
142
0
    auto parseUntilFamily = static_cast<ProtocolTypeFamily>(parseUntil);
143
0
    setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown);
144
0
  }
145
146
  Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily)
147
0
  {
148
0
    m_FreeRawPacket = false;
149
0
    m_RawPacket = nullptr;
150
0
    m_FirstLayer = nullptr;
151
0
    setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown);
152
0
  }
153
154
  Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer)
155
0
  {
156
0
    m_FreeRawPacket = false;
157
0
    m_RawPacket = nullptr;
158
0
    m_FirstLayer = nullptr;
159
0
    setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer);
160
0
  }
161
162
  void Packet::destructPacketData()
163
1.01M
  {
164
1.01M
    Layer* curLayer = m_FirstLayer;
165
4.99M
    while (curLayer != nullptr)
166
3.97M
    {
167
3.97M
      Layer* nextLayer = curLayer->getNextLayer();
168
3.97M
      if (curLayer->m_IsAllocatedInPacket)
169
3.97M
        delete curLayer;
170
3.97M
      curLayer = nextLayer;
171
3.97M
    }
172
173
1.01M
    if (m_RawPacket != nullptr && m_FreeRawPacket)
174
693k
    {
175
693k
      delete m_RawPacket;
176
693k
    }
177
1.01M
  }
178
179
  Packet& Packet::operator=(const Packet& other)
180
0
  {
181
0
    destructPacketData();
182
183
0
    copyDataFrom(other);
184
185
0
    return *this;
186
0
  }
187
188
  void Packet::copyDataFrom(const Packet& other)
189
693k
  {
190
693k
    m_RawPacket = new RawPacket(*(other.m_RawPacket));
191
693k
    m_FreeRawPacket = true;
192
693k
    m_MaxPacketLen = other.m_MaxPacketLen;
193
693k
    m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType());
194
693k
    m_LastLayer = m_FirstLayer;
195
693k
    m_CanReallocateData = true;
196
693k
    Layer* curLayer = m_FirstLayer;
197
3.97M
    while (curLayer != nullptr)
198
3.28M
    {
199
3.28M
      curLayer->parseNextLayer();
200
3.28M
      curLayer->m_IsAllocatedInPacket = true;
201
3.28M
      curLayer = curLayer->getNextLayer();
202
3.28M
      if (curLayer != nullptr)
203
2.59M
        m_LastLayer = curLayer;
204
3.28M
    }
205
693k
  }
206
207
  void Packet::reallocateRawData(size_t newSize)
208
18.7k
  {
209
18.7k
    PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize);
210
211
    // allocate a new array with size newSize
212
18.7k
    m_MaxPacketLen = newSize;
213
214
    // set the new array to RawPacket
215
18.7k
    if (!m_RawPacket->reallocateData(m_MaxPacketLen))
216
0
    {
217
0
      PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes");
218
0
      return;
219
0
    }
220
221
    // set all data pointers in layers to the new array address
222
18.7k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
223
224
113k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
225
94.6k
    {
226
94.6k
      PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'");
227
94.6k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
228
94.6k
      dataPtr += curLayer->getHeaderLen();
229
94.6k
    }
230
18.7k
  }
231
232
  bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket)
233
0
  {
234
0
    if (newLayer == nullptr)
235
0
    {
236
0
      PCPP_LOG_ERROR("Layer to add is nullptr");
237
0
      return false;
238
0
    }
239
240
0
    if (newLayer->isAllocatedToPacket())
241
0
    {
242
0
      PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet");
243
0
      return false;
244
0
    }
245
246
0
    if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer)
247
0
    {
248
0
      PCPP_LOG_ERROR("Cannot insert layer after packet trailer");
249
0
      return false;
250
0
    }
251
252
0
    size_t newLayerHeaderLen = newLayer->getHeaderLen();
253
0
    if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen)
254
0
    {
255
0
      if (!m_CanReallocateData)
256
0
      {
257
0
        PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: "
258
0
                       << m_MaxPacketLen << " bytes");
259
0
        return false;
260
0
      }
261
      // reallocate to maximum value of: twice the max size of the packet or max size + new required length
262
0
      if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen * 2)
263
0
        reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen);
264
0
      else
265
0
        reallocateRawData(m_MaxPacketLen * 2);
266
0
    }
267
268
    // insert layer data to raw packet
269
0
    int indexToInsertData = 0;
270
0
    if (prevLayer != nullptr)
271
0
      indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData();
272
0
    m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen);
273
274
    // delete previous layer data
275
0
    delete[] newLayer->m_Data;
276
277
    // add layer to layers linked list
278
0
    if (prevLayer != nullptr)
279
0
    {
280
0
      newLayer->setNextLayer(prevLayer->getNextLayer());
281
0
      newLayer->setPrevLayer(prevLayer);
282
0
      prevLayer->setNextLayer(newLayer);
283
0
    }
284
0
    else  // prevLayer == nullptr
285
0
    {
286
0
      newLayer->setNextLayer(m_FirstLayer);
287
0
      if (m_FirstLayer != nullptr)
288
0
        m_FirstLayer->setPrevLayer(newLayer);
289
0
      m_FirstLayer = newLayer;
290
0
    }
291
292
0
    if (newLayer->getNextLayer() == nullptr)
293
0
      m_LastLayer = newLayer;
294
0
    else
295
0
      newLayer->getNextLayer()->setPrevLayer(newLayer);
296
297
    // assign layer with this packet only
298
0
    newLayer->m_Packet = this;
299
300
    // Set flag to indicate if new layer is allocated to packet.
301
0
    if (ownInPacket)
302
0
      newLayer->m_IsAllocatedInPacket = true;
303
304
    // re-calculate all layers data ptr and data length
305
306
    // first, get ptr and data length of the raw packet
307
0
    const uint8_t* dataPtr = m_RawPacket->getRawData();
308
0
    size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen());
309
310
    // if a packet trailer exists, get its length
311
0
    size_t packetTrailerLen = 0;
312
0
    if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
313
0
      packetTrailerLen = m_LastLayer->getDataLen();
314
315
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each one
316
0
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
317
0
    {
318
      // set data ptr to layer
319
0
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
320
321
      // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers.
322
      // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the
323
      // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data
324
      // length
325
0
      if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
326
0
        curLayer->m_DataLen = dataLen;
327
0
      else
328
0
        curLayer->m_DataLen = dataLen - packetTrailerLen;
329
330
      // advance data ptr and data length
331
0
      dataPtr += curLayer->getHeaderLen();
332
0
      dataLen -= curLayer->getHeaderLen();
333
0
    }
334
335
0
    return true;
336
0
  }
337
338
  bool Packet::removeLayer(ProtocolType layerType, int index)
339
0
  {
340
0
    Layer* layerToRemove = getLayerOfType(layerType, index);
341
342
0
    if (layerToRemove != nullptr)
343
0
    {
344
0
      return removeLayer(layerToRemove, true);
345
0
    }
346
0
    else
347
0
    {
348
0
      PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
349
0
      return false;
350
0
    }
351
0
  }
352
353
  bool Packet::removeFirstLayer()
354
0
  {
355
0
    Layer* firstLayer = getFirstLayer();
356
0
    if (firstLayer == nullptr)
357
0
    {
358
0
      PCPP_LOG_ERROR("Packet has no layers");
359
0
      return false;
360
0
    }
361
362
0
    return removeLayer(firstLayer, true);
363
0
  }
364
365
  bool Packet::removeLastLayer()
366
0
  {
367
0
    Layer* lastLayer = getLastLayer();
368
0
    if (lastLayer == nullptr)
369
0
    {
370
0
      PCPP_LOG_ERROR("Packet has no layers");
371
0
      return false;
372
0
    }
373
374
0
    return removeLayer(lastLayer, true);
375
0
  }
376
377
  bool Packet::removeAllLayersAfter(Layer* layer)
378
0
  {
379
0
    Layer* curLayer = layer->getNextLayer();
380
0
    while (curLayer != nullptr)
381
0
    {
382
0
      Layer* tempLayer = curLayer->getNextLayer();
383
0
      if (!removeLayer(curLayer, true))
384
0
        return false;
385
0
      curLayer = tempLayer;
386
0
    }
387
388
0
    return true;
389
0
  }
390
391
  Layer* Packet::detachLayer(ProtocolType layerType, int index)
392
0
  {
393
0
    Layer* layerToDetach = getLayerOfType(layerType, index);
394
395
0
    if (layerToDetach != nullptr)
396
0
    {
397
0
      if (removeLayer(layerToDetach, false))
398
0
        return layerToDetach;
399
0
      else
400
0
        return nullptr;
401
0
    }
402
0
    else
403
0
    {
404
0
      PCPP_LOG_ERROR("Layer of the requested type was not found in packet");
405
0
      return nullptr;
406
0
    }
407
0
  }
408
409
  bool Packet::removeLayer(Layer* layer, bool tryToDelete)
410
0
  {
411
0
    if (layer == nullptr)
412
0
    {
413
0
      PCPP_LOG_ERROR("Layer is nullptr");
414
0
      return false;
415
0
    }
416
417
    // verify layer is allocated to a packet
418
0
    if (!layer->isAllocatedToPacket())
419
0
    {
420
0
      PCPP_LOG_ERROR("Layer isn't allocated to any packet");
421
0
      return false;
422
0
    }
423
424
    // verify layer is allocated to *this* packet
425
0
    Layer* curLayer = layer;
426
0
    while (curLayer->m_PrevLayer != nullptr)
427
0
      curLayer = curLayer->m_PrevLayer;
428
0
    if (curLayer != m_FirstLayer)
429
0
    {
430
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
431
0
      return false;
432
0
    }
433
434
    // before removing the layer's data, copy it so it can be later assigned as the removed layer's data
435
0
    size_t headerLen = layer->getHeaderLen();
436
0
    size_t layerOldDataSize = headerLen;
437
0
    auto layerOldData = std::make_unique<uint8_t[]>(layerOldDataSize);
438
0
    memcpy(layerOldData.get(), layer->m_Data, layerOldDataSize);
439
440
    // remove data from raw packet
441
0
    size_t numOfBytesToRemove = headerLen;
442
0
    int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData();
443
0
    if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove))
444
0
    {
445
0
      PCPP_LOG_ERROR("Couldn't remove data from packet");
446
0
      return false;
447
0
    }
448
449
    // remove layer from layers linked list
450
0
    if (layer->m_PrevLayer != nullptr)
451
0
      layer->m_PrevLayer->setNextLayer(layer->m_NextLayer);
452
0
    if (layer->m_NextLayer != nullptr)
453
0
      layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer);
454
455
    // take care of head and tail ptrs
456
0
    if (m_FirstLayer == layer)
457
0
      m_FirstLayer = layer->m_NextLayer;
458
0
    if (m_LastLayer == layer)
459
0
      m_LastLayer = layer->m_PrevLayer;
460
0
    layer->setNextLayer(nullptr);
461
0
    layer->setPrevLayer(nullptr);
462
463
    // get packet trailer len if exists
464
0
    size_t packetTrailerLen = 0;
465
0
    if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer)
466
0
      packetTrailerLen = m_LastLayer->getDataLen();
467
468
    // re-calculate all layers data ptr and data length
469
470
    // first, get ptr and data length of the raw packet
471
0
    const uint8_t* dataPtr = m_RawPacket->getRawData();
472
0
    size_t dataLen = static_cast<size_t>(m_RawPacket->getRawDataLen());
473
474
0
    curLayer = m_FirstLayer;
475
476
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each one
477
0
    while (curLayer != nullptr)
478
0
    {
479
      // set data ptr to layer
480
0
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
481
482
      // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers.
483
      // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the
484
      // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data
485
      // length
486
0
      if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer)
487
0
        curLayer->m_DataLen = dataLen;
488
0
      else
489
0
        curLayer->m_DataLen = dataLen - packetTrailerLen;
490
491
      // advance data ptr and data length
492
0
      dataPtr += curLayer->getHeaderLen();
493
0
      dataLen -= curLayer->getHeaderLen();
494
495
      // move to next layer
496
0
      curLayer = curLayer->getNextLayer();
497
0
    }
498
499
    // if layer was allocated by this packet and tryToDelete flag is set, delete it
500
0
    if (tryToDelete && layer->m_IsAllocatedInPacket)
501
0
    {
502
0
      delete layer;
503
0
    }
504
    // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can
505
    // be reused
506
0
    else
507
0
    {
508
0
      layer->m_Packet = nullptr;
509
0
      layer->m_Data = layerOldData.release();
510
0
      layer->m_DataLen = layerOldDataSize;
511
0
    }
512
513
0
    return true;
514
0
  }
515
516
  Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const
517
0
  {
518
0
    int curIndex = 0;
519
0
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
520
0
    {
521
0
      if (curLayer->getProtocol() != layerType)
522
0
        continue;
523
524
0
      if (curIndex == index)
525
0
        return curLayer;
526
527
0
      curIndex++;
528
0
    }
529
530
0
    return nullptr;
531
0
  }
532
533
  bool Packet::isPacketOfType(ProtocolType protocolType) const
534
11.7M
  {
535
65.8M
    for (Layer* curLayer = getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
536
54.8M
    {
537
54.8M
      if (curLayer->getProtocol() == protocolType)
538
767k
      {
539
767k
        return true;
540
767k
      }
541
54.8M
    }
542
543
11.0M
    return false;
544
11.7M
  }
545
546
  bool Packet::isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const
547
2.77M
  {
548
2.77M
    Layer* curLayer = getFirstLayer();
549
15.5M
    while (curLayer != nullptr)
550
12.8M
    {
551
12.8M
      if (curLayer->isMemberOfProtocolFamily(protocolTypeFamily))
552
101k
      {
553
101k
        return true;
554
101k
      }
555
12.7M
      curLayer = curLayer->getNextLayer();
556
12.7M
    }
557
558
2.67M
    return false;
559
2.77M
  }
560
561
  bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend)
562
111k
  {
563
111k
    if (layer == nullptr)
564
0
    {
565
0
      PCPP_LOG_ERROR("Layer is nullptr");
566
0
      return false;
567
0
    }
568
569
    // verify layer is allocated to this packet
570
111k
    if (!(layer->m_Packet == this))
571
0
    {
572
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
573
0
      return false;
574
0
    }
575
576
111k
    if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen)
577
18.7k
    {
578
18.7k
      if (!m_CanReallocateData)
579
0
      {
580
0
        PCPP_LOG_ERROR(
581
0
            "With the layer extended size the packet will exceed the size of the pre-allocated buffer: "
582
0
            << m_MaxPacketLen << " bytes");
583
0
        return false;
584
0
      }
585
      // reallocate to maximum value of: twice the max size of the packet or max size + new required length
586
18.7k
      if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen * 2)
587
0
        reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen);
588
18.7k
      else
589
18.7k
        reallocateRawData(m_MaxPacketLen * 2);
590
18.7k
    }
591
592
    // insert layer data to raw packet
593
111k
    int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
594
    // passing nullptr to insertData will move the data by numOfBytesToExtend
595
    // no new data has to be created for this insertion which saves at least little time
596
    // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided
597
    // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the
598
    // packet size by numOfBytesToExtend
599
111k
    m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend);
600
601
    // re-calculate all layers data ptr and data length
602
111k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
603
604
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer
605
111k
    bool passedExtendedLayer = false;
606
895k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
607
784k
    {
608
      // set the data ptr
609
784k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
610
611
      // set a flag if arrived to the layer being extended
612
784k
      if (curLayer->getPrevLayer() == layer)
613
53.7k
        passedExtendedLayer = true;
614
615
      // change the data length only for layers who come before the extended layer. For layers who come after,
616
      // data length isn't changed
617
784k
      if (!passedExtendedLayer)
618
591k
        curLayer->m_DataLen += numOfBytesToExtend;
619
620
      // assuming header length of the layer that requested to be extended hasn't been enlarged yet
621
784k
      size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0);
622
784k
      dataPtr += headerLen;
623
784k
    }
624
625
111k
    return true;
626
111k
  }
627
628
  bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten)
629
112k
  {
630
112k
    if (layer == nullptr)
631
0
    {
632
0
      PCPP_LOG_ERROR("Layer is nullptr");
633
0
      return false;
634
0
    }
635
636
    // verify layer is allocated to this packet
637
112k
    if (!(layer->m_Packet == this))
638
0
    {
639
0
      PCPP_LOG_ERROR("Layer isn't allocated to this packet");
640
0
      return false;
641
0
    }
642
643
    // remove data from raw packet
644
112k
    int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData();
645
112k
    if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten))
646
2.65k
    {
647
2.65k
      PCPP_LOG_ERROR("Couldn't remove data from packet");
648
2.65k
      return false;
649
2.65k
    }
650
651
    // re-calculate all layers data ptr and data length
652
109k
    const uint8_t* dataPtr = m_RawPacket->getRawData();
653
654
    // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer
655
109k
    Layer* curLayer = m_FirstLayer;
656
109k
    bool passedExtendedLayer = false;
657
875k
    while (curLayer != nullptr)
658
766k
    {
659
      // set the data ptr
660
766k
      curLayer->m_Data = const_cast<uint8_t*>(dataPtr);
661
662
      // set a flag if arrived to the layer being shortened
663
766k
      if (curLayer->getPrevLayer() == layer)
664
51.7k
        passedExtendedLayer = true;
665
666
      // change the data length only for layers who come before the shortened layer. For layers who come after,
667
      // data length isn't changed
668
766k
      if (!passedExtendedLayer)
669
577k
        curLayer->m_DataLen -= numOfBytesToShorten;
670
671
      // assuming header length of the layer that requested to be extended hasn't been enlarged yet
672
766k
      size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0);
673
766k
      dataPtr += headerLen;
674
766k
      curLayer = curLayer->getNextLayer();
675
766k
    }
676
677
109k
    return true;
678
112k
  }
679
680
  void Packet::computeCalculateFields()
681
159k
  {
682
    // calculated fields should be calculated from top layer to bottom layer
683
852k
    for (Layer* curLayer = m_LastLayer; curLayer != nullptr; curLayer = curLayer->getPrevLayer())
684
693k
    {
685
693k
      curLayer->computeCalculateFields();
686
693k
    }
687
159k
  }
688
689
  std::string Packet::printPacketInfo(bool timeAsLocalTime) const
690
159k
  {
691
159k
    std::ostringstream dataLenStream;
692
159k
    dataLenStream << m_RawPacket->getRawDataLen();
693
694
    // convert raw packet timestamp to printable format
695
159k
    timespec timestamp = m_RawPacket->getPacketTimeStamp();
696
159k
    time_t nowtime = timestamp.tv_sec;
697
159k
    struct tm* nowtm = nullptr;
698
159k
#if __cplusplus > 199711L && !defined(_WIN32)
699
    // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime,
700
    // but they're defined only in newer compilers (>= C++0x).
701
    // on Windows localtime and gmtime are already thread-safe so there is not need
702
    // to use localtime_r and gmtime_r
703
159k
    struct tm nowtm_r;
704
159k
    if (timeAsLocalTime)
705
159k
      nowtm = localtime_r(&nowtime, &nowtm_r);
706
0
    else
707
0
      nowtm = gmtime_r(&nowtime, &nowtm_r);
708
709
159k
    if (nowtm != nullptr)
710
159k
      nowtm = &nowtm_r;
711
#else
712
    // on Window compilers localtime and gmtime are already thread safe.
713
    // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and
714
    // gmtime
715
    if (timeAsLocalTime)
716
      nowtm = localtime(&nowtime);
717
    else
718
      nowtm = gmtime(&nowtime);
719
#endif
720
721
159k
    char buf[128];
722
159k
    if (nowtm != nullptr)
723
159k
    {
724
159k
      char tmbuf[64];
725
159k
      strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
726
159k
      snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec);
727
159k
    }
728
0
    else
729
0
      snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000");
730
731
159k
    return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf);
732
159k
  }
733
734
  Layer* Packet::createFirstLayer(LinkLayerType linkType)
735
852k
  {
736
852k
    size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen();
737
852k
    if (rawDataLen == 0)
738
347
      return nullptr;
739
740
852k
    const uint8_t* rawData = m_RawPacket->getRawData();
741
742
852k
    if (linkType == LINKTYPE_ETHERNET)
743
709k
    {
744
709k
      if (EthLayer::isDataValid(rawData, rawDataLen))
745
705k
      {
746
705k
        return new EthLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
747
705k
      }
748
3.68k
      else if (EthDot3Layer::isDataValid(rawData, rawDataLen))
749
3.62k
      {
750
3.62k
        return new EthDot3Layer(const_cast<uint8_t*>(rawData), rawDataLen, this);
751
3.62k
      }
752
60
      else
753
60
      {
754
60
        return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
755
60
      }
756
709k
    }
757
142k
    else if (linkType == LINKTYPE_LINUX_SLL)
758
127k
    {
759
127k
      return new SllLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
760
127k
    }
761
14.7k
    else if (linkType == LINKTYPE_LINUX_SLL2 && Sll2Layer::isDataValid(rawData, rawDataLen))
762
0
    {
763
0
      return new Sll2Layer(const_cast<uint8_t*>(rawData), rawDataLen, this);
764
0
    }
765
14.7k
    else if (linkType == LINKTYPE_NULL)
766
4.95k
    {
767
4.95k
      if (rawDataLen >= sizeof(uint32_t))
768
4.95k
        return new NullLoopbackLayer(const_cast<uint8_t*>(rawData), rawDataLen, this);
769
0
      else  // rawDataLen is too small fir Null/Loopback
770
0
        return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
771
4.95k
    }
772
9.74k
    else if (linkType == LINKTYPE_RAW || linkType == LINKTYPE_DLT_RAW1 || linkType == LINKTYPE_DLT_RAW2)
773
354
    {
774
354
      uint8_t ipVer = rawData[0] & 0xf0;
775
354
      if (ipVer == 0x40)
776
155
      {
777
155
        return IPv4Layer::isDataValid(rawData, rawDataLen)
778
155
                   ? static_cast<Layer*>(
779
93
                         new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this))
780
155
                   : static_cast<Layer*>(
781
62
                         new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this));
782
155
      }
783
199
      else if (ipVer == 0x60)
784
69
      {
785
69
        return IPv6Layer::isDataValid(rawData, rawDataLen)
786
69
                   ? static_cast<Layer*>(
787
67
                         new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this))
788
69
                   : static_cast<Layer*>(
789
2
                         new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this));
790
69
      }
791
130
      else
792
130
      {
793
130
        return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
794
130
      }
795
354
    }
796
9.39k
    else if (linkType == LINKTYPE_IPV4)
797
253
    {
798
253
      return IPv4Layer::isDataValid(rawData, rawDataLen)
799
253
                 ? static_cast<Layer*>(new IPv4Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this))
800
253
                 : static_cast<Layer*>(
801
184
                       new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this));
802
253
    }
803
9.13k
    else if (linkType == LINKTYPE_IPV6)
804
196
    {
805
196
      return IPv6Layer::isDataValid(rawData, rawDataLen)
806
196
                 ? static_cast<Layer*>(new IPv6Layer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this))
807
196
                 : static_cast<Layer*>(
808
130
                       new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this));
809
196
    }
810
8.94k
    else if (linkType == LINKTYPE_NFLOG)
811
1.93k
    {
812
1.93k
      return NflogLayer::isDataValid(rawData, rawDataLen)
813
1.93k
                 ? static_cast<Layer*>(new NflogLayer(const_cast<uint8_t*>(rawData), rawDataLen, this))
814
1.93k
                 : static_cast<Layer*>(
815
38
                       new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this));
816
1.93k
    }
817
7.00k
    else if (linkType == LINKTYPE_C_HDLC)
818
165
    {
819
165
      return CiscoHdlcLayer::isDataValid(rawData, rawDataLen)
820
165
                 ? static_cast<Layer*>(new CiscoHdlcLayer(const_cast<uint8_t*>(rawData), rawDataLen, this))
821
165
                 : static_cast<Layer*>(
822
0
                       new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this));
823
165
    }
824
825
    // unknown link type
826
6.84k
    return new PayloadLayer(const_cast<uint8_t*>(rawData), rawDataLen, nullptr, this);
827
852k
  }
828
829
  std::string Packet::toString(bool timeAsLocalTime) const
830
159k
  {
831
159k
    std::vector<std::string> stringList;
832
159k
    toStringList(stringList, timeAsLocalTime);
833
159k
    return std::accumulate(stringList.begin(), stringList.end(), std::string(),
834
852k
                           [](std::string a, const std::string& b) { return std::move(a) + b + '\n'; });
835
159k
  }
836
837
  void Packet::toStringList(std::vector<std::string>& result, bool timeAsLocalTime) const
838
159k
  {
839
159k
    result.clear();
840
159k
    result.push_back(printPacketInfo(timeAsLocalTime));
841
842
852k
    for (Layer* curLayer = m_FirstLayer; curLayer != nullptr; curLayer = curLayer->getNextLayer())
843
693k
    {
844
693k
      result.push_back(curLayer->toString());
845
693k
    }
846
159k
  }
847
848
}  // namespace pcpp