Coverage Report

Created: 2026-11-12 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/header/GtpLayer.h
Line
Count
Source
1
#pragma once
2
3
#include "Layer.h"
4
#include "TLVData.h"
5
#include <vector>
6
#include <bitset>
7
8
/// @file
9
10
/// @namespace pcpp
11
/// @brief The main namespace for the PcapPlusPlus lib
12
namespace pcpp
13
{
14
15
#pragma pack(push, 1)
16
  /// @struct gtpv1_header
17
  /// GTP v1 common message header
18
  struct gtpv1_header
19
  {
20
#if (BYTE_ORDER == LITTLE_ENDIAN)
21
    /// A 1-bit value that states whether there is a N-PDU number optional field
22
    uint8_t npduNumberFlag : 1,
23
        /// A 1-bit value that states whether there is a Sequence Number optional field
24
        sequenceNumberFlag : 1,
25
        /// A 1-bit value that states whether there is an extension header optional field
26
        extensionHeaderFlag : 1,
27
        /// Reserved bit
28
        reserved : 1,
29
        /// A 1-bit value that differentiates GTP (value 1) from GTP' (value 0)
30
        protocolType : 1,
31
        /// GTP version
32
        version : 3;
33
#else
34
    /// GTP version
35
    uint8_t version : 3,
36
        /// A 1-bit value that differentiates GTP (value 1) from GTP' (value 0)
37
        protocolType : 1,
38
        /// Reserved bit
39
        reserved : 1,
40
        /// A 1-bit value that states whether there is an extension header optional field
41
        extensionHeaderFlag : 1,
42
        /// A 1-bit value that states whether there is a Sequence Number optional field
43
        sequenceNumberFlag : 1,
44
        /// A 1-bit value that states whether there is a N-PDU number optional field
45
        npduNumberFlag : 1;
46
#endif
47
    /// An 8-bit field that indicates the type of GTP message
48
    uint8_t messageType;
49
50
    /// A 16-bit field that indicates the length of the payload in bytes (rest of the packet following the mandatory
51
    /// 8-byte GTP header). Includes the optional fields
52
    uint16_t messageLength;
53
54
    /// Tunnel endpoint identifier - A 32-bit(4-octet) field used to multiplex different connections in the same GTP
55
    /// tunnel
56
    uint32_t teid;
57
  };
58
#pragma pack(pop)
59
  static_assert(sizeof(gtpv1_header) == 8, "gtpv1_header size is not 8 bytes");
60
61
  /// An enum representing the possible GTP v1 message types.
62
  /// All of the message types except for #GtpV1_GPDU are considered GTP-C messages. #GtpV1_GPDU is considered a GTP-U
63
  /// message
64
  enum GtpV1MessageType
65
  {
66
    /// GTPv1 Message Type Unknown
67
    GtpV1_MessageTypeUnknown = 0,
68
    /// Echo Request
69
    GtpV1_EchoRequest = 1,
70
    /// Echo Response
71
    GtpV1_EchoResponse = 2,
72
    /// Version Not Supported
73
    GtpV1_VersionNotSupported = 3,
74
    /// Node Alive Request
75
    GtpV1_NodeAliveRequest = 4,
76
    /// Node Alive Response
77
    GtpV1_NodeAliveResponse = 5,
78
    /// Redirection Request
79
    GtpV1_RedirectionRequest = 6,
80
    /// Create PDP Context Request
81
    GtpV1_CreatePDPContextRequest = 7,
82
    /// Create PDP Context Response
83
    GtpV1_CreatePDPContextResponse = 16,
84
    /// Update PDP Context Request
85
    GtpV1_UpdatePDPContextRequest = 17,
86
    /// Update PDP Context Response
87
    GtpV1_UpdatePDPContextResponse = 18,
88
    /// Delete PDP Context Request
89
    GtpV1_DeletePDPContextRequest = 19,
90
    /// Delete PDP Context Response
91
    GtpV1_DeletePDPContextResponse = 20,
92
    /// Initiate PDP Context Activation Request
93
    GtpV1_InitiatePDPContextActivationRequest = 22,
94
    /// Initiate PDP Context Activation Response
95
    GtpV1_InitiatePDPContextActivationResponse = 23,
96
    /// Error Indication
97
    GtpV1_ErrorIndication = 26,
98
    /// PDU Notification Request
99
    GtpV1_PDUNotificationRequest = 27,
100
    /// PDU Notification Response
101
    GtpV1_PDUNotificationResponse = 28,
102
    /// PDU Notification Reject Request
103
    GtpV1_PDUNotificationRejectRequest = 29,
104
    /// PDU Notification Reject Response
105
    GtpV1_PDUNotificationRejectResponse = 30,
106
    /// Supported Extensions Header Notification
107
    GtpV1_SupportedExtensionsHeaderNotification = 31,
108
    /// Send Routing for GPRS Request
109
    GtpV1_SendRoutingforGPRSRequest = 32,
110
    /// Send Routing for GPRS Response
111
    GtpV1_SendRoutingforGPRSResponse = 33,
112
    /// Failure Report Request
113
    GtpV1_FailureReportRequest = 34,
114
    /// Failure Report Response
115
    GtpV1_FailureReportResponse = 35,
116
    /// Note MS Present Request
117
    GtpV1_NoteMSPresentRequest = 36,
118
    /// Note MS Present Response
119
    GtpV1_NoteMSPresentResponse = 37,
120
    /// Identification Request
121
    GtpV1_IdentificationRequest = 38,
122
    /// Identification Response
123
    GtpV1_IdentificationResponse = 39,
124
    /// SGSN Context Request
125
    GtpV1_SGSNContextRequest = 50,
126
    /// SGSN Context Response
127
    GtpV1_SGSNContextResponse = 51,
128
    /// SGSN Context Acknowledge
129
    GtpV1_SGSNContextAcknowledge = 52,
130
    /// Forward Relocation Request
131
    GtpV1_ForwardRelocationRequest = 53,
132
    /// Forward Relocation Response
133
    GtpV1_ForwardRelocationResponse = 54,
134
    /// Forward Relocation Complete
135
    GtpV1_ForwardRelocationComplete = 55,
136
    /// Relocation Cancel Request
137
    GtpV1_RelocationCancelRequest = 56,
138
    /// Relocation Cancel Response
139
    GtpV1_RelocationCancelResponse = 57,
140
    /// Forward SRNS Context
141
    GtpV1_ForwardSRNSContext = 58,
142
    /// Forward Relocation Complete Acknowledge
143
    GtpV1_ForwardRelocationCompleteAcknowledge = 59,
144
    /// Forward SRNS Context Acknowledge
145
    GtpV1_ForwardSRNSContextAcknowledge = 60,
146
    /// UE Registration Request
147
    GtpV1_UERegistrationRequest = 61,
148
    /// UE Registration Response
149
    GtpV1_UERegistrationResponse = 62,
150
    /// RAN Information Relay
151
    GtpV1_RANInformationRelay = 70,
152
    /// MBMS Notification Request
153
    GtpV1_MBMSNotificationRequest = 96,
154
    /// MBMS Notification Response
155
    GtpV1_MBMSNotificationResponse = 97,
156
    /// MBMS Notification Reject Request
157
    GtpV1_MBMSNotificationRejectRequest = 98,
158
    /// MBMS Notification Reject Response
159
    GtpV1_MBMSNotificationRejectResponse = 99,
160
    /// Create MBMS Notification Request
161
    GtpV1_CreateMBMSNotificationRequest = 100,
162
    /// Create MBMS Notification Response
163
    GtpV1_CreateMBMSNotificationResponse = 101,
164
    /// Update MBMS Notification Request
165
    GtpV1_UpdateMBMSNotificationRequest = 102,
166
    /// Update MBMS Notification Response
167
    GtpV1_UpdateMBMSNotificationResponse = 103,
168
    /// Delete MBMS Notification Request
169
    GtpV1_DeleteMBMSNotificationRequest = 104,
170
    /// Delete MBMS Notification Response
171
    GtpV1_DeleteMBMSNotificationResponse = 105,
172
    /// MBMS Registration Request
173
    GtpV1_MBMSRegistrationRequest = 112,
174
    /// MBMS Registration Response
175
    GtpV1_MBMSRegistrationResponse = 113,
176
    /// MBMS De-Registration Request
177
    GtpV1_MBMSDeRegistrationRequest = 114,
178
    /// MBMS De-Registration Response
179
    GtpV1_MBMSDeRegistrationResponse = 115,
180
    /// MBMS Session Start Request
181
    GtpV1_MBMSSessionStartRequest = 116,
182
    /// MBMS Session Start Response
183
    GtpV1_MBMSSessionStartResponse = 117,
184
    /// MBMS Session Stop Request
185
    GtpV1_MBMSSessionStopRequest = 118,
186
    /// MBMS Session Stop Response
187
    GtpV1_MBMSSessionStopResponse = 119,
188
    /// MBMS Session Update Request
189
    GtpV1_MBMSSessionUpdateRequest = 120,
190
    /// MBMS Session Update Response
191
    GtpV1_MBMSSessionUpdateResponse = 121,
192
    /// MS Info Change Request
193
    GtpV1_MSInfoChangeRequest = 128,
194
    /// MS Info Change Response
195
    GtpV1_MSInfoChangeResponse = 129,
196
    /// Data Record Transfer Request
197
    GtpV1_DataRecordTransferRequest = 240,
198
    /// Data Record Transfer Response
199
    GtpV1_DataRecordTransferResponse = 241,
200
    /// End Marker
201
    GtpV1_EndMarker = 254,
202
    /// G-PDU
203
    GtpV1_GPDU = 255
204
  };
205
206
  /// @class GtpV1Layer
207
  /// A class representing the [GTP v1](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol) protocol.
208
  class GtpV1Layer : public Layer
209
  {
210
  private:
211
    struct gtpv1_header_extra
212
    {
213
      uint16_t sequenceNumber;
214
      uint8_t npduNumber;
215
      uint8_t nextExtensionHeader;
216
    };
217
218
    gtpv1_header_extra* getHeaderExtra() const;
219
220
    void init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum,
221
              uint8_t npduNum);
222
223
  public:
224
    /// @class GtpExtension
225
    /// A class that represents [GTP header extensions](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol)
226
    class GtpExtension
227
    {
228
      friend class GtpV1Layer;
229
230
    private:
231
      uint8_t* m_Data;
232
      size_t m_DataLen;
233
      uint8_t m_ExtType;
234
235
      GtpExtension(uint8_t* data, size_t dataLen, uint8_t type);
236
237
      void setNextHeaderType(uint8_t nextHeaderType);
238
239
      static GtpExtension createGtpExtension(uint8_t* data, size_t dataLen, uint8_t extType, uint16_t content);
240
241
    public:
242
      /// An empty c'tor that creates an empty object, meaning one that isNull() returns "true")
243
      GtpExtension();
244
245
      /// A copy c'tor for this class
246
      /// @param[in] other The GTP extension to copy from
247
      GtpExtension(const GtpExtension& other);
248
249
      /// An assignment operator for this class
250
      /// @param[in] other The extension to assign from
251
      /// @return A reference to the assignee
252
      GtpExtension& operator=(const GtpExtension& other);
253
254
      /// @return Instances of this class may be initialized as empty, meaning they don't contain any data. In
255
      /// these cases this method returns true
256
      bool isNull() const;
257
258
      /// @return The extension type. If the object is empty a value of zero is returned
259
      uint8_t getExtensionType() const;
260
261
      /// @return The total length of the extension including the length and next extension type fields.
262
      /// If the object is empty a value of zero is returned
263
      size_t getTotalLength() const;
264
265
      /// @return The length of the extension's content, excluding the extension length and next extension type
266
      /// fields. If the object is empty a value of zero is returned
267
      size_t getContentLength() const;
268
269
      /// @return A byte array that includes the extension's content. The length of this array can be determined
270
      /// by getContentLength(). If the object is empty a null value is returned
271
      uint8_t* getContent() const;
272
273
      /// @return The extension type of the next header. If there are no more header extensions or if this object
274
      /// is empty a value of zero is returned
275
      uint8_t getNextExtensionHeaderType() const;
276
277
      /// @return An instance of this class representing the next extension header, if exists in the message. If
278
      /// there are no more header extensions or if this object is empty an empty instance of GtpExtension is
279
      /// returned, meaning one that GtpExtension#isNull() returns "true"
280
      GtpExtension getNextExtension() const;
281
    };  // GtpExtension
282
283
    ~GtpV1Layer() override = default;
284
285
    /// A constructor that creates the layer from an existing packet raw data
286
    /// @param[in] data A pointer to the raw data
287
    /// @param[in] dataLen Size of the data in bytes
288
    /// @param[in] prevLayer A pointer to the previous layer
289
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
290
    GtpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
291
74.8k
        : Layer(data, dataLen, prevLayer, packet, GTPv1)
292
74.8k
    {}
293
294
    /// A constructor that creates a new GTPv1 layer and sets the message type and the TEID value
295
    /// @param[in] messageType The GTPv1 message type to be set in the newly created layer
296
    /// @param[in] teid The TEID value to be set in the newly created layer
297
    GtpV1Layer(GtpV1MessageType messageType, uint32_t teid);
298
299
    /// A constructor that creates a new GTPv1 layer and sets various parameters
300
    /// @param[in] messageType The GTPv1 message type to be set in the newly created layer
301
    /// @param[in] teid The TEID value to be set in the newly created layer
302
    /// @param[in] setSeqNum A flag indicating whether to set a sequence number. If set to "false" then the
303
    /// parameter "seqNum" will be ignored
304
    /// @param[in] seqNum The sequence number to be set in the newly created later. If "setSeqNum" is set to false
305
    /// this parameter will be ignored
306
    /// @param[in] setNpduNum A flag indicating whether to set the N-PDU number. If set to "false" then the
307
    /// parameter "npduNum" will be ignored
308
    /// @param[in] npduNum The N-PDU number to be set in the newly created later. If "setNpduNum" is set to false
309
    /// this parameter will be ignored
310
    GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum,
311
               uint8_t npduNum);
312
313
    /// A static method that takes a byte array and detects whether it is a GTP v1 message
314
    /// @param[in] data A byte array
315
    /// @param[in] dataSize The byte array size (in bytes)
316
    /// @return True if the data is identified as GTP v1 message (GTP-C or GTP-U)
317
    static bool isGTPv1(const uint8_t* data, size_t dataSize);
318
319
    /// @return The GTP v1 common header structure. Notice this points directly to the data, so every change will
320
    /// change the actual packet data
321
    gtpv1_header* getHeader() const
322
307k
    {
323
307k
      return reinterpret_cast<gtpv1_header*>(m_Data);
324
307k
    }
325
326
    /// Get the sequence number if exists on the message (sequence number is an optional field in GTP messages)
327
    /// @param[out] seqNumber Set with the sequence number value if exists in the layer. Otherwise remains unchanged
328
    /// @return True if the sequence number field exists in layer, in which case seqNumber is set with the value.
329
    /// Or false otherwise
330
    bool getSequenceNumber(uint16_t& seqNumber) const;
331
332
    /// Set a sequence number
333
    /// @param[in] seqNumber The sequence number to set
334
    /// @return True if the value was set successfully, false otherwise. In case of failure a corresponding error
335
    /// message will be written to log
336
    bool setSequenceNumber(uint16_t seqNumber);
337
338
    /// Get the N-PDU number if exists on the message (N-PDU number is an optional field in GTP messages)
339
    /// @param[out] npduNum Set with the N-PDU number value if exists in the layer. Otherwise remains unchanged
340
    /// @return True if the N-PDU number field exists in layer, in which case npduNum is set with the value.
341
    /// Or false otherwise
342
    bool getNpduNumber(uint8_t& npduNum) const;
343
344
    /// Set an N-PDU number
345
    /// @param[in] npduNum The N-PDU number to set
346
    /// @return True if the value was set successfully, false otherwise. In case of failure a corresponding error
347
    /// message will be written to log
348
    bool setNpduNumber(uint8_t npduNum);
349
350
    /// Get the type of the next header extension if exists on the message (extensions are optional in GTP messages)
351
    /// @param[out] nextExtType Set with the next header extension type if exists in layer. Otherwise remains
352
    /// unchanged
353
    /// @return True if the message contains header extensions, in which case nextExtType is set to the next
354
    /// header extension type. If there are no header extensions false is returned and nextExtType remains unchanged
355
    bool getNextExtensionHeaderType(uint8_t& nextExtType) const;
356
357
    /// @return An object that represents the next extension header, if exists in the message. If there are no
358
    /// extensions an empty object is returned, meaning an object which GtpExtension#isNull() returns "true"
359
    GtpExtension getNextExtension() const;
360
361
    /// Add a GTPv1 header extension. It is assumed that the extension is 4 bytes in length and its content is 2
362
    /// bytes in length. If you need a different content size please reach out to me. This method takes care of
363
    /// extending the layer to make room for the new extension and also sets the relevant flags and fields
364
    /// @param[in] extensionType The type of the new extension
365
    /// @param[in] extensionContent A 2-byte long content
366
    /// @return An object representing the newly added extension. If there was an error adding the extension a null
367
    /// object will be returned (meaning GtpExtension#isNull() will return "true") and a corresponding error message
368
    /// will be written to log
369
    GtpExtension addExtension(uint8_t extensionType, uint16_t extensionContent);
370
371
    /// @return The message type of this GTP packet
372
    GtpV1MessageType getMessageType() const;
373
374
    /// @return A string representation of the packet's message type
375
    std::string getMessageTypeAsString() const;
376
377
    /// @return True if this is a GTP-U message, false otherwise
378
    bool isGTPUMessage() const;
379
380
    /// @return True if this is a GTP-C message, false otherwise
381
    bool isGTPCMessage() const;
382
383
    /// A static method that checks whether the port is considered as GTPv1
384
    /// @param[in] port The port number to be checked
385
    /// @return True if the port matches those associated with the GTPv1 protocol
386
    static bool isGTPv1Port(uint16_t port)
387
689k
    {
388
689k
      return port == 2152 /* GTP-U */ || port == 2123 /* GTP-C */;
389
689k
    }
390
391
    // implement abstract methods
392
393
    /// Identifies the following next layers for GTP-U packets: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer
394
    void parseNextLayer() override;
395
396
    /// @return The size of the GTP header. For GTP-C packets the size is determined by the value of
397
    /// gtpv1_header#messageLength and for GTP-U the size only includes the GTP header itself (meaning
398
    /// the size of gtpv1_header plus the size of the optional fields such as sequence number, N-PDU
399
    /// or extensions if exist)
400
    size_t getHeaderLen() const override;
401
402
    /// Calculate the following fields:
403
    /// - gtpv1_header#messageLength
404
    void computeCalculateFields() override;
405
406
    std::string toString() const override;
407
408
    OsiModelLayer getOsiModelLayer() const override
409
10.5k
    {
410
10.5k
      return OsiModelTransportLayer;
411
10.5k
    }
412
413
    /// @struct SerializedFields
414
    /// Fields written by GtpV1Layer's serializeLayer(), in addition to Layer::SerializedFields
415
    struct SerializedFields : Layer::SerializedFields
416
    {
417
      /// @return All field descriptors for GtpV1Layer
418
      static std::vector<FieldDescriptor> all()
419
0
      {
420
0
        auto result = Layer::SerializedFields::all();
421
0
        std::initializer_list<FieldDescriptor> extra{ Version,         ProtocolType,  MessageType,
422
0
                                                    MessageTypeName, MessageLength, Teid,
423
0
                                                    SequenceNumber,  NpduNumber,    Extensions };
424
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
425
0
        return result;
426
0
      }
427
428
      /// @brief GTP version, as an integer
429
      static const FieldDescriptor Version;
430
      /// @brief Protocol type bit, as an integer: 1 for GTP, 0 for GTP'
431
      static const FieldDescriptor ProtocolType;
432
      /// @brief GTP message type, as an integer
433
      static const FieldDescriptor MessageType;
434
      /// @brief GTP message type name, as returned by getMessageTypeAsString()
435
      static const FieldDescriptor MessageTypeName;
436
      /// @brief Message length field in bytes (host byte order), excluding the mandatory 8-byte header
437
      static const FieldDescriptor MessageLength;
438
      /// @brief Tunnel endpoint identifier in hexadecimal (host byte order)
439
      static const FieldDescriptor Teid;
440
      /// @brief Sequence number (host byte order), only when the sequence number flag is set
441
      static const FieldDescriptor SequenceNumber;
442
      /// @brief N-PDU number, only when the N-PDU number flag is set
443
      static const FieldDescriptor NpduNumber;
444
      /// @brief List of header extension types, only when the extension header flag is set
445
      static const FieldDescriptor Extensions;
446
      /// @brief A single header extension type, as an integer
447
      static const FieldDescriptor Extension;
448
    };
449
450
  protected:
451
    void serializeLayer(ObjectScope& serializer) const override;
452
  };
453
454
  /// @class GtpV2MessageType
455
  /// The enum wrapper class of GTPv2 message type
456
  class GtpV2MessageType
457
  {
458
  public:
459
    /// Define enum types and the corresponding int values
460
    enum Value : uint8_t
461
    {
462
      /// Unknown message
463
      Unknown = 0,
464
      /// Echo Request message
465
      EchoRequest = 1,
466
      /// Echo Response message
467
      EchoResponse = 2,
468
      /// Version Not Supported message
469
      VersionNotSupported = 3,
470
      /// Create Session Request message
471
      CreateSessionRequest = 32,
472
      /// Create Session Response message
473
      CreateSessionResponse = 33,
474
      /// Modify Bearer Request message
475
      ModifyBearerRequest = 34,
476
      /// Modify Bearer Response message
477
      ModifyBearerResponse = 35,
478
      /// Delete Session Request message
479
      DeleteSessionRequest = 36,
480
      /// Delete Session Response message
481
      DeleteSessionResponse = 37,
482
      /// Change Notification Request message
483
      ChangeNotificationRequest = 38,
484
      /// Change Notification Response message
485
      ChangeNotificationResponse = 39,
486
      /// Remote UE Report Notifications message
487
      RemoteUEReportNotifications = 40,
488
      /// Remote UE Report Acknowledge message
489
      RemoteUEReportAcknowledge = 41,
490
      /// Modify Bearer Command message
491
      ModifyBearerCommand = 64,
492
      /// Modify Bearer Failure message
493
      ModifyBearerFailure = 65,
494
      /// Delete Bearer Command message
495
      DeleteBearerCommand = 66,
496
      /// Delete Bearer Failure message
497
      DeleteBearerFailure = 67,
498
      /// Bearer Resource Command message
499
      BearerResourceCommand = 68,
500
      /// Bearer Resource Failure message
501
      BearerResourceFailure = 69,
502
      /// Downlink Data Notification Failure message
503
      DownlinkDataNotificationFailure = 70,
504
      /// Trace Session Activation message
505
      TraceSessionActivation = 71,
506
      /// Trace Session Deactivation message
507
      TraceSessionDeactivation = 72,
508
      /// Stop Paging Indication message
509
      StopPagingIndication = 73,
510
      /// Create Bearer Request message
511
      CreateBearerRequest = 95,
512
      /// Create Bearer Response message
513
      CreateBearerResponse = 96,
514
      /// Update Bearer Request message
515
      UpdateBearerRequest = 97,
516
      /// Update Bearer Response message
517
      UpdateBearerResponse = 98,
518
      /// Delete Bearer Request message
519
      DeleteBearerRequest = 99,
520
      /// Delete Bearer Response message
521
      DeleteBearerResponse = 100,
522
      /// Delete PDN Request message
523
      DeletePDNRequest = 101,
524
      /// Delete PDN Response message
525
      DeletePDNResponse = 102,
526
      /// PGW Downlink Notification message
527
      PGWDownlinkNotification = 103,
528
      /// PGW Downlink Acknowledge message
529
      PGWDownlinkAcknowledge = 104,
530
      /// Identification Request message
531
      IdentificationRequest = 128,
532
      /// Identification Response message
533
      IdentificationResponse = 129,
534
      /// Context Request message
535
      ContextRequest = 130,
536
      /// Context Response message
537
      ContextResponse = 131,
538
      /// Context Acknowledge message
539
      ContextAcknowledge = 132,
540
      /// Forward Relocation Request message
541
      ForwardRelocationRequest = 133,
542
      /// Forward Relocation Response message
543
      ForwardRelocationResponse = 134,
544
      /// Forward Relocation Notification message
545
      ForwardRelocationNotification = 135,
546
      /// Forward Relocation Acknowledge message
547
      ForwardRelocationAcknowledge = 136,
548
      /// Forward Access Notification message
549
      ForwardAccessNotification = 137,
550
      /// Forward Access Acknowledge message
551
      ForwardAccessAcknowledge = 138,
552
      /// Relocation Cancel Request message
553
      RelocationCancelRequest = 139,
554
      /// Relocation Cancel Response message
555
      RelocationCancelResponse = 140,
556
      /// Configuration Transfer Tunnel message
557
      ConfigurationTransferTunnel = 141,
558
      /// Detach Notification message
559
      DetachNotification = 149,
560
      /// Detach Acknowledge message
561
      DetachAcknowledge = 150,
562
      /// CS Paging message
563
      CSPaging = 151,
564
      /// RAN Information Relay message
565
      RANInformationRelay = 152,
566
      /// Alert MME Notification message
567
      AlertMMENotification = 153,
568
      /// Alert MME Acknowledge message
569
      AlertMMEAcknowledge = 154,
570
      /// UE Activity Notification message
571
      UEActivityNotification = 155,
572
      /// UE Activity Acknowledge message
573
      UEActivityAcknowledge = 156,
574
      /// ISR Status message
575
      ISRStatus = 157,
576
      /// Create Forwarding Request message
577
      CreateForwardingRequest = 160,
578
      /// Create Forwarding Response message
579
      CreateForwardingResponse = 161,
580
      /// Suspend Notification message
581
      SuspendNotification = 162,
582
      /// Suspend Acknowledge message
583
      SuspendAcknowledge = 163,
584
      /// Resume Notification message
585
      ResumeNotification = 164,
586
      /// Resume Acknowledge message
587
      ResumeAcknowledge = 165,
588
      /// Create Indirect Data Tunnel Request message
589
      CreateIndirectDataTunnelRequest = 166,
590
      /// Create Indirect Data Tunnel Response message
591
      CreateIndirectDataTunnelResponse = 167,
592
      /// Delete Indirect Data Tunnel Request message
593
      DeleteIndirectDataTunnelRequest = 168,
594
      /// Delete Indirect Data Tunnel Response message
595
      DeleteIndirectDataTunnelResponse = 169,
596
      /// Release Access Bearers Request message
597
      ReleaseAccessBearersRequest = 170,
598
      /// Release Access Bearers Response message
599
      ReleaseAccessBearersResponse = 171,
600
      /// Downlink Data Notification message
601
      DownlinkDataNotification = 176,
602
      /// Downlink Data Acknowledge message
603
      DownlinkDataAcknowledge = 177,
604
      /// PGW Restart Notification message
605
      PGWRestartNotification = 179,
606
      /// PGW Restart Acknowledge message
607
      PGWRestartAcknowledge = 180,
608
      /// Update PDN Connection Request message
609
      UpdatePDNConnectionRequest = 200,
610
      /// Update PDN Connection Response message
611
      UpdatePDNConnectionResponse = 201,
612
      /// Modify Access Bearers Request message
613
      ModifyAccessBearersRequest = 211,
614
      /// Modify Access Bearers Response message
615
      ModifyAccessBearersResponse = 212,
616
      /// MMBS Session Start Request message
617
      MMBSSessionStartRequest = 231,
618
      /// MMBS Session Start Response message
619
      MMBSSessionStartResponse = 232,
620
      /// MMBS Session Update Request message
621
      MMBSSessionUpdateRequest = 233,
622
      /// MMBS Session Update Response message
623
      MMBSSessionUpdateResponse = 234,
624
      /// MMBS Session Stop Request message
625
      MMBSSessionStopRequest = 235,
626
      /// MMBS Session Stop Response message
627
      MMBSSessionStopResponse = 236
628
    };
629
630
    GtpV2MessageType() = default;
631
632
    // cppcheck-suppress noExplicitConstructor
633
    /// Construct GtpV2MessageType from Value enum
634
    /// @param[in] value the message type enum value
635
14.0k
    constexpr GtpV2MessageType(Value value) : m_Value(value)
636
14.0k
    {}
637
638
    /// @return A string representation of the message type
639
    std::string toString() const;
640
641
    /// A static method that creates GtpV2MessageType from an integer value
642
    /// @param[in] value The message type integer value
643
    /// @return The message type that corresponds to the integer value. If the integer value
644
    /// doesn't corresponds to any message type, GtpV2MessageType::Unknown is returned
645
    static GtpV2MessageType fromUintValue(uint8_t value);
646
647
    // Allow switch and comparisons.
648
    constexpr operator Value() const
649
7.53k
    {
650
7.53k
      return m_Value;
651
7.53k
    }
652
653
    // Prevent usage: if(GtpV2MessageType)
654
    explicit operator bool() const = delete;
655
656
  private:
657
    Value m_Value = GtpV2MessageType::Unknown;
658
  };
659
660
  /// @class GtpV2InformationElement
661
  /// A wrapper class for GTPv2 information elements (IE). This class does not create or modify IEs, but rather
662
  /// serves as a wrapper and provides useful methods for retrieving data from them
663
  class GtpV2InformationElement : public TLVRecord<uint8_t, uint16_t>
664
  {
665
  public:
666
    /// GTPv2 Information Element (IE) types as defined in 3GPP TS 29.274
667
    enum class Type : uint8_t
668
    {
669
      /// Unknown or reserved value
670
      Unknown = 0,
671
      /// International Mobile Subscriber Identity
672
      Imsi = 1,
673
      /// Indicates the result of a procedure
674
      Cause = 2,
675
      /// Recovery counter for GTP path management
676
      Recovery = 3,
677
      /// Session Transfer Number for SRVCC
678
      StnSr = 51,
679
      /// Access Point Name
680
      Apn = 71,
681
      /// Aggregate Maximum Bit Rate
682
      Ambr = 72,
683
      /// EPS Bearer ID
684
      Ebi = 73,
685
      /// IPv4/IPv6 Address
686
      IpAddress = 74,
687
      /// Mobile Equipment Identity (IMEI or IMEISV)
688
      Mei = 75,
689
      /// Mobile Station International Subscriber Directory Number
690
      Msisdn = 76,
691
      /// Indication flags for various features and capabilities
692
      Indication = 77,
693
      /// Protocol Configuration Options
694
      Pco = 78,
695
      /// PDN Address Allocation
696
      Paa = 79,
697
      /// Bearer Level Quality of Service
698
      BearerQos = 80,
699
      /// Flow Level Quality of Service
700
      FlowQos = 81,
701
      /// Radio Access Technology Type
702
      RatType = 82,
703
      /// Current PLMN and MME identifier
704
      ServingNetwork = 83,
705
      /// Bearer Traffic Flow Template
706
      BearerTft = 84,
707
      /// Traffic Aggregation Description
708
      Tad = 85,
709
      /// User Location Information
710
      Uli = 86,
711
      /// Fully Qualified TEID
712
      FTeid = 87,
713
      /// Temporary Mobile Subscriber Identity
714
      Tmsi = 88,
715
      /// Global Core Network ID
716
      GlobalCnId = 89,
717
      /// S103 PDN Data Forwarding Info
718
      S103PdnDataForwardingInfo = 90,
719
      /// S1-U Data Forwarding Info
720
      S1UDataForwardingInfo = 91,
721
      /// Delay Value in integer multiples of 50 milliseconds
722
      DelayValue = 92,
723
      /// Bearer Context
724
      BearerContext = 93,
725
      /// Charging ID for this PDP context
726
      ChargingId = 94,
727
      /// Charging Characteristics
728
      ChargingCharacteristics = 95,
729
      /// Trace Information
730
      TraceInformation = 96,
731
      /// Bearer Flags
732
      BearerFlags = 97,
733
      /// PDN Type (IPv4, IPv6, IPv4v6)
734
      PdnType = 99,
735
      /// Procedure Transaction ID
736
      Pti = 100,
737
      /// MM Context (GSM Key and Triplets)
738
      MmContext1 = 103,
739
      /// MM Context (UMTS Key, Used Cipher and Quintuplets)
740
      MmContext2 = 104,
741
      /// MM Context (GSM Key, Used Cipher and Quintuplets)
742
      MmContext3 = 105,
743
      /// MM Context (UMTS Key and Quintuplets)
744
      MmContext4 = 106,
745
      /// MM Context (EPS Security Context, Quadruplets and Quintuplets)
746
      MmContext5 = 107,
747
      /// MM Context (UMTS Key, Quadruplets and Quintuplets)
748
      MmContext6 = 108,
749
      /// PDN Connection
750
      PdnConnection = 109,
751
      /// PDU Numbers
752
      PduNumbers = 110,
753
      /// Packet TMSI
754
      PTmsi = 111,
755
      /// P-TMSI Signature
756
      PTmsiSignature = 112,
757
      /// Hop Counter
758
      HopCounter = 113,
759
      /// UE Time Zone
760
      UeTimeZone = 114,
761
      /// Trace Reference
762
      TraceReference = 115,
763
      /// Complete Request Message
764
      CompleteRequestMessage = 116,
765
      /// Globally Unique Temporary Identity
766
      Guti = 117,
767
      /// F-Container
768
      FContainer = 118,
769
      /// F-Cause
770
      FCause = 119,
771
      /// PLMN Identity
772
      PlmnId = 120,
773
      /// Target Identification
774
      TargetIdentification = 121,
775
      /// Packet Flow ID
776
      PacketFlowId = 123,
777
      /// RAB Context
778
      RabContext = 124,
779
      /// Source RNC PDCP Context Info
780
      SourceRncPdcpContextInfo = 125,
781
      /// Port Number
782
      PortNumber = 126,
783
      /// APN Restriction
784
      ApnRestriction = 127,
785
      /// Selection Mode
786
      SelectionMode = 128,
787
      /// Source Identification
788
      SourceIdentification = 129,
789
      /// Change Reporting Action
790
      ChangeReportingAction = 131,
791
      /// Fully Qualified PDN Connection Set Identifier
792
      FqCsid = 132,
793
      /// Channel Needed
794
      ChannelNeeded = 133,
795
      /// eMLPP Priority
796
      EmlppPriority = 134,
797
      /// Node Type
798
      NodeType = 135,
799
      /// Fully Qualified Domain Name
800
      Fqdn = 136,
801
      /// Transaction Identifier
802
      Ti = 137,
803
      /// MBMS Session Duration
804
      MbmsSessionDuration = 138,
805
      /// MBMS Service Area
806
      MbmsServiceArea = 139,
807
      /// MBMS Session Identifier
808
      MbmsSessionIdentifier = 140,
809
      /// MBMS Flow Identifier
810
      MbmsFlowIdentifier = 141,
811
      /// MBMS IP Multicast Distribution
812
      MbmsIpMulticastDistribution = 142,
813
      /// MBMS Distribution Acknowledge
814
      MbmsDistributionAcknowledge = 143,
815
      /// RF Selection Priority Index
816
      RfspIndex = 144,
817
      /// User CSG Information
818
      Uci = 145,
819
      /// CSG Information Reporting Action
820
      CsgInformationReportingAction = 146,
821
      /// CSG ID
822
      CsgId = 147,
823
      /// CSG Membership Indication
824
      Cmi = 148,
825
      /// Service Indicator
826
      ServiceIndicator = 149,
827
      /// Detach Type
828
      DetachType = 150,
829
      /// Local Distinguished Name
830
      Ldn = 151,
831
      /// Node Features
832
      NodeFeatures = 152,
833
      /// MBMS Time To Data Transfer
834
      MbmsTimeToDataTransfer = 153,
835
      /// Throttling
836
      Throttling = 154,
837
      /// Allocation Retention Priority
838
      Arp = 155,
839
      /// EPC Timer
840
      EpcTimer = 156,
841
      /// Signalling Priority Indication
842
      SignallingPriorityIndication = 157,
843
      /// Temporary Mobile Group Identity
844
      Tmgi = 158,
845
      /// Additional MM Context For SRVCC
846
      AdditionalMmContextForSrvcc = 159,
847
      /// Additional Flags For SRVCC
848
      AdditionalFlagsForSrvcc = 160,
849
      /// MDT Configuration
850
      MdtConfiguration = 162,
851
      /// Additional Protocol Configuration Options
852
      Apco = 163,
853
      /// Absolute Time of MBMS Data Transfer
854
      AbsoluteTimeOfMbmsDataTransfer = 164,
855
      /// H(e)NB Information Reporting
856
      HenbInformationReporting = 165,
857
      /// IPv4 Configuration Parameters
858
      Ipv4ConfigurationParameters = 166,
859
      /// Change To Report Flags
860
      ChangeToReportFlags = 167,
861
      /// Action Indication
862
      ActionIndication = 168,
863
      /// TWAN Identifier
864
      TwanIdentifier = 169,
865
      /// ULI Timestamp
866
      UliTimestamp = 170,
867
      /// MBMS Flags
868
      MbmsFlags = 171,
869
      /// RAN/NAS Cause
870
      RanNasCause = 172,
871
      /// CN Operator Selection Entity
872
      CnOperatorSelectionEntity = 173,
873
      /// Trusted WLAN Mode Indication
874
      Twmi = 174,
875
      /// Node Number
876
      NodeNumber = 175,
877
      /// Node Identifier
878
      NodeIdentifier = 176,
879
      /// Presence Reporting Area Action
880
      PresenceReportingAreaAction = 177,
881
      /// Presence Reporting Area Information
882
      PresenceReportingAreaInformation = 178,
883
      /// TWAN Identifier Timestamp
884
      TwanIdentifierTimestamp = 179,
885
      /// Overload Control Information
886
      OverloadControlInformation = 180,
887
      /// Load Control Information
888
      LoadControlInformation = 181,
889
      /// Metric
890
      Metric = 182,
891
      /// Sequence Number
892
      SequenceNumber = 183,
893
      /// APN and Relative Capacity
894
      ApnAndRelativeCapacity = 184,
895
      /// WLAN Offloadability Indication
896
      WlanOffloadabilityIndication = 185,
897
      /// Paging and Service Information
898
      PagingAndServiceInformation = 186,
899
      /// Integer Number
900
      IntegerNumber = 187,
901
      /// Millisecond Time Stamp
902
      MillisecondTimeStamp = 188,
903
      /// Monitoring Event Information
904
      MonitoringEventInformation = 189,
905
      /// ECGI List
906
      EcgiList = 190,
907
      /// Remote UE Context
908
      RemoteUeContext = 191,
909
      /// Remote User ID
910
      RemoteUserId = 192,
911
      /// Remote UE IP Information
912
      RemoteUeIpInformation = 193,
913
      /// CIoT Optimizations Support Indication
914
      CiotOptimizationsSupportIndication = 194,
915
      /// SCEF PDN Connection
916
      ScefPdnConnection = 195,
917
      /// Header Compression Configuration
918
      HeaderCompressionConfiguration = 196,
919
      /// Extended Protocol Configuration Options
920
      ExtendedPco = 197,
921
      /// Serving PLMN Rate Control
922
      ServingPlmnRateControl = 198,
923
      /// Counter
924
      Counter = 199,
925
      /// Mapped UE Usage Type
926
      MappedUeUsageType = 200,
927
      /// Secondary RAT Usage Data Report
928
      SecondaryRatUsageDataReport = 201,
929
      /// UP Function Selection Indication Flags
930
      UpFunctionSelectionIndicationFlags = 202,
931
      /// Maximum Packet Loss Rate
932
      MaximumPacketLossRate = 203,
933
      /// APN Rate Control Status
934
      ApnRateControlStatus = 204,
935
      /// Extended Trace Information
936
      ExtendedTraceInformation = 205,
937
      /// Monitoring Event Extension Information
938
      MonitoringEventExtensionInformation = 206,
939
      /// Additional RRM Policy Index
940
      AdditionalRrmPolicyIndex = 207,
941
      /// V2X Context
942
      V2xContext = 208,
943
      /// PC5 QoS Parameters
944
      Pc5QosParameters = 209,
945
      /// Services Authorized
946
      ServicesAuthorized = 210,
947
      /// Bit Rate
948
      BitRate = 211,
949
      /// PC5 QoS Flow
950
      Pc5QosFlow = 212,
951
      /// SGi PtP Tunnel Address
952
      SgiPtpTunnelAddress = 213
953
    };
954
955
    /// A c'tor for this class that gets a pointer to the IE raw data (byte array)
956
    /// @param[in] infoElementRawData A pointer to the IE raw data
957
0
    explicit GtpV2InformationElement(uint8_t* infoElementRawData) : TLVRecord(infoElementRawData)
958
0
    {}
959
960
    ~GtpV2InformationElement() override = default;
961
962
    /// @return The information element (IE) type
963
    GtpV2InformationElement::Type getIEType();
964
965
    /// @return The IE CR flag
966
    uint8_t getCRFlag();
967
968
    /// @return The IE instance value
969
    uint8_t getInstance();
970
971
    // implement abstract methods
972
973
    size_t getValueOffset() const override
974
0
    {
975
0
      return sizeof(uint8_t);
976
0
    }
977
978
    size_t getTotalSize() const override;
979
980
    size_t getDataSize() const override;
981
  };
982
983
  /// @class GtpV2InformationElementBuilder
984
  /// A class for building GTPv2 information elements (IE). This builder receives the IE parameters in its c'tor,
985
  /// builds the IE raw buffer and provides a build() method to get a GtpV2InformationElement object out of it
986
  class GtpV2InformationElementBuilder : public TLVRecordBuilder
987
  {
988
  public:
989
    /// A c'tor for building information elements (IE) which their value is a byte array. The
990
    /// GtpV2InformationElement object can be later retrieved by calling build().
991
    /// @param[in] infoElementType Information elements (IE) type
992
    /// @param[in] crFlag CR flag value
993
    /// @param[in] instance Instance value
994
    /// @param[in] infoElementValue A byte array of the IE value
995
    GtpV2InformationElementBuilder(GtpV2InformationElement::Type infoElementType, const std::bitset<4>& crFlag,
996
                                   const std::bitset<4>& instance, const std::vector<uint8_t>& infoElementValue);
997
998
    /// Build the GtpV2InformationElement object out of the parameters defined in the c'tor
999
    /// @return The GtpV2InformationElement object
1000
    GtpV2InformationElement build() const;
1001
1002
  private:
1003
    std::bitset<4> m_CRFlag;
1004
    std::bitset<4> m_Instance;
1005
  };
1006
1007
  /// @class GtpV2Layer
1008
  /// A class representing the GTPv2 defined in 3GPP TS 29.274
1009
  class GtpV2Layer : public Layer
1010
  {
1011
  public:
1012
20.8k
    ~GtpV2Layer() override = default;
1013
1014
    /// A constructor that creates the layer from an existing packet raw data
1015
    /// @param[in] data A pointer to the raw data
1016
    /// @param[in] dataLen Size of the data in bytes
1017
    /// @param[in] prevLayer A pointer to the previous layer
1018
    /// @param[in] packet A pointer to the Packet instance where layer will be stored in
1019
    GtpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
1020
20.8k
        : Layer(data, dataLen, prevLayer, packet, GTPv2)
1021
20.8k
    {}
1022
1023
    /// A constructor that creates a new GTPv2 message
1024
    /// @param messageType GTPv2 message type
1025
    /// @param sequenceNumber Message sequence number
1026
    /// @param setTeid Whether or not to set Tunnel Endpoint Identifier in this message
1027
    /// @param teid Tunnel Endpoint Identifier value. Only used if setTeid is set to true
1028
    /// @param setMessagePriority Whether or not to set Message Priority in this message
1029
    /// @param messagePriority Message Priority. Only used if setMessagePriority to true
1030
    GtpV2Layer(GtpV2MessageType messageType, uint32_t sequenceNumber, bool setTeid = false, uint32_t teid = 0,
1031
               bool setMessagePriority = false, std::bitset<4> messagePriority = 0);
1032
1033
    /// A static method that checks whether the port is considered as GTPv2
1034
    /// @param[in] port The port number to be checked
1035
    /// @return True if the port matches those associated with the GTPv2 protocol
1036
    static bool isGTPv2Port(uint16_t port)
1037
929k
    {
1038
929k
      return port == 2123;
1039
929k
    }
1040
1041
    /// A static method that takes a byte array and detects whether it is a GTPv2 message
1042
    /// @param[in] data A byte array
1043
    /// @param[in] dataSize The byte array size (in bytes)
1044
    /// @return True if the data is identified as GTPv2 message
1045
    static bool isDataValid(const uint8_t* data, size_t dataSize);
1046
1047
    /// @return The message type
1048
    GtpV2MessageType getMessageType() const;
1049
1050
    /// Set message type
1051
    /// @param type The message type to set
1052
    void setMessageType(const GtpV2MessageType& type);
1053
1054
    /// @return The message length as set in the layer. Note it is different from getHeaderLen() because the later
1055
    /// refers to the entire layers length, and this property excludes the mandatory part of the GTP-C header
1056
    /// (the first 4 octets)
1057
    uint16_t getMessageLength() const;
1058
1059
    /// @return True if there is another GTPv2 message piggybacking on this message (will appear as another
1060
    /// GtpV2Layer after this layer)
1061
    bool isPiggybacking() const;
1062
1063
    /// Get the Tunnel Endpoint Identifier (TEID) if exists
1064
    /// @return A pair of 2 values; the first value states whether TEID exists, and if it's true the second value
1065
    /// contains the TEID value
1066
    std::pair<bool, uint32_t> getTeid() const;
1067
1068
    /// Set Tunnel Endpoint Identifier (TEID)
1069
    /// @param teid The TEID value to set
1070
    void setTeid(uint32_t teid);
1071
1072
    /// Unset Tunnel Endpoint Identifier (TEID) if exists in the layer (otherwise does nothing)
1073
    void unsetTeid();
1074
1075
    /// @return The sequence number
1076
    uint32_t getSequenceNumber() const;
1077
1078
    /// Set the sequence number
1079
    /// @param sequenceNumber The sequence number value to set
1080
    void setSequenceNumber(uint32_t sequenceNumber);
1081
1082
    /// Get the Message Property if exists
1083
    /// @return A pair of 2 values; the first value states whether Message Priority exists, and if it's true
1084
    /// the second value contains the Message Priority value
1085
    std::pair<bool, uint8_t> getMessagePriority() const;
1086
1087
    /// Set Message Priority
1088
    /// @param messagePriority The Message Priority value to set
1089
    void setMessagePriority(const std::bitset<4>& messagePriority);
1090
1091
    /// Unset Message Priority if exists in the layer (otherwise does nothing)
1092
    void unsetMessagePriority();
1093
1094
    /// @return The first GTPv2 Information Element (IE). If there are no IEs the returned value will contain
1095
    /// a logical null (GtpV2InformationElement#isNull() == true)
1096
    GtpV2InformationElement getFirstInformationElement() const;
1097
1098
    /// Get the GTPv2 Information Element (IE) that comes after a given IE. If the given IE was the last one, the
1099
    /// returned value will contain a logical null (GtpV2InformationElement#isNull() == true)
1100
    /// @param[in] infoElement A given GTPv2 Information Element
1101
    /// @return A GtpV2InformationElement object containing the IE that comes next, or logical null if the given
1102
    /// IE: (1) is the last one; (2) contains a logical null or (3) doesn't belong to this packet
1103
    GtpV2InformationElement getNextInformationElement(GtpV2InformationElement infoElement) const;
1104
1105
    /// Get a GTPv2 Information Element (IE) by type
1106
    /// @param[in] infoElementType GTPv2 Information Element (IE) type
1107
    /// @return A GtpV2InformationElement object containing the first IE that matches this type, or logical
1108
    /// null (GtpV2InformationElement#isNull() == true) if no such IE found
1109
    GtpV2InformationElement getInformationElement(GtpV2InformationElement::Type infoElementType) const;
1110
1111
    /// @return The number of GTPv2 Information Elements (IEs) in this layer
1112
    size_t getInformationElementCount() const;
1113
1114
    /// Add a new Information Element (IE) at the end of the layer
1115
    /// @param[in] infoElementBuilder A GtpV2InformationElementBuilder object that contains the requested
1116
    /// IE data to add
1117
    /// @return A GtpV2InformationElement object containing the newly added IE data or logical null
1118
    /// (GtpV2InformationElement#isNull() == true) if addition failed
1119
    GtpV2InformationElement addInformationElement(const GtpV2InformationElementBuilder& infoElementBuilder);
1120
1121
    /// Add a new Information Element (IE) after an existing one
1122
    /// @param[in] infoElementBuilder A GtpV2InformationElementBuilder object that contains the requested
1123
    /// IE data to add
1124
    /// @param[in] infoElementType The IE type which the newly added option will come after
1125
    /// @return A GtpV2InformationElement object containing the newly added IE data or logical null
1126
    /// (GtpV2InformationElement#isNull() == true) if addition failed
1127
    GtpV2InformationElement addInformationElementAfter(const GtpV2InformationElementBuilder& infoElementBuilder,
1128
                                                       GtpV2InformationElement::Type infoElementType);
1129
1130
    /// Remove an existing Information Element (IE) from the layer
1131
    /// @param[in] infoElementType The IE type to remove
1132
    /// @return True if the IE was successfully removed or false if type wasn't found or if removal failed
1133
    bool removeInformationElement(GtpV2InformationElement::Type infoElementType);
1134
1135
    /// Remove all Information Elements (IE) in this layer
1136
    /// @return True if all IEs were successfully removed or false if removal failed for some reason
1137
    bool removeAllInformationElements();
1138
1139
    // implement abstract methods
1140
1141
    /// Identifies if the next layer is GTPv2 piggyback. Otherwise sets PayloadLayer
1142
    void parseNextLayer() override;
1143
1144
    /// @return The size of the GTPv2 header including its Information Elements (IE)
1145
    size_t getHeaderLen() const override;
1146
1147
    /// Computes the piggybacking flag by checking if the next layer is also a GTPv2 message
1148
    void computeCalculateFields() override;
1149
1150
    std::string toString() const override;
1151
1152
    OsiModelLayer getOsiModelLayer() const override
1153
3.31k
    {
1154
3.31k
      return OsiModelTransportLayer;
1155
3.31k
    }
1156
1157
    /// @struct SerializedFields
1158
    /// Fields written by GtpV2Layer's serializeLayer(), in addition to Layer::SerializedFields
1159
    struct SerializedFields : Layer::SerializedFields
1160
    {
1161
      /// @return All field descriptors for GtpV2Layer
1162
      static std::vector<FieldDescriptor> all()
1163
0
      {
1164
0
        auto result = Layer::SerializedFields::all();
1165
0
        std::initializer_list<FieldDescriptor> extra{
1166
0
          MessageType, MessageTypeName, MessageLength,   Piggybacking,
1167
0
          Teid,        SequenceNumber,  MessagePriority, InformationElements
1168
0
        };
1169
0
        std::copy(extra.begin(), extra.end(), std::back_inserter(result));
1170
0
        return result;
1171
0
      }
1172
1173
      /// @brief GTPv2 message type, as the raw integer value from the header
1174
      static const FieldDescriptor MessageType;
1175
      /// @brief GTPv2 message type name, as returned by GtpV2MessageType::toString()
1176
      static const FieldDescriptor MessageTypeName;
1177
      /// @brief Message length field in bytes (host byte order), excluding the first 4 octets of the header
1178
      static const FieldDescriptor MessageLength;
1179
      /// @brief Whether another GTPv2 message is piggybacked on this one, as a boolean
1180
      static const FieldDescriptor Piggybacking;
1181
      /// @brief Tunnel endpoint identifier in hexadecimal (host byte order), only when the TEID flag is set
1182
      static const FieldDescriptor Teid;
1183
      /// @brief 24-bit sequence number (host byte order)
1184
      static const FieldDescriptor SequenceNumber;
1185
      /// @brief 4-bit message priority, only when the message priority flag is set
1186
      static const FieldDescriptor MessagePriority;
1187
      /// @brief List of information element (IE) types present in the message
1188
      static const FieldDescriptor InformationElements;
1189
      /// @brief A single information element (IE) type, as an integer
1190
      static const FieldDescriptor InformationElement;
1191
    };
1192
1193
  protected:
1194
    void serializeLayer(ObjectScope& serializer) const override;
1195
1196
  private:
1197
#pragma pack(push, 1)
1198
    struct gtpv2_basic_header
1199
    {
1200
#if (BYTE_ORDER == LITTLE_ENDIAN)
1201
      uint8_t unused : 2, messagePriorityPresent : 1, teidPresent : 1, piggybacking : 1, version : 3;
1202
#else
1203
      uint8_t version : 3, piggybacking : 1, teidPresent : 1, messagePriorityPresent : 1, unused : 2;
1204
#endif
1205
      uint8_t messageType;
1206
      uint16_t messageLength;
1207
    };
1208
#pragma pack(pop)
1209
1210
    TLVRecordReader<GtpV2InformationElement> m_IEReader;
1211
1212
    gtpv2_basic_header* getHeader() const
1213
45.7k
    {
1214
45.7k
      return reinterpret_cast<gtpv2_basic_header*>(m_Data);
1215
45.7k
    }
1216
1217
    uint8_t* getIEBasePtr() const;
1218
1219
    size_t getIEDataLen(const uint8_t* basePtr) const;
1220
1221
    GtpV2InformationElement addInformationElementAt(const GtpV2InformationElementBuilder& infoElementBuilder,
1222
                                                    int offset);
1223
  };
1224
}  // namespace pcpp