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