/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 | | } |