#include <signal.h>
#include "lmdbbackend.hh"
#include <pdns/arguments.hh>
+#include <pdns/base32.hh>
#if 0
#define DEBUGLOG(msg) L<<Logger::Error<<msg
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 )
/* 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) ) {
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 *);
};
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);
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()
{
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);
bool doNextcloser = false;
string unhashed, hashed, before, after;
string closest;
+ DNSResourceRecord rr;
if (mode == 2 || mode == 3 || mode == 4) {
closest=wildcard;
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);
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
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
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);
}
}
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()
{
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);
#include <unistd.h>
#include <boost/foreach.hpp>
#include <lmdb.h>
+#include "base32.hh"
StatBag S;
int g_numZones=0;
}
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();