/src/PcapPlusPlus/Packet++/header/DhcpLayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "TLVData.h" |
5 | | #include "IpAddress.h" |
6 | | #include "MacAddress.h" |
7 | | #include <string.h> |
8 | | |
9 | | /// @file |
10 | | |
11 | | /// @namespace pcpp |
12 | | /// @brief The main namespace for the PcapPlusPlus lib |
13 | | namespace pcpp |
14 | | { |
15 | | /// @struct dhcp_header |
16 | | /// Represents a DHCP protocol header |
17 | | #pragma pack(push, 1) |
18 | | struct dhcp_header |
19 | | { |
20 | | /// BootP opcode |
21 | | uint8_t opCode; |
22 | | /// Hardware type, set to 1 (Ethernet) by default |
23 | | uint8_t hardwareType; |
24 | | /// Hardware address length, set to 6 (MAC address length) by default |
25 | | uint8_t hardwareAddressLength; |
26 | | /// Hop count |
27 | | uint8_t hops; |
28 | | /// DHCP/BootP transaction ID |
29 | | uint32_t transactionID; |
30 | | /// The elapsed time, in seconds since the client sent its first BOOTREQUEST message |
31 | | uint16_t secondsElapsed; |
32 | | /// BootP flags |
33 | | uint16_t flags; |
34 | | /// Client IPv4 address |
35 | | uint32_t clientIpAddress; |
36 | | /// Your IPv4 address |
37 | | uint32_t yourIpAddress; |
38 | | /// Server IPv4 address |
39 | | uint32_t serverIpAddress; |
40 | | /// Gateway IPv4 address |
41 | | uint32_t gatewayIpAddress; |
42 | | /// Client hardware address, by default contains the MAC address (only 6 first bytes are used) |
43 | | uint8_t clientHardwareAddress[16]; |
44 | | /// BootP server name |
45 | | uint8_t serverName[64]; |
46 | | /// BootP boot file name |
47 | | uint8_t bootFilename[128]; |
48 | | /// DHCP magic number (set to the default value of 0x63538263) |
49 | | uint32_t magicNumber; |
50 | | }; |
51 | | #pragma pack(pop) |
52 | | static_assert(sizeof(dhcp_header) == 240, "dhcp_header size is not 240 bytes"); |
53 | | |
54 | | /// BootP opcodes |
55 | | enum BootpOpCodes |
56 | | { |
57 | | /// BootP request |
58 | | DHCP_BOOTREQUEST = 1, |
59 | | /// BootP reply |
60 | | DHCP_BOOTREPLY = 2 |
61 | | }; |
62 | | |
63 | | /// DHCP message types |
64 | | enum DhcpMessageType |
65 | | { |
66 | | /// Unknown message type |
67 | | DHCP_UNKNOWN_MSG_TYPE = 0, |
68 | | /// Discover message type |
69 | | DHCP_DISCOVER = 1, |
70 | | /// Offer message type |
71 | | DHCP_OFFER = 2, |
72 | | /// Request message type |
73 | | DHCP_REQUEST = 3, |
74 | | /// Decline message type |
75 | | DHCP_DECLINE = 4, |
76 | | /// Acknowledge message type |
77 | | DHCP_ACK = 5, |
78 | | /// Non-acknowledge message type |
79 | | DHCP_NAK = 6, |
80 | | /// Release message type |
81 | | DHCP_RELEASE = 7, |
82 | | /// Inform message type |
83 | | DHCP_INFORM = 8 |
84 | | }; |
85 | | |
86 | | /// DHCP option types. |
87 | | enum DhcpOptionTypes |
88 | | { |
89 | | /// Unknown option type |
90 | | DHCPOPT_UNKNOWN = -1, |
91 | | /// Pad |
92 | | DHCPOPT_PAD = 0, |
93 | | /// Subnet Mask Value |
94 | | DHCPOPT_SUBNET_MASK = 1, |
95 | | /// Time Offset in Seconds from UTC |
96 | | DHCPOPT_TIME_OFFSET = 2, |
97 | | /// N/4 Router addresses |
98 | | DHCPOPT_ROUTERS = 3, |
99 | | /// N/4 Timeserver addresses |
100 | | DHCPOPT_TIME_SERVERS = 4, |
101 | | /// N/4 IEN-116 Server addresses |
102 | | DHCPOPT_NAME_SERVERS = 5, |
103 | | /// N/4 DNS Server addresses |
104 | | DHCPOPT_DOMAIN_NAME_SERVERS = 6, |
105 | | /// N/4 Logging Server addresses |
106 | | DHCPOPT_LOG_SERVERS = 7, |
107 | | /// N/4 Quotes Server addresses |
108 | | DHCPOPT_QUOTES_SERVERS = 8, |
109 | | /// N/4 Quotes Server addresses |
110 | | DHCPOPT_LPR_SERVERS = 9, |
111 | | /// N/4 Quotes Server addresses |
112 | | DHCPOPT_IMPRESS_SERVERS = 10, |
113 | | /// N/4 RLP Server addresses |
114 | | DHCPOPT_RESOURCE_LOCATION_SERVERS = 11, |
115 | | /// Hostname string |
116 | | DHCPOPT_HOST_NAME = 12, |
117 | | /// Size of boot file in 512 byte chunks |
118 | | DHCPOPT_BOOT_SIZE = 13, |
119 | | /// Client to dump and name the file to dump it to |
120 | | DHCPOPT_MERIT_DUMP = 14, |
121 | | /// The DNS domain name of the client |
122 | | DHCPOPT_DOMAIN_NAME = 15, |
123 | | /// Swap Server address |
124 | | DHCPOPT_SWAP_SERVER = 16, |
125 | | /// Path name for root disk |
126 | | DHCPOPT_ROOT_PATH = 17, |
127 | | /// Path name for more BOOTP info |
128 | | DHCPOPT_EXTENSIONS_PATH = 18, |
129 | | /// Enable/Disable IP Forwarding |
130 | | DHCPOPT_IP_FORWARDING = 19, |
131 | | /// Enable/Disable Source Routing |
132 | | DHCPOPT_NON_LOCAL_SOURCE_ROUTING = 20, |
133 | | /// Routing Policy Filters |
134 | | DHCPOPT_POLICY_FILTER = 21, |
135 | | /// Max Datagram Reassembly Size |
136 | | DHCPOPT_MAX_DGRAM_REASSEMBLY = 22, |
137 | | /// Default IP Time to Live |
138 | | DEFAULT_IP_TTL = 23, |
139 | | /// Path MTU Aging Timeout |
140 | | DHCPOPT_PATH_MTU_AGING_TIMEOUT = 24, |
141 | | /// Path MTU Plateau Table |
142 | | PATH_MTU_PLATEAU_TABLE = 25, |
143 | | /// Interface MTU Size |
144 | | DHCPOPT_INTERFACE_MTU = 26, |
145 | | /// All Subnets are Local |
146 | | DHCPOPT_ALL_SUBNETS_LOCAL = 27, |
147 | | /// Broadcast Address |
148 | | DHCPOPT_BROADCAST_ADDRESS = 28, |
149 | | /// Perform Mask Discovery |
150 | | DHCPOPT_PERFORM_MASK_DISCOVERY = 29, |
151 | | /// Provide Mask to Others |
152 | | DHCPOPT_MASK_SUPPLIER = 30, |
153 | | /// Perform Router Discovery |
154 | | DHCPOPT_ROUTER_DISCOVERY = 31, |
155 | | /// Router Solicitation Address |
156 | | DHCPOPT_ROUTER_SOLICITATION_ADDRESS = 32, |
157 | | /// Static Routing Table |
158 | | DHCPOPT_STATIC_ROUTES = 33, |
159 | | /// Trailer Encapsulation |
160 | | DHCPOPT_TRAILER_ENCAPSULATION = 34, |
161 | | /// ARP Cache Timeout |
162 | | DHCPOPT_ARP_CACHE_TIMEOUT = 35, |
163 | | /// IEEE802.3 Encapsulation |
164 | | DHCPOPT_IEEE802_3_ENCAPSULATION = 36, |
165 | | /// Default TCP Time to Live |
166 | | DHCPOPT_DEFAULT_TCP_TTL = 37, |
167 | | /// TCP Keepalive Interval |
168 | | DHCPOPT_TCP_KEEPALIVE_INTERVAL = 38, |
169 | | /// TCP Keepalive Garbage |
170 | | DHCPOPT_TCP_KEEPALIVE_GARBAGE = 39, |
171 | | /// NIS Domain Name |
172 | | DHCPOPT_NIS_DOMAIN = 40, |
173 | | /// NIS Server Addresses |
174 | | DHCPOPT_NIS_SERVERS = 41, |
175 | | /// NTP Server Addresses |
176 | | DHCPOPT_NTP_SERVERS = 42, |
177 | | /// Vendor Specific Information |
178 | | DHCPOPT_VENDOR_ENCAPSULATED_OPTIONS = 43, |
179 | | /// NETBIOS Name Servers |
180 | | DHCPOPT_NETBIOS_NAME_SERVERS = 44, |
181 | | /// NETBIOS Datagram Distribution |
182 | | DHCPOPT_NETBIOS_DD_SERVER = 45, |
183 | | /// NETBIOS Node Type |
184 | | DHCPOPT_NETBIOS_NODE_TYPE = 46, |
185 | | /// NETBIOS Scope |
186 | | DHCPOPT_NETBIOS_SCOPE = 47, |
187 | | /// X Window Font Server |
188 | | DHCPOPT_FONT_SERVERS = 48, |
189 | | /// X Window Display Manager |
190 | | DHCPOPT_X_DISPLAY_MANAGER = 49, |
191 | | /// Requested IP Address |
192 | | DHCPOPT_DHCP_REQUESTED_ADDRESS = 50, |
193 | | /// IP Address Lease Time |
194 | | DHCPOPT_DHCP_LEASE_TIME = 51, |
195 | | /// Overload "sname" or "file" |
196 | | DHCPOPT_DHCP_OPTION_OVERLOAD = 52, |
197 | | /// DHCP Message Type |
198 | | DHCPOPT_DHCP_MESSAGE_TYPE = 53, |
199 | | /// DHCP Server Identification |
200 | | DHCPOPT_DHCP_SERVER_IDENTIFIER = 54, |
201 | | /// Parameter Request List |
202 | | DHCPOPT_DHCP_PARAMETER_REQUEST_LIST = 55, |
203 | | /// DHCP Error Message |
204 | | DHCPOPT_DHCP_MESSAGE = 56, |
205 | | /// DHCP Maximum Message Size |
206 | | DHCPOPT_DHCP_MAX_MESSAGE_SIZE = 57, |
207 | | /// DHCP Renewal (T1) Time |
208 | | DHCPOPT_DHCP_RENEWAL_TIME = 58, |
209 | | /// DHCP Rebinding (T2) Time |
210 | | DHCPOPT_DHCP_REBINDING_TIME = 59, |
211 | | /// Class Identifier |
212 | | DHCPOPT_VENDOR_CLASS_IDENTIFIER = 60, |
213 | | /// Class Identifier |
214 | | DHCPOPT_DHCP_CLIENT_IDENTIFIER = 61, |
215 | | /// NetWare/IP Domain Name |
216 | | DHCPOPT_NWIP_DOMAIN_NAME = 62, |
217 | | /// NetWare/IP sub Options |
218 | | DHCPOPT_NWIP_SUBOPTIONS = 63, |
219 | | /// NIS+ v3 Client Domain Name |
220 | | DHCPOPT_NIS_DOMAIN_NAME = 64, |
221 | | /// NIS+ v3 Server Addresses |
222 | | DHCPOPT_NIS_SERVER_ADDRESS = 65, |
223 | | /// TFTP Server Name |
224 | | DHCPOPT_TFTP_SERVER_NAME = 66, |
225 | | /// Boot File Name |
226 | | DHCPOPT_BOOTFILE_NAME = 67, |
227 | | /// Home Agent Addresses |
228 | | DHCPOPT_HOME_AGENT_ADDRESS = 68, |
229 | | /// Simple Mail Server (SMTP) Addresses |
230 | | DHCPOPT_SMTP_SERVER = 69, |
231 | | /// Post Office (POP3) Server Addresses |
232 | | DHCPOPT_POP3_SERVER = 70, |
233 | | /// Network News (NNTP) Server Addresses |
234 | | DHCPOPT_NNTP_SERVER = 71, |
235 | | /// WWW Server Addresses |
236 | | DHCPOPT_WWW_SERVER = 72, |
237 | | /// Finger Server Addresses |
238 | | DHCPOPT_FINGER_SERVER = 73, |
239 | | /// Chat (IRC) Server Addresses |
240 | | DHCPOPT_IRC_SERVER = 74, |
241 | | /// StreetTalk Server Addresses |
242 | | DHCPOPT_STREETTALK_SERVER = 75, |
243 | | /// ST Directory Assist. Addresses |
244 | | DHCPOPT_STDA_SERVER = 76, |
245 | | /// User Class Information |
246 | | DHCPOPT_USER_CLASS = 77, |
247 | | /// Directory Agent Information |
248 | | DHCPOPT_DIRECTORY_AGENT = 78, |
249 | | /// Service Location Agent Scope |
250 | | DHCPOPT_SERVICE_SCOPE = 79, |
251 | | /// Rapid Commit |
252 | | DHCPOPT_RAPID_COMMIT = 80, |
253 | | /// Fully Qualified Domain Name |
254 | | DHCPOPT_FQDN = 81, |
255 | | /// Relay Agent Information |
256 | | DHCPOPT_DHCP_AGENT_OPTIONS = 82, |
257 | | /// Internet Storage Name Service |
258 | | DHCPOPT_ISNS = 83, |
259 | | /// Novell Directory Services |
260 | | DHCPOPT_NDS_SERVERS = 85, |
261 | | /// Novell Directory Services |
262 | | DHCPOPT_NDS_TREE_NAME = 86, |
263 | | /// Novell Directory Services |
264 | | DHCPOPT_NDS_CONTEXT = 87, |
265 | | /// BCMCS Controller Domain Name list |
266 | | DHCPOPT_BCMCS_CONTROLLER_DOMAIN_NAME_LIST = 88, |
267 | | /// BCMCS Controller IPv4 address option |
268 | | DHCPOPT_BCMCS_CONTROLLER_IPV4_ADDRESS = 89, |
269 | | /// Authentication |
270 | | DHCPOPT_AUTHENTICATION = 90, |
271 | | /// Client Last Transaction Time |
272 | | DHCPOPT_CLIENT_LAST_TXN_TIME = 91, |
273 | | /// Associated IP |
274 | | DHCPOPT_ASSOCIATED_IP = 92, |
275 | | /// Client System Architecture |
276 | | DHCPOPT_CLIENT_SYSTEM = 93, |
277 | | /// Client Network Device Interface |
278 | | DHCPOPT_CLIENT_NDI = 94, |
279 | | /// Lightweight Directory Access Protocol [ |
280 | | DHCPOPT_LDAP = 95, |
281 | | /// UUID/GUID-based Client Identifier |
282 | | DHCPOPT_UUID_GUID = 97, |
283 | | /// Open Group's User Authentication |
284 | | DHCPOPT_USER_AUTH = 98, |
285 | | /// GEOCONF_CIVIC |
286 | | DHCPOPT_GEOCONF_CIVIC = 99, |
287 | | /// IEEE 1003.1 TZ String |
288 | | DHCPOPT_PCODE = 100, |
289 | | /// Reference to the TZ Database |
290 | | DHCPOPT_TCODE = 101, |
291 | | /// NetInfo Parent Server Address |
292 | | DHCPOPT_NETINFO_ADDRESS = 112, |
293 | | /// NetInfo Parent Server Tag |
294 | | DHCPOPT_NETINFO_TAG = 113, |
295 | | /// URL |
296 | | DHCPOPT_URL = 114, |
297 | | /// DHCP Auto-Configuration |
298 | | DHCPOPT_AUTO_CONFIG = 116, |
299 | | /// Name Service Search |
300 | | DHCPOPT_NAME_SERVICE_SEARCH = 117, |
301 | | /// Subnet Selection Option |
302 | | DHCPOPT_SUBNET_SELECTION = 118, |
303 | | /// DNS Domain Search List |
304 | | DHCPOPT_DOMAIN_SEARCH = 119, |
305 | | /// SIP Servers DHCP Option |
306 | | DHCPOPT_SIP_SERVERS = 120, |
307 | | /// Classless Static Route Option |
308 | | DHCPOPT_CLASSLESS_STATIC_ROUTE = 121, |
309 | | /// CableLabs Client Configuration |
310 | | DHCPOPT_CCC = 122, |
311 | | /// GeoConf Option |
312 | | DHCPOPT_GEOCONF = 123, |
313 | | /// Vendor-Identifying Vendor Class |
314 | | DHCPOPT_V_I_VENDOR_CLASS = 124, |
315 | | /// Vendor-Identifying Vendor-Specific Information |
316 | | DHCPOPT_V_I_VENDOR_OPTS = 125, |
317 | | /// OPTION_PANA_AGENT |
318 | | DHCPOPT_OPTION_PANA_AGENT = 136, |
319 | | /// OPTION_V4_LOST |
320 | | DHCPOPT_OPTION_V4_LOST = 137, |
321 | | /// CAPWAP Access Controller addresses |
322 | | DHCPOPT_OPTION_CAPWAP_AC_V4 = 138, |
323 | | /// A Series Of Suboptions |
324 | | DHCPOPT_OPTION_IPV4_ADDRESS_MOS = 139, |
325 | | /// A Series Of Suboptions |
326 | | DHCPOPT_OPTION_IPV4_FQDN_MOS = 140, |
327 | | /// List of domain names to search for SIP User Agent Configuration |
328 | | DHCPOPT_SIP_UA_CONFIG = 141, |
329 | | /// ANDSF IPv4 Address Option for DHCPv4 |
330 | | DHCPOPT_OPTION_IPV4_ADDRESS_ANDSF = 142, |
331 | | /// Geospatial Location with Uncertainty [RF |
332 | | DHCPOPT_GEOLOC = 144, |
333 | | /// Forcerenew Nonce Capable |
334 | | DHCPOPT_FORCERENEW_NONCE_CAPABLE = 145, |
335 | | /// Information for selecting RDNSS |
336 | | DHCPOPT_RDNSS_SELECTION = 146, |
337 | | /// Status code and optional N byte text message describing status |
338 | | DHCPOPT_STATUS_CODE = 151, |
339 | | /// Absolute time (seconds since Jan 1, 1970) message was sent |
340 | | DHCPOPT_BASE_TIME = 152, |
341 | | /// Number of seconds in the past when client entered current state |
342 | | DHCPOPT_START_TIME_OF_STATE = 153, |
343 | | /// Absolute time (seconds since Jan 1, 1970) for beginning of query |
344 | | DHCPOPT_QUERY_START_TIME = 154, |
345 | | /// Absolute time (seconds since Jan 1, 1970) for end of query |
346 | | DHCPOPT_QUERY_END_TIME = 155, |
347 | | /// State of IP address |
348 | | DHCPOPT_DHCP_STATE = 156, |
349 | | /// Indicates information came from local or remote server |
350 | | DHCPOPT_DATA_SOURCE = 157, |
351 | | /// Includes one or multiple lists of PCP server IP addresses; each list is treated as a separate PCP server |
352 | | DHCPOPT_OPTION_V4_PCP_SERVER = 158, |
353 | | /// This option is used to configure a set of ports bound to a shared IPv4 address |
354 | | DHCPOPT_OPTION_V4_PORTPARAMS = 159, |
355 | | /// DHCP Captive-Portal |
356 | | DHCPOPT_CAPTIVE_PORTAL = 160, |
357 | | /// Manufacturer Usage Descriptions |
358 | | DHCPOPT_OPTION_MUD_URL_V4 = 161, |
359 | | /// Etherboot |
360 | | DHCPOPT_ETHERBOOT = 175, |
361 | | /// IP Telephone |
362 | | DHCPOPT_IP_TELEPHONE = 176, |
363 | | /// Magic string = F1:00:74:7E |
364 | | DHCPOPT_PXELINUX_MAGIC = 208, |
365 | | /// Configuration file |
366 | | DHCPOPT_CONFIGURATION_FILE = 209, |
367 | | /// Path Prefix Option |
368 | | DHCPOPT_PATH_PREFIX = 210, |
369 | | /// Reboot Time |
370 | | DHCPOPT_REBOOT_TIME = 211, |
371 | | /// OPTION_6RD with N/4 6rd BR addresses |
372 | | DHCPOPT_OPTION_6RD = 212, |
373 | | /// Access Network Domain Name |
374 | | DHCPOPT_OPTION_V4_ACCESS_DOMAIN = 213, |
375 | | /// Subnet Allocation Option |
376 | | DHCPOPT_SUBNET_ALLOCATION = 220, |
377 | | /// Virtual Subnet Selection (VSS) Option |
378 | | DHCPOPT_VIRTUAL_SUBNET_SELECTION = 221, |
379 | | /// End (last option) |
380 | | DHCPOPT_END = 255 |
381 | | }; |
382 | | |
383 | | /// @class DhcpOption |
384 | | /// A wrapper class for DHCP options. This class does not create or modify DHCP option records, but rather |
385 | | /// serves as a wrapper and provides useful methods for setting and retrieving data to/from them |
386 | | class DhcpOption : public TLVRecord<uint8_t, uint8_t> |
387 | | { |
388 | | public: |
389 | | /// A c'tor for this class that gets a pointer to the option raw data (byte array) |
390 | | /// @param[in] optionRawData A pointer to the option raw data |
391 | 139k | explicit DhcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) |
392 | 139k | {} |
393 | | |
394 | | /// A d'tor for this class, currently does nothing |
395 | | ~DhcpOption() override = default; |
396 | | |
397 | | /// Retrieve DHCP option data as IPv4 address. Relevant only if option value is indeed an IPv4 address |
398 | | /// @return DHCP option data as IPv4 address |
399 | | IPv4Address getValueAsIpAddr() const |
400 | 1.30k | { |
401 | 1.30k | return getValueAs<uint32_t>(); |
402 | 1.30k | } |
403 | | |
404 | | /// Set DHCP option data as IPv4 address. This method copies the 4 bytes of the IP address to the option value |
405 | | /// @param[in] addr The IPv4 address to set |
406 | | /// @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set |
407 | | /// to 0). For example: if option data is 20 bytes long and you want to set the IP address in the 4 last bytes |
408 | | /// then use this method like this: setValueIpAddr(your_addr, 16) |
409 | | void setValueIpAddr(const IPv4Address& addr, int valueOffset = 0) |
410 | 0 | { |
411 | 0 | setValue<uint32_t>(addr.toInt(), valueOffset); |
412 | 0 | } |
413 | | |
414 | | /// Retrieve DHCP option data as string. Relevant only if option value is indeed a string |
415 | | /// @param[in] valueOffset An optional parameter that specifies where to start copy the DHCP option data. For |
416 | | /// example: when retrieving Client FQDN option, you may ignore the flags and RCODE fields using this method |
417 | | /// like this: getValueAsString(3). The default is 0 - start copying from the beginning of option data |
418 | | /// @return DHCP option data as string |
419 | | std::string getValueAsString(int valueOffset = 0) const |
420 | 1.30k | { |
421 | 1.30k | if (m_Data == nullptr || m_Data->recordLen - valueOffset < 1) |
422 | 28 | return ""; |
423 | | |
424 | 1.27k | return std::string(reinterpret_cast<const char*>(m_Data->recordValue) + valueOffset, |
425 | 1.27k | static_cast<int>(m_Data->recordLen) - valueOffset); |
426 | 1.30k | } |
427 | | |
428 | | /// Set DHCP option data as string. This method copies the string to the option value. If the string is longer |
429 | | /// than option length the string is trimmed so it will fit the option length |
430 | | /// @param[in] stringValue The string to set |
431 | | /// @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set |
432 | | /// to 0). For example: if option data is 20 bytes long and you want to set a 6 char-long string in the 6 last |
433 | | /// bytes then use this method like this: setValueString("string", 14) |
434 | | void setValueString(const std::string& stringValue, int valueOffset = 0) |
435 | 0 | { |
436 | 0 | // calculate the maximum length of the destination buffer |
437 | 0 | size_t len = static_cast<size_t>(m_Data->recordLen) - static_cast<size_t>(valueOffset); |
438 | 0 |
|
439 | 0 | // use the length of input string if a buffer is large enough for whole string |
440 | 0 | if (stringValue.length() < len) |
441 | 0 | len = stringValue.length(); |
442 | 0 |
|
443 | 0 | memcpy(m_Data->recordValue + valueOffset, stringValue.data(), len); |
444 | 0 | } |
445 | | |
446 | | /// Check if a pointer can be assigned to the TLV record data |
447 | | /// @param[in] recordRawData A pointer to the TLV record raw data |
448 | | /// @param[in] tlvDataLen The size of the TLV record raw data |
449 | | /// @return True if data is valid and can be assigned |
450 | | static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen) |
451 | 139k | { |
452 | 139k | auto data = reinterpret_cast<TLVRawData const*>(recordRawData); |
453 | 139k | if (data == nullptr) |
454 | 0 | return false; |
455 | | |
456 | 139k | if (tlvDataLen < sizeof(TLVRawData::recordType)) |
457 | 5.42k | return false; |
458 | | |
459 | 134k | if (data->recordType == static_cast<uint8_t>(DHCPOPT_END) || |
460 | 134k | data->recordType == static_cast<uint8_t>(DHCPOPT_PAD)) |
461 | 101k | return true; |
462 | | |
463 | 32.4k | return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen); |
464 | 134k | } |
465 | | |
466 | | // implement abstract methods |
467 | | |
468 | | size_t getTotalSize() const override |
469 | 0 | { |
470 | 0 | if (m_Data == nullptr) |
471 | 0 | return 0; |
472 | 0 |
|
473 | 0 | if (m_Data->recordType == static_cast<uint8_t>(DHCPOPT_END) || |
474 | 0 | m_Data->recordType == static_cast<uint8_t>(DHCPOPT_PAD)) |
475 | 0 | return sizeof(uint8_t); |
476 | 0 |
|
477 | 0 | return sizeof(uint8_t) * 2 + static_cast<size_t>(m_Data->recordLen); |
478 | 0 | } |
479 | | |
480 | | size_t getDataSize() const override |
481 | 0 | { |
482 | 0 | if (m_Data == nullptr) |
483 | 0 | return 0; |
484 | 0 |
|
485 | 0 | if (m_Data->recordType == static_cast<uint8_t>(DHCPOPT_END) || |
486 | 0 | m_Data->recordType == static_cast<uint8_t>(DHCPOPT_PAD)) |
487 | 0 | return 0; |
488 | 0 |
|
489 | 0 | return m_Data->recordLen; |
490 | 0 | } |
491 | | }; |
492 | | |
493 | | /// @class DhcpOptionBuilder |
494 | | /// A class for building DHCP options. This builder receives the option parameters in its c'tor, |
495 | | /// builds the DHCP option raw buffer and provides a build() method to get a DhcpOption object out of it |
496 | | class DhcpOptionBuilder : public TLVRecordBuilder |
497 | | { |
498 | | public: |
499 | | /// A c'tor for building DHCP options which their value is a byte array. The DhcpOption object can later |
500 | | /// be retrieved by calling build() |
501 | | /// @param[in] optionType DHCP option type |
502 | | /// @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in |
503 | | /// any way |
504 | | /// @param[in] optionValueLen DHCP option value length in bytes |
505 | | DhcpOptionBuilder(DhcpOptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) |
506 | | : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue, optionValueLen) |
507 | 0 | {} |
508 | | |
509 | | /// A c'tor for building DHCP options which have a 1-byte value. The DhcpOption object can later be retrieved |
510 | | /// by calling build() |
511 | | /// @param[in] optionType DHCP option type |
512 | | /// @param[in] optionValue A 1-byte option value |
513 | | DhcpOptionBuilder(DhcpOptionTypes optionType, uint8_t optionValue) |
514 | | : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue) |
515 | 0 | {} |
516 | | |
517 | | /// A c'tor for building DHCP options which have a 2-byte value. The DhcpOption object can later be retrieved |
518 | | /// by calling build() |
519 | | /// @param[in] optionType DHCP option type |
520 | | /// @param[in] optionValue A 2-byte option value |
521 | | DhcpOptionBuilder(DhcpOptionTypes optionType, uint16_t optionValue) |
522 | | : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue) |
523 | 0 | {} |
524 | | |
525 | | /// A c'tor for building DHCP options which have a 4-byte value. The DhcpOption object can later be retrieved |
526 | | /// by calling build() |
527 | | /// @param[in] optionType DHCP option type |
528 | | /// @param[in] optionValue A 4-byte option value |
529 | | DhcpOptionBuilder(DhcpOptionTypes optionType, uint32_t optionValue) |
530 | | : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue) |
531 | 0 | {} |
532 | | |
533 | | /// A c'tor for building DHCP options which have an IPv4Address value. The DhcpOption object can later be |
534 | | /// retrieved by calling build() |
535 | | /// @param[in] optionType DHCP option type |
536 | | /// @param[in] optionValue The IPv4 address option value |
537 | | DhcpOptionBuilder(DhcpOptionTypes optionType, const IPv4Address& optionValue) |
538 | | : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue) |
539 | 0 | {} |
540 | | |
541 | | /// A c'tor for building DHCP options which have a string value. The DhcpOption object can later be retrieved |
542 | | /// by calling build() |
543 | | /// @param[in] optionType DHCP option type |
544 | | /// @param[in] optionValue The string option value |
545 | | DhcpOptionBuilder(DhcpOptionTypes optionType, const std::string& optionValue) |
546 | | : TLVRecordBuilder(static_cast<uint8_t>(optionType), optionValue) |
547 | 0 | {} |
548 | | |
549 | | /// A copy c'tor which copies all the data from another instance of DhcpOptionBuilder |
550 | | /// @param[in] other The instance to copy from |
551 | | DhcpOptionBuilder(const DhcpOptionBuilder& other) : TLVRecordBuilder(other) |
552 | 0 | {} |
553 | | |
554 | | /// Assignment operator that copies all data from another instance of DhcpOptionBuilder |
555 | | /// @param[in] other The instance to assign from |
556 | | /// @return A reference to the assignee |
557 | | DhcpOptionBuilder& operator=(const DhcpOptionBuilder& other) |
558 | 0 | { |
559 | 0 | TLVRecordBuilder::operator=(other); |
560 | 0 | return *this; |
561 | 0 | } |
562 | | |
563 | | /// Build the DhcpOption object out of the parameters defined in the c'tor |
564 | | /// @return The DhcpOption object |
565 | | DhcpOption build() const; |
566 | | }; |
567 | | |
568 | | /// @class DhcpLayer |
569 | | /// Represents a DHCP (Dynamic Host Configuration Protocol) protocol layer |
570 | | class DhcpLayer : public Layer |
571 | | { |
572 | | public: |
573 | | /// A constructor that creates the layer from an existing packet raw data |
574 | | /// @param[in] data A pointer to the raw data |
575 | | /// @param[in] dataLen Size of the data in bytes |
576 | | /// @param[in] prevLayer A pointer to the previous layer |
577 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored in |
578 | | DhcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
579 | | |
580 | | /// A constructor that creates the layer from scratch. Adds a ::DHCPOPT_DHCP_MESSAGE_TYPE and a ::DHCPOPT_END |
581 | | /// options |
582 | | /// @param[in] msgType A DHCP message type to be set |
583 | | /// @param[in] clientMacAddr A client MAC address to set in dhcp_header#clientHardwareAddress field |
584 | | DhcpLayer(DhcpMessageType msgType, const MacAddress& clientMacAddr); |
585 | | |
586 | | /// A constructor that creates the layer from scratch with clean data |
587 | | DhcpLayer(); |
588 | | |
589 | | /// A destructor for this layer |
590 | 6.65k | ~DhcpLayer() override = default; |
591 | | |
592 | | /// Get a pointer to the DHCP header. Notice this points directly to the data, so every change will change the |
593 | | /// actual packet data |
594 | | /// @return A pointer to the @ref dhcp_header |
595 | | dhcp_header* getDhcpHeader() const |
596 | 10.5k | { |
597 | 10.5k | return reinterpret_cast<dhcp_header*>(m_Data); |
598 | 10.5k | } |
599 | | |
600 | | /// @return The BootP opcode of this message |
601 | | BootpOpCodes getOpCode() const |
602 | 1.31k | { |
603 | 1.31k | return static_cast<BootpOpCodes>(getDhcpHeader()->opCode); |
604 | 1.31k | } |
605 | | |
606 | | /// @return The client IPv4 address (as extracted from dhcp_header#clientIpAddress converted to IPv4Address |
607 | | /// object) |
608 | | IPv4Address getClientIpAddress() const |
609 | 1.31k | { |
610 | 1.31k | return getDhcpHeader()->clientIpAddress; |
611 | 1.31k | } |
612 | | |
613 | | /// Set the client IPv4 address in dhcp_header#clientIpAddress |
614 | | /// @param[in] addr The IPv4 address to set |
615 | | void setClientIpAddress(const IPv4Address& addr) |
616 | 0 | { |
617 | 0 | getDhcpHeader()->clientIpAddress = addr.toInt(); |
618 | 0 | } |
619 | | |
620 | | /// @return The server IPv4 address (as extracted from dhcp_header#serverIpAddress converted to IPv4Address |
621 | | /// object) |
622 | | IPv4Address getServerIpAddress() const |
623 | 1.31k | { |
624 | 1.31k | return getDhcpHeader()->serverIpAddress; |
625 | 1.31k | } |
626 | | |
627 | | /// Set the server IPv4 address in dhcp_header#serverIpAddress |
628 | | /// @param[in] addr The IPv4 address to set |
629 | | void setServerIpAddress(const IPv4Address& addr) |
630 | 0 | { |
631 | 0 | getDhcpHeader()->serverIpAddress = addr.toInt(); |
632 | 0 | } |
633 | | |
634 | | /// @return Your IPv4 address (as extracted from dhcp_header#yourIpAddress converted to IPv4Address object) |
635 | | IPv4Address getYourIpAddress() const |
636 | 1.31k | { |
637 | 1.31k | return getDhcpHeader()->yourIpAddress; |
638 | 1.31k | } |
639 | | |
640 | | /// Set your IPv4 address in dhcp_header#yourIpAddress |
641 | | /// @param[in] addr The IPv4 address to set |
642 | | void setYourIpAddress(const IPv4Address& addr) |
643 | 0 | { |
644 | 0 | getDhcpHeader()->yourIpAddress = addr.toInt(); |
645 | 0 | } |
646 | | |
647 | | /// @return Gateway IPv4 address (as extracted from dhcp_header#gatewayIpAddress converted to IPv4Address |
648 | | /// object) |
649 | | IPv4Address getGatewayIpAddress() const |
650 | 1.31k | { |
651 | 1.31k | return getDhcpHeader()->gatewayIpAddress; |
652 | 1.31k | } |
653 | | |
654 | | /// Set the gateway IPv4 address in dhcp_header#gatewayIpAddress |
655 | | /// @param[in] addr The IPv4 address to set |
656 | | void setGatewayIpAddress(const IPv4Address& addr) |
657 | 0 | { |
658 | 0 | getDhcpHeader()->gatewayIpAddress = addr.toInt(); |
659 | 0 | } |
660 | | |
661 | | /// @return The client MAC address as extracted from dhcp_header#clientHardwareAddress, assuming |
662 | | /// dhcp_header#hardwareType is 1 (Ethernet) and dhcp_header#hardwareAddressLength is 6 (MAC address length). |
663 | | /// Otherwise returns MacAddress#Zero |
664 | | MacAddress getClientHardwareAddress() const; |
665 | | |
666 | | /// Set a MAC address into the first 6 bytes of dhcp_header#clientHardwareAddress. This method also sets |
667 | | /// dhcp_header#hardwareType to 1 (Ethernet) and dhcp_header#hardwareAddressLength to 6 (MAC address length) |
668 | | /// @param[in] addr The MAC address to set |
669 | | void setClientHardwareAddress(const MacAddress& addr); |
670 | | |
671 | | /// @return DHCP message type as extracted from ::DHCPOPT_DHCP_MESSAGE_TYPE option. If this option doesn't exist |
672 | | /// the value of |
673 | | /// ::DHCP_UNKNOWN_MSG_TYPE is returned |
674 | | DhcpMessageType getMessageType() const; |
675 | | |
676 | | /// Set DHCP message type. This method searches for existing ::DHCPOPT_DHCP_MESSAGE_TYPE option. If found, it |
677 | | /// sets the requested message type as its value. If not, it creates a ::DHCPOPT_DHCP_MESSAGE_TYPE option and |
678 | | /// sets the requested message type as its value |
679 | | /// @param[in] msgType Message type to set |
680 | | /// @return True if message type was set successfully or false if msgType is ::DHCP_UNKNOWN_MSG_TYPE or if |
681 | | /// failed to add |
682 | | /// ::DHCPOPT_DHCP_MESSAGE_TYPE option |
683 | | bool setMessageType(DhcpMessageType msgType); |
684 | | |
685 | | /// @return The first DHCP option in the packet. If there are no DHCP options the returned value will contain |
686 | | /// a logical null (DhcpOption#isNull() == true) |
687 | | DhcpOption getFirstOptionData() const; |
688 | | |
689 | | /// Get the DHCP option that comes after a given option. If the given option was the last one, the |
690 | | /// returned value will contain a logical null (DhcpOption#isNull() == true) |
691 | | /// @param[in] dhcpOption A given DHCP option |
692 | | /// @return A DhcpOption object containing the option data that comes next, or logical null if the given DHCP |
693 | | /// option: (1) was the last one; (2) contains a logical null or (3) doesn't belong to this packet |
694 | | DhcpOption getNextOptionData(DhcpOption dhcpOption) const; |
695 | | |
696 | | /// Get a DHCP option by type |
697 | | /// @param[in] option DHCP option type |
698 | | /// @return A DhcpOption object containing the first DHCP option data that matches this type, or logical null |
699 | | /// (DhcpOption#isNull() == true) if no such option found |
700 | | DhcpOption getOptionData(DhcpOptionTypes option) const; |
701 | | |
702 | | /// @return The number of DHCP options in this layer |
703 | | size_t getOptionsCount() const; |
704 | | |
705 | | /// Add a new DHCP option at the end of the layer |
706 | | /// @param[in] optionBuilder A DhcpOptionBuilder object that contains the requested DHCP option data to add |
707 | | /// @return A DhcpOption object containing the newly added DHCP option data or logical null |
708 | | /// (DhcpOption#isNull() == true) if addition failed |
709 | | DhcpOption addOption(const DhcpOptionBuilder& optionBuilder); |
710 | | |
711 | | /// Add a new DHCP option after an existing one |
712 | | /// @param[in] optionBuilder A DhcpOptionBuilder object that contains the requested DHCP option data to add |
713 | | /// @param[in] prevOption The DHCP option type which the newly added option will come after |
714 | | /// @return A DhcpOption object containing the newly added DHCP option data or logical null |
715 | | /// (DhcpOption#isNull() == true) if addition failed |
716 | | DhcpOption addOptionAfter(const DhcpOptionBuilder& optionBuilder, DhcpOptionTypes prevOption); |
717 | | |
718 | | /// Remove an existing DHCP option from the layer |
719 | | /// @param[in] optionType The DHCP option type to remove |
720 | | /// @return True if DHCP option was successfully removed or false if type wasn't found or if removal failed |
721 | | bool removeOption(DhcpOptionTypes optionType); |
722 | | |
723 | | /// Remove all DHCP options in this layer |
724 | | /// @return True if all DHCP options were successfully removed or false if removal failed for some reason |
725 | | bool removeAllOptions(); |
726 | | |
727 | | /// A static method that checks whether a pair of ports are considered DHCP ports |
728 | | /// @param[in] portSrc The source port number to check |
729 | | /// @param[in] portDst The destination port number to check |
730 | | /// @return True if these are DHCP port numbers, false otherwise |
731 | | static inline bool isDhcpPorts(uint16_t portSrc, uint16_t portDst); |
732 | | |
733 | | // implement abstract methods |
734 | | |
735 | | /// Does nothing for this layer (DhcpLayer is always last) |
736 | | void parseNextLayer() override |
737 | 6.65k | {} |
738 | | |
739 | | /// @return The size of @ref dhcp_header + size of options |
740 | | size_t getHeaderLen() const override |
741 | 67.7k | { |
742 | 67.7k | return m_DataLen; |
743 | 67.7k | } |
744 | | |
745 | | /// Calculate the following fields: |
746 | | /// - @ref dhcp_header#magicNumber = DHCP magic number (0x63538263) |
747 | | /// - @ref dhcp_header#opCode = ::DHCP_BOOTREQUEST for message types: ::DHCP_DISCOVER, ::DHCP_REQUEST, |
748 | | /// ::DHCP_DECLINE, ::DHCP_RELEASE, |
749 | | /// ::DHCP_INFORM, ::DHCP_UNKNOWN_MSG_TYPE |
750 | | /// ::DHCP_BOOTREPLY for message types: ::DHCP_OFFER, ::DHCP_ACK, ::DHCP_NAK |
751 | | /// - @ref dhcp_header#hardwareType = 1 (Ethernet) |
752 | | /// - @ref dhcp_header#hardwareAddressLength = 6 (MAC address length) |
753 | | void computeCalculateFields() override; |
754 | | |
755 | | std::string toString() const override; |
756 | | |
757 | | OsiModelLayer getOsiModelLayer() const override |
758 | 1.31k | { |
759 | 1.31k | return OsiModelApplicationLayer; |
760 | 1.31k | } |
761 | | |
762 | | private: |
763 | | uint8_t* getOptionsBasePtr() const |
764 | 66.4k | { |
765 | 66.4k | return m_Data + sizeof(dhcp_header); |
766 | 66.4k | } |
767 | | |
768 | | TLVRecordReader<DhcpOption> m_OptionReader; |
769 | | |
770 | | void initDhcpLayer(size_t numOfBytesToAllocate); |
771 | | |
772 | | DhcpOption addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset); |
773 | | }; |
774 | | |
775 | | // implementation of inline methods |
776 | | |
777 | | bool DhcpLayer::isDhcpPorts(uint16_t portSrc, uint16_t portDst) |
778 | 0 | { |
779 | 0 | return ((portSrc == 68 && portDst == 67) || (portSrc == 67 && portDst == 68) || |
780 | 0 | (portSrc == 67 && portDst == 67)); |
781 | 0 | } |
782 | | |
783 | | } // namespace pcpp |