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