Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/header/IPv6Extensions.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PACKETPP_IPV6_EXTENSION
2
#define PACKETPP_IPV6_EXTENSION
3
4
#include <vector>
5
#include "IpAddress.h"
6
#include "Layer.h"
7
#include "TLVData.h"
8
9
/// @file
10
11
/**
12
 * \namespace pcpp
13
 * \brief The main namespace for the PcapPlusPlus lib
14
 */
15
namespace pcpp
16
{
17
18
  /**
19
   * @class IPv6Extension
20
   * A base class for all supported IPv6 extensions. This class is abstract, meaning it cannot be instantiated or copied
21
   * (has private c'tor and copy c'tor)
22
   */
23
  class IPv6Extension
24
  {
25
    friend class IPv6Layer;
26
27
  public:
28
29
    /**
30
     * An enum representing all supported IPv6 extension types
31
     */
32
    enum IPv6ExtensionType
33
    {
34
      /** Hop-By-Hop extension type */
35
      IPv6HopByHop = 0,
36
      /** Routing extension type */
37
      IPv6Routing = 43,
38
      /** IPv6 fragmentation extension type */
39
      IPv6Fragmentation = 44,
40
      /** Authentication Header extension type */
41
      IPv6AuthenticationHdr = 51,
42
      /** Destination extension type */
43
      IPv6Destination = 60,
44
      /** Unknown or unsupported extension type */
45
      IPv6ExtensionUnknown = 255
46
    };
47
48
    /**
49
     * @return The size of extension in bytes, meaning (for most extensions): 8 * ([headerLen field] + 1)
50
     */
51
18.6k
    virtual size_t getExtensionLen() const { return 8 * (getBaseHeader()->headerLen+1); }
52
53
    /**
54
     * @return The type of the extension
55
     */
56
1.67k
    IPv6ExtensionType getExtensionType() const { return m_ExtType; }
57
58
    /**
59
     * A destructor for this class
60
     */
61
    virtual ~IPv6Extension();
62
63
    /**
64
     * @return A pointer to the next header or NULL if the extension is the last one
65
     */
66
14.7k
    IPv6Extension* getNextHeader() const { return m_NextHeader; }
67
68
  protected:
69
70
    struct ipv6_ext_base_header
71
    {
72
      uint8_t nextHeader;
73
      uint8_t headerLen;
74
    };
75
76
    // protected c'tor
77
    IPv6Extension(IDataContainer* dataContainer, size_t offset) :
78
9.76k
      m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(dataContainer), m_Offset(offset), m_ShadowData(NULL) {}
79
80
    // protected empty c'tor
81
    IPv6Extension() :
82
0
      m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(NULL), m_Offset(0), m_ShadowData(NULL) {}
83
84
    // protected assignment operator
85
    IPv6Extension& operator=(const IPv6Extension& other);
86
87
    uint8_t* getDataPtr() const;
88
89
    void initShadowPtr(size_t size);
90
91
30.6k
    ipv6_ext_base_header* getBaseHeader() const { return (ipv6_ext_base_header*)getDataPtr(); }
92
93
5.01k
    void setNextHeader(IPv6Extension* nextHeader) { m_NextHeader = nextHeader; }
94
95
    IPv6Extension* m_NextHeader;
96
    IPv6ExtensionType m_ExtType;
97
98
  private:
99
    IDataContainer* m_DataContainer;
100
    size_t m_Offset;
101
    uint8_t* m_ShadowData;
102
103
  };
104
105
106
107
  /**
108
   * @class IPv6FragmentationHeader
109
   * Represents an IPv6 fragmentation extension header and allows easy access to all fragmentation parameters
110
   */
111
  class IPv6FragmentationHeader : public IPv6Extension
112
  {
113
    friend class IPv6Layer;
114
115
  public:
116
117
    /**
118
     * @struct ipv6_frag_header
119
     * A struct representing IPv6 fragmentation header
120
     */
121
    struct ipv6_frag_header
122
    {
123
      /** Next header type */
124
      uint8_t nextHeader;
125
      /** Fragmentation header size is fixed 8 bytes, so len is always zero */
126
      uint8_t headerLen;
127
      /** Offset, in 8-octet units, relative to the start of the fragmentable part of the original packet
128
       * plus 1-bit indicating if more fragments will follow */
129
      uint16_t fragOffsetAndFlags;
130
      /** packet identification value. Needed for reassembly of the original packet */
131
      uint32_t id;
132
    };
133
134
    /**
135
     * A c'tor for creating a new IPv6 fragmentation extension object not bounded to a packet. Useful for adding new extensions to an
136
     * IPv6 layer with IPv6Layer#addExtension()
137
     * @param[in] fragId Fragmentation ID
138
     * @param[in] fragOffset Fragmentation offset
139
     * @param[in] lastFragment Indicates whether this fragment is the last one
140
     */
141
    IPv6FragmentationHeader(uint32_t fragId, uint16_t fragOffset, bool lastFragment);
142
143
    /**
144
     * Get a pointer to the fragmentation header. Notice the returned pointer points directly to the data, so every change will modify
145
     * the actual packet data
146
     * @return A pointer to the @ref ipv6_frag_header
147
     */
148
0
    ipv6_frag_header* getFragHeader() const { return (ipv6_frag_header*)getDataPtr(); }
149
150
    /**
151
     * @return True if this is the first fragment (which usually contains the L4 header), false otherwise
152
     */
153
    bool isFirstFragment() const;
154
155
    /**
156
     * @return True if this is the last fragment, false otherwise
157
     */
158
    bool isLastFragment() const;
159
160
    /**
161
     * @return True if the "more fragments" bit is set, meaning more fragments are expected to follow this fragment
162
     */
163
    bool isMoreFragments() const;
164
165
    /**
166
     * @return The fragment offset
167
     */
168
    uint16_t getFragmentOffset() const;
169
170
  private:
171
172
    IPv6FragmentationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset)
173
669
    {
174
669
      m_ExtType = IPv6Fragmentation;
175
669
    }
176
177
  };
178
179
180
  /**
181
   * An abstract base class for Hop-By-Hop and Destination IPv6 extensions which their structure contains Type-Length-Value (TLV) options.
182
   * This class provides access to these options and their data as well as methods to create new options. Notice this class is abstract
183
   * and cannot be instantiated
184
   */
185
  class IPv6TLVOptionHeader : public IPv6Extension
186
  {
187
    friend class IPv6Layer;
188
189
  public:
190
191
    /**
192
     * @class IPv6Option
193
     * A class representing a Type-Length-Value (TLV) options that are used inside Hop-By-Hop and Destinations IPv6
194
     * extensions. This class does not create or modify IPv6 option records, but rather serves as a wrapper and
195
     * provides useful methods for retrieving data from them
196
     */
197
    class IPv6Option : public TLVRecord<uint8_t, uint8_t>
198
    {
199
    public:
200
201
      static const uint8_t Pad0OptionType = 0;
202
      static const uint8_t PadNOptionType = 1;
203
204
      /**
205
       * A c'tor for this class that gets a pointer to the option raw data (byte array)
206
       * @param[in] optionRawData A pointer to the attribute raw data
207
       */
208
0
      explicit IPv6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
209
210
      /**
211
       * A d'tor for this class, currently does nothing
212
       */
213
0
      ~IPv6Option() { }
214
215
      // implement abstract methods
216
217
      size_t getTotalSize() const
218
0
      {
219
0
        if (m_Data->recordType == Pad0OptionType)
220
0
          return sizeof(uint8_t);
221
222
0
        return (size_t)(m_Data->recordLen + sizeof(uint16_t));
223
0
      }
224
225
      size_t getDataSize() const
226
0
      {
227
0
        if (m_Data->recordType == Pad0OptionType)
228
0
          return (size_t)0;
229
230
0
        return (size_t)m_Data->recordLen;
231
0
      }
232
    };
233
234
235
    /**
236
     * @class IPv6TLVOptionBuilder
237
     * A class for building IPv6 Type-Length-Value (TLV) options. This builder receives the option parameters in its c'tor,
238
     * builds the option raw buffer and provides a method to build a IPv6Option object out of it
239
     */
240
    class IPv6TLVOptionBuilder : public TLVRecordBuilder
241
    {
242
    public:
243
244
      /**
245
       * A c'tor for building IPv6 TLV options which their value is a byte array. The IPv6Option object can later
246
       * be retrieved by calling build()
247
       * @param[in] optType IPv6 option type
248
       * @param[in] optValue A buffer containing the option value. This buffer is read-only and isn't modified in any way
249
       * @param[in] optValueLen Option value length in bytes
250
       */
251
      IPv6TLVOptionBuilder(uint8_t optType, const uint8_t* optValue, uint8_t optValueLen) :
252
0
        TLVRecordBuilder(optType, optValue, optValueLen) { }
253
254
      /**
255
       * A c'tor for building IPv6 TLV options which have a 1-byte value. The IPv6Option object can later be retrieved
256
       * by calling build()
257
       * @param[in] optType IPv6 option type
258
       * @param[in] optValue A 1-byte option value
259
       */
260
      IPv6TLVOptionBuilder(uint8_t optType, uint8_t optValue) :
261
0
        TLVRecordBuilder(optType, optValue) { }
262
263
      /**
264
       * A c'tor for building IPv6 TLV options which have a 2-byte value. The IPv6Option object can later be retrieved
265
       * by calling build()
266
       * @param[in] optType IPv6 option type
267
       * @param[in] optValue A 2-byte option value
268
       */
269
      IPv6TLVOptionBuilder(uint8_t optType, uint16_t optValue) :
270
0
        TLVRecordBuilder(optType, optValue) { }
271
272
      /**
273
       * A copy c'tor that creates an instance of this class out of another instance and copies all the data from it
274
       * @param[in] other The instance to copy data from
275
       */
276
      IPv6TLVOptionBuilder(const IPv6TLVOptionBuilder& other) :
277
0
        TLVRecordBuilder(other) {}
278
279
      /**
280
       * Assignment operator that copies all data from another instance of IPv6TLVOptionBuilder
281
       * @param[in] other The instance to assign from
282
       */
283
      IPv6TLVOptionBuilder& operator=(const IPv6TLVOptionBuilder& other)
284
0
      {
285
0
        TLVRecordBuilder::operator=(other);
286
0
        return *this;
287
0
      }
288
289
      /**
290
       * Build the IPv6Option object out of the parameters defined in the c'tor
291
       * @return The IPv6Option object
292
       */
293
      IPv6Option build() const;
294
    };
295
296
    /**
297
     * Retrieve an option by its type
298
     * @param[in] optionType Option type
299
     * @return An IPv6Option object that wraps the option data. If option isn't found a logical NULL is returned
300
     * (IPv6Option#isNull() == true)
301
     */
302
    IPv6Option getOption(uint8_t optionType) const;
303
304
    /**
305
     * @return An IPv6Option that wraps the first option data or logical NULL (IPv6Option#isNull() == true) if no options exist
306
     */
307
    IPv6Option getFirstOption() const;
308
309
    /**
310
     * Returns a pointer to the option that comes after the option given as the parameter
311
     * @param[in] option A pointer to an option instance
312
     * @return An IPv6Option object that wraps the option data. In the following cases logical NULL (IPv6Option#isNull() == true)
313
     * is returned:
314
     * (1) input parameter is out-of-bounds for this extension or
315
     * (2) the next option doesn't exist or
316
     * (3) the input option is NULL
317
     */
318
    IPv6Option getNextOption(IPv6Option& option) const;
319
320
    /**
321
     * @returns The number of options this IPv6 extension contains
322
     */
323
    size_t getOptionCount() const;
324
325
  protected:
326
327
    /** A private c'tor to keep this object from being constructed */
328
    explicit IPv6TLVOptionHeader(const std::vector<IPv6TLVOptionBuilder>& options);
329
330
    IPv6TLVOptionHeader(IDataContainer* dataContainer, size_t offset);
331
332
  private:
333
334
    TLVRecordReader<IPv6Option> m_OptionReader;
335
  };
336
337
338
339
  /**
340
   * @class IPv6HopByHopHeader
341
   * Represents IPv6 Hop-By-Hop extension header and allows easy access to all of its data including the TLV options stored
342
   */
343
  class IPv6HopByHopHeader : public IPv6TLVOptionHeader
344
  {
345
    friend class IPv6Layer;
346
347
  public:
348
349
    /**
350
     * A c'tor for creating a new IPv6 Hop-By-Hop extension object not bounded to a packet. Useful for adding new extensions to an
351
     * IPv6 layer with IPv6Layer#addExtension()
352
     * @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that will be stored in the
353
     * extension data. Notice this vector is read-only and its content won't be modified
354
     */
355
0
    explicit IPv6HopByHopHeader(const std::vector<IPv6TLVOptionBuilder>& options) : IPv6TLVOptionHeader(options) { m_ExtType = IPv6HopByHop; }
356
357
  private:
358
359
6.52k
    IPv6HopByHopHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) { m_ExtType = IPv6HopByHop; }
360
  };
361
362
363
364
  /**
365
   * @class IPv6DestinationHeader
366
   * Represents IPv6 destination extension header and allows easy access to all of its data including the TLV options stored in it
367
   */
368
  class IPv6DestinationHeader : public IPv6TLVOptionHeader
369
  {
370
    friend class IPv6Layer;
371
372
  public:
373
374
    /**
375
     * A c'tor for creating a new IPv6 destination extension object not bounded to a packet. Useful for adding new extensions to an
376
     * IPv6 layer with IPv6Layer#addExtension()
377
     * @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that will be stored in the
378
     * extension data. Notice this vector is read-only and its content won't be modified
379
     */
380
0
    explicit IPv6DestinationHeader(const std::vector<IPv6TLVOptionBuilder>& options) : IPv6TLVOptionHeader(options) { m_ExtType = IPv6Destination; }
381
382
  private:
383
384
731
    IPv6DestinationHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) { m_ExtType = IPv6Destination; }
385
  };
386
387
388
389
  /**
390
   * @class IPv6RoutingHeader
391
   * Represents IPv6 routing extension header and allows easy access to all of its data
392
   */
393
  class IPv6RoutingHeader : public IPv6Extension
394
  {
395
    friend class IPv6Layer;
396
397
  public:
398
399
    /**
400
     * @struct ipv6_routing_header
401
     * A struct representing the fixed part of the IPv6 routing extension header
402
     */
403
    struct ipv6_routing_header
404
    {
405
      /** Next header type */
406
      uint8_t nextHeader;
407
      /** The length of this header, in multiples of 8 octets, not including the first 8 octets */
408
      uint8_t headerLen;
409
      /** A value representing the routing type */
410
      uint8_t routingType;
411
      /** Number of nodes this packet still has to visit before reaching its final destination */
412
      uint8_t segmentsLeft;
413
    };
414
415
    /**
416
     * A c'tor for creating a new IPv6 routing extension object not bounded to a packet. Useful for adding new extensions to an
417
     * IPv6 layer with IPv6Layer#addExtension()
418
     * @param[in] routingType Routing type value (will be written to ipv6_routing_header#routingType field)
419
     * @param[in] segmentsLeft Segments left value (will be written to ipv6_routing_header#segmentsLeft field)
420
     * @param[in] additionalRoutingData A pointer to a buffer containing the additional routing data for this extension. Notice this
421
     * buffer is read-only and its content isn't modified
422
     * @param[in] additionalRoutingDataLen The length of the additional routing data buffer
423
     */
424
    IPv6RoutingHeader(uint8_t routingType, uint8_t segmentsLeft, const uint8_t* additionalRoutingData, size_t additionalRoutingDataLen);
425
426
    /**
427
     * Get a pointer to the fixed part of the routing header. Notice the return pointer points directly to the data, so every change will modify
428
     * the actual packet data
429
     * @return A pointer to the @ref ipv6_routing_header
430
     */
431
0
    ipv6_routing_header* getRoutingHeader() const { return (ipv6_routing_header*)getDataPtr(); }
432
433
    /**
434
     * @return A pointer to the buffer containing the additional routing data for this extension. Notice that any change in this buffer
435
     * will lead to a change in the extension data
436
     */
437
    uint8_t* getRoutingAdditionalData() const;
438
439
    /**
440
     * @return The length of the additional routing parameters buffer
441
     */
442
    size_t getRoutingAdditionalDataLength() const;
443
444
    /**
445
     * In many cases the additional routing data is actually IPv6 address(es). This method converts the raw buffer data into an IPv6 address
446
     * @param[in] offset An offset in the additional routing buffer pointing to where the IPv6 address begins. In some cases there are
447
     * multiple IPv6 addresses in the additional routing data buffer so this offset points to where the request IPv6 address begins. Also,
448
     * even if there is only one IPv6 address in this buffer, sometimes it isn't written in the beginning of the buffer, so the offset points
449
     * to where the IPv6 address begins. This is an optional parameter and the default offset is 0
450
     * @return The IPv6 address stored in the additional routing data buffer from the offset defined by the user. If offset is out-of-bounds
451
     * of the extension of doesn't have 16 bytes (== the length of IPv6 address) until the end of the buffer - IPv6Address#Zero is returned
452
     */
453
    IPv6Address getRoutingAdditionalDataAsIPv6Address(size_t offset = 0) const;
454
455
  private:
456
457
1.39k
    IPv6RoutingHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6Routing; }
458
459
  };
460
461
462
  /**
463
   * @class IPv6AuthenticationHeader
464
   * Represents IPv6 authentication header extension (used in IPSec protocol) and allows easy access to all of its data
465
   */
466
  class IPv6AuthenticationHeader : public IPv6Extension
467
  {
468
    friend class IPv6Layer;
469
470
  public:
471
472
    /**
473
     * @struct ipv6_authentication_header
474
     * A struct representing the fixed part of the IPv6 authentication header extension
475
     */
476
    struct ipv6_authentication_header
477
    {
478
      /** Next header type */
479
      uint8_t nextHeader;
480
      /** The length of this Authentication Header in 4-octet units, minus 2. For example, an AH value of 4
481
       * equals: [ 3×(32-bit fixed-length AH fields) + 3×(32-bit ICV fields) − 2 ] and thus an AH value of 4 means 24 octets */
482
      uint8_t headerLen;
483
      /** Reserved bytes, all zeros */
484
      uint16_t reserved;
485
      /** Arbitrary value which is used (together with the destination IP address) to identify the security association of the receiving party */
486
      uint32_t securityParametersIndex;
487
      /** A monotonic strictly increasing sequence number (incremented by 1 for every packet sent) */
488
      uint32_t sequenceNumber;
489
    };
490
491
    /**
492
     * A c'tor for creating a new IPv6 authentication header extension object not bounded to a packet. Useful for adding new extensions to an
493
     * IPv6 layer with IPv6Layer#addExtension()
494
     * @param[in] securityParametersIndex Security Parameters Index (SPI) value (will be written to ipv6_authentication_header#securityParametersIndex field)
495
     * @param[in] sequenceNumber Sequence number value (will be written to ipv6_authentication_header#sequenceNumber field)
496
     * @param[in] integrityCheckValue A pointer to a buffer containing the integrity check value (ICV) data for this extension. Notice this
497
     * pointer is read-only and its content isn't modified in any way
498
     * @param[in] integrityCheckValueLen The length of the integrity check value (ICV) buffer
499
     */
500
    IPv6AuthenticationHeader(uint32_t securityParametersIndex, uint32_t sequenceNumber, const uint8_t* integrityCheckValue, size_t integrityCheckValueLen);
501
502
    /**
503
     * Get a pointer to the fixed part of the authentication header. Notice the return pointer points directly to the data, so every change
504
     * will modify the actual packet data
505
     * @return A pointer to the @ref ipv6_authentication_header
506
     */
507
0
    ipv6_authentication_header* getAuthHeader() const { return (ipv6_authentication_header*)getDataPtr(); }
508
509
    /**
510
     * @return A pointer to the buffer containing the integrity check value (ICV) for this extension. Notice that any change in this buffer
511
     * will lead to a change in the extension data
512
     */
513
    uint8_t* getIntegrityCheckValue() const;
514
515
    /**
516
     * @return The length of the integrity check value (ICV) buffer
517
     */
518
    size_t getIntegrityCheckValueLength() const;
519
520
    // overridden methods
521
522
    /**
523
     * In the authentication header the extension length is calculated in a different way than other extensions. The
524
     * calculation is: [ 4 * (ipv6_authentication_header#headerLen + 2) ]
525
     * @return The length of this extension
526
     */
527
878
    size_t getExtensionLen() const { return 4 * (getBaseHeader()->headerLen+2); }
528
529
  private:
530
531
439
    IPv6AuthenticationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6AuthenticationHdr; }
532
  };
533
534
}
535
536
#endif // PACKETPP_IPV6_EXTENSION