Coverage Report

Created: 2024-02-25 06:29

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