Coverage Report

Created: 2023-01-17 06:15

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