Coverage Report

Created: 2026-08-31 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/GreLayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModuleGreLayer
2
3
#include "GreLayer.h"
4
#include "EthLayer.h"
5
#include "EthDot3Layer.h"
6
#include "IPv4Layer.h"
7
#include "IPv6Layer.h"
8
#include "PPPoELayer.h"
9
#include "VlanLayer.h"
10
#include "MplsLayer.h"
11
#include "PayloadLayer.h"
12
#include "PacketUtils.h"
13
#include "Logger.h"
14
#include "EndianPortable.h"
15
16
// ==============
17
// GreLayer class
18
// ==============
19
20
namespace pcpp
21
{
22
23
  ProtocolType GreLayer::getGREVersion(uint8_t* greData, size_t greDataLen)
24
121k
  {
25
121k
    if (greDataLen < sizeof(gre_basic_header))
26
70
      return UnknownProtocol;
27
28
121k
    uint8_t version = *(greData + 1);
29
121k
    version &= 0x07;
30
121k
    if (version == 0)
31
11.1k
      return GREv0;
32
109k
    else if (version == 1)
33
109k
      return GREv1;
34
351
    else
35
351
      return UnknownProtocol;
36
121k
  }
37
38
  uint8_t* GreLayer::getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const
39
24.8k
  {
40
24.8k
    uint8_t* ptr = m_Data + sizeof(gre_basic_header);
41
42
24.8k
    auto* header = reinterpret_cast<gre_basic_header*>(m_Data);
43
44
24.8k
    constexpr int numGreField = 4;
45
67.8k
    for (int curFieldAsInt = static_cast<int>(GreChecksumOrRouting); curFieldAsInt < numGreField; ++curFieldAsInt)
46
67.8k
    {
47
67.8k
      const GreField curField = static_cast<GreField>(curFieldAsInt);
48
67.8k
      bool curFieldExists = false;
49
50
67.8k
      uint8_t* origPtr = ptr;
51
52
67.8k
      switch (curField)
53
67.8k
      {
54
24.8k
      case GreChecksumOrRouting:
55
24.8k
        if (header->checksumBit == 1 || header->routingBit == 1)
56
9.59k
        {
57
9.59k
          curFieldExists = true;
58
9.59k
          ptr += sizeof(uint32_t);
59
9.59k
        }
60
24.8k
        break;
61
18.4k
      case GreKey:
62
18.4k
        if (header->keyBit == 1)
63
16.6k
        {
64
16.6k
          curFieldExists = true;
65
16.6k
          ptr += sizeof(uint32_t);
66
16.6k
        }
67
18.4k
        break;
68
17.8k
      case GreSeq:
69
17.8k
        if (header->sequenceNumBit == 1)
70
16.8k
        {
71
16.8k
          curFieldExists = true;
72
16.8k
          ptr += sizeof(uint32_t);
73
16.8k
        }
74
17.8k
        break;
75
6.64k
      case GreAck:
76
6.64k
        if (header->ackSequenceNumBit == 1)
77
6.64k
        {
78
6.64k
          curFieldExists = true;
79
6.64k
          ptr += sizeof(uint32_t);
80
6.64k
        }
81
6.64k
        break;
82
0
      default:  // shouldn't get there
83
0
        return nullptr;
84
67.8k
      }
85
86
67.8k
      if (field == curField)
87
24.8k
      {
88
24.8k
        if (curFieldExists || returnOffsetEvenIfFieldMissing)
89
24.8k
          return origPtr;
90
91
0
        return nullptr;
92
24.8k
      }
93
67.8k
    }  // for
94
95
0
    return nullptr;
96
24.8k
  }
97
98
  void GreLayer::computeCalculateFieldsInner()
99
13.1k
  {
100
13.1k
    gre_basic_header* header = (gre_basic_header*)m_Data;
101
13.1k
    if (m_NextLayer != nullptr)
102
13.1k
    {
103
13.1k
      switch (m_NextLayer->getProtocol())
104
13.1k
      {
105
47
      case IPv4:
106
47
        header->protocol = htobe16(PCPP_ETHERTYPE_IP);
107
47
        break;
108
2
      case IPv6:
109
2
        header->protocol = htobe16(PCPP_ETHERTYPE_IPV6);
110
2
        break;
111
3
      case VLAN:
112
3
        header->protocol = htobe16(PCPP_ETHERTYPE_VLAN);
113
3
        break;
114
18
      case MPLS:
115
18
        header->protocol = htobe16(PCPP_ETHERTYPE_MPLS);
116
18
        break;
117
9.38k
      case PPP_PPTP:
118
9.38k
        header->protocol = htobe16(PCPP_ETHERTYPE_PPP);
119
9.38k
        break;
120
0
      case Ethernet:
121
0
        header->protocol = htobe16(PCPP_ETHERTYPE_ETHBRIDGE);
122
0
        break;
123
3.65k
      default:
124
3.65k
        break;
125
13.1k
      }
126
13.1k
    }
127
13.1k
  }
128
129
  bool GreLayer::getSequenceNumber(uint32_t& seqNumber) const
130
13.1k
  {
131
13.1k
    gre_basic_header* header = (gre_basic_header*)m_Data;
132
133
13.1k
    if (header->sequenceNumBit == 0)
134
1.98k
      return false;
135
136
11.1k
    uint32_t* val = (uint32_t*)getFieldValue(GreSeq, false);
137
11.1k
    if (val == nullptr)
138
0
      return false;
139
140
11.1k
    seqNumber = be32toh(*val);
141
11.1k
    return true;
142
11.1k
  }
143
144
  bool GreLayer::setSequenceNumber(uint32_t seqNumber)
145
0
  {
146
0
    gre_basic_header* header = (gre_basic_header*)m_Data;
147
148
0
    bool needToExtendLayer = false;
149
150
0
    if (header->sequenceNumBit == 0)
151
0
      needToExtendLayer = true;
152
153
0
    uint8_t* offsetPtr = getFieldValue(GreSeq, true);
154
155
0
    int offset = offsetPtr - m_Data;
156
0
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
157
0
    {
158
0
      header->sequenceNumBit = 0;
159
0
      PCPP_LOG_ERROR("Couldn't extend layer to set sequence number");
160
0
      return false;
161
0
    }
162
163
0
    header = (gre_basic_header*)m_Data;
164
0
    header->sequenceNumBit = 1;
165
0
    uint32_t* seqPtr = (uint32_t*)(m_Data + offset);
166
0
    *seqPtr = htobe32(seqNumber);
167
168
0
    return true;
169
0
  }
170
171
  bool GreLayer::unsetSequenceNumber()
172
0
  {
173
0
    gre_basic_header* header = (gre_basic_header*)m_Data;
174
175
0
    if (header->sequenceNumBit == 0)
176
0
    {
177
0
      PCPP_LOG_ERROR("Couldn't unset sequence number as it's already unset");
178
0
      return false;
179
0
    }
180
181
0
    uint8_t* offsetPtr = getFieldValue(GreSeq, true);
182
183
0
    int offset = offsetPtr - m_Data;
184
0
    if (!shortenLayer(offset, sizeof(uint32_t)))
185
0
    {
186
0
      PCPP_LOG_ERROR("Couldn't shorted layer to unset sequence number");
187
0
      return false;
188
0
    }
189
190
0
    header = (gre_basic_header*)m_Data;
191
0
    header->sequenceNumBit = 0;
192
0
    return true;
193
0
  }
194
195
  void GreLayer::parseNextLayer()
196
120k
  {
197
120k
    size_t headerLen = getHeaderLen();
198
120k
    if (m_DataLen <= headerLen)
199
2.47k
      return;
200
201
118k
    gre_basic_header* header = (gre_basic_header*)m_Data;
202
118k
    uint8_t* payload = m_Data + headerLen;
203
118k
    size_t payloadLen = m_DataLen - headerLen;
204
205
118k
    switch (be16toh(header->protocol))
206
118k
    {
207
1.53k
    case PCPP_ETHERTYPE_IP:
208
1.53k
      tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen);
209
1.53k
      break;
210
23
    case PCPP_ETHERTYPE_IPV6:
211
23
      tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen);
212
23
      break;
213
24
    case PCPP_ETHERTYPE_VLAN:
214
24
      constructNextLayer<VlanLayer>(payload, payloadLen);
215
24
      break;
216
154
    case PCPP_ETHERTYPE_MPLS:
217
154
      tryConstructNextLayerWithFallback<MplsLayer, PayloadLayer>(payload, payloadLen);
218
154
      break;
219
101k
    case PCPP_ETHERTYPE_PPP:
220
101k
      tryConstructNextLayerWithFallback<PPP_PPTPLayer, PayloadLayer>(payload, payloadLen);
221
101k
      break;
222
0
    case PCPP_ETHERTYPE_ETHBRIDGE:
223
0
    {
224
0
      if (tryConstructNextLayer<EthLayer>(payload, payloadLen) != nullptr)
225
0
      {
226
0
        break;
227
0
      }
228
229
0
      tryConstructNextLayerWithFallback<EthDot3Layer, PayloadLayer>(payload, payloadLen);
230
0
      break;
231
0
    }
232
15.2k
    default:
233
15.2k
      constructNextLayer<PayloadLayer>(payload, payloadLen);
234
118k
    }
235
118k
  }
236
237
  size_t GreLayer::getHeaderLen() const
238
146k
  {
239
146k
    size_t result = sizeof(gre_basic_header);
240
241
146k
    gre_basic_header const* header = reinterpret_cast<gre_basic_header const*>(m_Data);
242
243
146k
    if (header->checksumBit == 1 || header->routingBit == 1)
244
18.6k
      result += 4;
245
146k
    if (header->keyBit == 1)
246
131k
      result += 4;
247
146k
    if (header->sequenceNumBit == 1)
248
132k
      result += 4;
249
146k
    if (header->ackSequenceNumBit == 1)
250
73.2k
      result += 4;
251
252
146k
    return result;
253
146k
  }
254
255
  // ================
256
  // GREv0Layer class
257
  // ================
258
259
  GREv0Layer::GREv0Layer()
260
0
  {
261
0
    allocData(sizeof(gre_basic_header));
262
0
    m_Protocol = GREv0;
263
0
  }
264
265
  bool GREv0Layer::getChecksum(uint16_t& checksum)
266
2.17k
  {
267
2.17k
    if (getGreHeader()->checksumBit == 0)
268
502
      return false;
269
270
1.67k
    uint16_t* val = (uint16_t*)getFieldValue(GreChecksumOrRouting, false);
271
1.67k
    if (val == nullptr)
272
0
      return false;
273
274
1.67k
    checksum = be16toh(*val);
275
1.67k
    return true;
276
1.67k
  }
277
278
  bool GREv0Layer::setChecksum(uint16_t checksum)
279
3.35k
  {
280
3.35k
    gre_basic_header* header = getGreHeader();
281
282
3.35k
    bool needToExtendLayer = false;
283
284
3.35k
    if (header->routingBit == 0 && header->checksumBit == 0)
285
0
      needToExtendLayer = true;
286
287
3.35k
    uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true);
288
3.35k
    int offset = offsetPtr - m_Data;
289
    // extend layer in 4 bytes to keep 4-byte alignment
290
3.35k
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
291
0
    {
292
0
      PCPP_LOG_ERROR("Couldn't extend layer to set checksum");
293
0
      return false;
294
0
    }
295
296
3.35k
    uint16_t* checksumPtr = (uint16_t*)(m_Data + offset);
297
3.35k
    *checksumPtr = htobe16(checksum);
298
299
    // if layer was extended in 4 bytes, make sure the offset field stays 0
300
3.35k
    if (needToExtendLayer)
301
0
    {
302
0
      checksumPtr++;
303
0
      *checksumPtr = 0;
304
0
    }
305
306
3.35k
    header = getGreHeader();
307
3.35k
    header->checksumBit = 1;
308
309
3.35k
    return true;
310
3.35k
  }
311
312
  bool GREv0Layer::unsetChecksum()
313
0
  {
314
0
    gre_basic_header* header = getGreHeader();
315
316
0
    if (header->checksumBit == 0)
317
0
    {
318
0
      PCPP_LOG_ERROR("Couldn't unset checksum as it's already unset");
319
0
      return false;
320
0
    }
321
322
    // if both routing and checksum are unset we need to shorted the layer
323
0
    bool needToShortenLayer = (header->routingBit == 0);
324
325
0
    uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true);
326
0
    int offset = offsetPtr - m_Data;
327
0
    if (needToShortenLayer && !shortenLayer(offset, sizeof(uint32_t)))
328
0
    {
329
0
      PCPP_LOG_ERROR("Couldn't extend layer to unset checksum");
330
0
      return false;
331
0
    }
332
333
0
    if (!needToShortenLayer)  // meaning routing bit is set - only zero the checksum field
334
0
    {
335
0
      uint16_t* checksumPtr = (uint16_t*)(m_Data + offset);
336
0
      *checksumPtr = 0;
337
0
    }
338
339
0
    header = getGreHeader();
340
0
    header->checksumBit = 0;
341
342
0
    return true;
343
0
  }
344
345
  bool GREv0Layer::getOffset(uint16_t& offset) const
346
2.17k
  {
347
2.17k
    if (getGreHeader()->routingBit == 0)
348
798
      return false;
349
350
1.37k
    uint8_t* val = (uint8_t*)getFieldValue(GreChecksumOrRouting, false);
351
1.37k
    if (val == nullptr)
352
0
      return false;
353
354
1.37k
    offset = be16toh(*(val + 2));
355
1.37k
    return true;
356
1.37k
  }
357
358
  bool GREv0Layer::getKey(uint32_t& key) const
359
2.17k
  {
360
2.17k
    if (getGreHeader()->keyBit == 0)
361
1.54k
      return false;
362
363
628
    uint32_t* val = (uint32_t*)getFieldValue(GreKey, false);
364
628
    if (val == nullptr)
365
0
      return false;
366
367
628
    key = be32toh(*val);
368
628
    return true;
369
628
  }
370
371
  bool GREv0Layer::setKey(uint32_t key)
372
0
  {
373
0
    gre_basic_header* header = getGreHeader();
374
375
0
    bool needToExtendLayer = false;
376
377
0
    if (header->keyBit == 0)
378
0
      needToExtendLayer = true;
379
380
0
    uint8_t* offsetPtr = getFieldValue(GreKey, true);
381
382
0
    int offset = offsetPtr - m_Data;
383
0
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
384
0
    {
385
0
      header->keyBit = 0;
386
0
      PCPP_LOG_ERROR("Couldn't extend layer to set key");
387
0
      return false;
388
0
    }
389
390
0
    header = getGreHeader();
391
0
    header->keyBit = 1;
392
0
    uint32_t* keyPtr = (uint32_t*)(m_Data + offset);
393
0
    *keyPtr = htobe32(key);
394
395
0
    return true;
396
0
  }
397
398
  bool GREv0Layer::unsetKey()
399
0
  {
400
0
    gre_basic_header* header = getGreHeader();
401
402
0
    if (header->keyBit == 0)
403
0
    {
404
0
      PCPP_LOG_ERROR("Couldn't unset key as it's already unset");
405
0
      return false;
406
0
    }
407
408
0
    uint8_t* offsetPtr = getFieldValue(GreKey, true);
409
410
0
    int offset = offsetPtr - m_Data;
411
0
    if (!shortenLayer(offset, sizeof(uint32_t)))
412
0
    {
413
0
      PCPP_LOG_ERROR("Couldn't shorted layer to unset key");
414
0
      return false;
415
0
    }
416
417
0
    header = (gre_basic_header*)m_Data;
418
0
    header->keyBit = 0;
419
0
    return true;
420
0
  }
421
422
  void GREv0Layer::computeCalculateFields()
423
2.17k
  {
424
2.17k
    computeCalculateFieldsInner();
425
426
2.17k
    if (getGreHeader()->checksumBit == 0)
427
502
      return;
428
429
    // calculate checksum
430
1.67k
    setChecksum(0);
431
432
1.67k
    ScalarBuffer<uint16_t> buffer;
433
1.67k
    buffer.buffer = (uint16_t*)m_Data;
434
1.67k
    buffer.len = m_DataLen;
435
1.67k
    size_t checksum = computeChecksum(&buffer, 1);
436
437
1.67k
    setChecksum(checksum);
438
1.67k
  }
439
440
  std::string GREv0Layer::toString() const
441
4.35k
  {
442
4.35k
    return "GRE Layer, version 0";
443
4.35k
  }
444
445
  // ================
446
  // GREv1Layer class
447
  // ================
448
449
  GREv1Layer::GREv1Layer(uint16_t callID)
450
0
  {
451
0
    allocData(sizeof(gre1_header));
452
0
    m_Protocol = GREv1;
453
454
0
    gre1_header* header = getGreHeader();
455
0
    header->keyBit = 1;
456
0
    header->version = 1;
457
0
    header->callID = htobe16(callID);
458
0
  }
459
460
  bool GREv1Layer::getAcknowledgmentNum(uint32_t& ackNum) const
461
11.0k
  {
462
11.0k
    if (getGreHeader()->ackSequenceNumBit == 0)
463
4.36k
      return false;
464
465
6.64k
    uint32_t* val = (uint32_t*)getFieldValue(GreAck, false);
466
6.64k
    if (val == nullptr)
467
0
      return false;
468
469
6.64k
    ackNum = be32toh(*val);
470
6.64k
    return true;
471
6.64k
  }
472
473
  bool GREv1Layer::setAcknowledgmentNum(uint32_t ackNum)
474
0
  {
475
0
    bool needToExtendLayer = false;
476
477
0
    gre1_header* header = getGreHeader();
478
479
0
    if (header->ackSequenceNumBit == 0)
480
0
      needToExtendLayer = true;
481
482
0
    uint8_t* offsetPtr = getFieldValue(GreAck, true);
483
0
    int offset = offsetPtr - m_Data;
484
0
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
485
0
    {
486
0
      PCPP_LOG_ERROR("Couldn't extend layer to set ack number");
487
0
      return false;
488
0
    }
489
490
0
    header = getGreHeader();
491
0
    header->ackSequenceNumBit = 1;
492
0
    uint32_t* ackPtr = (uint32_t*)(m_Data + offset);
493
0
    *ackPtr = htobe32(ackNum);
494
0
    return true;
495
0
  }
496
497
  bool GREv1Layer::unsetAcknowledgmentNum()
498
0
  {
499
0
    gre1_header* header = getGreHeader();
500
501
0
    if (header->ackSequenceNumBit == 0)
502
0
    {
503
0
      PCPP_LOG_ERROR("Couldn't unset ack number as it's already unset");
504
0
      return false;
505
0
    }
506
507
0
    uint8_t* offsetPtr = getFieldValue(GreAck, true);
508
509
0
    int offset = offsetPtr - m_Data;
510
0
    if (!shortenLayer(offset, sizeof(uint32_t)))
511
0
    {
512
0
      PCPP_LOG_ERROR("Couldn't shorted layer to unset ack number");
513
0
      return false;
514
0
    }
515
516
0
    header = getGreHeader();
517
0
    header->ackSequenceNumBit = 0;
518
0
    return true;
519
0
  }
520
521
  void GREv1Layer::computeCalculateFields()
522
11.0k
  {
523
11.0k
    computeCalculateFieldsInner();
524
525
11.0k
    getGreHeader()->payloadLength = htobe16(m_DataLen - getHeaderLen());
526
11.0k
  }
527
528
  std::string GREv1Layer::toString() const
529
22.0k
  {
530
22.0k
    return "GRE Layer, version 1";
531
22.0k
  }
532
533
  // ===================
534
  // PPP_PPTPLayer class
535
  // ===================
536
537
  PPP_PPTPLayer::PPP_PPTPLayer(uint8_t address, uint8_t control)
538
0
  {
539
0
    allocData(sizeof(ppp_pptp_header));
540
0
    m_Protocol = PPP_PPTP;
541
542
0
    ppp_pptp_header* header = getPPP_PPTPHeader();
543
0
    header->address = address;
544
0
    header->control = control;
545
0
  }
546
547
  void PPP_PPTPLayer::parseNextLayer()
548
101k
  {
549
101k
    size_t headerLen = getHeaderLen();
550
101k
    if (m_DataLen <= headerLen)
551
27
      return;
552
553
101k
    uint8_t* payload = m_Data + headerLen;
554
101k
    size_t payloadLen = m_DataLen - headerLen;
555
556
101k
    switch (be16toh(getPPP_PPTPHeader()->protocol))
557
101k
    {
558
100k
    case PCPP_PPP_IP:
559
100k
      tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen);
560
100k
      break;
561
71
    case PCPP_PPP_IPV6:
562
71
      tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen);
563
71
      break;
564
790
    default:
565
790
      constructNextLayer<PayloadLayer>(payload, payloadLen);
566
790
      break;
567
101k
    }
568
101k
  }
569
570
  void PPP_PPTPLayer::computeCalculateFields()
571
9.38k
  {
572
9.38k
    ppp_pptp_header* header = getPPP_PPTPHeader();
573
9.38k
    if (m_NextLayer != nullptr)
574
9.38k
    {
575
9.38k
      switch (m_NextLayer->getProtocol())
576
9.38k
      {
577
9.23k
      case IPv4:
578
9.23k
        header->protocol = htobe16(PCPP_PPP_IP);
579
9.23k
        break;
580
0
      case IPv6:
581
0
        header->protocol = htobe16(PCPP_PPP_IPV6);
582
0
        break;
583
157
      default:
584
157
        break;
585
9.38k
      }
586
9.38k
    }
587
0
    else
588
0
      header->protocol = 0;
589
9.38k
  }
590
591
}  // namespace pcpp