From cc894edba608b6c59b5ffcb1a3a8c3f55b59f905 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Mon, 9 Apr 2018 17:46:31 +0200 Subject: [PATCH] superwip --- tdns/Makefile | 2 +- tdns/dns-storage.hh | 9 ++++++++- tdns/dns-types.cc | 48 +++++++++++++++++++++++++++++++++++++++++++++ tdns/dns-types.hh | 48 +++++++++++++++++++++++++++++++++++++-------- tdns/dnsmessages.cc | 6 ++++-- tdns/dnsmessages.hh | 2 +- tdns/safearray.hh | 6 ++++++ tdns/tdns.cc | 45 +++--------------------------------------- 8 files changed, 111 insertions(+), 55 deletions(-) create mode 100644 tdns/dns-types.cc diff --git a/tdns/Makefile b/tdns/Makefile index 68ade10..b8bcf7e 100644 --- a/tdns/Makefile +++ b/tdns/Makefile @@ -12,5 +12,5 @@ clean: -include *.d -tdns: tdns.o dns-storage.o dnsmessages.o ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o +tdns: tdns.o dns-types.o dns-storage.o dnsmessages.o ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o g++ -std=gnu++14 $^ -o $@ -pthread diff --git a/tdns/dns-storage.hh b/tdns/dns-storage.hh index 88190e9..8bddfe4 100644 --- a/tdns/dns-storage.hh +++ b/tdns/dns-storage.hh @@ -50,9 +50,16 @@ struct dnsname std::ostream & operator<<(std::ostream &os, const dnsname& d); dnsname operator+(const dnsname& a, const dnsname& b); +struct DNSMessageWriter; +struct RRGenerator +{ + virtual void toMessage(DNSMessageWriter& dpw) = 0; +}; + + struct RRSet { - std::vector contents; + std::vector> contents; uint32_t ttl{3600}; }; diff --git a/tdns/dns-types.cc b/tdns/dns-types.cc new file mode 100644 index 0000000..6a3054a --- /dev/null +++ b/tdns/dns-types.cc @@ -0,0 +1,48 @@ +#include "dns-types.hh" + +std::unique_ptr AGenerator::make(const ComboAddress& ca) +{ + return std::move(std::make_unique(ca.sin4.sin_addr.s_addr)); +} + +void AGenerator::toMessage(DNSMessageWriter& dmw) +{ + dmw.payload.putUInt32(d_ip); +} + + +std::unique_ptr AAAAGenerator::make(const ComboAddress& ca) +{ + if(ca.sin4.sin_family != AF_INET6) + throw std::runtime_error("This was not an IPv6 address in AAAA generator"); + auto p = (const unsigned char*)ca.sin6.sin6_addr.s6_addr; + unsigned char ip[16]; + memcpy(&ip, p, 16); + + return std::move(std::make_unique(ip)); +} + +void AAAAGenerator::toMessage(DNSMessageWriter& dmw) +{ + dmw.payload.putBlob(d_ip, 16); +} + +void SOAGenerator::toMessage(DNSMessageWriter& dmw) +{ + putName(dmw.payload, d_mname); putName(dmw.payload, d_rname); + dmw.payload.putUInt32(d_serial); dmw.payload.putUInt32(d_refresh); + dmw.payload.putUInt32(d_retry); dmw.payload.putUInt32(d_expire); + dmw.payload.putUInt32(d_minimum); +} + +#if 0 +std::string serializeMXRecord(uint16_t prio, const dnsname& mname) +{ + SafeArray<256> sa; + sa.putUInt16(prio); + putName(sa, mname); + return sa.serialize(); +} +#endif + + diff --git a/tdns/dns-types.hh b/tdns/dns-types.hh index 8e5067d..1d97b22 100644 --- a/tdns/dns-types.hh +++ b/tdns/dns-types.hh @@ -1,16 +1,48 @@ #pragma once +#include #include "dns-storage.hh" #include "dnsmessages.hh" - -struct RRGenerator -{ - virtual void toPacket(DNSMessageWriter& dpw) = 0; -}; +#include "comboaddress.hh" struct AGenerator : RRGenerator { - std::unique_ptr make(ComboAddress); - std::unique_ptr make(std::string); - void toPacket(DNSMessageWriter& dpw) override; + AGenerator(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) + { + return make(ComboAddress(s)); + } + void toMessage(DNSMessageWriter& dpw) override; +}; + +struct AAAAGenerator : RRGenerator +{ + AAAAGenerator(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) + { + return make(ComboAddress(s)); + } + void toMessage(DNSMessageWriter& dpw) override; + unsigned char d_ip[16]; +}; + +struct SOAGenerator : RRGenerator +{ + 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) : + 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(Targs&&... fargs) + { + return std::move(std::make_unique(std::forward(fargs)...)); + } + void toMessage(DNSMessageWriter& dpw) override; + dnsname d_mname, d_rname; + uint32_t d_serial, d_minimum, d_refresh, d_retry, d_expire; }; diff --git a/tdns/dnsmessages.cc b/tdns/dnsmessages.cc index 5ca5e1c..89e7c08 100644 --- a/tdns/dnsmessages.cc +++ b/tdns/dnsmessages.cc @@ -1,4 +1,5 @@ #include "dnsmessages.hh" +#include "dns-types.hh" using namespace std; @@ -24,14 +25,15 @@ void DNSMessageReader::getQuestion(dnsname& name, DNSType& type) } -void DNSMessageWriter::putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::string& content) +void DNSMessageWriter::putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr& content) { auto cursize = payload.payloadpos; try { putName(payload, name); payload.putUInt16((int)type); payload.putUInt16(1); payload.putUInt32(ttl); - payload.putUInt16(content.size()); // check for overflow! + payload.putUInt16(0); // XXXX + content->toMessage(*this); payload.putBlob(content); } catch(...) { diff --git a/tdns/dnsmessages.hh b/tdns/dnsmessages.hh index 57e951c..9531e02 100644 --- a/tdns/dnsmessages.hh +++ b/tdns/dnsmessages.hh @@ -18,7 +18,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::string& rr); + void putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr& rr); std::string serialize() const; }; diff --git a/tdns/safearray.hh b/tdns/safearray.hh index 2516c13..439ff66 100644 --- a/tdns/safearray.hh +++ b/tdns/safearray.hh @@ -55,6 +55,12 @@ struct SafeArray payloadpos += blob.size();; } + void putBlob(const unsigned char* blob, int size) + { + memcpy(&payload.at(payloadpos+size) - size, blob, size); + payloadpos += size; + } + std::string getBlob(int size) { std::string ret(&payload.at(payloadpos), &payload.at(payloadpos+size)); diff --git a/tdns/tdns.cc b/tdns/tdns.cc index a50c57e..1079960 100644 --- a/tdns/tdns.cc +++ b/tdns/tdns.cc @@ -18,8 +18,6 @@ using namespace std; - - std::string serializeDNSName(const dnsname& dn) { std::string ret; @@ -31,44 +29,6 @@ std::string serializeDNSName(const dnsname& dn) return ret; } -std::string serializeMXRecord(uint16_t prio, const dnsname& mname) -{ - SafeArray<256> sa; - sa.putUInt16(prio); - putName(sa, mname); - return sa.serialize(); -} - - -std::string serializeSOARecord(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) -{ - SafeArray<256> sa; - putName(sa, mname); putName(sa, rname); - sa.putUInt32(serial); sa.putUInt32(refresh); - sa.putUInt32(retry); sa.putUInt32(expire); - sa.putUInt32(minimum); - - return sa.serialize(); -} - -std::string serializeARecord(const std::string& src) -{ - ComboAddress ca(src); - if(ca.sin4.sin_family != AF_INET) - throw std::runtime_error("Could not convert '"+src+"' to an IPv4 address"); - auto p = (const char*)&ca.sin4.sin_addr.s_addr; - return std::string(p, p+4); -} - -std::string serializeAAAARecord(const std::string& src) -{ - ComboAddress ca(src); - if(ca.sin4.sin_family != AF_INET6) - throw std::runtime_error("Could not convert '"+src+"' to an IPv6 address"); - auto p = (const char*)ca.sin6.sin6_addr.s6_addr; - return std::string(p, p+16); -} - bool processQuestion(const DNSNode& zones, DNSMessageReader& dm, const ComboAddress& local, const ComboAddress& remote, DNSMessageWriter& response) try { @@ -345,8 +305,9 @@ void loadZones(DNSNode& zones) { auto zone = zones.add({"powerdns", "org"}); zone->zone = new DNSNode(); // XXX ICK - zone->zone->rrsets[DNSType::SOA]={{serializeSOARecord({"ns1", "powerdns", "org"}, {"admin", "powerdns", "org"}, 1)}}; - zone->zone->rrsets[DNSType::MX]={{serializeMXRecord(25, {"server1", "powerdns", "org"})}}; + SOAGenerator::make({"ns1", "powerdns", "org"}, {"admin", "powerdns", "org"}, 1); + // zone->zone->rrsets[DNSType::SOA]={{}}; + // zone->zone->rrsets[DNSType::MX]={{serializeMXRecord(25, {"server1", "powerdns", "org"})}}; zone->zone->rrsets[DNSType::A]={{serializeARecord("1.2.3.4")}, 300}; zone->zone->rrsets[DNSType::AAAA]={{serializeAAAARecord("::1"), serializeAAAARecord("2001::1"), serializeAAAARecord("2a02:a440:b085:1:beee:7bff:fe89:f0fb")}, 900};