Coverage Report

Created: 2026-11-12 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Packet++/src/DnsLayer.cpp
Line
Count
Source
1
199k
#define LOG_MODULE PacketLogModuleDnsLayer
2
3
#include "DnsLayer.h"
4
#include "Logger.h"
5
#include <sstream>
6
#include <vector>
7
#include "EndianPortable.h"
8
9
namespace pcpp
10
{
11
12
  // ~~~~~~~~
13
  // DnsLayer
14
  // ~~~~~~~~
15
16
  DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
17
94.1k
      : Layer(data, dataLen, prevLayer, packet)
18
94.1k
  {
19
94.1k
    init(0, true);
20
94.1k
  }
21
22
  DnsLayer::DnsLayer()
23
0
  {
24
0
    initNewLayer(0);
25
0
  }
26
27
21.1k
  DnsLayer::DnsLayer(const DnsLayer& other) : Layer(other)
28
21.1k
  {
29
21.1k
    init(other.m_OffsetAdjustment, true);
30
21.1k
  }
31
32
  DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, size_t offsetAdjustment)
33
16.4k
      : Layer(data, dataLen, prevLayer, packet)
34
16.4k
  {
35
16.4k
    init(offsetAdjustment, true);
36
16.4k
  }
37
38
  DnsLayer::DnsLayer(size_t offsetAdjustment)
39
0
  {
40
0
    initNewLayer(offsetAdjustment);
41
0
  }
42
43
  DnsLayer& DnsLayer::operator=(const DnsLayer& other)
44
21.1k
  {
45
21.1k
    Layer::operator=(other);
46
47
21.1k
    IDnsResource* curResource = m_ResourceList;
48
56.9k
    while (curResource != nullptr)
49
35.7k
    {
50
35.7k
      IDnsResource* temp = curResource->getNextResource();
51
35.7k
      delete curResource;
52
35.7k
      curResource = temp;
53
35.7k
    }
54
55
21.1k
    init(other.m_OffsetAdjustment, true);
56
57
21.1k
    return (*this);
58
21.1k
  }
59
60
  DnsLayer::~DnsLayer()
61
131k
  {
62
131k
    IDnsResource* curResource = m_ResourceList;
63
327k
    while (curResource != nullptr)
64
195k
    {
65
195k
      IDnsResource* nextResource = curResource->getNextResource();
66
195k
      delete curResource;
67
195k
      curResource = nextResource;
68
195k
    }
69
131k
  }
70
71
  void DnsLayer::init(size_t offsetAdjustment, bool callParseResource)
72
152k
  {
73
152k
    m_OffsetAdjustment = offsetAdjustment;
74
152k
    m_Protocol = DNS;
75
152k
    m_ResourceList = nullptr;
76
77
152k
    m_FirstQuery = nullptr;
78
152k
    m_FirstAnswer = nullptr;
79
152k
    m_FirstAuthority = nullptr;
80
152k
    m_FirstAdditional = nullptr;
81
82
152k
    if (callParseResource)
83
152k
      parseResources();
84
152k
  }
85
86
  void DnsLayer::initNewLayer(size_t offsetAdjustment)
87
0
  {
88
0
    m_OffsetAdjustment = offsetAdjustment;
89
0
    const size_t headerLen = getBasicHeaderSize();
90
0
    allocData(headerLen);
91
92
0
    init(m_OffsetAdjustment, false);
93
0
  }
94
95
  size_t DnsLayer::getBasicHeaderSize()
96
237k
  {
97
237k
    return sizeof(dnshdr) + m_OffsetAdjustment;
98
237k
  }
99
100
  dnshdr* DnsLayer::getDnsHeader() const
101
1.33M
  {
102
1.33M
    uint8_t* ptr = m_Data + m_OffsetAdjustment;
103
1.33M
    return reinterpret_cast<dnshdr*>(ptr);
104
1.33M
  }
105
106
  bool DnsLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource* resource)
107
133k
  {
108
133k
    if (!Layer::extendLayer(offsetInLayer, numOfBytesToExtend))
109
16.2k
      return false;
110
111
117k
    IDnsResource* curResource = resource->getNextResource();
112
138k
    while (curResource != nullptr)
113
21.4k
    {
114
21.4k
      curResource->m_OffsetInLayer += numOfBytesToExtend;
115
21.4k
      curResource = curResource->getNextResource();
116
21.4k
    }
117
117k
    return true;
118
133k
  }
119
120
  bool DnsLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource)
121
66.2k
  {
122
66.2k
    if (!Layer::shortenLayer(offsetInLayer, numOfBytesToShorten))
123
386
      return false;
124
125
65.8k
    IDnsResource* curResource = resource->getNextResource();
126
81.4k
    while (curResource != nullptr)
127
15.5k
    {
128
15.5k
      curResource->m_OffsetInLayer -= numOfBytesToShorten;
129
15.5k
      curResource = curResource->getNextResource();
130
15.5k
    }
131
65.8k
    return true;
132
66.2k
  }
133
134
  void DnsLayer::parseResources()
135
152k
  {
136
152k
    size_t offsetInPacket = getBasicHeaderSize();
137
152k
    IDnsResource* curResource = m_ResourceList;
138
139
152k
    uint16_t numOfQuestions = be16toh(getDnsHeader()->numberOfQuestions);
140
152k
    uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers);
141
152k
    uint16_t numOfAuthority = be16toh(getDnsHeader()->numberOfAuthority);
142
152k
    uint16_t numOfAdditional = be16toh(getDnsHeader()->numberOfAdditional);
143
144
152k
    uint32_t numOfOtherResources = numOfQuestions + numOfAnswers + numOfAuthority + numOfAdditional;
145
146
152k
    if (numOfOtherResources > 300)
147
30.3k
    {
148
30.3k
      PCPP_LOG_ERROR(
149
30.3k
          "DNS layer contains more than 300 resources, probably a bad packet. Skipping parsing DNS resources");
150
30.3k
      return;
151
30.3k
    }
152
153
353k
    for (uint32_t i = 0; i < numOfOtherResources; i++)
154
280k
    {
155
280k
      DnsResourceType resType;
156
280k
      if (numOfQuestions > 0)
157
172k
      {
158
172k
        resType = DnsQueryType;
159
172k
        numOfQuestions--;
160
172k
      }
161
108k
      else if (numOfAnswers > 0)
162
42.4k
      {
163
42.4k
        resType = DnsAnswerType;
164
42.4k
        numOfAnswers--;
165
42.4k
      }
166
65.9k
      else if (numOfAuthority > 0)
167
27.0k
      {
168
27.0k
        resType = DnsAuthorityType;
169
27.0k
        numOfAuthority--;
170
27.0k
      }
171
38.8k
      else
172
38.8k
      {
173
38.8k
        resType = DnsAdditionalType;
174
38.8k
        numOfAdditional--;
175
38.8k
      }
176
177
280k
      DnsResource* newResource = nullptr;
178
280k
      DnsQuery* newQuery = nullptr;
179
280k
      IDnsResource* newGenResource = nullptr;
180
280k
      if (resType == DnsQueryType)
181
172k
      {
182
172k
        newQuery = new DnsQuery(this, offsetInPacket);
183
172k
        newGenResource = newQuery;
184
172k
        offsetInPacket += newQuery->getSize();
185
172k
      }
186
108k
      else
187
108k
      {
188
108k
        newResource = new DnsResource(this, offsetInPacket, resType);
189
108k
        newGenResource = newResource;
190
108k
        offsetInPacket += newResource->getSize();
191
108k
      }
192
193
280k
      if (offsetInPacket > m_DataLen)
194
49.9k
      {
195
        // Parse packet failed, DNS resource is out of bounds. Probably a bad packet
196
49.9k
        delete newGenResource;
197
49.9k
        return;
198
49.9k
      }
199
200
      // this resource is the first resource
201
230k
      if (m_ResourceList == nullptr)
202
104k
      {
203
104k
        m_ResourceList = newGenResource;
204
104k
        curResource = m_ResourceList;
205
104k
      }
206
125k
      else
207
125k
      {
208
125k
        curResource->setNextResource(newGenResource);
209
125k
        curResource = curResource->getNextResource();
210
125k
      }
211
212
230k
      if (resType == DnsQueryType && m_FirstQuery == nullptr)
213
103k
        m_FirstQuery = newQuery;
214
127k
      else if (resType == DnsAnswerType && m_FirstAnswer == nullptr)
215
12.6k
        m_FirstAnswer = newResource;
216
114k
      else if (resType == DnsAuthorityType && m_FirstAuthority == nullptr)
217
9.65k
        m_FirstAuthority = newResource;
218
104k
      else if (resType == DnsAdditionalType && m_FirstAdditional == nullptr)
219
8.50k
        m_FirstAdditional = newResource;
220
230k
    }
221
122k
  }
222
223
  IDnsResource* DnsLayer::getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name,
224
                                            bool exactMatch) const
225
169k
  {
226
169k
    size_t index = 0;
227
294k
    while (index < resourceCount)
228
219k
    {
229
219k
      if (startFrom == nullptr)
230
27.9k
        return nullptr;
231
232
191k
      std::string resourceName = startFrom->getName();
233
191k
      if (exactMatch && resourceName == name)
234
390
        return startFrom;
235
191k
      else if (!exactMatch && resourceName.find(name) != std::string::npos)
236
65.8k
        return startFrom;
237
238
125k
      startFrom = startFrom->getNextResource();
239
240
125k
      index++;
241
125k
    }
242
243
75.1k
    return nullptr;
244
169k
  }
245
246
  DnsQuery* DnsLayer::getQuery(const std::string& name, bool exactMatch) const
247
42.3k
  {
248
42.3k
    uint16_t numOfQueries = be16toh(getDnsHeader()->numberOfQuestions);
249
42.3k
    IDnsResource* res = getResourceByName(m_FirstQuery, numOfQueries, name, exactMatch);
250
42.3k
    if (res != nullptr)
251
16.5k
      return dynamic_cast<DnsQuery*>(res);
252
25.7k
    return nullptr;
253
42.3k
  }
254
255
  DnsQuery* DnsLayer::getFirstQuery() const
256
21.1k
  {
257
21.1k
    return m_FirstQuery;
258
21.1k
  }
259
260
  DnsQuery* DnsLayer::getNextQuery(DnsQuery* query) const
261
20.9k
  {
262
20.9k
    if (query == nullptr || query->getNextResource() == nullptr || query->getType() != DnsQueryType ||
263
10.6k
        query->getNextResource()->getType() != DnsQueryType)
264
13.9k
      return nullptr;
265
266
6.97k
    return (DnsQuery*)(query->getNextResource());
267
20.9k
  }
268
269
  size_t DnsLayer::getQueryCount() const
270
75.6k
  {
271
75.6k
    return be16toh(getDnsHeader()->numberOfQuestions);
272
75.6k
  }
273
274
  DnsResource* DnsLayer::getAnswer(const std::string& name, bool exactMatch) const
275
42.3k
  {
276
42.3k
    uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers);
277
42.3k
    IDnsResource* res = getResourceByName(m_FirstAnswer, numOfAnswers, name, exactMatch);
278
42.3k
    if (res != nullptr)
279
16.5k
      return dynamic_cast<DnsResource*>(res);
280
25.8k
    return nullptr;
281
42.3k
  }
282
283
  DnsResource* DnsLayer::getFirstAnswer() const
284
21.1k
  {
285
21.1k
    return m_FirstAnswer;
286
21.1k
  }
287
288
  DnsResource* DnsLayer::getNextAnswer(DnsResource* answer) const
289
5.44k
  {
290
5.44k
    if (answer == nullptr || answer->getNextResource() == nullptr || answer->getType() != DnsAnswerType ||
291
3.35k
        answer->getNextResource()->getType() != DnsAnswerType)
292
2.45k
      return nullptr;
293
294
2.99k
    return (DnsResource*)(answer->getNextResource());
295
5.44k
  }
296
297
  size_t DnsLayer::getAnswerCount() const
298
75.2k
  {
299
75.2k
    return be16toh(getDnsHeader()->numberOfAnswers);
300
75.2k
  }
301
302
  DnsResource* DnsLayer::getAuthority(const std::string& name, bool exactMatch) const
303
42.3k
  {
304
42.3k
    uint16_t numOfAuthorities = be16toh(getDnsHeader()->numberOfAuthority);
305
42.3k
    IDnsResource* res = getResourceByName(m_FirstAuthority, numOfAuthorities, name, exactMatch);
306
42.3k
    if (res != nullptr)
307
16.4k
      return dynamic_cast<DnsResource*>(res);
308
25.8k
    return nullptr;
309
42.3k
  }
310
311
  DnsResource* DnsLayer::getFirstAuthority() const
312
21.1k
  {
313
21.1k
    return m_FirstAuthority;
314
21.1k
  }
315
316
  DnsResource* DnsLayer::getNextAuthority(DnsResource* authority) const
317
2.35k
  {
318
2.35k
    if (authority == nullptr || authority->getNextResource() == nullptr ||
319
1.32k
        authority->getType() != DnsAuthorityType || authority->getNextResource()->getType() != DnsAuthorityType)
320
1.53k
      return nullptr;
321
322
818
    return (DnsResource*)(authority->getNextResource());
323
2.35k
  }
324
325
  size_t DnsLayer::getAuthorityCount() const
326
75.6k
  {
327
75.6k
    return be16toh(getDnsHeader()->numberOfAuthority);
328
75.6k
  }
329
330
  DnsResource* DnsLayer::getAdditionalRecord(const std::string& name, bool exactMatch) const
331
42.3k
  {
332
42.3k
    uint16_t numOfAdditionalRecords = be16toh(getDnsHeader()->numberOfAdditional);
333
42.3k
    IDnsResource* res = getResourceByName(m_FirstAdditional, numOfAdditionalRecords, name, exactMatch);
334
42.3k
    if (res != nullptr)
335
16.6k
      return dynamic_cast<DnsResource*>(res);
336
25.7k
    return nullptr;
337
42.3k
  }
338
339
  DnsResource* DnsLayer::getFirstAdditionalRecord() const
340
21.1k
  {
341
21.1k
    return m_FirstAdditional;
342
21.1k
  }
343
344
  DnsResource* DnsLayer::getNextAdditionalRecord(DnsResource* additionalRecord) const
345
2.61k
  {
346
2.61k
    if (additionalRecord == nullptr || additionalRecord->getNextResource() == nullptr ||
347
1.21k
        additionalRecord->getType() != DnsAdditionalType ||
348
1.21k
        additionalRecord->getNextResource()->getType() != DnsAdditionalType)
349
1.40k
      return nullptr;
350
351
1.21k
    return (DnsResource*)(additionalRecord->getNextResource());
352
2.61k
  }
353
354
  size_t DnsLayer::getAdditionalRecordCount() const
355
75.7k
  {
356
75.7k
    return be16toh(getDnsHeader()->numberOfAdditional);
357
75.7k
  }
358
359
  std::string DnsLayer::toString() const
360
42.3k
  {
361
42.3k
    std::ostringstream tidAsString;
362
42.3k
    tidAsString << be16toh(getDnsHeader()->transactionID);
363
364
42.3k
    std::ostringstream queryCount;
365
42.3k
    queryCount << getQueryCount();
366
367
42.3k
    std::ostringstream answerCount;
368
42.3k
    answerCount << getAnswerCount();
369
370
42.3k
    std::ostringstream authorityCount;
371
42.3k
    authorityCount << getAuthorityCount();
372
373
42.3k
    std::ostringstream additionalCount;
374
42.3k
    additionalCount << getAdditionalRecordCount();
375
376
42.3k
    if (getDnsHeader()->queryOrResponse == 1)
377
8.37k
    {
378
8.37k
      return "DNS query response, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() +
379
8.37k
             ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() +
380
8.37k
             ", additional record: " + additionalCount.str();
381
8.37k
    }
382
33.9k
    else if (getDnsHeader()->queryOrResponse == 0)
383
33.9k
    {
384
33.9k
      return "DNS query, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() +
385
33.9k
             ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() +
386
33.9k
             ", additional record: " + additionalCount.str();
387
33.9k
    }
388
0
    else  // not likely - a DNS with no answers and no queries
389
0
    {
390
0
      return "DNS record without queries and answers, ID: " + tidAsString.str() + ";" +
391
0
             " queries: " + queryCount.str() + ", answers: " + answerCount.str() +
392
0
             ", authorities: " + authorityCount.str() + ", additional record: " + additionalCount.str();
393
0
    }
394
42.3k
  }
395
396
  static constexpr const char* dnsTypeToString(DnsType dnsType)
397
0
  {
398
0
    switch (dnsType)
399
0
    {
400
0
    case DNS_TYPE_A:
401
0
      return "A";
402
0
    case DNS_TYPE_NS:
403
0
      return "NS";
404
0
    case DNS_TYPE_MD:
405
0
      return "MD";
406
0
    case DNS_TYPE_MF:
407
0
      return "MF";
408
0
    case DNS_TYPE_CNAME:
409
0
      return "CNAME";
410
0
    case DNS_TYPE_SOA:
411
0
      return "SOA";
412
0
    case DNS_TYPE_MB:
413
0
      return "MB";
414
0
    case DNS_TYPE_MG:
415
0
      return "MG";
416
0
    case DNS_TYPE_MR:
417
0
      return "MR";
418
0
    case DNS_TYPE_NULL_R:
419
0
      return "NULL";
420
0
    case DNS_TYPE_WKS:
421
0
      return "WKS";
422
0
    case DNS_TYPE_PTR:
423
0
      return "PTR";
424
0
    case DNS_TYPE_HINFO:
425
0
      return "HINFO";
426
0
    case DNS_TYPE_MINFO:
427
0
      return "MINFO";
428
0
    case DNS_TYPE_MX:
429
0
      return "MX";
430
0
    case DNS_TYPE_TXT:
431
0
      return "TXT";
432
0
    case DNS_TYPE_RP:
433
0
      return "RP";
434
0
    case DNS_TYPE_AFSDB:
435
0
      return "AFSDB";
436
0
    case DNS_TYPE_X25:
437
0
      return "X25";
438
0
    case DNS_TYPE_ISDN:
439
0
      return "ISDN";
440
0
    case DNS_TYPE_RT:
441
0
      return "RT";
442
0
    case DNS_TYPE_NSAP:
443
0
      return "NSAP";
444
0
    case DNS_TYPE_NSAP_PTR:
445
0
      return "NSAP-PTR";
446
0
    case DNS_TYPE_SIG:
447
0
      return "SIG";
448
0
    case DNS_TYPE_KEY:
449
0
      return "KEY";
450
0
    case DNS_TYPE_PX:
451
0
      return "PX";
452
0
    case DNS_TYPE_GPOS:
453
0
      return "GPOS";
454
0
    case DNS_TYPE_AAAA:
455
0
      return "AAAA";
456
0
    case DNS_TYPE_LOC:
457
0
      return "LOC";
458
0
    case DNS_TYPE_NXT:
459
0
      return "NXT";
460
0
    case DNS_TYPE_EID:
461
0
      return "EID";
462
0
    case DNS_TYPE_NIMLOC:
463
0
      return "NIMLOC";
464
0
    case DNS_TYPE_SRV:
465
0
      return "SRV";
466
0
    case DNS_TYPE_ATMA:
467
0
      return "ATMA";
468
0
    case DNS_TYPE_NAPTR:
469
0
      return "NAPTR";
470
0
    case DNS_TYPE_KX:
471
0
      return "KX";
472
0
    case DNS_TYPE_CERT:
473
0
      return "CERT";
474
0
    case DNS_TYPE_A6:
475
0
      return "A6";
476
0
    case DNS_TYPE_DNAM:
477
0
      return "DNAME";
478
0
    case DNS_TYPE_SINK:
479
0
      return "SINK";
480
0
    case DNS_TYPE_OPT:
481
0
      return "OPT";
482
0
    case DNS_TYPE_APL:
483
0
      return "APL";
484
0
    case DNS_TYPE_DS:
485
0
      return "DS";
486
0
    case DNS_TYPE_SSHFP:
487
0
      return "SSHFP";
488
0
    case DNS_TYPE_IPSECKEY:
489
0
      return "IPSECKEY";
490
0
    case DNS_TYPE_RRSIG:
491
0
      return "RRSIG";
492
0
    case DNS_TYPE_NSEC:
493
0
      return "NSEC";
494
0
    case DNS_TYPE_DNSKEY:
495
0
      return "DNSKEY";
496
0
    case DNS_TYPE_DHCID:
497
0
      return "DHCID";
498
0
    case DNS_TYPE_NSEC3:
499
0
      return "NSEC3";
500
0
    case DNS_TYPE_NSEC3PARAM:
501
0
      return "NSEC3PARAM";
502
0
    case DNS_TYPE_ALL:
503
0
      return "ANY";
504
0
    default:
505
0
      return "Unknown";
506
0
    }
507
0
  }
508
509
  const FieldDescriptor DnsLayer::SerializedFields::TransactionID{ Layer::SerializedFields::MaxID + 1,
510
                                                                 "transactionID" };
511
  const FieldDescriptor DnsLayer::SerializedFields::IsResponse{ Layer::SerializedFields::MaxID + 2, "isResponse" };
512
  const FieldDescriptor DnsLayer::SerializedFields::Opcode{ Layer::SerializedFields::MaxID + 3, "opcode" };
513
  const FieldDescriptor DnsLayer::SerializedFields::AuthoritativeAnswer{ Layer::SerializedFields::MaxID + 4,
514
                                                                       "authoritativeAnswer" };
515
  const FieldDescriptor DnsLayer::SerializedFields::Truncation{ Layer::SerializedFields::MaxID + 5, "truncation" };
516
  const FieldDescriptor DnsLayer::SerializedFields::RecursionDesired{ Layer::SerializedFields::MaxID + 6,
517
                                                                    "recursionDesired" };
518
  const FieldDescriptor DnsLayer::SerializedFields::RecursionAvailable{ Layer::SerializedFields::MaxID + 7,
519
                                                                      "recursionAvailable" };
520
  const FieldDescriptor DnsLayer::SerializedFields::AuthenticData{ Layer::SerializedFields::MaxID + 8,
521
                                                                 "authenticData" };
522
  const FieldDescriptor DnsLayer::SerializedFields::CheckingDisabled{ Layer::SerializedFields::MaxID + 9,
523
                                                                    "checkingDisabled" };
524
  const FieldDescriptor DnsLayer::SerializedFields::ResponseCode{ Layer::SerializedFields::MaxID + 10,
525
                                                                "responseCode" };
526
  const FieldDescriptor DnsLayer::SerializedFields::Queries{ Layer::SerializedFields::MaxID + 11, "queries" };
527
  const FieldDescriptor DnsLayer::SerializedFields::Answers{ Layer::SerializedFields::MaxID + 12, "answers" };
528
  const FieldDescriptor DnsLayer::SerializedFields::Authorities{ Layer::SerializedFields::MaxID + 13, "authorities" };
529
  const FieldDescriptor DnsLayer::SerializedFields::AdditionalRecords{ Layer::SerializedFields::MaxID + 14,
530
                                                                     "additionalRecords" };
531
532
  const DnsLayer::SerializedFields::QueryObject DnsQueryObject{ 0, "query" };
533
  const FieldDescriptor DnsLayer::SerializedFields::QueryObject::Name{ 0, "name" };
534
  const FieldDescriptor DnsLayer::SerializedFields::QueryObject::Type{ 1, "type" };
535
  const FieldDescriptor DnsLayer::SerializedFields::QueryObject::TypeName{ 2, "typeName" };
536
  const FieldDescriptor DnsLayer::SerializedFields::QueryObject::Class{ 3, "class" };
537
538
  const DnsLayer::SerializedFields::ResourceObject DnsResourceObject{ 0, "resource" };
539
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::Name{ 0, "name" };
540
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::Type{ 1, "type" };
541
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::TypeName{ 2, "typeName" };
542
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::Class{ 3, "class" };
543
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::Ttl{ 4, "ttl" };
544
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::DataLength{ 5, "dataLength" };
545
  const FieldDescriptor DnsLayer::SerializedFields::ResourceObject::Data{ 6, "data" };
546
547
  void DnsLayer::serializeLayer(ObjectScope& serializer) const
548
0
  {
549
0
    using QueryFields = SerializedFields::QueryObject;
550
0
    using ResourceFields = SerializedFields::ResourceObject;
551
552
0
    const dnshdr* hdr = getDnsHeader();
553
0
    serializer.writeHexField(SerializedFields::TransactionID, be16toh(hdr->transactionID));
554
0
    serializer.writeField(SerializedFields::IsResponse, hdr->queryOrResponse == 1);
555
0
    serializer.writeField(SerializedFields::Opcode, static_cast<uint8_t>(hdr->opcode));
556
0
    serializer.writeField(SerializedFields::AuthoritativeAnswer, hdr->authoritativeAnswer == 1);
557
0
    serializer.writeField(SerializedFields::Truncation, hdr->truncation == 1);
558
0
    serializer.writeField(SerializedFields::RecursionDesired, hdr->recursionDesired == 1);
559
0
    serializer.writeField(SerializedFields::RecursionAvailable, hdr->recursionAvailable == 1);
560
0
    serializer.writeField(SerializedFields::AuthenticData, hdr->authenticData == 1);
561
0
    serializer.writeField(SerializedFields::CheckingDisabled, hdr->checkingDisabled == 1);
562
0
    serializer.writeField(SerializedFields::ResponseCode, static_cast<uint8_t>(hdr->responseCode));
563
564
0
    {
565
0
      auto queries = serializer.writeArray(SerializedFields::Queries);
566
0
      for (DnsQuery* query = getFirstQuery(); query != nullptr; query = getNextQuery(query))
567
0
      {
568
0
        auto queryObject = queries.writeObject(DnsQueryObject);
569
0
        queryObject.writeField(QueryFields::Name, query->getName());
570
0
        queryObject.writeField(QueryFields::Type, static_cast<uint16_t>(query->getDnsType()));
571
0
        queryObject.writeField(QueryFields::TypeName, dnsTypeToString(query->getDnsType()));
572
0
        queryObject.writeField(QueryFields::Class, static_cast<uint16_t>(query->getDnsClass()));
573
0
      }
574
0
    }
575
576
0
    auto writeResource = [](ArrayScope& resources, const DnsResource* resource) {
577
0
      auto resourceObject = resources.writeObject(DnsResourceObject);
578
0
      resourceObject.writeField(ResourceFields::Name, resource->getName());
579
0
      resourceObject.writeField(ResourceFields::Type, static_cast<uint16_t>(resource->getDnsType()));
580
0
      resourceObject.writeField(ResourceFields::TypeName, dnsTypeToString(resource->getDnsType()));
581
0
      resourceObject.writeField(ResourceFields::Class, static_cast<uint16_t>(resource->getDnsClass()));
582
0
      resourceObject.writeField(ResourceFields::Ttl, resource->getTTL());
583
0
      resourceObject.writeField(ResourceFields::DataLength, resource->getDataLength());
584
      // raw byte arrays of records without a dedicated data type aren't meaningful to serialize
585
0
      auto data = resource->getData();
586
0
      if (!data.isTypeOf<GenericDnsResourceData>())
587
0
      {
588
0
        resourceObject.writeField(ResourceFields::Data, data->toString());
589
0
      }
590
0
    };
591
592
0
    {
593
0
      auto answers = serializer.writeArray(SerializedFields::Answers);
594
0
      for (DnsResource* answer = getFirstAnswer(); answer != nullptr; answer = getNextAnswer(answer))
595
0
      {
596
0
        writeResource(answers, answer);
597
0
      }
598
0
    }
599
600
0
    {
601
0
      auto authorities = serializer.writeArray(SerializedFields::Authorities);
602
0
      for (DnsResource* authority = getFirstAuthority(); authority != nullptr;
603
0
           authority = getNextAuthority(authority))
604
0
      {
605
0
        writeResource(authorities, authority);
606
0
      }
607
0
    }
608
609
0
    auto additionalRecords = serializer.writeArray(SerializedFields::AdditionalRecords);
610
0
    for (DnsResource* additionalRecord = getFirstAdditionalRecord(); additionalRecord != nullptr;
611
0
         additionalRecord = getNextAdditionalRecord(additionalRecord))
612
0
    {
613
0
      writeResource(additionalRecords, additionalRecord);
614
0
    }
615
0
  }
616
617
  IDnsResource* DnsLayer::getFirstResource(DnsResourceType resType) const
618
65.8k
  {
619
65.8k
    switch (resType)
620
65.8k
    {
621
16.5k
    case DnsQueryType:
622
16.5k
    {
623
16.5k
      return m_FirstQuery;
624
0
    }
625
16.1k
    case DnsAnswerType:
626
16.1k
    {
627
16.1k
      return m_FirstAnswer;
628
0
    }
629
16.4k
    case DnsAuthorityType:
630
16.4k
    {
631
16.4k
      return m_FirstAuthority;
632
0
    }
633
16.6k
    case DnsAdditionalType:
634
16.6k
    {
635
16.6k
      return m_FirstAdditional;
636
0
    }
637
0
    default:
638
0
      return nullptr;
639
65.8k
    }
640
65.8k
  }
641
642
  void DnsLayer::setFirstResource(DnsResourceType resType, IDnsResource* resource)
643
96.8k
  {
644
96.8k
    switch (resType)
645
96.8k
    {
646
4.36k
    case DnsQueryType:
647
4.36k
    {
648
4.36k
      m_FirstQuery = dynamic_cast<DnsQuery*>(resource);
649
4.36k
      break;
650
0
    }
651
30.1k
    case DnsAnswerType:
652
30.1k
    {
653
30.1k
      m_FirstAnswer = dynamic_cast<DnsResource*>(resource);
654
30.1k
      break;
655
0
    }
656
31.2k
    case DnsAuthorityType:
657
31.2k
    {
658
31.2k
      m_FirstAuthority = dynamic_cast<DnsResource*>(resource);
659
31.2k
      break;
660
0
    }
661
31.1k
    case DnsAdditionalType:
662
31.1k
    {
663
31.1k
      m_FirstAdditional = dynamic_cast<DnsResource*>(resource);
664
31.1k
      break;
665
0
    }
666
0
    default:
667
0
      return;
668
96.8k
    }
669
96.8k
  }
670
671
  DnsResource* DnsLayer::addResource(DnsResourceType resType, const std::string& name, DnsType dnsType,
672
                                     DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data)
673
63.5k
  {
674
63.5k
    if (data == nullptr)
675
0
    {
676
0
      PCPP_LOG_ERROR("Given data is nullptr");
677
0
      return nullptr;
678
0
    }
679
680
    // The temporary buffer holds the encoded name and the fixed RR header. The encoded name is at most the decoded
681
    // name plus 2 bytes and the fixed RR header is 10 bytes long. The RDATA is added by setData() after the new
682
    // resource is attached to the layer, so the buffer doesn't need to leave room for it
683
63.5k
    std::vector<uint8_t> newResourceRawData(name.size() + 2 + 10, 0);
684
685
63.5k
    DnsResource* newResource = new DnsResource(newResourceRawData.data(), resType);
686
687
63.5k
    newResource->setDnsClass(dnsClass);
688
689
63.5k
    newResource->setDnsType(dnsType);
690
691
    // cannot return false since layer shouldn't be extended or shortened in this stage
692
63.5k
    newResource->setName(name);
693
694
63.5k
    newResource->setTTL(ttl);
695
696
63.5k
    size_t newResourceOffsetInLayer = getBasicHeaderSize();
697
63.5k
    IDnsResource* curResource = m_ResourceList;
698
105k
    while (curResource != nullptr && curResource->getType() <= resType)
699
85.6k
    {
700
85.6k
      newResourceOffsetInLayer += curResource->getSize();
701
702
85.6k
      if (newResourceOffsetInLayer > m_DataLen)
703
1.40k
      {
704
        // This possibly means that the DNS layer has been created from a malformed packet.
705
1.40k
        PCPP_LOG_ERROR("Couldn't add resource! DNS Layer is malformed and contains out of bounds resources.");
706
1.40k
        delete newResource;
707
1.40k
        return nullptr;
708
1.40k
      }
709
710
84.2k
      IDnsResource* nextResource = curResource->getNextResource();
711
84.2k
      if (nextResource == nullptr || nextResource->getType() > resType)
712
42.1k
        break;
713
42.0k
      curResource = nextResource;
714
42.0k
    }
715
716
    // set next resource for new resource. This must happen here for extendLayer to succeed
717
62.1k
    if (curResource != nullptr)
718
42.3k
    {
719
42.3k
      if (curResource->getType() > newResource->getType())
720
158
        newResource->setNextResource(m_ResourceList);
721
42.1k
      else
722
42.1k
        newResource->setNextResource(curResource->getNextResource());
723
42.3k
    }
724
19.8k
    else
725
19.8k
    {
726
      // curResource != nullptr
727
19.8k
      newResource->setNextResource(m_ResourceList);
728
19.8k
    }
729
730
    // extend layer to make room for the new resource
731
62.1k
    if (!extendLayer(newResourceOffsetInLayer, newResource->getSize(), newResource))
732
11.7k
    {
733
11.7k
      PCPP_LOG_ERROR("Couldn't extend DNS layer, addResource failed");
734
11.7k
      delete newResource;
735
11.7k
      return nullptr;
736
11.7k
    }
737
738
    // connect the new resource to layer
739
50.3k
    newResource->setDnsLayer(this, newResourceOffsetInLayer);
740
741
    // connect the new resource to the layer's resource list
742
50.3k
    if (curResource != nullptr)
743
38.2k
    {
744
      // if the new resource should be the first resource in the packet, its next resource is already the current
745
      // first resource, which must not point back to it
746
38.2k
      if (curResource->getType() <= newResource->getType())
747
38.2k
      {
748
38.2k
        curResource->setNextResource(newResource);
749
38.2k
      }
750
      // this means the new resource is the first of it's type
751
38.2k
      if (curResource->getType() < newResource->getType())
752
34.6k
      {
753
34.6k
        setFirstResource(resType, newResource);
754
34.6k
      }
755
      // this means the new resource should be the first resource in the packet
756
3.61k
      else if (curResource->getType() > newResource->getType())
757
27
      {
758
27
        m_ResourceList = newResource;
759
760
27
        setFirstResource(resType, newResource);
761
27
      }
762
38.2k
    }
763
12.0k
    else  // curResource != nullptr, meaning this is the first resource in layer
764
12.0k
    {
765
12.0k
      m_ResourceList = newResource;
766
767
12.0k
      setFirstResource(resType, newResource);
768
12.0k
    }
769
770
    // set the resource data after the resource is attached to the layer, so setData() can extend the layer
771
    // by the size of the serialized RDATA
772
50.3k
    if (!newResource->setData(data))
773
0
    {
774
0
      PCPP_LOG_ERROR("Couldn't set new resource data");
775
0
      if (!removeResource(newResource))
776
0
        PCPP_LOG_ERROR("Couldn't remove the new resource from the DNS layer");
777
0
      return nullptr;
778
0
    }
779
780
50.3k
    return newResource;
781
50.3k
  }
782
783
  DnsQuery* DnsLayer::addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass)
784
21.1k
  {
785
    // create new query on temporary buffer
786
21.1k
    uint8_t newQueryRawData[256];
787
21.1k
    DnsQuery* newQuery = new DnsQuery(newQueryRawData);
788
789
21.1k
    newQuery->setDnsClass(dnsClass);
790
21.1k
    newQuery->setDnsType(dnsType);
791
792
    // cannot return false since layer shouldn't be extended or shortened in this stage
793
21.1k
    newQuery->setName(name);
794
795
    // find the offset in the layer to insert the new query
796
21.1k
    size_t newQueryOffsetInLayer = getBasicHeaderSize();
797
21.1k
    DnsQuery* curQuery = getFirstQuery();
798
28.1k
    while (curQuery != nullptr)
799
20.9k
    {
800
20.9k
      newQueryOffsetInLayer += curQuery->getSize();
801
20.9k
      DnsQuery* nextQuery = getNextQuery(curQuery);
802
20.9k
      if (nextQuery == nullptr)
803
13.9k
        break;
804
6.97k
      curQuery = nextQuery;
805
6.97k
    }
806
807
    // set next resource for new query. This must happen here for extendLayer to succeed
808
21.1k
    if (curQuery != nullptr)
809
13.9k
      newQuery->setNextResource(curQuery->getNextResource());
810
7.20k
    else
811
7.20k
      newQuery->setNextResource(m_ResourceList);
812
813
    // extend layer to make room for the new query
814
21.1k
    if (!extendLayer(newQueryOffsetInLayer, newQuery->getSize(), newQuery))
815
4.43k
    {
816
4.43k
      PCPP_LOG_ERROR("Couldn't extend DNS layer, addQuery failed");
817
4.43k
      delete newQuery;
818
4.43k
      return nullptr;
819
4.43k
    }
820
821
    // connect the new query to layer
822
16.7k
    newQuery->setDnsLayer(this, newQueryOffsetInLayer);
823
824
    // connect the new query to the layer's resource list
825
16.7k
    if (curQuery != nullptr)
826
12.2k
      curQuery->setNextResource(newQuery);
827
4.52k
    else  // curQuery == nullptr, meaning this is the first query
828
4.52k
    {
829
4.52k
      m_ResourceList = newQuery;
830
4.52k
      m_FirstQuery = newQuery;
831
4.52k
    }
832
833
    // increase number of queries
834
16.7k
    getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() + 1);
835
836
16.7k
    return newQuery;
837
21.1k
  }
838
839
  DnsQuery* DnsLayer::addQuery(DnsQuery* const copyQuery)
840
0
  {
841
0
    if (copyQuery == nullptr)
842
0
      return nullptr;
843
844
0
    return addQuery(copyQuery->getName(), copyQuery->getDnsType(), copyQuery->getDnsClass());
845
0
  }
846
847
  bool DnsLayer::removeQuery(const std::string& queryNameToRemove, bool exactMatch)
848
42.3k
  {
849
42.3k
    DnsQuery* queryToRemove = getQuery(queryNameToRemove, exactMatch);
850
42.3k
    if (queryToRemove == nullptr)
851
25.7k
    {
852
25.7k
      PCPP_LOG_DEBUG("Query not found");
853
25.7k
      return false;
854
25.7k
    }
855
856
16.5k
    return removeQuery(queryToRemove);
857
42.3k
  }
858
859
  bool DnsLayer::removeQuery(DnsQuery* queryToRemove)
860
16.5k
  {
861
16.5k
    bool res = removeResource(queryToRemove);
862
16.5k
    if (res)
863
16.5k
    {
864
      // decrease number of query records
865
16.5k
      getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() - 1);
866
16.5k
    }
867
868
16.5k
    return res;
869
16.5k
  }
870
871
  DnsResource* DnsLayer::addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl,
872
                                   IDnsResourceData* data)
873
21.1k
  {
874
21.1k
    DnsResource* res = addResource(DnsAnswerType, name, dnsType, dnsClass, ttl, data);
875
21.1k
    if (res != nullptr)
876
16.7k
    {
877
      // increase number of answer records
878
16.7k
      getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() + 1);
879
16.7k
    }
880
881
21.1k
    return res;
882
21.1k
  }
883
884
  DnsResource* DnsLayer::addAnswer(DnsResource* const copyAnswer)
885
0
  {
886
0
    if (copyAnswer == nullptr)
887
0
      return nullptr;
888
889
0
    return addAnswer(copyAnswer->getName(), copyAnswer->getDnsType(), copyAnswer->getDnsClass(),
890
0
                     copyAnswer->getTTL(), copyAnswer->getData().get());
891
0
  }
892
893
  bool DnsLayer::removeAnswer(const std::string& answerNameToRemove, bool exactMatch)
894
42.3k
  {
895
42.3k
    DnsResource* answerToRemove = getAnswer(answerNameToRemove, exactMatch);
896
42.3k
    if (answerToRemove == nullptr)
897
25.8k
    {
898
25.8k
      PCPP_LOG_DEBUG("Answer record not found");
899
25.8k
      return false;
900
25.8k
    }
901
902
16.5k
    return removeAnswer(answerToRemove);
903
42.3k
  }
904
905
  bool DnsLayer::removeAnswer(DnsResource* answerToRemove)
906
16.5k
  {
907
16.5k
    bool res = removeResource(answerToRemove);
908
16.5k
    if (res)
909
16.1k
    {
910
      // decrease number of answer records
911
16.1k
      getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() - 1);
912
16.1k
    }
913
914
16.5k
    return res;
915
16.5k
  }
916
917
  DnsResource* DnsLayer::addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl,
918
                                      IDnsResourceData* data)
919
21.1k
  {
920
21.1k
    DnsResource* res = addResource(DnsAuthorityType, name, dnsType, dnsClass, ttl, data);
921
21.1k
    if (res != nullptr)
922
16.7k
    {
923
      // increase number of authority records
924
16.7k
      getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() + 1);
925
16.7k
    }
926
927
21.1k
    return res;
928
21.1k
  }
929
930
  DnsResource* DnsLayer::addAuthority(DnsResource* const copyAuthority)
931
0
  {
932
0
    if (copyAuthority == nullptr)
933
0
      return nullptr;
934
935
0
    return addAuthority(copyAuthority->getName(), copyAuthority->getDnsType(), copyAuthority->getDnsClass(),
936
0
                        copyAuthority->getTTL(), copyAuthority->getData().get());
937
0
  }
938
939
  bool DnsLayer::removeAuthority(const std::string& authorityNameToRemove, bool exactMatch)
940
42.3k
  {
941
42.3k
    DnsResource* authorityToRemove = getAuthority(authorityNameToRemove, exactMatch);
942
42.3k
    if (authorityToRemove == nullptr)
943
25.8k
    {
944
25.8k
      PCPP_LOG_DEBUG("Authority not found");
945
25.8k
      return false;
946
25.8k
    }
947
948
16.4k
    return removeAuthority(authorityToRemove);
949
42.3k
  }
950
951
  bool DnsLayer::removeAuthority(DnsResource* authorityToRemove)
952
16.4k
  {
953
16.4k
    bool res = removeResource(authorityToRemove);
954
16.4k
    if (res)
955
16.4k
    {
956
      // decrease number of authority records
957
16.4k
      getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() - 1);
958
16.4k
    }
959
960
16.4k
    return res;
961
16.4k
  }
962
963
  DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass,
964
                                             uint32_t ttl, IDnsResourceData* data)
965
21.1k
  {
966
21.1k
    DnsResource* res = addResource(DnsAdditionalType, name, dnsType, dnsClass, ttl, data);
967
21.1k
    if (res != nullptr)
968
16.8k
    {
969
      // increase number of authority records
970
16.8k
      getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() + 1);
971
16.8k
    }
972
973
21.1k
    return res;
974
21.1k
  }
975
976
  DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1,
977
                                             uint32_t customData2, IDnsResourceData* data)
978
21.1k
  {
979
21.1k
    DnsResource* res = addAdditionalRecord(name, dnsType, DNS_CLASS_ANY, customData2, data);
980
21.1k
    if (res != nullptr)
981
16.8k
    {
982
16.8k
      res->setCustomDnsClass(customData1);
983
16.8k
    }
984
985
21.1k
    return res;
986
21.1k
  }
987
988
  DnsResource* DnsLayer::addAdditionalRecord(DnsResource* const copyAdditionalRecord)
989
0
  {
990
0
    if (copyAdditionalRecord == nullptr)
991
0
      return nullptr;
992
993
0
    return addAdditionalRecord(copyAdditionalRecord->getName(), copyAdditionalRecord->getDnsType(),
994
0
                               copyAdditionalRecord->getCustomDnsClass(), copyAdditionalRecord->getTTL(),
995
0
                               copyAdditionalRecord->getData().get());
996
0
  }
997
998
  bool DnsLayer::removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch)
999
42.3k
  {
1000
42.3k
    DnsResource* additionalRecordToRemove = getAdditionalRecord(additionalRecordNameToRemove, exactMatch);
1001
42.3k
    if (additionalRecordToRemove == nullptr)
1002
25.7k
    {
1003
25.7k
      PCPP_LOG_DEBUG("Additional record not found");
1004
25.7k
      return false;
1005
25.7k
    }
1006
1007
16.6k
    return removeAdditionalRecord(additionalRecordToRemove);
1008
42.3k
  }
1009
1010
  bool DnsLayer::removeAdditionalRecord(DnsResource* additionalRecordToRemove)
1011
16.6k
  {
1012
16.6k
    bool res = removeResource(additionalRecordToRemove);
1013
16.6k
    if (res)
1014
16.6k
    {
1015
      // decrease number of additional records
1016
16.6k
      getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() - 1);
1017
16.6k
    }
1018
1019
16.6k
    return res;
1020
16.6k
  }
1021
1022
  bool DnsLayer::removeResource(IDnsResource* resourceToRemove)
1023
66.2k
  {
1024
66.2k
    if (resourceToRemove == nullptr)
1025
0
    {
1026
0
      PCPP_LOG_DEBUG("resourceToRemove cannot be nullptr");
1027
0
      return false;
1028
0
    }
1029
1030
    // find the resource preceding resourceToRemove
1031
66.2k
    IDnsResource* prevResource = m_ResourceList;
1032
1033
66.2k
    if (m_ResourceList != resourceToRemove)
1034
50.2k
    {
1035
87.8k
      while (prevResource != nullptr)
1036
87.8k
      {
1037
87.8k
        IDnsResource* temp = prevResource->getNextResource();
1038
87.8k
        if (temp == resourceToRemove)
1039
50.2k
          break;
1040
1041
37.5k
        prevResource = temp;
1042
37.5k
      }
1043
50.2k
    }
1044
1045
66.2k
    if (prevResource == nullptr)
1046
0
    {
1047
0
      PCPP_LOG_DEBUG("Resource not found");
1048
0
      return false;
1049
0
    }
1050
1051
    // shorten the layer and fix offset in layer for all next DNS resources in the packet
1052
66.2k
    if (!shortenLayer(resourceToRemove->m_OffsetInLayer, resourceToRemove->getSize(), resourceToRemove))
1053
386
    {
1054
386
      PCPP_LOG_ERROR("Couldn't shorten the DNS layer, resource cannot be removed");
1055
386
      return false;
1056
386
    }
1057
1058
    // remove resourceToRemove from the resources linked list
1059
65.8k
    if (m_ResourceList != resourceToRemove)
1060
49.9k
    {
1061
49.9k
      prevResource->setNextResource(resourceToRemove->getNextResource());
1062
49.9k
    }
1063
15.9k
    else
1064
15.9k
    {
1065
15.9k
      m_ResourceList = resourceToRemove->getNextResource();
1066
15.9k
    }
1067
1068
    // check whether resourceToRemove was the first of its type
1069
65.8k
    if (getFirstResource(resourceToRemove->getType()) == resourceToRemove)
1070
50.1k
    {
1071
50.1k
      IDnsResource* nextResource = resourceToRemove->getNextResource();
1072
50.1k
      if (nextResource != nullptr && nextResource->getType() == resourceToRemove->getType())
1073
80
        setFirstResource(resourceToRemove->getType(), nextResource);
1074
50.0k
      else
1075
50.0k
        setFirstResource(resourceToRemove->getType(), nullptr);
1076
50.1k
    }
1077
1078
    // free resourceToRemove memory
1079
65.8k
    delete resourceToRemove;
1080
1081
65.8k
    return true;
1082
66.2k
  }
1083
1084
  // ~~~~~~~~~~~~~~~
1085
  // DnsOverTcpLayer
1086
  // ~~~~~~~~~~~~~~~
1087
1088
  uint16_t DnsOverTcpLayer::getTcpMessageLength()
1089
0
  {
1090
0
    return be16toh(*(uint16_t*)m_Data);
1091
0
  }
1092
1093
  void DnsOverTcpLayer::setTcpMessageLength(uint16_t value)
1094
3.13k
  {
1095
3.13k
    ((uint16_t*)m_Data)[0] = htobe16(value);
1096
3.13k
  }
1097
1098
  void DnsOverTcpLayer::computeCalculateFields()
1099
3.13k
  {
1100
3.13k
    setTcpMessageLength(m_DataLen - sizeof(uint16_t));
1101
3.13k
  }
1102
1103
  const FieldDescriptor DnsOverTcpLayer::SerializedFields::TcpMessageLength{ DnsLayer::SerializedFields::MaxID + 1,
1104
                                                                           "tcpMessageLength" };
1105
1106
  void DnsOverTcpLayer::serializeLayer(ObjectScope& serializer) const
1107
0
  {
1108
0
    DnsLayer::serializeLayer(serializer);
1109
    serializer.writeField(SerializedFields::TcpMessageLength, be16toh(*reinterpret_cast<uint16_t*>(m_Data)));
1110
0
  }
1111
1112
}  // namespace pcpp