2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
22 #ifndef PDNS_DNSRECORDS_HH
23 #define PDNS_DNSRECORDS_HH
29 #include "dnsparser.hh"
30 #include "dnswriter.hh"
31 #include "rcpgenerator.hh"
34 #include "namespaces.hh"
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) override; \
45 uint16_t getType() const override { return QType::RNAME; } \
46 template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false);
48 class NAPTRRecordContent : public DNSRecordContent
51 NAPTRRecordContent(uint16_t order, uint16_t preference, string flags, string services, string regexp, DNSName replacement);
53 includeboilerplate(NAPTR)
54 template<class Convertor> void xfrRecordContent(Convertor& conv);
56 uint16_t d_order, d_preference;
57 string d_flags, d_services, d_regexp;
58 DNSName d_replacement;
62 class ARecordContent : public DNSRecordContent
65 explicit ARecordContent(const ComboAddress& ca);
66 explicit ARecordContent(uint32_t ip);
68 void doRecordCheck(const DNSRecord& dr);
69 ComboAddress getCA(int port=0) const;
70 bool operator==(const DNSRecordContent& rhs) const override
72 if(typeid(*this) != typeid(rhs))
74 return d_ip == dynamic_cast<const ARecordContent&>(rhs).d_ip;
80 class AAAARecordContent : public DNSRecordContent
83 AAAARecordContent(std::string &val);
84 explicit AAAARecordContent(const ComboAddress& ca);
85 includeboilerplate(AAAA)
86 ComboAddress getCA(int port=0) const;
87 bool operator==(const DNSRecordContent& rhs) const override
89 if(typeid(*this) != typeid(rhs))
91 return d_ip6 == dynamic_cast<const decltype(this)>(&rhs)->d_ip6;
94 string d_ip6; // why??
97 class MXRecordContent : public DNSRecordContent
100 MXRecordContent(uint16_t preference, const DNSName& mxname);
102 includeboilerplate(MX)
104 uint16_t d_preference;
107 bool operator==(const DNSRecordContent& rhs) const override
109 if(typeid(*this) != typeid(rhs))
111 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
112 return std::tie(d_preference, d_mxname) == std::tie(rrhs->d_preference, rrhs->d_mxname);
117 class KXRecordContent : public DNSRecordContent
120 KXRecordContent(uint16_t preference, const DNSName& exchanger);
122 includeboilerplate(KX)
125 uint16_t d_preference;
129 class IPSECKEYRecordContent : public DNSRecordContent
132 IPSECKEYRecordContent(uint16_t preference, uint8_t gatewaytype, uint8_t algo, const DNSName& gateway, const string& publickey);
134 includeboilerplate(IPSECKEY)
141 uint8_t d_preference, d_gatewaytype, d_algorithm;
144 class DHCIDRecordContent : public DNSRecordContent
147 includeboilerplate(DHCID)
154 class SRVRecordContent : public DNSRecordContent
157 SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const DNSName& target);
159 includeboilerplate(SRV)
161 uint16_t d_weight, d_port;
163 uint16_t d_preference;
166 class TSIGRecordContent : public DNSRecordContent
169 includeboilerplate(TSIG)
170 TSIGRecordContent() {}
172 uint16_t d_origID{0};
179 // uint16_t d_macSize;
180 uint16_t d_eRcode{0};
181 // uint16_t d_otherLen
185 class TXTRecordContent : public DNSRecordContent
188 includeboilerplate(TXT)
193 #ifdef HAVE_LUA_RECORDS
194 class LUARecordContent : public DNSRecordContent
197 includeboilerplate(LUA)
198 string getCode() const;
204 class ENTRecordContent : public DNSRecordContent
207 includeboilerplate(ENT)
210 class SPFRecordContent : public DNSRecordContent
213 includeboilerplate(SPF)
214 const std::string& getText() const
224 class NSRecordContent : public DNSRecordContent
227 includeboilerplate(NS)
228 explicit NSRecordContent(const DNSName& content) : d_content(content){}
229 const DNSName& getNS() const { return d_content; }
230 bool operator==(const DNSRecordContent& rhs) const override
232 if(typeid(*this) != typeid(rhs))
234 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
235 return d_content == rrhs->d_content;
242 class PTRRecordContent : public DNSRecordContent
245 includeboilerplate(PTR)
246 explicit PTRRecordContent(const DNSName& content) : d_content(content){}
247 const DNSName& getContent() const { return d_content; }
252 class CNAMERecordContent : public DNSRecordContent
255 includeboilerplate(CNAME)
256 CNAMERecordContent(const DNSName& content) : d_content(content){}
257 DNSName getTarget() const { return d_content; }
262 class ALIASRecordContent : public DNSRecordContent
265 includeboilerplate(ALIAS)
271 class DNAMERecordContent : public DNSRecordContent
274 includeboilerplate(DNAME)
275 DNAMERecordContent(const DNSName& content) : d_content(content){}
276 const DNSName& getTarget() const { return d_content; }
282 class MBRecordContent : public DNSRecordContent
285 includeboilerplate(MB)
291 class MGRecordContent : public DNSRecordContent
294 includeboilerplate(MG)
300 class MRRecordContent : public DNSRecordContent
303 includeboilerplate(MR)
309 class MINFORecordContent : public DNSRecordContent
312 includeboilerplate(MINFO)
319 class OPTRecordContent : public DNSRecordContent
323 includeboilerplate(OPT)
324 void getData(vector<pair<uint16_t, string> > &opts);
330 class HINFORecordContent : public DNSRecordContent
333 includeboilerplate(HINFO)
336 string d_cpu, d_host;
339 class RPRecordContent : public DNSRecordContent
342 includeboilerplate(RP)
345 DNSName d_mbox, d_info;
349 class DNSKEYRecordContent : public DNSRecordContent
352 DNSKEYRecordContent();
353 includeboilerplate(DNSKEY)
354 uint16_t getTag() const;
358 uint8_t d_protocol{0};
359 uint8_t d_algorithm{0};
361 bool operator<(const DNSKEYRecordContent& rhs) const
363 return tie(d_flags, d_protocol, d_algorithm, d_key) <
364 tie(rhs.d_flags, rhs.d_protocol, rhs.d_algorithm, rhs.d_key);
368 class CDNSKEYRecordContent : public DNSRecordContent
371 CDNSKEYRecordContent();
372 includeboilerplate(CDNSKEY)
376 uint8_t d_protocol{0};
377 uint8_t d_algorithm{0};
381 class DSRecordContent : public DNSRecordContent
385 bool operator==(const DNSRecordContent& rhs) const override
387 if(typeid(*this) != typeid(rhs))
389 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
390 return tie(d_tag, d_algorithm, d_digesttype, d_digest) ==
391 tie(rrhs->d_tag, rrhs->d_algorithm, rrhs->d_digesttype, rrhs->d_digest);
393 bool operator<(const DSRecordContent& rhs) const
395 return tie(d_tag, d_algorithm, d_digesttype, d_digest) <
396 tie(rhs.d_tag, rhs.d_algorithm, rhs.d_digesttype, rhs.d_digest);
399 includeboilerplate(DS)
402 uint8_t d_algorithm{0}, d_digesttype{0};
406 class CDSRecordContent : public DNSRecordContent
410 includeboilerplate(CDS)
413 uint8_t d_algorithm{0}, d_digesttype{0};
417 class DLVRecordContent : public DNSRecordContent
421 includeboilerplate(DLV)
424 uint8_t d_algorithm{0}, d_digesttype{0};
429 class SSHFPRecordContent : public DNSRecordContent
432 includeboilerplate(SSHFP)
435 uint8_t d_algorithm, d_fptype;
436 string d_fingerprint;
439 class KEYRecordContent : public DNSRecordContent
442 includeboilerplate(KEY)
446 uint8_t d_protocol, d_algorithm;
447 string d_certificate;
450 class AFSDBRecordContent : public DNSRecordContent
453 includeboilerplate(AFSDB)
461 class CERTRecordContent : public DNSRecordContent
464 includeboilerplate(CERT)
467 uint16_t d_type, d_tag;
468 string d_certificate;
472 class TLSARecordContent : public DNSRecordContent
475 includeboilerplate(TLSA)
478 uint8_t d_certusage, d_selector, d_matchtype;
482 class SMIMEARecordContent : public DNSRecordContent
485 includeboilerplate(SMIMEA)
488 uint8_t d_certusage, d_selector, d_matchtype;
492 class OPENPGPKEYRecordContent : public DNSRecordContent
495 includeboilerplate(OPENPGPKEY)
502 class RRSIGRecordContent : public DNSRecordContent
505 RRSIGRecordContent();
506 includeboilerplate(RRSIG)
512 uint32_t d_originalttl{0}, d_sigexpire{0}, d_siginception{0};
513 uint8_t d_algorithm{0}, d_labels{0};
527 class RKEYRecordContent : public DNSRecordContent
531 includeboilerplate(RKEY)
533 uint8_t d_protocol{0}, d_algorithm{0};
537 class SOARecordContent : public DNSRecordContent
540 includeboilerplate(SOA)
541 SOARecordContent(const DNSName& mname, const DNSName& rname, const struct soatimes& st);
545 struct soatimes d_st;
551 NSECBitmap(): d_bitset(nullptr)
554 NSECBitmap(const NSECBitmap& rhs): d_set(rhs.d_set)
557 d_bitset = std::unique_ptr<std::bitset<nbTypes>>(new std::bitset<nbTypes>(*(rhs.d_bitset)));
560 NSECBitmap& operator=(const NSECBitmap& rhs)
565 d_bitset = std::unique_ptr<std::bitset<nbTypes>>(new std::bitset<nbTypes>(*(rhs.d_bitset)));
570 NSECBitmap(NSECBitmap&& rhs): d_bitset(std::move(rhs.d_bitset)), d_set(std::move(rhs.d_set))
573 bool isSet(uint16_t type) const
576 return d_bitset->test(type);
578 return d_set.count(type);
580 void set(uint16_t type)
583 if (d_set.size() >= 200) {
597 return d_bitset->count();
604 void fromPacket(PacketReader& pr);
605 void toPacket(DNSPacketWriter& pw);
606 std::string getZoneRepresentation() const;
608 static constexpr size_t const nbTypes = 65536;
612 void migrateToBitSet()
614 d_bitset = std::unique_ptr<std::bitset<nbTypes>>(new std::bitset<nbTypes>());
615 for (const auto& type : d_set) {
620 /* using a dynamic set is very efficient for a small number of
621 types covered (~200), but uses a lot of memory (up to 3MB)
622 when there are a lot of them.
623 So we start with the set, but allocate and switch to a bitset
624 if the number of covered types increases a lot */
625 std::unique_ptr<std::bitset<nbTypes>> d_bitset;
626 std::set<uint16_t> d_set;
629 class NSECRecordContent : public DNSRecordContent
632 static void report(void);
635 NSECRecordContent(const string& content, const string& zone=""); //FIXME400: DNSName& zone?
637 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
638 static std::shared_ptr<DNSRecordContent> make(const string& content);
639 string getZoneRepresentation(bool noDot=false) const override;
640 void toPacket(DNSPacketWriter& pw) override;
641 uint16_t getType() const override
645 bool isSet(uint16_t type) const
647 return d_bitmap.isSet(type);
649 void set(uint16_t type)
653 void set(const NSECBitmap& bitmap)
657 size_t numberOfTypesSet() const
659 return d_bitmap.count();
667 class NSEC3RecordContent : public DNSRecordContent
670 static void report(void);
673 NSEC3RecordContent(const string& content, const string& zone=""); //FIXME400: DNSName& zone?
675 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
676 static std::shared_ptr<DNSRecordContent> make(const string& content);
677 string getZoneRepresentation(bool noDot=false) const override;
678 void toPacket(DNSPacketWriter& pw) override;
680 uint8_t d_algorithm{0}, d_flags{0};
681 uint16_t d_iterations{0};
685 uint16_t getType() const override
689 bool isSet(uint16_t type) const
691 return d_bitmap.isSet(type);
693 void set(uint16_t type)
697 void set(const NSECBitmap& bitmap)
701 size_t numberOfTypesSet() const
703 return d_bitmap.count();
711 class NSEC3PARAMRecordContent : public DNSRecordContent
714 static void report(void);
715 NSEC3PARAMRecordContent()
717 NSEC3PARAMRecordContent(const string& content, const string& zone=""); // FIXME400: DNSName& zone?
719 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
720 static std::shared_ptr<DNSRecordContent> make(const string& content);
721 string getZoneRepresentation(bool noDot=false) const override;
722 void toPacket(DNSPacketWriter& pw) override;
724 uint16_t getType() const override
726 return QType::NSEC3PARAM;
730 uint8_t d_algorithm{0}, d_flags{0};
731 uint16_t d_iterations{0};
736 class LOCRecordContent : public DNSRecordContent
739 static void report(void);
742 LOCRecordContent(const string& content, const string& zone="");
744 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
745 static std::shared_ptr<DNSRecordContent> make(const string& content);
746 string getZoneRepresentation(bool noDot=false) const override;
747 void toPacket(DNSPacketWriter& pw) override;
749 uint8_t d_version{0}, d_size{0}, d_horizpre{0}, d_vertpre{0};
750 uint32_t d_latitude{0}, d_longitude{0}, d_altitude{0};
751 uint16_t getType() const override
759 class EUI48RecordContent : public DNSRecordContent
762 EUI48RecordContent() {};
763 static void report(void);
764 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
765 static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
766 string getZoneRepresentation(bool noDot=false) const override;
767 void toPacket(DNSPacketWriter& pw) override;
768 uint16_t getType() const override { return QType::EUI48; }
770 // storage for the bytes
774 class EUI64RecordContent : public DNSRecordContent
777 EUI64RecordContent() {};
778 static void report(void);
779 static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
780 static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
781 string getZoneRepresentation(bool noDot=false) const override;
782 void toPacket(DNSPacketWriter& pw) override;
783 uint16_t getType() const override { return QType::EUI64; }
785 // storage for the bytes
789 class TKEYRecordContent : public DNSRecordContent
793 includeboilerplate(TKEY)
795 // storage for the bytes
796 uint16_t d_othersize{0};
798 uint32_t d_inception{0};
799 uint32_t d_expiration{0};
806 uint16_t d_keysize{0};
810 class URIRecordContent : public DNSRecordContent {
812 includeboilerplate(URI)
814 uint16_t d_priority, d_weight;
818 class CAARecordContent : public DNSRecordContent {
820 includeboilerplate(CAA)
823 string d_tag, d_value;
826 #define boilerplate(RNAME, RTYPE) \
827 std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \
829 return std::make_shared<RNAME##RecordContent>(dr, pr); \
832 RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr) \
838 std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const string& zonedata) \
840 return std::make_shared<RNAME##RecordContent>(zonedata); \
843 void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) \
845 this->xfrPacket(pw); \
848 void RNAME##RecordContent::report(void) \
850 regist(1, RTYPE, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \
851 regist(254, RTYPE, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \
853 void RNAME##RecordContent::unreport(void) \
855 unregist(1, RTYPE); \
856 unregist(254, RTYPE); \
859 RNAME##RecordContent::RNAME##RecordContent(const string& zoneData) \
862 RecordTextReader rtr(zoneData); \
865 catch(RecordTextException& rte) { \
866 throw MOADNSException("Parsing record content (try 'pdnsutil check-zone'): "+string(rte.what())); \
870 string RNAME##RecordContent::getZoneRepresentation(bool noDot) const \
873 RecordTextWriter rtw(ret, noDot); \
874 const_cast<RNAME##RecordContent*>(this)->xfrPacket(rtw); \
879 #define boilerplate_conv(RNAME, TYPE, CONV) \
880 boilerplate(RNAME, TYPE) \
881 template<class Convertor> \
882 void RNAME##RecordContent::xfrPacket(Convertor& conv, bool noDot) \
885 if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
890 enum zFlags { DNSSECOK=32768 };
891 vector<pair<uint16_t, string> > d_options;
892 uint16_t d_packetsize{0};
893 uint16_t d_extFlags{0};
894 uint8_t d_extRCode, d_version;
896 //! Convenience function that fills out EDNS0 options, and returns true if there are any
899 bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo);
900 DNSRecord makeOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t extFlags);
901 void reportBasicTypes();
902 void reportOtherTypes();
903 void reportAllTypes();
904 ComboAddress getAddr(const DNSRecord& dr, uint16_t defport=0);
905 void checkHostnameCorrectness(const DNSResourceRecord& rr);