Coverage Report

Created: 2026-10-17 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/DhcpLayer.cpp
Line
Count
Source
1
0
#define LOG_MODULE PacketLogModuleDhcpLayer
2
3
#include "DhcpLayer.h"
4
#include "Logger.h"
5
#include "EndianPortable.h"
6
#include "Serializers.h"
7
#include "GeneralUtils.h"
8
9
namespace pcpp
10
{
11
12
  constexpr uint32_t DhcpMagicNumber = 0x63538263;
13
14
  DhcpOption DhcpOptionBuilder::build() const
15
0
  {
16
0
    size_t recSize = 2 * sizeof(uint8_t) + m_RecValueLen;
17
0
    uint8_t recType = static_cast<uint8_t>(m_RecType);
18
19
0
    if ((recType == DHCPOPT_END || recType == DHCPOPT_PAD))
20
0
    {
21
0
      if (m_RecValueLen != 0)
22
0
      {
23
0
        PCPP_LOG_ERROR(
24
0
            "Can't set DHCP END option or DHCP PAD option with size different than 0, tried to set size "
25
0
            << (int)m_RecValueLen);
26
0
        return DhcpOption(nullptr);
27
0
      }
28
29
0
      recSize = sizeof(uint8_t);
30
0
    }
31
32
0
    uint8_t* recordBuffer = new uint8_t[recSize];
33
0
    memset(recordBuffer, 0, recSize);
34
0
    recordBuffer[0] = recType;
35
0
    if (recSize > 1)
36
0
    {
37
0
      recordBuffer[1] = static_cast<uint8_t>(m_RecValueLen);
38
0
      if (m_RecValue != nullptr)
39
0
        memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen);
40
0
      else
41
0
        memset(recordBuffer + 2, 0, m_RecValueLen);
42
0
    }
43
44
0
    return DhcpOption(recordBuffer);
45
0
  }
46
47
  DhcpLayer::DhcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
48
0
      : Layer(data, dataLen, prevLayer, packet, DHCP)
49
0
  {}
50
51
  void DhcpLayer::initDhcpLayer(size_t numOfBytesToAllocate)
52
0
  {
53
0
    allocData(numOfBytesToAllocate);
54
0
    m_Protocol = DHCP;
55
0
  }
56
57
0
  DhcpLayer::DhcpLayer() : Layer()
58
0
  {
59
0
    initDhcpLayer(sizeof(dhcp_header));
60
0
  }
61
62
0
  DhcpLayer::DhcpLayer(DhcpMessageType msgType, const MacAddress& clientMacAddr) : Layer()
63
0
  {
64
0
    initDhcpLayer(sizeof(dhcp_header) + 4 * sizeof(uint8_t));
65
66
0
    setClientHardwareAddress(clientMacAddr);
67
68
0
    uint8_t* msgTypeOptionPtr = m_Data + sizeof(dhcp_header);
69
0
    msgTypeOptionPtr[0] = (uint8_t)DHCPOPT_DHCP_MESSAGE_TYPE;  // option code
70
0
    msgTypeOptionPtr[1] = 1;                                   // option len
71
0
    msgTypeOptionPtr[2] = (uint8_t)msgType;                    // option data - message type
72
73
0
    msgTypeOptionPtr[3] = (uint8_t)DHCPOPT_END;
74
0
  }
75
76
  MacAddress DhcpLayer::getClientHardwareAddress() const
77
0
  {
78
0
    dhcp_header* hdr = getDhcpHeader();
79
0
    if (hdr != nullptr && hdr->hardwareType == 1 && hdr->hardwareAddressLength == 6)
80
0
      return MacAddress(hdr->clientHardwareAddress);
81
82
0
    PCPP_LOG_DEBUG("Hardware type isn't Ethernet or hardware addr len != 6, returning MacAddress:Zero");
83
84
0
    return MacAddress::Zero;
85
0
  }
86
87
  void DhcpLayer::setClientHardwareAddress(const MacAddress& addr)
88
0
  {
89
0
    dhcp_header* hdr = getDhcpHeader();
90
0
    hdr->hardwareType = 1;           // Ethernet
91
0
    hdr->hardwareAddressLength = 6;  // MAC address length
92
0
    addr.copyTo(hdr->clientHardwareAddress);
93
0
  }
94
95
  void DhcpLayer::computeCalculateFields()
96
0
  {
97
0
    dhcp_header* hdr = getDhcpHeader();
98
99
0
    hdr->magicNumber = DhcpMagicNumber;
100
101
0
    DhcpMessageType msgType = getMessageType();
102
0
    switch (msgType)
103
0
    {
104
0
    case DHCP_DISCOVER:
105
0
    case DHCP_REQUEST:
106
0
    case DHCP_DECLINE:
107
0
    case DHCP_RELEASE:
108
0
    case DHCP_INFORM:
109
0
    case DHCP_UNKNOWN_MSG_TYPE:
110
0
      hdr->opCode = DHCP_BOOTREQUEST;
111
0
      break;
112
0
    case DHCP_OFFER:
113
0
    case DHCP_ACK:
114
0
    case DHCP_NAK:
115
0
      hdr->opCode = DHCP_BOOTREPLY;
116
0
      break;
117
0
    default:
118
0
      break;
119
0
    }
120
121
0
    hdr->hardwareType = 1;           // Ethernet
122
0
    hdr->hardwareAddressLength = 6;  // MAC address length
123
0
  }
124
125
  std::string DhcpLayer::toString() const
126
0
  {
127
0
    std::string msgType = "Unknown";
128
0
    switch (getMessageType())
129
0
    {
130
0
    case DHCP_DISCOVER:
131
0
    {
132
0
      msgType = "Discover";
133
0
      break;
134
0
    }
135
0
    case DHCP_OFFER:
136
0
    {
137
0
      msgType = "Offer";
138
0
      break;
139
0
    }
140
0
    case DHCP_REQUEST:
141
0
    {
142
0
      msgType = "Request";
143
0
      break;
144
0
    }
145
0
    case DHCP_DECLINE:
146
0
    {
147
0
      msgType = "Decline";
148
0
      break;
149
0
    }
150
0
    case DHCP_ACK:
151
0
    {
152
0
      msgType = "Acknowledge";
153
0
      break;
154
0
    }
155
0
    case DHCP_NAK:
156
0
    {
157
0
      msgType = "Negative Acknowledge";
158
0
      break;
159
0
    }
160
0
    case DHCP_RELEASE:
161
0
    {
162
0
      msgType = "Release";
163
0
      break;
164
0
    }
165
0
    case DHCP_INFORM:
166
0
    {
167
0
      msgType = "Inform";
168
0
      break;
169
0
    }
170
0
    default:
171
0
      break;
172
0
    }
173
174
0
    return "DHCP layer (" + msgType + ")";
175
0
  }
176
177
  DhcpMessageType DhcpLayer::getMessageType() const
178
0
  {
179
0
    DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE);
180
0
    if (opt.isNull())
181
0
      return DHCP_UNKNOWN_MSG_TYPE;
182
183
0
    return (DhcpMessageType)opt.getValueAs<uint8_t>();
184
0
  }
185
186
  bool DhcpLayer::setMessageType(DhcpMessageType msgType)
187
0
  {
188
0
    if (msgType == DHCP_UNKNOWN_MSG_TYPE)
189
0
      return false;
190
191
0
    DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE);
192
0
    if (opt.isNull())
193
0
    {
194
0
      opt = addOptionAfter(DhcpOptionBuilder(DHCPOPT_DHCP_MESSAGE_TYPE, (uint8_t)msgType), DHCPOPT_UNKNOWN);
195
0
      if (opt.isNull())
196
0
        return false;
197
0
    }
198
199
0
    opt.setValue<uint8_t>((uint8_t)msgType);
200
0
    return true;
201
0
  }
202
203
  DhcpOption DhcpLayer::getOptionData(DhcpOptionTypes option) const
204
0
  {
205
0
    return m_OptionReader.getTLVRecord((uint8_t)option, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
206
0
  }
207
208
  DhcpOption DhcpLayer::getFirstOptionData() const
209
0
  {
210
0
    return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
211
0
  }
212
213
  DhcpOption DhcpLayer::getNextOptionData(DhcpOption dhcpOption) const
214
0
  {
215
0
    return m_OptionReader.getNextTLVRecord(dhcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
216
0
  }
217
218
  size_t DhcpLayer::getOptionsCount() const
219
0
  {
220
0
    return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header));
221
0
  }
222
223
  DhcpOption DhcpLayer::addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset)
224
0
  {
225
0
    DhcpOption newOpt = optionBuilder.build();
226
227
0
    if (newOpt.isNull())
228
0
    {
229
0
      PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOpt.getType());
230
0
      return DhcpOption(nullptr);
231
0
    }
232
233
0
    size_t sizeToExtend = newOpt.getTotalSize();
234
235
0
    if (!extendLayer(offset, sizeToExtend))
236
0
    {
237
0
      PCPP_LOG_ERROR("Could not extend DhcpLayer in [" << newOpt.getTotalSize() << "] bytes");
238
0
      newOpt.purgeRecordData();
239
0
      return DhcpOption(nullptr);
240
0
    }
241
242
0
    memcpy(m_Data + offset, newOpt.getRecordBasePtr(), newOpt.getTotalSize());
243
244
0
    uint8_t* newOptPtr = m_Data + offset;
245
246
0
    m_OptionReader.changeTLVRecordCount(1);
247
248
0
    newOpt.purgeRecordData();
249
250
0
    return DhcpOption(newOptPtr);
251
0
  }
252
253
  DhcpOption DhcpLayer::addOption(const DhcpOptionBuilder& optionBuilder)
254
0
  {
255
0
    int offset = 0;
256
0
    DhcpOption endOpt = getOptionData(DHCPOPT_END);
257
0
    if (!endOpt.isNull())
258
0
      offset = endOpt.getRecordBasePtr() - m_Data;
259
0
    else
260
0
      offset = getHeaderLen();
261
262
0
    return addOptionAt(optionBuilder, offset);
263
0
  }
264
265
  DhcpOption DhcpLayer::addOptionAfter(const DhcpOptionBuilder& optionBuilder, DhcpOptionTypes prevOption)
266
0
  {
267
0
    int offset = 0;
268
269
0
    DhcpOption prevOpt = getOptionData(prevOption);
270
271
0
    if (prevOpt.isNull())
272
0
    {
273
0
      offset = sizeof(dhcp_header);
274
0
    }
275
0
    else
276
0
    {
277
0
      offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data;
278
0
    }
279
280
0
    return addOptionAt(optionBuilder, offset);
281
0
  }
282
283
  bool DhcpLayer::removeOption(DhcpOptionTypes optionType)
284
0
  {
285
0
    DhcpOption optToRemove = getOptionData(optionType);
286
0
    if (optToRemove.isNull())
287
0
    {
288
0
      return false;
289
0
    }
290
291
0
    int offset = optToRemove.getRecordBasePtr() - m_Data;
292
293
0
    if (!shortenLayer(offset, optToRemove.getTotalSize()))
294
0
    {
295
0
      return false;
296
0
    }
297
298
0
    m_OptionReader.changeTLVRecordCount(-1);
299
0
    return true;
300
0
  }
301
302
  bool DhcpLayer::removeAllOptions()
303
0
  {
304
0
    int offset = sizeof(dhcp_header);
305
306
0
    if (!shortenLayer(offset, getHeaderLen() - offset))
307
0
      return false;
308
309
0
    m_OptionReader.changeTLVRecordCount(0 - getOptionsCount());
310
0
    return true;
311
0
  }
312
313
  static constexpr const char* dhcpMessageTypeToString(DhcpMessageType msgType)
314
0
  {
315
0
    switch (msgType)
316
0
    {
317
0
    case DHCP_DISCOVER:
318
0
      return "Discover";
319
0
    case DHCP_OFFER:
320
0
      return "Offer";
321
0
    case DHCP_REQUEST:
322
0
      return "Request";
323
0
    case DHCP_DECLINE:
324
0
      return "Decline";
325
0
    case DHCP_ACK:
326
0
      return "Acknowledge";
327
0
    case DHCP_NAK:
328
0
      return "Negative Acknowledge";
329
0
    case DHCP_RELEASE:
330
0
      return "Release";
331
0
    case DHCP_INFORM:
332
0
      return "Inform";
333
0
    default:
334
0
      return "Unknown";
335
0
    }
336
0
  }
337
338
  static constexpr const char* dhcpOptionTypeToString(DhcpOptionTypes optType)
339
0
  {
340
0
    switch (optType)
341
0
    {
342
0
    case DHCPOPT_PAD:
343
0
      return "Pad";
344
0
    case DHCPOPT_SUBNET_MASK:
345
0
      return "SubnetMask";
346
0
    case DHCPOPT_TIME_OFFSET:
347
0
      return "TimeOffset";
348
0
    case DHCPOPT_ROUTERS:
349
0
      return "Routers";
350
0
    case DHCPOPT_TIME_SERVERS:
351
0
      return "TimeServers";
352
0
    case DHCPOPT_NAME_SERVERS:
353
0
      return "NameServers";
354
0
    case DHCPOPT_DOMAIN_NAME_SERVERS:
355
0
      return "DomainNameServers";
356
0
    case DHCPOPT_LOG_SERVERS:
357
0
      return "LogServers";
358
0
    case DHCPOPT_QUOTES_SERVERS:
359
0
      return "QuotesServers";
360
0
    case DHCPOPT_LPR_SERVERS:
361
0
      return "LprServers";
362
0
    case DHCPOPT_IMPRESS_SERVERS:
363
0
      return "ImpressServers";
364
0
    case DHCPOPT_RESOURCE_LOCATION_SERVERS:
365
0
      return "ResourceLocationServers";
366
0
    case DHCPOPT_HOST_NAME:
367
0
      return "HostName";
368
0
    case DHCPOPT_BOOT_SIZE:
369
0
      return "BootSize";
370
0
    case DHCPOPT_MERIT_DUMP:
371
0
      return "MeritDump";
372
0
    case DHCPOPT_DOMAIN_NAME:
373
0
      return "DomainName";
374
0
    case DHCPOPT_SWAP_SERVER:
375
0
      return "SwapServer";
376
0
    case DHCPOPT_ROOT_PATH:
377
0
      return "RootPath";
378
0
    case DHCPOPT_EXTENSIONS_PATH:
379
0
      return "ExtensionsPath";
380
0
    case DHCPOPT_IP_FORWARDING:
381
0
      return "IPForwarding";
382
0
    case DHCPOPT_NON_LOCAL_SOURCE_ROUTING:
383
0
      return "NonLocalSourceRouting";
384
0
    case DHCPOPT_POLICY_FILTER:
385
0
      return "PolicyFilter";
386
0
    case DHCPOPT_MAX_DGRAM_REASSEMBLY:
387
0
      return "MaxDatagramReassemblySize";
388
0
    case DEFAULT_IP_TTL:
389
0
      return "DefaultIPTTL";
390
0
    case DHCPOPT_PATH_MTU_AGING_TIMEOUT:
391
0
      return "PathMTUAgingTimeout";
392
0
    case PATH_MTU_PLATEAU_TABLE:
393
0
      return "PathMTUPlateauTable";
394
0
    case DHCPOPT_INTERFACE_MTU:
395
0
      return "InterfaceMTU";
396
0
    case DHCPOPT_ALL_SUBNETS_LOCAL:
397
0
      return "AllSubnetsAreLocal";
398
0
    case DHCPOPT_BROADCAST_ADDRESS:
399
0
      return "BroadcastAddress";
400
0
    case DHCPOPT_PERFORM_MASK_DISCOVERY:
401
0
      return "PerformMaskDiscovery";
402
0
    case DHCPOPT_MASK_SUPPLIER:
403
0
      return "MaskSupplier";
404
0
    case DHCPOPT_ROUTER_DISCOVERY:
405
0
      return "RouterDiscovery";
406
0
    case DHCPOPT_ROUTER_SOLICITATION_ADDRESS:
407
0
      return "RouterSolicitationAddress";
408
0
    case DHCPOPT_STATIC_ROUTES:
409
0
      return "StaticRoutes";
410
0
    case DHCPOPT_TRAILER_ENCAPSULATION:
411
0
      return "TrailerEncapsulation";
412
0
    case DHCPOPT_ARP_CACHE_TIMEOUT:
413
0
      return "ARPCacheTimeout";
414
0
    case DHCPOPT_IEEE802_3_ENCAPSULATION:
415
0
      return "IEEE802_3Encapsulation";
416
0
    case DHCPOPT_DEFAULT_TCP_TTL:
417
0
      return "DefaultTCPTTL";
418
0
    case DHCPOPT_TCP_KEEPALIVE_INTERVAL:
419
0
      return "TCPKeepaliveInterval";
420
0
    case DHCPOPT_TCP_KEEPALIVE_GARBAGE:
421
0
      return "TCPKeepaliveGarbage";
422
0
    case DHCPOPT_NIS_DOMAIN:
423
0
      return "NISDomain";
424
0
    case DHCPOPT_NIS_SERVERS:
425
0
      return "NISServers";
426
0
    case DHCPOPT_NTP_SERVERS:
427
0
      return "NTPServers";
428
0
    case DHCPOPT_VENDOR_ENCAPSULATED_OPTIONS:
429
0
      return "VendorEncapsulatedOptions";
430
0
    case DHCPOPT_NETBIOS_NAME_SERVERS:
431
0
      return "NetBIOSNameServers";
432
0
    case DHCPOPT_NETBIOS_DD_SERVER:
433
0
      return "NetBIOSDatagramDistributionServer";
434
0
    case DHCPOPT_NETBIOS_NODE_TYPE:
435
0
      return "NetBIOSNodeType";
436
0
    case DHCPOPT_NETBIOS_SCOPE:
437
0
      return "NetBIOSScope";
438
0
    case DHCPOPT_FONT_SERVERS:
439
0
      return "FontServers";
440
0
    case DHCPOPT_X_DISPLAY_MANAGER:
441
0
      return "XDisplayManager";
442
0
    case DHCPOPT_DHCP_REQUESTED_ADDRESS:
443
0
      return "RequestedIPAddress";
444
0
    case DHCPOPT_DHCP_LEASE_TIME:
445
0
      return "IPAddressLeaseTime";
446
0
    case DHCPOPT_DHCP_OPTION_OVERLOAD:
447
0
      return "OptionOverload";
448
0
    case DHCPOPT_DHCP_MESSAGE_TYPE:
449
0
      return "DHCPMessageType";
450
0
    case DHCPOPT_DHCP_SERVER_IDENTIFIER:
451
0
      return "ServerIdentifier";
452
0
    case DHCPOPT_DHCP_PARAMETER_REQUEST_LIST:
453
0
      return "ParameterRequestList";
454
0
    case DHCPOPT_DHCP_MESSAGE:
455
0
      return "DHCPErrorMessage";
456
0
    case DHCPOPT_DHCP_MAX_MESSAGE_SIZE:
457
0
      return "DHCPMaxMessageSize";
458
0
    case DHCPOPT_DHCP_RENEWAL_TIME:
459
0
      return "RenewalTime";
460
0
    case DHCPOPT_DHCP_REBINDING_TIME:
461
0
      return "RebindingTime";
462
0
    case DHCPOPT_VENDOR_CLASS_IDENTIFIER:
463
0
      return "VendorClassIdentifier";
464
0
    case DHCPOPT_DHCP_CLIENT_IDENTIFIER:
465
0
      return "ClientIdentifier";
466
0
    case DHCPOPT_NWIP_DOMAIN_NAME:
467
0
      return "NWIPDomainName";
468
0
    case DHCPOPT_NWIP_SUBOPTIONS:
469
0
      return "NWIPSubOptions";
470
0
    case DHCPOPT_NIS_DOMAIN_NAME:
471
0
      return "NISPlusDomainName";
472
0
    case DHCPOPT_NIS_SERVER_ADDRESS:
473
0
      return "NISPlusServerAddress";
474
0
    case DHCPOPT_TFTP_SERVER_NAME:
475
0
      return "TFTPServerName";
476
0
    case DHCPOPT_BOOTFILE_NAME:
477
0
      return "BootfileName";
478
0
    case DHCPOPT_HOME_AGENT_ADDRESS:
479
0
      return "HomeAgentAddress";
480
0
    case DHCPOPT_SMTP_SERVER:
481
0
      return "SMTPServer";
482
0
    case DHCPOPT_POP3_SERVER:
483
0
      return "POP3Server";
484
0
    case DHCPOPT_NNTP_SERVER:
485
0
      return "NNTPServer";
486
0
    case DHCPOPT_WWW_SERVER:
487
0
      return "WWWServer";
488
0
    case DHCPOPT_FINGER_SERVER:
489
0
      return "FingerServer";
490
0
    case DHCPOPT_IRC_SERVER:
491
0
      return "IRCServer";
492
0
    case DHCPOPT_STREETTALK_SERVER:
493
0
      return "StreetTalkServer";
494
0
    case DHCPOPT_STDA_SERVER:
495
0
      return "STDAServer";
496
0
    case DHCPOPT_USER_CLASS:
497
0
      return "UserClass";
498
0
    case DHCPOPT_DIRECTORY_AGENT:
499
0
      return "DirectoryAgent";
500
0
    case DHCPOPT_SERVICE_SCOPE:
501
0
      return "ServiceScope";
502
0
    case DHCPOPT_RAPID_COMMIT:
503
0
      return "RapidCommit";
504
0
    case DHCPOPT_FQDN:
505
0
      return "FQDN";
506
0
    case DHCPOPT_DHCP_AGENT_OPTIONS:
507
0
      return "RelayAgentInformation";
508
0
    case DHCPOPT_ISNS:
509
0
      return "ISNS";
510
0
    case DHCPOPT_NDS_SERVERS:
511
0
      return "NDSServers";
512
0
    case DHCPOPT_NDS_TREE_NAME:
513
0
      return "NDSTreeName";
514
0
    case DHCPOPT_NDS_CONTEXT:
515
0
      return "NDSContext";
516
0
    case DHCPOPT_BCMCS_CONTROLLER_DOMAIN_NAME_LIST:
517
0
      return "BCMCSDomainNameList";
518
0
    case DHCPOPT_BCMCS_CONTROLLER_IPV4_ADDRESS:
519
0
      return "BCMCSIPv4Address";
520
0
    case DHCPOPT_AUTHENTICATION:
521
0
      return "Authentication";
522
0
    case DHCPOPT_CLIENT_LAST_TXN_TIME:
523
0
      return "ClientLastTransactionTime";
524
0
    case DHCPOPT_ASSOCIATED_IP:
525
0
      return "AssociatedIP";
526
0
    case DHCPOPT_CLIENT_SYSTEM:
527
0
      return "ClientSystem";
528
0
    case DHCPOPT_CLIENT_NDI:
529
0
      return "ClientNDI";
530
0
    case DHCPOPT_LDAP:
531
0
      return "LDAP";
532
0
    case DHCPOPT_UUID_GUID:
533
0
      return "UUID_GUID";
534
0
    case DHCPOPT_USER_AUTH:
535
0
      return "UserAuthentication";
536
0
    case DHCPOPT_GEOCONF_CIVIC:
537
0
      return "GeoConfCivic";
538
0
    case DHCPOPT_PCODE:
539
0
      return "PCode";
540
0
    case DHCPOPT_TCODE:
541
0
      return "TCode";
542
0
    case DHCPOPT_NETINFO_ADDRESS:
543
0
      return "NetInfoAddress";
544
0
    case DHCPOPT_NETINFO_TAG:
545
0
      return "NetInfoTag";
546
0
    case DHCPOPT_URL:
547
0
      return "URL";
548
0
    case DHCPOPT_AUTO_CONFIG:
549
0
      return "AutoConfig";
550
0
    case DHCPOPT_NAME_SERVICE_SEARCH:
551
0
      return "NameServiceSearch";
552
0
    case DHCPOPT_SUBNET_SELECTION:
553
0
      return "SubnetSelection";
554
0
    case DHCPOPT_DOMAIN_SEARCH:
555
0
      return "DomainSearch";
556
0
    case DHCPOPT_SIP_SERVERS:
557
0
      return "SIPServers";
558
0
    case DHCPOPT_CLASSLESS_STATIC_ROUTE:
559
0
      return "ClasslessStaticRoute";
560
0
    case DHCPOPT_CCC:
561
0
      return "CableLabsClientConfig";
562
0
    case DHCPOPT_GEOCONF:
563
0
      return "GeoConf";
564
0
    case DHCPOPT_V_I_VENDOR_CLASS:
565
0
      return "VendorIdentifyingVendorClass";
566
0
    case DHCPOPT_V_I_VENDOR_OPTS:
567
0
      return "VendorIdentifyingVendorSpecificInfo";
568
0
    case DHCPOPT_OPTION_PANA_AGENT:
569
0
      return "PANAAgent";
570
0
    case DHCPOPT_OPTION_V4_LOST:
571
0
      return "V4Lost";
572
0
    case DHCPOPT_OPTION_CAPWAP_AC_V4:
573
0
      return "CapwapAcV4";
574
0
    case DHCPOPT_OPTION_IPV4_ADDRESS_MOS:
575
0
      return "IPv4AddressMOS";
576
0
    case DHCPOPT_OPTION_IPV4_FQDN_MOS:
577
0
      return "IPv4FqdnMOS";
578
0
    case DHCPOPT_SIP_UA_CONFIG:
579
0
      return "SIPUAConfig";
580
0
    case DHCPOPT_OPTION_IPV4_ADDRESS_ANDSF:
581
0
      return "IPv4AddressANDSF";
582
0
    case DHCPOPT_GEOLOC:
583
0
      return "GeoLoc";
584
0
    case DHCPOPT_FORCERENEW_NONCE_CAPABLE:
585
0
      return "ForceRenewNonceCapable";
586
0
    case DHCPOPT_RDNSS_SELECTION:
587
0
      return "RDNSSSelection";
588
0
    case DHCPOPT_STATUS_CODE:
589
0
      return "StatusCode";
590
0
    case DHCPOPT_BASE_TIME:
591
0
      return "BaseTime";
592
0
    case DHCPOPT_START_TIME_OF_STATE:
593
0
      return "StartTimeOfState";
594
0
    case DHCPOPT_QUERY_START_TIME:
595
0
      return "QueryStartTime";
596
0
    case DHCPOPT_QUERY_END_TIME:
597
0
      return "QueryEndTime";
598
0
    case DHCPOPT_DHCP_STATE:
599
0
      return "DHCPState";
600
0
    case DHCPOPT_DATA_SOURCE:
601
0
      return "DataSource";
602
0
    case DHCPOPT_OPTION_V4_PCP_SERVER:
603
0
      return "OptionV4PcpServer";
604
0
    case DHCPOPT_OPTION_V4_PORTPARAMS:
605
0
      return "OptionV4PortParams";
606
0
    case DHCPOPT_CAPTIVE_PORTAL:
607
0
      return "CaptivePortal";
608
0
    case DHCPOPT_OPTION_MUD_URL_V4:
609
0
      return "OptionMudUrlV4";
610
0
    case DHCPOPT_ETHERBOOT:
611
0
      return "Etherboot";
612
0
    case DHCPOPT_IP_TELEPHONE:
613
0
      return "IPTelephone";
614
0
    case DHCPOPT_PXELINUX_MAGIC:
615
0
      return "PxeLinuxMagic";
616
0
    case DHCPOPT_CONFIGURATION_FILE:
617
0
      return "ConfigurationFile";
618
0
    case DHCPOPT_PATH_PREFIX:
619
0
      return "PathPrefix";
620
0
    case DHCPOPT_REBOOT_TIME:
621
0
      return "RebootTime";
622
0
    case DHCPOPT_OPTION_6RD:
623
0
      return "Option6RD";
624
0
    case DHCPOPT_OPTION_V4_ACCESS_DOMAIN:
625
0
      return "OptionV4AccessDomain";
626
0
    case DHCPOPT_SUBNET_ALLOCATION:
627
0
      return "SubnetAllocation";
628
0
    case DHCPOPT_VIRTUAL_SUBNET_SELECTION:
629
0
      return "VirtualSubnetSelection";
630
0
    case DHCPOPT_END:
631
0
      return "End";
632
0
    default:
633
0
      return "Unknown";
634
0
    }
635
0
  }
636
637
  const FieldDescriptor DhcpLayer::SerializedFields::OpCode{ Layer::SerializedFields::MaxID + 1, "opCode" };
638
  const FieldDescriptor DhcpLayer::SerializedFields::HardwareType{ Layer::SerializedFields::MaxID + 2,
639
                                                                 "hardwareType" };
640
  const FieldDescriptor DhcpLayer::SerializedFields::HardwareAddressLength{ Layer::SerializedFields::MaxID + 3,
641
                                                                          "hardwareAddressLength" };
642
  const FieldDescriptor DhcpLayer::SerializedFields::Hops{ Layer::SerializedFields::MaxID + 4, "hops" };
643
  const FieldDescriptor DhcpLayer::SerializedFields::TransactionID{ Layer::SerializedFields::MaxID + 5,
644
                                                                  "transactionID" };
645
  const FieldDescriptor DhcpLayer::SerializedFields::SecondsElapsed{ Layer::SerializedFields::MaxID + 6,
646
                                                                   "secondsElapsed" };
647
  const FieldDescriptor DhcpLayer::SerializedFields::Flags{ Layer::SerializedFields::MaxID + 7, "flags" };
648
  const FieldDescriptor DhcpLayer::SerializedFields::ClientIpAddress{ Layer::SerializedFields::MaxID + 8,
649
                                                                    "clientIpAddress" };
650
  const FieldDescriptor DhcpLayer::SerializedFields::YourIpAddress{ Layer::SerializedFields::MaxID + 9,
651
                                                                  "yourIpAddress" };
652
  const FieldDescriptor DhcpLayer::SerializedFields::ServerIpAddress{ Layer::SerializedFields::MaxID + 10,
653
                                                                    "serverIpAddress" };
654
  const FieldDescriptor DhcpLayer::SerializedFields::GatewayIpAddress{ Layer::SerializedFields::MaxID + 11,
655
                                                                     "gatewayIpAddress" };
656
  const FieldDescriptor DhcpLayer::SerializedFields::ClientHardwareAddress{ Layer::SerializedFields::MaxID + 12,
657
                                                                          "clientHardwareAddress" };
658
  const FieldDescriptor DhcpLayer::SerializedFields::MessageType{ Layer::SerializedFields::MaxID + 14,
659
                                                                "messageType" };
660
  const FieldDescriptor DhcpLayer::SerializedFields::Options{ Layer::SerializedFields::MaxID + 15, "options" };
661
  const FieldDescriptor DhcpLayer::SerializedFields::Option{ 0, "option" };
662
663
  void DhcpLayer::serializeLayer(ObjectScope& serializer) const
664
0
  {
665
0
    const dhcp_header* hdr = getDhcpHeader();
666
0
    serializer.writeField(SerializedFields::OpCode, getOpCode() == DHCP_BOOTREQUEST ? "BootRequest"
667
0
                                                    : getOpCode() == DHCP_BOOTREPLY ? "BootReply"
668
0
                                                                                    : "Unknown");
669
0
    serializer.writeField(SerializedFields::HardwareType, hdr->hardwareType);
670
0
    serializer.writeField(SerializedFields::HardwareAddressLength, hdr->hardwareAddressLength);
671
0
    serializer.writeField(SerializedFields::Hops, hdr->hops);
672
0
    serializer.writeHexField(SerializedFields::TransactionID, be32toh(hdr->transactionID));
673
0
    serializer.writeField(SerializedFields::SecondsElapsed, be16toh(hdr->secondsElapsed));
674
0
    serializer.writeHexField(SerializedFields::Flags, be16toh(hdr->flags));
675
0
    serializer.writeField(SerializedFields::ClientIpAddress, getClientIpAddress().toString());
676
0
    serializer.writeField(SerializedFields::YourIpAddress, getYourIpAddress().toString());
677
0
    serializer.writeField(SerializedFields::ServerIpAddress, getServerIpAddress().toString());
678
0
    serializer.writeField(SerializedFields::GatewayIpAddress, getGatewayIpAddress().toString());
679
0
    serializer.writeField(SerializedFields::ClientHardwareAddress, getClientHardwareAddress().toString());
680
0
    serializer.writeField(SerializedFields::MessageType, dhcpMessageTypeToString(getMessageType()));
681
0
    auto options = serializer.writeArray(SerializedFields::Options);
682
0
    for (auto opt = getFirstOptionData(); opt.isNotNull(); opt = getNextOptionData(opt))
683
0
    {
684
0
      options.writeField(SerializedFields::Option,
685
0
                         dhcpOptionTypeToString(static_cast<DhcpOptionTypes>(opt.getType())));
686
0
    }
687
0
  }
688
689
}  // namespace pcpp