Coverage Report

Created: 2025-07-11 07:47

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