diff --git a/tdns/contents.cc b/tdns/contents.cc index e07e468..bc8d40b 100644 --- a/tdns/contents.cc +++ b/tdns/contents.cc @@ -6,31 +6,27 @@ void loadZones(DNSNode& zones) auto zone = zones.add({"powerdns", "org"}); auto newzone = zone->zone = new DNSNode(); // XXX ICK - newzone->rrsets[DNSType::SOA].add(SOAGenerator::make({"ns1", "powerdns", "org"}, {"admin", "powerdns", "org"}, 1)); - newzone->rrsets[DNSType::MX].add(MXGenerator::make(25, {"server1", "powerdns", "org"})); + newzone->addRRs(SOAGen::make({"ns1", "powerdns", "org"}, {"admin", "powerdns", "org"}, 1)); + newzone->rrsets[DNSType::MX].add(MXGen::make(25, {"server1", "powerdns", "org"})); - newzone->rrsets[DNSType::A].add(AGenerator::make("1.2.3.4")); - newzone->rrsets[DNSType::AAAA].add(AAAAGenerator::make("::1")); + newzone->rrsets[DNSType::A].add(AGen::make("1.2.3.4")); + newzone->rrsets[DNSType::AAAA].add(AAAAGen::make("::1")); newzone->rrsets[DNSType::AAAA].ttl= 900; - newzone->rrsets[DNSType::NS].add(NameGenerator::make({"ns1", "powerdns", "org"})); - newzone->rrsets[DNSType::TXT].add(TXTGenerator::make("Proudly served by tdns " __DATE__ " " __TIME__)); + newzone->rrsets[DNSType::NS].add(NSGen::make({"ns1", "powerdns", "org"})); + newzone->addRRs(TXTGen::make("Proudly served by tdns " __DATE__ " " __TIME__)); - newzone->add({"www"})->rrsets[DNSType::CNAME].add(NameGenerator::make({"server1","powerdns","org"})); - newzone->add({"www2"})->rrsets[DNSType::CNAME].add(NameGenerator::make({"nosuchserver1","powerdns","org"})); + newzone->add({"www"})->rrsets[DNSType::CNAME].add(CNAMEGen::make({"server1","powerdns","org"})); + newzone->add({"www2"})->rrsets[DNSType::CNAME].add(CNAMEGen::make({"nosuchserver1","powerdns","org"})); - newzone->add({"server1"})->rrsets[DNSType::A].add(AGenerator::make("213.244.168.210")); - newzone->add({"server1"})->rrsets[DNSType::AAAA].add(AAAAGenerator::make("::1")); - - newzone->add({"server2"})->rrsets[DNSType::A].add(AGenerator::make("213.244.168.210")); - newzone->add({"server2"})->rrsets[DNSType::AAAA].add(AAAAGenerator::make("::1")); + newzone->add({"server1"})->addRRs(AGen::make("213.244.168.210"), AAAAGen::make("::1")); + newzone->add({"server2"})->addRRs(AGen::make("213.244.168.210"), AAAAGen::make("::1")); - newzone->add({"*", "nl"})->rrsets[DNSType::A].add(AGenerator::make("5.6.7.8")); - newzone->add({"*", "fr"})->rrsets[DNSType::CNAME].add(NameGenerator::make({"server2", "powerdns", "org"})); + newzone->add({"*", "nl"})->rrsets[DNSType::A].add(AGen::make("5.6.7.8")); + newzone->add({"*", "fr"})->rrsets[DNSType::CNAME].add(CNAMEGen::make({"server2", "powerdns", "org"})); - newzone->add({"fra"})->rrsets[DNSType::NS].add(NameGenerator::make({"ns1","fra","powerdns","org"})); - newzone->add({"fra"})->rrsets[DNSType::NS].add(NameGenerator::make({"ns2","fra","powerdns","org"})); + newzone->add({"fra"})->addRRs(NSGen::make({"ns1","fra","powerdns","org"}), NSGen::make({"ns1","fra","powerdns","org"})); - newzone->add({"ns1", "fra"})->rrsets[DNSType::A].add(AGenerator::make("12.13.14.15")); - newzone->add({"NS2", "fra"})->rrsets[DNSType::A].add(AGenerator::make("12.13.14.16")); - newzone->add({"NS2", "fra"})->rrsets[DNSType::AAAA].add(AAAAGenerator::make("::1")); + newzone->add({"ns1", "fra"})->addRRs(AGen::make("12.13.14.15")); + newzone->add({"NS2", "fra"})->addRRs(AGen::make("12.13.14.16"), AAAAGen::make("::1")); + newzone->add({"something"})->addRRs(AAAAGen::make("::1"), AGen::make("12.13.14.15")); } diff --git a/tdns/dns-storage.cc b/tdns/dns-storage.cc index 755f30e..2cbb513 100644 --- a/tdns/dns-storage.cc +++ b/tdns/dns-storage.cc @@ -103,3 +103,8 @@ std::ostream & operator<<(std::ostream &os, const dnsname& d) os<&&a) +{ + rrsets[a->getType()].add(std::move(a)); +} diff --git a/tdns/dns-storage.hh b/tdns/dns-storage.hh index 2442737..214b3b4 100644 --- a/tdns/dns-storage.hh +++ b/tdns/dns-storage.hh @@ -56,15 +56,16 @@ std::ostream & operator<<(std::ostream &os, const dnsname& d); dnsname operator+(const dnsname& a, const dnsname& b); struct DNSMessageWriter; -struct RRGenerator +struct RRGen { virtual void toMessage(DNSMessageWriter& dpw) = 0; + virtual DNSType getType() const = 0; }; struct RRSet { - std::vector> contents; - void add(std::unique_ptr&& rr) + std::vector> contents; + void add(std::unique_ptr&& rr) { contents.emplace_back(std::move(rr)); } @@ -85,9 +86,19 @@ struct DNSNode DNSNode* add(dnsname name); std::map children; std::map rrsets; + + + void addRRs(std::unique_ptr&&a); + + template + void addRRs(std::unique_ptr&&a, Types&&... args) + { + addRRs(std::move(a)); + addRRs(std::forward(args)...); + } + void visit(std::function visitor, dnsname name) const; DNSNode* zone{0}; // if this is set, this node is a zone }; - void loadZones(DNSNode& zones); diff --git a/tdns/dns-types.cc b/tdns/dns-types.cc index db39cc3..3a7dc7d 100644 --- a/tdns/dns-types.cc +++ b/tdns/dns-types.cc @@ -1,16 +1,16 @@ #include "dns-types.hh" -std::unique_ptr AGenerator::make(const ComboAddress& ca) +std::unique_ptr AGen::make(const ComboAddress& ca) { - return std::move(std::make_unique(ca.sin4.sin_addr.s_addr)); + return std::make_unique(ca.sin4.sin_addr.s_addr); } -void AGenerator::toMessage(DNSMessageWriter& dmw) +void AGen::toMessage(DNSMessageWriter& dmw) { dmw.payload.putUInt32(d_ip); } -std::unique_ptr AAAAGenerator::make(const ComboAddress& ca) +std::unique_ptr AAAAGen::make(const ComboAddress& ca) { if(ca.sin4.sin_family != AF_INET6) throw std::runtime_error("This was not an IPv6 address in AAAA generator"); @@ -18,15 +18,15 @@ std::unique_ptr AAAAGenerator::make(const ComboAddress& ca) unsigned char ip[16]; memcpy(&ip, p, 16); - return std::move(std::make_unique(ip)); + return std::make_unique(ip); } -void AAAAGenerator::toMessage(DNSMessageWriter& dmw) +void AAAAGen::toMessage(DNSMessageWriter& dmw) { dmw.payload.putBlob(d_ip, 16); } -void SOAGenerator::toMessage(DNSMessageWriter& dmw) +void SOAGen::toMessage(DNSMessageWriter& dmw) { putName(dmw.payload, d_mname); putName(dmw.payload, d_rname); dmw.payload.putUInt32(d_serial); dmw.payload.putUInt32(d_refresh); @@ -34,18 +34,24 @@ void SOAGenerator::toMessage(DNSMessageWriter& dmw) dmw.payload.putUInt32(d_minimum); } -void NameGenerator::toMessage(DNSMessageWriter& dmw) +void CNAMEGen::toMessage(DNSMessageWriter& dmw) { putName(dmw.payload, d_name); } -void MXGenerator::toMessage(DNSMessageWriter& dmw) +void NSGen::toMessage(DNSMessageWriter& dmw) +{ + putName(dmw.payload, d_name); +} + + +void MXGen::toMessage(DNSMessageWriter& dmw) { dmw.payload.putUInt16(d_prio); putName(dmw.payload, d_name); } -void TXTGenerator::toMessage(DNSMessageWriter& dmw) +void TXTGen::toMessage(DNSMessageWriter& dmw) { // XXX should autosplit dmw.payload.putUInt8(d_txt.length()); diff --git a/tdns/dns-types.hh b/tdns/dns-types.hh index 573bfd4..3e75a02 100644 --- a/tdns/dns-types.hh +++ b/tdns/dns-types.hh @@ -4,79 +4,98 @@ #include "dnsmessages.hh" #include "comboaddress.hh" -struct AGenerator : RRGenerator +struct AGen : RRGen { - AGenerator(uint32_t ip) : d_ip(ip) {} + AGen(uint32_t ip) : d_ip(ip) {} uint32_t d_ip; - static std::unique_ptr make(const ComboAddress&); - static std::unique_ptr make(const std::string& s) + static std::unique_ptr make(const ComboAddress&); + static std::unique_ptr make(const std::string& s) { return make(ComboAddress(s)); } void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::A; } }; -struct AAAAGenerator : RRGenerator +struct AAAAGen : RRGen { - AAAAGenerator(unsigned char ip[16]) + AAAAGen(unsigned char ip[16]) { memcpy(d_ip, ip, 16); } - static std::unique_ptr make(const ComboAddress&); - static std::unique_ptr make(const std::string& s) + static std::unique_ptr make(const ComboAddress&); + static std::unique_ptr make(const std::string& s) { return make(ComboAddress(s)); } void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::AAAA; } unsigned char d_ip[16]; }; -struct SOAGenerator : RRGenerator +struct SOAGen : RRGen { - SOAGenerator(const dnsname& mname, const dnsname& rname, uint32_t serial, uint32_t minimum=3600, uint32_t refresh=10800, uint32_t retry=3600, uint32_t expire=604800) : + SOAGen(const dnsname& mname, const dnsname& rname, uint32_t serial, uint32_t minimum=3600, uint32_t refresh=10800, uint32_t retry=3600, uint32_t expire=604800) : d_mname(mname), d_rname(rname), d_serial(serial), d_minimum(minimum), d_refresh(refresh), d_retry(retry), d_expire(expire) {} template - static std::unique_ptr make(const dnsname& mname, const dnsname& rname, Targs&& ... fargs) + static std::unique_ptr make(const dnsname& mname, const dnsname& rname, Targs&& ... fargs) { - return std::make_unique(mname, rname, std::forward(fargs)...); + return std::make_unique(mname, rname, std::forward(fargs)...); } void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::SOA; } dnsname d_mname, d_rname; uint32_t d_serial, d_minimum, d_refresh, d_retry, d_expire; }; -struct NameGenerator : RRGenerator +struct CNAMEGen : RRGen { - NameGenerator(const dnsname& name) : d_name(name) {} - static std::unique_ptr make(const dnsname& mname) + CNAMEGen(const dnsname& name) : d_name(name) {} + static std::unique_ptr make(const dnsname& mname) { - return std::make_unique(mname); + return std::make_unique(mname); } void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::CNAME; } dnsname d_name; }; -struct MXGenerator : RRGenerator +struct NSGen : RRGen { - MXGenerator(uint16_t prio, const dnsname& name) : d_prio(prio), d_name(name) {} - static std::unique_ptr make(uint16_t prio, const dnsname& name) + NSGen(const dnsname& name) : d_name(name) {} + static std::unique_ptr make(const dnsname& mname) { - return std::make_unique(prio, name); + return std::make_unique(mname); } void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::NS; } + dnsname d_name; +}; + + +struct MXGen : RRGen +{ + MXGen(uint16_t prio, const dnsname& name) : d_prio(prio), d_name(name) {} + static std::unique_ptr make(uint16_t prio, const dnsname& name) + { + return std::make_unique(prio, name); + } + void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::MX; } uint16_t d_prio; dnsname d_name; }; -struct TXTGenerator : RRGenerator +struct TXTGen : RRGen { - TXTGenerator(const std::string& txt) : d_txt(txt) {} - static std::unique_ptr make(const std::string& txt) + TXTGen(const std::string& txt) : d_txt(txt) {} + static std::unique_ptr make(const std::string& txt) { - return std::make_unique(txt); + return std::make_unique(txt); } void toMessage(DNSMessageWriter& dpw) override; + DNSType getType() const override { return DNSType::TXT; } std::string d_txt; }; diff --git a/tdns/dnsmessages.cc b/tdns/dnsmessages.cc index 3ef1225..1d503f0 100644 --- a/tdns/dnsmessages.cc +++ b/tdns/dnsmessages.cc @@ -25,7 +25,7 @@ void DNSMessageReader::getQuestion(dnsname& name, DNSType& type) } -void DNSMessageWriter::putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr& content) +void DNSMessageWriter::putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr& content) { auto cursize = payload.payloadpos; try { diff --git a/tdns/dnsmessages.hh b/tdns/dnsmessages.hh index 2be6bd6..6d55342 100644 --- a/tdns/dnsmessages.hh +++ b/tdns/dnsmessages.hh @@ -19,7 +19,7 @@ struct DNSMessageWriter struct dnsheader dh=dnsheader{}; SafeArray<1500> payload; void setQuestion(const dnsname& name, DNSType type); - void putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr& rr); + void putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr& rr); std::string serialize() const; }; @@ -33,4 +33,3 @@ inline void putName(SafeArray<1500>& payload, const dnsname& name) } payload.putUInt8(0); } - diff --git a/tdns/tdns.cc b/tdns/tdns.cc index d339537..e1069ca 100644 --- a/tdns/tdns.cc +++ b/tdns/tdns.cc @@ -101,7 +101,7 @@ try vector toresolve; for(const auto& rr : rrset.contents) { response.putRR(DNSSection::Authority, zonecutname+zone, DNSType::NS, rrset.ttl, rr); - toresolve.push_back(dynamic_cast(rr.get())->d_name); + toresolve.push_back(dynamic_cast(rr.get())->d_name); } addAdditional(bestzone, zone, toresolve, response); @@ -124,7 +124,7 @@ try for(const auto& rr : rrset.contents) { response.putRR(DNSSection::Answer, lastnode+zone, t.first, rrset.ttl, rr); if(t.first == DNSType::MX) - additional.push_back(dynamic_cast(rr.get())->d_name); + additional.push_back(dynamic_cast(rr.get())->d_name); } } @@ -134,7 +134,7 @@ try for(const auto& rr : rrset.contents) { response.putRR(DNSSection::Answer, lastnode+zone, type, rrset.ttl, rr); if(type == DNSType::MX) - additional.push_back(dynamic_cast(rr.get())->d_name); + additional.push_back(dynamic_cast(rr.get())->d_name); } } @@ -144,7 +144,7 @@ try dnsname target; for(const auto& rr : rrset.contents) { response.putRR(DNSSection::Answer, lastnode+zone, DNSType::CNAME, rrset.ttl, rr); - target=dynamic_cast(rr.get())->d_name; + target=dynamic_cast(rr.get())->d_name; } if(target.makeRelative(zone)) { cout<<" Should follow CNAME to "<