Coverage Report

Created: 2023-01-25 06:41

/src/PcapPlusPlus/Packet++/src/DnsLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
0
#define LOG_MODULE PacketLogModuleDnsLayer
2
3
#include "DnsLayer.h"
4
#include "Logger.h"
5
#include "IpAddress.h"
6
#include <sstream>
7
#include <string.h>
8
#include <iomanip>
9
#include <stdlib.h>
10
#include "EndianPortable.h"
11
12
namespace pcpp
13
{
14
15
// ~~~~~~~~
16
// DnsLayer
17
// ~~~~~~~~
18
19
DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)
20
  : Layer(data, dataLen, prevLayer, packet)
21
4.23k
{
22
4.23k
  init(0, true);
23
4.23k
}
24
25
DnsLayer::DnsLayer()
26
0
{
27
0
  initNewLayer(0);
28
0
}
29
30
DnsLayer::DnsLayer(const DnsLayer& other) : Layer(other)
31
0
{
32
0
  init(other.m_OffsetAdjustment, true);
33
0
}
34
35
DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, size_t offsetAdjustment)
36
  : Layer(data, dataLen, prevLayer, packet)
37
3.05k
{
38
3.05k
  init(offsetAdjustment, true);
39
3.05k
}
40
41
DnsLayer::DnsLayer(size_t offsetAdjustment)
42
0
{
43
0
  initNewLayer(offsetAdjustment);
44
0
}
45
46
DnsLayer& DnsLayer::operator=(const DnsLayer& other)
47
0
{
48
0
  Layer::operator=(other);
49
50
0
  IDnsResource* curResource = m_ResourceList;
51
0
  while (curResource != NULL)
52
0
  {
53
0
    IDnsResource* temp = curResource->getNextResource();
54
0
    delete curResource;
55
0
    curResource = temp;
56
0
  }
57
58
0
  init(other.m_OffsetAdjustment, true);
59
60
0
  return (*this);
61
0
}
62
63
DnsLayer::~DnsLayer()
64
7.29k
{
65
7.29k
  IDnsResource* curResource = m_ResourceList;
66
33.7k
  while (curResource != NULL)
67
26.4k
  {
68
26.4k
    IDnsResource* nextResource = curResource->getNextResource();
69
26.4k
    delete curResource;
70
26.4k
    curResource = nextResource;
71
26.4k
  }
72
7.29k
}
73
74
void DnsLayer::init(size_t offsetAdjustment, bool callParseResource)
75
7.29k
{
76
7.29k
  m_OffsetAdjustment = offsetAdjustment;
77
7.29k
  m_Protocol = DNS;
78
7.29k
  m_ResourceList = NULL;
79
80
7.29k
  m_FirstQuery = NULL;
81
7.29k
  m_FirstAnswer = NULL;
82
7.29k
  m_FirstAuthority = NULL;
83
7.29k
  m_FirstAdditional = NULL;
84
85
7.29k
  if (callParseResource)
86
7.29k
    parseResources();
87
7.29k
}
88
89
90
void DnsLayer::initNewLayer(size_t offsetAdjustment)
91
0
{
92
0
  m_OffsetAdjustment = offsetAdjustment;
93
0
  const size_t headerLen = getBasicHeaderSize();
94
0
  m_DataLen = headerLen;
95
0
  m_Data = new uint8_t[headerLen];
96
0
  memset(m_Data, 0, headerLen);
97
98
0
  init(m_OffsetAdjustment, false);
99
0
}
100
101
size_t DnsLayer::getBasicHeaderSize()
102
7.29k
{
103
7.29k
  return sizeof(dnshdr) + m_OffsetAdjustment;
104
7.29k
}
105
106
dnshdr* DnsLayer::getDnsHeader() const
107
29.1k
{
108
29.1k
  uint8_t* ptr = m_Data + m_OffsetAdjustment;
109
29.1k
  return (dnshdr*)ptr;
110
29.1k
}
111
112
bool DnsLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource* resource)
113
0
{
114
0
  if (!Layer::extendLayer(offsetInLayer, numOfBytesToExtend))
115
0
    return false;
116
117
0
  IDnsResource* curResource = resource->getNextResource();
118
0
  while (curResource != NULL)
119
0
  {
120
0
    curResource->m_OffsetInLayer += numOfBytesToExtend;
121
0
    curResource = curResource->getNextResource();
122
0
  }
123
0
  return true;
124
0
}
125
126
127
bool DnsLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource)
128
0
{
129
0
  if (!Layer::shortenLayer(offsetInLayer, numOfBytesToShorten))
130
0
    return false;
131
132
0
  IDnsResource* curResource = resource->getNextResource();
133
0
  while (curResource != NULL)
134
0
  {
135
0
    curResource->m_OffsetInLayer -= numOfBytesToShorten;
136
0
    curResource = curResource->getNextResource();
137
0
  }
138
0
  return true;
139
0
}
140
141
142
void DnsLayer::parseResources()
143
7.29k
{
144
7.29k
  size_t offsetInPacket = getBasicHeaderSize();
145
7.29k
  IDnsResource* curResource = m_ResourceList;
146
147
7.29k
  uint16_t numOfQuestions = be16toh(getDnsHeader()->numberOfQuestions);
148
7.29k
  uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers);
149
7.29k
  uint16_t numOfAuthority = be16toh(getDnsHeader()->numberOfAuthority);
150
7.29k
  uint16_t numOfAdditional = be16toh(getDnsHeader()->numberOfAdditional);
151
152
7.29k
  uint32_t numOfOtherResources = numOfQuestions + numOfAnswers + numOfAuthority + numOfAdditional;
153
154
7.29k
  if (numOfOtherResources > 300)
155
2.15k
  {
156
2.15k
    PCPP_LOG_ERROR("DNS layer contains more than 300 resources, probably a bad packet. "
157
2.15k
        "Skipping parsing DNS resources");
158
2.15k
    return;
159
2.15k
  }
160
161
31.5k
  for (uint32_t i = 0; i < numOfOtherResources; i++)
162
30.7k
  {
163
30.7k
    DnsResourceType resType;
164
30.7k
    if (numOfQuestions > 0)
165
22.9k
    {
166
22.9k
      resType = DnsQueryType;
167
22.9k
      numOfQuestions--;
168
22.9k
    }
169
7.79k
    else if (numOfAnswers > 0)
170
3.28k
    {
171
3.28k
      resType = DnsAnswerType;
172
3.28k
      numOfAnswers--;
173
3.28k
    }
174
4.51k
    else if (numOfAuthority > 0)
175
2.52k
    {
176
2.52k
      resType = DnsAuthorityType;
177
2.52k
      numOfAuthority--;
178
2.52k
    }
179
1.99k
    else
180
1.99k
    {
181
1.99k
      resType = DnsAdditionalType;
182
1.99k
      numOfAdditional--;
183
1.99k
    }
184
185
30.7k
    DnsResource* newResource = NULL;
186
30.7k
    DnsQuery* newQuery = NULL;
187
30.7k
    IDnsResource* newGenResource = NULL;
188
30.7k
    if (resType == DnsQueryType)
189
22.9k
    {
190
22.9k
      newQuery = new DnsQuery(this, offsetInPacket);
191
22.9k
      newGenResource = newQuery;
192
22.9k
      offsetInPacket += newQuery->getSize();
193
22.9k
    }
194
7.79k
    else
195
7.79k
    {
196
7.79k
      newResource = new DnsResource(this, offsetInPacket, resType);
197
7.79k
      newGenResource = newResource;
198
7.79k
      offsetInPacket += newResource->getSize();
199
7.79k
    }
200
201
30.7k
    if (offsetInPacket > m_DataLen)
202
4.29k
    {
203
      //Parse packet failed, DNS resource is out of bounds. Probably a bad packet
204
4.29k
      delete newGenResource;
205
4.29k
      return;
206
4.29k
    }
207
208
    // this resource is the first resource
209
26.4k
    if (m_ResourceList == NULL)
210
3.74k
    {
211
3.74k
      m_ResourceList = newGenResource;
212
3.74k
      curResource = m_ResourceList;
213
3.74k
    }
214
22.7k
    else
215
22.7k
    {
216
22.7k
      curResource->setNexResource(newGenResource);
217
22.7k
      curResource = curResource->getNextResource();
218
22.7k
    }
219
220
26.4k
    if (resType == DnsQueryType && m_FirstQuery == NULL)
221
1.52k
      m_FirstQuery = newQuery;
222
24.9k
    else if (resType == DnsAnswerType && m_FirstAnswer == NULL)
223
1.14k
      m_FirstAnswer = newResource;
224
23.7k
    else if (resType == DnsAuthorityType && m_FirstAuthority == NULL)
225
719
      m_FirstAuthority = newResource;
226
23.0k
    else if (resType == DnsAdditionalType && m_FirstAdditional == NULL)
227
748
      m_FirstAdditional = newResource;
228
26.4k
  }
229
230
5.13k
}
231
232
IDnsResource* DnsLayer::getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, bool exactMatch) const
233
0
{
234
0
  size_t index = 0;
235
0
  while (index < resourceCount)
236
0
  {
237
0
    if (startFrom == NULL)
238
0
      return NULL;
239
240
0
    std::string resourceName = startFrom->getName();
241
0
    if (exactMatch && resourceName == name)
242
0
      return startFrom;
243
0
    else if (!exactMatch && resourceName.find(name) != std::string::npos)
244
0
      return startFrom;
245
246
0
    startFrom = startFrom->getNextResource();
247
248
0
    index++;
249
0
  }
250
251
0
  return NULL;
252
0
}
253
254
DnsQuery* DnsLayer::getQuery(const std::string& name, bool exactMatch) const
255
0
{
256
0
  uint16_t numOfQueries = be16toh(getDnsHeader()->numberOfQuestions);
257
0
  IDnsResource* res = getResourceByName(m_FirstQuery, numOfQueries, name, exactMatch);
258
0
  if (res != NULL)
259
0
    return dynamic_cast<DnsQuery*>(res);
260
0
  return NULL;
261
0
}
262
263
264
DnsQuery* DnsLayer::getFirstQuery() const
265
0
{
266
0
  return m_FirstQuery;
267
0
}
268
269
270
DnsQuery* DnsLayer::getNextQuery(DnsQuery* query) const
271
0
{
272
0
  if (query == NULL
273
0
    || query->getNextResource() == NULL
274
0
    || query->getType() != DnsQueryType
275
0
    || query->getNextResource()->getType() != DnsQueryType)
276
0
    return NULL;
277
278
0
  return (DnsQuery*)(query->getNextResource());
279
0
}
280
281
size_t DnsLayer::getQueryCount() const
282
0
{
283
0
  return be16toh(getDnsHeader()->numberOfQuestions);
284
0
}
285
286
DnsResource* DnsLayer::getAnswer(const std::string& name, bool exactMatch) const
287
0
{
288
0
  uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers);
289
0
  IDnsResource* res = getResourceByName(m_FirstAnswer, numOfAnswers, name, exactMatch);
290
0
  if (res != NULL)
291
0
    return dynamic_cast<DnsResource*>(res);
292
0
  return NULL;
293
0
}
294
295
DnsResource* DnsLayer::getFirstAnswer() const
296
0
{
297
0
  return m_FirstAnswer;
298
0
}
299
300
DnsResource* DnsLayer::getNextAnswer(DnsResource* answer) const
301
0
{
302
0
  if (answer == NULL
303
0
    || answer->getNextResource() == NULL
304
0
    || answer->getType() != DnsAnswerType
305
0
    || answer->getNextResource()->getType() != DnsAnswerType)
306
0
    return NULL;
307
308
0
  return (DnsResource*)(answer->getNextResource());
309
0
}
310
311
size_t DnsLayer::getAnswerCount() const
312
0
{
313
0
  return be16toh(getDnsHeader()->numberOfAnswers);
314
0
}
315
316
DnsResource* DnsLayer::getAuthority(const std::string& name, bool exactMatch) const
317
0
{
318
0
  uint16_t numOfAuthorities = be16toh(getDnsHeader()->numberOfAuthority);
319
0
  IDnsResource* res = getResourceByName(m_FirstAuthority, numOfAuthorities, name, exactMatch);
320
0
  if (res != NULL)
321
0
    return dynamic_cast<DnsResource*>(res);
322
0
  return NULL;
323
0
}
324
325
DnsResource* DnsLayer::getFirstAuthority() const
326
0
{
327
0
  return m_FirstAuthority;
328
0
}
329
330
DnsResource* DnsLayer::getNextAuthority(DnsResource* authority) const
331
0
{
332
0
  if (authority == NULL
333
0
    || authority->getNextResource() == NULL
334
0
    || authority->getType() != DnsAuthorityType
335
0
    || authority->getNextResource()->getType() != DnsAuthorityType)
336
0
    return NULL;
337
338
0
  return (DnsResource*)(authority->getNextResource());
339
0
}
340
341
size_t DnsLayer::getAuthorityCount() const
342
0
{
343
0
  return be16toh(getDnsHeader()->numberOfAuthority);
344
0
}
345
346
DnsResource* DnsLayer::getAdditionalRecord(const std::string& name, bool exactMatch) const
347
0
{
348
0
  uint16_t numOfAdditionalRecords = be16toh(getDnsHeader()->numberOfAdditional);
349
0
  IDnsResource* res = getResourceByName(m_FirstAdditional, numOfAdditionalRecords, name, exactMatch);
350
0
  if (res != NULL)
351
0
    return dynamic_cast<DnsResource*>(res);
352
0
  return NULL;
353
0
}
354
355
DnsResource* DnsLayer::getFirstAdditionalRecord() const
356
0
{
357
0
  return m_FirstAdditional;
358
0
}
359
360
DnsResource* DnsLayer::getNextAdditionalRecord(DnsResource* additionalRecord) const
361
0
{
362
0
  if (additionalRecord == NULL
363
0
    || additionalRecord->getNextResource() == NULL
364
0
    || additionalRecord->getType() != DnsAdditionalType
365
0
    || additionalRecord->getNextResource()->getType() != DnsAdditionalType)
366
0
    return NULL;
367
368
0
  return (DnsResource*)(additionalRecord->getNextResource());
369
0
}
370
371
size_t DnsLayer::getAdditionalRecordCount() const
372
0
{
373
0
  return be16toh(getDnsHeader()->numberOfAdditional);
374
0
}
375
376
std::string DnsLayer::toString() const
377
0
{
378
0
  std::ostringstream tidAsString;
379
0
  tidAsString << be16toh(getDnsHeader()->transactionID);
380
381
0
  std::ostringstream queryCount;
382
0
  queryCount << getQueryCount();
383
384
0
  std::ostringstream answerCount;
385
0
  answerCount << getAnswerCount();
386
387
0
  std::ostringstream authorityCount;
388
0
  authorityCount << getAuthorityCount();
389
390
0
  std::ostringstream additionalCount;
391
0
  additionalCount << getAdditionalRecordCount();
392
393
0
  if (getDnsHeader()->queryOrResponse == 1)
394
0
  {
395
0
    return "DNS query response, ID: " + tidAsString.str() + ";" +
396
0
        " queries: " + queryCount.str() +
397
0
        ", answers: " + answerCount.str() +
398
0
        ", authorities: " + authorityCount.str() +
399
0
        ", additional record: " + additionalCount.str();
400
0
  }
401
0
  else if (getDnsHeader()->queryOrResponse == 0)
402
0
  {
403
0
    return "DNS query, ID: " + tidAsString.str() + ";" +
404
0
        " queries: " + queryCount.str() +
405
0
        ", answers: " + answerCount.str() +
406
0
        ", authorities: " + authorityCount.str() +
407
0
        ", additional record: " + additionalCount.str();
408
409
0
  }
410
0
  else // not likely - a DNS with no answers and no queries
411
0
  {
412
0
    return "DNS record without queries and answers, ID: " + tidAsString.str() + ";" +
413
0
        " queries: " + queryCount.str() +
414
0
        ", answers: " + answerCount.str() +
415
0
        ", authorities: " + authorityCount.str() +
416
0
        ", additional record: " + additionalCount.str();
417
0
  }
418
0
}
419
420
IDnsResource* DnsLayer::getFirstResource(DnsResourceType resType) const
421
0
{
422
0
  switch (resType)
423
0
  {
424
0
  case DnsQueryType:
425
0
  {
426
0
    return m_FirstQuery;
427
0
  }
428
0
  case DnsAnswerType:
429
0
  {
430
0
    return m_FirstAnswer;
431
0
  }
432
0
  case DnsAuthorityType:
433
0
  {
434
0
    return m_FirstAuthority;
435
0
  }
436
0
  case DnsAdditionalType:
437
0
  {
438
0
    return m_FirstAdditional;
439
0
  }
440
0
  default:
441
0
    return NULL;
442
0
  }
443
0
}
444
445
void DnsLayer::setFirstResource(DnsResourceType resType, IDnsResource* resource)
446
0
{
447
0
  switch (resType)
448
0
  {
449
0
  case DnsQueryType:
450
0
  {
451
0
    m_FirstQuery = dynamic_cast<DnsQuery*>(resource);
452
0
    break;
453
0
  }
454
0
  case DnsAnswerType:
455
0
  {
456
0
    m_FirstAnswer = dynamic_cast<DnsResource*>(resource);
457
0
    break;
458
0
  }
459
0
  case DnsAuthorityType:
460
0
  {
461
0
    m_FirstAuthority = dynamic_cast<DnsResource*>(resource);
462
0
    break;
463
0
  }
464
0
  case DnsAdditionalType:
465
0
  {
466
0
    m_FirstAdditional = dynamic_cast<DnsResource*>(resource);
467
0
    break;
468
0
  }
469
0
  default:
470
0
    return;
471
0
  }
472
0
}
473
474
DnsResource* DnsLayer::addResource(DnsResourceType resType, const std::string& name, DnsType dnsType, DnsClass dnsClass,
475
    uint32_t ttl, IDnsResourceData* data)
476
0
{
477
  // create new query on temporary buffer
478
0
  uint8_t newResourceRawData[256];
479
0
  memset(newResourceRawData, 0, sizeof(newResourceRawData));
480
481
0
  DnsResource* newResource = new DnsResource(newResourceRawData, resType);
482
483
0
  newResource->setDnsClass(dnsClass);
484
485
0
  newResource->setDnsType(dnsType);
486
487
  // cannot return false since layer shouldn't be extended or shortened in this stage
488
0
  newResource->setName(name);
489
490
0
  newResource->setTTL(ttl);
491
492
0
  if (!newResource->setData(data))
493
0
  {
494
0
    delete newResource;
495
0
    PCPP_LOG_ERROR("Couldn't set new resource data");
496
0
    return NULL;
497
0
  }
498
499
0
  size_t newResourceOffsetInLayer = getBasicHeaderSize();
500
0
  IDnsResource* curResource = m_ResourceList;
501
0
  while (curResource != NULL && curResource->getType() <= resType)
502
0
  {
503
0
    newResourceOffsetInLayer += curResource->getSize();
504
0
    IDnsResource* nextResource = curResource->getNextResource();
505
0
    if (nextResource == NULL || nextResource->getType() > resType)
506
0
      break;
507
0
    curResource = nextResource;
508
0
  }
509
510
511
  // set next resource for new resource. This must happen here for extendLayer to succeed
512
0
  if (curResource != NULL)
513
0
  {
514
0
    if (curResource->getType() > newResource->getType())
515
0
      newResource->setNexResource(m_ResourceList);
516
0
    else
517
0
      newResource->setNexResource(curResource->getNextResource());
518
0
  }
519
0
  else //curResource != NULL
520
0
    newResource->setNexResource(m_ResourceList);
521
522
  // extend layer to make room for the new resource
523
0
  if (!extendLayer(newResourceOffsetInLayer, newResource->getSize(), newResource))
524
0
  {
525
0
    PCPP_LOG_ERROR("Couldn't extend DNS layer, addResource failed");
526
0
    delete newResource;
527
0
    return NULL;
528
0
  }
529
530
  // connect the new resource to layer
531
0
  newResource->setDnsLayer(this, newResourceOffsetInLayer);
532
533
  // connect the new resource to the layer's resource list
534
0
  if (curResource != NULL)
535
0
  {
536
0
    curResource->setNexResource(newResource);
537
    // this means the new resource is the first of it's type
538
0
    if (curResource->getType() < newResource->getType())
539
0
    {
540
0
      setFirstResource(resType, newResource);
541
0
    }
542
    // this means the new resource should be the first resource in the packet
543
0
    else if (curResource->getType() > newResource->getType())
544
0
    {
545
0
      m_ResourceList = newResource;
546
547
0
      setFirstResource(resType, newResource);
548
0
    }
549
0
  }
550
0
  else // curResource != NULL, meaning this is the first resource in layer
551
0
  {
552
0
    m_ResourceList = newResource;
553
554
0
    setFirstResource(resType, newResource);
555
0
  }
556
557
0
  return newResource;
558
0
}
559
560
561
DnsQuery* DnsLayer::addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass)
562
0
{
563
  // create new query on temporary buffer
564
0
  uint8_t newQueryRawData[256];
565
0
  DnsQuery* newQuery = new DnsQuery(newQueryRawData);
566
567
0
  newQuery->setDnsClass(dnsClass);
568
0
  newQuery->setDnsType(dnsType);
569
570
  // cannot return false since layer shouldn't be extended or shortened in this stage
571
0
  newQuery->setName(name);
572
573
574
  // find the offset in the layer to insert the new query
575
0
  size_t newQueryOffsetInLayer = getBasicHeaderSize();
576
0
  DnsQuery* curQuery = getFirstQuery();
577
0
  while (curQuery != NULL)
578
0
  {
579
0
    newQueryOffsetInLayer += curQuery->getSize();
580
0
    DnsQuery* nextQuery = getNextQuery(curQuery);
581
0
    if (nextQuery == NULL)
582
0
      break;
583
0
    curQuery = nextQuery;
584
585
0
  }
586
587
  // set next resource for new query. This must happen here for extendLayer to succeed
588
0
  if (curQuery != NULL)
589
0
    newQuery->setNexResource(curQuery->getNextResource());
590
0
  else
591
0
    newQuery->setNexResource(m_ResourceList);
592
593
  // extend layer to make room for the new query
594
0
  if (!extendLayer(newQueryOffsetInLayer, newQuery->getSize(), newQuery))
595
0
  {
596
0
    PCPP_LOG_ERROR("Couldn't extend DNS layer, addQuery failed");
597
0
    delete newQuery;
598
0
    return NULL;
599
0
  }
600
601
  // connect the new query to layer
602
0
  newQuery->setDnsLayer(this, newQueryOffsetInLayer);
603
604
  // connect the new query to the layer's resource list
605
0
  if (curQuery != NULL)
606
0
    curQuery->setNexResource(newQuery);
607
0
  else // curQuery == NULL, meaning this is the first query
608
0
  {
609
0
    m_ResourceList = newQuery;
610
0
    m_FirstQuery = newQuery;
611
0
  }
612
613
  // increase number of queries
614
0
  getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() + 1);
615
616
0
  return newQuery;
617
0
}
618
619
DnsQuery* DnsLayer::addQuery(DnsQuery* const copyQuery)
620
0
{
621
0
  if (copyQuery == NULL)
622
0
    return NULL;
623
624
0
  return addQuery(copyQuery->getName(), copyQuery->getDnsType(), copyQuery->getDnsClass());
625
0
}
626
627
bool DnsLayer::removeQuery(const std::string& queryNameToRemove, bool exactMatch)
628
0
{
629
0
  DnsQuery* queryToRemove = getQuery(queryNameToRemove, exactMatch);
630
0
  if (queryToRemove == NULL)
631
0
  {
632
0
    PCPP_LOG_DEBUG("Query not found");
633
0
    return false;
634
0
  }
635
636
0
  return removeQuery(queryToRemove);
637
0
}
638
639
bool DnsLayer::removeQuery(DnsQuery* queryToRemove)
640
0
{
641
0
  bool res = removeResource(queryToRemove);
642
0
  if (res)
643
0
  {
644
    // decrease number of query records
645
0
    getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() - 1);
646
0
  }
647
648
0
  return res;
649
0
}
650
651
DnsResource* DnsLayer::addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data)
652
0
{
653
0
  DnsResource* res = addResource(DnsAnswerType, name, dnsType, dnsClass, ttl, data);
654
0
  if (res != NULL)
655
0
  {
656
    // increase number of answer records
657
0
    getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() + 1);
658
0
  }
659
660
0
  return res;
661
0
}
662
663
DnsResource* DnsLayer::addAnswer(DnsResource* const copyAnswer)
664
0
{
665
0
  if (copyAnswer == NULL)
666
0
    return NULL;
667
668
0
  return addAnswer(copyAnswer->getName(), copyAnswer->getDnsType(), copyAnswer->getDnsClass(), copyAnswer->getTTL(), copyAnswer->getData().get());
669
0
}
670
671
bool DnsLayer::removeAnswer(const std::string& answerNameToRemove, bool exactMatch)
672
0
{
673
0
  DnsResource* answerToRemove = getAnswer(answerNameToRemove, exactMatch);
674
0
  if (answerToRemove == NULL)
675
0
  {
676
0
    PCPP_LOG_DEBUG("Answer record not found");
677
0
    return false;
678
0
  }
679
680
0
  return removeAnswer(answerToRemove);
681
0
}
682
683
bool DnsLayer::removeAnswer(DnsResource* answerToRemove)
684
0
{
685
0
  bool res = removeResource(answerToRemove);
686
0
  if (res)
687
0
  {
688
    // decrease number of answer records
689
0
    getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() - 1);
690
0
  }
691
692
0
  return res;
693
0
}
694
695
696
DnsResource* DnsLayer::addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data)
697
0
{
698
0
  DnsResource* res = addResource(DnsAuthorityType, name, dnsType, dnsClass, ttl, data);
699
0
  if (res != NULL)
700
0
  {
701
    // increase number of authority records
702
0
    getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() + 1);
703
0
  }
704
705
0
  return res;
706
0
}
707
708
DnsResource* DnsLayer::addAuthority(DnsResource* const copyAuthority)
709
0
{
710
0
  if (copyAuthority == NULL)
711
0
    return NULL;
712
713
0
  return addAuthority(copyAuthority->getName(), copyAuthority->getDnsType(), copyAuthority->getDnsClass(), copyAuthority->getTTL(), copyAuthority->getData().get());
714
0
}
715
716
bool DnsLayer::removeAuthority(const std::string& authorityNameToRemove, bool exactMatch)
717
0
{
718
0
  DnsResource* authorityToRemove = getAuthority(authorityNameToRemove, exactMatch);
719
0
  if (authorityToRemove == NULL)
720
0
  {
721
0
    PCPP_LOG_DEBUG("Authority not found");
722
0
    return false;
723
0
  }
724
725
0
  return removeAuthority(authorityToRemove);
726
0
}
727
728
bool DnsLayer::removeAuthority(DnsResource* authorityToRemove)
729
0
{
730
0
  bool res = removeResource(authorityToRemove);
731
0
  if (res)
732
0
  {
733
    // decrease number of authority records
734
0
    getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() - 1);
735
0
  }
736
737
0
  return res;
738
0
}
739
740
741
DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data)
742
0
{
743
0
  DnsResource* res = addResource(DnsAdditionalType, name, dnsType, dnsClass, ttl, data);
744
0
  if (res != NULL)
745
0
  {
746
    // increase number of authority records
747
0
    getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() + 1);
748
0
  }
749
750
0
  return res;
751
0
}
752
753
DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, uint32_t customData2, IDnsResourceData* data)
754
0
{
755
0
  DnsResource* res = addAdditionalRecord(name, dnsType, DNS_CLASS_ANY, customData2, data);
756
0
  if (res != NULL)
757
0
  {
758
0
    res->setCustomDnsClass(customData1);
759
0
  }
760
761
0
  return res;
762
0
}
763
764
DnsResource* DnsLayer::addAdditionalRecord(DnsResource* const copyAdditionalRecord)
765
0
{
766
0
  if (copyAdditionalRecord == NULL)
767
0
    return NULL;
768
769
0
  return addAdditionalRecord(copyAdditionalRecord->getName(), copyAdditionalRecord->getDnsType(), copyAdditionalRecord->getCustomDnsClass(), copyAdditionalRecord->getTTL(), copyAdditionalRecord->getData().get());
770
0
}
771
772
bool DnsLayer::removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch)
773
0
{
774
0
  DnsResource* additionalRecordToRemove = getAdditionalRecord(additionalRecordNameToRemove, exactMatch);
775
0
  if (additionalRecordToRemove == NULL)
776
0
  {
777
0
    PCPP_LOG_DEBUG("Additional record not found");
778
0
    return false;
779
0
  }
780
781
0
  return removeAdditionalRecord(additionalRecordToRemove);
782
0
}
783
784
bool DnsLayer::removeAdditionalRecord(DnsResource* additionalRecordToRemove)
785
0
{
786
0
  bool res = removeResource(additionalRecordToRemove);
787
0
  if (res)
788
0
  {
789
    // decrease number of additional records
790
0
    getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() - 1);
791
0
  }
792
793
0
  return res;
794
0
}
795
796
bool DnsLayer::removeResource(IDnsResource* resourceToRemove)
797
0
{
798
0
  if (resourceToRemove == NULL)
799
0
  {
800
0
    PCPP_LOG_DEBUG("resourceToRemove cannot be NULL");
801
0
    return false;
802
0
  }
803
804
  // find the resource preceding resourceToRemove
805
0
  IDnsResource* prevResource = m_ResourceList;
806
807
0
  if (m_ResourceList != resourceToRemove)
808
0
  {
809
0
    while (prevResource != NULL)
810
0
    {
811
0
      IDnsResource* temp = prevResource->getNextResource();
812
0
      if (temp == resourceToRemove)
813
0
        break;
814
815
0
      prevResource = temp;
816
0
    }
817
0
  }
818
819
0
  if (prevResource == NULL)
820
0
  {
821
0
    PCPP_LOG_DEBUG("Resource not found");
822
0
    return false;
823
0
  }
824
825
  // shorten the layer and fix offset in layer for all next DNS resources in the packet
826
0
  if (!shortenLayer(resourceToRemove->m_OffsetInLayer, resourceToRemove->getSize(), resourceToRemove))
827
0
  {
828
0
    PCPP_LOG_ERROR("Couldn't shorten the DNS layer, resource cannot be removed");
829
0
    return false;
830
0
  }
831
832
  // remove resourceToRemove from the resources linked list
833
0
  if (m_ResourceList != resourceToRemove)
834
0
  {
835
0
    prevResource->setNexResource(resourceToRemove->getNextResource());
836
0
  }
837
0
  else
838
0
  {
839
0
    m_ResourceList = resourceToRemove->getNextResource();
840
0
  }
841
842
  // check whether resourceToRemove was the first of its type
843
0
  if (getFirstResource(resourceToRemove->getType()) == resourceToRemove)
844
0
  {
845
0
    IDnsResource* nextResource = resourceToRemove->getNextResource();
846
0
    if (nextResource != NULL && nextResource->getType() == resourceToRemove->getType())
847
0
      setFirstResource(resourceToRemove->getType(), nextResource);
848
0
    else
849
0
      setFirstResource(resourceToRemove->getType(), NULL);
850
0
  }
851
852
  // free resourceToRemove memory
853
0
  delete resourceToRemove;
854
855
0
  return true;
856
0
}
857
858
859
// ~~~~~~~~~~~~~~~
860
// DnsOverTcpLayer
861
// ~~~~~~~~~~~~~~~
862
863
uint16_t DnsOverTcpLayer::getTcpMessageLength()
864
0
{
865
0
  return be16toh(*(uint16_t*)m_Data);
866
0
}
867
868
void DnsOverTcpLayer::setTcpMessageLength(uint16_t value)
869
0
{
870
0
  ((uint16_t*)m_Data)[0] = htobe16(value);
871
0
}
872
873
void DnsOverTcpLayer::computeCalculateFields()
874
0
{
875
0
  setTcpMessageLength(m_DataLen - sizeof(uint16_t));
876
0
}
877
878
} // namespace pcpp