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