Coverage Report

Created: 2025-11-24 07:12

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
54.6k
  {
25
54.6k
    if (greDataLen < sizeof(gre_basic_header))
26
0
      return UnknownProtocol;
27
28
54.6k
    uint8_t version = *(greData + 1);
29
54.6k
    version &= 0x07;
30
54.6k
    if (version == 0)
31
7.90k
      return GREv0;
32
46.7k
    else if (version == 1)
33
46.5k
      return GREv1;
34
175
    else
35
175
      return UnknownProtocol;
36
54.6k
  }
37
38
  uint8_t* GreLayer::getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const
39
14.6k
  {
40
14.6k
    uint8_t* ptr = m_Data + sizeof(gre_basic_header);
41
42
14.6k
    auto* header = reinterpret_cast<gre_basic_header*>(m_Data);
43
44
14.6k
    constexpr int numGreField = 4;
45
35.0k
    for (int curFieldAsInt = static_cast<int>(GreChecksumOrRouting); curFieldAsInt < numGreField; ++curFieldAsInt)
46
35.0k
    {
47
35.0k
      const GreField curField = static_cast<GreField>(curFieldAsInt);
48
35.0k
      bool curFieldExists = false;
49
50
35.0k
      uint8_t* origPtr = ptr;
51
52
35.0k
      switch (curField)
53
35.0k
      {
54
14.6k
      case GreChecksumOrRouting:
55
14.6k
        if (header->checksumBit == 1 || header->routingBit == 1)
56
7.83k
        {
57
7.83k
          curFieldExists = true;
58
7.83k
          ptr += sizeof(uint32_t);
59
7.83k
        }
60
14.6k
        break;
61
8.92k
      case GreKey:
62
8.92k
        if (header->keyBit == 1)
63
7.59k
        {
64
7.59k
          curFieldExists = true;
65
7.59k
          ptr += sizeof(uint32_t);
66
7.59k
        }
67
8.92k
        break;
68
8.53k
      case GreSeq:
69
8.53k
        if (header->sequenceNumBit == 1)
70
8.29k
        {
71
8.29k
          curFieldExists = true;
72
8.29k
          ptr += sizeof(uint32_t);
73
8.29k
        }
74
8.53k
        break;
75
3.02k
      case GreAck:
76
3.02k
        if (header->ackSequenceNumBit == 1)
77
3.02k
        {
78
3.02k
          curFieldExists = true;
79
3.02k
          ptr += sizeof(uint32_t);
80
3.02k
        }
81
3.02k
        break;
82
0
      default:  // shouldn't get there
83
0
        return nullptr;
84
35.0k
      }
85
86
35.0k
      if (field == curField)
87
14.6k
      {
88
14.6k
        if (curFieldExists || returnOffsetEvenIfFieldMissing)
89
14.6k
          return origPtr;
90
91
0
        return nullptr;
92
14.6k
      }
93
35.0k
    }  // for
94
95
0
    return nullptr;
96
14.6k
  }
97
98
  void GreLayer::computeCalculateFieldsInner()
99
6.20k
  {
100
6.20k
    gre_basic_header* header = (gre_basic_header*)m_Data;
101
6.20k
    if (m_NextLayer != nullptr)
102
6.20k
    {
103
6.20k
      switch (m_NextLayer->getProtocol())
104
6.20k
      {
105
0
      case IPv4:
106
0
        header->protocol = htobe16(PCPP_ETHERTYPE_IP);
107
0
        break;
108
0
      case IPv6:
109
0
        header->protocol = htobe16(PCPP_ETHERTYPE_IPV6);
110
0
        break;
111
0
      case VLAN:
112
0
        header->protocol = htobe16(PCPP_ETHERTYPE_VLAN);
113
0
        break;
114
0
      case MPLS:
115
0
        header->protocol = htobe16(PCPP_ETHERTYPE_MPLS);
116
0
        break;
117
4.06k
      case PPP_PPTP:
118
4.06k
        header->protocol = htobe16(PCPP_ETHERTYPE_PPP);
119
4.06k
        break;
120
0
      case Ethernet:
121
0
        header->protocol = htobe16(PCPP_ETHERTYPE_ETHBRIDGE);
122
0
        break;
123
2.13k
      default:
124
2.13k
        break;
125
6.20k
      }
126
6.20k
    }
127
6.20k
  }
128
129
  bool GreLayer::getSequenceNumber(uint32_t& seqNumber) const
130
6.20k
  {
131
6.20k
    gre_basic_header* header = (gre_basic_header*)m_Data;
132
133
6.20k
    if (header->sequenceNumBit == 0)
134
692
      return false;
135
136
5.51k
    uint32_t* val = (uint32_t*)getFieldValue(GreSeq, false);
137
5.51k
    if (val == nullptr)
138
0
      return false;
139
140
5.51k
    seqNumber = be32toh(*val);
141
5.51k
    return true;
142
5.51k
  }
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
54.5k
  {
197
54.5k
    size_t headerLen = getHeaderLen();
198
54.5k
    if (m_DataLen <= headerLen)
199
1.47k
      return;
200
201
53.0k
    gre_basic_header* header = (gre_basic_header*)m_Data;
202
53.0k
    uint8_t* payload = m_Data + headerLen;
203
53.0k
    size_t payloadLen = m_DataLen - headerLen;
204
205
53.0k
    switch (be16toh(header->protocol))
206
53.0k
    {
207
258
    case PCPP_ETHERTYPE_IP:
208
258
      m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
209
258
                        ? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
210
258
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
211
258
      break;
212
0
    case PCPP_ETHERTYPE_IPV6:
213
0
      m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
214
0
                        ? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
215
0
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
216
0
      break;
217
0
    case PCPP_ETHERTYPE_VLAN:
218
0
      m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet);
219
0
      break;
220
0
    case PCPP_ETHERTYPE_MPLS:
221
0
      m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet);
222
0
      break;
223
43.7k
    case PCPP_ETHERTYPE_PPP:
224
43.7k
      m_NextLayer = PPP_PPTPLayer::isDataValid(payload, payloadLen)
225
43.7k
                        ? static_cast<Layer*>(new PPP_PPTPLayer(payload, payloadLen, this, m_Packet))
226
43.7k
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
227
43.7k
      break;
228
0
    case PCPP_ETHERTYPE_ETHBRIDGE:
229
0
      if (EthLayer::isDataValid(payload, payloadLen))
230
0
      {
231
0
        m_NextLayer = new EthLayer(payload, payloadLen, this, m_Packet);
232
0
      }
233
0
      else if (EthDot3Layer::isDataValid(payload, payloadLen))
234
0
      {
235
0
        m_NextLayer = new EthDot3Layer(payload, payloadLen, this, m_Packet);
236
0
      }
237
0
      else
238
0
      {
239
0
        m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
240
0
      }
241
0
      break;
242
9.01k
    default:
243
9.01k
      m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
244
53.0k
    }
245
53.0k
  }
246
247
  size_t GreLayer::getHeaderLen() const
248
66.4k
  {
249
66.4k
    size_t result = sizeof(gre_basic_header);
250
251
66.4k
    gre_basic_header* header = (gre_basic_header*)m_Data;
252
253
66.4k
    if (header->checksumBit == 1 || header->routingBit == 1)
254
12.0k
      result += 4;
255
66.4k
    if (header->keyBit == 1)
256
57.7k
      result += 4;
257
66.4k
    if (header->sequenceNumBit == 1)
258
61.9k
      result += 4;
259
66.4k
    if (header->ackSequenceNumBit == 1)
260
34.9k
      result += 4;
261
262
66.4k
    return result;
263
66.4k
  }
264
265
  // ================
266
  // GREv0Layer class
267
  // ================
268
269
  GREv0Layer::GREv0Layer()
270
0
  {
271
0
    const size_t headerLen = sizeof(gre_basic_header);
272
0
    m_DataLen = headerLen;
273
0
    m_Data = new uint8_t[headerLen];
274
0
    memset(m_Data, 0, headerLen);
275
0
    m_Protocol = GREv0;
276
0
  }
277
278
  bool GREv0Layer::getChecksum(uint16_t& checksum)
279
1.58k
  {
280
1.58k
    if (getGreHeader()->checksumBit == 0)
281
98
      return false;
282
283
1.48k
    uint16_t* val = (uint16_t*)getFieldValue(GreChecksumOrRouting, false);
284
1.48k
    if (val == nullptr)
285
0
      return false;
286
287
1.48k
    checksum = be16toh(*val);
288
1.48k
    return true;
289
1.48k
  }
290
291
  bool GREv0Layer::setChecksum(uint16_t checksum)
292
2.96k
  {
293
2.96k
    gre_basic_header* header = getGreHeader();
294
295
2.96k
    bool needToExtendLayer = false;
296
297
2.96k
    if (header->routingBit == 0 && header->checksumBit == 0)
298
0
      needToExtendLayer = true;
299
300
2.96k
    uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true);
301
2.96k
    int offset = offsetPtr - m_Data;
302
    // extend layer in 4 bytes to keep 4-byte alignment
303
2.96k
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
304
0
    {
305
0
      PCPP_LOG_ERROR("Couldn't extend layer to set checksum");
306
0
      return false;
307
0
    }
308
309
2.96k
    uint16_t* checksumPtr = (uint16_t*)(m_Data + offset);
310
2.96k
    *checksumPtr = htobe16(checksum);
311
312
    // if layer was extended in 4 bytes, make sure the offset field stays 0
313
2.96k
    if (needToExtendLayer)
314
0
    {
315
0
      checksumPtr++;
316
0
      *checksumPtr = 0;
317
0
    }
318
319
2.96k
    header = getGreHeader();
320
2.96k
    header->checksumBit = 1;
321
322
2.96k
    return true;
323
2.96k
  }
324
325
  bool GREv0Layer::unsetChecksum()
326
0
  {
327
0
    gre_basic_header* header = getGreHeader();
328
329
0
    if (header->checksumBit == 0)
330
0
    {
331
0
      PCPP_LOG_ERROR("Couldn't unset checksum as it's already unset");
332
0
      return false;
333
0
    }
334
335
    // if both routing and checksum are unset we need to shorted the layer
336
0
    bool needToShortenLayer = (header->routingBit == 0);
337
338
0
    uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true);
339
0
    int offset = offsetPtr - m_Data;
340
0
    if (needToShortenLayer && !shortenLayer(offset, sizeof(uint32_t)))
341
0
    {
342
0
      PCPP_LOG_ERROR("Couldn't extend layer to unset checksum");
343
0
      return false;
344
0
    }
345
346
0
    if (!needToShortenLayer)  // meaning routing bit is set - only zero the checksum field
347
0
    {
348
0
      uint16_t* checksumPtr = (uint16_t*)(m_Data + offset);
349
0
      *checksumPtr = 0;
350
0
    }
351
352
0
    header = getGreHeader();
353
0
    header->checksumBit = 0;
354
355
0
    return true;
356
0
  }
357
358
  bool GREv0Layer::getOffset(uint16_t& offset) const
359
1.58k
  {
360
1.58k
    if (getGreHeader()->routingBit == 0)
361
350
      return false;
362
363
1.23k
    uint8_t* val = (uint8_t*)getFieldValue(GreChecksumOrRouting, false);
364
1.23k
    if (val == nullptr)
365
0
      return false;
366
367
1.23k
    offset = be16toh(*(val + 2));
368
1.23k
    return true;
369
1.23k
  }
370
371
  bool GREv0Layer::getKey(uint32_t& key) const
372
1.58k
  {
373
1.58k
    if (getGreHeader()->keyBit == 0)
374
1.18k
      return false;
375
376
392
    uint32_t* val = (uint32_t*)getFieldValue(GreKey, false);
377
392
    if (val == nullptr)
378
0
      return false;
379
380
392
    key = be32toh(*val);
381
392
    return true;
382
392
  }
383
384
  bool GREv0Layer::setKey(uint32_t key)
385
0
  {
386
0
    gre_basic_header* header = getGreHeader();
387
388
0
    bool needToExtendLayer = false;
389
390
0
    if (header->keyBit == 0)
391
0
      needToExtendLayer = true;
392
393
0
    uint8_t* offsetPtr = getFieldValue(GreKey, true);
394
395
0
    int offset = offsetPtr - m_Data;
396
0
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
397
0
    {
398
0
      header->keyBit = 0;
399
0
      PCPP_LOG_ERROR("Couldn't extend layer to set key");
400
0
      return false;
401
0
    }
402
403
0
    header = getGreHeader();
404
0
    header->keyBit = 1;
405
0
    uint32_t* keyPtr = (uint32_t*)(m_Data + offset);
406
0
    *keyPtr = htobe32(key);
407
408
0
    return true;
409
0
  }
410
411
  bool GREv0Layer::unsetKey()
412
0
  {
413
0
    gre_basic_header* header = getGreHeader();
414
415
0
    if (header->keyBit == 0)
416
0
    {
417
0
      PCPP_LOG_ERROR("Couldn't unset key as it's already unset");
418
0
      return false;
419
0
    }
420
421
0
    uint8_t* offsetPtr = getFieldValue(GreKey, true);
422
423
0
    int offset = offsetPtr - m_Data;
424
0
    if (!shortenLayer(offset, sizeof(uint32_t)))
425
0
    {
426
0
      PCPP_LOG_ERROR("Couldn't shorted layer to unset key");
427
0
      return false;
428
0
    }
429
430
0
    header = (gre_basic_header*)m_Data;
431
0
    header->keyBit = 0;
432
0
    return true;
433
0
  }
434
435
  void GREv0Layer::computeCalculateFields()
436
1.58k
  {
437
1.58k
    computeCalculateFieldsInner();
438
439
1.58k
    if (getGreHeader()->checksumBit == 0)
440
98
      return;
441
442
    // calculate checksum
443
1.48k
    setChecksum(0);
444
445
1.48k
    ScalarBuffer<uint16_t> buffer;
446
1.48k
    buffer.buffer = (uint16_t*)m_Data;
447
1.48k
    buffer.len = m_DataLen;
448
1.48k
    size_t checksum = computeChecksum(&buffer, 1);
449
450
1.48k
    setChecksum(checksum);
451
1.48k
  }
452
453
  std::string GREv0Layer::toString() const
454
3.16k
  {
455
3.16k
    return "GRE Layer, version 0";
456
3.16k
  }
457
458
  // ================
459
  // GREv1Layer class
460
  // ================
461
462
  GREv1Layer::GREv1Layer(uint16_t callID)
463
0
  {
464
0
    const size_t headerLen = sizeof(gre1_header);
465
0
    m_DataLen = headerLen;
466
0
    m_Data = new uint8_t[headerLen];
467
0
    memset(m_Data, 0, headerLen);
468
0
    m_Protocol = GREv1;
469
470
0
    gre1_header* header = getGreHeader();
471
0
    header->keyBit = 1;
472
0
    header->version = 1;
473
0
    header->callID = htobe16(callID);
474
0
  }
475
476
  bool GREv1Layer::getAcknowledgmentNum(uint32_t& ackNum) const
477
4.62k
  {
478
4.62k
    if (getGreHeader()->ackSequenceNumBit == 0)
479
1.60k
      return false;
480
481
3.02k
    uint32_t* val = (uint32_t*)getFieldValue(GreAck, false);
482
3.02k
    if (val == nullptr)
483
0
      return false;
484
485
3.02k
    ackNum = be32toh(*val);
486
3.02k
    return true;
487
3.02k
  }
488
489
  bool GREv1Layer::setAcknowledgmentNum(uint32_t ackNum)
490
0
  {
491
0
    bool needToExtendLayer = false;
492
493
0
    gre1_header* header = getGreHeader();
494
495
0
    if (header->ackSequenceNumBit == 0)
496
0
      needToExtendLayer = true;
497
498
0
    uint8_t* offsetPtr = getFieldValue(GreAck, true);
499
0
    int offset = offsetPtr - m_Data;
500
0
    if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t)))
501
0
    {
502
0
      PCPP_LOG_ERROR("Couldn't extend layer to set ack number");
503
0
      return false;
504
0
    }
505
506
0
    header = getGreHeader();
507
0
    header->ackSequenceNumBit = 1;
508
0
    uint32_t* ackPtr = (uint32_t*)(m_Data + offset);
509
0
    *ackPtr = htobe32(ackNum);
510
0
    return true;
511
0
  }
512
513
  bool GREv1Layer::unsetAcknowledgmentNum()
514
0
  {
515
0
    gre1_header* header = getGreHeader();
516
517
0
    if (header->ackSequenceNumBit == 0)
518
0
    {
519
0
      PCPP_LOG_ERROR("Couldn't unset ack number as it's already unset");
520
0
      return false;
521
0
    }
522
523
0
    uint8_t* offsetPtr = getFieldValue(GreAck, true);
524
525
0
    int offset = offsetPtr - m_Data;
526
0
    if (!shortenLayer(offset, sizeof(uint32_t)))
527
0
    {
528
0
      PCPP_LOG_ERROR("Couldn't shorted layer to unset ack number");
529
0
      return false;
530
0
    }
531
532
0
    header = getGreHeader();
533
0
    header->ackSequenceNumBit = 0;
534
0
    return true;
535
0
  }
536
537
  void GREv1Layer::computeCalculateFields()
538
4.62k
  {
539
4.62k
    computeCalculateFieldsInner();
540
541
4.62k
    getGreHeader()->payloadLength = htobe16(m_DataLen - getHeaderLen());
542
4.62k
  }
543
544
  std::string GREv1Layer::toString() const
545
9.24k
  {
546
9.24k
    return "GRE Layer, version 1";
547
9.24k
  }
548
549
  // ===================
550
  // PPP_PPTPLayer class
551
  // ===================
552
553
  PPP_PPTPLayer::PPP_PPTPLayer(uint8_t address, uint8_t control)
554
0
  {
555
0
    const size_t headerLen = sizeof(ppp_pptp_header);
556
0
    m_DataLen = headerLen;
557
0
    m_Data = new uint8_t[headerLen];
558
0
    memset(m_Data, 0, headerLen);
559
0
    m_Protocol = PPP_PPTP;
560
561
0
    ppp_pptp_header* header = getPPP_PPTPHeader();
562
0
    header->address = address;
563
0
    header->control = control;
564
0
  }
565
566
  void PPP_PPTPLayer::parseNextLayer()
567
43.7k
  {
568
43.7k
    size_t headerLen = getHeaderLen();
569
43.7k
    if (m_DataLen <= headerLen)
570
0
      return;
571
572
43.7k
    uint8_t* payload = m_Data + headerLen;
573
43.7k
    size_t payloadLen = m_DataLen - headerLen;
574
575
43.7k
    switch (be16toh(getPPP_PPTPHeader()->protocol))
576
43.7k
    {
577
43.5k
    case PCPP_PPP_IP:
578
43.5k
      m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
579
43.5k
                        ? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
580
43.5k
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
581
43.5k
      break;
582
0
    case PCPP_PPP_IPV6:
583
0
      m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
584
0
                        ? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
585
0
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
586
0
      break;
587
248
    default:
588
248
      m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
589
248
      break;
590
43.7k
    }
591
43.7k
  }
592
593
  void PPP_PPTPLayer::computeCalculateFields()
594
4.06k
  {
595
4.06k
    ppp_pptp_header* header = getPPP_PPTPHeader();
596
4.06k
    if (m_NextLayer != nullptr)
597
4.06k
    {
598
4.06k
      switch (m_NextLayer->getProtocol())
599
4.06k
      {
600
3.98k
      case IPv4:
601
3.98k
        header->protocol = htobe16(PCPP_PPP_IP);
602
3.98k
        break;
603
0
      case IPv6:
604
0
        header->protocol = htobe16(PCPP_PPP_IPV6);
605
0
        break;
606
77
      default:
607
77
        break;
608
4.06k
      }
609
4.06k
    }
610
0
    else
611
0
      header->protocol = 0;
612
4.06k
  }
613
614
}  // namespace pcpp