Coverage Report

Created: 2023-01-17 06:15

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