From e325f20c95c28ce5cb63921136d855d65587dbf7 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Fri, 2 Oct 2015 08:40:05 +0200 Subject: [PATCH] here you go. It works, passes regression tests, but creates timeouts I can't explain yet. Also, forwarding is broken right now in recursor. --- pdns/lua-auth.cc | 6 +- pdns/lua-pdns.cc | 62 ++++--- pdns/lua-pdns.hh | 4 +- pdns/lua-recursor.cc | 60 ++++--- pdns/lua-recursor.hh | 12 +- pdns/lwres.cc | 19 +- pdns/lwres.hh | 6 +- pdns/misc.cc | 36 +++- pdns/misc.hh | 10 +- pdns/packethandler.cc | 13 +- pdns/pdns_recursor.cc | 34 ++-- pdns/recursor_cache.cc | 207 ++++++--------------- pdns/recursor_cache.hh | 41 +---- pdns/reczones.cc | 126 ++++++------- pdns/secpoll-recursor.cc | 4 +- pdns/slavecommunicator.cc | 6 +- pdns/speedtest.cc | 45 ++--- pdns/syncres.cc | 358 +++++++++++++++++++------------------ pdns/syncres.hh | 26 +-- pdns/tcpreceiver.cc | 10 +- pdns/test-dnsrecords_cc.cc | 1 - pdns/ws-auth.cc | 4 +- pdns/ws-recursor.cc | 16 +- 23 files changed, 498 insertions(+), 608 deletions(-) diff --git a/pdns/lua-auth.cc b/pdns/lua-auth.cc index 2f62a9296..8b51ff442 100644 --- a/pdns/lua-auth.cc +++ b/pdns/lua-auth.cc @@ -175,10 +175,10 @@ static int ldp_getZone(lua_State *L) { static int ldp_addRecords(lua_State *L) { DNSPacket *p=ldp_checkDNSPacket(L); - vector rrs; + vector rrs; popResourceRecordsTable(L, DNSName("BOGUS"), rrs); - BOOST_FOREACH(DNSResourceRecord rr, rrs) { - p->addRecord(rr); + BOOST_FOREACH(const DNSRecord& dr, rrs) { + p->addRecord(DNSResourceRecord(dr)); } return 0; } diff --git a/pdns/lua-pdns.cc b/pdns/lua-pdns.cc index 38402635e..99f77504a 100644 --- a/pdns/lua-pdns.cc +++ b/pdns/lua-pdns.cc @@ -37,6 +37,7 @@ extern "C" { #include #include "logger.hh" #include "namespaces.hh" +#include "dnsparser.hh" bool netmaskMatchTable(lua_State* lua, const std::string& ip) { @@ -82,35 +83,35 @@ static bool getFromTable(lua_State *lua, const std::string &key, uint32_t& value return ret; } -void pushResourceRecordsTable(lua_State* lua, const vector& records) +void pushResourceRecordsTable(lua_State* lua, const vector& records) { // make a table of tables lua_newtable(lua); int pos=0; - BOOST_FOREACH(const DNSResourceRecord& rr, records) + for(const auto& rr: records) { // row number, used by 'lua_settable' below lua_pushnumber(lua, ++pos); // "row" table lua_newtable(lua); - lua_pushstring(lua, rr.qname.toString().c_str()); + lua_pushstring(lua, rr.d_name.toString().c_str()); lua_setfield(lua, -2, "qname"); // pushes value at the top of the stack to the table immediately below that (-1 = top, -2 is below) - lua_pushstring(lua, rr.content.c_str()); + lua_pushstring(lua, rr.d_content->getZoneRepresentation().c_str()); lua_setfield(lua, -2, "content"); - lua_pushnumber(lua, rr.qtype.getCode()); + lua_pushnumber(lua, rr.d_type); lua_setfield(lua, -2, "qtype"); - lua_pushnumber(lua, rr.ttl); + lua_pushnumber(lua, rr.d_ttl); lua_setfield(lua, -2, "ttl"); lua_pushnumber(lua, rr.d_place); lua_setfield(lua, -2, "place"); - lua_pushnumber(lua, rr.qclass); + lua_pushnumber(lua, rr.d_class); lua_setfield(lua, -2, "qclass"); lua_settable(lua, -3); // pushes the table we just built into the master table at position pushed above @@ -164,13 +165,13 @@ int getLuaTableLength(lua_State* lua, int depth) } // expects a table at offset 2, and, importantly DOES NOT POP IT from the stack - only the contents -void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector& ret) +void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector& ret) { /* get the result */ - DNSResourceRecord rr; - rr.qname = query; - rr.d_place = DNSResourceRecord::ANSWER; - rr.ttl = 3600; + DNSRecord rr; + rr.d_name = query; + rr.d_place = DNSRecord::Answer; + rr.d_ttl = 3600; int tableLen = getLuaTableLength(lua, 2); @@ -180,31 +181,36 @@ void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector(DNSRecordContent::mastermake(rr.d_type, rr.d_class, content)); - string qname = rr.qname.toString(); + if(!getFromTable(lua, "ttl", rr.d_ttl)) + rr.d_ttl=3600; + + string qname = rr.d_name.toString(); if(!getFromTable(lua, "qname", qname)) - rr.qname = query; + rr.d_name = query; if(!getFromTable(lua, "place", tmpnum)) - rr.d_place = DNSResourceRecord::ANSWER; + rr.d_place = DNSRecord::Answer; else { - rr.d_place = (DNSResourceRecord::Place) tmpnum; - if(rr.d_place > DNSResourceRecord::ADDITIONAL) - rr.d_place = DNSResourceRecord::ADDITIONAL; + rr.d_place = (DNSRecord::Place) tmpnum; + if(rr.d_place > DNSRecord::Additional) + rr.d_place = DNSRecord::Additional; } - if(!getFromTable(lua, "qclass", tmpnum)) - rr.qclass = QClass::IN; - else { - rr.qclass = tmpnum; - } /* removes 'value'; keeps 'key' for next iteration */ lua_pop(lua, 1); // table diff --git a/pdns/lua-pdns.hh b/pdns/lua-pdns.hh index f00979231..86125d699 100644 --- a/pdns/lua-pdns.hh +++ b/pdns/lua-pdns.hh @@ -32,8 +32,8 @@ protected: // FIXME? }; // enum for policy decisions, used by both auth and recursor. Not all values supported everywhere. namespace PolicyDecision { enum returnTypes { PASS=-1, DROP=-2, TRUNCATE=-3 }; }; -void pushResourceRecordsTable(lua_State* lua, const vector& records); -void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector& ret); +void pushResourceRecordsTable(lua_State* lua, const vector& records); +void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector& ret); void pushSyslogSecurityLevelTable(lua_State *lua); int getLuaTableLength(lua_State* lua, int depth); void luaStackDump (lua_State *L); diff --git a/pdns/lua-recursor.cc b/pdns/lua-recursor.cc index 7365881f0..3c25a7f70 100644 --- a/pdns/lua-recursor.cc +++ b/pdns/lua-recursor.cc @@ -3,7 +3,7 @@ #endif #include "lua-recursor.hh" // to avoid including all of syncres.hh -int directResolve(const std::string& qname, const QType& qtype, int qclass, vector& ret); +int directResolve(const std::string& qname, const QType& qtype, int qclass, vector& ret); #if !defined(HAVE_LUA) @@ -13,28 +13,28 @@ RecursorLua::RecursorLua(const std::string &fname) // empty } -bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { return false; } -bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { return false; } -bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { return false; } -bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { return false; } -bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res) +bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res) { return false; } @@ -62,8 +62,10 @@ extern "C" { #include #include #include "logger.hh" +#include "dnsparser.hh" #include "namespaces.hh" #include "rec_channel.hh" +#include "dnsrecords.hh" static int getRegisteredNameLua(lua_State *L) { const char *name = luaL_checkstring(L, 1); @@ -79,13 +81,13 @@ RecursorLua::RecursorLua(const std::string &fname) lua_setglobal(d_lua, "getregisteredname"); } -int followCNAMERecords(vector& ret, const QType& qtype) +int followCNAMERecords(vector& ret, const QType& qtype) { - vector resolved; - string target; - BOOST_FOREACH(DNSResourceRecord& rr, ret) { - if(rr.qtype.getCode() == QType::CNAME) { - target=rr.content; + vector resolved; + string target; // XXX DNSNAME PAIN + BOOST_FOREACH(DNSRecord& rr, ret) { + if(rr.d_type == QType::CNAME) { + target=std::dynamic_pointer_cast(rr.d_content)->getTarget().toString(); break; } } @@ -97,7 +99,7 @@ int followCNAMERecords(vector& ret, const QType& qtype) int rcode=directResolve(target, qtype, 1, resolved); // 1 == class - BOOST_FOREACH(const DNSResourceRecord& rr, resolved) + BOOST_FOREACH(const DNSRecord& rr, resolved) { ret.push_back(rr); } @@ -105,28 +107,28 @@ int followCNAMERecords(vector& ret, const QType& qtype) } -int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector& ret) +int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector& ret) { int rcode=directResolve(qname, QType(QType::A), 1, ret); ComboAddress prefixAddress(prefix); - BOOST_FOREACH(DNSResourceRecord& rr, ret) + BOOST_FOREACH(DNSRecord& rr, ret) { - if(rr.qtype.getCode() == QType::A && rr.d_place==DNSResourceRecord::ANSWER) { - ComboAddress ipv4(rr.content); + if(rr.d_type == QType::A && rr.d_place==DNSRecord::Answer) { + ComboAddress ipv4(std::dynamic_pointer_cast(rr.d_content)->getCA()); uint32_t tmp; memcpy((void*)&tmp, &ipv4.sin4.sin_addr.s_addr, 4); // tmp=htonl(tmp); memcpy(((char*)&prefixAddress.sin6.sin6_addr.s6_addr)+12, &tmp, 4); - rr.content = prefixAddress.toString(); - rr.qtype = QType(QType::AAAA); + rr.d_content = std::make_shared(prefixAddress); + rr.d_type = QType::AAAA; } } return rcode; } -int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector& ret) +int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector& ret) { /* qname has a reverse ordered IPv6 address, need to extract the underlying IPv4 address from it and turn it into an IPv4 in-addr.arpa query */ @@ -146,17 +148,17 @@ int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector& ret, int& res, bool* variable) +bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { if(d_nofuncs.nxdomain) return false; @@ -164,14 +166,14 @@ bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local return passthrough("nxdomain", remote, local, query, qtype, ret, res, variable); } -bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { if(d_nofuncs.preresolve) return false; return passthrough("preresolve", remote, local, query, qtype, ret, res, variable); } -bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { if(d_nofuncs.nodata) return false; @@ -179,14 +181,14 @@ bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,c return passthrough("nodata", remote, local, query, qtype, ret, res, variable); } -bool RecursorLua::postresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) +bool RecursorLua::postresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { if(d_nofuncs.postresolve) return false; return passthrough("postresolve", remote, local, query, qtype, ret, res, variable); } -bool RecursorLua::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector& ret, int& res) +bool RecursorLua::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector& ret, int& res) { if(d_nofuncs.preoutquery) return false; @@ -226,7 +228,7 @@ bool RecursorLua::ipfilter(const ComboAddress& remote, const ComboAddress& local } -bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, +bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable) { d_variable = false; diff --git a/pdns/lua-recursor.hh b/pdns/lua-recursor.hh index a4f7e24f3..2cf4eaa4c 100644 --- a/pdns/lua-recursor.hh +++ b/pdns/lua-recursor.hh @@ -9,14 +9,14 @@ class RecursorLua : public PowerDNSLua public: explicit RecursorLua(const std::string& fname); // ~RecursorLua(); - bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); - bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); - bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); - bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); - bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector& res, int& ret); + bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); + bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); + bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); + bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector& res, int& ret, bool* variable); + bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector& res, int& ret); bool ipfilter(const ComboAddress& remote, const ComboAddress& local); private: - bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable); + bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector& ret, int& res, bool* variable); struct NoFuncs { diff --git a/pdns/lwres.cc b/pdns/lwres.cc index 08206126c..e8e6a5daa 100644 --- a/pdns/lwres.cc +++ b/pdns/lwres.cc @@ -150,7 +150,7 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d if(ret <= 0) // includes 'timeout' return ret; - lwr->d_result.clear(); + lwr->d_records.clear(); try { lwr->d_tcbit=0; MOADNSParser mdp((const char*)buf.get(), len); @@ -162,15 +162,16 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d return 1; // this is "success", the error is set in lwr->d_rcode } - if(!pdns_iequals(domain, mdp.d_qname)) { + if(domain != mdp.d_qname) { if(!mdp.d_qname.empty() && domain.toString().find((char)0) == string::npos /* ugly */) {// embedded nulls are too noisy, plus empty domains are too L<d_records = mdp.d_answers; + + for(const auto& a : mdp.d_answers) + lwr->d_records.push_back(a.first); EDNSOpts edo; if(EDNS0Level > 0 && getEDNSOpts(mdp, &edo)) { @@ -199,13 +200,3 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d return -1; } -vector& LWResult::getResult() -{ - if(d_result.empty()) { - for(auto i=d_records.cbegin(); i != d_records.cend(); ++i) { - DNSResourceRecord rr(i->first); - d_result.push_back(rr); - } - } - return d_result; -} diff --git a/pdns/lwres.hh b/pdns/lwres.hh index 82bb0050a..ec33c396c 100644 --- a/pdns/lwres.hh +++ b/pdns/lwres.hh @@ -58,16 +58,12 @@ class LWResult { public: LWResult() : d_usec(0) {} - typedef vector res_t; - res_t& getResult(); - vector> d_records; + vector d_records; int d_rcode; bool d_aabit, d_tcbit; uint32_t d_usec; bool d_haveEDNS; - - vector d_result; }; int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res); diff --git a/pdns/misc.cc b/pdns/misc.cc index 340ab1b73..065cbd6c9 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -51,7 +51,7 @@ #include #include #include "iputils.hh" - +#include "dnsparser.hh" bool g_singleThreaded; @@ -547,16 +547,42 @@ void shuffle(vector& rrs) // we don't shuffle the rest } -static bool comparePlace(DNSResourceRecord a, DNSResourceRecord b) + +// shuffle, maintaining some semblance of order +void shuffle(vector& rrs) { - return (a.d_place < b.d_place); + vector::iterator first, second; + for(first=rrs.begin();first!=rrs.end();++first) + if(first->d_place==DNSRecord::Answer && first->d_type != QType::CNAME) // CNAME must come first + break; + for(second=first;second!=rrs.end();++second) + if(second->d_place!=DNSRecord::Answer) + break; + + if(second-first>1) + random_shuffle(first,second); + + // now shuffle the additional records + for(first=second;first!=rrs.end();++first) + if(first->d_place==DNSRecord::Additional && first->d_type != QType::CNAME) // CNAME must come first + break; + for(second=first; second!=rrs.end(); ++second) + if(second->d_place!=DNSRecord::Additional) + break; + + if(second-first>1) + random_shuffle(first,second); + + // we don't shuffle the rest } // make sure rrs is sorted in d_place order to avoid surprises later // then shuffle the parts that desire shuffling -void orderAndShuffle(vector& rrs) +void orderAndShuffle(vector& rrs) { - std::stable_sort(rrs.begin(), rrs.end(), comparePlace); + std::stable_sort(rrs.begin(), rrs.end(), [](const DNSRecord&a, const DNSRecord& b) { + return a.d_place < b.d_place; + }); shuffle(rrs); } diff --git a/pdns/misc.hh b/pdns/misc.hh index acce97644..43515a5a1 100644 --- a/pdns/misc.hh +++ b/pdns/misc.hh @@ -300,8 +300,9 @@ inline void unixDie(const string &why) } string makeHexDump(const string& str); +void shuffle(vector& rrs); void shuffle(vector& rrs); -void orderAndShuffle(vector& rrs); +void orderAndShuffle(vector& rrs); void normalizeTV(struct timeval& tv); const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs); @@ -349,13 +350,6 @@ inline bool pdns_iequals(const std::string& a, const std::string& b) return true; } -// FIXME400 remove this, it's just here to move faster while we DNSName the things -inline bool pdns_iequals(const DNSName& a, const DNSName& b) __attribute__((pure)); -inline bool pdns_iequals(const DNSName& a, const DNSName& b) -{ - return a==b; -} - inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure)); inline bool pdns_iequals_ch(const char a, const char b) { diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index 873f42479..ee3f06791 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -597,7 +597,7 @@ void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const DNSName& target, do { unhashed=next; } - while( next.chopOff() && !pdns_iequals(next, closest)); + while( next.chopOff() && !(next==closest)); hashed=hashQNameWithSalt(ns3rc, unhashed); DLOG(L<<"2 hash: "<qdomain)) { + if(sd.qname == p->qdomain) { addDNSKEY(p, r, sd); addNSEC3PARAM(p, r, sd); } @@ -1191,8 +1191,7 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) if(!retargetcount) r->qdomainzone=sd.qname; - - if(pdns_iequals(sd.qname, p->qdomain)) { + if(sd.qname==p->qdomain) { if(p->qtype.getCode() == QType::DNSKEY) { if(addDNSKEY(p, r, sd)) @@ -1205,7 +1204,7 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) } } - if(p->qtype.getCode() == QType::SOA && pdns_iequals(sd.qname, p->qdomain)) { + if(p->qtype.getCode() == QType::SOA && sd.qname==p->qdomain) { rr.qname=sd.qname; rr.qtype=QType::SOA; rr.content=serializeSOAData(sd); @@ -1253,7 +1252,7 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) if((p->qtype.getCode() == QType::ANY || rr.qtype == p->qtype) && rr.auth) weDone=1; // the line below fakes 'unauth NS' for delegations for non-DNSSEC backends. - if((rr.qtype == p->qtype && !rr.auth) || (rr.qtype.getCode() == QType::NS && (!rr.auth || !pdns_iequals(sd.qname, rr.qname)))) + if((rr.qtype == p->qtype && !rr.auth) || (rr.qtype.getCode() == QType::NS && (!rr.auth || !(sd.qname==rr.qname)))) weHaveUnauth=1; if(rr.qtype.getCode() == QType::CNAME && p->qtype.getCode() != QType::CNAME) @@ -1271,7 +1270,7 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse) } /* Add in SOA if required */ - if( pdns_iequals( target, sd.qname ) ) { + if(target==sd.qname) { rr.qtype = QType::SOA; rr.content = serializeSOAData(sd); rr.qname = sd.qname; diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 23fb9af73..a0632736a 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -546,7 +546,7 @@ void startDoResolve(void *p) } ComboAddress local; listenSocketsAddresses_t::const_iterator lociter; - vector ret; + vector ret; vector packet; DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass); @@ -607,6 +607,7 @@ void startDoResolve(void *p) } // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve + if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) { try { res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret); @@ -619,11 +620,11 @@ void startDoResolve(void *p) if(t_pdl->get()) { if(res == RCode::NoError) { - vector::const_iterator i; - for(i=ret.begin(); i!=ret.end(); ++i) - if(i->qtype.getCode() == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER) + auto i=ret.cbegin(); + for(; i!= ret.cend(); ++i) + if(i->d_type == dc->d_mdp.d_qtype && i->d_place == DNSRecord::Answer) break; - if(i == ret.end()) + if(i == ret.cend()) (*t_pdl)->nodata(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer); } else if(res == RCode::NXDomain) @@ -660,23 +661,15 @@ void startDoResolve(void *p) else { pw.getHeader()->rcode=res; - if(ret.size()) { orderAndShuffle(ret); - for(vector::const_iterator i=ret.begin(); i!=ret.end(); ++i) { - pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place); - minTTL = min(minTTL, i->ttl); - if(i->qtype.getCode() == QType::A) { // blast out A record w/o doing whole dnswriter thing - uint32_t ip=0; - IpToU32(i->content, &ip); - pw.xfr32BitInt(htonl(ip)); - } else { - shared_ptr drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content)); - drc->toPacket(pw); - } + for(auto i=ret.cbegin(); i!=ret.cend(); ++i) { + pw.startRecord(i->d_name, i->d_type, i->d_ttl, i->d_class, (DNSPacketWriter::Place)i->d_place); + minTTL = min(minTTL, i->d_ttl); + i->d_content->toPacket(pw); if(pw.size() > maxanswersize) { pw.rollback(); - if(i->d_place==DNSResourceRecord::ANSWER) // only truncate if we actually omitted parts of the answer + if(i->d_place==DNSRecord::Answer) // only truncate if we actually omitted parts of the answer { pw.getHeader()->tc=1; pw.truncate(); @@ -1342,7 +1335,7 @@ static void houseKeeping(void *) if(now.tv_sec - last_rootupdate > 7200) { SyncRes sr(now); sr.setDoEDNS0(true); - vector ret; + vector ret; sr.setNoCache(); int res=-1; @@ -1719,7 +1712,7 @@ retryWithName: // we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) { if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type && - pdns_iequals(pident.domain, mthread->key.domain)) { + pident.domain == mthread->key.domain) { mthread->key.nearMisses++; } @@ -1937,7 +1930,6 @@ void parseACLs() int serviceMain(int argc, char*argv[]) { L.setName(s_programname); - L.setLoglevel((Logger::Urgency)(6)); // info and up if(!::arg()["logging-facility"].empty()) { diff --git a/pdns/recursor_cache.cc b/pdns/recursor_cache.cc index a15df95c7..0fb1a2c49 100644 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@ -4,90 +4,13 @@ #include "recursor_cache.hh" #include "misc.hh" #include - #include "dnsrecords.hh" #include "arguments.hh" #include "syncres.hh" #include "recursor_cache.hh" #include "cachecleaner.hh" - -#include "namespaces.hh" #include "namespaces.hh" - -DNSResourceRecord String2DNSRR(const DNSName& qname, const QType& qt, const string& serial, uint32_t ttd) -{ - DNSResourceRecord rr; - rr.ttl=ttd; - rr.qtype=qt; - rr.qname=qname; - - if(rr.qtype.getCode()==QType::A && serial.size()==4) { - uint32_t ip; - memcpy((char*)&ip, serial.c_str(), 4); - rr.content=U32ToIP(ntohl(ip)); - } - else if(rr.qtype.getCode()==QType::AAAA && serial.size()==16) { - ComboAddress tmp; - memset(&tmp, 0, sizeof(tmp)); - tmp.sin4.sin_family=AF_INET6; - memcpy(tmp.sin6.sin6_addr.s6_addr, serial.c_str(), 16); - rr.content=tmp.toString(); - } - else if(rr.qtype.getCode()==QType::CNAME || rr.qtype.getCode()==QType::NS || rr.qtype.getCode()==QType::PTR) { - unsigned int frompos=0; - unsigned char labellen; - - while((labellen=serial.at(frompos++))) { - if((labellen & 0xc0) == 0xc0) { - string encoded=qname.toDNSString(); - uint16_t offset=256*(labellen & ~0xc0) + (unsigned int)serial.at(frompos++) - sizeof(dnsheader)-5; - - simpleExpandTo(encoded, offset, rr.content); - // cerr<<"Oops, fallback, content so far: '"< regen=DNSRecordContent::unserialize(qname, qt.getCode(), serial); - rr.content=regen->getZoneRepresentation(); - } - rr.content.reserve(0); - // rr.qname.reserve(0); - return rr; -} - -// returns the RDATA for rr - might be compressed! -string DNSRR2String(const DNSResourceRecord& rr) -{ - uint16_t type=rr.qtype.getCode(); - - if(type==QType::A) { - uint32_t ip; - IpToU32(rr.content, &ip); - return string((char*)&ip, 4); - } - else if(type==QType::AAAA) { - ComboAddress ca(rr.content); - return string((char*)&ca.sin6.sin6_addr.s6_addr, 16); - } - else if(type==QType::NS || type==QType::CNAME) - return simpleCompress(rr.content, rr.qname.toString()); - else { - string ret; - shared_ptr drc(DNSRecordContent::mastermake(type, 1, rr.content)); - ret=drc->serialize(rr.qname); - // cerr<<"stored '"<d_qname.toString().length(); - for(vector::const_iterator j=i->d_records.begin(); j!= i->d_records.end(); ++j) - ret+=j->size(); + for(auto j=i->d_records.begin(); j!= i->d_records.end(); ++j) + ret+= sizeof(*j); // XXX WRONG we don't know the stored size! j->size(); } return ret; } -int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set* res, vector>* signatures) +int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, vector* res, vector>* signatures) { unsigned int ttd=0; - // cerr<<"looking up "<< qname+"|"+qt.getName()<<"\n"; + // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n"; - if(!d_cachecachevalid || !pdns_iequals(d_cachedqname, qname)) { + if(!d_cachecachevalid || d_cachedqname!= qname) { // cerr<<"had cache cache miss"<clear(); if(d_cachecache.first!=d_cachecache.second) { for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i) - if(i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY || - (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) ) + if(i->d_ttd > now && (i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY || + (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) ) ) ) { - for(vector::const_iterator k=i->d_records.begin(); k != i->d_records.end(); ++k) { - if(k->d_ttd < 1000000000 || k->d_ttd > (uint32_t) now) { // FIXME what does the 100000000 number mean? - ttd=k->d_ttd; - if(res) { - DNSResourceRecord rr=String2DNSRR(qname, QType(i->d_qtype), k->d_string, ttd); - res->insert(rr); - } - } - } + + ttd = i->d_ttd; + for(auto k=i->d_records.begin(); k != i->d_records.end(); ++k) { + if(res) { + DNSRecord dr; + dr.d_name = qname; + dr.d_type = i->d_qtype; + dr.d_class = 1; + dr.d_content = *k; + dr.d_ttl = i->d_ttd; + dr.d_place = DNSRecord::Answer; + res->push_back(dr); + } + } + if(signatures) // if you do an ANY lookup you are hosed XXXX *signatures=i->d_signatures; if(res) { @@ -157,7 +86,7 @@ int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set -bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set& content, const CacheEntry& stored) +bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const vector& content, const CacheEntry& stored) { if(!stored.d_auth) { //~ cerr<<"feel free to scribble non-auth data!"<d_ttd > content.begin()->ttl) { + if(stored.d_ttd > content.begin()->d_ttl) { //~ cerr<<"attempt to LOWER TTL - fine by us"<& content, const vector>& signatures, bool auth) +void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt, const vector& content, const vector>& signatures, bool auth) { d_cachecachevalid=false; boost::tuple key=boost::make_tuple(qname, qt.getCode()); cache_t::iterator stored=d_cache.find(key); uint32_t maxTTD=UINT_MAX; - bool isNew=false; if(stored == d_cache.end()) { - stored=d_cache.insert(CacheEntry(key,vector(), auth)).first; - isNew=true; + stored=d_cache.insert(CacheEntry(key,CacheEntry::records_t(), auth)).first; } - pair::iterator, vector::iterator> range; - - StoredRecord dr; + CacheEntry ce=*stored; + ce.d_qtype=qt.getCode(); ce.d_signatures=signatures; - //~ cerr<<"asked to store "<< qname+"|"+qt.getName()<<" -> '"<content<<"', isnew="< '"<d_content->getZoneRepresentation()<<"', auth="<::iterator j; - for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) - if((time_t)j->d_ttd > now) - break; - if(j != ce.d_records.end()) { // we still have valid data, ignore unauth data + if(ce.d_ttd > now) { // we still have valid data, ignore unauth data // cerr<<"\tStill hold valid auth data, and the new data is unauth, return\n"; return; } @@ -227,44 +144,34 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt } // limit TTL of auth->auth NSset update if needed, except for root - if(ce.d_auth && auth && qt.getCode()==QType::NS && !(qname == DNSName("."))) { + if(ce.d_auth && auth && qt.getCode()==QType::NS && !(qname == DNSName())) { // cerr<<"\tLimiting TTL of auth->auth NS set replace"<::iterator j; - for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) { - maxTTD=min(maxTTD, j->d_ttd); - } + maxTTD = ce.d_ttd; } // make sure that we CAN refresh the root - if(auth && ((qname == DNSName(".")) || !attemptToRefreshNSTTL(qt, content, ce) ) ) { + if(auth && ((qname == DNSName()) || !attemptToRefreshNSTTL(qt, content, ce) ) ) { // cerr<<"\tGot auth data, and it was not refresh attempt of an unchanged NS set, nuking storage"<::const_iterator i=content.begin(); i != content.end(); ++i) { + for(auto i=content.cbegin(); i != content.cend(); ++i) { // cerr<<"To store: "<content<<" with ttl/ttd "<ttl<ttl); - dr.d_string=DNSRR2String(*i); + ce.d_ttd=min(maxTTD, i->d_ttl); // XXX this does weird things if TTLs differ in the set + ce.d_records.push_back(i->d_content); - if(isNew) - ce.d_records.push_back(dr); + /* else { range=equal_range(ce.d_records.begin(), ce.d_records.end(), dr); if(range.first != range.second) { // cerr<<"\t\tMay need to modify TTL of stored record\n"; for(vector::iterator j=range.first ; j!=range.second; ++j) { - /* see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html */ + // see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) { // don't allow auth servers to *raise* TTL of an NS record //~ cerr<<"\t\tNot doing so, trying to raise TTL NS\n"; continue; @@ -282,18 +189,11 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt //~ cerr<<"\t\tThere was no exact copy of this record, so adding & sorting\n"; ce.d_records.push_back(dr); sort(ce.d_records.begin(), ce.d_records.end()); - } + } } + */ } - if(isNew) { - // cerr<<"\tSorting (because of isNew)\n"; - sort(ce.d_records.begin(), ce.d_records.end()); - } - - if(ce.d_records.capacity() != ce.d_records.size()) - vector(ce.d_records).swap(ce.d_records); - d_cache.replace(stored, ce); } @@ -324,14 +224,8 @@ bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, uint16_t qtyp CacheEntry ce = *iter; - if(ce.d_records.size()==1) { - maxTTD=ce.d_records.begin()->d_ttd; - } - else { // find the LATEST ttd - for(vector::const_iterator i=ce.d_records.begin(); i != ce.d_records.end(); ++i) - maxTTD=max(maxTTD, i->d_ttd); - } + maxTTD=ce.d_ttd; int32_t maxTTL = maxTTD - now; if(maxTTL < 0) @@ -342,10 +236,10 @@ bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, uint16_t qtyp uint32_t newTTD = now + newTTL; - for(vector::iterator j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) { - if(j->d_ttd>newTTD) // do never renew expired or older TTLs - j->d_ttd = newTTD; - } + + if(ce.d_ttd > newTTD) // do never renew expired or older TTLs + ce.d_ttd = newTTD; + d_cache.replace(iter, ce); return true; @@ -389,11 +283,10 @@ uint64_t MemRecursorCache::doDump(int fd) uint64_t count=0; time_t now=time(0); for(sequence_t::const_iterator i=sidx.begin(); i != sidx.end(); ++i) { - for(vector::const_iterator j=i->d_records.begin(); j != i->d_records.end(); ++j) { + for(auto j=i->d_records.cbegin(); j != i->d_records.cend(); ++j) { count++; try { - DNSResourceRecord rr=String2DNSRR(i->d_qname, QType(i->d_qtype), j->d_string, j->d_ttd - now); - fprintf(fp, "%s %d IN %s %s\n", rr.qname.toString().c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str()); + fprintf(fp, "%s %d IN %s %s\n", i->d_qname.toString().c_str(), (int32_t)(i->d_ttd - now), DNSRecordContent::NumberToType(i->d_qtype).c_str(), (*j)->getZoneRepresentation().c_str()); } catch(...) { fprintf(fp, "; error printing '%s'\n", i->d_qname.toString().c_str()); diff --git a/pdns/recursor_cache.hh b/pdns/recursor_cache.hh index 4e21bac02..1c643d084 100644 --- a/pdns/recursor_cache.hh +++ b/pdns/recursor_cache.hh @@ -32,10 +32,9 @@ public: } unsigned int size(); unsigned int bytes(); - int get(time_t, const DNSName &qname, const QType& qt, set* res, vector>* signatures=0); + int get(time_t, const DNSName &qname, const QType& qt, vector* res, vector>* signatures=0); - int getDirect(time_t now, const char* qname, const QType& qt, uint32_t ttd[10], char* data[10], uint16_t len[10]); - void replace(time_t, const DNSName &qname, const QType& qt, const set& content, const vector>& signatures, bool auth); + void replace(time_t, const DNSName &qname, const QType& qt, const vector& content, const vector>& signatures, bool auth); void doPrune(void); void doSlash(int perc); uint64_t doDump(int fd); @@ -46,46 +45,25 @@ public: uint64_t cacheHits, cacheMisses; private: - struct StoredRecord - { - mutable uint32_t d_ttd; - string d_string; - - bool operator<(const StoredRecord& rhs) const - { - return d_string < rhs.d_string; - } - - unsigned int size() const - { - return sizeof(*this) + d_string.size(); - } - - }; struct CacheEntry { - CacheEntry(const boost::tuple& key, const vector& records, bool auth) : - d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records) + CacheEntry(const boost::tuple& key, const vector>& records, bool auth) : + d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records), d_ttd(0) {} - typedef vector records_t; + typedef vector> records_t; vector> d_signatures; uint32_t getTTD() const { - if(d_records.size()==1) - return d_records.begin()->d_ttd; - - uint32_t earliest=std::numeric_limits::max(); - for(records_t::const_iterator i=d_records.begin(); i != d_records.end(); ++i) - earliest=min(earliest, i->d_ttd); - return earliest; + return d_ttd; } DNSName d_qname; uint16_t d_qtype; bool d_auth; records_t d_records; + uint32_t d_ttd; }; typedef multi_index_container< @@ -107,9 +85,6 @@ private: pair d_cachecache; DNSName d_cachedqname; bool d_cachecachevalid; - bool attemptToRefreshNSTTL(const QType& qt, const set& content, const CacheEntry& stored); + bool attemptToRefreshNSTTL(const QType& qt, const vector& content, const CacheEntry& stored); }; -string DNSRR2String(const DNSResourceRecord& rr); -DNSResourceRecord String2DNSRR(const DNSName& qname, const QType& qt, const string& serial, uint32_t ttd); - #endif diff --git a/pdns/reczones.cc b/pdns/reczones.cc index 949a50541..08eec27c9 100644 --- a/pdns/reczones.cc +++ b/pdns/reczones.cc @@ -36,7 +36,7 @@ extern char** g_argv; void primeHints(void) { // prime root cache - setnsset; + vector nsset; if(!t_RC) t_RC = new MemRecursorCache(); @@ -50,31 +50,31 @@ void primeHints(void) "2001:503:c27::2:30", "2001:7fd::1", "2001:500:3::42", "2001:dc3::35" }; - DNSResourceRecord arr, aaaarr, nsrr; - arr.qtype=QType::A; - aaaarr.qtype=QType::AAAA; - nsrr.qtype=QType::NS; - arr.ttl=aaaarr.ttl=nsrr.ttl=time(0)+3600000; + DNSRecord arr, aaaarr, nsrr; + arr.d_type=QType::A; + aaaarr.d_type=QType::AAAA; + nsrr.d_type=QType::NS; + arr.d_ttl=aaaarr.d_ttl=nsrr.d_ttl=time(0)+3600000; for(char c='a';c<='m';++c) { static char templ[40]; strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1); *templ=c; - aaaarr.qname=arr.qname=DNSName(templ); - nsrr.content=templ; - arr.content=ips[c-'a']; - set aset; - aset.insert(arr); + aaaarr.d_name=arr.d_name=DNSName(templ); + nsrr.d_content=std::make_shared(DNSName(templ)); + arr.d_content=std::make_shared(ComboAddress(ips[c-'a'])); + vector aset; + aset.push_back(arr); t_RC->replace(time(0), DNSName(templ), QType(QType::A), aset, vector>(), true); // auth, nuke it all if (ip6s[c-'a'] != NULL) { - aaaarr.content=ip6s[c-'a']; + aaaarr.d_content=std::make_shared(ComboAddress(ip6s[c-'a'])); - set aaaaset; - aaaaset.insert(aaaarr); + vector aaaaset; + aaaaset.push_back(aaaarr); t_RC->replace(time(0), DNSName(templ), QType(QType::AAAA), aaaaset, vector>(), true); } - nsset.insert(nsrr); + nsset.push_back(nsrr); } } else { @@ -84,16 +84,16 @@ void primeHints(void) while(zpt.get(rr)) { rr.ttl+=time(0); if(rr.qtype.getCode()==QType::A) { - set aset; - aset.insert(rr); + vector aset; + aset.push_back(DNSRecord(rr)); t_RC->replace(time(0), rr.qname, QType(QType::A), aset, vector>(), true); // auth, etc see above } else if(rr.qtype.getCode()==QType::AAAA) { - set aaaaset; - aaaaset.insert(rr); + vector aaaaset; + aaaaset.push_back(DNSRecord(rr)); t_RC->replace(time(0), rr.qname, QType(QType::AAAA), aaaaset, vector>(), true); } else if(rr.qtype.getCode()==QType::NS) { rr.content=toLower(rr.content); - nsset.insert(rr); + nsset.push_back(DNSRecord(rr)); } } } @@ -105,30 +105,31 @@ static void makeNameToIPZone(SyncRes::domainmap_t* newMap, const DNSName& hostna SyncRes::AuthDomain ad; ad.d_rdForward=false; - DNSResourceRecord rr; - rr.qname=hostname; - rr.d_place=DNSResourceRecord::ANSWER; - rr.ttl=86400; - rr.qtype=QType::SOA; - rr.content="localhost. root 1 604800 86400 2419200 604800"; + DNSRecord dr; + dr.d_name=hostname; + dr.d_place=DNSRecord::Answer; + dr.d_ttl=86400; + dr.d_type=QType::SOA; + dr.d_class = 1; + dr.d_content = std::shared_ptr(DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800")); - ad.d_records.insert(rr); + ad.d_records.insert(dr); - rr.qtype=QType::NS; - rr.content="localhost."; + dr.d_type=QType::NS; + dr.d_content=std::make_shared("localhost."); - ad.d_records.insert(rr); + ad.d_records.insert(dr); - rr.qtype=QType::A; - rr.content=ip; - ad.d_records.insert(rr); + dr.d_type=QType::A; + dr.d_content= std::shared_ptr(DNSRecordContent::mastermake(QType::A, 1, ip)); + ad.d_records.insert(dr); - if(newMap->count(rr.qname)) { - L<count(dr.d_name)) { + L< SyncRes::AuthDomain ad; ad.d_rdForward=false; - DNSResourceRecord rr; + DNSRecord dr; for(int n=ipparts.size()-1; n>=0 ; --n) { - rr.qname.appendRawLabel(ipparts[n]); + dr.d_name.appendRawLabel(ipparts[n]); } - rr.qname.appendRawLabel("in-addr"); - rr.qname.appendRawLabel("arpa"); - - rr.d_place=DNSResourceRecord::ANSWER; - rr.ttl=86400; - rr.qtype=QType::SOA; - rr.content="localhost. root. 1 604800 86400 2419200 604800"; + dr.d_name.appendRawLabel("in-addr"); + dr.d_name.appendRawLabel("arpa"); + dr.d_class = 1; + dr.d_place=DNSRecord::Answer; + dr.d_ttl=86400; + dr.d_type=QType::SOA; + dr.d_content=std::shared_ptr(DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800")); - ad.d_records.insert(rr); + ad.d_records.insert(dr); - rr.qtype=QType::NS; - rr.content="localhost."; + dr.d_type=QType::NS; + dr.d_content=std::make_shared(DNSName("localhost.")); - ad.d_records.insert(rr); - rr.qtype=QType::PTR; + ad.d_records.insert(dr); + dr.d_type=QType::PTR; if(ipparts.size()==4) // otherwise this is a partial zone for(unsigned int n=1; n < parts.size(); ++n) { - rr.content=DNSName(parts[n]).toString(); - ad.d_records.insert(rr); + dr.d_content=std::shared_ptr(DNSRecordContent::mastermake(QType::PTR, 1, DNSName(parts[n]).toString())); // XXX FIXME DNSNAME PAIN CAN THIS BE RIGHT? + ad.d_records.insert(dr); } - if(newMap->count(rr.qname)) { - L<count(dr.d_name)) { + L<domainmap->begin(); i != t_sstorage->domainmap->end(); ++i) { for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j) - broadcastAccFunction(boost::bind(pleaseWipeCache, j->qname)); + broadcastAccFunction(boost::bind(pleaseWipeCache, j->d_name)); } string configname=::arg()["config-dir"]+"/recursor.conf"; @@ -291,7 +292,7 @@ string reloadAuthAndForwards() // purge again - new zones need to blank out the cache for(SyncRes::domainmap_t::const_iterator i = newDomainMap->begin(); i != newDomainMap->end(); ++i) { for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j) - broadcastAccFunction(boost::bind(pleaseWipeCache, j->qname)); + broadcastAccFunction(boost::bind(pleaseWipeCache, j->d_name)); } // this is pretty blunt @@ -336,10 +337,11 @@ SyncRes::domainmap_t* parseAuthAndForwards() L< ret; + vector ret; string version = "recursor-" +string(PACKAGEVERSION); string qstring(version.substr(0, 63)+ ".security-status."+::arg()["security-poll-suffix"]); @@ -38,7 +38,7 @@ void doSecPoll(time_t* last_secpoll) DNSName query(qstring); int res=sr.beginResolve(query, QType(QType::TXT), 1, ret); if(!res && !ret.empty()) { - string content=ret.begin()->content; + string content=ret.begin()->d_content->getZoneRepresentation(); if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') { content=content.substr(1, content.length()-2); } diff --git a/pdns/slavecommunicator.cc b/pdns/slavecommunicator.cc index 3d0bf5c51..e7327bf6a 100644 --- a/pdns/slavecommunicator.cc +++ b/pdns/slavecommunicator.cc @@ -190,7 +190,7 @@ void CommunicatorClass::suck(const DNSName &domain,const string &remote) } else if (optOutFlag != (ns3rc.d_flags & 1)) throw PDNSException("Zones with a mixture of Opt-Out NSEC3 RRs and non-Opt-Out NSEC3 RRs are not supported."); optOutFlag = ns3rc.d_flags & 1; - if (ns3rc.d_set.count(QType::NS) && !pdns_iequals(rr.qname, domain)) + if (ns3rc.d_set.count(QType::NS) && !(rr.qname==domain)) secured.insert(DNSName(toLower(makeRelative(rr.qname.toString(), domain.toString())))); // XXX DNSName pain continue; } @@ -207,7 +207,7 @@ void CommunicatorClass::suck(const DNSName &domain,const string &remote) break; } case QType::NS: { - if(!pdns_iequals(rr.qname, domain)) + if(rr.qname!=domain) nsset.insert(rr.qname); break; } @@ -318,7 +318,7 @@ void CommunicatorClass::suck(const DNSName &domain,const string &remote) if(nsset.count(shorter) && rr.qtype.getCode() != QType::DS) rr.auth=false; - if (pdns_iequals(shorter, domain)) // stop at apex + if (shorter==domain) // stop at apex break; }while(shorter.chopOff()); diff --git a/pdns/speedtest.cc b/pdns/speedtest.cc index 2f0c7c788..9b0c31396 100644 --- a/pdns/speedtest.cc +++ b/pdns/speedtest.cc @@ -58,9 +58,9 @@ struct ARecordTest void operator()() const { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A); for(int records = 0; records < d_records; records++) { - pw.startRecord("outpost.ds9a.nl", QType::A); + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::A); ARecordContent arc("1.2.3.4"); arc.toPacket(pw); } @@ -226,9 +226,9 @@ struct A2RecordTest void operator()() const { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A); ARecordContent arc("1.2.3.4"); - string name("outpost.ds9a.nl"); + DNSName name("outpost.ds9a.nl"); for(int records = 0; records < d_records; records++) { pw.startRecord(name, QType::A); @@ -252,9 +252,9 @@ struct TXTRecordTest void operator()() const { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::TXT); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::TXT); for(int records = 0; records < d_records; records++) { - pw.startRecord("outpost.ds9a.nl", QType::TXT); + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::TXT); TXTRecordContent arc("\"een leuk verhaaltje in een TXT\""); arc.toPacket(pw); } @@ -278,9 +278,9 @@ struct GenericRecordTest void operator()() const { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", d_type); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), d_type); for(int records = 0; records < d_records; records++) { - pw.startRecord("outpost.ds9a.nl", d_type); + pw.startRecord(DNSName("outpost.ds9a.nl"), d_type); DNSRecordContent*drc = DNSRecordContent::mastermake(d_type, 1, d_content); drc->toPacket(pw); @@ -306,9 +306,9 @@ struct AAAARecordTest void operator()() const { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::AAAA); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::AAAA); for(int records = 0; records < d_records; records++) { - pw.startRecord("outpost.ds9a.nl", QType::AAAA); + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::AAAA); DNSRecordContent*drc = DNSRecordContent::mastermake(QType::AAAA, 1, "fe80::21d:92ff:fe6d:8441"); drc->toPacket(pw); delete drc; @@ -330,10 +330,10 @@ struct SOARecordTest void operator()() const { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA); for(int records = 0; records < d_records; records++) { - pw.startRecord("outpost.ds9a.nl", QType::SOA); + pw.startRecord(DNSName("outpost.ds9a.nl"), QType::SOA); DNSRecordContent*drc = DNSRecordContent::mastermake(QType::SOA, 1, "a0.org.afilias-nst.info. noc.afilias-nst.info. 2008758137 1800 900 604800 86400"); drc->toPacket(pw); delete drc; @@ -346,7 +346,7 @@ struct SOARecordTest vector makeEmptyQuery() { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA); return packet; } @@ -354,7 +354,7 @@ vector makeEmptyQuery() vector makeRootReferral() { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA); // nobody reads what we output, but it appears to be the magic that shuts some nameservers up static const char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "199.7.91.13", "192.203.230.10", "192.5.5.241", "192.112.36.4", "128.63.2.53", @@ -365,7 +365,7 @@ vector makeRootReferral() for(char c='a';c<='m';++c) { *templ=c; - pw.startRecord(".", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY); + pw.startRecord(DNSName(), QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY); DNSRecordContent* drc = DNSRecordContent::mastermake(QType::NS, 1, templ); drc->toPacket(pw); delete drc; @@ -373,7 +373,7 @@ vector makeRootReferral() for(char c='a';c<='m';++c) { *templ=c; - pw.startRecord(".", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL); + pw.startRecord(DNSName(), QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL); DNSRecordContent* drc = DNSRecordContent::mastermake(QType::A, 1, ips[c-'a']); drc->toPacket(pw); delete drc; @@ -386,25 +386,25 @@ vector makeRootReferral() vector makeTypicalReferral() { vector packet; - DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A); + DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A); - pw.startRecord("ds9a.nl", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY); + pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY); DNSRecordContent* drc = DNSRecordContent::mastermake(QType::NS, 1, "ns1.ds9a.nl"); drc->toPacket(pw); delete drc; - pw.startRecord("ds9a.nl", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY); + pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY); drc = DNSRecordContent::mastermake(QType::NS, 1, "ns2.ds9a.nl"); drc->toPacket(pw); delete drc; - pw.startRecord("ns1.ds9a.nl", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL); + pw.startRecord(DNSName("ns1.ds9a.nl"), QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL); drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4"); drc->toPacket(pw); delete drc; - pw.startRecord("ns2.ds9a.nl", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL); + pw.startRecord(DNSName("ns2.ds9a.nl"), QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL); drc = DNSRecordContent::mastermake(QType::A, 1, "4.3.2.1"); drc->toPacket(pw); delete drc; @@ -546,7 +546,7 @@ struct ParsePacketTest for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { DNSResourceRecord rr; rr.qtype=i->first.d_type; - rr.qname=i->first.d_label; + rr.qname=i->first.d_name; rr.ttl=i->first.d_ttl; rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form @@ -838,6 +838,7 @@ int main(int argc, char** argv) try { reportAllTypes(); + doRun(NOPTest()); doRun(IEqualsTest()); diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 3e8b692d3..02b9df4c0 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -102,7 +102,7 @@ SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries( } /** everything begins here - this is the entry point just after receiving a packet */ -int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&ret) +int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&ret) { s_queries++; @@ -115,16 +115,17 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl if( (qtype.getCode()==QType::PTR && qname==arpa) || (qtype.getCode()==QType::A && qname==localhost)) { ret.clear(); - DNSResourceRecord rr; - rr.qname=qname; - rr.qtype=qtype; - rr.qclass=QClass::IN; - rr.ttl=86400; + DNSRecord dr; + dr.d_name=qname; + dr.d_place = DNSRecord::Answer; + dr.d_type=qtype.getCode(); + dr.d_class=QClass::IN; + dr.d_ttl=86400; if(qtype.getCode()==QType::PTR) - rr.content="localhost."; + dr.d_content=shared_ptr(DNSRecordContent::mastermake(QType::PTR, 1, "localhost.")); else - rr.content="127.0.0.1"; - ret.push_back(rr); + dr.d_content=shared_ptr(DNSRecordContent::mastermake(QType::A, 1, "127.0.0.1")); + ret.push_back(dr); return 0; } @@ -132,16 +133,18 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl (qname==versionbind || qname==idserver || qname==versionpdns ) ) { ret.clear(); - DNSResourceRecord rr; - rr.qname=qname; - rr.qtype=qtype; - rr.qclass=qclass; - rr.ttl=86400; + DNSRecord dr; + dr.d_name=qname; + dr.d_type=qtype.getCode(); + dr.d_class=qclass; + dr.d_ttl=86400; + dr.d_place = DNSRecord::Answer; if(qname==versionbind || qname==versionpdns) - rr.content="\""+::arg()["version-string"]+"\""; + dr.d_content=shared_ptr(DNSRecordContent::mastermake(QType::TXT, 3, "\""+::arg()["version-string"]+"\"")); else - rr.content="\""+s_serverID+"\""; - ret.push_back(rr); + dr.d_content=shared_ptr(DNSRecordContent::mastermake(QType::TXT, 3, "\""+s_serverID+"\"")); + + ret.push_back(dr); return 0; } @@ -156,7 +159,7 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl } //! This is the 'out of band resolver', in other words, the authoritative server -bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, int& res) +bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, int& res) { string prefix; if(doLog()) { @@ -182,7 +185,7 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vectorqtype==qtype || ziter->qtype.getCode()==QType::CNAME) // let rest of nameserver do the legwork on this one + if(qtype.getCode()==QType::ANY || ziter->d_type==qtype.getCode() || ziter->d_type==QType::CNAME) // let rest of nameserver do the legwork on this one ret.push_back(*ziter); } if(!ret.empty()) { @@ -192,11 +195,11 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vectorsecond.d_records.find(boost::make_tuple(authdomain, QType(QType::SOA))); + ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType::SOA)); if(ziter!=iter->second.d_records.end()) { - DNSResourceRecord rr=*ziter; - rr.d_place=DNSResourceRecord::AUTHORITY; - ret.push_back(rr); + DNSRecord dr=*ziter; + dr.d_place=DNSRecord::Nameserver; + ret.push_back(dr); } else LOG(prefix<first) && wcarddomain.chopOff()) { + while(wcarddomain != iter->first && wcarddomain.chopOff()) { LOG(prefix<second.d_records.equal_range(boost::make_tuple(DNSName("*")+wcarddomain)); if(range.first==range.second) continue; for(ziter=range.first; ziter!=range.second; ++ziter) { - DNSResourceRecord rr=*ziter; - if(rr.qtype == qtype || qtype.getCode() == QType::ANY) { - rr.qname = qname; - rr.d_place=DNSResourceRecord::ANSWER; - ret.push_back(rr); + DNSRecord dr=*ziter; + if(dr.d_type == qtype.getCode() || qtype.getCode() == QType::ANY) { + dr.d_name = qname; + dr.d_place=DNSRecord::Answer; + ret.push_back(dr); } } LOG(prefix<first)) { - range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType(QType::NS))); + while(nsdomain.chopOff() && nsdomain != iter->first) { + range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType::NS)); if(range.first==range.second) continue; for(ziter=range.first; ziter!=range.second; ++ziter) { - DNSResourceRecord rr=*ziter; - rr.d_place=DNSResourceRecord::AUTHORITY; - ret.push_back(rr); + DNSRecord dr=*ziter; + dr.d_place=DNSRecord::Nameserver; + ret.push_back(dr); } } if(ret.empty()) { LOG(prefix<second.d_records.find(boost::make_tuple(authdomain, QType(QType::SOA))); + ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType::SOA)); if(ziter!=iter->second.d_records.end()) { - DNSResourceRecord rr=*ziter; - rr.d_place=DNSResourceRecord::AUTHORITY; - ret.push_back(rr); + DNSRecord dr=*ziter; + dr.d_place=DNSRecord::Nameserver; + ret.push_back(dr); } - else + else { LOG(prefix<d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) { - cerr<<"Downgrading to NOEDNS because of "<d_rcode)<<" for query to "<d_rcode)<<" for query to "<d_haveEDNS) { if(mode != EDNSStatus::EDNSIGNORANT) { mode = EDNSStatus::EDNSIGNORANT; - cerr<<"We find that "<modeSetAt=d_now.tv_sec; - cerr<<"Result: ret="<d_haveEDNS<<", new mode: "<d_haveEDNS<<", new mode: "<&ret, int depth, set& beenthere) +int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, set& beenthere) { string prefix; if(doLog()) { @@ -376,8 +380,8 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector SyncRes::getAddrs(const DNSName &qname, int depth, set& beenthere) { - typedef vector res_t; + typedef vector res_t; res_t res; typedef vector ret_t; @@ -451,19 +456,23 @@ vector SyncRes::getAddrs(const DNSName &qname, int depth, setqtype.getCode()==QType::A || i->qtype.getCode()==QType::AAAA) { - ret.push_back(ComboAddress(i->content, 53)); + if(i->d_type == QType::A || i->d_type == QType::AAAA) { + if(auto rec = std::dynamic_pointer_cast(i->d_content)) + ret.push_back(rec->getCA(53)); + else if(auto rec = std::dynamic_pointer_cast(i->d_content)) + ret.push_back(rec->getCA(53)); done=true; } } } if(done) { if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around - set cset; + vector cset; if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), &cset) > 0) { - for(set::const_iterator k=cset.begin();k!=cset.end();++k) { - if(k->ttl > (unsigned int)d_now.tv_sec ) { - ret.push_back(ComboAddress(k->content, 53)); + for(auto k=cset.cbegin();k!=cset.cend();++k) { + if(k->d_ttl > (unsigned int)d_now.tv_sec ) { + ComboAddress ca=std::dynamic_pointer_cast(k->d_content)->getCA(53); + ret.push_back(ca); } } } @@ -493,7 +502,7 @@ vector SyncRes::getAddrs(const DNSName &qname, int depth, set&bestns, bool* flawedNSSet, int depth, set& beenthere) +void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector& bestns, bool* flawedNSSet, int depth, set& beenthere) { string prefix; DNSName subdomain(qname); @@ -506,22 +515,22 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set ns; + vector ns; *flawedNSSet = false; if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) { - for(set::const_iterator k=ns.begin();k!=ns.end();++k) { - if(k->ttl > (unsigned int)d_now.tv_sec ) { - set aset; + for(auto k=ns.cbegin();k!=ns.cend(); ++k) { + if(k->d_ttl > (unsigned int)d_now.tv_sec ) { + vector aset; - DNSResourceRecord rr=*k; - rr.content=k->content; - if(!DNSName(rr.content).isPartOf(subdomain) || t_RC->get(d_now.tv_sec, DNSName(rr.content), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A), + const DNSRecord& dr=*k; + auto nrr = std::dynamic_pointer_cast(dr.d_content); + if(!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A), doLog() ? &aset : 0) > 5) { - bestns.insert(rr); - LOG(prefix< '"< '"<getNS()<<"'"<getNS().isPartOf(subdomain)); if(!aset.empty()) { - LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<content<<") which we miss or is expired"<getNS()<<") which we miss or is expired"<getZoneRepresentation())); + // XXX we are passing a DNSName through a string here! if(beenthere.count(answer)) { brokeloop=true; LOG(prefix<::const_iterator j=beenthere.begin();j!=beenthere.end();++j) { bool neo = !(*j< answer || answer<*j); @@ -558,6 +569,7 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set::const_iterator server=iter->second.d_servers.begin(); server != iter->second.d_servers.end(); ++server) // nsset.insert((iter->second.d_rdForward ? "+" : "-") + server->toStringWithPort()); // add a '+' if the rd bit should be set - // XXX this doesn't work, nsset can't contain a port number, or a plus etc! + // XXX this doesn't work, nsset can't contain a port number, or a plus etc! DNSNAME PAIN abort(); } return authdomain; } - set bestns; + vector bestns; getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere); - for(set::const_iterator k=bestns.begin();k!=bestns.end();++k) { - nsset.insert(DNSName(k->content)); - if(k==bestns.begin()) - subdomain=k->qname; + for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) { + nsset.insert(std::dynamic_pointer_cast(k->d_content)->getNS()); + if(k==bestns.cbegin()) + subdomain=k->d_name; } return subdomain; } -bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res) +bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector& ret, int depth, int &res) { string prefix; if(doLog()) { @@ -622,18 +634,18 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector } LOG(prefix< cset; + vector cset; if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME),&cset) > 0) { - for(set::const_iterator j=cset.begin();j!=cset.end();++j) { - if(j->ttl>(unsigned int) d_now.tv_sec) { - LOG(prefix<content<<"'"<d_ttl>(unsigned int) d_now.tv_sec) { + LOG(prefix<d_content->getZoneRepresentation()<<"'"<beenthere; - res=doResolve(DNSName(j->content), qtype, ret, depth+1, beenthere); + res=doResolve(std::dynamic_pointer_cast(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere); } else res=0; @@ -652,7 +664,8 @@ static const DNSName getLastLabel(const DNSName& qname) return ret; } -bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res) + +bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res) { bool giveNegative=false; @@ -713,23 +726,23 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector cset; + vector cset; bool found=false, expired=false; vector> signatures; uint32_t ttl=0; if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_doDNSSEC ? &signatures : 0) > 0) { LOG(prefix<::const_iterator j=cset.begin();j!=cset.end();++j) { - LOG(j->content); - if(j->ttl>(unsigned int) d_now.tv_sec) { - DNSResourceRecord rr=*j; - ttl=rr.ttl-=d_now.tv_sec; + for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) { + LOG(j->d_content->getZoneRepresentation()); + if(j->d_ttl>(unsigned int) d_now.tv_sec) { + DNSRecord dr=*j; + ttl = (dr.d_ttl-=d_now.tv_sec); if(giveNegative) { - rr.d_place=DNSResourceRecord::AUTHORITY; - rr.ttl=sttl; + dr.d_place=DNSRecord::Nameserver; + dr.d_ttl=sttl; } - ret.push_back(rr); - LOG("[ttl="<getZoneRepresentation(); - rr.d_place=DNSResourceRecord::ANSWER; - - ret.push_back(rr); + DNSRecord dr; + dr.d_type=QType::RRSIG; + dr.d_name=sqname; + dr.d_ttl=ttl; + dr.d_content=signature; + dr.d_place=DNSRecord::Answer; + dr.d_class=1; + ret.push_back(dr); } LOG(endl); @@ -797,7 +810,7 @@ inline vector SyncRes::shuffleInSpeedOrder(set &tnameservers, if(doLog()) { LOG(prefix<<"Nameservers: "); - for(vector::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) { + for(vector::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) { if(i!=rnameservers.begin()) { LOG(", "); if(!((i-rnameservers.begin())%3)) { @@ -828,7 +841,7 @@ static bool magicAddrMatch(const QType& query, const QType& answer) /** returns -1 in case of no results, rcode otherwise */ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, - vector&ret, + vector&ret, int depth, set&beenthere) { string prefix; @@ -847,13 +860,14 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe LOG(prefix<doAgeCache(d_now.tv_sec, auth, QType::NS, 10)) g_stats.nsSetInvalidations++; } return -1; } // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now - if(pdns_iequals(qname, *tns) && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) { + if(qname == *tns && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) { LOG(prefix< nameservers, DNSName auth, bool flawedNSSe LWResult lwr; if(tns->empty()) { LOG(prefix<toString()<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"< nameservers, DNSName auth, bool flawedNSSe if(s_maxtotusec && d_totUsec > s_maxtotusec) throw ImmediateServFailException("Too much time waiting for "+qname.toString()+"|"+qtype.getName()+", timeouts: "+boost::lexical_cast(d_timeouts) +", throttles: "+boost::lexical_cast(d_throttledqueries) + ", queries: "+lexical_cast(d_outqueries)+", "+lexical_cast(d_totUsec/1000)+"msec"); - if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_result, resolveret)) { + if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_records, resolveret)) { LOG(prefix< nameservers, DNSName auth, bool flawedNSSe LOG(prefix<toString()<<" ("<< remoteIP->toString() <<"), rcode="<toString()<<" ("<< remoteIP->toString() <<"), rcode="<sin4.sin_family==AF_INET6) @@ -1027,13 +1042,13 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe if(s_minimumTTL) { for(auto& rec : lwr.d_records) { - rec.first.d_ttl = max(rec.first.d_ttl, s_minimumTTL); + rec.d_ttl = max(rec.d_ttl, s_minimumTTL); } } struct CachePair { - set records; + vector records; vector> signatures; }; typedef map, CachePair, TCacheComp > tcache_t; @@ -1041,29 +1056,29 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe if(d_doDNSSEC) { for(const auto& rec : lwr.d_records) { - if(rec.first.d_type == QType::RRSIG) { - auto rrsig = std::dynamic_pointer_cast(rec.first.d_content); - cerr<<"Got an RRSIG for "<d_type)<<" with name '"<d_type))].signatures.push_back(rrsig); + if(rec.d_type == QType::RRSIG) { + auto rrsig = std::dynamic_pointer_cast(rec.d_content); + // cerr<<"Got an RRSIG for "<d_type)<<" with name '"<d_type))].signatures.push_back(rrsig); } } } // reap all answers from this packet that are acceptable - for(LWResult::res_t::iterator i=lwr.getResult().begin();i != lwr.getResult().end();++i) { - if(i->qtype.getCode() == QType::OPT) { - LOG(prefix<qname.toString()<<"' from '"<qname.toString()<<"|"<qtype.getName()<<"|"<content<<"' from '"<qtype.getCode()==QType::ANY) { + LOG(prefix<getZoneRepresentation()<<"' from '"<domainmap->empty()) { - DNSName tmp_qname(i->qname); + DNSName tmp_qname(rec.d_name); auto auth_domain_iter=getBestAuthZone(&tmp_qname); if(auth_domain_iter!=t_sstorage->domainmap->end()) { if (auth_domain_iter->first != auth) { @@ -1077,28 +1092,26 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe } - if(i->qname.isPartOf(auth)) { - if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth.toString() /* ugh */)) { + if(rec.d_name.isPartOf(auth)) { + if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && rec.d_place==DNSRecord::Answer && ::arg().contains("delegation-only",auth.toString() /* ugh */)) { LOG("NO! Is from delegation-only zone"<qtype.getCode() == QType::RRSIG) { + else if(rec.d_type == QType::RRSIG) { LOG("RRSIG - separate"<ttl=min(s_maxcachettl, i->ttl); + rec.d_ttl=min(s_maxcachettl, rec.d_ttl); - DNSResourceRecord rr=*i; - rr.d_place=DNSResourceRecord::ANSWER; + DNSRecord dr(rec); + dr.d_place=DNSRecord::Answer; - rr.ttl += d_now.tv_sec; + dr.d_ttl += d_now.tv_sec; - if(rr.qtype.getCode() == QType::NS) // people fiddle with the case - rr.content=toLower(rr.content); // this must stay! (the cache can't be case-insensitive on the RHS of records) - tcache[make_pair(i->qname,i->qtype)].records.insert(rr); + tcache[make_pair(rec.d_name,QType(rec.d_type))].records.push_back(dr); } } else @@ -1110,14 +1123,14 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe if(i->second.records.size() > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2) uint32_t lowestTTL=std::numeric_limits::max(); for(auto& record : i->second.records) - lowestTTL=min(lowestTTL, record.ttl); + lowestTTL=min(lowestTTL, record.d_ttl); for(auto& record : i->second.records) - *const_cast(&record.ttl)=lowestTTL; + *const_cast(&record.d_ttl)=lowestTTL; // boom } - cout<<"Have "<second.records.size()<<" records and "<second.signatures.size()<<" signatures for "<first.first.toString(); - cout<<'|'<first.second.getCode())<second.records.size()<<" records and "<second.signatures.size()<<" signatures for "<first.first.toString(); + // cout<<'|'<first.second.getCode())<replace(d_now.tv_sec, i->first.first, i->first.second, i->second.records, i->second.signatures, lwr.d_aabit); } set nsset; @@ -1127,20 +1140,20 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe DNSName newauth, soaname; DNSName newtarget; - for(LWResult::res_t::iterator i=lwr.getResult().begin();i!=lwr.getResult().end();++i) { - if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::SOA && - lwr.d_rcode==RCode::NXDomain && dottedEndsOn(qname,i->qname) && dottedEndsOn(i->qname, auth)) { - LOG(prefix<ttl = min(i->ttl, s_maxnegttl); + rec.d_ttl = min(rec.d_ttl, s_maxnegttl); if(!newtarget.length()) // only add a SOA if we're not going anywhere after this - ret.push_back(*i); + ret.push_back(rec); NegCacheEntry ne; - ne.d_qname=i->qname; + ne.d_qname=rec.d_name; - ne.d_ttd=d_now.tv_sec + i->ttl; + ne.d_ttd=d_now.tv_sec + rec.d_ttl; ne.d_name=qname; ne.d_qtype=QType(0); // this encodes 'whole record' @@ -1153,41 +1166,42 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe negindic=true; } - else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) { - ret.push_back(*i); - newtarget=DNSName(i->content); + else if(rec.d_place==DNSRecord::Answer && rec.d_name == qname && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME)))) { + ret.push_back(rec); + newtarget=DNSName(rec.d_content->getZoneRepresentation()); } - else if(d_doDNSSEC && (i->qtype==QType::RRSIG || i->qtype==QType::NSEC || i->qtype==QType::NSEC3) && i->d_place==DNSResourceRecord::ANSWER){ - ret.push_back(*i); // enjoy your DNSSEC + else if(d_doDNSSEC && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSRecord::Answer){ + ret.push_back(rec); // enjoy your DNSSEC } // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively - else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && + else if(rec.d_place==DNSRecord::Answer && rec.d_name == qname && ( - i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) ) || sendRDQuery + rec.d_type==qtype.getCode() || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, QType(rec.d_type)) ) ) || sendRDQuery ) ) { - LOG(prefix<content<<"|"<qtype.getName()<<"'"<getZoneRepresentation()<<"|"<d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(i->qname) && i->qtype.getCode()==QType::NS) { - if(moreSpecificThan(i->qname,auth)) { - newauth=i->qname; - LOG(prefix<qname.toString()<<"' -> '"<content<<"'"< '"<getZoneRepresentation()<<"'"<qname.toString()<<"' -> '"<content<<"', had '"<content)); + else { + LOG(prefix< '"<getZoneRepresentation()<<"', had '"<getZoneRepresentation())); } - else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::DS) { - LOG(prefix<qname.toString()<<"' -> '"<content<<"'"< '"<getZoneRepresentation()<<"'"<d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && + else if(!done && rec.d_place==DNSRecord::Nameserver && dottedEndsOn(qname,rec.d_name) && rec.d_type==QType::SOA && lwr.d_rcode==RCode::NoError) { LOG(prefix< nameservers, DNSName auth, bool flawedNSSe LOG(prefix< ttl = min(s_maxnegttl, i->ttl); - ret.push_back(*i); + rec.d_ttl = min(s_maxnegttl, rec.d_ttl); + ret.push_back(rec); NegCacheEntry ne; - ne.d_qname=i->qname; - ne.d_ttd=d_now.tv_sec + i->ttl; + ne.d_qname=rec.d_name; + ne.d_ttd=d_now.tv_sec + rec.d_ttl; ne.d_name=qname; ne.d_qtype=qtype; if(qtype.getCode()) { // prevents us from blacking out a whole domain @@ -1215,7 +1229,7 @@ int SyncRes::doResolveAt(set nameservers, DNSName auth, bool flawedNSSe return 0; } if(!newtarget.empty()) { - if(pdns_iequals(newtarget,qname)) { + if(newtarget == qname) { LOG(prefix< nameservers, DNSName auth, bool flawedNSSe LOG(prefix<dnssecmap[newauth]=true; - for(const auto& e : t_sstorage->dnssecmap) + /* for(const auto& e : t_sstorage->dnssecmap) cout< nameservers, DNSName auth, bool flawedNSSe // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc -int directResolve(const std::string& qname, const QType& qtype, int qclass, vector& ret) +int directResolve(const std::string& qname, const QType& qtype, int qclass, vector& ret) { struct timeval now; gettimeofday(&now, 0); SyncRes sr(now); - int res = sr.beginResolve(DNSName(qname), QType(qtype), qclass, ret); // DNSName conversion XXX + return res; } diff --git a/pdns/syncres.hh b/pdns/syncres.hh index e9a1f5416..49c0b3c24 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -239,7 +239,7 @@ public: explicit SyncRes(const struct timeval& now); - int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&ret); + int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&ret); void setId(int id) { if(doLog()) @@ -394,14 +394,14 @@ public: vector d_servers; bool d_rdForward; typedef multi_index_container < - DNSResourceRecord, + DNSRecord, indexed_by < ordered_non_unique< - composite_key< DNSResourceRecord, - member, - member + composite_key< DNSRecord, + member, + member >, - composite_key_compare, std::less > + composite_key_compare, std::less > > > > records_t; @@ -439,14 +439,14 @@ public: private: struct GetBestNSAnswer; - int doResolveAt(set nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector&ret, + int doResolveAt(set nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector&ret, int depth, set&beenthere); - int doResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, set& beenthere); - bool doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); + int doResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, set& beenthere); + bool doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); domainmap_t::const_iterator getBestAuthZone(DNSName* qname); - bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); - bool doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); - void getBestNSFromCache(const DNSName &qname, const QType &qtype, set&bestns, bool* flawedNSSet, int depth, set& beenthere); + bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); + bool doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); + void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector&bestns, bool* flawedNSSet, int depth, set& beenthere); DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, set& nsset, bool* flawedNSSet, int depth, set&beenthere); inline vector shuffleInSpeedOrder(set &nameservers, const string &prefix); @@ -629,7 +629,7 @@ typedef boost::function pipefunc_t; void broadcastFunction(const pipefunc_t& func, bool skipSelf = false); void distributeAsyncFunction(const std::string& question, const pipefunc_t& func); -int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector& ret); +int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector& ret); template T broadcastAccFunction(const boost::function& func, bool skipSelf=false); diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index 204b43fef..65f5026e4 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -713,7 +713,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou if (rectify) { if (rr.qtype.getCode()) { qnames.insert(rr.qname); - if(rr.qtype.getCode() == QType::NS && !pdns_iequals(rr.qname, target)) + if(rr.qtype.getCode() == QType::NS && rr.qname!=target) nsset.insert(rr.qname); } else { // remove existing ents @@ -731,12 +731,12 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou // set auth BOOST_FOREACH(DNSResourceRecord &rr, rrs) { rr.auth=true; - if (rr.qtype.getCode() != QType::NS || !pdns_iequals(rr.qname, target)) { + if (rr.qtype.getCode() != QType::NS || rr.qname!=target) { DNSName shorter(rr.qname); do { - if (pdns_iequals(shorter, target)) // apex is always auth + if (shorter==target) // apex is always auth continue; - if(nsset.count(shorter) && !(pdns_iequals(rr.qname, shorter) && rr.qtype.getCode() == QType::DS)) + if(nsset.count(shorter) && !(rr.qname==shorter && rr.qtype.getCode() == QType::DS)) rr.auth=false; } while(shorter.chopOff()); } else @@ -749,7 +749,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou map nonterm; BOOST_FOREACH(DNSResourceRecord &rr, rrs) { DNSName shorter(rr.qname); - while(!pdns_iequals(shorter, target) && shorter.chopOff()) { + while(shorter != target && shorter.chopOff()) { if(!qnames.count(shorter)) { if(!(maxent)) { L< typedef boost::tuple case_t; diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index 01c6ef705..402af0f04 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -976,7 +976,7 @@ static void patchZone(HttpRequest* req, HttpResponse* resp) { } else if (changetype == "REPLACE") { // we only validate for REPLACE, as DELETE can be used to "fix" out of zone records. - if (!qname.isPartOf(zonename) && !pdns_iequals(qname, zonename)) + if (!qname.isPartOf(zonename) && qname != zonename) throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName()+": Name is out of zone"); new_records.clear(); @@ -991,7 +991,7 @@ static void patchZone(HttpRequest* req, HttpResponse* resp) { if (rr.qname != qname || rr.qtype != qtype) throw ApiException("Record "+rr.qname.toString()+"/"+rr.qtype.getName()+" "+rr.content+": Record wrongly bundled with RRset " + qname.toString() + "/" + qtype.getName()); - if (rr.qtype.getCode() == QType::SOA && pdns_iequals(rr.qname, zonename)) { + if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) { soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind); } } diff --git a/pdns/ws-recursor.cc b/pdns/ws-recursor.cc index b9082ed92..49da6d1cf 100644 --- a/pdns/ws-recursor.cc +++ b/pdns/ws-recursor.cc @@ -164,15 +164,15 @@ static void fillZone(const DNSName& zonename, HttpResponse* resp) Value records; records.SetArray(); - BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& rr, zone.d_records) { + BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& dr, zone.d_records) { Value object; object.SetObject(); - Value jname(rr.qname.toString().c_str(), doc.GetAllocator()); // copy + Value jname(dr.d_name.toString().c_str(), doc.GetAllocator()); // copy object.AddMember("name", jname, doc.GetAllocator()); - Value jtype(rr.qtype.getName().c_str(), doc.GetAllocator()); // copy + Value jtype(DNSRecordContent::NumberToType(dr.d_type).c_str(), doc.GetAllocator()); // copy object.AddMember("type", jtype, doc.GetAllocator()); - object.AddMember("ttl", rr.ttl, doc.GetAllocator()); - Value jcontent(rr.content.c_str(), doc.GetAllocator()); // copy + object.AddMember("ttl", dr.d_ttl, doc.GetAllocator()); + Value jcontent(dr.d_content->getZoneRepresentation().c_str(), doc.GetAllocator()); // copy object.AddMember("content", jcontent, doc.GetAllocator()); records.PushBack(object, doc.GetAllocator()); } @@ -392,7 +392,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { const SyncRes::AuthDomain& zone = val.second; BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& rr, zone.d_records) { - if (pdns_ci_find(rr.qname.toString(), q) == string::npos && pdns_ci_find(rr.content, q) == string::npos) + if (pdns_ci_find(rr.d_name.toString(), q) == string::npos && pdns_ci_find(rr.d_content->getZoneRepresentation(), q) == string::npos) continue; Value object; @@ -402,9 +402,9 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) { object.AddMember("zone_id", jzoneId, doc.GetAllocator()); Value jzoneName(val.first.toString().c_str(), doc.GetAllocator()); // copy object.AddMember("zone_name", jzoneName, doc.GetAllocator()); - Value jname(rr.qname.toString().c_str(), doc.GetAllocator()); // copy + Value jname(rr.d_name.toString().c_str(), doc.GetAllocator()); // copy object.AddMember("name", jname, doc.GetAllocator()); - Value jcontent(rr.content.c_str(), doc.GetAllocator()); // copy + Value jcontent(rr.d_content->getZoneRepresentation().c_str(), doc.GetAllocator()); // copy object.AddMember("content", jcontent, doc.GetAllocator()); doc.PushBack(object, doc.GetAllocator()); -- 2.40.0