]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
get NSECx direct from backend and use it for lmdb-backend
authorKees Monshouwer <mind04@monshouwer.org>
Fri, 30 May 2014 18:54:10 +0000 (20:54 +0200)
committermind04 <mind04@monshouwer.org>
Tue, 24 Jun 2014 16:23:28 +0000 (18:23 +0200)
modules/lmdbbackend/lmdbbackend.cc
modules/lmdbbackend/lmdbbackend.hh
pdns/dnsbackend.hh
pdns/misc.cc
pdns/misc.hh
pdns/packethandler.cc
pdns/ueberbackend.cc
pdns/ueberbackend.hh
pdns/zone2lmdb.cc

index 0a2e470cc0b225446f737080acfb06ef9676cc6a..68e9c8c5ef0b73a086f4c22b306685e47a113890 100644 (file)
@@ -21,6 +21,7 @@
 #include <signal.h>
 #include "lmdbbackend.hh"
 #include <pdns/arguments.hh>
+#include <pdns/base32.hh>
 
 #if 0
 #define DEBUGLOG(msg) L<<Logger::Error<<msg
@@ -111,6 +112,77 @@ void LMDBBackend::reload() {
     open_db();
 }
 
+bool LMDBBackend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
+{
+  if (kind == "PRESIGNED") {
+    meta.push_back("1");
+  } else if (kind == "NSEC3PARAM") {
+    meta.push_back("1 0 1 abcd");
+  }
+  return true;
+}
+
+bool LMDBBackend::getDirectNSECx(uint32_t id, const string &hashed, string &before, DNSResourceRecord &rr)
+{
+  MDB_val key, data;
+  string key_str, cur_key, cur_value;
+  vector<string> keyparts, valparts;
+
+  key_str=itoa(id)+"\t"+toBase32Hex(bitFlip(hashed));
+  key.mv_data = (char *)key_str.c_str();
+  key.mv_size = key_str.length();
+
+  before.clear();
+  if(!mdb_cursor_get(nsecx_cursor, &key, &data, MDB_SET_RANGE)) {
+    cur_key.assign((const char *)key.mv_data, key.mv_size);
+    cur_value.assign((const char *)data.mv_data, data.mv_size);
+    stringtok(keyparts,cur_key,"\t");
+    stringtok(valparts,cur_value,"\t");
+
+    if( keyparts.size() != 2 || valparts.size() != 4 ) {
+      throw PDNSException("Invalid record in nsecx table: key: '" + cur_key + "'; value: "+ cur_value);
+    }
+
+    // is the key a full match or does the id part match our zone?
+    // if it does we have a valid answer.
+    if (!key_str.compare(cur_key) || atoi(keyparts[0].c_str()) == (int) id) // FIXME need atoui
+      goto hasnsecx;
+  }
+  // no match, now we look for the last record in the NSECx chain.
+  key_str=itoa(id)+"\t";
+  key.mv_data = (char *)key_str.c_str();
+  key.mv_size = key_str.length();
+
+  if(!mdb_cursor_get(nsecx_cursor, &key, &data, MDB_SET_RANGE)) {
+    cur_key.assign((const char *)key.mv_data, key.mv_size);
+    cur_value.assign((const char *)data.mv_data, data.mv_size);
+    stringtok(keyparts,cur_key,"\t");
+    stringtok(valparts,cur_value,"\t");
+
+    if( keyparts.size() != 2 || valparts.size() != 4 ) {
+      throw PDNSException("Invalid record in nsecx table: key: '" + cur_key + "'; value: "+ cur_value);
+    }
+
+    if (!key_str.compare(cur_key) || atoi(keyparts[0].c_str()) == (int) id) // FIXME we need atoui
+      goto hasnsecx;
+  }
+
+  DEBUGLOG("NSECx record for '"<<toBase32Hex(bitFlip(hashed))<<"'' in zone '"<<id<<"' not found"<<endl);
+  return true;
+
+hasnsecx:
+
+  before=bitFlip(fromBase32Hex(keyparts[1]));
+  rr.qname=valparts[0];
+  rr.ttl=atoi(valparts[1].c_str());
+  rr.qtype=DNSRecordContent::TypeToNumber(valparts[2]);
+  rr.content=valparts[3];
+  rr.d_place=DNSResourceRecord::AUTHORITY;
+  rr.auth=true;
+
+  return true;
+}
+
 // Get the zone name and value of the requested zone (reversed) OR the entry
 // just before where it should have been
 bool LMDBBackend::getAuthZone( string &rev_zone )
@@ -139,7 +211,7 @@ bool LMDBBackend::getAuthZone( string &rev_zone )
 
     /* Only skip this bit if we got an exact hit on the SOA or if the key is a shoter
      * version of rev_zone. Otherwise we have to go back to the previous record */
-    if( orig.compare( 0, rev_zone.length(), rev_zone ) != 0 ) {
+    if( orig.compare( rev_zone ) != 0 ) {
         /* Skip back 1 entry to what should be a substring of what was searched
          * for (or a totally different entry) */
         if( mdb_cursor_get(zone_cursor, &key, &data, MDB_PREV) ) {
index ba881941e21f06b2a432bd9eab43153243858a43..7ddd277954790c4b5485c2bc42f17fb1f6843712 100644 (file)
@@ -45,6 +45,9 @@ public:
     void reload();
     bool get(DNSResourceRecord &rr);
 
+    bool getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta);
+    bool getDirectNSECx(uint32_t id, const string &hashed, string &before, DNSResourceRecord &rr);
+
     bool getAuthZone( string &rev_zone );
     bool getAuthData( SOAData &, DNSPacket *);
 };
index 0024925b5491e2ac1d4ccc0cc03686d42ba5ee11..b035d83e5a81fcdcadec7b63ba17ca4a05525319 100644 (file)
@@ -363,6 +363,17 @@ public:
     return false;
   }
 
+  //! called to get a NSECx record from backend
+  virtual bool getDirectNSECx(uint32_t id, const string &hashed, string &before, DNSResourceRecord &rr)
+  {
+    return false;
+  }
+  //! called to get RRSIG record(s) from backend
+  virtual bool getDirectRRSIGs(uint32_t id, const string &qname, const QType &qtype, const vector<DNSResourceRecord>&rrs)
+  {
+    return false;
+  }
+
 protected:
   bool mustDo(const string &key);
   const string &getArg(const string &key);
index 70f81170fbba4beb0c4373dfc39af4828f77974f..a43030ba6f28506dc1e5631146d34ed532061737 100644 (file)
@@ -434,6 +434,15 @@ string uitoa(unsigned int i) // MSVC 6 doesn't grok overloading (un)signed
   return o.str();
 }
 
+string bitFlip(const string &str)
+{
+  string::size_type pos=0, epos=str.size();
+  string ret;
+  ret.reserve(epos);
+  for(;pos < epos; ++pos)
+    ret.append(1, ~str[pos]);
+  return ret;
+}
 
 string stringerror()
 {
index 4712e28ac185e050831998487b5e9f45f2292c85..a503f8da68788cc2e322ae48d378f17736347d34 100644 (file)
@@ -171,6 +171,7 @@ string stringerror();
 string netstringerror();
 string itoa(int i);
 string uitoa(unsigned int i);
+string bitFlip(const string &str);
 
 void dropPrivs(int uid, int gid);
 int makeGidNumeric(const string &group);
index 4f260df9281d837825cf9022fc7208bc943b6d2a..d08b90fbc9ed3c8d669121b2bdf5f4ef45731c31 100644 (file)
@@ -633,6 +633,7 @@ void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const string& target, c
   bool doNextcloser = false;
   string unhashed, hashed, before, after;
   string closest;
+  DNSResourceRecord rr;
 
   if (mode == 2 || mode == 3 || mode == 4) {
     closest=wildcard;
@@ -648,7 +649,8 @@ void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const string& target, c
     hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
     DLOG(L<<"1 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
 
-    getNSEC3Hashes(narrow, sd.db, sd.domain_id,  hashed, false, unhashed, before, after, mode);
+    if(!B.getDirectNSECx(sd.domain_id, hashed, before, rr))
+      getNSEC3Hashes(narrow, sd.db, sd.domain_id,  hashed, false, unhashed, before, after, mode);
 
     if (((mode == 0 && ns3rc.d_flags) ||  mode == 1) && (hashed != before)) {
       DLOG(L<<"No matching NSEC3, do closest (provable) encloser"<<endl);
@@ -668,11 +670,15 @@ void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const string& target, c
       hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
       DLOG(L<<"1 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
 
-      getNSEC3Hashes(narrow, sd.db, sd.domain_id,  hashed, false, unhashed, before, after);
+      if(!B.getDirectNSECx(sd.domain_id, hashed, before, rr))
+        getNSEC3Hashes(narrow, sd.db, sd.domain_id,  hashed, false, unhashed, before, after);
     }
 
-    DLOG(L<<"Done calling for matching, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
-    emitNSEC3(ns3rc, sd, unhashed, before, after, target, r, mode);
+    if (!after.empty()) {
+      DLOG(L<<"Done calling for matching, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
+      emitNSEC3(ns3rc, sd, unhashed, before, after, target, r, mode);
+    } else if(!before.empty())
+      r->addRecord(rr);
   }
 
   // add covering NSEC3 RR
@@ -685,10 +691,12 @@ void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const string& target, c
 
     hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
     DLOG(L<<"2 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
-
-    getNSEC3Hashes(narrow, sd.db,sd.domain_id,  hashed, true, unhashed, before, after);
-    DLOG(L<<"Done calling for covering, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
-    emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+    if(!B.getDirectNSECx(sd.domain_id, hashed, before, rr)) {
+      getNSEC3Hashes(narrow, sd.db,sd.domain_id,  hashed, true, unhashed, before, after);
+      DLOG(L<<"Done calling for covering, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
+      emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+    } else if(!before.empty())
+      r->addRecord(rr);
   }
 
   // wildcard denial
@@ -698,9 +706,12 @@ void PacketHandler::addNSEC3(DNSPacket *p, DNSPacket *r, const string& target, c
     hashed=hashQNameWithSalt(ns3rc.d_iterations, ns3rc.d_salt, unhashed);
     DLOG(L<<"3 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
 
-    getNSEC3Hashes(narrow, sd.db, sd.domain_id,  hashed, (mode != 2), unhashed, before, after);
-    DLOG(L<<"Done calling for '*', hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
-    emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+    if(!B.getDirectNSECx(sd.domain_id, hashed, before, rr)) {
+      getNSEC3Hashes(narrow, sd.db, sd.domain_id,  hashed, (mode != 2), unhashed, before, after);
+      DLOG(L<<"Done calling for '*', hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
+      emitNSEC3( ns3rc, sd, unhashed, before, after, target, r, mode);
+    } else if(!before.empty())
+      r->addRecord(rr);
   }
 }
 
index 08bac7d5dbb9ccb405df7d24d7d26edb3321e5fd..37098f2fe059bb1c654a4ae80907e1dea57ac83c 100644 (file)
@@ -235,6 +235,24 @@ bool UeberBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
   return true;
 }
 
+bool UeberBackend::getDirectNSECx(uint32_t id, const string &hashed, string &before, DNSResourceRecord &rr)
+{
+  BOOST_FOREACH(DNSBackend* db, backends) {
+    if(db->getDirectNSECx(id, hashed, before, rr))
+      return true;
+  }
+  return false;
+}
+
+bool UeberBackend::getDirectRRSIGs(uint32_t id, const string &qname, const QType &qtype, const vector<DNSResourceRecord>&rrs)
+{
+  BOOST_FOREACH(DNSBackend* db, backends) {
+    if(db->getDirectRRSIGs(id, qname, qtype, rrs))
+      return true;
+  }
+  return false;
+}
+
 /* Called from anywhere to signal a reload of all backend databases */
 void UeberBackend::reload_all()
 {
index 53eef920ca4d845c272e71c3c13598b97f6399f3..23bea196dae7a24011946247048825939956a4bd 100644 (file)
@@ -144,6 +144,9 @@ public:
   bool activateDomainKey(const string& name, unsigned int id);
   bool deactivateDomainKey(const string& name, unsigned int id);
 
+  bool getDirectNSECx(uint32_t id, const string &hashed, string &before, DNSResourceRecord &rr);
+  bool getDirectRRSIGs(uint32_t id, const string &qname, const QType &qtype, const vector<DNSResourceRecord>&rrs);
+
   bool getTSIGKey(const string& name, string* algorithm, string* content);
   bool setTSIGKey(const string& name, const string& algorithm, const string& content);
   bool deleteTSIGKey(const string& name);
index 2741868527749c8bd05210a764645006d7d5d087..a7d84c4e4f658af541d57324393ebd44f7391e08 100644 (file)
@@ -42,6 +42,7 @@
 #include <unistd.h>
 #include <boost/foreach.hpp>
 #include <lmdb.h>
+#include "base32.hh"
 
 StatBag S;
 int g_numZones=0;
@@ -117,8 +118,11 @@ void emitData(string zone, ZoneParserTNG &zpt){
     }
 
     if (rr.qtype == QType::NSEC || rr.qtype == QType::NSEC3) {
-      keyStr=stripDot(rr.qname)+"\t"+itoa(g_numZones+1);
-      dataStr=itoa(rr.ttl)+"\t"+rr.content;
+      if (rr.qtype == QType::NSEC)
+        keyStr=stripDot(rr.qname)+"\t"+itoa(g_numZones+1);
+      else
+        keyStr=itoa(g_numZones+1)+"\t"+toBase32Hex(bitFlip(fromBase32Hex(makeRelative(stripDot(rr.qname), zone))));
+      dataStr=rr.qname+"\t"+itoa(rr.ttl)+"\t"+rr.qtype.getName()+"\t"+rr.content;
 
       key.mv_data = (char*)keyStr.c_str();
       key.mv_size = keyStr.length();