Coverage Report

Created: 2023-01-17 06:15

/src/PcapPlusPlus/Packet++/header/DhcpV6Layer.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef PACKETPP_DHCPV6_LAYER
2
#define PACKETPP_DHCPV6_LAYER
3
4
#include "Layer.h"
5
#include "TLVData.h"
6
7
/// @file
8
9
/**
10
 * \namespace pcpp
11
 * \brief The main namespace for the PcapPlusPlus lib
12
 */
13
namespace pcpp
14
{
15
  /**
16
   * DHCPv6 message types
17
   */
18
  enum DhcpV6MessageType
19
  {
20
    /** Unknown message type */
21
    DHCPV6_UNKNOWN_MSG_TYPE    = 0,
22
    /** Solicit message type (Client to Server) */
23
    DHCPV6_SOLICIT             = 1,
24
    /** Advertise message type (Server to Client) */
25
    DHCPV6_ADVERTISE           = 2,
26
    /** Request message type (Client to Server) */
27
    DHCPV6_REQUEST             = 3,
28
    /** Confirm message type (Client to Server) */
29
    DHCPV6_CONFIRM             = 4,
30
    /** Renew message type (Client to Server) */
31
    DHCPV6_RENEW               = 5,
32
    /** Rebind message type (Client to Server) */
33
    DHCPV6_REBIND              = 6,
34
    /** Reply message type (Server to Client) */
35
    DHCPV6_REPLY               = 7,
36
    /** Release message type (Client to Server) */
37
    DHCPV6_RELEASE             = 8,
38
    /** Decline message type (Client to Server) */
39
    DHCPV6_DECLINE             = 9,
40
    /** Reconfigure message type (Server to Client) */
41
    DHCPV6_RECONFIGURE         = 10,
42
    /** Information-Request message type (Client to Server) */
43
    DHCPV6_INFORMATION_REQUEST = 11,
44
    /** Relay-Forward message type (Relay agent to Server) */
45
    DHCPV6_RELAY_FORWARD       = 12,
46
    /** Relay-Reply message type (Server to Relay agent) */
47
    DHCPV6_RELAY_REPLY         = 13
48
  };
49
50
  /**
51
   * DHCPv6 option types.
52
   * Resources for more information:
53
   * - https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781118073810.app2
54
   * - https://datatracker.ietf.org/doc/html/rfc5970
55
   * - https://datatracker.ietf.org/doc/html/rfc6607
56
   * - https://datatracker.ietf.org/doc/html/rfc8520
57
   */
58
  enum DhcpV6OptionType
59
  {
60
    /** Unknown option type */
61
    DHCPV6_OPT_UNKNOWN                  = 0,
62
    /** Client Identifier (DUID of client) */
63
    DHCPV6_OPT_CLIENTID                 = 1,
64
    /** Server Identifier (DUID of server) */
65
    DHCPV6_OPT_SERVERID                 = 2,
66
    /** Identity Association for Non-temporary addresses */
67
    DHCPV6_OPT_IA_NA                    = 3,
68
    /** Identity Association for Temporary addresses */
69
    DHCPV6_OPT_IA_TA                    = 4,
70
    /** IA Address option */
71
    DHCPV6_OPT_IAADDR                   = 5,
72
    /** Option Request Option */
73
    DHCPV6_OPT_ORO                      = 6,
74
    /** Preference setting */
75
    DHCPV6_OPT_PREFERENCE               = 7,
76
    /** The amount of time since the client began the current DHCP transaction */
77
    DHCPV6_OPT_ELAPSED_TIME             = 8,
78
    /** The DHCP message being relayed by a relay agent */
79
    DHCPV6_OPT_RELAY_MSG                = 9,
80
    /** Authentication  information */
81
    DHCPV6_OPT_AUTH                     = 11,
82
    /** Server unicast */
83
    DHCPV6_OPT_UNICAST                  = 12,
84
    /** Status code */
85
    DHCPV6_OPT_STATUS_CODE              = 13,
86
    /** Rapid commit */
87
    DHCPV6_OPT_RAPID_COMMIT             = 14,
88
    /** User class */
89
    DHCPV6_OPT_USER_CLASS               = 15,
90
    /** Vendor class */
91
    DHCPV6_OPT_VENDOR_CLASS             = 16,
92
    /** Vendor specific information */
93
    DHCPV6_OPT_VENDOR_OPTS              = 17,
94
    /** Interface ID */
95
    DHCPV6_OPT_INTERFACE_ID             = 18,
96
    /** Reconfigure Message */
97
    DHCPV6_OPT_RECONF_MSG               = 19,
98
    /** Reconfigure Accept */
99
    DHCPV6_OPT_RECONF_ACCEPT            = 20,
100
    /** SIP Servers Domain Name */
101
    DHCPV6_OPT_SIP_SERVERS_D            = 21,
102
    /** SIP Servers IPv6 Address List */
103
    DHCPV6_OPT_SIP_SERVERS_A            = 22,
104
    /** DNS Recursive Name Server */
105
    DHCPV6_OPT_DNS_SERVERS              = 23,
106
    /** Domain Search List */
107
    DHCPV6_OPT_DOMAIN_LIST              = 24,
108
    /** Identity Association for Prefix Delegation */
109
    DHCPV6_OPT_IA_PD                    = 25,
110
    /** IA_PD Prefix */
111
    DHCPV6_OPT_IAPREFIX                 = 26,
112
    /** Network Information Service (NIS) Servers */
113
    DHCPV6_OPT_NIS_SERVERS              = 27,
114
    /** Network Information Service v2 (NIS+) Servers */
115
    DHCPV6_OPT_NISP_SERVERS             = 28,
116
    /** Network Information Service (NIS) domain name */
117
    DHCPV6_OPT_NIS_DOMAIN_NAME          = 29,
118
    /** Network Information Service v2 (NIS+) domain name */
119
    DHCPV6_OPT_NISP_DOMAIN_NAME         = 30,
120
    /** Simple Network Time Protocol (SNTP) servers */
121
    DHCPV6_OPT_SNTP_SERVERS             = 31,
122
    /** Information Refresh */
123
    DHCPV6_OPT_INFORMATION_REFRESH_TIME = 32,
124
    /** Broadcast and Multicast Service (BCMCS) Domain Name List */
125
    DHCPV6_OPT_BCMCS_SERVER_D           = 33,
126
    /** Broadcast and Multicast Service (BCMCS) IPv6 Address List */
127
    DHCPV6_OPT_BCMCS_SERVER_A           = 34,
128
    /** Geographical location in civic (e.g., postal) format */
129
    DHCPV6_OPT_GEOCONF_CIVIC            = 36,
130
    /** Relay Agent Remote ID */
131
    DHCPV6_OPT_REMOTE_ID                = 37,
132
    /** Relay Agent Subscriber ID */
133
    DHCPV6_OPT_SUBSCRIBER_ID            = 38,
134
    /** FQDN */
135
    DHCPV6_OPT_CLIENT_FQDN              = 39,
136
    /** One or more IPv6 addresses associated with PANA (Protocol for carrying Authentication for Network Access) Authentication Agents */
137
    DHCPV6_OPT_PANA_AGENT               = 40,
138
    /** Time zone to be used by the client in IEEE 1003.1 format */
139
    DHCPV6_OPT_NEW_POSIX_TIMEZONE       = 41,
140
    /** Time zone (TZ) database entry referred to by entry name */
141
    DHCPV6_OPT_NEW_TZDB_TIMEZONE        = 42,
142
    /** Relay Agent Echo Request */
143
    DHCPV6_OPT_ERO                      = 43,
144
    /** Query option */
145
    DHCPV6_OPT_LQ_QUERY                 = 44,
146
    /** Client Data */
147
    DHCPV6_OPT_CLIENT_DATA              = 45,
148
    /** Client Last Transaction Time */
149
    DHCPV6_OPT_CLT_TIME                 = 46,
150
    /** Relay data */
151
    DHCPV6_OPT_LQ_RELAY_DATA            = 47,
152
    /** Client link */
153
    DHCPV6_OPT_LQ_CLIENT_LINK           = 48,
154
    /** Mobile IPv6 Home Network Information */
155
    DHCPV6_OPT_MIP6_HNINF               = 49,
156
    /** Mobile IPv6 Relay Agent */
157
    DHCPV6_OPT_MIP6_RELAY               = 50,
158
    /** Location to Service Translation (LoST) server domain name */
159
    DHCPV6_OPT_V6_LOST                  = 51,
160
    /** Access Points (CAPWAP) Access Controller IPv6 addresses */
161
    DHCPV6_OPT_CAPWAP_AC_V6             = 52,
162
    /** DHCPv6 Bulk LeaseQuery */
163
    DHCPV6_OPT_RELAY_ID                 = 53,
164
    /** List of IPv6 addresses for servers providing particular types of IEEE 802.21 Mobility Service (MoS) */
165
    DHCPV6_OPT_IPH6_ADDRESS_MOS         = 54,
166
    /** List of FQDNs for servers providing particular types of IEEE 802.21 Mobility Service (MoS) */
167
    DHCPV6_OPT_IPV6_FQDN_MOS            = 55,
168
    /** Network Time Protocol (NTP) or Simple NTP (SNTP) Server Location */
169
    DHCPV6_OPT_NTP_SERVER               = 56,
170
    /** Boot File Uniform Resource Locator (URL) */
171
    DHCPV6_OPT_BOOTFILE_URL             = 59,
172
    /** Boot File Parameters */
173
    DHCPV6_OPT_BOOTFILE_PARAM           = 60,
174
    /** Client System Architecture Type */
175
    DHCPV6_OPT_CLIENT_ARCH_TYPE         = 61,
176
    /** Client Network Interface Identifier */
177
    DHCPV6_OPT_NII                      = 62,
178
    /** ERP Local Domain Name */
179
    DHCPV6_OPT_ERP_LOCAL_DOMAIN_NAME    = 65,
180
    /** Relay supplied options */
181
    DHCPV6_OPT_RELAY_SUPPLIED_OPTIONS   = 66,
182
    /** Virtual Subnet Selection */
183
    DHCPV6_OPT_VSS                      = 68,
184
    /** Client link layer */
185
    DHCPV6_OPT_CLIENT_LINKLAYER_ADDR    = 79,
186
    /** Manufacturer Usage Description */
187
    DHCPV6_OPT_MUD_URL                  = 112
188
  };
189
190
  /**
191
   * @class DhcpV6Option
192
   * A wrapper class for DHCPv6 options. This class does not create or modify DHCP option records, but rather
193
   * serves as a wrapper and provides useful methods for setting and retrieving data to/from them
194
   */
195
  class DhcpV6Option : public TLVRecord<uint16_t, uint16_t>
196
  {
197
  public:
198
    /**
199
     * A c'tor for this class that gets a pointer to the option raw data (byte array)
200
     * @param[in] optionRawData A pointer to the option raw data
201
     */
202
0
    explicit DhcpV6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { }
203
204
    /**
205
     * A d'tor for this class, currently does nothing
206
     */
207
0
    virtual ~DhcpV6Option() { }
208
209
    /**
210
     * @return The option type converted to ::DhcpV6OptionType enum
211
     */
212
    DhcpV6OptionType getType() const;
213
214
    /**
215
     * @return The raw option value (byte array) as a hex string
216
     */
217
    std::string getValueAsHexString() const;
218
219
    // implement abstract methods
220
221
    size_t getTotalSize() const;
222
    size_t getDataSize() const;
223
  };
224
225
  /**
226
   * @class DhcpV6OptionBuilder
227
   * A class for building DHCPv6 options. This builder receives the option parameters in its c'tor,
228
   * builds the DHCPv6 option raw buffer and provides a build() method to get a DhcpV6Option object out of it
229
   */
230
  class DhcpV6OptionBuilder : public TLVRecordBuilder
231
  {
232
  public:
233
    /**
234
     * A c'tor for building DHCPv6 options from a string representing the hex stream of the raw byte value.
235
     * The DhcpV6Option object can later be retrieved by calling build()
236
     * @param[in] optionType DHCPv6 option type
237
     * @param[in] optionValueAsHexStream The value as a hex stream string
238
     */
239
    DhcpV6OptionBuilder(DhcpV6OptionType optionType, const std::string& optionValueAsHexStream) :
240
0
      TLVRecordBuilder(static_cast<uint16_t>(optionType), optionValueAsHexStream, true) { }
241
242
    /**
243
     * A c'tor for building DHCPv6 options from a byte array representing their value. The DhcpV6Option object can be later
244
     * retrieved by calling build()
245
     * @param[in] optionType DHCPv6 option type
246
     * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way.
247
     * @param[in] optionValueLen Option value length in bytes
248
     */
249
    DhcpV6OptionBuilder(DhcpV6OptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) :
250
0
      TLVRecordBuilder(static_cast<uint16_t>(optionType), optionValue, optionValueLen) {}
251
252
    /**
253
     * Build the DhcpV6Option object out of the parameters defined in the c'tor
254
     * @return The DhcpV6Option object
255
     */
256
    DhcpV6Option build() const;
257
  };
258
259
  /**
260
   * @struct dhcpv6_header
261
   * Represents the basic DHCPv6 protocol header
262
   */
263
  struct dhcpv6_header
264
  {
265
    /** DHCPv6 message type */
266
    uint8_t messageType;
267
    /** DHCPv6 transaction ID (first byte) */
268
    uint8_t transactionId1;
269
    /** DHCPv6 transaction ID (second byte) */
270
    uint8_t transactionId2;
271
    /** DHCPv6 transaction ID (last byte) */
272
    uint8_t transactionId3;
273
  };
274
275
  /**
276
   * @class DhcpV6Layer
277
   * Represents a DHCPv6 (Dynamic Host Configuration Protocol version 6) protocol layer
278
   */
279
  class DhcpV6Layer : public Layer
280
  {
281
  public:
282
283
    /**
284
     * A constructor that creates the layer from an existing packet raw data
285
     * @param[in] data A pointer to the raw data
286
     * @param[in] dataLen Size of the data in bytes
287
     * @param[in] prevLayer A pointer to the previous layer
288
     * @param[in] packet A pointer to the Packet instance where layer will be stored in
289
     */
290
    DhcpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet);
291
292
    /**
293
     * A constructor that creates the layer from scratch
294
     * @param[in] messageType A DHCPv6 message type to be set
295
     * @param[in] transactionId The transaction ID to be set. Notice the transaction ID is 3-byte long so the value shouldn't exceed 0xFFFFFF
296
     */
297
    DhcpV6Layer(DhcpV6MessageType messageType, uint32_t transactionId);
298
299
    /**
300
     * @return The message type of this DHCPv6 message
301
     */
302
    DhcpV6MessageType getMessageType() const;
303
304
    /**
305
     * @return The string value of the message type of this DHCPv6 message
306
     */
307
    std::string getMessageTypeAsString() const;
308
309
    /**
310
     * Set the message type for this layer
311
     * @param[in] messageType The message type to set
312
     * @return No return value
313
     */
314
    void setMessageType(DhcpV6MessageType messageType);
315
316
    /**
317
     * @return The transaction ID of this DHCPv6 message
318
     */
319
    uint32_t getTransactionID() const;
320
321
    /**
322
     * Set the transaction ID for this DHCPv6 message
323
     * @param[in] transactionId The transaction ID value to set
324
     * @return No return value
325
     */
326
    void setTransactionID(uint32_t transactionId) const;
327
328
    /**
329
     * @return The first DHCPv6 option in the packet. If there are no DHCPv6 options the returned value will contain
330
     * a logical NULL (DhcpV6Option#isNull() == true)
331
     */
332
    DhcpV6Option getFirstOptionData() const;
333
334
    /**
335
     * Get the DHCPv6 option that comes after a given option. If the given option was the last one, the
336
     * returned value will contain a logical NULL (DhcpV6Option#isNull() == true)
337
     * @param[in] dhcpv6Option A given DHCPv6 option
338
     * @return A DhcpV6Option object containing the option data that comes next, or logical NULL if the given DHCPv6
339
     * option: (1) was the last one; (2) contains a logical NULL or (3) doesn't belong to this packet
340
     */
341
    DhcpV6Option getNextOptionData(DhcpV6Option dhcpv6Option) const;
342
343
    /**
344
     * Get a DHCPv6 option by type
345
     * @param[in] option DHCPv6 option type
346
     * @return A DhcpV6OptionType object containing the first DHCP option data that matches this type, or logical NULL
347
     * (DhcpV6Option#isNull() == true) if no such option found
348
     */
349
    DhcpV6Option getOptionData(DhcpV6OptionType option) const;
350
351
    /**
352
     * @return The number of DHCPv6 options in this layer
353
     */
354
    size_t getOptionCount() const;
355
356
    /**
357
     * Add a new DHCPv6 option at the end of the layer
358
     * @param[in] optionBuilder A DhcpV6OptionBuilder object that contains the requested DHCPv6 option data to add
359
     * @return A DhcpV6Option object containing the newly added DHCP option data or logical NULL
360
     * (DhcpV6Option#isNull() == true) if addition failed
361
     */
362
    DhcpV6Option addOption(const DhcpV6OptionBuilder& optionBuilder);
363
364
    /**
365
     * Add a new DHCPv6 option after an existing one
366
     * @param[in] optionBuilder A DhcpV6OptionBuilder object that contains the requested DHCPv6 option data to add
367
     * @param[in] optionType The DHCPv6 option type which the newly added option will come after
368
     * @return A DhcpV6Option object containing the newly added DHCPv6 option data or logical NULL
369
     * (DhcpV6Option#isNull() == true) if addition failed
370
     */
371
    DhcpV6Option addOptionAfter(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType);
372
373
    /**
374
     * Add a new DHCPv6 option before an existing one
375
     * @param[in] optionBuilder A DhcpV6OptionBuilder object that contains the requested DHCPv6 option data to add
376
     * @param[in] optionType The DHCPv6 option type which the newly added option will come before
377
     * @return A DhcpV6Option object containing the newly added DHCPv6 option data or logical NULL
378
     * (DhcpV6Option#isNull() == true) if addition failed
379
     */
380
    DhcpV6Option addOptionBefore(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType);
381
382
    /**
383
     * Remove an existing DHCPv6 option from the layer
384
     * @param[in] optionType The DHCPv6 option type to remove
385
     * @return True if DHCPv6 option was successfully removed or false if type wasn't found or if removal failed
386
     */
387
    bool removeOption(DhcpV6OptionType optionType);
388
389
    /**
390
     * Remove all DHCPv6 options in this layer
391
     * @return True if all DHCPv6 options were successfully removed or false if removal failed for some reason
392
     */
393
    bool removeAllOptions();
394
395
    /**
396
     * A static method that checks whether a port is considered as a DHCPv6 port
397
     * @param[in] port The port number to check
398
     * @return True if this is a DHCPv6 port number, false otherwise
399
     */
400
    static inline bool isDhcpV6Port(uint16_t port);
401
402
    /**
403
     * A static method that validates the input data
404
     * @param[in] data The pointer to the beginning of a byte stream of an DHCPv6 layer
405
     * @param[in] dataLen The length of the byte stream
406
     * @return True if the data is valid and can represent an DHCPv6 layer
407
     */
408
    static inline bool isDataValid(const uint8_t* data, size_t dataLen);
409
410
    // implement abstract methods
411
412
    /**
413
     * Does nothing for this layer (DhcpV6Layer is always last)
414
     */
415
739
    void parseNextLayer() {}
416
417
    /**
418
     * @return The size of @ref dhcpv6_header + size of options
419
     */
420
0
    size_t getHeaderLen() const { return m_DataLen; }
421
422
    /**
423
     * Does nothing for this layer
424
     */
425
0
    void computeCalculateFields() {}
426
427
    std::string toString() const;
428
429
739
    OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; }
430
431
  private:
432
0
    uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(dhcpv6_header); }
433
0
    dhcpv6_header* getDhcpHeader() const { return (dhcpv6_header*)m_Data; }
434
    DhcpV6Option addOptionAt(const DhcpV6OptionBuilder& optionBuilder, int offset);
435
436
    TLVRecordReader<DhcpV6Option> m_OptionReader;
437
  };
438
439
440
  // implementation of inline methods
441
442
  bool DhcpV6Layer::isDhcpV6Port(uint16_t port)
443
36.9k
  {
444
36.9k
    return (port == 546) || (port == 547);
445
446
36.9k
  }
447
448
  bool DhcpV6Layer::isDataValid(const uint8_t* data, size_t dataLen)
449
831
  {
450
831
    return dataLen >= sizeof(dhcpv6_header);
451
831
  }
452
453
}
454
# endif // PACKETPP_DHCPV6_LAYER