This commit is contained in:
bert hubert 2018-04-11 12:45:26 +02:00
parent b89079028a
commit ba62c04bd2
8 changed files with 105 additions and 65 deletions

View File

@ -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"));
}

View File

@ -103,3 +103,8 @@ std::ostream & operator<<(std::ostream &os, const dnsname& d)
os<<l<<".";
return os;
}
void DNSNode::addRRs(std::unique_ptr<RRGen>&&a)
{
rrsets[a->getType()].add(std::move(a));
}

View File

@ -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<std::unique_ptr<RRGenerator>> contents;
void add(std::unique_ptr<RRGenerator>&& rr)
std::vector<std::unique_ptr<RRGen>> contents;
void add(std::unique_ptr<RRGen>&& rr)
{
contents.emplace_back(std::move(rr));
}
@ -85,9 +86,19 @@ struct DNSNode
DNSNode* add(dnsname name);
std::map<dnslabel, DNSNode, DNSLabelCompare> children;
std::map<DNSType, RRSet > rrsets;
void addRRs(std::unique_ptr<RRGen>&&a);
template<typename... Types>
void addRRs(std::unique_ptr<RRGen>&&a, Types&&... args)
{
addRRs(std::move(a));
addRRs(std::forward<Types>(args)...);
}
void visit(std::function<void(const dnsname& name, const DNSNode*)> visitor, dnsname name) const;
DNSNode* zone{0}; // if this is set, this node is a zone
};
void loadZones(DNSNode& zones);

View File

@ -1,16 +1,16 @@
#include "dns-types.hh"
std::unique_ptr<RRGenerator> AGenerator::make(const ComboAddress& ca)
std::unique_ptr<RRGen> AGen::make(const ComboAddress& ca)
{
return std::move(std::make_unique<AGenerator>(ca.sin4.sin_addr.s_addr));
return std::make_unique<AGen>(ca.sin4.sin_addr.s_addr);
}
void AGenerator::toMessage(DNSMessageWriter& dmw)
void AGen::toMessage(DNSMessageWriter& dmw)
{
dmw.payload.putUInt32(d_ip);
}
std::unique_ptr<RRGenerator> AAAAGenerator::make(const ComboAddress& ca)
std::unique_ptr<RRGen> 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<RRGenerator> AAAAGenerator::make(const ComboAddress& ca)
unsigned char ip[16];
memcpy(&ip, p, 16);
return std::move(std::make_unique<AAAAGenerator>(ip));
return std::make_unique<AAAAGen>(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());

View File

@ -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<RRGenerator> make(const ComboAddress&);
static std::unique_ptr<RRGenerator> make(const std::string& s)
static std::unique_ptr<RRGen> make(const ComboAddress&);
static std::unique_ptr<RRGen> 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<RRGenerator> make(const ComboAddress&);
static std::unique_ptr<RRGenerator> make(const std::string& s)
static std::unique_ptr<RRGen> make(const ComboAddress&);
static std::unique_ptr<RRGen> 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<typename ... Targs>
static std::unique_ptr<RRGenerator> make(const dnsname& mname, const dnsname& rname, Targs&& ... fargs)
static std::unique_ptr<RRGen> make(const dnsname& mname, const dnsname& rname, Targs&& ... fargs)
{
return std::make_unique<SOAGenerator>(mname, rname, std::forward<Targs>(fargs)...);
return std::make_unique<SOAGen>(mname, rname, std::forward<Targs>(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<RRGenerator> make(const dnsname& mname)
CNAMEGen(const dnsname& name) : d_name(name) {}
static std::unique_ptr<RRGen> make(const dnsname& mname)
{
return std::make_unique<NameGenerator>(mname);
return std::make_unique<CNAMEGen>(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<RRGenerator> make(uint16_t prio, const dnsname& name)
NSGen(const dnsname& name) : d_name(name) {}
static std::unique_ptr<RRGen> make(const dnsname& mname)
{
return std::make_unique<MXGenerator>(prio, name);
return std::make_unique<NSGen>(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<RRGen> make(uint16_t prio, const dnsname& name)
{
return std::make_unique<MXGen>(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<RRGenerator> make(const std::string& txt)
TXTGen(const std::string& txt) : d_txt(txt) {}
static std::unique_ptr<RRGen> make(const std::string& txt)
{
return std::make_unique<TXTGenerator>(txt);
return std::make_unique<TXTGen>(txt);
}
void toMessage(DNSMessageWriter& dpw) override;
DNSType getType() const override { return DNSType::TXT; }
std::string d_txt;
};

View File

@ -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<RRGenerator>& content)
void DNSMessageWriter::putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr<RRGen>& content)
{
auto cursize = payload.payloadpos;
try {

View File

@ -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<RRGenerator>& rr);
void putRR(DNSSection section, const dnsname& name, DNSType type, uint32_t ttl, const std::unique_ptr<RRGen>& rr);
std::string serialize() const;
};
@ -33,4 +33,3 @@ inline void putName(SafeArray<1500>& payload, const dnsname& name)
}
payload.putUInt8(0);
}

View File

@ -101,7 +101,7 @@ try
vector<dnsname> toresolve;
for(const auto& rr : rrset.contents) {
response.putRR(DNSSection::Authority, zonecutname+zone, DNSType::NS, rrset.ttl, rr);
toresolve.push_back(dynamic_cast<NameGenerator*>(rr.get())->d_name);
toresolve.push_back(dynamic_cast<NSGen*>(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<MXGenerator*>(rr.get())->d_name);
additional.push_back(dynamic_cast<MXGen*>(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<MXGenerator*>(rr.get())->d_name);
additional.push_back(dynamic_cast<MXGen*>(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<NameGenerator*>(rr.get())->d_name;
target=dynamic_cast<CNAMEGen*>(rr.get())->d_name;
}
if(target.makeRelative(zone)) {
cout<<" Should follow CNAME to "<<target<<" within our zone"<<endl;
@ -315,6 +315,10 @@ void tcpClientThread(ComboAddress local, ComboAddress remote, int s, const DNSNo
int main(int argc, char** argv)
try
{
cout<<sizeof(AGen)<<endl;
cout<<sizeof(MXGen)<<endl;
cout<<sizeof(RRGen)<<endl;
if(argc != 2) {
cerr<<"Syntax: tdns ipaddress:port"<<endl;
return(EXIT_FAILURE);