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