Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/header/GreLayer.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PACKETPP_GRE_LAYER
2
#define PACKETPP_GRE_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
  /**
17
   * @struct gre_basic_header
18
   * Represents GRE basic protocol header (common for GREv0 and GREv1)
19
   */
20
#pragma pack(push, 1)
21
  struct gre_basic_header
22
  {
23
#if (BYTE_ORDER == LITTLE_ENDIAN)
24
    /** Number of additional encapsulations which are permitted. 0 is the default value */
25
    uint8_t recursionControl:3,
26
    /** Strict source routing bit (GRE v0 only) */
27
        strictSourceRouteBit:1,
28
    /** Set if sequence number exists */
29
        sequenceNumBit:1,
30
    /** Set if key exists */
31
        keyBit:1,
32
    /** Set if routing exists (GRE v0 only) */
33
        routingBit:1,
34
    /** Set if checksum exists (GRE v0 only) */
35
        checksumBit:1;
36
#else
37
    /** Set if checksum exists (GRE v0 only) */
38
    uint8_t checksumBit:1,
39
    /** Set if routing exists (GRE v0 only) */
40
        routingBit:1,
41
    /** Set if key exists */
42
        keyBit:1,
43
    /** Set if sequence number exists */
44
        sequenceNumBit:1,
45
    /** Strict source routing bit (GRE v0 only) */
46
        strictSourceRouteBit:1,
47
    /** Number of additional encapsulations which are permitted. 0 is the default value */
48
        recursionControl:3;
49
#endif
50
#if (BYTE_ORDER == LITTLE_ENDIAN)
51
    /** GRE version - can be 0 or 1 */
52
    uint8_t version:3,
53
    /** Reserved */
54
        flags:4,
55
    /** Set if acknowledgment number is set (GRE v1 only) */
56
        ackSequenceNumBit:1;
57
#else
58
    /** Set if acknowledgment number is set (GRE v1 only) */
59
    uint8_t ackSequenceNumBit:1,
60
    /** Reserved */
61
        flags:4,
62
    /** GRE version - can be 0 or 1 */
63
        version:3;
64
#endif
65
66
    /** Protocol type of the next layer */
67
    uint16_t protocol;
68
  };
69
#pragma pack(pop)
70
71
72
  /**
73
   * @struct gre1_header
74
   * Represents GREv1 protocol header
75
   */
76
#pragma pack(push, 1)
77
  struct gre1_header : gre_basic_header
78
  {
79
    /** Size of the payload not including the GRE header */
80
    uint16_t payloadLength;
81
    /** Contains the Peer's Call ID for the session to which this packet belongs */
82
    uint16_t callID;
83
  };
84
#pragma pack(pop)
85
86
87
  /**
88
   * @struct ppp_pptp_header
89
   * Represents PPP layer that comes after GREv1 as part of PPTP protocol
90
   */
91
#pragma pack(push, 1)
92
  struct ppp_pptp_header
93
  {
94
    /** Broadcast address */
95
    uint8_t address;
96
    /** Control byte */
97
    uint8_t control;
98
    /** Protocol type of the next layer (see PPP_* macros at PPPoELayer.h) */
99
    uint16_t protocol;
100
  };
101
#pragma pack(pop)
102
103
104
  /**
105
   * @class GreLayer
106
   * Abstract base class for GRE layers (GREv0Layer and GREv1Layer). Cannot be instantiated and contains common logic for derived classes
107
   */
108
  class GreLayer : public Layer
109
  {
110
  public:
111
112
0
    virtual ~GreLayer() {}
113
114
    /**
115
     * A static method that determines the GRE version of GRE layer raw data by looking at the gre_basic_header#version
116
     * field
117
     * @param[in] greData GRE layer raw data
118
     * @param[in] greDataLen Size of raw data
119
     * @return ::GREv0 or ::GREv1 values if raw data is GREv0 or GREv1 (accordingly) or ::UnknownProtocol otherwise
120
     */
121
    static ProtocolType getGREVersion(uint8_t* greData, size_t greDataLen);
122
123
    /**
124
     * Get sequence number value if field exists in layer
125
     * @param[out] seqNumber The returned sequence number value if exists in layer. Else remain unchanged
126
     * @return True if sequence number field exists in layer. In this case seqNumber will be filled with the value.
127
     * Or false if sequence number field doesn't exist in layer
128
     */
129
    bool getSequenceNumber(uint32_t& seqNumber) const;
130
131
    /**
132
     * Set sequence number value. If field already exists (gre_basic_header#sequenceNumBit is set) then only the new
133
     * value is set. If field doesn't exist it will be added to the layer, gre_basic_header#sequenceNumBit will be set
134
     * and the new value will be set
135
     * @param[in] seqNumber The sequence number value to set
136
     * @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer)
137
     */
138
    bool setSequenceNumber(uint32_t seqNumber);
139
140
    /**
141
     * Unset sequence number and remove it from the layer
142
     * @return True if managed to unset successfully or false (and error log) if sequence number wasn't set in the first
143
     * place or if didn't manage to remove it from the layer
144
     */
145
    bool unsetSequenceNumber();
146
147
148
    // implement abstract methods
149
150
    /**
151
     * Currently identifies the following next layers:
152
     *   IPv4Layer, IPv6Layer, VlanLayer, MplsLayer, PPP_PPTPLayer, EthLayer, EthDot3Layer
153
     * Otherwise sets PayloadLayer
154
     */
155
    void parseNextLayer();
156
157
    /**
158
     * @return Size of GRE header (may change if optional fields are added or removed)
159
     */
160
    size_t getHeaderLen() const;
161
162
10.4k
    OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; }
163
164
  protected:
165
10.4k
    GreLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { }
166
167
0
    GreLayer() {}
168
169
    enum GreField
170
    {
171
      GreChecksumOrRouting = 0,
172
      GreKey = 1,
173
      GreSeq = 2,
174
      GreAck = 3
175
    };
176
177
    uint8_t* getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const;
178
179
    void computeCalculateFieldsInner();
180
  };
181
182
183
  /**
184
   * @class GREv0Layer
185
   * Represents a GRE version 0 protocol. Limitation: currently this layer doesn't support GRE routing information parsing
186
   * and editing. So if a GREv0 packet includes routing information it won't be parse correctly. I didn't add it because
187
   * of lack of time, but if you need it please tell me and I'll add it
188
   */
189
  class GREv0Layer : public GreLayer
190
  {
191
  public:
192
193
     /** A constructor that creates the layer from an existing packet raw data
194
     * @param[in] data A pointer to the raw data
195
     * @param[in] dataLen Size of the data in bytes
196
     * @param[in] prevLayer A pointer to the previous layer
197
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
198
     */
199
8.38k
    GREv0Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : GreLayer(data, dataLen, prevLayer, packet) { m_Protocol = GREv0; }
200
201
    /**
202
     * A constructor that creates a new GREv0 header and allocates the data
203
     */
204
    GREv0Layer();
205
206
0
    virtual ~GREv0Layer() {}
207
208
    /**
209
     * Get a pointer to the basic GRE header containing only non-optional fields. Notice this points directly to the data,
210
     * so every change will change the actual packet data. Also please notice that changing the set bits
211
     * (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit, gre_basic_header#routingBit,
212
     * gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using the proper set or unset methods (such
213
     * as setChecksum(), unsetChecksum(), etc.) may result to wrong calculation of header length and really weird bugs.
214
     * Please avoid doing so
215
     * @return A pointer to the gre_basic_header
216
     */
217
0
    gre_basic_header* getGreHeader() const { return (gre_basic_header*)m_Data; }
218
219
    /**
220
     * Get checksum value if field exists in layer
221
     * @param[out] checksum The returned checksum value if exists in layer. Else remain unchanged
222
     * @return True if checksum field exists in layer. In this case checksum parameter will be filled with the value.
223
     * Or false if checksum field doesn't exist in layer
224
     */
225
    bool getChecksum(uint16_t& checksum);
226
227
    /**
228
     * Set checksum value. If checksum or offset fields already exist (gre_basic_header#checksumBit or gre_basic_header#routingBit are set)
229
     * then only the new value is set. If both fields don't exist a new 4-byte value will be added to the layer,
230
     * gre_basic_header#checksumBit will be set (gre_basic_header#routingBit will remain unset), the new checksum value
231
     * will be set and offset value will be set to 0. The reason both fields are added is that GREv0 protocol states
232
     * both of them or none of them should exist on packet (even if only one of the bits are set)
233
     * @param[in] checksum The checksum value to set
234
     * @return True if managed to set the value/s successfully, or false otherwise (if couldn't extend the layer)
235
     */
236
    bool setChecksum(uint16_t checksum);
237
238
    /**
239
     * Unset checksum and possibly remove it from the layer. It will be removed from the layer only if gre_basic_header#routingBit
240
     * is not set as well. Otherwise checksum field will remain on packet with value of 0
241
     * @return True if managed to unset successfully or false (and error log) if checksum wasn't set in the first
242
     * place or if didn't manage to remove it from the layer
243
     */
244
    bool unsetChecksum();
245
246
    /**
247
     * Get offset value if field exists in layer. Notice there is no setOffset() method as GRE routing information isn't
248
     * supported yet (see comment on class description)
249
     * @param[out] offset The returned offset value if exists in layer. Else remain unchanged
250
     * @return True if offset field exists in layer. In this case offset parameter will be filled with the value.
251
     * Or false if offset field doesn't exist in layer
252
     */
253
    bool getOffset(uint16_t& offset) const;
254
255
    /**
256
     * Get key value if field exists in layer
257
     * @param[out] key The returned key value if exists in layer. Else remain unchanged
258
     * @return True if key field exists in layer. In this case key parameter will be filled with the value.
259
     * Or false if key field doesn't exist in layer
260
     */
261
    bool getKey(uint32_t& key) const;
262
263
    /**
264
     * Set key value. If field already exists (gre_basic_header#keyBit is set) then only the new value is set.
265
     * If field doesn't exist it will be added to the layer, gre_basic_header#keyBit will be set
266
     * and the new value will be set
267
     * @param[in] key The key value to set
268
     * @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer)
269
     */
270
    bool setKey(uint32_t key);
271
272
    /**
273
     * Unset key and remove it from the layer
274
     * @return True if managed to unset successfully or false (and error log) if key wasn't set in the first
275
     * place or if didn't manage to remove it from the layer
276
     */
277
    bool unsetKey();
278
279
280
    // implement abstract methods
281
282
283
    /**
284
     * Calculate the following fields:
285
     * - gre_basic_header#protocol
286
     * - GRE checksum field (if exists in packet)
287
     */
288
    void computeCalculateFields();
289
290
    std::string toString() const;
291
292
  };
293
294
295
  /**
296
   * @class GREv1Layer
297
   * Represents a GRE version 1 protocol
298
   */
299
  class GREv1Layer : public GreLayer
300
  {
301
  public:
302
303
     /** A constructor that creates the layer from an existing packet raw data
304
     * @param[in] data A pointer to the raw data
305
     * @param[in] dataLen Size of the data in bytes
306
     * @param[in] prevLayer A pointer to the previous layer
307
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
308
     */
309
2.09k
    GREv1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : GreLayer(data, dataLen, prevLayer, packet) { m_Protocol = GREv1; }
310
311
    /**
312
     * A constructor that creates a new GREv1 header and allocates the data
313
     * @param[in] callID The call ID to set
314
     */
315
    explicit GREv1Layer(uint16_t callID);
316
317
0
    virtual ~GREv1Layer() {}
318
319
    /**
320
     * Get a pointer to the basic GREv1 header containing all non-optional fields. Notice this points directly to the data, so every change will change the actual
321
     * packet data. Also please notice that changing the set bits (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit,
322
     * gre_basic_header#routingBit, gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using the proper set or unset methods
323
     * (such as setAcknowledgmentNum(), unsetSequenceNumber(), etc.) may result to wrong calculation of header length or illegal GREv1 packet and
324
     * to some really weird bugs. Please avoid doing so
325
     * @return A pointer to the gre1_header
326
     */
327
0
    gre1_header* getGreHeader() const { return (gre1_header*)m_Data; }
328
329
    /**
330
     * Get acknowledgment (ack) number value if field exists in layer
331
     * @param[out] ackNum The returned ack number value if exists in layer. Else remain unchanged
332
     * @return True if ack number field exists in layer. In this case ackNum will be filled with the value.
333
     * Or false if ack number field doesn't exist in layer
334
     */
335
    bool getAcknowledgmentNum(uint32_t& ackNum) const;
336
337
    /**
338
     * Set acknowledgment (ack) number value. If field already exists (gre_basic_header#ackSequenceNumBit is set)
339
     * then only the new value is set. If field doesn't exist it will be added to the layer,
340
     * gre_basic_header#ackSequenceNumBit will be set and the new value will be set
341
     * @param[in] ackNum The ack number value to set
342
     * @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer)
343
     */
344
    bool setAcknowledgmentNum(uint32_t ackNum);
345
346
    /**
347
     * Unset acknowledgment (ack) number and remove it from the layer
348
     * @return True if managed to unset successfully or false (and error log) if ack number wasn't set in the first
349
     * place or if didn't manage to remove it from the layer
350
     */
351
    bool unsetAcknowledgmentNum();
352
353
354
    // implement abstract methods
355
356
    /**
357
     * Calculate the following fields:
358
     * - gre1_header#payloadLength
359
     * - gre_basic_header#protocol
360
     */
361
    void computeCalculateFields();
362
363
    std::string toString() const;
364
365
  };
366
367
368
  /**
369
   * @class PPP_PPTPLayer
370
   * Represent a PPP (point-to-point) protocol header that comes after GREv1 header, as part of PPTP - Point-to-Point Tunneling Protocol
371
   */
372
  class PPP_PPTPLayer : public Layer
373
  {
374
  public:
375
    /**
376
     * A constructor that creates the layer from an existing packet raw data
377
     * @param[in] data A pointer to the raw data (will be casted to @ref ppp_pptp_header)
378
     * @param[in] dataLen Size of the data in bytes
379
     * @param[in] prevLayer A pointer to the previous layer
380
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
381
     */
382
2.94k
    PPP_PPTPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = PPP_PPTP; }
383
384
    /**
385
     * A constructor that allocates a new PPP-PPTP header
386
     * @param[in] address Address field
387
     * @param[in] control Control field
388
     */
389
    PPP_PPTPLayer(uint8_t address, uint8_t control);
390
391
0
    ~PPP_PPTPLayer() {}
392
393
    /**
394
     * Get a pointer to the PPP-PPTP header. Notice this points directly to the data, so every change will change the actual packet data
395
     * @return A pointer to the @ref ppp_pptp_header
396
     */
397
2.58k
    ppp_pptp_header* getPPP_PPTPHeader() const { return (ppp_pptp_header*)m_Data; }
398
399
400
    // implement abstract methods
401
402
    /**
403
     * Currently identifies the following next layers: IPv4Layer, IPv6Layer. Otherwise sets PayloadLayer
404
     */
405
    void parseNextLayer();
406
407
    /**
408
     * @return The size of @ref ppp_pptp_header
409
     */
410
2.94k
    size_t getHeaderLen() const { return sizeof(ppp_pptp_header); }
411
412
    /**
413
     * Calculate the following fields:
414
     * - ppp_pptp_header#protocol
415
     */
416
    void computeCalculateFields();
417
418
0
    std::string toString() const { return "PPP for PPTP Layer"; }
419
420
2.94k
    OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; }
421
422
  };
423
424
} // namespace pcpp
425
426
#endif /* PACKETPP_GRE_LAYER */