Coverage Report

Created: 2024-02-25 06:29

/src/PcapPlusPlus/Packet++/header/GtpLayer.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "Layer.h"
4
5
/// @file
6
7
8
/**
9
 * \namespace pcpp
10
 * \brief The main namespace for the PcapPlusPlus lib
11
 */
12
namespace pcpp
13
{
14
15
#pragma pack(push, 1)
16
  /**
17
   * @struct gtpv1_header
18
   * GTP v1 common message header
19
   */
20
  struct gtpv1_header
21
  {
22
#if (BYTE_ORDER == LITTLE_ENDIAN)
23
    /** A 1-bit value that states whether there is a N-PDU number optional field */
24
    uint8_t npduNumberFlag:1,
25
    /** A 1-bit value that states whether there is a Sequence Number optional field */
26
    sequenceNumberFlag:1,
27
    /** A 1-bit value that states whether there is an extension header optional field */
28
    extensionHeaderFlag:1,
29
    /** Reserved bit */
30
    reserved:1,
31
    /** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */
32
    protocolType:1,
33
    /** GTP version */
34
    version:3;
35
#else
36
    /** GTP version */
37
    uint8_t version:3,
38
    /** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */
39
    protocolType:1,
40
    /** Reserved bit */
41
    reserved:1,
42
    /** A 1-bit value that states whether there is an extension header optional field */
43
    extensionHeaderFlag:1,
44
    /** A 1-bit value that states whether there is a Sequence Number optional field */
45
    sequenceNumberFlag:1,
46
    /** A 1-bit value that states whether there is a N-PDU number optional field */
47
    npduNumberFlag:1;
48
#endif
49
    /** An 8-bit field that indicates the type of GTP message */
50
    uint8_t messageType;
51
52
    /** A 16-bit field that indicates the length of the payload in bytes (rest of the packet following the mandatory 8-byte GTP header). Includes the optional fields */
53
    uint16_t messageLength;
54
55
    /** Tunnel endpoint identifier - A 32-bit(4-octet) field used to multiplex different connections in the same GTP tunnel */
56
    uint32_t teid;
57
  };
58
59
#pragma pack(pop)
60
61
  /**
62
   * An enum representing the possible GTP v1 message types.
63
   * All of the message types except for #GtpV1_GPDU are considered GTP-C messages. #GtpV1_GPDU is considered a GTP-U message
64
   */
65
  enum GtpV1MessageType
66
  {
67
    /** GTPv1 Message Type Unknown */
68
    GtpV1_MessageTypeUnknown = 0,
69
    /** Echo Request */
70
    GtpV1_EchoRequest = 1,
71
    /** Echo Response */
72
    GtpV1_EchoResponse = 2,
73
    /** Version Not Supported */
74
    GtpV1_VersionNotSupported = 3,
75
    /** Node Alive Request */
76
    GtpV1_NodeAliveRequest = 4,
77
    /** Node Alive Response */
78
    GtpV1_NodeAliveResponse = 5,
79
    /** Redirection Request */
80
    GtpV1_RedirectionRequest = 6,
81
    /** Create PDP Context Request */
82
    GtpV1_CreatePDPContextRequest = 7,
83
    /** Create PDP Context Response */
84
    GtpV1_CreatePDPContextResponse = 16,
85
    /** Update PDP Context Request */
86
    GtpV1_UpdatePDPContextRequest = 17,
87
    /** Update PDP Context Response */
88
    GtpV1_UpdatePDPContextResponse = 18,
89
    /** Delete PDP Context Request */
90
    GtpV1_DeletePDPContextRequest = 19,
91
    /** Delete PDP Context Response */
92
    GtpV1_DeletePDPContextResponse = 20,
93
    /** Initiate PDP Context Activation Request */
94
    GtpV1_InitiatePDPContextActivationRequest = 22,
95
    /** Initiate PDP Context Activation Response */
96
    GtpV1_InitiatePDPContextActivationResponse = 23,
97
    /** Error Indication */
98
    GtpV1_ErrorIndication = 26,
99
    /** PDU Notification Request */
100
    GtpV1_PDUNotificationRequest = 27,
101
    /** PDU Notification Response */
102
    GtpV1_PDUNotificationResponse = 28,
103
    /** PDU Notification Reject Request */
104
    GtpV1_PDUNotificationRejectRequest = 29,
105
    /** PDU Notification Reject Response */
106
    GtpV1_PDUNotificationRejectResponse = 30,
107
    /** Supported Extensions Header Notification */
108
    GtpV1_SupportedExtensionsHeaderNotification = 31,
109
    /** Send Routing for GPRS Request */
110
    GtpV1_SendRoutingforGPRSRequest = 32,
111
    /** Send Routing for GPRS Response */
112
    GtpV1_SendRoutingforGPRSResponse = 33,
113
    /** Failure Report Request */
114
    GtpV1_FailureReportRequest = 34,
115
    /** Failure Report Response */
116
    GtpV1_FailureReportResponse = 35,
117
    /** Note MS Present Request */
118
    GtpV1_NoteMSPresentRequest = 36,
119
    /** Note MS Present Response */
120
    GtpV1_NoteMSPresentResponse = 37,
121
    /** Identification Request */
122
    GtpV1_IdentificationRequest = 38,
123
    /** Identification Response */
124
    GtpV1_IdentificationResponse = 39,
125
    /** SGSN Context Request */
126
    GtpV1_SGSNContextRequest = 50,
127
    /** SGSN Context Response */
128
    GtpV1_SGSNContextResponse = 51,
129
    /** SGSN Context Acknowledge */
130
    GtpV1_SGSNContextAcknowledge = 52,
131
    /** Forward Relocation Request */
132
    GtpV1_ForwardRelocationRequest = 53,
133
    /** Forward Relocation Response */
134
    GtpV1_ForwardRelocationResponse = 54,
135
    /** Forward Relocation Complete */
136
    GtpV1_ForwardRelocationComplete = 55,
137
    /** Relocation Cancel Request */
138
    GtpV1_RelocationCancelRequest = 56,
139
    /** Relocation Cancel Response */
140
    GtpV1_RelocationCancelResponse = 57,
141
    /** Forward SRNS Context */
142
    GtpV1_ForwardSRNSContext = 58,
143
    /** Forward Relocation Complete Acknowledge */
144
    GtpV1_ForwardRelocationCompleteAcknowledge = 59,
145
    /** Forward SRNS Context Acknowledge */
146
    GtpV1_ForwardSRNSContextAcknowledge = 60,
147
    /** UE Registration Request */
148
    GtpV1_UERegistrationRequest = 61,
149
    /** UE Registration Response */
150
    GtpV1_UERegistrationResponse = 62,
151
    /** RAN Information Relay */
152
    GtpV1_RANInformationRelay = 70,
153
    /** MBMS Notification Request */
154
    GtpV1_MBMSNotificationRequest = 96,
155
    /** MBMS Notification Response */
156
    GtpV1_MBMSNotificationResponse = 97,
157
    /** MBMS Notification Reject Request */
158
    GtpV1_MBMSNotificationRejectRequest = 98,
159
    /** MBMS Notification Reject Response */
160
    GtpV1_MBMSNotificationRejectResponse = 99,
161
    /** Create MBMS Notification Request */
162
    GtpV1_CreateMBMSNotificationRequest = 100,
163
    /** Create MBMS Notification Response */
164
    GtpV1_CreateMBMSNotificationResponse = 101,
165
    /** Update MBMS Notification Request */
166
    GtpV1_UpdateMBMSNotificationRequest = 102,
167
    /** Update MBMS Notification Response */
168
    GtpV1_UpdateMBMSNotificationResponse = 103,
169
    /** Delete MBMS Notification Request */
170
    GtpV1_DeleteMBMSNotificationRequest = 104,
171
    /** Delete MBMS Notification Response */
172
    GtpV1_DeleteMBMSNotificationResponse = 105,
173
    /** MBMS Registration Request */
174
    GtpV1_MBMSRegistrationRequest = 112,
175
    /** MBMS Registration Response */
176
    GtpV1_MBMSRegistrationResponse = 113,
177
    /** MBMS De-Registration Request */
178
    GtpV1_MBMSDeRegistrationRequest = 114,
179
    /** MBMS De-Registration Response */
180
    GtpV1_MBMSDeRegistrationResponse = 115,
181
    /** MBMS Session Start Request */
182
    GtpV1_MBMSSessionStartRequest = 116,
183
    /** MBMS Session Start Response */
184
    GtpV1_MBMSSessionStartResponse = 117,
185
    /** MBMS Session Stop Request */
186
    GtpV1_MBMSSessionStopRequest = 118,
187
    /** MBMS Session Stop Response */
188
    GtpV1_MBMSSessionStopResponse = 119,
189
    /** MBMS Session Update Request */
190
    GtpV1_MBMSSessionUpdateRequest = 120,
191
    /** MBMS Session Update Response */
192
    GtpV1_MBMSSessionUpdateResponse = 121,
193
    /** MS Info Change Request */
194
    GtpV1_MSInfoChangeRequest = 128,
195
    /** MS Info Change Response */
196
    GtpV1_MSInfoChangeResponse = 129,
197
    /** Data Record Transfer Request */
198
    GtpV1_DataRecordTransferRequest = 240,
199
    /** Data Record Transfer Response */
200
    GtpV1_DataRecordTransferResponse = 241,
201
    /** End Marker */
202
    GtpV1_EndMarker = 254,
203
    /** G-PDU */
204
    GtpV1_GPDU = 255
205
  };
206
207
208
  /**
209
   * @class GtpV1Layer
210
   * A class representing the [GTP v1](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol) protocol.
211
   */
212
  class GtpV1Layer : public Layer
213
  {
214
  private:
215
    struct gtpv1_header_extra
216
    {
217
      uint16_t sequenceNumber;
218
      uint8_t npduNumber;
219
      uint8_t nextExtensionHeader;
220
    };
221
222
    gtpv1_header_extra* getHeaderExtra() const;
223
224
    void init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum);
225
226
  public:
227
228
    /**
229
     * @class GtpExtension
230
     * A class that represents [GTP header extensions](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol)
231
     */
232
    class GtpExtension
233
    {
234
      friend class GtpV1Layer;
235
236
    private:
237
      uint8_t* m_Data;
238
      size_t m_DataLen;
239
      uint8_t m_ExtType;
240
241
      GtpExtension(uint8_t* data, size_t dataLen, uint8_t type);
242
243
      void setNextHeaderType(uint8_t nextHeaderType);
244
245
      static GtpExtension createGtpExtension(uint8_t* data, size_t dataLen, uint8_t extType, uint16_t content);
246
247
    public:
248
249
      /**
250
       * An empty c'tor that creates an empty object, meaning one that isNull() returns "true")
251
       */
252
      GtpExtension();
253
254
      /**
255
       * A copy c'tor for this class
256
       * @param[in] other The GTP extension to copy from
257
       */
258
      GtpExtension(const GtpExtension& other);
259
260
      /**
261
       * An assignment operator for this class
262
       * @param[in] other The extension to assign from
263
       * @return A reference to the assignee
264
       */
265
      GtpExtension& operator=(const GtpExtension& other);
266
267
      /**
268
       * @return Instances of this class may be initialized as empty, meaning they don't contain any data. In
269
       * these cases this method returns true
270
       */
271
      bool isNull() const;
272
273
      /**
274
       * @return The extension type. If the object is empty a value of zero is returned
275
       */
276
      uint8_t getExtensionType() const;
277
278
      /**
279
       * @return The total length of the extension including the length and next extension type fields.
280
       * If the object is empty a value of zero is returned
281
       */
282
      size_t getTotalLength() const;
283
284
      /**
285
       * @return The length of the extension's content, excluding the extension length and next extension type fields.
286
       * If the object is empty a value of zero is returned
287
       */
288
      size_t getContentLength() const;
289
290
      /**
291
       * @return A byte array that includes the extension's content. The length of this array can be determined by
292
       * getContentLength(). If the object is empty a null value is returned
293
       */
294
      uint8_t* getContent() const;
295
296
      /**
297
       * @return The extension type of the next header. If there are no more header extensions or if this object is empty
298
       * a value of zero is returned
299
       */
300
      uint8_t getNextExtensionHeaderType() const;
301
302
      /**
303
       * @return An instance of this class representing the next extension header, if exists in the message. If there are
304
       * no more header extensions or if this object is empty an empty instance of GtpExtension is returned, meaning
305
       * one that GtpExtension#isNull() returns "true"
306
       */
307
      GtpExtension getNextExtension() const;
308
    }; // GtpExtension
309
310
0
    virtual ~GtpV1Layer() {}
311
312
     /** A constructor that creates the layer from an existing packet raw data
313
     * @param[in] data A pointer to the raw data
314
     * @param[in] dataLen Size of the data in bytes
315
     * @param[in] prevLayer A pointer to the previous layer
316
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
317
     */
318
33.5k
    GtpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = GTPv1; }
319
320
    /**
321
     * A constructor that creates a new GTPv1 layer and sets the message type and the TEID value
322
     * @param[in] messageType The GTPv1 message type to be set in the newly created layer
323
     * @param[in] teid The TEID value to be set in the newly created layer
324
     */
325
    GtpV1Layer(GtpV1MessageType messageType, uint32_t teid);
326
327
    /**
328
     * A constructor that creates a new GTPv1 layer and sets various parameters
329
     * @param[in] messageType The GTPv1 message type to be set in the newly created layer
330
     * @param[in] teid The TEID value to be set in the newly created layer
331
     * @param[in] setSeqNum A flag indicating whether to set a sequence number. If set to "false" then the parameter "seqNum" will be ignored
332
     * @param[in] seqNum The sequence number to be set in the newly created later. If "setSeqNum" is set to false this parameter will be ignored
333
     * @param[in] setNpduNum A flag indicating whether to set the N-PDU number. If set to "false" then the parameter "npduNum" will be ignored
334
     * @param[in] npduNum The N-PDU number to be set in the newly created later. If "setNpduNum" is set to false this parameter will be ignored
335
     */
336
    GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum);
337
338
    /**
339
     * A static method that takes a byte array and detects whether it is a GTP v1 message
340
     * @param[in] data A byte array
341
     * @param[in] dataSize The byte array size (in bytes)
342
     * @return True if the data is identified as GTP v1 message (GTP-C or GTP-U)
343
     */
344
    static bool isGTPv1(const uint8_t* data, size_t dataSize);
345
346
    /**
347
     * @return The GTP v1 common header structure. Notice this points directly to the data, so every change will change the actual packet data
348
     */
349
151k
    gtpv1_header* getHeader() const { return (gtpv1_header*)m_Data; }
350
351
    /**
352
     * Get the sequence number if exists on the message (sequence number is an optional field in GTP messages)
353
     * @param[out] seqNumber Set with the sequence number value if exists in the layer. Otherwise remains unchanged
354
     * @return True if the sequence number field exists in layer, in which case seqNumber is set with the value.
355
     * Or false otherwise
356
     */
357
    bool getSequenceNumber(uint16_t& seqNumber) const;
358
359
    /**
360
     * Set a sequence number
361
     * @param[in] seqNumber The sequence number to set
362
     * @return True if the value was set successfully, false otherwise. In case of failure a corresponding error message will be written to log
363
     */
364
    bool setSequenceNumber(const uint16_t seqNumber);
365
366
    /**
367
     * Get the N-PDU number if exists on the message (N-PDU number is an optional field in GTP messages)
368
     * @param[out] npduNum Set with the N-PDU number value if exists in the layer. Otherwise remains unchanged
369
     * @return True if the N-PDU number field exists in layer, in which case npduNum is set with the value.
370
     * Or false otherwise
371
     */
372
    bool getNpduNumber(uint8_t& npduNum) const;
373
374
    /**
375
     * Set an N-PDU number
376
     * @param[in] npduNum The N-PDU number to set
377
     * @return True if the value was set successfully, false otherwise. In case of failure a corresponding error message will be written to log
378
     */
379
    bool setNpduNumber(const uint8_t npduNum);
380
381
    /**
382
     * Get the type of the next header extension if exists on the message (extensions are optional in GTP messages)
383
     * @param[out] nextExtType Set with the next header extension type if exists in layer. Otherwise remains unchanged
384
     * @return True if the message contains header extensions, in which case nextExtType is set to the next
385
     * header extension type. If there are no header extensions false is returned and nextExtType remains unchanged
386
     */
387
    bool getNextExtensionHeaderType(uint8_t& nextExtType) const;
388
389
    /**
390
     * @return An object that represents the next extension header, if exists in the message. If there are no extensions
391
     * an empty object is returned, meaning an object which GtpExtension#isNull() returns "true"
392
     */
393
    GtpExtension getNextExtension() const;
394
395
    /**
396
     * Add a GTPv1 header extension. It is assumed that the extension is 4 bytes in length and its content is 2 bytes in length.
397
     * If you need a different content size please reach out to me. This method takes care of extending the layer to make room for
398
     * the new extension and also sets the relevant flags and fields
399
     * @param[in] extensionType The type of the new extension
400
     * @param[in] extensionContent A 2-byte long content
401
     * @return An object representing the newly added extension. If there was an error adding the extension a null object will be
402
     * returned (meaning GtpExtension#isNull() will return "true") and a corresponding error message will be written to log
403
     */
404
    GtpExtension addExtension(uint8_t extensionType, uint16_t extensionContent);
405
406
    /**
407
     * @return The message type of this GTP packet
408
     */
409
    GtpV1MessageType getMessageType() const;
410
411
    /**
412
     * @return A string representation of the packet's message type
413
     */
414
    std::string getMessageTypeAsString() const;
415
416
    /**
417
     * @return True if this is a GTP-U message, false otherwise
418
     */
419
    bool isGTPUMessage() const;
420
421
    /**
422
     * @return True if this is a GTP-C message, false otherwise
423
     */
424
    bool isGTPCMessage() const;
425
426
    /**
427
     * A static method that checks whether the port is considered as GTPv1
428
     * @param[in] port The port number to be checked
429
     * @return True if the port matches those associated with the BGP protocol
430
     */
431
264k
    static bool isGTPv1Port(uint16_t port) { return port == 2152 /* GTP-U */ || port == 2123 /* GTP-C */; }
432
433
434
    // implement abstract methods
435
436
    /**
437
     * Identifies the following next layers for GTP-U packets: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer
438
     */
439
    void parseNextLayer();
440
441
    /**
442
     * @return The size of the GTP header. For GTP-C packets the size is determined by the value of
443
     * gtpv1_header#messageLength and for GTP-U the size only includes the GTP header itself (meaning
444
     * the size of gtpv1_header plus the size of the optional fields such as sequence number, N-PDU
445
     * or extensions if exist)
446
     */
447
    size_t getHeaderLen() const;
448
449
    /**
450
     * Calculate the following fields:
451
     * - gtpv1_header#messageLength
452
     */
453
    void computeCalculateFields();
454
455
    std::string toString() const;
456
457
4.65k
    OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; }
458
  };
459
}