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