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