• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.67
/pdns/dnsrecords.hh
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#pragma once
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26

27
#include "dnsparser.hh"
28
#include "dnswriter.hh"
29
#include "lock.hh"
30
#include "rcpgenerator.hh"
31
#include <set>
32
#include <bitset>
33
#include "namespaces.hh"
34
#include "iputils.hh"
35
#include "svc-records.hh"
36

37
struct ReportIsOnlyCallableByReportAllTypes;
38

39
#define includeboilerplate(RNAME)   RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr); \
40
  RNAME##RecordContent(const string& zoneData);                                                  \
41
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);                         \
42
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);          \
43
  static std::shared_ptr<DNSRecordContent> make(const string& zonedata);                         \
44
  string getZoneRepresentation(bool noDot=false) const override;                                 \
45
  void toPacket(DNSPacketWriter& pw) const override;                                             \
46
  uint16_t getType() const override { return QType::RNAME; }                                     \
152,142✔
47
  template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false) const;             \
48
  template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false);
49

50
class NAPTRRecordContent : public DNSRecordContent
51
{
52
public:
53
  NAPTRRecordContent(uint16_t order, uint16_t preference, string flags, string services, string regexp, DNSName replacement);
54

55
  includeboilerplate(NAPTR)
56
  template<class Convertor> void xfrRecordContent(Convertor& conv);
57
  const string& getFlags() const
58
  {
6✔
59
    return d_flags;
6✔
60
  }
6✔
61
  const DNSName& getReplacement() const
62
  {
6✔
63
    return d_replacement;
6✔
64
  }
6✔
65
private:
66
  uint16_t d_order, d_preference;
67
  string d_flags, d_services, d_regexp;
68
  DNSName d_replacement;
69
};
70

71

72
class ARecordContent : public DNSRecordContent
73
{
74
public:
75
  explicit ARecordContent(const ComboAddress& ca);
76
  explicit ARecordContent(uint32_t ip);
77
  includeboilerplate(A)
78
  void doRecordCheck(const DNSRecord& dr);
79
  ComboAddress getCA(int port=0) const;
80
  bool operator==(const DNSRecordContent& rhs) const override
81
  {
70✔
82
    if(typeid(*this) != typeid(rhs))
70✔
83
      return false;
3✔
84
    return d_ip == dynamic_cast<const ARecordContent&>(rhs).d_ip;
67✔
85
  }
70✔
86
private:
87
  uint32_t d_ip;
88
};
89

90
class AAAARecordContent : public DNSRecordContent
91
{
92
public:
93
  AAAARecordContent(std::string &val);
94
  explicit AAAARecordContent(const ComboAddress& ca);
95
  includeboilerplate(AAAA)
96
  ComboAddress getCA(int port=0) const;
97
  bool operator==(const DNSRecordContent& rhs) const override
98
  {
44✔
99
    if(typeid(*this) != typeid(rhs))
44✔
100
      return false;
4✔
101
    return d_ip6 == dynamic_cast<const decltype(this)>(&rhs)->d_ip6;
40✔
102
  }
44✔
103
private:
104
  string d_ip6; // why??
105
};
106

107
class MXRecordContent : public DNSRecordContent
108
{
109
public:
110
  MXRecordContent(uint16_t preference, DNSName  mxname);
111

112
  includeboilerplate(MX)
113

114
  uint16_t d_preference;
115
  DNSName d_mxname;
116

117
  bool operator==(const DNSRecordContent& rhs) const override
118
  {
9✔
119
    if(typeid(*this) != typeid(rhs))
9!
120
      return false;
×
121
    auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
9✔
122
    return std::tie(d_preference, d_mxname) == std::tie(rrhs->d_preference, rrhs->d_mxname);
9✔
123
  }
9✔
124

125
};
126

127
class KXRecordContent : public DNSRecordContent
128
{
129
public:
130
  KXRecordContent(uint16_t preference, const DNSName& exchanger);
131

132
  includeboilerplate(KX)
133

134
private:
135
  uint16_t d_preference;
136
  DNSName d_exchanger;
137
};
138

139
class IPSECKEYRecordContent : public DNSRecordContent
140
{
141
public:
142
  IPSECKEYRecordContent(uint16_t preference, uint8_t gatewaytype, uint8_t algo, const DNSName& gateway, const string& publickey);
143

144
  includeboilerplate(IPSECKEY)
145

146
private:
147
  uint32_t d_ip4;
148
  DNSName d_gateway;
149
  string d_publickey;
150
  string d_ip6;
151
  uint8_t d_preference, d_gatewaytype, d_algorithm;
152
};
153

154
class DHCIDRecordContent : public DNSRecordContent
155
{
156
public:
157
  includeboilerplate(DHCID)
158

159
private:
160
  string d_content;
161
};
162

163

164
class SRVRecordContent : public DNSRecordContent
165
{
166
public:
167
  SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, DNSName  target);
168

169
  includeboilerplate(SRV)
170

171
  uint16_t d_weight, d_port;
172
  DNSName d_target;
173
  uint16_t d_preference;
174
};
175

176
class TSIGRecordContent : public DNSRecordContent
177
{
178
public:
179
  includeboilerplate(TSIG)
180
  TSIGRecordContent() = default;
2,777,312✔
181

182
  uint16_t d_origID{0};
183
  uint16_t d_fudge{0};
184

185
  DNSName d_algoName;
186
  string d_mac;
187
  string d_otherData;
188
  uint64_t d_time{0};
189
  //  uint16_t d_macSize;
190
  uint16_t d_eRcode{0};
191
  // uint16_t d_otherLen
192
};
193

194

195
class TXTRecordContent : public DNSRecordContent
196
{
197
public:
198
  includeboilerplate(TXT)
199

200
  string d_text;
201
};
202

203
#ifdef HAVE_LUA_RECORDS
204
class LUARecordContent : public DNSRecordContent
205
{
206
public:
207
  includeboilerplate(LUA)
208
  string getCode() const;
209
  uint16_t d_type;
210
  string d_code;
211
};
212
#endif
213

214
class ENTRecordContent : public DNSRecordContent
215
{
216
public:
217
  includeboilerplate(ENT)
218
};
219

220
class SPFRecordContent : public DNSRecordContent
221
{
222
public:
223
  includeboilerplate(SPF)
224
  const std::string& getText() const
225
  {
1✔
226
    return d_text;
1✔
227
  }
1✔
228

229
private:
230
  string d_text;
231
};
232

233

234
class NSRecordContent : public DNSRecordContent
235
{
236
public:
237
  includeboilerplate(NS)
238
  explicit NSRecordContent(const DNSName& content) : d_content(content){}
14,762✔
239
  const DNSName& getNS() const { return d_content; }
312,684✔
240
  bool operator==(const DNSRecordContent& rhs) const override
241
  {
97✔
242
    if(typeid(*this) != typeid(rhs))
97!
243
      return false;
×
244
    auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
97✔
245
    return d_content == rrhs->d_content;
97✔
246
  }
97✔
247

248
private:
249
  DNSName d_content;
250
};
251

252
class PTRRecordContent : public DNSRecordContent
253
{
254
public:
255
  includeboilerplate(PTR)
256
  explicit PTRRecordContent(const DNSName& content) : d_content(content){}
6✔
257
  const DNSName& getContent() const { return d_content; }
34✔
258
private:
259
  DNSName d_content;
260
};
261

262
class CNAMERecordContent : public DNSRecordContent
263
{
264
public:
265
  includeboilerplate(CNAME)
266
  CNAMERecordContent(const DNSName& content) : d_content(content){}
174✔
267
  DNSName getTarget() const { return d_content; }
6,374✔
268
private:
269
  DNSName d_content;
270
};
271

272
#if !defined(RECURSOR)
273
class ALIASRecordContent : public DNSRecordContent
274
{
275
public:
276
  includeboilerplate(ALIAS)
277

278
  [[nodiscard]] const DNSName& getContent() const
279
  {
280
    return d_content;
281
  }
282
private:
283
  DNSName d_content;
284
};
285
#endif
286

287
class DNAMERecordContent : public DNSRecordContent
288
{
289
public:
290
  includeboilerplate(DNAME)
291
  DNAMERecordContent(const DNSName& content) : d_content(content){}
×
292
  const DNSName& getTarget() const { return d_content; }
72✔
293
private:
294
  DNSName d_content;
295
};
296

297

298
class MBRecordContent : public DNSRecordContent
299
{
300
public:
301
  includeboilerplate(MB)
302

303
private:
304
  DNSName d_madname;
305
};
306

307
class MGRecordContent : public DNSRecordContent
308
{
309
public:
310
  includeboilerplate(MG)
311

312
private:
313
  DNSName d_mgmname;
314
};
315

316
class MRRecordContent : public DNSRecordContent
317
{
318
public:
319
  includeboilerplate(MR)
320

321
private:
322
  DNSName d_alias;
323
};
324

325
class MINFORecordContent : public DNSRecordContent
326
{
327
public:
328
  includeboilerplate(MINFO)
329

330
private:
331
  DNSName d_rmailbx;
332
  DNSName d_emailbx;
333
};
334

335
class OPTRecordContent : public DNSRecordContent
336
{
337
public:
338
  OPTRecordContent() = default;
2✔
339
  includeboilerplate(OPT)
340
  void getData(vector<pair<uint16_t, string> > &opts) const;
341
private:
342
  string d_data;
343
};
344

345

346
class HINFORecordContent : public DNSRecordContent
347
{
348
public:
349
  includeboilerplate(HINFO)
350

351
private:
352
  string d_cpu, d_host;
353
};
354

355
class RPRecordContent : public DNSRecordContent
356
{
357
public:
358
  includeboilerplate(RP)
359

360
private:
361
  DNSName d_mbox, d_info;
362
};
363

364

365
class DNSKEYRecordContent : public DNSRecordContent
366
{
367
public:
368
  DNSKEYRecordContent();
369
  includeboilerplate(DNSKEY)
370
  uint16_t getTag() const;
371

372
  uint16_t d_flags{0};
373
  uint8_t d_protocol{0};
374
  uint8_t d_algorithm{0};
375
  string d_key;
376
  bool operator<(const DNSKEYRecordContent& rhs) const
377
  {
5,127✔
378
    return std::tie(d_flags, d_protocol, d_algorithm, d_key) <
5,127✔
379
      std::tie(rhs.d_flags, rhs.d_protocol, rhs.d_algorithm, rhs.d_key);
5,127✔
380
  }
5,127✔
381
};
382

383
class CDNSKEYRecordContent : public DNSRecordContent
384
{
385
public:
386
  CDNSKEYRecordContent();
387
  includeboilerplate(CDNSKEY)
388
  uint16_t getTag();
389

390
  uint16_t d_flags{0};
391
  uint8_t d_protocol{0};
392
  uint8_t d_algorithm{0};
393
  string d_key;
394
};
395

396
class DSRecordContent : public DNSRecordContent
397
{
398
public:
399
  DSRecordContent();
400
  bool operator==(const DNSRecordContent& rhs) const override
401
  {
1,704✔
402
    if(typeid(*this) != typeid(rhs))
1,704!
403
      return false;
×
404
    auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
1,704✔
405
    return std::tie(d_tag, d_algorithm, d_digesttype, d_digest) ==
1,704✔
406
      std::tie(rrhs->d_tag, rrhs->d_algorithm, rrhs->d_digesttype, rrhs->d_digest);
1,704✔
407
  }
1,704✔
408
  bool operator<(const DSRecordContent& rhs) const
409
  {
5,283✔
410
    return std::tie(d_tag, d_algorithm, d_digesttype, d_digest) <
5,283✔
411
      std::tie(rhs.d_tag, rhs.d_algorithm, rhs.d_digesttype, rhs.d_digest);
5,283✔
412
  }
5,283✔
413

414
  includeboilerplate(DS)
415

416
  uint16_t d_tag{0};
417
  uint8_t d_algorithm{0}, d_digesttype{0};
418
  string d_digest;
419
};
420

421
class CDSRecordContent : public DNSRecordContent
422
{
423
public:
424
  CDSRecordContent();
425
  includeboilerplate(CDS)
426

427
  uint16_t d_tag{0};
428
  uint8_t d_algorithm{0}, d_digesttype{0};
429
  string d_digest;
430
};
431

432
class DLVRecordContent : public DNSRecordContent
433
{
434
public:
435
  DLVRecordContent();
436
  includeboilerplate(DLV)
437

438
  uint16_t d_tag{0};
439
  uint8_t d_algorithm{0}, d_digesttype{0};
440
  string d_digest;
441
};
442

443

444
class SSHFPRecordContent : public DNSRecordContent
445
{
446
public:
447
  includeboilerplate(SSHFP)
448

449
private:
450
  uint8_t d_algorithm, d_fptype;
451
  string d_fingerprint;
452
};
453

454
class KEYRecordContent : public DNSRecordContent
455
{
456
public:
457
  includeboilerplate(KEY)
458

459
private:
460
  uint16_t d_flags;
461
  uint8_t d_protocol, d_algorithm;
462
  string d_certificate;
463
};
464

465
class AFSDBRecordContent : public DNSRecordContent
466
{
467
public:
468
  includeboilerplate(AFSDB)
469

470
private:
471
  uint16_t d_subtype;
472
  DNSName d_hostname;
473
};
474

475

476
#ifdef CERT
477
#error likely openssl/ssl2.h is included, defining CERT, avoid that or undef CERT before including dnsrecords.hh
478
#endif
479

480
class CERTRecordContent : public DNSRecordContent
481
{
482
public:
483
  includeboilerplate(CERT)
484

485
private:
486
  uint16_t d_type, d_tag;
487
  string d_certificate;
488
  uint8_t d_algorithm;
489
};
490

491
class TLSARecordContent : public DNSRecordContent
492
{
493
public:
494
  includeboilerplate(TLSA)
495

496
private:
497
  uint8_t d_certusage, d_selector, d_matchtype;
498
  string d_cert;
499
};
500

501
class SMIMEARecordContent : public DNSRecordContent
502
{
503
public:
504
  includeboilerplate(SMIMEA)
505

506
private:
507
  uint8_t d_certusage, d_selector, d_matchtype;
508
  string d_cert;
509
};
510

511
class OPENPGPKEYRecordContent : public DNSRecordContent
512
{
513
public:
514
  includeboilerplate(OPENPGPKEY)
515

516
private:
517
  string d_keyring;
518
};
519

520
class SVCBBaseRecordContent : public DNSRecordContent
521
{
522
  public:
523
    const DNSName& getTarget() const {return d_target;}
×
524
    uint16_t getPriority() const {return d_priority;}
×
525
    // Returns true if a value for |key| was set to 'auto'
526
    bool autoHint(const SvcParam::SvcParamKey &key) const;
527
    // Sets the |addresses| to the existing hints for |key|
528
    void setHints(const SvcParam::SvcParamKey &key, const std::vector<ComboAddress> &addresses);
529
    // Removes the parameter for |key| from d_params
530
    void removeParam(const SvcParam::SvcParamKey &key);
531
    // Whether or not there are any parameter
532
    bool hasParams() const;
533
    // Whether or not the param of |key| exists
534
    bool hasParam(const SvcParam::SvcParamKey &key) const;
535
    // Get the parameter with |key|, will throw out_of_range if param isn't there
536
    SvcParam getParam(const SvcParam::SvcParamKey &key) const;
537
    virtual std::shared_ptr<SVCBBaseRecordContent> clone() const = 0;
538

539
  protected:
540
    std::set<SvcParam> d_params;
541
    DNSName d_target;
542
    uint16_t d_priority;
543

544
    // Get the iterator to parameter with |key|, return value can be d_params::end
545
  std::set<SvcParam>::const_iterator getParamIt(const SvcParam::SvcParamKey &key) const;
546
};
547

548
class SVCBRecordContent : public SVCBBaseRecordContent
549
{
550
public:
551
  includeboilerplate(SVCB)
552
  std::shared_ptr<SVCBBaseRecordContent> clone() const override;
553
};
554

555
class HTTPSRecordContent : public SVCBBaseRecordContent
556
{
557
public:
558
  includeboilerplate(HTTPS)
559
  std::shared_ptr<SVCBBaseRecordContent> clone() const override;
560
};
561

562
class RRSIGRecordContent : public DNSRecordContent
563
{
564
public:
565
  RRSIGRecordContent();
566
  includeboilerplate(RRSIG)
567

568
  uint16_t d_type{0};
569
  uint16_t d_tag{0};
570
  DNSName d_signer;
571
  string d_signature;
572
  uint32_t d_originalttl{0}, d_sigexpire{0}, d_siginception{0};
573
  uint8_t d_algorithm{0}, d_labels{0};
574
};
575

576
//namespace {
577
  struct soatimes
578
  {
579
    uint32_t serial;
580
    uint32_t refresh;
581
    uint32_t retry;
582
    uint32_t expire;
583
    uint32_t minimum;
584
  };
585
//}
586

587
class RKEYRecordContent : public DNSRecordContent
588
{
589
public:
590
  RKEYRecordContent();
591
  includeboilerplate(RKEY)
592
  uint16_t d_flags{0};
593
  uint8_t d_protocol{0}, d_algorithm{0};
594
  string d_key;
595
};
596

597
class SOARecordContent : public DNSRecordContent
598
{
599
public:
600
  includeboilerplate(SOA)
601
  SOARecordContent(DNSName  mname, DNSName  rname, const struct soatimes& st);
602

603
  DNSName d_mname;
604
  DNSName d_rname;
605
  struct soatimes d_st;
606
};
607

608
class ZONEMDRecordContent : public DNSRecordContent
609
{
610
public:
611
  includeboilerplate(ZONEMD)
612
  //ZONEMDRecordContent(uint32_t serial, uint8_t scheme, uint8_t hashalgo, string digest);
613

614
  uint32_t d_serial;
615
  uint8_t d_scheme;
616
  uint8_t d_hashalgo;
617
  string d_digest;
618
};
619

620
class NSECBitmap
621
{
622
public:
623
  NSECBitmap(): d_bitset(nullptr)
624
  {
52,110✔
625
  }
52,110✔
626
  NSECBitmap(const NSECBitmap& rhs): d_set(rhs.d_set)
627
  {
46✔
628
    if (rhs.d_bitset) {
46!
629
      d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset));
×
630
    }
×
631
  }
46✔
632
  NSECBitmap& operator=(const NSECBitmap& rhs)
633
  {
×
634
    d_set = rhs.d_set;
×
635

×
636
    if (rhs.d_bitset) {
×
637
      d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset));
×
638
    }
×
639

×
640
    return *this;
×
641
  }
×
642
  NSECBitmap(NSECBitmap&& rhs) noexcept :
643
    d_bitset(std::move(rhs.d_bitset)), d_set(std::move(rhs.d_set))
644
  {
364✔
645
  }
364✔
646
  bool isSet(uint16_t type) const
647
  {
596,612✔
648
    if (d_bitset) {
596,612✔
649
      return d_bitset->test(type);
393,222✔
650
    }
393,222✔
651
    return d_set.count(type);
203,390✔
652
  }
596,612✔
653
  void set(uint16_t type)
654
  {
531,393✔
655
    if (!d_bitset) {
531,393✔
656
      if (d_set.size() >= 200) {
139,382✔
657
        migrateToBitSet();
6✔
658
      }
6✔
659
    }
139,382✔
660
    if (d_bitset) {
531,393✔
661
      d_bitset->set(type);
392,016✔
662
    }
392,016✔
663
    else {
139,377✔
664
      d_set.insert(type);
139,377✔
665
    }
139,377✔
666
  }
531,393✔
667
  size_t count() const
668
  {
21✔
669
    if (d_bitset) {
21✔
670
      return d_bitset->count();
6✔
671
    }
6✔
672
    else {
15✔
673
      return d_set.size();
15✔
674
    }
15✔
675
  }
21✔
676

677
  void fromPacket(PacketReader& pr);
678
  void toPacket(DNSPacketWriter& pw) const;
679
  std::string getZoneRepresentation() const;
680

681
  static constexpr size_t const nbTypes = 65536;
682

683
private:
684

685
  void migrateToBitSet()
686
  {
6✔
687
    d_bitset = std::make_unique<std::bitset<nbTypes>>();
6✔
688
    for (const auto& type : d_set) {
1,200✔
689
      d_bitset->set(type);
1,200✔
690
    }
1,200✔
691
    d_set.clear();
6✔
692
  }
6✔
693
  /* using a dynamic set is very efficient for a small number of
694
     types covered (~200), but uses a lot of memory (up to 3MB)
695
     when there are a lot of them.
696
     So we start with the set, but allocate and switch to a bitset
697
     if the number of covered types increases a lot */
698
  std::unique_ptr<std::bitset<nbTypes>> d_bitset;
699
  std::set<uint16_t> d_set;
700
};
701

702
class NSECRecordContent : public DNSRecordContent
703
{
704
public:
705
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
706
  NSECRecordContent() = default;
2,076✔
707
  NSECRecordContent(const string& content, const DNSName& zone=DNSName());
708

709
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
710
  static std::shared_ptr<DNSRecordContent> make(const string& content);
711
  string getZoneRepresentation(bool noDot=false) const override;
712
  void toPacket(DNSPacketWriter& pw) const override;
713
  uint16_t getType() const override
714
  {
4,395✔
715
    return QType::NSEC;
4,395✔
716
  }
4,395✔
717
  bool isSet(uint16_t type) const
718
  {
198,639✔
719
    return d_bitmap.isSet(type);
198,639✔
720
  }
198,639✔
721
  void set(uint16_t type)
722
  {
197,434✔
723
    d_bitmap.set(type);
197,434✔
724
  }
197,434✔
725
  void set(const NSECBitmap& bitmap)
726
  {
×
727
    d_bitmap = bitmap;
×
728
  }
×
729
  size_t numberOfTypesSet() const
730
  {
9✔
731
    return d_bitmap.count();
9✔
732
  }
9✔
733

734
  DNSName d_next;
735
private:
736
  NSECBitmap d_bitmap;
737
};
738

739
class NSEC3RecordContent : public DNSRecordContent
740
{
741
public:
742
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
743
  NSEC3RecordContent() = default;
2,669✔
744
  NSEC3RecordContent(const string& content, const DNSName& zone=DNSName());
745

746
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
747
  static std::shared_ptr<DNSRecordContent> make(const string& content);
748
  string getZoneRepresentation(bool noDot=false) const override;
749
  void toPacket(DNSPacketWriter& pw) const override;
750

751
  uint8_t d_algorithm{0}, d_flags{0};
752
  uint16_t d_iterations{0};
753
  string d_salt;
754
  string d_nexthash;
755

756
  uint16_t getType() const override
757
  {
3,372✔
758
    return QType::NSEC3;
3,372✔
759
  }
3,372✔
760
  bool isSet(uint16_t type) const
761
  {
397,972✔
762
    return d_bitmap.isSet(type);
397,972✔
763
  }
397,972✔
764
  void set(uint16_t type)
765
  {
317,059✔
766
    d_bitmap.set(type);
317,059✔
767
  }
317,059✔
768
  void set(const NSECBitmap& bitmap)
769
  {
×
770
    d_bitmap = bitmap;
×
771
  }
×
772
  size_t numberOfTypesSet() const
773
  {
12✔
774
    return d_bitmap.count();
12✔
775
  }
12✔
776
  bool isOptOut() const
777
  {
44,894✔
778
    return d_flags & 1;
44,894✔
779
  }
44,894✔
780

781
private:
782
  NSECBitmap d_bitmap;
783
};
784

785
class CSYNCRecordContent : public DNSRecordContent
786
{
787
public:
788
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
789
  CSYNCRecordContent() = default;
3✔
790
  CSYNCRecordContent(const string& content, const DNSName& zone=DNSName());
791

792
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
793
  static std::shared_ptr<DNSRecordContent> make(const string& content);
794
  string getZoneRepresentation(bool noDot=false) const override;
795
  void toPacket(DNSPacketWriter& pw) const override;
796

797
  uint16_t getType() const override
798
  {
3✔
799
    return QType::CSYNC;
3✔
800
  }
3✔
801

802
  void set(uint16_t type)
803
  {
9✔
804
    d_bitmap.set(type);
9✔
805
  }
9✔
806

807
private:
808
  uint32_t d_serial{0};
809
  uint16_t d_flags{0};
810
  NSECBitmap d_bitmap;
811
};
812

813
class NSEC3PARAMRecordContent : public DNSRecordContent
814
{
815
public:
816
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
817
  NSEC3PARAMRecordContent() = default;
15✔
818
  NSEC3PARAMRecordContent(const string& content, const DNSName& zone=DNSName());
819

820
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
821
  static std::shared_ptr<DNSRecordContent> make(const string& content);
822
  string getZoneRepresentation(bool noDot=false) const override;
823
  void toPacket(DNSPacketWriter& pw) const override;
824

825
  uint16_t getType() const override
826
  {
3✔
827
    return QType::NSEC3PARAM;
3✔
828
  }
3✔
829

830

831
  uint8_t d_algorithm{0}, d_flags{0};
832
  uint16_t d_iterations{0};
833
  string d_salt;
834
};
835

836

837
class LOCRecordContent : public DNSRecordContent
838
{
839
public:
840
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
841
  LOCRecordContent() = default;
18✔
842
  LOCRecordContent(const string& content, const string& zone="");
843

844
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
845
  static std::shared_ptr<DNSRecordContent> make(const string& content);
846
  string getZoneRepresentation(bool noDot=false) const override;
847
  void toPacket(DNSPacketWriter& pw) const override;
848

849
  uint8_t d_version{0}, d_size{0}, d_horizpre{0}, d_vertpre{0};
850
  uint32_t d_latitude{0}, d_longitude{0}, d_altitude{0};
851
  uint16_t getType() const override
852
  {
12✔
853
    return QType::LOC;
12✔
854
  }
12✔
855

856
private:
857
};
858

859

860
class NIDRecordContent : public DNSRecordContent
861
{
862
public:
863
  includeboilerplate(NID);
864

865
private:
866
  uint16_t d_preference;
867
  NodeOrLocatorID d_node_id;
868
};
869

870
class L32RecordContent : public DNSRecordContent
871
{
872
public:
873
  includeboilerplate(L32);
874

875
private:
876
  uint16_t d_preference;
877
  uint32_t d_locator;
878
};
879

880
class L64RecordContent : public DNSRecordContent
881
{
882
public:
883
  includeboilerplate(L64);
884

885
private:
886
  uint16_t d_preference;
887
  NodeOrLocatorID d_locator;
888
};
889

890
class LPRecordContent : public DNSRecordContent
891
{
892
public:
893
  includeboilerplate(LP);
894

895
private:
896
  uint16_t d_preference;
897
  DNSName d_fqdn;
898
};
899

900
class EUI48RecordContent : public DNSRecordContent
901
{
902
public:
903
  EUI48RecordContent() = default;
24✔
904
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
905
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
906
  static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
907
  string getZoneRepresentation(bool noDot=false) const override;
908
  void toPacket(DNSPacketWriter& pw) const override;
909
  uint16_t getType() const override { return QType::EUI48; }
3✔
910
private:
911
 // storage for the bytes
912
 uint8_t d_eui48[6];
913
};
914

915
class EUI64RecordContent : public DNSRecordContent
916
{
917
public:
918
  EUI64RecordContent() = default;
24✔
919
  static void report(const ReportIsOnlyCallableByReportAllTypes& guard);
920
  static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
921
  static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
922
  string getZoneRepresentation(bool noDot=false) const override;
923
  void toPacket(DNSPacketWriter& pw) const override;
924
  uint16_t getType() const override { return QType::EUI64; }
3✔
925
private:
926
 // storage for the bytes
927
 uint8_t d_eui64[8];
928
};
929

930
#define APL_FAMILY_IPV4 1
366✔
931
#define APL_FAMILY_IPV6 2
273✔
932
typedef struct s_APLRDataElement {
933
  uint16_t d_family;
934
  uint8_t d_prefix;
935
  bool d_n : 1;
936
  unsigned int d_afdlength : 7;
937
  union u_d_ip {
938
      uint8_t d_ip4[4];
939
      uint8_t d_ip6[16];
940
  } d_ip;
941
} APLRDataElement;
942
class APLRecordContent : public DNSRecordContent
943
{
944
public:
945
  APLRecordContent() = default;
132✔
946
  includeboilerplate(APL)
947
private:
948
  std::vector<APLRDataElement> aplrdata;
949
  APLRDataElement parseAPLElement(const string &element);
950
};
951

952

953
class TKEYRecordContent : public DNSRecordContent
954
{
955
public:
956
  TKEYRecordContent();
957
  includeboilerplate(TKEY)
958

959
  // storage for the bytes
960
  uint16_t d_othersize{0};
961
  uint16_t d_mode{0};
962
  uint32_t d_inception{0};
963
  uint32_t d_expiration{0};
964

965
  DNSName d_algo;
966
  string d_key;
967
  string d_other;
968

969
  uint16_t d_error{0};
970
  uint16_t d_keysize{0};
971
private:
972
};
973

974
class URIRecordContent : public DNSRecordContent {
975
  public:
976
    includeboilerplate(URI)
977
  private:
978
    uint16_t d_priority, d_weight;
979
    string d_target;
980
};
981

982
class CAARecordContent : public DNSRecordContent {
983
  public:
984
    includeboilerplate(CAA)
985
  private:
986
    uint8_t d_flags;
987
    string d_tag, d_value;
988
};
989

990
#define boilerplate(RNAME)                                                                         \
991
std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \
475,318✔
992
{                                                                                                  \
475,318✔
993
  return std::make_shared<RNAME##RecordContent>(dr, pr);                                           \
475,318✔
994
}                                                                                                  \
475,318✔
995
                                                                                                   \
996
RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr)                  \
474,306✔
997
{                                                                                                  \
474,306✔
998
  doRecordCheck(dr);                                                                               \
474,306✔
999
  xfrPacket(pr);                                                                                   \
474,306✔
1000
}                                                                                                  \
474,306✔
1001
                                                                                                   \
1002
std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const string& zonedata)         \
262,244✔
1003
{                                                                                                  \
262,244✔
1004
  return std::make_shared<RNAME##RecordContent>(zonedata);                                         \
262,244✔
1005
}                                                                                                  \
262,244✔
1006
                                                                                                   \
1007
void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) const                                     \
129,450✔
1008
{                                                                                                  \
129,450✔
1009
  this->xfrPacket(pw);                                                                             \
129,450✔
1010
}                                                                                                  \
129,450✔
1011
                                                                                                   \
1012
void RNAME##RecordContent::report(const ReportIsOnlyCallableByReportAllTypes& /* unused */)        \
7,554✔
1013
{                                                                                                  \
7,554✔
1014
  regist(1, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME);       \
7,554✔
1015
  regist(254, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME);     \
7,554✔
1016
}                                                                                                  \
7,554✔
1017
                                                                                                   \
1018
RNAME##RecordContent::RNAME##RecordContent(const string& zoneData)                                 \
317,427✔
1019
{                                                                                                  \
317,427✔
1020
  try {                                                                                            \
317,427✔
1021
    RecordTextReader rtr(zoneData);                                                                \
317,427✔
1022
    xfrPacket(rtr);                                                                                \
317,427✔
1023
  }                                                                                                \
317,427✔
1024
  catch(RecordTextException& rte) {                                                                \
317,427✔
1025
    throw MOADNSException("Parsing record content (try 'pdnsutil check-zone'): "+string(rte.what()));  \
37✔
1026
  }                                                                                                \
37✔
1027
}                                                                                                  \
317,427✔
1028
                                                                                                   \
1029
string RNAME##RecordContent::getZoneRepresentation(bool noDot) const                               \
53,041✔
1030
{                                                                                                  \
53,041✔
1031
  string ret;                                                                                      \
53,041✔
1032
  RecordTextWriter rtw(ret, noDot);                                                                       \
53,041✔
1033
  const_cast<RNAME##RecordContent*>(this)->xfrPacket(rtw);                                         \
53,041✔
1034
  return ret;                                                                                      \
53,041✔
1035
}
53,041✔
1036

1037

1038
#define boilerplate_conv(RNAME, CONV)                                   \
1039
boilerplate(RNAME)                                                      \
1040
template<class Convertor>                                               \
1041
void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) \
843,641✔
1042
{                                                                       \
843,641✔
1043
  CONV;                                                                 \
843,641!
1044
  if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
843,641!
1045
}                                                                       \
84✔
1046
template<class Convertor>                                               \
1047
void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) const \
129,448✔
1048
{                                                                       \
129,448✔
1049
  CONV;                                                                 \
129,448!
1050
  if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
129,448!
1051
}                                                                       \
21✔
1052

1053
struct EDNSOpts
1054
{
1055
  enum zFlags { DNSSECOK=32768 };
1056
  vector<pair<uint16_t, string> > d_options;
1057
  uint16_t d_packetsize{0};
1058
  uint16_t d_extFlags{0};
1059
  uint8_t d_extRCode, d_version;
1060
};
1061
//! Convenience function that fills out EDNS0 options, and returns true if there are any
1062

1063
class MOADNSParser;
1064
bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo);
1065
void reportAllTypes();
1066
ComboAddress getAddr(const DNSRecord& dr, uint16_t defport=0);
1067
void checkHostnameCorrectness(const DNSResourceRecord& rr);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc