]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
here you go. It works, passes regression tests, but creates timeouts I can't explain...
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 2 Oct 2015 06:40:05 +0000 (08:40 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 2 Oct 2015 06:40:05 +0000 (08:40 +0200)
23 files changed:
pdns/lua-auth.cc
pdns/lua-pdns.cc
pdns/lua-pdns.hh
pdns/lua-recursor.cc
pdns/lua-recursor.hh
pdns/lwres.cc
pdns/lwres.hh
pdns/misc.cc
pdns/misc.hh
pdns/packethandler.cc
pdns/pdns_recursor.cc
pdns/recursor_cache.cc
pdns/recursor_cache.hh
pdns/reczones.cc
pdns/secpoll-recursor.cc
pdns/slavecommunicator.cc
pdns/speedtest.cc
pdns/syncres.cc
pdns/syncres.hh
pdns/tcpreceiver.cc
pdns/test-dnsrecords_cc.cc
pdns/ws-auth.cc
pdns/ws-recursor.cc

index 2f62a92965044e573f2ad255b5ac5f411f964d3a..8b51ff44225e7016763bd6c3bffda7c315328516 100644 (file)
@@ -175,10 +175,10 @@ static int ldp_getZone(lua_State *L) {
 
 static int ldp_addRecords(lua_State *L) {
   DNSPacket *p=ldp_checkDNSPacket(L);
-  vector<DNSResourceRecord> rrs;
+  vector<DNSRecord> 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;
 }
index 38402635e81be29bc3991a5329c4cb004fd7211e..99f77504a923d809ecd50035b4cf3e0318690ff6 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 #include <stdexcept>
 #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<DNSResourceRecord>& records)
+void pushResourceRecordsTable(lua_State* lua, const vector<DNSRecord>& 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<DNSResourceRecord>& ret)
+void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSRecord>& 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<DNSRes
 
     uint32_t tmpnum=0;
     if(!getFromTable(lua, "qtype", tmpnum))
-      rr.qtype=QType::A;
+      rr.d_type=QType::A;
     else
-      rr.qtype=tmpnum;
+      rr.d_type=tmpnum;
 
-    getFromTable(lua, "content", rr.content);
-    if(!getFromTable(lua, "ttl", rr.ttl))
-      rr.ttl=3600;
+    if(!getFromTable(lua, "qclass", tmpnum))
+      rr.d_class = QClass::IN;
+    else {
+      rr.d_class = tmpnum;
+    }
+
+
+    string content;
+    getFromTable(lua, "content", content);
+    rr.d_content=shared_ptr<DNSRecordContent>(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
index f00979231e947e39e897169c743ec080f2ad1a99..86125d699e5b4d5e24305c24b7e17f588121af0a 100644 (file)
@@ -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<DNSResourceRecord>& records);
-void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSResourceRecord>& ret);
+void pushResourceRecordsTable(lua_State* lua, const vector<DNSRecord>& records);
+void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSRecord>& ret);
 void pushSyslogSecurityLevelTable(lua_State *lua);
 int getLuaTableLength(lua_State* lua, int depth);
 void luaStackDump (lua_State *L);
index 7365881f00717d771aadc02edeea88644f18469f..3c25a7f707bd4727e7247c8fac9494970d09504e 100644 (file)
@@ -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<DNSResourceRecord>& ret);
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSRecord>& 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<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
 
-bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res)
 {
   return false;
 }
@@ -62,8 +62,10 @@ extern "C" {
 #include <stdexcept>
 #include <boost/foreach.hpp>
 #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<DNSResourceRecord>& ret, const QType& qtype)
+int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
 {
-  vector<DNSResourceRecord> resolved;
-  string target;
-  BOOST_FOREACH(DNSResourceRecord& rr, ret) {
-    if(rr.qtype.getCode() == QType::CNAME) {
-      target=rr.content;
+  vector<DNSRecord> resolved;
+  string target; // XXX DNSNAME PAIN
+  BOOST_FOREACH(DNSRecord& rr, ret) {
+    if(rr.d_type == QType::CNAME) {
+      target=std::dynamic_pointer_cast<CNAMERecordContent>(rr.d_content)->getTarget().toString();
       break;
     }
   }
@@ -97,7 +99,7 @@ int followCNAMERecords(vector<DNSResourceRecord>& 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<DNSResourceRecord>& ret, const QType& qtype)
 
 }
 
-int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSResourceRecord>& ret)
+int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSRecord>& 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<ARecordContent>(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<AAAARecordContent>(prefixAddress);
+      rr.d_type = QType::AAAA;
     }
   }
   return rcode;
 }
 
-int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector<DNSResourceRecord>& ret)
+int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector<DNSRecord>& 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<DN
 
 
   int rcode = directResolve(newquery, QType(QType::PTR), 1, ret);
-  BOOST_FOREACH(DNSResourceRecord& rr, ret)
+  BOOST_FOREACH(DNSRecord& rr, ret)
   {
-    if(rr.qtype.getCode() == QType::PTR && rr.d_place==DNSResourceRecord::ANSWER) {
-      rr.qname = qname;
+    if(rr.d_type == QType::PTR && rr.d_place==DNSRecord::Answer) {
+      rr.d_name = qname;
     }
   }
   return rcode;
 
 }
 
-bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& 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<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& 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<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& 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<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::postresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& 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<DNSResourceRecord>& ret, int& res)
+bool RecursorLua::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSRecord>& 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<DNSResourceRecord>& ret,
+bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret,
   int& res, bool* variable)
 {
   d_variable = false;
index a4f7e24f35b4983b6d5434835ebaf5e2121606dc..2cf4eaa4cd6121616d83576277503bfdc94d7f79 100644 (file)
@@ -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<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
+  bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+  bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+  bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+  bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+  bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSRecord>& 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<DNSResourceRecord>& ret, int& res, bool* variable);
+  bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable);
 
   struct NoFuncs
   {
index 08206126c18983897119d80272f698d63711c20b..e8e6a5daad6a60410f762421e097ef39be10cebd 100644 (file)
@@ -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<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl;
       }
       // unexpected count has already been done @ pdns_recursor.cc
       goto out;
     }
-
-    lwr->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<DNSResourceRecord>& 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;
-}
index 82bb0050ad7d51a6f5c6a5b468aebbd274d9cb20..ec33c396c6135c8f5eda27cd001e0d31652c69e0 100644 (file)
@@ -58,16 +58,12 @@ class LWResult
 {
 public:
   LWResult() : d_usec(0) {}
-  typedef vector<DNSResourceRecord> res_t;
-  res_t& getResult();
 
-  vector<pair<DNSRecord, uint16_t>> d_records;
+  vector<DNSRecord> d_records;
   int d_rcode;
   bool d_aabit, d_tcbit;
   uint32_t d_usec;
   bool d_haveEDNS;
-
-  vector<DNSResourceRecord> d_result;
 };
 
 int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res);
index 340ab1b73f09e26083a50c254961cf0e29896621..065cbd6c964db280dd0dbdd165ca56304c77d286 100644 (file)
@@ -51,7 +51,7 @@
 #include <sys/types.h>
 #include <boost/algorithm/string.hpp>
 #include "iputils.hh"
-
+#include "dnsparser.hh"
 
 bool g_singleThreaded;
 
@@ -547,16 +547,42 @@ void shuffle(vector<DNSResourceRecord>& rrs)
   // we don't shuffle the rest
 }
 
-static bool comparePlace(DNSResourceRecord a, DNSResourceRecord b)
+
+// shuffle, maintaining some semblance of order
+void shuffle(vector<DNSRecord>& rrs)
 {
-  return (a.d_place < b.d_place);
+  vector<DNSRecord>::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<DNSResourceRecord>& rrs)
+void orderAndShuffle(vector<DNSRecord>& 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);
 }
 
index acce97644081c966f04c86b17faf8bb1bfa64240..43515a5a14c08de145100ea8412e2ea75ca76d49 100644 (file)
@@ -300,8 +300,9 @@ inline void unixDie(const string &why)
 }
 
 string makeHexDump(const string& str);
+void shuffle(vector<DNSRecord>& rrs);
 void shuffle(vector<DNSResourceRecord>& rrs);
-void orderAndShuffle(vector<DNSResourceRecord>& rrs);
+void orderAndShuffle(vector<DNSRecord>& 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)
 {
index 873f42479a957ef18bdb24f590ec29d1bd1f0d0a..ee3f06791a267c348143ffedc1b7aa9bf474c772 100644 (file)
@@ -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: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
@@ -952,7 +952,7 @@ void PacketHandler::completeANYRecords(DNSPacket *p, DNSPacket*r, SOAData& sd, c
     return;
     
   addNSECX(p, r, target, DNSName(), sd.qname, 5);
-  if(pdns_iequals(sd.qname, p->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;
index 23fb9af73c6e2d63bb05deec315af328d6294d92..a0632736adfa9248a0cedb06e24e0e9ad090b262 100644 (file)
@@ -546,7 +546,7 @@ void startDoResolve(void *p)
     }
     ComboAddress local;
     listenSocketsAddresses_t::const_iterator lociter;
-    vector<DNSResourceRecord> ret;
+    vector<DNSRecord> ret;
     vector<uint8_t> 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<DNSResourceRecord>::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<DNSResourceRecord>::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<DNSRecordContent> 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<DNSResourceRecord> ret;
+      vector<DNSRecord> 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()) {
index a15df95c768b0f925c9bd25f989c2c054f2ca620..0fb1a2c49856292fe87f03c88131de5c679a4c6b 100644 (file)
@@ -4,90 +4,13 @@
 #include "recursor_cache.hh"
 #include "misc.hh"
 #include <iostream>
-
 #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: '"<<rr.content<<"', offset: "<<offset<<", '"<<qname<<"', "<<qt.getName()<<"\n";
-        break;
-      }
-      rr.content.append(serial.c_str()+frompos, labellen);
-      frompos+=labellen;
-      rr.content.append(1,'.');
-    }
-    if(rr.content.empty())
-      rr.content=".";
-  }
-  else {
-    shared_ptr<DNSRecordContent> 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<DNSRecordContent> drc(DNSRecordContent::mastermake(type, 1, rr.content));
-    ret=drc->serialize(rr.qname);
-  //  cerr<<"stored '"<<rr.qname<<" '"<<rr.qtype.getName()<<"' '"<<rr.content<<"' as "<<ret.size()<<" bytes"<<endl;
-    return ret;
-  }
-}
-
 unsigned int MemRecursorCache::size()
 {
   return (unsigned int)d_cache.size();
@@ -101,42 +24,48 @@ unsigned int MemRecursorCache::bytes()
   for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
     ret+=sizeof(struct CacheEntry);
     ret+=(unsigned int)i->d_qname.toString().length();
-    for(vector<StoredRecord>::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<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures)
+int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* 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"<<endl;
     d_cachedqname=qname;
     d_cachecache=d_cache.equal_range(tie(qname));
     d_cachecachevalid=true;
   }
-//  else cerr<<"had cache cache hit!"<<endl;
+  //  else cerr<<"had cache cache hit!"<<endl;
 
   if(res)
     res->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<StoredRecord>::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<DNSResourceRecord>& content, const CacheEntry& stored)
+bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const vector<DNSRecord>& content, const CacheEntry& stored)
 {
   if(!stored.d_auth) {
     //~ cerr<<"feel free to scribble non-auth data!"<<endl;
@@ -175,7 +104,7 @@ bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResou
   if(stored.d_records.empty())
     return false;
 
-  if(stored.d_records.begin()->d_ttd > content.begin()->ttl) {
+  if(stored.d_ttd > content.begin()->d_ttl) {
     //~ cerr<<"attempt to LOWER TTL - fine by us"<<endl;
     return false;
   }
@@ -185,39 +114,27 @@ bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResou
   return true;
 }
 
-/* the code below is rather tricky - it basically replaces the stuff cached for qname by content, but it is special
-   cased for when inserting identical records with only differing ttls, in which case the entry is not
-   touched, but only given a new ttd */
-void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth)
+void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt,  const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth)
 {
   d_cachecachevalid=false;
   boost::tuple<DNSName, uint16_t> 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<StoredRecord>(), auth)).first;
-    isNew=true;
+    stored=d_cache.insert(CacheEntry(key,CacheEntry::records_t(), auth)).first;
   }
-  pair<vector<StoredRecord>::iterator, vector<StoredRecord>::iterator> range;
-
-  StoredRecord dr;
+  
   CacheEntry ce=*stored;
+  ce.d_qtype=qt.getCode();
   ce.d_signatures=signatures;
-  //~ cerr<<"asked to store "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"', isnew="<<isNew<<", auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n";
 
-  if(qt.getCode()==QType::SOA || qt.getCode()==QType::CNAME)  { // you can only have one (1) each of these
-    //    cerr<<"\tCleaning out existing store because of SOA and CNAME\n";
-    ce.d_records.clear();
-  }
+  //  cerr<<"asked to store "<< qname<<"|"+qt.getName()<<" -> '"<<content.begin()->d_content->getZoneRepresentation()<<"', auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n";
+
+  ce.d_records.clear();
 
   if(!auth && ce.d_auth) {  // unauth data came in, we have some auth data, but is it fresh?
-    vector<StoredRecord>::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"<<endl;
-    vector<StoredRecord>::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"<<endl;
     ce.d_records.clear(); // clear non-auth data
     ce.d_auth = true;
-    isNew=true;           // data should be sorted again
   }
 //  else cerr<<"\tNot nuking"<<endl;
 
-  // make sure we don't accidentally merge old and new unauth data
-  if(!auth && !ce.d_auth) {
-    ce.d_records.clear();
-    isNew=true;
-  }
 
   // cerr<<"\tHave "<<content.size()<<" records to store\n";
-  for(set<DNSResourceRecord>::const_iterator i=content.begin(); i != content.end(); ++i) {
+  for(auto i=content.cbegin(); i != content.cend(); ++i) {
     // cerr<<"To store: "<<i->content<<" with ttl/ttd "<<i->ttl<<endl;
-    dr.d_ttd=min(maxTTD, i->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<StoredRecord>::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<StoredRecord>(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<StoredRecord>::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<StoredRecord>::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<StoredRecord>::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());
index 4e21bac02f72e2585cc40ecb75045193b83308c0..1c643d08431912900d58b8eba8ab4a53f5cebbb9 100644 (file)
@@ -32,10 +32,9 @@ public:
   }
   unsigned int size();
   unsigned int bytes();
-  int get(time_t, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=0);
+  int get(time_t, const DNSName &qname, const QType& qt, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* 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<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth);
+  void replace(time_t, const DNSName &qname, const QType& qt,  const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& 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<DNSName, uint16_t>& key, const vector<StoredRecord>& records, bool auth) : 
-      d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records)
+    CacheEntry(const boost::tuple<DNSName, uint16_t>& key, const vector<shared_ptr<DNSRecordContent>>& records, bool auth) : 
+      d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records), d_ttd(0)
     {}
 
-    typedef vector<StoredRecord> records_t;
+    typedef vector<std::shared_ptr<DNSRecordContent>> records_t;
     vector<std::shared_ptr<RRSIGRecordContent>> d_signatures;
     uint32_t getTTD() const
     {
-      if(d_records.size()==1)
-        return d_records.begin()->d_ttd;
-
-      uint32_t earliest=std::numeric_limits<uint32_t>::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<cache_t::iterator, cache_t::iterator> d_cachecache;
   DNSName d_cachedqname;
   bool d_cachecachevalid;
-  bool attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored);
+  bool attemptToRefreshNSTTL(const QType& qt, const vector<DNSRecord>& content, const CacheEntry& stored);
 };
-string DNSRR2String(const DNSResourceRecord& rr);
-DNSResourceRecord String2DNSRR(const DNSName& qname, const QType& qt, const string& serial, uint32_t ttd);
-
 #endif
index 949a50541fc2612c96eaa74169a2c5f10dbc03f0..08eec27c94172ea073cbc3c4a779fdc503de496b 100644 (file)
@@ -36,7 +36,7 @@ extern char** g_argv;
 void primeHints(void)
 {
   // prime root cache
-  set<DNSResourceRecord>nsset;
+  vector<DNSRecord> 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<DNSResourceRecord> aset;
-      aset.insert(arr);
+      aaaarr.d_name=arr.d_name=DNSName(templ);
+      nsrr.d_content=std::make_shared<NSRecordContent>(DNSName(templ));
+      arr.d_content=std::make_shared<ARecordContent>(ComboAddress(ips[c-'a']));
+      vector<DNSRecord> aset;
+      aset.push_back(arr);
       t_RC->replace(time(0), DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); // auth, nuke it all
       if (ip6s[c-'a'] != NULL) {
-        aaaarr.content=ip6s[c-'a'];
+        aaaarr.d_content=std::make_shared<AAAARecordContent>(ComboAddress(ip6s[c-'a']));
 
-        set<DNSResourceRecord> aaaaset;
-        aaaaset.insert(aaaarr);
+        vector<DNSRecord> aaaaset;
+        aaaaset.push_back(aaaarr);
         t_RC->replace(time(0), DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), 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<DNSResourceRecord> aset;
-        aset.insert(rr);
+        vector<DNSRecord> aset;
+        aset.push_back(DNSRecord(rr));
         t_RC->replace(time(0), rr.qname, QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); // auth, etc see above
       } else if(rr.qtype.getCode()==QType::AAAA) {
-        set<DNSResourceRecord> aaaaset;
-        aaaaset.insert(rr);
+        vector<DNSRecord> aaaaset;
+        aaaaset.push_back(DNSRecord(rr));
         t_RC->replace(time(0), rr.qname, QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), 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>(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<NSRecordContent>("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>(DNSRecordContent::mastermake(QType::A, 1, ip));
+  ad.d_records.insert(dr);
   
-  if(newMap->count(rr.qname)) {  
-    L<<Logger::Warning<<"Hosts file will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl;
+  if(newMap->count(dr.d_name)) {  
+    L<<Logger::Warning<<"Hosts file will not overwrite zone '"<<dr.d_name<<"' already loaded"<<endl;
   }
   else {
-    L<<Logger::Warning<<"Inserting forward zone '"<<rr.qname<<"' based on hosts file"<<endl;
-    (*newMap)[rr.qname]=ad;
+    L<<Logger::Warning<<"Inserting forward zone '"<<dr.d_name<<"' based on hosts file"<<endl;
+    (*newMap)[dr.d_name]=ad;
   }
 }
 
@@ -142,39 +143,39 @@ static void makeIPToNamesZone(SyncRes::domainmap_t* newMap, const vector<string>
   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>(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<NSRecordContent>(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>(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<<Logger::Warning<<"Will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl;
+  if(newMap->count(dr.d_name)) {  
+    L<<Logger::Warning<<"Will not overwrite zone '"<<dr.d_name<<"' already loaded"<<endl;
   }
   else {
     if(ipparts.size()==4)
-      L<<Logger::Warning<<"Inserting reverse zone '"<<rr.qname<<"' based on hosts file"<<endl;
-    (*newMap)[rr.qname]=ad;
+      L<<Logger::Warning<<"Inserting reverse zone '"<<dr.d_name<<"' based on hosts file"<<endl;
+    (*newMap)[dr.d_name]=ad;
   }
 }
 
@@ -250,7 +251,7 @@ string reloadAuthAndForwards()
   
     for(SyncRes::domainmap_t::const_iterator i = t_sstorage->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<uint64_t>(boost::bind(pleaseWipeCache, j->qname));
+        broadcastAccFunction<uint64_t>(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<uint64_t>(boost::bind(pleaseWipeCache, j->qname));
+        broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->d_name));
     }
 
     // this is pretty blunt
@@ -336,10 +337,11 @@ SyncRes::domainmap_t* parseAuthAndForwards()
         L<<Logger::Error<<"Parsing authoritative data for zone '"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl;
         ZoneParserTNG zpt(headers.second, DNSName(headers.first));
         DNSResourceRecord rr;
+       DNSRecord dr;
         while(zpt.get(rr)) {
           try {
-            string tmp=DNSRR2String(rr);
-            rr=String2DNSRR(rr.qname, rr.qtype, tmp, rr.ttl);
+           dr=DNSRecord(rr);
+           dr.d_place=DNSRecord::Answer;
           }
           catch(std::exception &e) {
             delete newMap;
@@ -350,7 +352,7 @@ SyncRes::domainmap_t* parseAuthAndForwards()
             throw PDNSException("Error parsing record '"+rr.qname.toString()+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'");
           }
 
-          ad.d_records.insert(rr);
+          ad.d_records.insert(dr);
         }
       }
       else {
index ce187c3155baf42cbabcdbfb887f223810ffcf65..cc211c19348a1f0ab7e6867b5783bc81facca6ba 100644 (file)
@@ -24,7 +24,7 @@ void doSecPoll(time_t* last_secpoll)
   gettimeofday(&now, 0);
   SyncRes sr(now);
   sr.d_doDNSSEC=true;
-  vector<DNSResourceRecord> ret;
+  vector<DNSRecord> 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);
     }
index 3d0bf5c514d2d8d086e9429d791788ae5569bbc6..e7327bf6aab1b481dbbdbf8d907ee57e42fe2905 100644 (file)
@@ -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());
 
index 2f0c7c788bad007dc2cede74ea9eaea3d3394e73..9b0c31396fbe2ee53b40e37391ebb214b5564fb3 100644 (file)
@@ -58,9 +58,9 @@ struct ARecordTest
   void operator()() const
   {
     vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> makeEmptyQuery()
 {
   vector<uint8_t> 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<uint8_t> makeEmptyQuery()
 vector<uint8_t> makeRootReferral()
 {
   vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> makeRootReferral()
 vector<uint8_t> makeTypicalReferral()
 {
   vector<uint8_t> 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());
index 3e8b692d35679cc3dbca8a07551f0a6410ea1def..02b9df4c047f861133ed177f7e1b1e4122105b44 100644 (file)
@@ -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<DNSResourceRecord>&ret)
+int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&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>(DNSRecordContent::mastermake(QType::PTR, 1, "localhost."));
     else
-      rr.content="127.0.0.1";
-    ret.push_back(rr);
+      dr.d_content=shared_ptr<DNSRecordContent>(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>(DNSRecordContent::mastermake(QType::TXT, 3, "\""+::arg()["version-string"]+"\""));
     else
-      rr.content="\""+s_serverID+"\"";
-    ret.push_back(rr);
+      dr.d_content=shared_ptr<DNSRecordContent>(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<DNSResourceRecord>&ret, int depth, int& res)
+bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int& res)
 {
   string prefix;
   if(doLog()) {
@@ -182,7 +185,7 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSR
   bool somedata=false;
   for(ziter=range.first; ziter!=range.second; ++ziter) {
     somedata=true;
-    if(qtype.getCode()==QType::ANY || ziter->qtype==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, vector<DNSR
   }
   if(somedata) {
     LOG(prefix<<qname.toString()<<": found record in '"<<authdomain.toString()<<"', but nothing of the right type, sending SOA"<<endl);
-    ziter=iter->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
       LOG(prefix<<qname.toString()<<": can't find SOA record '"<<authdomain.toString()<<"' in our zone!"<<endl);
@@ -206,18 +209,18 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSR
 
   LOG(prefix<<qname.toString()<<": nothing found so far in '"<<authdomain.toString()<<"', trying wildcards"<<endl);
   DNSName wcarddomain(qname);
-  while(!pdns_iequals(wcarddomain, iter->first) && wcarddomain.chopOff()) {
+  while(wcarddomain != iter->first && wcarddomain.chopOff()) {
     LOG(prefix<<qname.toString()<<": trying '*."+wcarddomain.toString()+"' in "<<authdomain.toString()<<endl);
     range=iter->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<<qname.toString()<<": in '"<<authdomain.toString()<<"', had wildcard match on '*."+wcarddomain.toString()+"'"<<endl);
@@ -227,27 +230,28 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSR
 
   DNSName nsdomain(qname);
 
-  while(nsdomain.chopOff() && !pdns_iequals(nsdomain, iter->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<<qname.toString()<<": no NS match in zone '"<<authdomain.toString()<<"' either, handing out SOA"<<endl);
-    ziter=iter->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<<qname.toString()<<": can't find SOA record '"<<authdomain.toString()<<"' in our zone!"<<endl);
+    }
     res=RCode::NXDomain;
   }
   else
@@ -305,7 +309,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const DNSName& domain,
 
   int ret;
   for(int tries = 0; tries < 3; ++tries) {
-    cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
+    //    cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
     
     if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
       EDNSLevel = 1;
@@ -317,36 +321,36 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const DNSName& domain,
     ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, res);
 
     if(ret == 0 || ret < 0) {
-      cerr<< (ret < 0 ? "Transport error" : "Timeout")<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"' (ret="<<ret<<"), no change in mode"<<endl;
+      //      cerr<< (ret < 0 ? "Transport error" : "Timeout")<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"' (ret="<<ret<<"), no change in mode"<<endl;
       return ret;
     }
     else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
       if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp)  {
-       cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"'"<<endl;
+       //      cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"'"<<endl;
         mode = EDNSStatus::NOEDNS;
         continue;
       }
       else if(!res->d_haveEDNS) {
         if(mode != EDNSStatus::EDNSIGNORANT) {
           mode = EDNSStatus::EDNSIGNORANT;
-         cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain.toString()<<"', moving to mode 3"<<endl;
+         //      cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain.toString()<<"', moving to mode 3"<<endl;
        }
       }
       else {
        mode = EDNSStatus::EDNSOK;
-       cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
+       //      cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
       }
       
     }
     if(oldmode != mode)
       ednsstatus->modeSetAt=d_now.tv_sec;
-    cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;  
+    //    cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;  
     return ret;
   }
   return ret;
 }
 
-int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
+int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
 {
   string prefix;
   if(doLog()) {
@@ -376,8 +380,8 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResou
           // filter out the good stuff from lwr.result()
 
          for(const auto& rec : lwr.d_records) {
-            if((DNSResourceRecord::Place)rec.first.d_place == DNSResourceRecord::ANSWER)
-              ret.push_back(DNSResourceRecord(rec.first));
+            if(rec.d_place == DNSRecord::Answer)
+              ret.push_back(rec);
           }
           return res;
         }
@@ -411,6 +415,7 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResou
     return 0;
 
   LOG(prefix<<qname.toString()<<": failed (res="<<res<<")"<<endl);
+  ;
   return res<0 ? RCode::ServFail : res;
 }
 
@@ -426,7 +431,7 @@ static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
 */
 vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, int depth, set<GetBestNSAnswer>& beenthere)
 {
-  typedef vector<DNSResourceRecord> res_t;
+  typedef vector<DNSRecord> res_t;
   res_t res;
 
   typedef vector<ComboAddress> ret_t;
@@ -451,19 +456,23 @@ vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, int depth, set<GetB
 
     if(!doResolve(qname, type, res,depth+1, beenthere) && !res.empty()) {  // this consults cache, OR goes out
       for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
-        if(i->qtype.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<ARecordContent>(i->d_content))
+           ret.push_back(rec->getCA(53));
+         else if(auto rec = std::dynamic_pointer_cast<AAAARecordContent>(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<DNSResourceRecord> cset;
+       vector<DNSRecord> cset;
        if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), &cset) > 0) {
-         for(set<DNSResourceRecord>::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<AAAARecordContent>(k->d_content)->getCA(53);
+             ret.push_back(ca);
            }
          }
        }
@@ -493,7 +502,7 @@ vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, int depth, set<GetB
   return ret;
 }
 
-void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
+void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
 {
   string prefix;
   DNSName subdomain(qname);
@@ -506,22 +515,22 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<D
   do {
     brokeloop=false;
     LOG(prefix<<qname.toString()<<": Checking if we have NS in cache for '"<<subdomain.toString()<<"'"<<endl);
-    set<DNSResourceRecord> ns;
+    vector<DNSRecord> ns;
     *flawedNSSet = false;
     if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) {
-      for(set<DNSResourceRecord>::const_iterator k=ns.begin();k!=ns.end();++k) {
-        if(k->ttl > (unsigned int)d_now.tv_sec ) {
-          set<DNSResourceRecord> aset;
+      for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
+        if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
+          vector<DNSRecord> 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<NSRecordContent>(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<<qname.toString()<<": NS (with ip, or non-glue) in cache for '"<<subdomain.toString()<<"' -> '"<<rr.content<<"'"<<endl);
-            LOG(prefix<<qname.toString()<<": within bailiwick: "<<DNSName(rr.content).isPartOf(subdomain) /* ugh */);
+            bestns.push_back(dr);
+            LOG(prefix<<qname.toString()<<": NS (with ip, or non-glue) in cache for '"<<subdomain.toString()<<"' -> '"<<nrr->getNS()<<"'"<<endl);
+            LOG(prefix<<qname.toString()<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
             if(!aset.empty()) {
-              LOG(",  in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<<endl);
+              LOG(",  in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
             }
             else {
               LOG(", not in cache / did not look at cache"<<endl);
@@ -529,7 +538,7 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<D
           }
           else {
             *flawedNSSet=true;
-            LOG(prefix<<qname.toString()<<": NS in cache for '"<<subdomain.toString()<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl);
+            LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
           }
         }
       }
@@ -537,12 +546,14 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<D
         GetBestNSAnswer answer;
         answer.qname=qname;
        answer.qtype=qtype.getCode();
-       BOOST_FOREACH(const DNSResourceRecord& rr, bestns)
-         answer.bestns.insert(make_pair(rr.qname, rr.content));
+       for(const auto& dr : bestns)
+         answer.bestns.insert(make_pair(dr.d_name, dr.d_content->getZoneRepresentation()));
+       // XXX we are passing a DNSName through a string here!
 
         if(beenthere.count(answer)) {
          brokeloop=true;
           LOG(prefix<<qname.toString()<<": We have NS in cache for '"<<subdomain.toString()<<"' but part of LOOP (already seen "<<answer.qname.toString()<<")! Trying less specific NS"<<endl);
+         ;
           if(doLog())
             for( set<GetBestNSAnswer>::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<D
       }
     }
     LOG(prefix<<qname.toString()<<": no valid/useful NS in cache for '"<<subdomain.toString()<<"'"<<endl);
+    ;
     if(subdomain.isRoot() && !brokeloop) {
       primeHints();
       LOG(prefix<<qname.toString()<<": reprimed the root"<<endl);
@@ -589,25 +601,25 @@ DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtyp
     else {
       for(vector<ComboAddress>::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<DNSResourceRecord> bestns;
+  vector<DNSRecord> bestns;
   getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
 
-  for(set<DNSResourceRecord>::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<NSRecordContent>(k->d_content)->getNS());
+    if(k==bestns.cbegin())
+      subdomain=k->d_name;
   }
   return subdomain;
 }
 
-bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
+bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& 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<<qname.toString()<<": Looking for CNAME cache hit of '"<<(qname.toString()+"|CNAME")<<"'"<<endl);
-  set<DNSResourceRecord> cset;
+  vector<DNSRecord> cset;
   if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME),&cset) > 0) {
 
-    for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
-      if(j->ttl>(unsigned int) d_now.tv_sec) {
-        LOG(prefix<<qname.toString()<<": Found cache CNAME hit for '"<< (qname.toString()+"|CNAME") <<"' to '"<<j->content<<"'"<<endl);
-        DNSResourceRecord rr=*j;
-        rr.ttl-=d_now.tv_sec;
-        ret.push_back(rr);
+    for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
+      if(j->d_ttl>(unsigned int) d_now.tv_sec) {
+        LOG(prefix<<qname.toString()<<": Found cache CNAME hit for '"<< (qname.toString()+"|CNAME") <<"' to '"<<j->d_content->getZoneRepresentation()<<"'"<<endl);
+        DNSRecord dr=*j;
+        dr.d_ttl-=d_now.tv_sec;
+        ret.push_back(dr);
         if(!(qtype==QType(QType::CNAME))) { // perhaps they really wanted a CNAME!
           set<GetBestNSAnswer>beenthere;
-          res=doResolve(DNSName(j->content), qtype, ret, depth+1, beenthere);
+          res=doResolve(std::dynamic_pointer_cast<CNAMERecordContent>(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<DNSResourceRecord>&ret, int depth, int &res)
+
+bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res)
 {
   bool giveNegative=false;
 
@@ -713,23 +726,23 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
       }
     }
   }
-  set<DNSResourceRecord> cset;
+  vector<DNSRecord> cset;
   bool found=false, expired=false;
   vector<std::shared_ptr<RRSIGRecordContent>> signatures;
   uint32_t ttl=0;
   if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_doDNSSEC ? &signatures : 0) > 0) {
     LOG(prefix<<sqname.toString()<<": Found cache hit for "<<sqt.getName()<<": ");
-    for(set<DNSResourceRecord>::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="<<rr.ttl<<"] ");
+        ret.push_back(dr);
+        LOG("[ttl="<<dr.d_ttl<<"] ");
         found=true;
       }
       else {
@@ -739,14 +752,14 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
     }
 
     for(const auto& signature : signatures) {
-      DNSResourceRecord rr;
-      rr.qtype=QType(QType::RRSIG);
-      rr.qname=sqname;
-      rr.ttl=ttl; 
-      rr.content=signature->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<DNSName> SyncRes::shuffleInSpeedOrder(set<DNSName> &tnameservers,
 
   if(doLog()) {
     LOG(prefix<<"Nameservers: ");
-               for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
+    for(vector<DNSName>::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<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
-                         vector<DNSResourceRecord>&ret,
+                         vector<DNSRecord>&ret,
                          int depth, set<GetBestNSAnswer>&beenthere)
 {
   string prefix;
@@ -847,13 +860,14 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         LOG(prefix<<qname.toString()<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth.toString()<<"'"<<endl);
         if(auth!=DNSName() && flawedNSSet) {
           LOG(prefix<<qname.toString()<<": Ageing nameservers for level '"<<auth.toString()<<"', next query might succeed"<<endl);
+         
           if(t_RC->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<<qname.toString()<<": Not using NS to resolve itself! ("<<(1+tns-rnameservers.begin())<<"/"<<rnameservers.size()<<")"<<endl);
         continue;
       }
@@ -868,12 +882,13 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
       LWResult lwr;
       if(tns->empty()) {
         LOG(prefix<<qname.toString()<<": Domain is out-of-band"<<endl);
-        doOOBResolve(qname, qtype, lwr.d_result, depth, lwr.d_rcode);
+        doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
         lwr.d_tcbit=false;
         lwr.d_aabit=true;
       }
       else {
         LOG(prefix<<qname.toString()<<": Trying to resolve NS '"<<tns->toString()<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
+       ;
 
         if(!isCanonical(*tns)) {
           LOG(prefix<<qname.toString()<<": Domain has hardcoded nameserver(s)"<<endl);
@@ -942,7 +957,7 @@ int SyncRes::doResolveAt(set<DNSName> 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<string>(d_timeouts) +", throttles: "+boost::lexical_cast<string>(d_throttledqueries) + ", queries: "+lexical_cast<string>(d_outqueries)+", "+lexical_cast<string>(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<<qname.toString()<<": query handled by Lua"<<endl);
            }
            else
@@ -1014,7 +1029,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
           LOG(prefix<<qname.toString()<<": truncated bit set, over TCP?"<<endl);
           return RCode::ServFail;
         }
-        LOG(prefix<<qname.toString()<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<tns->toString()<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
+        LOG(prefix<<qname.toString()<<": Got "<<(unsigned int)lwr.d_records.size()<<" answers from "<<tns->toString()<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
 
         /*  // for you IPv6 fanatics :-)
         if(remoteIP->sin4.sin_family==AF_INET6)
@@ -1027,13 +1042,13 @@ int SyncRes::doResolveAt(set<DNSName> 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<DNSResourceRecord> records;
+       vector<DNSRecord> records;
        vector<shared_ptr<RRSIGRecordContent>> signatures;
       };
       typedef map<pair<DNSName, QType>, CachePair, TCacheComp > tcache_t;
@@ -1041,29 +1056,29 @@ int SyncRes::doResolveAt(set<DNSName> 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<RRSIGRecordContent>(rec.first.d_content);
-           cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.first.d_name<<"'"<<endl;
-           tcache[make_pair(rec.first.d_name, QType(rrsig->d_type))].signatures.push_back(rrsig);
+         if(rec.d_type == QType::RRSIG) {
+           auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(rec.d_content);
+           //      cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
+           tcache[make_pair(rec.d_name, QType(rrsig->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()<<": skipping OPT answer '"<<i->qname.toString()<<"' from '"<<auth.toString()<<"' nameservers" <<endl);
+      for(auto& rec : lwr.d_records) {
+        if(rec.d_type == QType::OPT) {
+          LOG(prefix<<qname.toString()<<": skipping OPT answer '"<<rec.d_name<<"' from '"<<auth.toString()<<"' nameservers" <<endl);
           continue;
         }
-        LOG(prefix<<qname.toString()<<": accept answer '"<<i->qname.toString()<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth.toString()<<"' nameservers? ");
-        if(i->qtype.getCode()==QType::ANY) {
+        LOG(prefix<<qname.toString()<<": accept answer '"<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"|"<<rec.d_content->getZoneRepresentation()<<"' from '"<<auth.toString()<<"' nameservers? "<<(int)rec.d_place<<" ");
+        if(rec.d_type == QType::ANY) {
           LOG("NO! - we don't accept 'ANY' data"<<endl);
           continue;
         }
 
         // Check if we are authoritative for a zone in this answer
         if (!t_sstorage->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<DNSName> 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"<<endl);
             s_nodelegated++;
             return RCode::NXDomain;
           }
-         else if(i->qtype.getCode() == QType::RRSIG) {
+         else if(rec.d_type == QType::RRSIG) {
            LOG("RRSIG - separate"<<endl);
          }
           else {
             LOG("YES!"<<endl);
 
-            i->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<DNSName> 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<uint32_t>::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<uint32_t*>(&record.ttl)=lowestTTL;
+           *const_cast<uint32_t*>(&record.d_ttl)=lowestTTL; // boom
         }
 
-       cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.first.toString();
-       cout<<'|'<<DNSRecordContent::NumberToType(i->first.second.getCode())<<endl;
+       //      cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.first.toString();
+       //      cout<<'|'<<DNSRecordContent::NumberToType(i->first.second.getCode())<<endl;
         t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second.records, i->second.signatures, lwr.d_aabit);
       }
       set<DNSName> nsset;
@@ -1127,20 +1140,20 @@ int SyncRes::doResolveAt(set<DNSName> 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<<qname.toString()<<": got negative caching indication for name '"<<qname.toString()+"' (accept="<<dottedEndsOn(i->qname, auth)<<"), newtarget='"<<newtarget.toString()<<"'"<<endl);
+      for(auto& rec : lwr.d_records) {
+        if(rec.d_place==DNSRecord::Nameserver && rec.d_type==QType::SOA && 
+           lwr.d_rcode==RCode::NXDomain && dottedEndsOn(qname,rec.d_name) && dottedEndsOn(rec.d_name, auth)) {
+          LOG(prefix<<qname.toString()<<": got negative caching indication for name '"<<qname.toString()+"' (accept="<<dottedEndsOn(rec.d_name, auth)<<"), newtarget='"<<newtarget.toString()<<"'"<<endl);
 
-          i->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<DNSName> 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<<qname.toString()<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl);
+           LOG(prefix<<qname.toString()<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
 
           done=true;
-          ret.push_back(*i);
+          ret.push_back(rec);
         }
-        else if(i->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()<<": got NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
+        else if(rec.d_place==DNSRecord::Nameserver && qname.isPartOf(rec.d_name) && rec.d_type==QType::NS) {
+          if(moreSpecificThan(rec.d_name,auth)) {
+            newauth=rec.d_name;
+            LOG(prefix<<qname.toString()<<": got NS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
             realreferral=true;
           }
-          else
-            LOG(prefix<<qname.toString()<<": got upwards/level NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"', had '"<<auth.toString()<<"'"<<endl);
-          nsset.insert(DNSName(i->content));
+          else {
+            LOG(prefix<<qname.toString()<<": got upwards/level NS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth.toString()<<"'"<<endl);
+         }
+          nsset.insert(DNSName(rec.d_content->getZoneRepresentation()));
         }
-        else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::DS) { 
-         LOG(prefix<<qname.toString()<<": got DS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
+        else if(rec.d_place==DNSRecord::Nameserver && dottedEndsOn(qname,rec.d_name) && rec.d_type==QType::DS) { 
+         LOG(prefix<<qname.toString()<<": got DS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
          sawDS=true;
        }
-        else if(!done && i->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<<qname.toString()<<": got negative caching indication for '"<< (qname.toString()+"|"+qtype.getName()+"'") <<endl);
 
@@ -1195,11 +1209,11 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
             LOG(prefix<<qname.toString()<<": Hang on! Got a redirect to '"<<newtarget.toString()<<"' already"<<endl);
           }
           else {
-            i-> 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<DNSName> nameservers, DNSName auth, bool flawedNSSe
         return 0;
       }
       if(!newtarget.empty()) {
-        if(pdns_iequals(newtarget,qname)) {
+        if(newtarget == qname) {
           LOG(prefix<<qname.toString()<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
           return RCode::ServFail;
         }
@@ -1240,9 +1254,9 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         LOG(prefix<<qname.toString()<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, looping to them"<<endl);
        if(sawDS) {
          t_sstorage->dnssecmap[newauth]=true;
-         for(const auto& e : t_sstorage->dnssecmap)
+         /*      for(const auto& e : t_sstorage->dnssecmap)
            cout<<e.first.toString()<<' ';
-         cout<<endl;
+           cout<<endl;*/
        }
         auth=newauth;
         nameservers=nsset;
@@ -1258,13 +1272,13 @@ int SyncRes::doResolveAt(set<DNSName> 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<DNSResourceRecord>& ret)
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSRecord>& 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;
 }
index e9a1f5416590a33c5779558649be50a811bc4fbe..49c0b3c24fd9f77cc46f92f66d2c748d7979d6cf 100644 (file)
@@ -239,7 +239,7 @@ public:
 
   explicit SyncRes(const struct timeval& now);
 
-  int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret);
+  int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret);
   void setId(int id)
   {
     if(doLog())
@@ -394,14 +394,14 @@ public:
     vector<ComboAddress> d_servers;
     bool d_rdForward;
     typedef multi_index_container <
-      DNSResourceRecord,
+      DNSRecord,
       indexed_by <
         ordered_non_unique<
-          composite_key< DNSResourceRecord,
-                        member<DNSResourceRecord, DNSName, &DNSResourceRecord::qname>,
-                        member<DNSResourceRecord, QType, &DNSResourceRecord::qtype>
+          composite_key< DNSRecord,
+                        member<DNSRecord, DNSName, &DNSRecord::d_name>,
+                        member<DNSRecord, uint16_t, &DNSRecord::d_type>
                        >,
-          composite_key_compare<std::less<DNSName>, std::less<QType> >
+          composite_key_compare<std::less<DNSName>, std::less<uint16_t> >
         >
       >
     > records_t;
@@ -439,14 +439,14 @@ public:
 
 private:
   struct GetBestNSAnswer;
-  int doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
+  int doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret,
                  int depth, set<GetBestNSAnswer>&beenthere);
-  int doResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
-  bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
+  int doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
+  bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res);
   domainmap_t::const_iterator getBestAuthZone(DNSName* qname);
-  bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
-  bool doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
-  void getBestNSFromCache(const DNSName &qname, const QType &qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
+  bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res);
+  bool doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res);
+  void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector<DNSRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
   DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, set<DNSName>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
 
   inline vector<DNSName> shuffleInSpeedOrder(set<DNSName> &nameservers, const string &prefix);
@@ -629,7 +629,7 @@ typedef boost::function<void*(void)> 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<DNSResourceRecord>& ret);
+int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret);
 
 template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
 
index 204b43fef28a3f5ef28884fe8421f692d213a8f1..65f5026e4977c9fc4e1837cf597d0fd807fe95fe 100644 (file)
@@ -713,7 +713,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr<DNSPacket> 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<DNSPacket> 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<DNSPacket> q, int ou
       map<DNSName,bool> 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<<Logger::Warning<<"Zone '"<<target<<"' has too many empty non terminals."<<endl;
index 697dd249579789a0edbf15b0537be5dcd1c6b39a..70fd006d3c80bb2198d36d60034ad37b9e9515d8 100644 (file)
@@ -21,7 +21,6 @@ BOOST_AUTO_TEST_SUITE(test_dnsrecords_cc)
 
 typedef enum { zone, wire } case_type_enum_t;
 
-
 BOOST_AUTO_TEST_CASE(test_record_types) {
   // tuple contains <type, user value, zone representation, line value, broken>
   typedef boost::tuple<const QType::typeenum, const std::string, const std::string, const std::string, bool> case_t;
index 01c6ef705b5239edc0fa46d42be305333d7f9e9a..402af0f04a0361bd70f5105dd44a49f388c67eca 100644 (file)
@@ -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);
           }
         }
index b9082ed925dda9477073120dd2683dc7b60c690e..49da6d1cfc53c88320d6b0232e5a3dcdd896b491 100644 (file)
@@ -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());