Coverage Report

Created: 2025-12-14 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/GtpLayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModuleGtpLayer
2
3
#include <unordered_map>
4
#include <sstream>
5
#include "Logger.h"
6
#include "GtpLayer.h"
7
#include "IPv4Layer.h"
8
#include "IPv6Layer.h"
9
#include "PayloadLayer.h"
10
#include "EndianPortable.h"
11
12
namespace pcpp
13
{
14
15
82.1k
#define PCPP_GTP_V1_GPDU_MESSAGE_TYPE 0xff
16
17
  /// ==================
18
  /// GtpExtension class
19
  /// ==================
20
21
  GtpV1Layer::GtpExtension::GtpExtension()
22
27.6k
  {
23
27.6k
    m_Data = nullptr;
24
27.6k
    m_DataLen = 0;
25
27.6k
    m_ExtType = 0;
26
27.6k
  }
27
28
  GtpV1Layer::GtpExtension::GtpExtension(uint8_t* data, size_t dataLen, uint8_t type)
29
1.06k
  {
30
1.06k
    m_Data = data;
31
1.06k
    m_DataLen = dataLen;
32
1.06k
    m_ExtType = type;
33
1.06k
  }
34
35
  GtpV1Layer::GtpExtension::GtpExtension(const GtpExtension& other)
36
0
  {
37
0
    m_Data = other.m_Data;
38
0
    m_DataLen = other.m_DataLen;
39
0
    m_ExtType = other.m_ExtType;
40
0
  }
41
42
  GtpV1Layer::GtpExtension& GtpV1Layer::GtpExtension::operator=(const GtpV1Layer::GtpExtension& other)
43
269
  {
44
269
    m_Data = other.m_Data;
45
269
    m_DataLen = other.m_DataLen;
46
269
    m_ExtType = other.m_ExtType;
47
269
    return *this;
48
269
  }
49
50
  bool GtpV1Layer::GtpExtension::isNull() const
51
19.7k
  {
52
19.7k
    return m_Data == nullptr;
53
19.7k
  }
54
55
  uint8_t GtpV1Layer::GtpExtension::getExtensionType() const
56
4.50k
  {
57
4.50k
    return m_ExtType;
58
4.50k
  }
59
60
  size_t GtpV1Layer::GtpExtension::getTotalLength() const
61
12.3k
  {
62
12.3k
    if (m_Data == nullptr)
63
7.41k
    {
64
7.41k
      return 0;
65
7.41k
    }
66
67
4.93k
    size_t len = (size_t)(m_Data[0] * 4);
68
4.93k
    if (len <= m_DataLen)
69
451
    {
70
451
      return len;
71
451
    }
72
73
4.48k
    return m_DataLen;
74
4.93k
  }
75
76
  size_t GtpV1Layer::GtpExtension::getContentLength() const
77
6.23k
  {
78
6.23k
    size_t res = getTotalLength();
79
80
6.23k
    if (res >= 2 * sizeof(uint8_t))
81
2.39k
    {
82
2.39k
      return (size_t)(res - 2 * sizeof(uint8_t));
83
2.39k
    }
84
85
3.83k
    return 0;
86
6.23k
  }
87
88
  uint8_t* GtpV1Layer::GtpExtension::getContent() const
89
4.50k
  {
90
4.50k
    if (m_Data == nullptr || getContentLength() == 0)
91
3.77k
    {
92
3.77k
      return nullptr;
93
3.77k
    }
94
95
730
    return m_Data + sizeof(uint8_t);
96
4.50k
  }
97
98
  uint8_t GtpV1Layer::GtpExtension::getNextExtensionHeaderType() const
99
4.77k
  {
100
4.77k
    if (m_Data == nullptr || getTotalLength() < 4)
101
3.83k
    {
102
3.83k
      return 0;
103
3.83k
    }
104
105
938
    uint8_t res = *(uint8_t*)(m_Data + sizeof(uint8_t) + getContentLength());
106
107
938
    return res;
108
4.77k
  }
109
110
  GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::getNextExtension() const
111
4.77k
  {
112
4.77k
    size_t totalLength = getTotalLength();
113
4.77k
    uint8_t nextExtType = getNextExtensionHeaderType();
114
4.77k
    if (nextExtType > 0 && m_DataLen > totalLength + sizeof(uint8_t))
115
0
    {
116
0
      return { m_Data + totalLength, m_DataLen - totalLength, nextExtType };
117
0
    }
118
4.77k
    else
119
4.77k
    {
120
4.77k
      return {};
121
4.77k
    }
122
4.77k
  }
123
124
  void GtpV1Layer::GtpExtension::setNextHeaderType(uint8_t nextHeaderType)
125
0
  {
126
0
    if (m_Data != nullptr && m_DataLen > 1)
127
0
    {
128
0
      m_Data[getTotalLength() - 1] = nextHeaderType;
129
0
    }
130
0
  }
131
132
  GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::createGtpExtension(uint8_t* data, size_t dataLen,
133
                                                                        uint8_t extType, uint16_t content)
134
0
  {
135
0
    if (dataLen < 4 * sizeof(uint8_t))
136
0
    {
137
0
      return {};
138
0
    }
139
140
0
    data[0] = 1;
141
0
    data[1] = (content >> 8);
142
0
    data[2] = content & 0xff;
143
0
    data[3] = 0;
144
145
0
    return { data, dataLen, extType };
146
0
  }
147
148
  /// ================
149
  /// GtpV1Layer class
150
  /// ================
151
152
  GtpV1Layer::GtpV1Layer(GtpV1MessageType messageType, uint32_t teid)
153
0
  {
154
0
    init(messageType, teid, false, 0, false, 0);
155
0
  }
156
157
  GtpV1Layer::GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum,
158
                         bool setNpduNum, uint8_t npduNum)
159
0
  {
160
0
    init(messageType, teid, setSeqNum, seqNum, setNpduNum, npduNum);
161
0
  }
162
163
  void GtpV1Layer::init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum,
164
                        uint8_t npduNum)
165
0
  {
166
0
    size_t dataLen = sizeof(gtpv1_header);
167
0
    if (setSeqNum || setNpduNum)
168
0
    {
169
0
      dataLen += sizeof(gtpv1_header_extra);
170
0
    }
171
172
0
    m_DataLen = dataLen;
173
0
    m_Data = new uint8_t[dataLen];
174
0
    memset(m_Data, 0, dataLen);
175
0
    m_Protocol = GTPv1;
176
177
0
    gtpv1_header* hdr = getHeader();
178
0
    hdr->version = 1;
179
0
    hdr->protocolType = 1;
180
0
    hdr->messageType = (uint8_t)messageType;
181
0
    hdr->teid = htobe32(teid);
182
183
0
    if (setSeqNum || setNpduNum)
184
0
    {
185
0
      hdr->messageLength = htobe16(sizeof(gtpv1_header_extra));
186
0
      gtpv1_header_extra* extraHdr = getHeaderExtra();
187
0
      if (setSeqNum)
188
0
      {
189
0
        hdr->sequenceNumberFlag = 1;
190
0
        extraHdr->sequenceNumber = htobe16(seqNum);
191
0
      }
192
193
0
      if (setNpduNum)
194
0
      {
195
0
        hdr->npduNumberFlag = 1;
196
0
        extraHdr->npduNumber = npduNum;
197
0
      }
198
0
    }
199
0
  }
200
201
  bool GtpV1Layer::isGTPv1(const uint8_t* data, size_t dataSize)
202
30.1k
  {
203
30.1k
    if (data != nullptr && dataSize >= sizeof(gtpv1_header) && (data[0] & 0xE0) == 0x20)
204
29.8k
    {
205
29.8k
      return true;
206
29.8k
    }
207
208
296
    return false;
209
30.1k
  }
210
211
  GtpV1Layer::gtpv1_header_extra* GtpV1Layer::getHeaderExtra() const
212
55.7k
  {
213
55.7k
    if (m_Data != nullptr && m_DataLen >= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra))
214
55.1k
    {
215
55.1k
      return (gtpv1_header_extra*)(m_Data + sizeof(gtpv1_header));
216
55.1k
    }
217
218
547
    return nullptr;
219
55.7k
  }
220
221
  bool GtpV1Layer::getSequenceNumber(uint16_t& seqNumber) const
222
4.50k
  {
223
4.50k
    gtpv1_header* header = getHeader();
224
4.50k
    gtpv1_header_extra* headerExtra = getHeaderExtra();
225
4.50k
    if (header != nullptr && headerExtra != nullptr && header->sequenceNumberFlag == 1)
226
2.36k
    {
227
2.36k
      seqNumber = be16toh(headerExtra->sequenceNumber);
228
2.36k
      return true;
229
2.36k
    }
230
231
2.13k
    return false;
232
4.50k
  }
233
234
  bool GtpV1Layer::setSequenceNumber(const uint16_t seqNumber)
235
0
  {
236
    // get GTP header
237
0
    gtpv1_header* header = getHeader();
238
0
    if (header == nullptr)
239
0
    {
240
0
      PCPP_LOG_ERROR("Set sequence failed: GTP header is nullptr");
241
0
      return false;
242
0
    }
243
244
    // if all flags are unset then create the GTP extra header
245
0
    if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0)
246
0
    {
247
0
      if (!extendLayer(sizeof(gtpv1_header), sizeof(gtpv1_header_extra)))
248
0
      {
249
0
        PCPP_LOG_ERROR("Set sequence failed: cannot extend layer");
250
0
        return false;
251
0
      }
252
0
      header = getHeader();
253
0
    }
254
255
    // get the extra header
256
0
    gtpv1_header_extra* headerExtra = getHeaderExtra();
257
0
    if (headerExtra == nullptr)
258
0
    {
259
0
      PCPP_LOG_ERROR("Set sequence failed: extra header is nullptr");
260
0
      return false;
261
0
    }
262
263
    // set seq number
264
0
    header->sequenceNumberFlag = 1;
265
0
    headerExtra->sequenceNumber = htobe16(seqNumber);
266
267
    // extend GTP length
268
0
    header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(gtpv1_header_extra));
269
270
0
    return true;
271
0
  }
272
273
  bool GtpV1Layer::getNpduNumber(uint8_t& npduNum) const
274
4.50k
  {
275
4.50k
    gtpv1_header* header = getHeader();
276
4.50k
    gtpv1_header_extra* headerExtra = getHeaderExtra();
277
4.50k
    if (header != nullptr && headerExtra != nullptr && header->npduNumberFlag == 1)
278
1.41k
    {
279
1.41k
      npduNum = headerExtra->npduNumber;
280
1.41k
      return true;
281
1.41k
    }
282
283
3.08k
    return false;
284
4.50k
  }
285
286
  bool GtpV1Layer::setNpduNumber(const uint8_t npduNum)
287
0
  {
288
    // get GTP header
289
0
    gtpv1_header* header = getHeader();
290
0
    if (header == nullptr)
291
0
    {
292
0
      PCPP_LOG_ERROR("Set N-PDU failed: GTP header is nullptr");
293
0
      return false;
294
0
    }
295
296
    // if all flags are unset then create the GTP extra header
297
0
    if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0)
298
0
    {
299
0
      if (!extendLayer(sizeof(gtpv1_header), sizeof(gtpv1_header_extra)))
300
0
      {
301
0
        PCPP_LOG_ERROR("Set N-PDU failed: cannot extend layer");
302
0
        return false;
303
0
      }
304
0
      header = getHeader();
305
0
    }
306
307
    // get the extra header
308
0
    gtpv1_header_extra* headerExtra = getHeaderExtra();
309
0
    if (headerExtra == nullptr)
310
0
    {
311
0
      PCPP_LOG_ERROR("Set N-PDU failed: extra header is nullptr");
312
0
      return false;
313
0
    }
314
315
    // set N-PDU value
316
0
    header->npduNumberFlag = 1;
317
0
    headerExtra->npduNumber = npduNum;
318
319
    // extend GTP length
320
0
    header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(gtpv1_header_extra));
321
322
0
    return true;
323
0
  }
324
325
  bool GtpV1Layer::getNextExtensionHeaderType(uint8_t& nextExtType) const
326
23.9k
  {
327
23.9k
    gtpv1_header* header = getHeader();
328
23.9k
    gtpv1_header_extra* headerExtra = getHeaderExtra();
329
23.9k
    if (header != nullptr && headerExtra != nullptr && header->extensionHeaderFlag == 1)
330
4.60k
    {
331
4.60k
      nextExtType = headerExtra->nextExtensionHeader;
332
4.60k
      return true;
333
4.60k
    }
334
335
19.3k
    return false;
336
23.9k
  }
337
338
  GtpV1Layer::GtpExtension GtpV1Layer::getNextExtension() const
339
23.9k
  {
340
23.9k
    uint8_t nextExtType = 0;
341
23.9k
    bool nextExtExists = getNextExtensionHeaderType(nextExtType);
342
23.9k
    if (!nextExtExists || nextExtType == 0 || m_DataLen <= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra))
343
22.8k
    {
344
22.8k
      return {};
345
22.8k
    }
346
347
1.06k
    return { m_Data + sizeof(gtpv1_header) + sizeof(gtpv1_header_extra),
348
1.06k
           m_DataLen - sizeof(gtpv1_header) - sizeof(gtpv1_header_extra), nextExtType };
349
23.9k
  }
350
351
  GtpV1Layer::GtpExtension GtpV1Layer::addExtension(uint8_t extensionType, uint16_t extensionContent)
352
0
  {
353
    // get GTP header
354
0
    gtpv1_header* header = getHeader();
355
0
    if (header == nullptr)
356
0
    {
357
0
      PCPP_LOG_ERROR("Add extension failed: GTP header is nullptr");
358
0
      return {};
359
0
    }
360
361
0
    size_t offsetForNewExtension = sizeof(gtpv1_header);
362
363
    // if all flags are unset then create the GTP extra header
364
0
    if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0)
365
0
    {
366
0
      if (!extendLayer(offsetForNewExtension, sizeof(gtpv1_header_extra)))
367
0
      {
368
0
        PCPP_LOG_ERROR("Add extension failed: cannot extend layer");
369
0
        return {};
370
0
      }
371
0
    }
372
373
    // get the extra header
374
0
    gtpv1_header_extra* headerExtra = getHeaderExtra();
375
0
    if (headerExtra == nullptr)
376
0
    {
377
0
      PCPP_LOG_ERROR("Add extension failed: extra header is nullptr");
378
0
      return {};
379
0
    }
380
381
0
    offsetForNewExtension += sizeof(gtpv1_header_extra);
382
383
    // find the last GTP header extension
384
0
    GtpV1Layer::GtpExtension lastExt = getNextExtension();
385
386
    // go over the GTP header extensions
387
0
    while (!lastExt.getNextExtension().isNull())
388
0
    {
389
      // add ext total length to offset
390
0
      offsetForNewExtension += lastExt.getTotalLength();
391
0
      lastExt = lastExt.getNextExtension();
392
0
    }
393
394
    // lastExt != null means layer contains 1 or more extensions
395
0
    if (!lastExt.isNull())
396
0
    {
397
      // add ext total length to offset
398
0
      offsetForNewExtension += lastExt.getTotalLength();
399
0
    }
400
401
    // allocate extension space in layer (assuming extension length can only be 4 bytes)
402
0
    if (!extendLayer(offsetForNewExtension, 4 * sizeof(uint8_t)))
403
0
    {
404
0
      PCPP_LOG_ERROR("Add extension failed: cannot extend layer");
405
0
      return {};
406
0
    }
407
408
    // lastExt != null means layer contains 1 or more extensions
409
0
    if (!lastExt.isNull())
410
0
    {
411
      // set the next header type in the last extension
412
0
      lastExt.setNextHeaderType(extensionType);
413
0
    }
414
0
    else
415
0
    {
416
      // mark extension flags in the layer
417
0
      header = getHeader();
418
0
      headerExtra = getHeaderExtra();
419
420
0
      header->extensionHeaderFlag = 1;
421
0
      headerExtra->nextExtensionHeader = extensionType;
422
0
    }
423
424
    // create the extension data and return the extension object to the user
425
0
    return GtpV1Layer::GtpExtension::createGtpExtension(
426
0
        m_Data + offsetForNewExtension, m_DataLen - offsetForNewExtension, extensionType, extensionContent);
427
0
  }
428
429
  GtpV1MessageType GtpV1Layer::getMessageType() const
430
4.50k
  {
431
4.50k
    gtpv1_header* header = getHeader();
432
433
4.50k
    if (header == nullptr)
434
0
    {
435
0
      return GtpV1_MessageTypeUnknown;
436
0
    }
437
438
4.50k
    return (GtpV1MessageType)header->messageType;
439
4.50k
  }
440
441
  std::unordered_map<uint8_t, std::string> createGtpV1MessageTypeToStringMap()
442
2
  {
443
2
    std::unordered_map<uint8_t, std::string> tempMap;
444
445
2
    tempMap[0] = "GTPv1 Message Type Unknown";
446
2
    tempMap[1] = "Echo Request";
447
2
    tempMap[2] = "Echo Response";
448
2
    tempMap[3] = "Version Not Supported";
449
2
    tempMap[4] = "Node Alive Request";
450
2
    tempMap[5] = "Node Alive Response";
451
2
    tempMap[6] = "Redirection Request";
452
2
    tempMap[7] = "Create PDP Context Request";
453
2
    tempMap[16] = "Create PDP Context Response";
454
2
    tempMap[17] = "Update PDP Context Request";
455
2
    tempMap[18] = "Update PDP Context Response";
456
2
    tempMap[19] = "Delete PDP Context Request";
457
2
    tempMap[20] = "Delete PDP Context Response";
458
2
    tempMap[22] = "Initiate PDP Context Activation Request";
459
2
    tempMap[23] = "Initiate PDP Context Activation Response";
460
2
    tempMap[26] = "Error Indication";
461
2
    tempMap[27] = "PDU Notification Request";
462
2
    tempMap[28] = "PDU Notification Response";
463
2
    tempMap[29] = "PDU Notification Reject Request";
464
2
    tempMap[30] = "PDU Notification Reject Response";
465
2
    tempMap[31] = "Supported Extensions Header Notification";
466
2
    tempMap[32] = "Send Routing for GPRS Request";
467
2
    tempMap[33] = "Send Routing for GPRS Response";
468
2
    tempMap[34] = "Failure Report Request";
469
2
    tempMap[35] = "Failure Report Response";
470
2
    tempMap[36] = "Note MS Present Request";
471
2
    tempMap[37] = "Note MS Present Response";
472
2
    tempMap[38] = "Identification Request";
473
2
    tempMap[39] = "Identification Response";
474
2
    tempMap[50] = "SGSN Context Request";
475
2
    tempMap[51] = "SGSN Context Response";
476
2
    tempMap[52] = "SGSN Context Acknowledge";
477
2
    tempMap[53] = "Forward Relocation Request";
478
2
    tempMap[54] = "Forward Relocation Response";
479
2
    tempMap[55] = "Forward Relocation Complete";
480
2
    tempMap[56] = "Relocation Cancel Request";
481
2
    tempMap[57] = "Relocation Cancel Response";
482
2
    tempMap[58] = "Forward SRNS Context";
483
2
    tempMap[59] = "Forward Relocation Complete Acknowledge";
484
2
    tempMap[60] = "Forward SRNS Context Acknowledge";
485
2
    tempMap[61] = "UE Registration Request";
486
2
    tempMap[62] = "UE Registration Response";
487
2
    tempMap[70] = "RAN Information Relay";
488
2
    tempMap[96] = "MBMS Notification Request";
489
2
    tempMap[97] = "MBMS Notification Response";
490
2
    tempMap[98] = "MBMS Notification Reject Request";
491
2
    tempMap[99] = "MBMS Notification Reject Response";
492
2
    tempMap[100] = "Create MBMS Notification Request";
493
2
    tempMap[101] = "Create MBMS Notification Response";
494
2
    tempMap[102] = "Update MBMS Notification Request";
495
2
    tempMap[103] = "Update MBMS Notification Response";
496
2
    tempMap[104] = "Delete MBMS Notification Request";
497
2
    tempMap[105] = "Delete MBMS Notification Response";
498
2
    tempMap[112] = "MBMS Registration Request";
499
2
    tempMap[113] = "MBMS Registration Response";
500
2
    tempMap[114] = "MBMS De-Registration Request";
501
2
    tempMap[115] = "MBMS De-Registration Response";
502
2
    tempMap[116] = "MBMS Session Start Request";
503
2
    tempMap[117] = "MBMS Session Start Response";
504
2
    tempMap[118] = "MBMS Session Stop Request";
505
2
    tempMap[119] = "MBMS Session Stop Response";
506
2
    tempMap[120] = "MBMS Session Update Request";
507
2
    tempMap[121] = "MBMS Session Update Response";
508
2
    tempMap[128] = "MS Info Change Request";
509
2
    tempMap[129] = "MS Info Change Response";
510
2
    tempMap[240] = "Data Record Transfer Request";
511
2
    tempMap[241] = "Data Record Transfer Response";
512
2
    tempMap[254] = "End Marker";
513
2
    tempMap[255] = "G-PDU";
514
515
2
    return tempMap;
516
2
  }
517
518
  const std::unordered_map<uint8_t, std::string> GTPv1MsgTypeToStringMap = createGtpV1MessageTypeToStringMap();
519
520
  std::string GtpV1Layer::getMessageTypeAsString() const
521
8.21k
  {
522
8.21k
    gtpv1_header* header = getHeader();
523
524
8.21k
    if (header == nullptr)
525
0
    {
526
0
      return GTPv1MsgTypeToStringMap.find(0)->second;
527
0
    }
528
529
8.21k
    auto iter = GTPv1MsgTypeToStringMap.find(header->messageType);
530
8.21k
    if (iter != GTPv1MsgTypeToStringMap.end())
531
4.72k
    {
532
4.72k
      return iter->second;
533
4.72k
    }
534
3.49k
    else
535
3.49k
    {
536
3.49k
      return GTPv1MsgTypeToStringMap.find(0)->second;
537
3.49k
    }
538
8.21k
  }
539
540
  bool GtpV1Layer::isGTPUMessage() const
541
4.50k
  {
542
4.50k
    gtpv1_header* header = getHeader();
543
4.50k
    if (header == nullptr)
544
0
    {
545
0
      return false;
546
0
    }
547
548
4.50k
    return header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
549
4.50k
  }
550
551
  bool GtpV1Layer::isGTPCMessage() const
552
4.50k
  {
553
4.50k
    gtpv1_header* header = getHeader();
554
4.50k
    if (header == nullptr)
555
0
    {
556
0
      return false;
557
0
    }
558
559
4.50k
    return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
560
4.50k
  }
561
562
  void GtpV1Layer::parseNextLayer()
563
29.8k
  {
564
29.8k
    size_t headerLen = getHeaderLen();
565
29.8k
    if (headerLen < sizeof(gtpv1_header))
566
0
    {
567
      // do nothing
568
0
      return;
569
0
    }
570
571
29.8k
    gtpv1_header* header = getHeader();
572
29.8k
    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
573
9.72k
    {
574
      // this is a GTP-C message, hence it is the last layer
575
9.72k
      return;
576
9.72k
    }
577
578
20.0k
    if (m_DataLen <= headerLen)
579
242
    {
580
      // no data beyond headerLen, nothing to parse further
581
242
      return;
582
242
    }
583
584
    // GTP-U message, try to parse the next layer
585
586
19.8k
    auto* payload = static_cast<uint8_t*>(m_Data + headerLen);
587
19.8k
    size_t payloadLen = m_DataLen - headerLen;
588
589
19.8k
    uint8_t subProto = *payload;
590
19.8k
    if (subProto >= 0x45 && subProto <= 0x4e)
591
17.4k
    {
592
17.4k
      m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
593
17.4k
                        ? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
594
17.4k
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
595
17.4k
    }
596
2.45k
    else if ((subProto & 0xf0) == 0x60)
597
1.74k
    {
598
1.74k
      m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
599
1.74k
                        ? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
600
1.74k
                        : static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
601
1.74k
    }
602
706
    else
603
706
    {
604
706
      m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
605
706
    }
606
19.8k
  }
607
608
  size_t GtpV1Layer::getHeaderLen() const
609
34.3k
  {
610
34.3k
    gtpv1_header* header = getHeader();
611
34.3k
    if (header == nullptr)
612
0
    {
613
0
      return 0;
614
0
    }
615
616
34.3k
    size_t res = sizeof(gtpv1_header);
617
618
34.3k
    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
619
11.5k
    {
620
11.5k
      size_t msgLen = be16toh(header->messageLength);
621
11.5k
      res += (msgLen > m_DataLen - sizeof(gtpv1_header) ? m_DataLen - sizeof(gtpv1_header) : msgLen);
622
11.5k
    }
623
22.7k
    else
624
22.7k
    {
625
22.7k
      gtpv1_header_extra* headerExtra = getHeaderExtra();
626
22.7k
      if (headerExtra != nullptr &&
627
22.6k
          (header->extensionHeaderFlag == 1 || header->sequenceNumberFlag == 1 || header->npduNumberFlag == 1))
628
19.4k
      {
629
19.4k
        res += sizeof(gtpv1_header_extra);
630
19.4k
        GtpExtension nextExt = getNextExtension();
631
19.7k
        while (!nextExt.isNull())
632
269
        {
633
269
          res += nextExt.getTotalLength();
634
269
          nextExt = nextExt.getNextExtension();
635
269
        }
636
19.4k
      }
637
22.7k
    }
638
639
34.3k
    return res;
640
34.3k
  }
641
642
  std::string GtpV1Layer::toString() const
643
9.00k
  {
644
9.00k
    std::string res = "GTP v1 Layer";
645
646
9.00k
    gtpv1_header* header = getHeader();
647
9.00k
    if (header != nullptr)
648
9.00k
    {
649
9.00k
      std::stringstream teidStream;
650
9.00k
      teidStream << be32toh(header->teid);
651
652
9.00k
      std::string gtpu_gtpc;
653
9.00k
      if (header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
654
5.28k
      {
655
5.28k
        gtpu_gtpc = "GTP-U message";
656
5.28k
      }
657
3.71k
      else
658
3.71k
      {
659
3.71k
        gtpu_gtpc = "GTP-C message: " + getMessageTypeAsString();
660
3.71k
      }
661
662
9.00k
      res += ", " + gtpu_gtpc + ", TEID: " + teidStream.str();
663
9.00k
    }
664
665
9.00k
    return res;
666
9.00k
  }
667
668
  void GtpV1Layer::computeCalculateFields()
669
4.50k
  {
670
4.50k
    gtpv1_header* hdr = getHeader();
671
4.50k
    if (hdr == nullptr)
672
0
    {
673
0
      return;
674
0
    }
675
676
4.50k
    hdr->messageLength = htobe16(m_DataLen - sizeof(gtpv1_header));
677
4.50k
  }
678
679
  /// ================
680
  /// GtpV2MessageType
681
  /// ================
682
683
  struct GtpV2MessageTypeHash
684
  {
685
    size_t operator()(const GtpV2MessageType& messageType) const
686
164
    {
687
164
      return static_cast<uint8_t>(messageType);
688
164
    }
689
  };
690
691
  static const std::unordered_map<GtpV2MessageType, std::string, GtpV2MessageTypeHash> messageTypeMap = {
692
    { GtpV2MessageType::EchoRequest,                      "Echo Request"                         },
693
    { GtpV2MessageType::EchoResponse,                     "Echo Response"                        },
694
    { GtpV2MessageType::VersionNotSupported,              "Version Not Supported"                },
695
    { GtpV2MessageType::CreateSessionRequest,             "Create Session Request"               },
696
    { GtpV2MessageType::CreateSessionResponse,            "Create Session Response"              },
697
    { GtpV2MessageType::ModifyBearerRequest,              "Modify Bearer Request"                },
698
    { GtpV2MessageType::ModifyBearerResponse,             "Modify Bearer Response"               },
699
    { GtpV2MessageType::DeleteSessionRequest,             "Delete Session Request"               },
700
    { GtpV2MessageType::DeleteSessionResponse,            "Delete Session Response"              },
701
    { GtpV2MessageType::ChangeNotificationRequest,        "Change Notification Request"          },
702
    { GtpV2MessageType::ChangeNotificationResponse,       "Change Notification Response"         },
703
    { GtpV2MessageType::RemoteUEReportNotifications,      "Remote UE Report Notifications"       },
704
    { GtpV2MessageType::RemoteUEReportAcknowledge,        "Remote UE Report Acknowledge"         },
705
    { GtpV2MessageType::ModifyBearerCommand,              "Modify Bearer Command"                },
706
    { GtpV2MessageType::ModifyBearerFailure,              "Modify Bearer Failure"                },
707
    { GtpV2MessageType::DeleteBearerCommand,              "Delete Bearer Command"                },
708
    { GtpV2MessageType::DeleteBearerFailure,              "Delete Bearer Failure"                },
709
    { GtpV2MessageType::BearerResourceCommand,            "Bearer Resource Command"              },
710
    { GtpV2MessageType::BearerResourceFailure,            "Bearer Resource Failure"              },
711
    { GtpV2MessageType::DownlinkDataNotificationFailure,  "Downlink Data Notification Failure"   },
712
    { GtpV2MessageType::TraceSessionActivation,           "Trace Session Activation"             },
713
    { GtpV2MessageType::TraceSessionDeactivation,         "Trace Session Deactivation"           },
714
    { GtpV2MessageType::StopPagingIndication,             "Stop Paging Indication"               },
715
    { GtpV2MessageType::CreateBearerRequest,              "Create Bearer Request"                },
716
    { GtpV2MessageType::CreateBearerResponse,             "Create Bearer Response"               },
717
    { GtpV2MessageType::UpdateBearerRequest,              "Update Bearer Request"                },
718
    { GtpV2MessageType::UpdateBearerResponse,             "Update Bearer Response"               },
719
    { GtpV2MessageType::DeleteBearerRequest,              "Delete Bearer Request"                },
720
    { GtpV2MessageType::DeleteBearerResponse,             "Delete Bearer Response"               },
721
    { GtpV2MessageType::DeletePDNRequest,                 "Delete PDN Request"                   },
722
    { GtpV2MessageType::DeletePDNResponse,                "Delete PDN Response"                  },
723
    { GtpV2MessageType::PGWDownlinkNotification,          "PGW Downlink Notification"            },
724
    { GtpV2MessageType::PGWDownlinkAcknowledge,           "PGW Downlink Acknowledge"             },
725
    { GtpV2MessageType::IdentificationRequest,            "Identification Request"               },
726
    { GtpV2MessageType::IdentificationResponse,           "Identification Response"              },
727
    { GtpV2MessageType::ContextRequest,                   "Context Request"                      },
728
    { GtpV2MessageType::ContextResponse,                  "Context Response"                     },
729
    { GtpV2MessageType::ContextAcknowledge,               "Context Acknowledge"                  },
730
    { GtpV2MessageType::ForwardRelocationRequest,         "Forward Relocation Request"           },
731
    { GtpV2MessageType::ForwardRelocationResponse,        "Forward Relocation Response"          },
732
    { GtpV2MessageType::ForwardRelocationNotification,    "Forward Relocation Notification"      },
733
    { GtpV2MessageType::ForwardRelocationAcknowledge,     "Forward Relocation Acknowledge"       },
734
    { GtpV2MessageType::ForwardAccessNotification,        "Forward Access Notification"          },
735
    { GtpV2MessageType::ForwardAccessAcknowledge,         "Forward Access Acknowledge"           },
736
    { GtpV2MessageType::RelocationCancelRequest,          "Relocation Cancel Request"            },
737
    { GtpV2MessageType::RelocationCancelResponse,         "Relocation Cancel Response"           },
738
    { GtpV2MessageType::ConfigurationTransferTunnel,      "Configuration Transfer Tunnel"        },
739
    { GtpV2MessageType::DetachNotification,               "Detach Notification"                  },
740
    { GtpV2MessageType::DetachAcknowledge,                "Detach Acknowledge"                   },
741
    { GtpV2MessageType::CSPaging,                         "CS Paging"                            },
742
    { GtpV2MessageType::RANInformationRelay,              "RAN Information Relay"                },
743
    { GtpV2MessageType::AlertMMENotification,             "Alert MME Notification"               },
744
    { GtpV2MessageType::AlertMMEAcknowledge,              "Alert MME Acknowledge"                },
745
    { GtpV2MessageType::UEActivityNotification,           "UE Activity Notification"             },
746
    { GtpV2MessageType::UEActivityAcknowledge,            "UE Activity Acknowledge"              },
747
    { GtpV2MessageType::ISRStatus,                        "ISR Status"                           },
748
    { GtpV2MessageType::CreateForwardingRequest,          "Create Forwarding Request"            },
749
    { GtpV2MessageType::CreateForwardingResponse,         "Create Forwarding Response"           },
750
    { GtpV2MessageType::SuspendNotification,              "Suspend Notification"                 },
751
    { GtpV2MessageType::SuspendAcknowledge,               "Suspend Acknowledge"                  },
752
    { GtpV2MessageType::ResumeNotification,               "Resume Notification"                  },
753
    { GtpV2MessageType::ResumeAcknowledge,                "Resume Acknowledge"                   },
754
    { GtpV2MessageType::CreateIndirectDataTunnelRequest,  "Create Indirect Data Tunnel Request"  },
755
    { GtpV2MessageType::CreateIndirectDataTunnelResponse, "Create Indirect Data Tunnel Response" },
756
    { GtpV2MessageType::DeleteIndirectDataTunnelRequest,  "Delete Indirect Data Tunnel Request"  },
757
    { GtpV2MessageType::DeleteIndirectDataTunnelResponse, "Delete Indirect Data Tunnel Response" },
758
    { GtpV2MessageType::ReleaseAccessBearersRequest,      "Release Access Bearers Request"       },
759
    { GtpV2MessageType::ReleaseAccessBearersResponse,     "Release Access Bearers Response"      },
760
    { GtpV2MessageType::DownlinkDataNotification,         "Downlink Data Notification"           },
761
    { GtpV2MessageType::DownlinkDataAcknowledge,          "Downlink Data Acknowledge"            },
762
    { GtpV2MessageType::PGWRestartNotification,           "PGW Restart Notification"             },
763
    { GtpV2MessageType::PGWRestartAcknowledge,            "PGW Restart Acknowledge"              },
764
    { GtpV2MessageType::UpdatePDNConnectionRequest,       "Update PDN Connection Request"        },
765
    { GtpV2MessageType::UpdatePDNConnectionResponse,      "Update PDN Connection Response"       },
766
    { GtpV2MessageType::ModifyAccessBearersRequest,       "Modify Access Bearers Request"        },
767
    { GtpV2MessageType::ModifyAccessBearersResponse,      "Modify Access Bearers Response"       },
768
    { GtpV2MessageType::MMBSSessionStartRequest,          "MMBS Session Start Request"           },
769
    { GtpV2MessageType::MMBSSessionStartResponse,         "MMBS Session Start Response"          },
770
    { GtpV2MessageType::MMBSSessionUpdateRequest,         "MMBS Session Update Request"          },
771
    { GtpV2MessageType::MMBSSessionUpdateResponse,        "MMBS Session Update Response"         },
772
    { GtpV2MessageType::MMBSSessionStopRequest,           "MMBS Session Stop Request"            },
773
    { GtpV2MessageType::MMBSSessionStopResponse,          "MMBS Session Stop Response"           }
774
  };
775
776
  std::string GtpV2MessageType::toString() const
777
0
  {
778
0
    auto iter = messageTypeMap.find(m_Value);
779
0
    if (iter != messageTypeMap.end())
780
0
    {
781
0
      return iter->second;
782
0
    }
783
784
0
    return "Unknown GTPv2 Message Type";
785
0
  }
786
787
  // clang-format off
788
  static const std::unordered_map<uint8_t, GtpV2MessageType> uintToValueMap = {
789
    { static_cast<uint8_t>(GtpV2MessageType::EchoRequest),                      GtpV2MessageType::EchoRequest                      },
790
    { static_cast<uint8_t>(GtpV2MessageType::EchoResponse),                     GtpV2MessageType::EchoResponse                     },
791
    { static_cast<uint8_t>(GtpV2MessageType::VersionNotSupported),              GtpV2MessageType::VersionNotSupported              },
792
    { static_cast<uint8_t>(GtpV2MessageType::CreateSessionRequest),             GtpV2MessageType::CreateSessionRequest             },
793
    { static_cast<uint8_t>(GtpV2MessageType::CreateSessionResponse),            GtpV2MessageType::CreateSessionResponse            },
794
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerRequest),              GtpV2MessageType::ModifyBearerRequest              },
795
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerResponse),             GtpV2MessageType::ModifyBearerResponse             },
796
    { static_cast<uint8_t>(GtpV2MessageType::DeleteSessionRequest),             GtpV2MessageType::DeleteSessionRequest             },
797
    { static_cast<uint8_t>(GtpV2MessageType::DeleteSessionResponse),            GtpV2MessageType::DeleteSessionResponse            },
798
    { static_cast<uint8_t>(GtpV2MessageType::ChangeNotificationRequest),        GtpV2MessageType::ChangeNotificationRequest        },
799
    { static_cast<uint8_t>(GtpV2MessageType::ChangeNotificationResponse),       GtpV2MessageType::ChangeNotificationResponse       },
800
    { static_cast<uint8_t>(GtpV2MessageType::RemoteUEReportNotifications),      GtpV2MessageType::RemoteUEReportNotifications      },
801
    { static_cast<uint8_t>(GtpV2MessageType::RemoteUEReportAcknowledge),        GtpV2MessageType::RemoteUEReportAcknowledge        },
802
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerCommand),              GtpV2MessageType::ModifyBearerCommand              },
803
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerFailure),              GtpV2MessageType::ModifyBearerFailure              },
804
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerCommand),              GtpV2MessageType::DeleteBearerCommand              },
805
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerFailure),              GtpV2MessageType::DeleteBearerFailure              },
806
    { static_cast<uint8_t>(GtpV2MessageType::BearerResourceCommand),            GtpV2MessageType::BearerResourceCommand            },
807
    { static_cast<uint8_t>(GtpV2MessageType::BearerResourceFailure),            GtpV2MessageType::BearerResourceFailure            },
808
    { static_cast<uint8_t>(GtpV2MessageType::DownlinkDataNotificationFailure),  GtpV2MessageType::DownlinkDataNotificationFailure  },
809
    { static_cast<uint8_t>(GtpV2MessageType::TraceSessionActivation),           GtpV2MessageType::TraceSessionActivation           },
810
    { static_cast<uint8_t>(GtpV2MessageType::TraceSessionDeactivation),         GtpV2MessageType::TraceSessionDeactivation         },
811
    { static_cast<uint8_t>(GtpV2MessageType::StopPagingIndication),             GtpV2MessageType::StopPagingIndication             },
812
    { static_cast<uint8_t>(GtpV2MessageType::CreateBearerRequest),              GtpV2MessageType::CreateBearerRequest              },
813
    { static_cast<uint8_t>(GtpV2MessageType::CreateBearerResponse),             GtpV2MessageType::CreateBearerResponse             },
814
    { static_cast<uint8_t>(GtpV2MessageType::UpdateBearerRequest),              GtpV2MessageType::UpdateBearerRequest              },
815
    { static_cast<uint8_t>(GtpV2MessageType::UpdateBearerResponse),             GtpV2MessageType::UpdateBearerResponse             },
816
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerRequest),              GtpV2MessageType::DeleteBearerRequest              },
817
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerResponse),             GtpV2MessageType::DeleteBearerResponse             },
818
    { static_cast<uint8_t>(GtpV2MessageType::DeletePDNRequest),                 GtpV2MessageType::DeletePDNRequest                 },
819
    { static_cast<uint8_t>(GtpV2MessageType::DeletePDNResponse),                GtpV2MessageType::DeletePDNResponse                },
820
    { static_cast<uint8_t>(GtpV2MessageType::PGWDownlinkNotification),          GtpV2MessageType::PGWDownlinkNotification          },
821
    { static_cast<uint8_t>(GtpV2MessageType::PGWDownlinkAcknowledge),           GtpV2MessageType::PGWDownlinkAcknowledge           },
822
    { static_cast<uint8_t>(GtpV2MessageType::IdentificationRequest),            GtpV2MessageType::IdentificationRequest            },
823
    { static_cast<uint8_t>(GtpV2MessageType::IdentificationResponse),           GtpV2MessageType::IdentificationResponse           },
824
    { static_cast<uint8_t>(GtpV2MessageType::ContextRequest),                   GtpV2MessageType::ContextRequest                   },
825
    { static_cast<uint8_t>(GtpV2MessageType::ContextResponse),                  GtpV2MessageType::ContextResponse                  },
826
    { static_cast<uint8_t>(GtpV2MessageType::ContextAcknowledge),               GtpV2MessageType::ContextAcknowledge               },
827
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationRequest),         GtpV2MessageType::ForwardRelocationRequest         },
828
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationResponse),        GtpV2MessageType::ForwardRelocationResponse        },
829
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationNotification),    GtpV2MessageType::ForwardRelocationNotification    },
830
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationAcknowledge),     GtpV2MessageType::ForwardRelocationAcknowledge     },
831
    { static_cast<uint8_t>(GtpV2MessageType::ForwardAccessNotification),        GtpV2MessageType::ForwardAccessNotification        },
832
    { static_cast<uint8_t>(GtpV2MessageType::ForwardAccessAcknowledge),         GtpV2MessageType::ForwardAccessAcknowledge         },
833
    { static_cast<uint8_t>(GtpV2MessageType::RelocationCancelRequest),          GtpV2MessageType::RelocationCancelRequest          },
834
    { static_cast<uint8_t>(GtpV2MessageType::RelocationCancelResponse),         GtpV2MessageType::RelocationCancelResponse         },
835
    { static_cast<uint8_t>(GtpV2MessageType::ConfigurationTransferTunnel),      GtpV2MessageType::ConfigurationTransferTunnel      },
836
    { static_cast<uint8_t>(GtpV2MessageType::DetachNotification),               GtpV2MessageType::DetachNotification               },
837
    { static_cast<uint8_t>(GtpV2MessageType::DetachAcknowledge),                GtpV2MessageType::DetachAcknowledge                },
838
    { static_cast<uint8_t>(GtpV2MessageType::CSPaging),                         GtpV2MessageType::CSPaging                         },
839
    { static_cast<uint8_t>(GtpV2MessageType::RANInformationRelay),              GtpV2MessageType::RANInformationRelay              },
840
    { static_cast<uint8_t>(GtpV2MessageType::AlertMMENotification),             GtpV2MessageType::AlertMMENotification             },
841
    { static_cast<uint8_t>(GtpV2MessageType::AlertMMEAcknowledge),              GtpV2MessageType::AlertMMEAcknowledge              },
842
    { static_cast<uint8_t>(GtpV2MessageType::UEActivityNotification),           GtpV2MessageType::UEActivityNotification           },
843
    { static_cast<uint8_t>(GtpV2MessageType::UEActivityAcknowledge),            GtpV2MessageType::UEActivityAcknowledge            },
844
    { static_cast<uint8_t>(GtpV2MessageType::ISRStatus),                        GtpV2MessageType::ISRStatus                        },
845
    { static_cast<uint8_t>(GtpV2MessageType::CreateForwardingRequest),          GtpV2MessageType::CreateForwardingRequest          },
846
    { static_cast<uint8_t>(GtpV2MessageType::CreateForwardingResponse),         GtpV2MessageType::CreateForwardingResponse         },
847
    { static_cast<uint8_t>(GtpV2MessageType::SuspendNotification),              GtpV2MessageType::SuspendNotification              },
848
    { static_cast<uint8_t>(GtpV2MessageType::SuspendAcknowledge),               GtpV2MessageType::SuspendAcknowledge               },
849
    { static_cast<uint8_t>(GtpV2MessageType::ResumeNotification),               GtpV2MessageType::ResumeNotification               },
850
    { static_cast<uint8_t>(GtpV2MessageType::ResumeAcknowledge),                GtpV2MessageType::ResumeAcknowledge                },
851
    { static_cast<uint8_t>(GtpV2MessageType::CreateIndirectDataTunnelRequest),  GtpV2MessageType::CreateIndirectDataTunnelRequest  },
852
    { static_cast<uint8_t>(GtpV2MessageType::CreateIndirectDataTunnelResponse), GtpV2MessageType::CreateIndirectDataTunnelResponse },
853
    { static_cast<uint8_t>(GtpV2MessageType::DeleteIndirectDataTunnelRequest),  GtpV2MessageType::DeleteIndirectDataTunnelRequest  },
854
    { static_cast<uint8_t>(GtpV2MessageType::DeleteIndirectDataTunnelResponse), GtpV2MessageType::DeleteIndirectDataTunnelResponse },
855
    { static_cast<uint8_t>(GtpV2MessageType::ReleaseAccessBearersRequest),      GtpV2MessageType::ReleaseAccessBearersRequest      },
856
    { static_cast<uint8_t>(GtpV2MessageType::ReleaseAccessBearersResponse),     GtpV2MessageType::ReleaseAccessBearersResponse     },
857
    { static_cast<uint8_t>(GtpV2MessageType::DownlinkDataNotification),         GtpV2MessageType::DownlinkDataNotification         },
858
    { static_cast<uint8_t>(GtpV2MessageType::DownlinkDataAcknowledge),          GtpV2MessageType::DownlinkDataAcknowledge          },
859
    { static_cast<uint8_t>(GtpV2MessageType::PGWRestartNotification),           GtpV2MessageType::PGWRestartNotification           },
860
    { static_cast<uint8_t>(GtpV2MessageType::PGWRestartAcknowledge),            GtpV2MessageType::PGWRestartAcknowledge            },
861
    { static_cast<uint8_t>(GtpV2MessageType::UpdatePDNConnectionRequest),       GtpV2MessageType::UpdatePDNConnectionRequest       },
862
    { static_cast<uint8_t>(GtpV2MessageType::UpdatePDNConnectionResponse),      GtpV2MessageType::UpdatePDNConnectionResponse      },
863
    { static_cast<uint8_t>(GtpV2MessageType::ModifyAccessBearersRequest),       GtpV2MessageType::ModifyAccessBearersRequest       },
864
    { static_cast<uint8_t>(GtpV2MessageType::ModifyAccessBearersResponse),      GtpV2MessageType::ModifyAccessBearersResponse      },
865
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStartRequest),          GtpV2MessageType::MMBSSessionStartRequest          },
866
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStartResponse),         GtpV2MessageType::MMBSSessionStartResponse         },
867
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionUpdateRequest),         GtpV2MessageType::MMBSSessionUpdateRequest         },
868
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionUpdateResponse),        GtpV2MessageType::MMBSSessionUpdateResponse        },
869
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStopRequest),           GtpV2MessageType::MMBSSessionStopRequest           },
870
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStopResponse),          GtpV2MessageType::MMBSSessionStopResponse          }
871
  };
872
  // clang-format on
873
874
  GtpV2MessageType GtpV2MessageType::fromUintValue(uint8_t value)
875
0
  {
876
0
    auto iter = uintToValueMap.find(value);
877
0
    if (iter != uintToValueMap.end())
878
0
    {
879
0
      return iter->second;
880
0
    }
881
882
0
    return Unknown;
883
0
  }
884
885
  /// =======================
886
  /// GtpV2InformationElement
887
  /// =======================
888
889
  GtpV2InformationElement::Type GtpV2InformationElement::getIEType()
890
0
  {
891
0
    if (m_Data == nullptr)
892
0
    {
893
0
      return GtpV2InformationElement::Type::Unknown;
894
0
    }
895
896
0
    auto ieType = m_Data->recordType;
897
0
    if ((ieType >= 4 && ieType <= 50) || (ieType >= 52 && ieType <= 70) || ieType == 98 || ieType == 101 ||
898
0
        ieType == 102 || ieType == 122 || ieType == 130 || ieType == 161 || ieType > 213)
899
0
    {
900
0
      return GtpV2InformationElement::Type::Unknown;
901
0
    }
902
903
0
    return static_cast<GtpV2InformationElement::Type>(ieType);
904
0
  }
905
906
  uint8_t GtpV2InformationElement::getCRFlag()
907
0
  {
908
0
    if (m_Data == nullptr)
909
0
    {
910
0
      return 0;
911
0
    }
912
913
0
    return m_Data->recordValue[0] >> 4;
914
0
  }
915
916
  uint8_t GtpV2InformationElement::getInstance()
917
0
  {
918
0
    if (m_Data == nullptr)
919
0
    {
920
0
      return 0;
921
0
    }
922
923
0
    return m_Data->recordValue[0] & 0xf;
924
0
  }
925
926
  size_t GtpV2InformationElement::getTotalSize() const
927
0
  {
928
0
    if (m_Data == nullptr)
929
0
    {
930
0
      return 0;
931
0
    }
932
933
0
    return getDataSize() + 2 * sizeof(uint8_t) + sizeof(uint16_t);
934
0
  }
935
936
  size_t GtpV2InformationElement::getDataSize() const
937
0
  {
938
0
    if (m_Data == nullptr)
939
0
    {
940
0
      return 0;
941
0
    }
942
943
0
    return static_cast<size_t>(be16toh(m_Data->recordLen));
944
0
  }
945
946
  /// ==============================
947
  /// GtpV2InformationElementBuilder
948
  /// ==============================
949
950
  GtpV2InformationElementBuilder::GtpV2InformationElementBuilder(GtpV2InformationElement::Type infoElementType,
951
                                                                 const std::bitset<4>& crFlag,
952
                                                                 const std::bitset<4>& instance,
953
                                                                 const std::vector<uint8_t>& infoElementValue)
954
0
      : TLVRecordBuilder(static_cast<uint32_t>(infoElementType), infoElementValue.data(),
955
0
                         static_cast<uint8_t>(infoElementValue.size())),
956
0
        m_CRFlag(crFlag), m_Instance(instance)
957
0
  {}
958
959
  GtpV2InformationElement GtpV2InformationElementBuilder::build() const
960
0
  {
961
0
    if (m_RecType == 0)
962
0
    {
963
0
      GtpV2InformationElement(nullptr);
964
0
    }
965
966
0
    size_t infoElementBaseSize = sizeof(uint8_t) + sizeof(uint16_t);
967
0
    size_t infoElementTotalSize = infoElementBaseSize + sizeof(uint8_t) + m_RecValueLen;
968
0
    auto* recordBuffer = new uint8_t[infoElementTotalSize];
969
0
    recordBuffer[0] = static_cast<uint8_t>(m_RecType);
970
0
    auto infoElementLength = htobe16(m_RecValueLen);
971
0
    memcpy(recordBuffer + sizeof(uint8_t), &infoElementLength, sizeof(uint16_t));
972
0
    auto crFlag = static_cast<uint8_t>(m_CRFlag.to_ulong());
973
0
    auto instance = static_cast<uint8_t>(m_Instance.to_ulong());
974
0
    recordBuffer[infoElementBaseSize] = ((crFlag << 4) & 0xf0) | (instance & 0x0f);
975
0
    if (m_RecValueLen > 0 && m_RecValue != nullptr)
976
0
    {
977
0
      memcpy(recordBuffer + infoElementBaseSize + sizeof(uint8_t), m_RecValue, m_RecValueLen);
978
0
    }
979
980
0
    return GtpV2InformationElement(recordBuffer);
981
0
  }
982
983
  /// ==========
984
  /// GtpV2Layer
985
  /// ==========
986
987
  GtpV2Layer::GtpV2Layer(GtpV2MessageType messageType, uint32_t sequenceNumber, bool setTeid, uint32_t teid,
988
                         bool setMessagePriority, std::bitset<4> messagePriority)
989
0
  {
990
0
    size_t messageLength = sizeof(uint32_t) + (setTeid ? sizeof(uint32_t) : 0);
991
0
    size_t headerLen = sizeof(gtpv2_basic_header) + messageLength;
992
0
    m_DataLen = headerLen;
993
0
    m_Data = new uint8_t[headerLen];
994
0
    memset(m_Data, 0, headerLen);
995
996
0
    auto* hdr = getHeader();
997
0
    hdr->version = 2;
998
0
    hdr->teidPresent = setTeid;
999
0
    hdr->messagePriorityPresent = setMessagePriority;
1000
0
    hdr->messageType = static_cast<uint8_t>(messageType);
1001
0
    hdr->messageLength = htobe16(messageLength);
1002
1003
0
    auto* dataPtr = m_Data + sizeof(gtpv2_basic_header);
1004
0
    if (setTeid)
1005
0
    {
1006
0
      teid = htobe32(teid);
1007
0
      memcpy(dataPtr, &teid, sizeof(uint32_t));
1008
0
      dataPtr += sizeof(uint32_t);
1009
0
    }
1010
1011
0
    sequenceNumber = htobe32(sequenceNumber) >> 8;
1012
0
    memcpy(dataPtr, &sequenceNumber, sizeof(uint32_t));
1013
0
    dataPtr += sizeof(uint32_t) - 1;
1014
1015
0
    if (setMessagePriority)
1016
0
    {
1017
0
      auto messagePriorityNum = static_cast<uint8_t>(messagePriority.to_ulong());
1018
0
      dataPtr[0] = messagePriorityNum << 4;
1019
0
    }
1020
1021
0
    m_Protocol = GTPv2;
1022
0
  }
1023
1024
  bool GtpV2Layer::isDataValid(const uint8_t* data, size_t dataSize)
1025
0
  {
1026
0
    if (!data || dataSize < sizeof(gtpv2_basic_header) + sizeof(uint32_t))
1027
0
    {
1028
0
      return false;
1029
0
    }
1030
1031
0
    auto* header = reinterpret_cast<const gtpv2_basic_header*>(data);
1032
1033
0
    if (header->version != 2)
1034
0
    {
1035
0
      return false;
1036
0
    }
1037
1038
0
    return true;
1039
0
  }
1040
1041
  GtpV2MessageType GtpV2Layer::getMessageType() const
1042
0
  {
1043
0
    return GtpV2MessageType::fromUintValue(getHeader()->messageType);
1044
0
  }
1045
1046
  void GtpV2Layer::setMessageType(const GtpV2MessageType& type)
1047
0
  {
1048
0
    getHeader()->messageType = type;
1049
0
  }
1050
1051
  uint16_t GtpV2Layer::getMessageLength() const
1052
0
  {
1053
0
    return be16toh(getHeader()->messageLength);
1054
0
  }
1055
1056
  bool GtpV2Layer::isPiggybacking() const
1057
0
  {
1058
0
    return getHeader()->piggybacking;
1059
0
  }
1060
1061
  std::pair<bool, uint32_t> GtpV2Layer::getTeid() const
1062
0
  {
1063
0
    if (!getHeader()->teidPresent)
1064
0
    {
1065
0
      return { false, 0 };
1066
0
    }
1067
1068
0
    return { true, be32toh(*reinterpret_cast<uint32_t*>(m_Data + sizeof(gtpv2_basic_header))) };
1069
0
  }
1070
1071
  void GtpV2Layer::setTeid(uint32_t teid)
1072
0
  {
1073
0
    auto* header = getHeader();
1074
1075
0
    auto teidOffset = sizeof(gtpv2_basic_header);
1076
0
    if (!header->teidPresent)
1077
0
    {
1078
0
      if (!extendLayer(static_cast<int>(teidOffset), sizeof(uint32_t)))
1079
0
      {
1080
0
        PCPP_LOG_ERROR("Unable to set TEID: failed to extend the layer");
1081
0
        return;
1082
0
      }
1083
0
      header = getHeader();
1084
0
      header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(uint32_t));
1085
0
    }
1086
1087
0
    reinterpret_cast<uint32_t*>(m_Data + teidOffset)[0] = htobe32(teid);
1088
1089
0
    header->teidPresent = 1;
1090
0
  }
1091
1092
  void GtpV2Layer::unsetTeid()
1093
0
  {
1094
0
    auto* header = getHeader();
1095
1096
0
    if (!header->teidPresent)
1097
0
    {
1098
0
      return;
1099
0
    }
1100
1101
0
    auto teidOffset = sizeof(gtpv2_basic_header);
1102
0
    if (!shortenLayer(static_cast<int>(teidOffset), sizeof(uint32_t)))
1103
0
    {
1104
0
      PCPP_LOG_ERROR("Unable to unset TEID: failed to shorten the layer");
1105
0
      return;
1106
0
    }
1107
1108
0
    header = getHeader();
1109
0
    header->messageLength = htobe16(be16toh(header->messageLength) - sizeof(uint32_t));
1110
0
    header->teidPresent = 0;
1111
0
  }
1112
1113
  uint32_t GtpV2Layer::getSequenceNumber() const
1114
0
  {
1115
0
    auto* sequencePos = m_Data + sizeof(gtpv2_basic_header);
1116
0
    if (getHeader()->teidPresent)
1117
0
    {
1118
0
      sequencePos += sizeof(uint32_t);
1119
0
    }
1120
1121
0
    return be32toh(*reinterpret_cast<uint32_t*>(sequencePos)) >> 8;
1122
0
  }
1123
1124
  void GtpV2Layer::setSequenceNumber(uint32_t sequenceNumber)
1125
0
  {
1126
0
    auto* sequencePos = m_Data + sizeof(gtpv2_basic_header);
1127
0
    if (getHeader()->teidPresent)
1128
0
    {
1129
0
      sequencePos += sizeof(uint32_t);
1130
0
    }
1131
1132
0
    sequenceNumber = htobe32(sequenceNumber) >> 8;
1133
0
    memcpy(sequencePos, &sequenceNumber, sizeof(uint32_t) - 1);
1134
0
  }
1135
1136
  std::pair<bool, uint8_t> GtpV2Layer::getMessagePriority() const
1137
0
  {
1138
0
    auto* header = getHeader();
1139
1140
0
    if (!header->messagePriorityPresent)
1141
0
    {
1142
0
      return { false, 0 };
1143
0
    }
1144
1145
0
    auto* mpPos = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t) - 1;
1146
0
    if (header->teidPresent)
1147
0
    {
1148
0
      mpPos += sizeof(uint32_t);
1149
0
    }
1150
1151
0
    return { true, mpPos[0] >> 4 };
1152
0
  }
1153
1154
  void GtpV2Layer::setMessagePriority(const std::bitset<4>& messagePriority)
1155
0
  {
1156
0
    auto* header = getHeader();
1157
1158
0
    header->messagePriorityPresent = 1;
1159
1160
0
    auto* mpPos = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t) - 1;
1161
0
    if (header->teidPresent)
1162
0
    {
1163
0
      mpPos += sizeof(uint32_t);
1164
0
    }
1165
1166
0
    auto messagePriorityNum = static_cast<uint8_t>(messagePriority.to_ulong());
1167
0
    mpPos[0] = messagePriorityNum << 4;
1168
0
  }
1169
1170
  void GtpV2Layer::unsetMessagePriority()
1171
0
  {
1172
0
    auto* header = getHeader();
1173
1174
0
    header->messagePriorityPresent = 0;
1175
1176
0
    auto* mpPos = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t) - 1;
1177
0
    if (header->teidPresent)
1178
0
    {
1179
0
      mpPos += sizeof(uint32_t);
1180
0
    }
1181
1182
0
    mpPos[0] = 0;
1183
0
  }
1184
1185
  GtpV2InformationElement GtpV2Layer::getFirstInformationElement() const
1186
0
  {
1187
0
    auto* basePtr = getIEBasePtr();
1188
0
    return m_IEReader.getFirstTLVRecord(basePtr, m_Data + getHeaderLen() - basePtr);
1189
0
  }
1190
1191
  GtpV2InformationElement GtpV2Layer::getNextInformationElement(GtpV2InformationElement infoElement) const
1192
0
  {
1193
0
    auto* basePtr = getIEBasePtr();
1194
0
    return m_IEReader.getNextTLVRecord(infoElement, basePtr, m_Data + getHeaderLen() - basePtr);
1195
0
  }
1196
1197
  GtpV2InformationElement GtpV2Layer::getInformationElement(GtpV2InformationElement::Type infoElementType) const
1198
0
  {
1199
0
    auto* basePtr = getIEBasePtr();
1200
0
    return m_IEReader.getTLVRecord(static_cast<uint32_t>(infoElementType), basePtr,
1201
0
                                   m_Data + getHeaderLen() - basePtr);
1202
0
  }
1203
1204
  size_t GtpV2Layer::getInformationElementCount() const
1205
0
  {
1206
0
    auto* basePtr = getIEBasePtr();
1207
0
    return m_IEReader.getTLVRecordCount(basePtr, m_Data + getHeaderLen() - basePtr);
1208
0
  }
1209
1210
  GtpV2InformationElement GtpV2Layer::addInformationElement(const GtpV2InformationElementBuilder& infoElementBuilder)
1211
0
  {
1212
0
    return addInformationElementAt(infoElementBuilder, static_cast<int>(getHeaderLen()));
1213
0
  }
1214
1215
  GtpV2InformationElement GtpV2Layer::addInformationElementAfter(
1216
      const GtpV2InformationElementBuilder& infoElementBuilder, GtpV2InformationElement::Type infoElementType)
1217
0
  {
1218
0
    auto prevInfoElement = getInformationElement(infoElementType);
1219
1220
0
    if (prevInfoElement.isNull())
1221
0
    {
1222
0
      PCPP_LOG_ERROR("Information element type " << static_cast<int>(infoElementType)
1223
0
                                                 << " doesn't exist in layer");
1224
0
      return GtpV2InformationElement(nullptr);
1225
0
    }
1226
0
    auto offset = prevInfoElement.getRecordBasePtr() + prevInfoElement.getTotalSize() - m_Data;
1227
0
    return addInformationElementAt(infoElementBuilder, offset);
1228
0
  }
1229
1230
  bool GtpV2Layer::removeInformationElement(GtpV2InformationElement::Type infoElementType)
1231
0
  {
1232
0
    auto infoElementToRemove = getInformationElement(infoElementType);
1233
0
    if (infoElementToRemove.isNull())
1234
0
    {
1235
0
      return false;
1236
0
    }
1237
1238
0
    int offset = infoElementToRemove.getRecordBasePtr() - m_Data;
1239
1240
0
    auto infoElementSize = infoElementToRemove.getTotalSize();
1241
0
    if (!shortenLayer(offset, infoElementSize))
1242
0
    {
1243
0
      return false;
1244
0
    }
1245
1246
0
    getHeader()->messageLength = htobe16(be16toh(getHeader()->messageLength) - infoElementSize);
1247
0
    m_IEReader.changeTLVRecordCount(-1);
1248
0
    return true;
1249
0
  }
1250
1251
  bool GtpV2Layer::removeAllInformationElements()
1252
0
  {
1253
0
    auto firstInfoElement = getFirstInformationElement();
1254
0
    if (firstInfoElement.isNull())
1255
0
    {
1256
0
      return true;
1257
0
    }
1258
1259
0
    auto offset = firstInfoElement.getRecordBasePtr() - m_Data;
1260
1261
0
    if (!shortenLayer(offset, getHeaderLen() - offset))
1262
0
    {
1263
0
      return false;
1264
0
    }
1265
1266
0
    m_IEReader.changeTLVRecordCount(static_cast<int>(0 - getInformationElementCount()));
1267
0
    return true;
1268
0
  }
1269
1270
  GtpV2InformationElement GtpV2Layer::addInformationElementAt(
1271
      const GtpV2InformationElementBuilder& infoElementBuilder, int offset)
1272
0
  {
1273
0
    auto newInfoElement = infoElementBuilder.build();
1274
1275
0
    if (newInfoElement.isNull())
1276
0
    {
1277
0
      PCPP_LOG_ERROR("Cannot build new information element");
1278
0
      return newInfoElement;
1279
0
    }
1280
1281
0
    auto sizeToExtend = newInfoElement.getTotalSize();
1282
1283
0
    if (!extendLayer(offset, sizeToExtend))
1284
0
    {
1285
0
      PCPP_LOG_ERROR("Could not extend GtpV2Layer in [" << sizeToExtend << "] bytes");
1286
0
      newInfoElement.purgeRecordData();
1287
0
      return GtpV2InformationElement(nullptr);
1288
0
    }
1289
1290
0
    memcpy(m_Data + offset, newInfoElement.getRecordBasePtr(), newInfoElement.getTotalSize());
1291
1292
0
    auto newMessageLength = getMessageLength() + newInfoElement.getTotalSize();
1293
1294
0
    newInfoElement.purgeRecordData();
1295
1296
0
    m_IEReader.changeTLVRecordCount(1);
1297
1298
0
    getHeader()->messageLength = htobe16(newMessageLength);
1299
1300
0
    uint8_t* newInfoElementPtr = m_Data + offset;
1301
1302
0
    return GtpV2InformationElement(newInfoElementPtr);
1303
0
  }
1304
1305
  void GtpV2Layer::parseNextLayer()
1306
0
  {
1307
0
    auto headerLen = getHeaderLen();
1308
0
    if (m_DataLen <= headerLen)
1309
0
    {
1310
0
      return;
1311
0
    }
1312
1313
0
    auto* nextLayerData = m_Data + headerLen;
1314
0
    auto nextLayerDataLen = m_DataLen - headerLen;
1315
1316
0
    if (getHeader()->piggybacking && GtpV2Layer::isDataValid(nextLayerData, nextLayerDataLen))
1317
0
    {
1318
0
      m_NextLayer = new GtpV2Layer(nextLayerData, nextLayerDataLen, this, m_Packet);
1319
0
    }
1320
0
    else
1321
0
    {
1322
0
      m_NextLayer = new PayloadLayer(nextLayerData, nextLayerDataLen, this, m_Packet);
1323
0
    }
1324
0
  }
1325
1326
  size_t GtpV2Layer::getHeaderLen() const
1327
0
  {
1328
0
    auto messageLength = be16toh(getHeader()->messageLength) + sizeof(gtpv2_basic_header);
1329
0
    if (messageLength > m_DataLen)
1330
0
    {
1331
0
      return m_DataLen;
1332
0
    }
1333
1334
0
    return messageLength;
1335
0
  }
1336
1337
  void GtpV2Layer::computeCalculateFields()
1338
0
  {
1339
0
    if (m_NextLayer == nullptr)
1340
0
    {
1341
0
      return;
1342
0
    }
1343
1344
0
    if (m_NextLayer->getProtocol() == GTPv2)
1345
0
    {
1346
0
      getHeader()->piggybacking = 1;
1347
0
    }
1348
0
    else
1349
0
    {
1350
0
      getHeader()->piggybacking = 0;
1351
0
    }
1352
0
  }
1353
1354
  std::string GtpV2Layer::toString() const
1355
0
  {
1356
0
    return "GTPv2 Layer, " + getMessageType().toString() + " message";
1357
0
  }
1358
1359
  uint8_t* GtpV2Layer::getIEBasePtr() const
1360
0
  {
1361
0
    auto* basePtr = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t);
1362
0
    if (getHeader()->teidPresent)
1363
0
    {
1364
0
      basePtr += sizeof(uint32_t);
1365
0
    }
1366
1367
0
    return basePtr;
1368
0
  }
1369
1370
}  // namespace pcpp