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