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.
27 #include "dnsparser.hh"
28 #include "dnswriter.hh"
30 #include "rcpgenerator.hh"
33 #include "namespaces.hh"
35 #include "svc-records.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) 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);
49 class NAPTRRecordContent : public DNSRecordContent
52 NAPTRRecordContent(uint16_t order, uint16_t preference, string flags, string services, string regexp, DNSName replacement);
54 includeboilerplate(NAPTR)
55 template<class Convertor> void xfrRecordContent(Convertor& conv);
56 const string& getFlags() const
60 const DNSName& getReplacement() const
65 uint16_t d_order, d_preference;
66 string d_flags, d_services, d_regexp;
67 DNSName d_replacement;
71 class ARecordContent : public DNSRecordContent
74 explicit ARecordContent(const ComboAddress& ca);
75 explicit ARecordContent(uint32_t ip);
77 void doRecordCheck(const DNSRecord& dr);
78 ComboAddress getCA(int port=0) const;
79 bool operator==(const DNSRecordContent& rhs) const override
81 if(typeid(*this) != typeid(rhs))
83 return d_ip == dynamic_cast<const ARecordContent&>(rhs).d_ip;
89 class AAAARecordContent : public DNSRecordContent
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
98 if(typeid(*this) != typeid(rhs))
100 return d_ip6 == dynamic_cast<const decltype(this)>(&rhs)->d_ip6;
103 string d_ip6; // why??
106 class MXRecordContent : public DNSRecordContent
109 MXRecordContent(uint16_t preference, DNSName mxname);
111 includeboilerplate(MX)
113 uint16_t d_preference;
116 bool operator==(const DNSRecordContent& rhs) const override
118 if(typeid(*this) != typeid(rhs))
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);
126 class KXRecordContent : public DNSRecordContent
129 KXRecordContent(uint16_t preference, const DNSName& exchanger);
131 includeboilerplate(KX)
134 uint16_t d_preference;
138 class IPSECKEYRecordContent : public DNSRecordContent
141 IPSECKEYRecordContent(uint16_t preference, uint8_t gatewaytype, uint8_t algo, const DNSName& gateway, const string& publickey);
143 includeboilerplate(IPSECKEY)
150 uint8_t d_preference, d_gatewaytype, d_algorithm;
153 class DHCIDRecordContent : public DNSRecordContent
156 includeboilerplate(DHCID)
163 class SRVRecordContent : public DNSRecordContent
166 SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, DNSName target);
168 includeboilerplate(SRV)
170 uint16_t d_weight, d_port;
172 uint16_t d_preference;
175 class TSIGRecordContent : public DNSRecordContent
178 includeboilerplate(TSIG)
179 TSIGRecordContent() = default;
181 uint16_t d_origID{0};
188 // uint16_t d_macSize;
189 uint16_t d_eRcode{0};
190 // uint16_t d_otherLen
194 class TXTRecordContent : public DNSRecordContent
197 includeboilerplate(TXT)
202 #ifdef HAVE_LUA_RECORDS
203 class LUARecordContent : public DNSRecordContent
206 includeboilerplate(LUA)
207 string getCode() const;
213 class ENTRecordContent : public DNSRecordContent
216 includeboilerplate(ENT)
219 class SPFRecordContent : public DNSRecordContent
222 includeboilerplate(SPF)
223 const std::string& getText() const
233 class NSRecordContent : public DNSRecordContent
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
241 if(typeid(*this) != typeid(rhs))
243 auto rrhs =dynamic_cast<const decltype(this)>(&rhs);
244 return d_content == rrhs->d_content;
251 class PTRRecordContent : public DNSRecordContent
254 includeboilerplate(PTR)
255 explicit PTRRecordContent(const DNSName& content) : d_content(content){}
256 const DNSName& getContent() const { return d_content; }
261 class CNAMERecordContent : public DNSRecordContent
264 includeboilerplate(CNAME)
265 CNAMERecordContent(const DNSName& content) : d_content(content){}
266 DNSName getTarget() const { return d_content; }
271 #if !defined(RECURSOR)
272 class ALIASRecordContent : public DNSRecordContent
275 includeboilerplate(ALIAS)
277 [[nodiscard]] const DNSName& getContent() const
286 class DNAMERecordContent : public DNSRecordContent
289 includeboilerplate(DNAME)
290 DNAMERecordContent(const DNSName& content) : d_content(content){}
291 const DNSName& getTarget() const { return d_content; }
297 class MBRecordContent : public DNSRecordContent
300 includeboilerplate(MB)
306 class MGRecordContent : public DNSRecordContent
309 includeboilerplate(MG)
315 class MRRecordContent : public DNSRecordContent
318 includeboilerplate(MR)
324 class MINFORecordContent : public DNSRecordContent
327 includeboilerplate(MINFO)
334 class OPTRecordContent : public DNSRecordContent
337 OPTRecordContent() = default;
338 includeboilerplate(OPT)
339 void getData(vector<pair<uint16_t, string> > &opts) const;
345 class HINFORecordContent : public DNSRecordContent
348 includeboilerplate(HINFO)
351 string d_cpu, d_host;
354 class RPRecordContent : public DNSRecordContent
357 includeboilerplate(RP)
360 DNSName d_mbox, d_info;
364 class DNSKEYRecordContent : public DNSRecordContent
367 DNSKEYRecordContent();
368 includeboilerplate(DNSKEY)
369 uint16_t getTag() const;
372 uint8_t d_protocol{0};
373 uint8_t d_algorithm{0};
375 bool operator<(const DNSKEYRecordContent& rhs) const
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);
382 class CDNSKEYRecordContent : public DNSRecordContent
385 CDNSKEYRecordContent();
386 includeboilerplate(CDNSKEY)
390 uint8_t d_protocol{0};
391 uint8_t d_algorithm{0};
395 class DSRecordContent : public DNSRecordContent
399 bool operator==(const DNSRecordContent& rhs) const override
401 if(typeid(*this) != typeid(rhs))
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);
407 bool operator<(const DSRecordContent& rhs) const
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);
413 includeboilerplate(DS)
416 uint8_t d_algorithm{0}, d_digesttype{0};
420 class CDSRecordContent : public DNSRecordContent
424 includeboilerplate(CDS)
427 uint8_t d_algorithm{0}, d_digesttype{0};
431 class DLVRecordContent : public DNSRecordContent
435 includeboilerplate(DLV)
438 uint8_t d_algorithm{0}, d_digesttype{0};
443 class SSHFPRecordContent : public DNSRecordContent
446 includeboilerplate(SSHFP)
449 uint8_t d_algorithm, d_fptype;
450 string d_fingerprint;
453 class KEYRecordContent : public DNSRecordContent
456 includeboilerplate(KEY)
460 uint8_t d_protocol, d_algorithm;
461 string d_certificate;
464 class AFSDBRecordContent : public DNSRecordContent
467 includeboilerplate(AFSDB)
476 #error likely openssl/ssl2.h is included, defining CERT, avoid that or undef CERT before including dnsrecords.hh
479 class CERTRecordContent : public DNSRecordContent
482 includeboilerplate(CERT)
485 uint16_t d_type, d_tag;
486 string d_certificate;
490 class TLSARecordContent : public DNSRecordContent
493 includeboilerplate(TLSA)
496 uint8_t d_certusage, d_selector, d_matchtype;
500 class SMIMEARecordContent : public DNSRecordContent
503 includeboilerplate(SMIMEA)
506 uint8_t d_certusage, d_selector, d_matchtype;
510 class OPENPGPKEYRecordContent : public DNSRecordContent
513 includeboilerplate(OPENPGPKEY)
519 class SVCBBaseRecordContent : public DNSRecordContent
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;
539 std::set<SvcParam> d_params;
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;
547 class SVCBRecordContent : public SVCBBaseRecordContent
550 includeboilerplate(SVCB)
551 std::shared_ptr<SVCBBaseRecordContent> clone() const override;
554 class HTTPSRecordContent : public SVCBBaseRecordContent
557 includeboilerplate(HTTPS)
558 std::shared_ptr<SVCBBaseRecordContent> clone() const override;
561 class RRSIGRecordContent : public DNSRecordContent
564 RRSIGRecordContent();
565 includeboilerplate(RRSIG)
571 uint32_t d_originalttl{0}, d_sigexpire{0}, d_siginception{0};
572 uint8_t d_algorithm{0}, d_labels{0};
586 class RKEYRecordContent : public DNSRecordContent
590 includeboilerplate(RKEY)
592 uint8_t d_protocol{0}, d_algorithm{0};
596 class SOARecordContent : public DNSRecordContent
599 includeboilerplate(SOA)
600 SOARecordContent(DNSName mname, DNSName rname, const struct soatimes& st);
604 struct soatimes d_st;
607 class ZONEMDRecordContent : public DNSRecordContent
610 includeboilerplate(ZONEMD)
611 //ZONEMDRecordContent(uint32_t serial, uint8_t scheme, uint8_t hashalgo, string digest);
622 NSECBitmap(): d_bitset(nullptr)
625 NSECBitmap(const NSECBitmap& rhs): d_set(rhs.d_set)
628 d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset));
631 NSECBitmap& operator=(const NSECBitmap& rhs)
636 d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset));
641 NSECBitmap(NSECBitmap&& rhs) noexcept :
642 d_bitset(std::move(rhs.d_bitset)), d_set(std::move(rhs.d_set))
645 bool isSet(uint16_t type) const
648 return d_bitset->test(type);
650 return d_set.count(type);
652 void set(uint16_t type)
655 if (d_set.size() >= 200) {
669 return d_bitset->count();
676 void fromPacket(PacketReader& pr);
677 void toPacket(DNSPacketWriter& pw) const;
678 std::string getZoneRepresentation() const;
680 static constexpr size_t const nbTypes = 65536;
684 void migrateToBitSet()
686 d_bitset = std::make_unique<std::bitset<nbTypes>>();
687 for (const auto& type : d_set) {
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;
701 class NSECRecordContent : public DNSRecordContent
704 static void report();
705 NSECRecordContent() = default;
706 NSECRecordContent(const string& content, const DNSName& zone=DNSName());
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
716 bool isSet(uint16_t type) const
718 return d_bitmap.isSet(type);
720 void set(uint16_t type)
724 void set(const NSECBitmap& bitmap)
728 size_t numberOfTypesSet() const
730 return d_bitmap.count();
738 class NSEC3RecordContent : public DNSRecordContent
741 static void report();
742 NSEC3RecordContent() = default;
743 NSEC3RecordContent(const string& content, const DNSName& zone=DNSName());
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;
750 uint8_t d_algorithm{0}, d_flags{0};
751 uint16_t d_iterations{0};
755 uint16_t getType() const override
759 bool isSet(uint16_t type) const
761 return d_bitmap.isSet(type);
763 void set(uint16_t type)
767 void set(const NSECBitmap& bitmap)
771 size_t numberOfTypesSet() const
773 return d_bitmap.count();
775 bool isOptOut() const
784 class CSYNCRecordContent : public DNSRecordContent
787 static void report();
788 CSYNCRecordContent() = default;
789 CSYNCRecordContent(const string& content, const DNSName& zone=DNSName());
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;
796 uint16_t getType() const override
801 void set(uint16_t type)
807 uint32_t d_serial{0};
812 class NSEC3PARAMRecordContent : public DNSRecordContent
815 static void report();
816 NSEC3PARAMRecordContent() = default;
817 NSEC3PARAMRecordContent(const string& content, const DNSName& zone=DNSName());
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;
824 uint16_t getType() const override
826 return QType::NSEC3PARAM;
830 uint8_t d_algorithm{0}, d_flags{0};
831 uint16_t d_iterations{0};
836 class LOCRecordContent : public DNSRecordContent
839 static void report();
840 LOCRecordContent() = default;
841 LOCRecordContent(const string& content, const string& zone="");
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;
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
859 class NIDRecordContent : public DNSRecordContent
862 includeboilerplate(NID);
865 uint16_t d_preference;
866 NodeOrLocatorID d_node_id;
869 class L32RecordContent : public DNSRecordContent
872 includeboilerplate(L32);
875 uint16_t d_preference;
879 class L64RecordContent : public DNSRecordContent
882 includeboilerplate(L64);
885 uint16_t d_preference;
886 NodeOrLocatorID d_locator;
889 class LPRecordContent : public DNSRecordContent
892 includeboilerplate(LP);
895 uint16_t d_preference;
899 class EUI48RecordContent : public DNSRecordContent
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; }
910 // storage for the bytes
914 class EUI64RecordContent : public DNSRecordContent
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; }
925 // storage for the bytes
929 #define APL_FAMILY_IPV4 1
930 #define APL_FAMILY_IPV6 2
931 typedef struct s_APLRDataElement {
935 unsigned int d_afdlength : 7;
941 class APLRecordContent : public DNSRecordContent
944 APLRecordContent() = default;
945 includeboilerplate(APL)
947 std::vector<APLRDataElement> aplrdata;
948 APLRDataElement parseAPLElement(const string &element);
952 class TKEYRecordContent : public DNSRecordContent
956 includeboilerplate(TKEY)
958 // storage for the bytes
959 uint16_t d_othersize{0};
961 uint32_t d_inception{0};
962 uint32_t d_expiration{0};
969 uint16_t d_keysize{0};
973 class URIRecordContent : public DNSRecordContent {
975 includeboilerplate(URI)
977 uint16_t d_priority, d_weight;
981 class CAARecordContent : public DNSRecordContent {
983 includeboilerplate(CAA)
986 string d_tag, d_value;
989 #define boilerplate(RNAME) \
990 std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \
992 return std::make_shared<RNAME##RecordContent>(dr, pr); \
995 RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr) \
1001 std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const string& zonedata) \
1003 return std::make_shared<RNAME##RecordContent>(zonedata); \
1006 void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) const \
1008 this->xfrPacket(pw); \
1011 void RNAME##RecordContent::report(void) \
1013 regist(1, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \
1014 regist(254, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \
1016 void RNAME##RecordContent::unreport(void) \
1018 unregist(1, QType::RNAME); \
1019 unregist(254, QType::RNAME); \
1022 RNAME##RecordContent::RNAME##RecordContent(const string& zoneData) \
1025 RecordTextReader rtr(zoneData); \
1028 catch(RecordTextException& rte) { \
1029 throw MOADNSException("Parsing record content (try 'pdnsutil check-zone'): "+string(rte.what())); \
1033 string RNAME##RecordContent::getZoneRepresentation(bool noDot) const \
1036 RecordTextWriter rtw(ret, noDot); \
1037 const_cast<RNAME##RecordContent*>(this)->xfrPacket(rtw); \
1042 #define boilerplate_conv(RNAME, CONV) \
1043 boilerplate(RNAME) \
1044 template<class Convertor> \
1045 void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) \
1048 if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
1050 template<class Convertor> \
1051 void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) const \
1054 if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
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;
1065 //! Convenience function that fills out EDNS0 options, and returns true if there are any
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);