]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsrecords.hh
rec: mention rust compiler in compiling docs
[thirdparty/pdns.git] / 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 #define includeboilerplate(RNAME) RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr); \
38 RNAME##RecordContent(const string& zoneData); \
39 static void report(void); \
40 static void unreport(void); \
41 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); \
42 static std::shared_ptr<DNSRecordContent> make(const string& zonedata); \
43 string getZoneRepresentation(bool noDot=false) const override; \
44 void toPacket(DNSPacketWriter& pw) const override; \
45 uint16_t getType() const override { return QType::RNAME; } \
46 template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false) const; \
47 template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false);
48
49 class NAPTRRecordContent : public DNSRecordContent
50 {
51 public:
52 NAPTRRecordContent(uint16_t order, uint16_t preference, string flags, string services, string regexp, DNSName replacement);
53
54 includeboilerplate(NAPTR)
55 template<class Convertor> void xfrRecordContent(Convertor& conv);
56 const string& getFlags() const
57 {
58 return d_flags;
59 }
60 const DNSName& getReplacement() const
61 {
62 return d_replacement;
63 }
64 private:
65 uint16_t d_order, d_preference;
66 string d_flags, d_services, d_regexp;
67 DNSName d_replacement;
68 };
69
70
71 class ARecordContent : public DNSRecordContent
72 {
73 public:
74 explicit ARecordContent(const ComboAddress& ca);
75 explicit ARecordContent(uint32_t ip);
76 includeboilerplate(A)
77 void doRecordCheck(const DNSRecord& dr);
78 ComboAddress getCA(int port=0) const;
79 bool operator==(const DNSRecordContent& rhs) const override
80 {
81 if(typeid(*this) != typeid(rhs))
82 return false;
83 return d_ip == dynamic_cast<const ARecordContent&>(rhs).d_ip;
84 }
85 private:
86 uint32_t d_ip;
87 };
88
89 class AAAARecordContent : public DNSRecordContent
90 {
91 public:
92 AAAARecordContent(std::string &val);
93 explicit AAAARecordContent(const ComboAddress& ca);
94 includeboilerplate(AAAA)
95 ComboAddress getCA(int port=0) const;
96 bool operator==(const DNSRecordContent& rhs) const override
97 {
98 if(typeid(*this) != typeid(rhs))
99 return false;
100 return d_ip6 == dynamic_cast<const decltype(this)>(&rhs)->d_ip6;
101 }
102 private:
103 string d_ip6; // why??
104 };
105
106 class MXRecordContent : public DNSRecordContent
107 {
108 public:
109 MXRecordContent(uint16_t preference, DNSName mxname);
110
111 includeboilerplate(MX)
112
113 uint16_t d_preference;
114 DNSName d_mxname;
115
116 bool operator==(const DNSRecordContent& rhs) const override
117 {
118 if(typeid(*this) != typeid(rhs))
119 return false;
120 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
121 return std::tie(d_preference, d_mxname) == std::tie(rrhs->d_preference, rrhs->d_mxname);
122 }
123
124 };
125
126 class KXRecordContent : public DNSRecordContent
127 {
128 public:
129 KXRecordContent(uint16_t preference, const DNSName& exchanger);
130
131 includeboilerplate(KX)
132
133 private:
134 uint16_t d_preference;
135 DNSName d_exchanger;
136 };
137
138 class IPSECKEYRecordContent : public DNSRecordContent
139 {
140 public:
141 IPSECKEYRecordContent(uint16_t preference, uint8_t gatewaytype, uint8_t algo, const DNSName& gateway, const string& publickey);
142
143 includeboilerplate(IPSECKEY)
144
145 private:
146 uint32_t d_ip4;
147 DNSName d_gateway;
148 string d_publickey;
149 string d_ip6;
150 uint8_t d_preference, d_gatewaytype, d_algorithm;
151 };
152
153 class DHCIDRecordContent : public DNSRecordContent
154 {
155 public:
156 includeboilerplate(DHCID)
157
158 private:
159 string d_content;
160 };
161
162
163 class SRVRecordContent : public DNSRecordContent
164 {
165 public:
166 SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, DNSName target);
167
168 includeboilerplate(SRV)
169
170 uint16_t d_weight, d_port;
171 DNSName d_target;
172 uint16_t d_preference;
173 };
174
175 class TSIGRecordContent : public DNSRecordContent
176 {
177 public:
178 includeboilerplate(TSIG)
179 TSIGRecordContent() = default;
180
181 uint16_t d_origID{0};
182 uint16_t d_fudge{0};
183
184 DNSName d_algoName;
185 string d_mac;
186 string d_otherData;
187 uint64_t d_time{0};
188 // uint16_t d_macSize;
189 uint16_t d_eRcode{0};
190 // uint16_t d_otherLen
191 };
192
193
194 class TXTRecordContent : public DNSRecordContent
195 {
196 public:
197 includeboilerplate(TXT)
198
199 string d_text;
200 };
201
202 #ifdef HAVE_LUA_RECORDS
203 class LUARecordContent : public DNSRecordContent
204 {
205 public:
206 includeboilerplate(LUA)
207 string getCode() const;
208 uint16_t d_type;
209 string d_code;
210 };
211 #endif
212
213 class ENTRecordContent : public DNSRecordContent
214 {
215 public:
216 includeboilerplate(ENT)
217 };
218
219 class SPFRecordContent : public DNSRecordContent
220 {
221 public:
222 includeboilerplate(SPF)
223 const std::string& getText() const
224 {
225 return d_text;
226 }
227
228 private:
229 string d_text;
230 };
231
232
233 class NSRecordContent : public DNSRecordContent
234 {
235 public:
236 includeboilerplate(NS)
237 explicit NSRecordContent(const DNSName& content) : d_content(content){}
238 const DNSName& getNS() const { return d_content; }
239 bool operator==(const DNSRecordContent& rhs) const override
240 {
241 if(typeid(*this) != typeid(rhs))
242 return false;
243 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
244 return d_content == rrhs->d_content;
245 }
246
247 private:
248 DNSName d_content;
249 };
250
251 class PTRRecordContent : public DNSRecordContent
252 {
253 public:
254 includeboilerplate(PTR)
255 explicit PTRRecordContent(const DNSName& content) : d_content(content){}
256 const DNSName& getContent() const { return d_content; }
257 private:
258 DNSName d_content;
259 };
260
261 class CNAMERecordContent : public DNSRecordContent
262 {
263 public:
264 includeboilerplate(CNAME)
265 CNAMERecordContent(const DNSName& content) : d_content(content){}
266 DNSName getTarget() const { return d_content; }
267 private:
268 DNSName d_content;
269 };
270
271 #if !defined(RECURSOR)
272 class ALIASRecordContent : public DNSRecordContent
273 {
274 public:
275 includeboilerplate(ALIAS)
276
277 [[nodiscard]] const DNSName& getContent() const
278 {
279 return d_content;
280 }
281 private:
282 DNSName d_content;
283 };
284 #endif
285
286 class DNAMERecordContent : public DNSRecordContent
287 {
288 public:
289 includeboilerplate(DNAME)
290 DNAMERecordContent(const DNSName& content) : d_content(content){}
291 const DNSName& getTarget() const { return d_content; }
292 private:
293 DNSName d_content;
294 };
295
296
297 class MBRecordContent : public DNSRecordContent
298 {
299 public:
300 includeboilerplate(MB)
301
302 private:
303 DNSName d_madname;
304 };
305
306 class MGRecordContent : public DNSRecordContent
307 {
308 public:
309 includeboilerplate(MG)
310
311 private:
312 DNSName d_mgmname;
313 };
314
315 class MRRecordContent : public DNSRecordContent
316 {
317 public:
318 includeboilerplate(MR)
319
320 private:
321 DNSName d_alias;
322 };
323
324 class MINFORecordContent : public DNSRecordContent
325 {
326 public:
327 includeboilerplate(MINFO)
328
329 private:
330 DNSName d_rmailbx;
331 DNSName d_emailbx;
332 };
333
334 class OPTRecordContent : public DNSRecordContent
335 {
336 public:
337 OPTRecordContent() = default;
338 includeboilerplate(OPT)
339 void getData(vector<pair<uint16_t, string> > &opts) const;
340 private:
341 string d_data;
342 };
343
344
345 class HINFORecordContent : public DNSRecordContent
346 {
347 public:
348 includeboilerplate(HINFO)
349
350 private:
351 string d_cpu, d_host;
352 };
353
354 class RPRecordContent : public DNSRecordContent
355 {
356 public:
357 includeboilerplate(RP)
358
359 private:
360 DNSName d_mbox, d_info;
361 };
362
363
364 class DNSKEYRecordContent : public DNSRecordContent
365 {
366 public:
367 DNSKEYRecordContent();
368 includeboilerplate(DNSKEY)
369 uint16_t getTag() const;
370
371 uint16_t d_flags{0};
372 uint8_t d_protocol{0};
373 uint8_t d_algorithm{0};
374 string d_key;
375 bool operator<(const DNSKEYRecordContent& rhs) const
376 {
377 return std::tie(d_flags, d_protocol, d_algorithm, d_key) <
378 std::tie(rhs.d_flags, rhs.d_protocol, rhs.d_algorithm, rhs.d_key);
379 }
380 };
381
382 class CDNSKEYRecordContent : public DNSRecordContent
383 {
384 public:
385 CDNSKEYRecordContent();
386 includeboilerplate(CDNSKEY)
387 uint16_t getTag();
388
389 uint16_t d_flags{0};
390 uint8_t d_protocol{0};
391 uint8_t d_algorithm{0};
392 string d_key;
393 };
394
395 class DSRecordContent : public DNSRecordContent
396 {
397 public:
398 DSRecordContent();
399 bool operator==(const DNSRecordContent& rhs) const override
400 {
401 if(typeid(*this) != typeid(rhs))
402 return false;
403 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
404 return std::tie(d_tag, d_algorithm, d_digesttype, d_digest) ==
405 std::tie(rrhs->d_tag, rrhs->d_algorithm, rrhs->d_digesttype, rrhs->d_digest);
406 }
407 bool operator<(const DSRecordContent& rhs) const
408 {
409 return std::tie(d_tag, d_algorithm, d_digesttype, d_digest) <
410 std::tie(rhs.d_tag, rhs.d_algorithm, rhs.d_digesttype, rhs.d_digest);
411 }
412
413 includeboilerplate(DS)
414
415 uint16_t d_tag{0};
416 uint8_t d_algorithm{0}, d_digesttype{0};
417 string d_digest;
418 };
419
420 class CDSRecordContent : public DNSRecordContent
421 {
422 public:
423 CDSRecordContent();
424 includeboilerplate(CDS)
425
426 uint16_t d_tag{0};
427 uint8_t d_algorithm{0}, d_digesttype{0};
428 string d_digest;
429 };
430
431 class DLVRecordContent : public DNSRecordContent
432 {
433 public:
434 DLVRecordContent();
435 includeboilerplate(DLV)
436
437 uint16_t d_tag{0};
438 uint8_t d_algorithm{0}, d_digesttype{0};
439 string d_digest;
440 };
441
442
443 class SSHFPRecordContent : public DNSRecordContent
444 {
445 public:
446 includeboilerplate(SSHFP)
447
448 private:
449 uint8_t d_algorithm, d_fptype;
450 string d_fingerprint;
451 };
452
453 class KEYRecordContent : public DNSRecordContent
454 {
455 public:
456 includeboilerplate(KEY)
457
458 private:
459 uint16_t d_flags;
460 uint8_t d_protocol, d_algorithm;
461 string d_certificate;
462 };
463
464 class AFSDBRecordContent : public DNSRecordContent
465 {
466 public:
467 includeboilerplate(AFSDB)
468
469 private:
470 uint16_t d_subtype;
471 DNSName d_hostname;
472 };
473
474
475 #ifdef CERT
476 #error likely openssl/ssl2.h is included, defining CERT, avoid that or undef CERT before including dnsrecords.hh
477 #endif
478
479 class CERTRecordContent : public DNSRecordContent
480 {
481 public:
482 includeboilerplate(CERT)
483
484 private:
485 uint16_t d_type, d_tag;
486 string d_certificate;
487 uint8_t d_algorithm;
488 };
489
490 class TLSARecordContent : public DNSRecordContent
491 {
492 public:
493 includeboilerplate(TLSA)
494
495 private:
496 uint8_t d_certusage, d_selector, d_matchtype;
497 string d_cert;
498 };
499
500 class SMIMEARecordContent : public DNSRecordContent
501 {
502 public:
503 includeboilerplate(SMIMEA)
504
505 private:
506 uint8_t d_certusage, d_selector, d_matchtype;
507 string d_cert;
508 };
509
510 class OPENPGPKEYRecordContent : public DNSRecordContent
511 {
512 public:
513 includeboilerplate(OPENPGPKEY)
514
515 private:
516 string d_keyring;
517 };
518
519 class SVCBBaseRecordContent : public DNSRecordContent
520 {
521 public:
522 const DNSName& getTarget() const {return d_target;}
523 uint16_t getPriority() const {return d_priority;}
524 // Returns true if a value for |key| was set to 'auto'
525 bool autoHint(const SvcParam::SvcParamKey &key) const;
526 // Sets the |addresses| to the existing hints for |key|
527 void setHints(const SvcParam::SvcParamKey &key, const std::vector<ComboAddress> &addresses);
528 // Removes the parameter for |key| from d_params
529 void removeParam(const SvcParam::SvcParamKey &key);
530 // Whether or not there are any parameter
531 bool hasParams() const;
532 // Whether or not the param of |key| exists
533 bool hasParam(const SvcParam::SvcParamKey &key) const;
534 // Get the parameter with |key|, will throw out_of_range if param isn't there
535 SvcParam getParam(const SvcParam::SvcParamKey &key) const;
536 virtual std::shared_ptr<SVCBBaseRecordContent> clone() const = 0;
537
538 protected:
539 std::set<SvcParam> d_params;
540 DNSName d_target;
541 uint16_t d_priority;
542
543 // Get the iterator to parameter with |key|, return value can be d_params::end
544 std::set<SvcParam>::const_iterator getParamIt(const SvcParam::SvcParamKey &key) const;
545 };
546
547 class SVCBRecordContent : public SVCBBaseRecordContent
548 {
549 public:
550 includeboilerplate(SVCB)
551 std::shared_ptr<SVCBBaseRecordContent> clone() const override;
552 };
553
554 class HTTPSRecordContent : public SVCBBaseRecordContent
555 {
556 public:
557 includeboilerplate(HTTPS)
558 std::shared_ptr<SVCBBaseRecordContent> clone() const override;
559 };
560
561 class RRSIGRecordContent : public DNSRecordContent
562 {
563 public:
564 RRSIGRecordContent();
565 includeboilerplate(RRSIG)
566
567 uint16_t d_type{0};
568 uint16_t d_tag{0};
569 DNSName d_signer;
570 string d_signature;
571 uint32_t d_originalttl{0}, d_sigexpire{0}, d_siginception{0};
572 uint8_t d_algorithm{0}, d_labels{0};
573 };
574
575 //namespace {
576 struct soatimes
577 {
578 uint32_t serial;
579 uint32_t refresh;
580 uint32_t retry;
581 uint32_t expire;
582 uint32_t minimum;
583 };
584 //}
585
586 class RKEYRecordContent : public DNSRecordContent
587 {
588 public:
589 RKEYRecordContent();
590 includeboilerplate(RKEY)
591 uint16_t d_flags{0};
592 uint8_t d_protocol{0}, d_algorithm{0};
593 string d_key;
594 };
595
596 class SOARecordContent : public DNSRecordContent
597 {
598 public:
599 includeboilerplate(SOA)
600 SOARecordContent(DNSName mname, DNSName rname, const struct soatimes& st);
601
602 DNSName d_mname;
603 DNSName d_rname;
604 struct soatimes d_st;
605 };
606
607 class ZONEMDRecordContent : public DNSRecordContent
608 {
609 public:
610 includeboilerplate(ZONEMD)
611 //ZONEMDRecordContent(uint32_t serial, uint8_t scheme, uint8_t hashalgo, string digest);
612
613 uint32_t d_serial;
614 uint8_t d_scheme;
615 uint8_t d_hashalgo;
616 string d_digest;
617 };
618
619 class NSECBitmap
620 {
621 public:
622 NSECBitmap(): d_bitset(nullptr)
623 {
624 }
625 NSECBitmap(const NSECBitmap& rhs): d_set(rhs.d_set)
626 {
627 if (rhs.d_bitset) {
628 d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset));
629 }
630 }
631 NSECBitmap& operator=(const NSECBitmap& rhs)
632 {
633 d_set = rhs.d_set;
634
635 if (rhs.d_bitset) {
636 d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset));
637 }
638
639 return *this;
640 }
641 NSECBitmap(NSECBitmap&& rhs) noexcept :
642 d_bitset(std::move(rhs.d_bitset)), d_set(std::move(rhs.d_set))
643 {
644 }
645 bool isSet(uint16_t type) const
646 {
647 if (d_bitset) {
648 return d_bitset->test(type);
649 }
650 return d_set.count(type);
651 }
652 void set(uint16_t type)
653 {
654 if (!d_bitset) {
655 if (d_set.size() >= 200) {
656 migrateToBitSet();
657 }
658 }
659 if (d_bitset) {
660 d_bitset->set(type);
661 }
662 else {
663 d_set.insert(type);
664 }
665 }
666 size_t count() const
667 {
668 if (d_bitset) {
669 return d_bitset->count();
670 }
671 else {
672 return d_set.size();
673 }
674 }
675
676 void fromPacket(PacketReader& pr);
677 void toPacket(DNSPacketWriter& pw) const;
678 std::string getZoneRepresentation() const;
679
680 static constexpr size_t const nbTypes = 65536;
681
682 private:
683
684 void migrateToBitSet()
685 {
686 d_bitset = std::make_unique<std::bitset<nbTypes>>();
687 for (const auto& type : d_set) {
688 d_bitset->set(type);
689 }
690 d_set.clear();
691 }
692 /* using a dynamic set is very efficient for a small number of
693 types covered (~200), but uses a lot of memory (up to 3MB)
694 when there are a lot of them.
695 So we start with the set, but allocate and switch to a bitset
696 if the number of covered types increases a lot */
697 std::unique_ptr<std::bitset<nbTypes>> d_bitset;
698 std::set<uint16_t> d_set;
699 };
700
701 class NSECRecordContent : public DNSRecordContent
702 {
703 public:
704 static void report();
705 NSECRecordContent() = default;
706 NSECRecordContent(const string& content, const DNSName& zone=DNSName());
707
708 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
709 static std::shared_ptr<DNSRecordContent> make(const string& content);
710 string getZoneRepresentation(bool noDot=false) const override;
711 void toPacket(DNSPacketWriter& pw) const override;
712 uint16_t getType() const override
713 {
714 return QType::NSEC;
715 }
716 bool isSet(uint16_t type) const
717 {
718 return d_bitmap.isSet(type);
719 }
720 void set(uint16_t type)
721 {
722 d_bitmap.set(type);
723 }
724 void set(const NSECBitmap& bitmap)
725 {
726 d_bitmap = bitmap;
727 }
728 size_t numberOfTypesSet() const
729 {
730 return d_bitmap.count();
731 }
732
733 DNSName d_next;
734 private:
735 NSECBitmap d_bitmap;
736 };
737
738 class NSEC3RecordContent : public DNSRecordContent
739 {
740 public:
741 static void report();
742 NSEC3RecordContent() = default;
743 NSEC3RecordContent(const string& content, const DNSName& zone=DNSName());
744
745 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
746 static std::shared_ptr<DNSRecordContent> make(const string& content);
747 string getZoneRepresentation(bool noDot=false) const override;
748 void toPacket(DNSPacketWriter& pw) const override;
749
750 uint8_t d_algorithm{0}, d_flags{0};
751 uint16_t d_iterations{0};
752 string d_salt;
753 string d_nexthash;
754
755 uint16_t getType() const override
756 {
757 return QType::NSEC3;
758 }
759 bool isSet(uint16_t type) const
760 {
761 return d_bitmap.isSet(type);
762 }
763 void set(uint16_t type)
764 {
765 d_bitmap.set(type);
766 }
767 void set(const NSECBitmap& bitmap)
768 {
769 d_bitmap = bitmap;
770 }
771 size_t numberOfTypesSet() const
772 {
773 return d_bitmap.count();
774 }
775 bool isOptOut() const
776 {
777 return d_flags & 1;
778 }
779
780 private:
781 NSECBitmap d_bitmap;
782 };
783
784 class CSYNCRecordContent : public DNSRecordContent
785 {
786 public:
787 static void report();
788 CSYNCRecordContent() = default;
789 CSYNCRecordContent(const string& content, const DNSName& zone=DNSName());
790
791 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
792 static std::shared_ptr<DNSRecordContent> make(const string& content);
793 string getZoneRepresentation(bool noDot=false) const override;
794 void toPacket(DNSPacketWriter& pw) const override;
795
796 uint16_t getType() const override
797 {
798 return QType::CSYNC;
799 }
800
801 void set(uint16_t type)
802 {
803 d_bitmap.set(type);
804 }
805
806 private:
807 uint32_t d_serial{0};
808 uint16_t d_flags{0};
809 NSECBitmap d_bitmap;
810 };
811
812 class NSEC3PARAMRecordContent : public DNSRecordContent
813 {
814 public:
815 static void report();
816 NSEC3PARAMRecordContent() = default;
817 NSEC3PARAMRecordContent(const string& content, const DNSName& zone=DNSName());
818
819 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
820 static std::shared_ptr<DNSRecordContent> make(const string& content);
821 string getZoneRepresentation(bool noDot=false) const override;
822 void toPacket(DNSPacketWriter& pw) const override;
823
824 uint16_t getType() const override
825 {
826 return QType::NSEC3PARAM;
827 }
828
829
830 uint8_t d_algorithm{0}, d_flags{0};
831 uint16_t d_iterations{0};
832 string d_salt;
833 };
834
835
836 class LOCRecordContent : public DNSRecordContent
837 {
838 public:
839 static void report();
840 LOCRecordContent() = default;
841 LOCRecordContent(const string& content, const string& zone="");
842
843 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
844 static std::shared_ptr<DNSRecordContent> make(const string& content);
845 string getZoneRepresentation(bool noDot=false) const override;
846 void toPacket(DNSPacketWriter& pw) const override;
847
848 uint8_t d_version{0}, d_size{0}, d_horizpre{0}, d_vertpre{0};
849 uint32_t d_latitude{0}, d_longitude{0}, d_altitude{0};
850 uint16_t getType() const override
851 {
852 return QType::LOC;
853 }
854
855 private:
856 };
857
858
859 class NIDRecordContent : public DNSRecordContent
860 {
861 public:
862 includeboilerplate(NID);
863
864 private:
865 uint16_t d_preference;
866 NodeOrLocatorID d_node_id;
867 };
868
869 class L32RecordContent : public DNSRecordContent
870 {
871 public:
872 includeboilerplate(L32);
873
874 private:
875 uint16_t d_preference;
876 uint32_t d_locator;
877 };
878
879 class L64RecordContent : public DNSRecordContent
880 {
881 public:
882 includeboilerplate(L64);
883
884 private:
885 uint16_t d_preference;
886 NodeOrLocatorID d_locator;
887 };
888
889 class LPRecordContent : public DNSRecordContent
890 {
891 public:
892 includeboilerplate(LP);
893
894 private:
895 uint16_t d_preference;
896 DNSName d_fqdn;
897 };
898
899 class EUI48RecordContent : public DNSRecordContent
900 {
901 public:
902 EUI48RecordContent() = default;
903 static void report();
904 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
905 static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
906 string getZoneRepresentation(bool noDot=false) const override;
907 void toPacket(DNSPacketWriter& pw) const override;
908 uint16_t getType() const override { return QType::EUI48; }
909 private:
910 // storage for the bytes
911 uint8_t d_eui48[6];
912 };
913
914 class EUI64RecordContent : public DNSRecordContent
915 {
916 public:
917 EUI64RecordContent() = default;
918 static void report();
919 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
920 static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
921 string getZoneRepresentation(bool noDot=false) const override;
922 void toPacket(DNSPacketWriter& pw) const override;
923 uint16_t getType() const override { return QType::EUI64; }
924 private:
925 // storage for the bytes
926 uint8_t d_eui64[8];
927 };
928
929 #define APL_FAMILY_IPV4 1
930 #define APL_FAMILY_IPV6 2
931 typedef struct s_APLRDataElement {
932 uint16_t d_family;
933 uint8_t d_prefix;
934 bool d_n : 1;
935 unsigned int d_afdlength : 7;
936 union u_d_ip {
937 uint8_t d_ip4[4];
938 uint8_t d_ip6[16];
939 } d_ip;
940 } APLRDataElement;
941 class APLRecordContent : public DNSRecordContent
942 {
943 public:
944 APLRecordContent() = default;
945 includeboilerplate(APL)
946 private:
947 std::vector<APLRDataElement> aplrdata;
948 APLRDataElement parseAPLElement(const string &element);
949 };
950
951
952 class TKEYRecordContent : public DNSRecordContent
953 {
954 public:
955 TKEYRecordContent();
956 includeboilerplate(TKEY)
957
958 // storage for the bytes
959 uint16_t d_othersize{0};
960 uint16_t d_mode{0};
961 uint32_t d_inception{0};
962 uint32_t d_expiration{0};
963
964 DNSName d_algo;
965 string d_key;
966 string d_other;
967
968 uint16_t d_error{0};
969 uint16_t d_keysize{0};
970 private:
971 };
972
973 class URIRecordContent : public DNSRecordContent {
974 public:
975 includeboilerplate(URI)
976 private:
977 uint16_t d_priority, d_weight;
978 string d_target;
979 };
980
981 class CAARecordContent : public DNSRecordContent {
982 public:
983 includeboilerplate(CAA)
984 private:
985 uint8_t d_flags;
986 string d_tag, d_value;
987 };
988
989 #define boilerplate(RNAME) \
990 std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \
991 { \
992 return std::make_shared<RNAME##RecordContent>(dr, pr); \
993 } \
994 \
995 RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr) \
996 { \
997 doRecordCheck(dr); \
998 xfrPacket(pr); \
999 } \
1000 \
1001 std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const string& zonedata) \
1002 { \
1003 return std::make_shared<RNAME##RecordContent>(zonedata); \
1004 } \
1005 \
1006 void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) const \
1007 { \
1008 this->xfrPacket(pw); \
1009 } \
1010 \
1011 void RNAME##RecordContent::report(void) \
1012 { \
1013 regist(1, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \
1014 regist(254, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \
1015 } \
1016 void RNAME##RecordContent::unreport(void) \
1017 { \
1018 unregist(1, QType::RNAME); \
1019 unregist(254, QType::RNAME); \
1020 } \
1021 \
1022 RNAME##RecordContent::RNAME##RecordContent(const string& zoneData) \
1023 { \
1024 try { \
1025 RecordTextReader rtr(zoneData); \
1026 xfrPacket(rtr); \
1027 } \
1028 catch(RecordTextException& rte) { \
1029 throw MOADNSException("Parsing record content (try 'pdnsutil check-zone'): "+string(rte.what())); \
1030 } \
1031 } \
1032 \
1033 string RNAME##RecordContent::getZoneRepresentation(bool noDot) const \
1034 { \
1035 string ret; \
1036 RecordTextWriter rtw(ret, noDot); \
1037 const_cast<RNAME##RecordContent*>(this)->xfrPacket(rtw); \
1038 return ret; \
1039 }
1040
1041
1042 #define boilerplate_conv(RNAME, CONV) \
1043 boilerplate(RNAME) \
1044 template<class Convertor> \
1045 void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) \
1046 { \
1047 CONV; \
1048 if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
1049 } \
1050 template<class Convertor> \
1051 void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) const \
1052 { \
1053 CONV; \
1054 if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
1055 } \
1056
1057 struct EDNSOpts
1058 {
1059 enum zFlags { DNSSECOK=32768 };
1060 vector<pair<uint16_t, string> > d_options;
1061 uint16_t d_packetsize{0};
1062 uint16_t d_extFlags{0};
1063 uint8_t d_extRCode, d_version;
1064 };
1065 //! Convenience function that fills out EDNS0 options, and returns true if there are any
1066
1067 class MOADNSParser;
1068 bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo);
1069 void reportBasicTypes();
1070 void reportOtherTypes();
1071 void reportAllTypes();
1072 ComboAddress getAddr(const DNSRecord& dr, uint16_t defport=0);
1073 void checkHostnameCorrectness(const DNSResourceRecord& rr);