Coverage Report

Created: 2024-02-25 06:29

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