Coverage Report

Created: 2026-02-14 06:19

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
30.1k
#define PCPP_GTP_V1_GPDU_MESSAGE_TYPE 0xff
16
17
  /// ==================
18
  /// GtpExtension class
19
  /// ==================
20
21
  GtpV1Layer::GtpExtension::GtpExtension()
22
11.2k
  {
23
11.2k
    m_Data = nullptr;
24
11.2k
    m_DataLen = 0;
25
11.2k
    m_ExtType = 0;
26
11.2k
  }
27
28
  GtpV1Layer::GtpExtension::GtpExtension(uint8_t* data, size_t dataLen, uint8_t type)
29
1.85k
  {
30
1.85k
    m_Data = data;
31
1.85k
    m_DataLen = dataLen;
32
1.85k
    m_ExtType = type;
33
1.85k
  }
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
1.72k
  {
44
1.72k
    m_Data = other.m_Data;
45
1.72k
    m_DataLen = other.m_DataLen;
46
1.72k
    m_ExtType = other.m_ExtType;
47
1.72k
    return *this;
48
1.72k
  }
49
50
  bool GtpV1Layer::GtpExtension::isNull() const
51
9.83k
  {
52
9.83k
    return m_Data == nullptr;
53
9.83k
  }
54
55
  uint8_t GtpV1Layer::GtpExtension::getExtensionType() const
56
1.62k
  {
57
1.62k
    return m_ExtType;
58
1.62k
  }
59
60
  size_t GtpV1Layer::GtpExtension::getTotalLength() const
61
10.3k
  {
62
10.3k
    if (m_Data == nullptr)
63
3.05k
    {
64
3.05k
      return 0;
65
3.05k
    }
66
67
7.26k
    size_t len = (size_t)(m_Data[0] * 4);
68
7.26k
    if (len <= m_DataLen)
69
6.41k
    {
70
6.41k
      return len;
71
6.41k
    }
72
73
859
    return m_DataLen;
74
7.26k
  }
75
76
  size_t GtpV1Layer::GtpExtension::getContentLength() const
77
3.42k
  {
78
3.42k
    size_t res = getTotalLength();
79
80
3.42k
    if (res >= 2 * sizeof(uint8_t))
81
1.88k
    {
82
1.88k
      return (size_t)(res - 2 * sizeof(uint8_t));
83
1.88k
    }
84
85
1.54k
    return 0;
86
3.42k
  }
87
88
  uint8_t* GtpV1Layer::GtpExtension::getContent() const
89
1.62k
  {
90
1.62k
    if (m_Data == nullptr || getContentLength() == 0)
91
1.53k
    {
92
1.53k
      return nullptr;
93
1.53k
    }
94
95
92
    return m_Data + sizeof(uint8_t);
96
1.62k
  }
97
98
  uint8_t GtpV1Layer::GtpExtension::getNextExtensionHeaderType() const
99
3.34k
  {
100
3.34k
    if (m_Data == nullptr || getTotalLength() < 4)
101
1.64k
    {
102
1.64k
      return 0;
103
1.64k
    }
104
105
1.70k
    uint8_t res = *(uint8_t*)(m_Data + sizeof(uint8_t) + getContentLength());
106
107
1.70k
    return res;
108
3.34k
  }
109
110
  GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::getNextExtension() const
111
3.34k
  {
112
3.34k
    size_t totalLength = getTotalLength();
113
3.34k
    uint8_t nextExtType = getNextExtensionHeaderType();
114
3.34k
    if (nextExtType > 0 && m_DataLen > totalLength + sizeof(uint8_t))
115
1.03k
    {
116
1.03k
      return { m_Data + totalLength, m_DataLen - totalLength, nextExtType };
117
1.03k
    }
118
2.31k
    else
119
2.31k
    {
120
2.31k
      return {};
121
2.31k
    }
122
3.34k
  }
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
23.6k
  {
203
23.6k
    if (data != nullptr && dataSize >= sizeof(gtpv1_header) && (data[0] & 0xE0) == 0x20)
204
11.0k
    {
205
11.0k
      return true;
206
11.0k
    }
207
208
12.6k
    return false;
209
23.6k
  }
210
211
  GtpV1Layer::gtpv1_header_extra* GtpV1Layer::getHeaderExtra() const
212
22.4k
  {
213
22.4k
    if (m_Data != nullptr && m_DataLen >= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra))
214
22.4k
    {
215
22.4k
      return (gtpv1_header_extra*)(m_Data + sizeof(gtpv1_header));
216
22.4k
    }
217
218
33
    return nullptr;
219
22.4k
  }
220
221
  bool GtpV1Layer::getSequenceNumber(uint16_t& seqNumber) const
222
1.62k
  {
223
1.62k
    gtpv1_header* header = getHeader();
224
1.62k
    gtpv1_header_extra* headerExtra = getHeaderExtra();
225
1.62k
    if (header != nullptr && headerExtra != nullptr && header->sequenceNumberFlag == 1)
226
1.07k
    {
227
1.07k
      seqNumber = be16toh(headerExtra->sequenceNumber);
228
1.07k
      return true;
229
1.07k
    }
230
231
550
    return false;
232
1.62k
  }
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
1.62k
  {
275
1.62k
    gtpv1_header* header = getHeader();
276
1.62k
    gtpv1_header_extra* headerExtra = getHeaderExtra();
277
1.62k
    if (header != nullptr && headerExtra != nullptr && header->npduNumberFlag == 1)
278
194
    {
279
194
      npduNum = headerExtra->npduNumber;
280
194
      return true;
281
194
    }
282
283
1.43k
    return false;
284
1.62k
  }
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
9.74k
  {
327
9.74k
    gtpv1_header* header = getHeader();
328
9.74k
    gtpv1_header_extra* headerExtra = getHeaderExtra();
329
9.74k
    if (header != nullptr && headerExtra != nullptr && header->extensionHeaderFlag == 1)
330
1.25k
    {
331
1.25k
      nextExtType = headerExtra->nextExtensionHeader;
332
1.25k
      return true;
333
1.25k
    }
334
335
8.48k
    return false;
336
9.74k
  }
337
338
  GtpV1Layer::GtpExtension GtpV1Layer::getNextExtension() const
339
9.74k
  {
340
9.74k
    uint8_t nextExtType = 0;
341
9.74k
    bool nextExtExists = getNextExtensionHeaderType(nextExtType);
342
9.74k
    if (!nextExtExists || nextExtType == 0 || m_DataLen <= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra))
343
8.92k
    {
344
8.92k
      return {};
345
8.92k
    }
346
347
818
    return { m_Data + sizeof(gtpv1_header) + sizeof(gtpv1_header_extra),
348
818
           m_DataLen - sizeof(gtpv1_header) - sizeof(gtpv1_header_extra), nextExtType };
349
9.74k
  }
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
1.62k
  {
431
1.62k
    gtpv1_header* header = getHeader();
432
433
1.62k
    if (header == nullptr)
434
0
    {
435
0
      return GtpV1_MessageTypeUnknown;
436
0
    }
437
438
1.62k
    return (GtpV1MessageType)header->messageType;
439
1.62k
  }
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
2.62k
  {
522
2.62k
    gtpv1_header* header = getHeader();
523
524
2.62k
    if (header == nullptr)
525
0
    {
526
0
      return GTPv1MsgTypeToStringMap.find(0)->second;
527
0
    }
528
529
2.62k
    auto iter = GTPv1MsgTypeToStringMap.find(header->messageType);
530
2.62k
    if (iter != GTPv1MsgTypeToStringMap.end())
531
1.48k
    {
532
1.48k
      return iter->second;
533
1.48k
    }
534
1.14k
    else
535
1.14k
    {
536
1.14k
      return GTPv1MsgTypeToStringMap.find(0)->second;
537
1.14k
    }
538
2.62k
  }
539
540
  bool GtpV1Layer::isGTPUMessage() const
541
1.62k
  {
542
1.62k
    gtpv1_header* header = getHeader();
543
1.62k
    if (header == nullptr)
544
0
    {
545
0
      return false;
546
0
    }
547
548
1.62k
    return header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
549
1.62k
  }
550
551
  bool GtpV1Layer::isGTPCMessage() const
552
1.62k
  {
553
1.62k
    gtpv1_header* header = getHeader();
554
1.62k
    if (header == nullptr)
555
0
    {
556
0
      return false;
557
0
    }
558
559
1.62k
    return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
560
1.62k
  }
561
562
  void GtpV1Layer::parseNextLayer()
563
11.0k
  {
564
11.0k
    size_t headerLen = getHeaderLen();
565
11.0k
    if (headerLen < sizeof(gtpv1_header))
566
0
    {
567
      // do nothing
568
0
      return;
569
0
    }
570
571
11.0k
    gtpv1_header* header = getHeader();
572
11.0k
    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
573
2.62k
    {
574
      // this is a GTP-C message, hence it is the last layer
575
2.62k
      return;
576
2.62k
    }
577
578
8.38k
    if (m_DataLen <= headerLen)
579
165
    {
580
      // no data beyond headerLen, nothing to parse further
581
165
      return;
582
165
    }
583
584
    // GTP-U message, try to parse the next layer
585
586
8.21k
    auto* payload = static_cast<uint8_t*>(m_Data + headerLen);
587
8.21k
    size_t payloadLen = m_DataLen - headerLen;
588
589
8.21k
    uint8_t subProto = *payload;
590
8.21k
    if (subProto >= 0x45 && subProto <= 0x4e)
591
6.77k
    {
592
6.77k
      tryConstructNextLayerWithFallback<IPv4Layer, PayloadLayer>(payload, payloadLen);
593
6.77k
    }
594
1.44k
    else if ((subProto & 0xf0) == 0x60)
595
646
    {
596
646
      tryConstructNextLayerWithFallback<IPv6Layer, PayloadLayer>(payload, payloadLen);
597
646
    }
598
797
    else
599
797
    {
600
797
      constructNextLayer<PayloadLayer>(payload, payloadLen);
601
797
    }
602
8.21k
  }
603
604
  size_t GtpV1Layer::getHeaderLen() const
605
12.6k
  {
606
12.6k
    gtpv1_header* header = getHeader();
607
12.6k
    if (header == nullptr)
608
0
    {
609
0
      return 0;
610
0
    }
611
612
12.6k
    size_t res = sizeof(gtpv1_header);
613
614
12.6k
    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
615
3.12k
    {
616
3.12k
      size_t msgLen = be16toh(header->messageLength);
617
3.12k
      res += (msgLen > m_DataLen - sizeof(gtpv1_header) ? m_DataLen - sizeof(gtpv1_header) : msgLen);
618
3.12k
    }
619
9.50k
    else
620
9.50k
    {
621
9.50k
      gtpv1_header_extra* headerExtra = getHeaderExtra();
622
9.50k
      if (headerExtra != nullptr &&
623
9.49k
          (header->extensionHeaderFlag == 1 || header->sequenceNumberFlag == 1 || header->npduNumberFlag == 1))
624
8.11k
      {
625
8.11k
        res += sizeof(gtpv1_header_extra);
626
8.11k
        GtpExtension nextExt = getNextExtension();
627
9.83k
        while (!nextExt.isNull())
628
1.72k
        {
629
1.72k
          res += nextExt.getTotalLength();
630
1.72k
          nextExt = nextExt.getNextExtension();
631
1.72k
        }
632
8.11k
      }
633
9.50k
    }
634
635
12.6k
    return res;
636
12.6k
  }
637
638
  std::string GtpV1Layer::toString() const
639
3.25k
  {
640
3.25k
    std::string res = "GTP v1 Layer";
641
642
3.25k
    gtpv1_header* header = getHeader();
643
3.25k
    if (header != nullptr)
644
3.25k
    {
645
3.25k
      std::stringstream teidStream;
646
3.25k
      teidStream << be32toh(header->teid);
647
648
3.25k
      std::string gtpu_gtpc;
649
3.25k
      if (header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
650
2.24k
      {
651
2.24k
        gtpu_gtpc = "GTP-U message";
652
2.24k
      }
653
1.00k
      else
654
1.00k
      {
655
1.00k
        gtpu_gtpc = "GTP-C message: " + getMessageTypeAsString();
656
1.00k
      }
657
658
3.25k
      res += ", " + gtpu_gtpc + ", TEID: " + teidStream.str();
659
3.25k
    }
660
661
3.25k
    return res;
662
3.25k
  }
663
664
  void GtpV1Layer::computeCalculateFields()
665
1.62k
  {
666
1.62k
    gtpv1_header* hdr = getHeader();
667
1.62k
    if (hdr == nullptr)
668
0
    {
669
0
      return;
670
0
    }
671
672
1.62k
    hdr->messageLength = htobe16(m_DataLen - sizeof(gtpv1_header));
673
1.62k
  }
674
675
  /// ================
676
  /// GtpV2MessageType
677
  /// ================
678
679
  struct GtpV2MessageTypeHash
680
  {
681
    size_t operator()(const GtpV2MessageType& messageType) const
682
356
    {
683
356
      return static_cast<uint8_t>(messageType);
684
356
    }
685
  };
686
687
  static const std::unordered_map<GtpV2MessageType, std::string, GtpV2MessageTypeHash> messageTypeMap = {
688
    { GtpV2MessageType::EchoRequest,                      "Echo Request"                         },
689
    { GtpV2MessageType::EchoResponse,                     "Echo Response"                        },
690
    { GtpV2MessageType::VersionNotSupported,              "Version Not Supported"                },
691
    { GtpV2MessageType::CreateSessionRequest,             "Create Session Request"               },
692
    { GtpV2MessageType::CreateSessionResponse,            "Create Session Response"              },
693
    { GtpV2MessageType::ModifyBearerRequest,              "Modify Bearer Request"                },
694
    { GtpV2MessageType::ModifyBearerResponse,             "Modify Bearer Response"               },
695
    { GtpV2MessageType::DeleteSessionRequest,             "Delete Session Request"               },
696
    { GtpV2MessageType::DeleteSessionResponse,            "Delete Session Response"              },
697
    { GtpV2MessageType::ChangeNotificationRequest,        "Change Notification Request"          },
698
    { GtpV2MessageType::ChangeNotificationResponse,       "Change Notification Response"         },
699
    { GtpV2MessageType::RemoteUEReportNotifications,      "Remote UE Report Notifications"       },
700
    { GtpV2MessageType::RemoteUEReportAcknowledge,        "Remote UE Report Acknowledge"         },
701
    { GtpV2MessageType::ModifyBearerCommand,              "Modify Bearer Command"                },
702
    { GtpV2MessageType::ModifyBearerFailure,              "Modify Bearer Failure"                },
703
    { GtpV2MessageType::DeleteBearerCommand,              "Delete Bearer Command"                },
704
    { GtpV2MessageType::DeleteBearerFailure,              "Delete Bearer Failure"                },
705
    { GtpV2MessageType::BearerResourceCommand,            "Bearer Resource Command"              },
706
    { GtpV2MessageType::BearerResourceFailure,            "Bearer Resource Failure"              },
707
    { GtpV2MessageType::DownlinkDataNotificationFailure,  "Downlink Data Notification Failure"   },
708
    { GtpV2MessageType::TraceSessionActivation,           "Trace Session Activation"             },
709
    { GtpV2MessageType::TraceSessionDeactivation,         "Trace Session Deactivation"           },
710
    { GtpV2MessageType::StopPagingIndication,             "Stop Paging Indication"               },
711
    { GtpV2MessageType::CreateBearerRequest,              "Create Bearer Request"                },
712
    { GtpV2MessageType::CreateBearerResponse,             "Create Bearer Response"               },
713
    { GtpV2MessageType::UpdateBearerRequest,              "Update Bearer Request"                },
714
    { GtpV2MessageType::UpdateBearerResponse,             "Update Bearer Response"               },
715
    { GtpV2MessageType::DeleteBearerRequest,              "Delete Bearer Request"                },
716
    { GtpV2MessageType::DeleteBearerResponse,             "Delete Bearer Response"               },
717
    { GtpV2MessageType::DeletePDNRequest,                 "Delete PDN Request"                   },
718
    { GtpV2MessageType::DeletePDNResponse,                "Delete PDN Response"                  },
719
    { GtpV2MessageType::PGWDownlinkNotification,          "PGW Downlink Notification"            },
720
    { GtpV2MessageType::PGWDownlinkAcknowledge,           "PGW Downlink Acknowledge"             },
721
    { GtpV2MessageType::IdentificationRequest,            "Identification Request"               },
722
    { GtpV2MessageType::IdentificationResponse,           "Identification Response"              },
723
    { GtpV2MessageType::ContextRequest,                   "Context Request"                      },
724
    { GtpV2MessageType::ContextResponse,                  "Context Response"                     },
725
    { GtpV2MessageType::ContextAcknowledge,               "Context Acknowledge"                  },
726
    { GtpV2MessageType::ForwardRelocationRequest,         "Forward Relocation Request"           },
727
    { GtpV2MessageType::ForwardRelocationResponse,        "Forward Relocation Response"          },
728
    { GtpV2MessageType::ForwardRelocationNotification,    "Forward Relocation Notification"      },
729
    { GtpV2MessageType::ForwardRelocationAcknowledge,     "Forward Relocation Acknowledge"       },
730
    { GtpV2MessageType::ForwardAccessNotification,        "Forward Access Notification"          },
731
    { GtpV2MessageType::ForwardAccessAcknowledge,         "Forward Access Acknowledge"           },
732
    { GtpV2MessageType::RelocationCancelRequest,          "Relocation Cancel Request"            },
733
    { GtpV2MessageType::RelocationCancelResponse,         "Relocation Cancel Response"           },
734
    { GtpV2MessageType::ConfigurationTransferTunnel,      "Configuration Transfer Tunnel"        },
735
    { GtpV2MessageType::DetachNotification,               "Detach Notification"                  },
736
    { GtpV2MessageType::DetachAcknowledge,                "Detach Acknowledge"                   },
737
    { GtpV2MessageType::CSPaging,                         "CS Paging"                            },
738
    { GtpV2MessageType::RANInformationRelay,              "RAN Information Relay"                },
739
    { GtpV2MessageType::AlertMMENotification,             "Alert MME Notification"               },
740
    { GtpV2MessageType::AlertMMEAcknowledge,              "Alert MME Acknowledge"                },
741
    { GtpV2MessageType::UEActivityNotification,           "UE Activity Notification"             },
742
    { GtpV2MessageType::UEActivityAcknowledge,            "UE Activity Acknowledge"              },
743
    { GtpV2MessageType::ISRStatus,                        "ISR Status"                           },
744
    { GtpV2MessageType::CreateForwardingRequest,          "Create Forwarding Request"            },
745
    { GtpV2MessageType::CreateForwardingResponse,         "Create Forwarding Response"           },
746
    { GtpV2MessageType::SuspendNotification,              "Suspend Notification"                 },
747
    { GtpV2MessageType::SuspendAcknowledge,               "Suspend Acknowledge"                  },
748
    { GtpV2MessageType::ResumeNotification,               "Resume Notification"                  },
749
    { GtpV2MessageType::ResumeAcknowledge,                "Resume Acknowledge"                   },
750
    { GtpV2MessageType::CreateIndirectDataTunnelRequest,  "Create Indirect Data Tunnel Request"  },
751
    { GtpV2MessageType::CreateIndirectDataTunnelResponse, "Create Indirect Data Tunnel Response" },
752
    { GtpV2MessageType::DeleteIndirectDataTunnelRequest,  "Delete Indirect Data Tunnel Request"  },
753
    { GtpV2MessageType::DeleteIndirectDataTunnelResponse, "Delete Indirect Data Tunnel Response" },
754
    { GtpV2MessageType::ReleaseAccessBearersRequest,      "Release Access Bearers Request"       },
755
    { GtpV2MessageType::ReleaseAccessBearersResponse,     "Release Access Bearers Response"      },
756
    { GtpV2MessageType::DownlinkDataNotification,         "Downlink Data Notification"           },
757
    { GtpV2MessageType::DownlinkDataAcknowledge,          "Downlink Data Acknowledge"            },
758
    { GtpV2MessageType::PGWRestartNotification,           "PGW Restart Notification"             },
759
    { GtpV2MessageType::PGWRestartAcknowledge,            "PGW Restart Acknowledge"              },
760
    { GtpV2MessageType::UpdatePDNConnectionRequest,       "Update PDN Connection Request"        },
761
    { GtpV2MessageType::UpdatePDNConnectionResponse,      "Update PDN Connection Response"       },
762
    { GtpV2MessageType::ModifyAccessBearersRequest,       "Modify Access Bearers Request"        },
763
    { GtpV2MessageType::ModifyAccessBearersResponse,      "Modify Access Bearers Response"       },
764
    { GtpV2MessageType::MMBSSessionStartRequest,          "MMBS Session Start Request"           },
765
    { GtpV2MessageType::MMBSSessionStartResponse,         "MMBS Session Start Response"          },
766
    { GtpV2MessageType::MMBSSessionUpdateRequest,         "MMBS Session Update Request"          },
767
    { GtpV2MessageType::MMBSSessionUpdateResponse,        "MMBS Session Update Response"         },
768
    { GtpV2MessageType::MMBSSessionStopRequest,           "MMBS Session Stop Request"            },
769
    { GtpV2MessageType::MMBSSessionStopResponse,          "MMBS Session Stop Response"           }
770
  };
771
772
  std::string GtpV2MessageType::toString() const
773
192
  {
774
192
    auto iter = messageTypeMap.find(m_Value);
775
192
    if (iter != messageTypeMap.end())
776
40
    {
777
40
      return iter->second;
778
40
    }
779
780
152
    return "Unknown GTPv2 Message Type";
781
192
  }
782
783
  // clang-format off
784
  static const std::unordered_map<uint8_t, GtpV2MessageType> uintToValueMap = {
785
    { static_cast<uint8_t>(GtpV2MessageType::EchoRequest),                      GtpV2MessageType::EchoRequest                      },
786
    { static_cast<uint8_t>(GtpV2MessageType::EchoResponse),                     GtpV2MessageType::EchoResponse                     },
787
    { static_cast<uint8_t>(GtpV2MessageType::VersionNotSupported),              GtpV2MessageType::VersionNotSupported              },
788
    { static_cast<uint8_t>(GtpV2MessageType::CreateSessionRequest),             GtpV2MessageType::CreateSessionRequest             },
789
    { static_cast<uint8_t>(GtpV2MessageType::CreateSessionResponse),            GtpV2MessageType::CreateSessionResponse            },
790
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerRequest),              GtpV2MessageType::ModifyBearerRequest              },
791
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerResponse),             GtpV2MessageType::ModifyBearerResponse             },
792
    { static_cast<uint8_t>(GtpV2MessageType::DeleteSessionRequest),             GtpV2MessageType::DeleteSessionRequest             },
793
    { static_cast<uint8_t>(GtpV2MessageType::DeleteSessionResponse),            GtpV2MessageType::DeleteSessionResponse            },
794
    { static_cast<uint8_t>(GtpV2MessageType::ChangeNotificationRequest),        GtpV2MessageType::ChangeNotificationRequest        },
795
    { static_cast<uint8_t>(GtpV2MessageType::ChangeNotificationResponse),       GtpV2MessageType::ChangeNotificationResponse       },
796
    { static_cast<uint8_t>(GtpV2MessageType::RemoteUEReportNotifications),      GtpV2MessageType::RemoteUEReportNotifications      },
797
    { static_cast<uint8_t>(GtpV2MessageType::RemoteUEReportAcknowledge),        GtpV2MessageType::RemoteUEReportAcknowledge        },
798
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerCommand),              GtpV2MessageType::ModifyBearerCommand              },
799
    { static_cast<uint8_t>(GtpV2MessageType::ModifyBearerFailure),              GtpV2MessageType::ModifyBearerFailure              },
800
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerCommand),              GtpV2MessageType::DeleteBearerCommand              },
801
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerFailure),              GtpV2MessageType::DeleteBearerFailure              },
802
    { static_cast<uint8_t>(GtpV2MessageType::BearerResourceCommand),            GtpV2MessageType::BearerResourceCommand            },
803
    { static_cast<uint8_t>(GtpV2MessageType::BearerResourceFailure),            GtpV2MessageType::BearerResourceFailure            },
804
    { static_cast<uint8_t>(GtpV2MessageType::DownlinkDataNotificationFailure),  GtpV2MessageType::DownlinkDataNotificationFailure  },
805
    { static_cast<uint8_t>(GtpV2MessageType::TraceSessionActivation),           GtpV2MessageType::TraceSessionActivation           },
806
    { static_cast<uint8_t>(GtpV2MessageType::TraceSessionDeactivation),         GtpV2MessageType::TraceSessionDeactivation         },
807
    { static_cast<uint8_t>(GtpV2MessageType::StopPagingIndication),             GtpV2MessageType::StopPagingIndication             },
808
    { static_cast<uint8_t>(GtpV2MessageType::CreateBearerRequest),              GtpV2MessageType::CreateBearerRequest              },
809
    { static_cast<uint8_t>(GtpV2MessageType::CreateBearerResponse),             GtpV2MessageType::CreateBearerResponse             },
810
    { static_cast<uint8_t>(GtpV2MessageType::UpdateBearerRequest),              GtpV2MessageType::UpdateBearerRequest              },
811
    { static_cast<uint8_t>(GtpV2MessageType::UpdateBearerResponse),             GtpV2MessageType::UpdateBearerResponse             },
812
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerRequest),              GtpV2MessageType::DeleteBearerRequest              },
813
    { static_cast<uint8_t>(GtpV2MessageType::DeleteBearerResponse),             GtpV2MessageType::DeleteBearerResponse             },
814
    { static_cast<uint8_t>(GtpV2MessageType::DeletePDNRequest),                 GtpV2MessageType::DeletePDNRequest                 },
815
    { static_cast<uint8_t>(GtpV2MessageType::DeletePDNResponse),                GtpV2MessageType::DeletePDNResponse                },
816
    { static_cast<uint8_t>(GtpV2MessageType::PGWDownlinkNotification),          GtpV2MessageType::PGWDownlinkNotification          },
817
    { static_cast<uint8_t>(GtpV2MessageType::PGWDownlinkAcknowledge),           GtpV2MessageType::PGWDownlinkAcknowledge           },
818
    { static_cast<uint8_t>(GtpV2MessageType::IdentificationRequest),            GtpV2MessageType::IdentificationRequest            },
819
    { static_cast<uint8_t>(GtpV2MessageType::IdentificationResponse),           GtpV2MessageType::IdentificationResponse           },
820
    { static_cast<uint8_t>(GtpV2MessageType::ContextRequest),                   GtpV2MessageType::ContextRequest                   },
821
    { static_cast<uint8_t>(GtpV2MessageType::ContextResponse),                  GtpV2MessageType::ContextResponse                  },
822
    { static_cast<uint8_t>(GtpV2MessageType::ContextAcknowledge),               GtpV2MessageType::ContextAcknowledge               },
823
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationRequest),         GtpV2MessageType::ForwardRelocationRequest         },
824
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationResponse),        GtpV2MessageType::ForwardRelocationResponse        },
825
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationNotification),    GtpV2MessageType::ForwardRelocationNotification    },
826
    { static_cast<uint8_t>(GtpV2MessageType::ForwardRelocationAcknowledge),     GtpV2MessageType::ForwardRelocationAcknowledge     },
827
    { static_cast<uint8_t>(GtpV2MessageType::ForwardAccessNotification),        GtpV2MessageType::ForwardAccessNotification        },
828
    { static_cast<uint8_t>(GtpV2MessageType::ForwardAccessAcknowledge),         GtpV2MessageType::ForwardAccessAcknowledge         },
829
    { static_cast<uint8_t>(GtpV2MessageType::RelocationCancelRequest),          GtpV2MessageType::RelocationCancelRequest          },
830
    { static_cast<uint8_t>(GtpV2MessageType::RelocationCancelResponse),         GtpV2MessageType::RelocationCancelResponse         },
831
    { static_cast<uint8_t>(GtpV2MessageType::ConfigurationTransferTunnel),      GtpV2MessageType::ConfigurationTransferTunnel      },
832
    { static_cast<uint8_t>(GtpV2MessageType::DetachNotification),               GtpV2MessageType::DetachNotification               },
833
    { static_cast<uint8_t>(GtpV2MessageType::DetachAcknowledge),                GtpV2MessageType::DetachAcknowledge                },
834
    { static_cast<uint8_t>(GtpV2MessageType::CSPaging),                         GtpV2MessageType::CSPaging                         },
835
    { static_cast<uint8_t>(GtpV2MessageType::RANInformationRelay),              GtpV2MessageType::RANInformationRelay              },
836
    { static_cast<uint8_t>(GtpV2MessageType::AlertMMENotification),             GtpV2MessageType::AlertMMENotification             },
837
    { static_cast<uint8_t>(GtpV2MessageType::AlertMMEAcknowledge),              GtpV2MessageType::AlertMMEAcknowledge              },
838
    { static_cast<uint8_t>(GtpV2MessageType::UEActivityNotification),           GtpV2MessageType::UEActivityNotification           },
839
    { static_cast<uint8_t>(GtpV2MessageType::UEActivityAcknowledge),            GtpV2MessageType::UEActivityAcknowledge            },
840
    { static_cast<uint8_t>(GtpV2MessageType::ISRStatus),                        GtpV2MessageType::ISRStatus                        },
841
    { static_cast<uint8_t>(GtpV2MessageType::CreateForwardingRequest),          GtpV2MessageType::CreateForwardingRequest          },
842
    { static_cast<uint8_t>(GtpV2MessageType::CreateForwardingResponse),         GtpV2MessageType::CreateForwardingResponse         },
843
    { static_cast<uint8_t>(GtpV2MessageType::SuspendNotification),              GtpV2MessageType::SuspendNotification              },
844
    { static_cast<uint8_t>(GtpV2MessageType::SuspendAcknowledge),               GtpV2MessageType::SuspendAcknowledge               },
845
    { static_cast<uint8_t>(GtpV2MessageType::ResumeNotification),               GtpV2MessageType::ResumeNotification               },
846
    { static_cast<uint8_t>(GtpV2MessageType::ResumeAcknowledge),                GtpV2MessageType::ResumeAcknowledge                },
847
    { static_cast<uint8_t>(GtpV2MessageType::CreateIndirectDataTunnelRequest),  GtpV2MessageType::CreateIndirectDataTunnelRequest  },
848
    { static_cast<uint8_t>(GtpV2MessageType::CreateIndirectDataTunnelResponse), GtpV2MessageType::CreateIndirectDataTunnelResponse },
849
    { static_cast<uint8_t>(GtpV2MessageType::DeleteIndirectDataTunnelRequest),  GtpV2MessageType::DeleteIndirectDataTunnelRequest  },
850
    { static_cast<uint8_t>(GtpV2MessageType::DeleteIndirectDataTunnelResponse), GtpV2MessageType::DeleteIndirectDataTunnelResponse },
851
    { static_cast<uint8_t>(GtpV2MessageType::ReleaseAccessBearersRequest),      GtpV2MessageType::ReleaseAccessBearersRequest      },
852
    { static_cast<uint8_t>(GtpV2MessageType::ReleaseAccessBearersResponse),     GtpV2MessageType::ReleaseAccessBearersResponse     },
853
    { static_cast<uint8_t>(GtpV2MessageType::DownlinkDataNotification),         GtpV2MessageType::DownlinkDataNotification         },
854
    { static_cast<uint8_t>(GtpV2MessageType::DownlinkDataAcknowledge),          GtpV2MessageType::DownlinkDataAcknowledge          },
855
    { static_cast<uint8_t>(GtpV2MessageType::PGWRestartNotification),           GtpV2MessageType::PGWRestartNotification           },
856
    { static_cast<uint8_t>(GtpV2MessageType::PGWRestartAcknowledge),            GtpV2MessageType::PGWRestartAcknowledge            },
857
    { static_cast<uint8_t>(GtpV2MessageType::UpdatePDNConnectionRequest),       GtpV2MessageType::UpdatePDNConnectionRequest       },
858
    { static_cast<uint8_t>(GtpV2MessageType::UpdatePDNConnectionResponse),      GtpV2MessageType::UpdatePDNConnectionResponse      },
859
    { static_cast<uint8_t>(GtpV2MessageType::ModifyAccessBearersRequest),       GtpV2MessageType::ModifyAccessBearersRequest       },
860
    { static_cast<uint8_t>(GtpV2MessageType::ModifyAccessBearersResponse),      GtpV2MessageType::ModifyAccessBearersResponse      },
861
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStartRequest),          GtpV2MessageType::MMBSSessionStartRequest          },
862
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStartResponse),         GtpV2MessageType::MMBSSessionStartResponse         },
863
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionUpdateRequest),         GtpV2MessageType::MMBSSessionUpdateRequest         },
864
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionUpdateResponse),        GtpV2MessageType::MMBSSessionUpdateResponse        },
865
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStopRequest),           GtpV2MessageType::MMBSSessionStopRequest           },
866
    { static_cast<uint8_t>(GtpV2MessageType::MMBSSessionStopResponse),          GtpV2MessageType::MMBSSessionStopResponse          }
867
  };
868
  // clang-format on
869
870
  GtpV2MessageType GtpV2MessageType::fromUintValue(uint8_t value)
871
192
  {
872
192
    auto iter = uintToValueMap.find(value);
873
192
    if (iter != uintToValueMap.end())
874
40
    {
875
40
      return iter->second;
876
40
    }
877
878
152
    return Unknown;
879
192
  }
880
881
  /// =======================
882
  /// GtpV2InformationElement
883
  /// =======================
884
885
  GtpV2InformationElement::Type GtpV2InformationElement::getIEType()
886
0
  {
887
0
    if (m_Data == nullptr)
888
0
    {
889
0
      return GtpV2InformationElement::Type::Unknown;
890
0
    }
891
892
0
    auto ieType = m_Data->recordType;
893
0
    if ((ieType >= 4 && ieType <= 50) || (ieType >= 52 && ieType <= 70) || ieType == 98 || ieType == 101 ||
894
0
        ieType == 102 || ieType == 122 || ieType == 130 || ieType == 161 || ieType > 213)
895
0
    {
896
0
      return GtpV2InformationElement::Type::Unknown;
897
0
    }
898
899
0
    return static_cast<GtpV2InformationElement::Type>(ieType);
900
0
  }
901
902
  uint8_t GtpV2InformationElement::getCRFlag()
903
0
  {
904
0
    if (m_Data == nullptr)
905
0
    {
906
0
      return 0;
907
0
    }
908
909
0
    return m_Data->recordValue[0] >> 4;
910
0
  }
911
912
  uint8_t GtpV2InformationElement::getInstance()
913
0
  {
914
0
    if (m_Data == nullptr)
915
0
    {
916
0
      return 0;
917
0
    }
918
919
0
    return m_Data->recordValue[0] & 0xf;
920
0
  }
921
922
  size_t GtpV2InformationElement::getTotalSize() const
923
0
  {
924
0
    if (m_Data == nullptr)
925
0
    {
926
0
      return 0;
927
0
    }
928
929
0
    return getDataSize() + 2 * sizeof(uint8_t) + sizeof(uint16_t);
930
0
  }
931
932
  size_t GtpV2InformationElement::getDataSize() const
933
0
  {
934
0
    if (m_Data == nullptr)
935
0
    {
936
0
      return 0;
937
0
    }
938
939
0
    return static_cast<size_t>(be16toh(m_Data->recordLen));
940
0
  }
941
942
  /// ==============================
943
  /// GtpV2InformationElementBuilder
944
  /// ==============================
945
946
  GtpV2InformationElementBuilder::GtpV2InformationElementBuilder(GtpV2InformationElement::Type infoElementType,
947
                                                                 const std::bitset<4>& crFlag,
948
                                                                 const std::bitset<4>& instance,
949
                                                                 const std::vector<uint8_t>& infoElementValue)
950
0
      : TLVRecordBuilder(static_cast<uint32_t>(infoElementType), infoElementValue.data(),
951
0
                         static_cast<uint8_t>(infoElementValue.size())),
952
0
        m_CRFlag(crFlag), m_Instance(instance)
953
0
  {}
954
955
  GtpV2InformationElement GtpV2InformationElementBuilder::build() const
956
0
  {
957
0
    if (m_RecType == 0)
958
0
    {
959
0
      GtpV2InformationElement(nullptr);
960
0
    }
961
962
0
    size_t infoElementBaseSize = sizeof(uint8_t) + sizeof(uint16_t);
963
0
    size_t infoElementTotalSize = infoElementBaseSize + sizeof(uint8_t) + m_RecValueLen;
964
0
    auto* recordBuffer = new uint8_t[infoElementTotalSize];
965
0
    recordBuffer[0] = static_cast<uint8_t>(m_RecType);
966
0
    auto infoElementLength = htobe16(m_RecValueLen);
967
0
    memcpy(recordBuffer + sizeof(uint8_t), &infoElementLength, sizeof(uint16_t));
968
0
    auto crFlag = static_cast<uint8_t>(m_CRFlag.to_ulong());
969
0
    auto instance = static_cast<uint8_t>(m_Instance.to_ulong());
970
0
    recordBuffer[infoElementBaseSize] = ((crFlag << 4) & 0xf0) | (instance & 0x0f);
971
0
    if (m_RecValueLen > 0 && m_RecValue != nullptr)
972
0
    {
973
0
      memcpy(recordBuffer + infoElementBaseSize + sizeof(uint8_t), m_RecValue, m_RecValueLen);
974
0
    }
975
976
0
    return GtpV2InformationElement(recordBuffer);
977
0
  }
978
979
  /// ==========
980
  /// GtpV2Layer
981
  /// ==========
982
983
  GtpV2Layer::GtpV2Layer(GtpV2MessageType messageType, uint32_t sequenceNumber, bool setTeid, uint32_t teid,
984
                         bool setMessagePriority, std::bitset<4> messagePriority)
985
0
  {
986
0
    size_t messageLength = sizeof(uint32_t) + (setTeid ? sizeof(uint32_t) : 0);
987
0
    size_t headerLen = sizeof(gtpv2_basic_header) + messageLength;
988
0
    m_DataLen = headerLen;
989
0
    m_Data = new uint8_t[headerLen];
990
0
    memset(m_Data, 0, headerLen);
991
992
0
    auto* hdr = getHeader();
993
0
    hdr->version = 2;
994
0
    hdr->teidPresent = setTeid;
995
0
    hdr->messagePriorityPresent = setMessagePriority;
996
0
    hdr->messageType = static_cast<uint8_t>(messageType);
997
0
    hdr->messageLength = htobe16(messageLength);
998
999
0
    auto* dataPtr = m_Data + sizeof(gtpv2_basic_header);
1000
0
    if (setTeid)
1001
0
    {
1002
0
      teid = htobe32(teid);
1003
0
      memcpy(dataPtr, &teid, sizeof(uint32_t));
1004
0
      dataPtr += sizeof(uint32_t);
1005
0
    }
1006
1007
0
    sequenceNumber = htobe32(sequenceNumber) >> 8;
1008
0
    memcpy(dataPtr, &sequenceNumber, sizeof(uint32_t));
1009
0
    dataPtr += sizeof(uint32_t) - 1;
1010
1011
0
    if (setMessagePriority)
1012
0
    {
1013
0
      auto messagePriorityNum = static_cast<uint8_t>(messagePriority.to_ulong());
1014
0
      dataPtr[0] = messagePriorityNum << 4;
1015
0
    }
1016
1017
0
    m_Protocol = GTPv2;
1018
0
  }
1019
1020
  bool GtpV2Layer::isDataValid(const uint8_t* data, size_t dataSize)
1021
729
  {
1022
729
    if (!data || dataSize < sizeof(gtpv2_basic_header) + sizeof(uint32_t))
1023
57
    {
1024
57
      return false;
1025
57
    }
1026
1027
672
    auto* header = reinterpret_cast<const gtpv2_basic_header*>(data);
1028
1029
672
    if (header->version != 2)
1030
87
    {
1031
87
      return false;
1032
87
    }
1033
1034
585
    return true;
1035
672
  }
1036
1037
  GtpV2MessageType GtpV2Layer::getMessageType() const
1038
192
  {
1039
192
    return GtpV2MessageType::fromUintValue(getHeader()->messageType);
1040
192
  }
1041
1042
  void GtpV2Layer::setMessageType(const GtpV2MessageType& type)
1043
0
  {
1044
0
    getHeader()->messageType = type;
1045
0
  }
1046
1047
  uint16_t GtpV2Layer::getMessageLength() const
1048
0
  {
1049
0
    return be16toh(getHeader()->messageLength);
1050
0
  }
1051
1052
  bool GtpV2Layer::isPiggybacking() const
1053
0
  {
1054
0
    return getHeader()->piggybacking;
1055
0
  }
1056
1057
  std::pair<bool, uint32_t> GtpV2Layer::getTeid() const
1058
0
  {
1059
0
    if (!getHeader()->teidPresent)
1060
0
    {
1061
0
      return { false, 0 };
1062
0
    }
1063
1064
0
    return { true, be32toh(*reinterpret_cast<uint32_t*>(m_Data + sizeof(gtpv2_basic_header))) };
1065
0
  }
1066
1067
  void GtpV2Layer::setTeid(uint32_t teid)
1068
0
  {
1069
0
    auto* header = getHeader();
1070
1071
0
    auto teidOffset = sizeof(gtpv2_basic_header);
1072
0
    if (!header->teidPresent)
1073
0
    {
1074
0
      if (!extendLayer(static_cast<int>(teidOffset), sizeof(uint32_t)))
1075
0
      {
1076
0
        PCPP_LOG_ERROR("Unable to set TEID: failed to extend the layer");
1077
0
        return;
1078
0
      }
1079
0
      header = getHeader();
1080
0
      header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(uint32_t));
1081
0
    }
1082
1083
0
    reinterpret_cast<uint32_t*>(m_Data + teidOffset)[0] = htobe32(teid);
1084
1085
0
    header->teidPresent = 1;
1086
0
  }
1087
1088
  void GtpV2Layer::unsetTeid()
1089
0
  {
1090
0
    auto* header = getHeader();
1091
1092
0
    if (!header->teidPresent)
1093
0
    {
1094
0
      return;
1095
0
    }
1096
1097
0
    auto teidOffset = sizeof(gtpv2_basic_header);
1098
0
    if (!shortenLayer(static_cast<int>(teidOffset), sizeof(uint32_t)))
1099
0
    {
1100
0
      PCPP_LOG_ERROR("Unable to unset TEID: failed to shorten the layer");
1101
0
      return;
1102
0
    }
1103
1104
0
    header = getHeader();
1105
0
    header->messageLength = htobe16(be16toh(header->messageLength) - sizeof(uint32_t));
1106
0
    header->teidPresent = 0;
1107
0
  }
1108
1109
  uint32_t GtpV2Layer::getSequenceNumber() const
1110
0
  {
1111
0
    auto* sequencePos = m_Data + sizeof(gtpv2_basic_header);
1112
0
    if (getHeader()->teidPresent)
1113
0
    {
1114
0
      sequencePos += sizeof(uint32_t);
1115
0
    }
1116
1117
0
    return be32toh(*reinterpret_cast<uint32_t*>(sequencePos)) >> 8;
1118
0
  }
1119
1120
  void GtpV2Layer::setSequenceNumber(uint32_t sequenceNumber)
1121
0
  {
1122
0
    auto* sequencePos = m_Data + sizeof(gtpv2_basic_header);
1123
0
    if (getHeader()->teidPresent)
1124
0
    {
1125
0
      sequencePos += sizeof(uint32_t);
1126
0
    }
1127
1128
0
    sequenceNumber = htobe32(sequenceNumber) >> 8;
1129
0
    memcpy(sequencePos, &sequenceNumber, sizeof(uint32_t) - 1);
1130
0
  }
1131
1132
  std::pair<bool, uint8_t> GtpV2Layer::getMessagePriority() const
1133
0
  {
1134
0
    auto* header = getHeader();
1135
1136
0
    if (!header->messagePriorityPresent)
1137
0
    {
1138
0
      return { false, 0 };
1139
0
    }
1140
1141
0
    auto* mpPos = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t) - 1;
1142
0
    if (header->teidPresent)
1143
0
    {
1144
0
      mpPos += sizeof(uint32_t);
1145
0
    }
1146
1147
0
    return { true, mpPos[0] >> 4 };
1148
0
  }
1149
1150
  void GtpV2Layer::setMessagePriority(const std::bitset<4>& messagePriority)
1151
0
  {
1152
0
    auto* header = getHeader();
1153
1154
0
    header->messagePriorityPresent = 1;
1155
1156
0
    auto* mpPos = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t) - 1;
1157
0
    if (header->teidPresent)
1158
0
    {
1159
0
      mpPos += sizeof(uint32_t);
1160
0
    }
1161
1162
0
    auto messagePriorityNum = static_cast<uint8_t>(messagePriority.to_ulong());
1163
0
    mpPos[0] = messagePriorityNum << 4;
1164
0
  }
1165
1166
  void GtpV2Layer::unsetMessagePriority()
1167
0
  {
1168
0
    auto* header = getHeader();
1169
1170
0
    header->messagePriorityPresent = 0;
1171
1172
0
    auto* mpPos = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t) - 1;
1173
0
    if (header->teidPresent)
1174
0
    {
1175
0
      mpPos += sizeof(uint32_t);
1176
0
    }
1177
1178
0
    mpPos[0] = 0;
1179
0
  }
1180
1181
  GtpV2InformationElement GtpV2Layer::getFirstInformationElement() const
1182
0
  {
1183
0
    auto* basePtr = getIEBasePtr();
1184
0
    return m_IEReader.getFirstTLVRecord(basePtr, m_Data + getHeaderLen() - basePtr);
1185
0
  }
1186
1187
  GtpV2InformationElement GtpV2Layer::getNextInformationElement(GtpV2InformationElement infoElement) const
1188
0
  {
1189
0
    auto* basePtr = getIEBasePtr();
1190
0
    return m_IEReader.getNextTLVRecord(infoElement, basePtr, m_Data + getHeaderLen() - basePtr);
1191
0
  }
1192
1193
  GtpV2InformationElement GtpV2Layer::getInformationElement(GtpV2InformationElement::Type infoElementType) const
1194
0
  {
1195
0
    auto* basePtr = getIEBasePtr();
1196
0
    return m_IEReader.getTLVRecord(static_cast<uint32_t>(infoElementType), basePtr,
1197
0
                                   m_Data + getHeaderLen() - basePtr);
1198
0
  }
1199
1200
  size_t GtpV2Layer::getInformationElementCount() const
1201
0
  {
1202
0
    auto* basePtr = getIEBasePtr();
1203
0
    return m_IEReader.getTLVRecordCount(basePtr, m_Data + getHeaderLen() - basePtr);
1204
0
  }
1205
1206
  GtpV2InformationElement GtpV2Layer::addInformationElement(const GtpV2InformationElementBuilder& infoElementBuilder)
1207
0
  {
1208
0
    return addInformationElementAt(infoElementBuilder, static_cast<int>(getHeaderLen()));
1209
0
  }
1210
1211
  GtpV2InformationElement GtpV2Layer::addInformationElementAfter(
1212
      const GtpV2InformationElementBuilder& infoElementBuilder, GtpV2InformationElement::Type infoElementType)
1213
0
  {
1214
0
    auto prevInfoElement = getInformationElement(infoElementType);
1215
1216
0
    if (prevInfoElement.isNull())
1217
0
    {
1218
0
      PCPP_LOG_ERROR("Information element type " << static_cast<int>(infoElementType)
1219
0
                                                 << " doesn't exist in layer");
1220
0
      return GtpV2InformationElement(nullptr);
1221
0
    }
1222
0
    auto offset = prevInfoElement.getRecordBasePtr() + prevInfoElement.getTotalSize() - m_Data;
1223
0
    return addInformationElementAt(infoElementBuilder, offset);
1224
0
  }
1225
1226
  bool GtpV2Layer::removeInformationElement(GtpV2InformationElement::Type infoElementType)
1227
0
  {
1228
0
    auto infoElementToRemove = getInformationElement(infoElementType);
1229
0
    if (infoElementToRemove.isNull())
1230
0
    {
1231
0
      return false;
1232
0
    }
1233
1234
0
    int offset = infoElementToRemove.getRecordBasePtr() - m_Data;
1235
1236
0
    auto infoElementSize = infoElementToRemove.getTotalSize();
1237
0
    if (!shortenLayer(offset, infoElementSize))
1238
0
    {
1239
0
      return false;
1240
0
    }
1241
1242
0
    getHeader()->messageLength = htobe16(be16toh(getHeader()->messageLength) - infoElementSize);
1243
0
    m_IEReader.changeTLVRecordCount(-1);
1244
0
    return true;
1245
0
  }
1246
1247
  bool GtpV2Layer::removeAllInformationElements()
1248
0
  {
1249
0
    auto firstInfoElement = getFirstInformationElement();
1250
0
    if (firstInfoElement.isNull())
1251
0
    {
1252
0
      return true;
1253
0
    }
1254
1255
0
    auto offset = firstInfoElement.getRecordBasePtr() - m_Data;
1256
1257
0
    if (!shortenLayer(offset, getHeaderLen() - offset))
1258
0
    {
1259
0
      return false;
1260
0
    }
1261
1262
0
    m_IEReader.changeTLVRecordCount(static_cast<int>(0 - getInformationElementCount()));
1263
0
    return true;
1264
0
  }
1265
1266
  GtpV2InformationElement GtpV2Layer::addInformationElementAt(
1267
      const GtpV2InformationElementBuilder& infoElementBuilder, int offset)
1268
0
  {
1269
0
    auto newInfoElement = infoElementBuilder.build();
1270
1271
0
    if (newInfoElement.isNull())
1272
0
    {
1273
0
      PCPP_LOG_ERROR("Cannot build new information element");
1274
0
      return newInfoElement;
1275
0
    }
1276
1277
0
    auto sizeToExtend = newInfoElement.getTotalSize();
1278
1279
0
    if (!extendLayer(offset, sizeToExtend))
1280
0
    {
1281
0
      PCPP_LOG_ERROR("Could not extend GtpV2Layer in [" << sizeToExtend << "] bytes");
1282
0
      newInfoElement.purgeRecordData();
1283
0
      return GtpV2InformationElement(nullptr);
1284
0
    }
1285
1286
0
    memcpy(m_Data + offset, newInfoElement.getRecordBasePtr(), newInfoElement.getTotalSize());
1287
1288
0
    auto newMessageLength = getMessageLength() + newInfoElement.getTotalSize();
1289
1290
0
    newInfoElement.purgeRecordData();
1291
1292
0
    m_IEReader.changeTLVRecordCount(1);
1293
1294
0
    getHeader()->messageLength = htobe16(newMessageLength);
1295
1296
0
    uint8_t* newInfoElementPtr = m_Data + offset;
1297
1298
0
    return GtpV2InformationElement(newInfoElementPtr);
1299
0
  }
1300
1301
  void GtpV2Layer::parseNextLayer()
1302
585
  {
1303
585
    auto headerLen = getHeaderLen();
1304
585
    if (m_DataLen <= headerLen)
1305
262
    {
1306
262
      return;
1307
262
    }
1308
1309
323
    auto* nextLayerData = m_Data + headerLen;
1310
323
    auto nextLayerDataLen = m_DataLen - headerLen;
1311
1312
323
    if (getHeader()->piggybacking)
1313
254
    {
1314
254
      tryConstructNextLayerWithFallback<GtpV2Layer, PayloadLayer>(nextLayerData, nextLayerDataLen);
1315
254
    }
1316
69
    else
1317
69
    {
1318
69
      constructNextLayer<PayloadLayer>(nextLayerData, nextLayerDataLen);
1319
69
    }
1320
323
  }
1321
1322
  size_t GtpV2Layer::getHeaderLen() const
1323
681
  {
1324
681
    auto messageLength = be16toh(getHeader()->messageLength) + sizeof(gtpv2_basic_header);
1325
681
    if (messageLength > m_DataLen)
1326
307
    {
1327
307
      return m_DataLen;
1328
307
    }
1329
1330
374
    return messageLength;
1331
681
  }
1332
1333
  void GtpV2Layer::computeCalculateFields()
1334
96
  {
1335
96
    if (m_NextLayer == nullptr)
1336
36
    {
1337
36
      return;
1338
36
    }
1339
1340
60
    if (m_NextLayer->getProtocol() == GTPv2)
1341
32
    {
1342
32
      getHeader()->piggybacking = 1;
1343
32
    }
1344
28
    else
1345
28
    {
1346
28
      getHeader()->piggybacking = 0;
1347
28
    }
1348
60
  }
1349
1350
  std::string GtpV2Layer::toString() const
1351
192
  {
1352
192
    return "GTPv2 Layer, " + getMessageType().toString() + " message";
1353
192
  }
1354
1355
  uint8_t* GtpV2Layer::getIEBasePtr() const
1356
0
  {
1357
0
    auto* basePtr = m_Data + sizeof(gtpv2_basic_header) + sizeof(uint32_t);
1358
0
    if (getHeader()->teidPresent)
1359
0
    {
1360
0
      basePtr += sizeof(uint32_t);
1361
0
    }
1362
1363
0
    return basePtr;
1364
0
  }
1365
1366
}  // namespace pcpp