CDB::CDB(const string &cdbfile)
{
-
- d_fd = open(cdbfile.c_str(), O_RDONLY);
- if (d_fd < 0)
- {
- L<<Logger::Error<<"Failed to open cdb database file '"<<cdbfile<<"'. Error: "<<stringerror()<<endl;
- throw new PDNSException("Failed to open cdb database file '"+cdbfile+"'. Error: " + stringerror());
- }
-
- int cdbinit = cdb_init(&d_cdb, d_fd);
- if (cdbinit < 0)
- {
- L<<Logger::Error<<"Failed to initialize cdb structure. ErrorNr: '"<<cdbinit<<endl;
- throw new PDNSException("Failed to initialize cdb structure.");
- }
+ d_fd = open(cdbfile.c_str(), O_RDONLY);
+ if (d_fd < 0)
+ {
+ L<<Logger::Error<<"Failed to open cdb database file '"<<cdbfile<<"'. Error: "<<stringerror()<<endl;
+ throw new PDNSException("Failed to open cdb database file '"+cdbfile+"'. Error: " + stringerror());
+ }
+
+ int cdbinit = cdb_init(&d_cdb, d_fd);
+ if (cdbinit < 0)
+ {
+ L<<Logger::Error<<"Failed to initialize cdb structure. ErrorNr: '"<<cdbinit<<endl;
+ throw new PDNSException("Failed to initialize cdb structure.");
+ }
}
CDB::~CDB() {
- cdb_free(&d_cdb);
- close(d_fd);
+ cdb_free(&d_cdb);
+ close(d_fd);
}
int CDB::searchKey(const string &key) {
- d_searchType = SearchKey;
+ d_searchType = SearchKey;
- // A 'bug' in tinycdb (the lib used for reading the CDB files) means we have to copy the key because the cdb_find struct
- // keeps a pointer to it.
- d_key = strdup(key.c_str());
- return cdb_findinit(&d_cdbf, &d_cdb, d_key, key.size());
+ // A 'bug' in tinycdb (the lib used for reading the CDB files) means we have to copy the key because the cdb_find struct
+ // keeps a pointer to it.
+ d_key = strdup(key.c_str());
+ return cdb_findinit(&d_cdbf, &d_cdb, d_key, key.size());
}
bool CDB::searchSuffix(const string &key) {
- d_searchType = SearchSuffix;
+ d_searchType = SearchSuffix;
- //See CDB::searchKey()
- d_key = strdup(key.c_str());
+ //See CDB::searchKey()
+ d_key = strdup(key.c_str());
- // We are ok with a search on things, but we do want to know if a record with that key exists.........
- bool hasDomain = (cdb_find(&d_cdb, key.c_str(), key.size()) == 1);
- if (hasDomain) {
- cdb_seqinit(&d_seqPtr, &d_cdb);
- }
+ // We are ok with a search on things, but we do want to know if a record with that key exists.........
+ bool hasDomain = (cdb_find(&d_cdb, key.c_str(), key.size()) == 1);
+ if (hasDomain) {
+ cdb_seqinit(&d_seqPtr, &d_cdb);
+ }
- return hasDomain;
+ return hasDomain;
}
void CDB::searchAll() {
- d_searchType = SearchAll;
- cdb_seqinit(&d_seqPtr, &d_cdb);
+ d_searchType = SearchAll;
+ cdb_seqinit(&d_seqPtr, &d_cdb);
}
bool CDB::moveToNext() {
- int hasNext = 0;
- if (d_searchType == SearchKey) {
- hasNext = cdb_findnext(&d_cdbf);
- } else {
- hasNext = cdb_seqnext(&d_seqPtr, &d_cdb);
- }
- return (hasNext > 0);
+ int hasNext = 0;
+ if (d_searchType == SearchKey) {
+ hasNext = cdb_findnext(&d_cdbf);
+ } else {
+ hasNext = cdb_seqnext(&d_seqPtr, &d_cdb);
+ }
+ return (hasNext > 0);
}
bool CDB::readNext(pair<string, string> &value) {
- while (moveToNext()) {
- unsigned int pos;
- unsigned int len;
-
- pos = cdb_keypos(&d_cdb);
- len = cdb_keylen(&d_cdb);
-
- char *key = (char *)malloc(len);
- cdb_read(&d_cdb, key, len, pos);
-
- if (d_searchType == SearchSuffix) {
- char *p = strstr(key, d_key);
- if (p == NULL) {
- free(key);
- continue;
- }
- }
- string skey(key, len);
- free(key);
-
- pos = cdb_datapos(&d_cdb);
- len = cdb_datalen(&d_cdb);
- char *val = (char *)malloc(len);
- cdb_read(&d_cdb, val, len, pos);
- string sval(val, len);
- free(val);
-
- value = make_pair(skey, sval);
- return true;
- }
- // We're done searching, so we can clean up d_key
- if (d_searchType != SearchAll) {
- free(d_key);
- }
- return false;
+ while (moveToNext()) {
+ unsigned int pos;
+ unsigned int len;
+
+ pos = cdb_keypos(&d_cdb);
+ len = cdb_keylen(&d_cdb);
+
+ char *key = (char *)malloc(len);
+ cdb_read(&d_cdb, key, len, pos);
+
+ if (d_searchType == SearchSuffix) {
+ char *p = strstr(key, d_key);
+ if (p == NULL) {
+ free(key);
+ continue;
+ }
+ }
+ string skey(key, len);
+ free(key);
+
+ pos = cdb_datapos(&d_cdb);
+ len = cdb_datalen(&d_cdb);
+ char *val = (char *)malloc(len);
+ cdb_read(&d_cdb, val, len, pos);
+ string sval(val, len);
+ free(val);
+
+ value = make_pair(skey, sval);
+ return true;
+ }
+ // We're done searching, so we can clean up d_key
+ if (d_searchType != SearchAll) {
+ free(d_key);
+ }
+ return false;
}
-
vector<string> CDB::findall(string &key)
{
- vector<string> ret;
- struct cdb_find cdbf;
-
- cdb_findinit(&cdbf, &d_cdb, key.c_str(), key.size());
- int x=0;
- while(cdb_findnext(&cdbf) > 0) {
- x++;
- unsigned int vpos = cdb_datapos(&d_cdb);
- unsigned int vlen = cdb_datalen(&d_cdb);
- char *val = (char *)malloc(vlen);
- cdb_read(&d_cdb, val, vlen, vpos);
- string sval(val, vlen);
- ret.push_back(sval);
- free(val);
- }
- return ret;
+ vector<string> ret;
+ struct cdb_find cdbf;
+
+ cdb_findinit(&cdbf, &d_cdb, key.c_str(), key.size());
+ int x=0;
+ while(cdb_findnext(&cdbf) > 0) {
+ x++;
+ unsigned int vpos = cdb_datapos(&d_cdb);
+ unsigned int vlen = cdb_datalen(&d_cdb);
+ char *val = (char *)malloc(vlen);
+ cdb_read(&d_cdb, val, vlen, vpos);
+ string sval(val, vlen);
+ ret.push_back(sval);
+ free(val);
+ }
+ return ret;
}
#include <utility>
#include <boost/foreach.hpp>
-
static string backendname="[TinyDNSBackend] ";
uint32_t TinyDNSBackend::s_lastId;
pthread_mutex_t TinyDNSBackend::s_domainInfoLock=PTHREAD_MUTEX_INITIALIZER;
TinyDNSBackend::TDI_suffix_t TinyDNSBackend::s_domainInfo;
-
vector<string> TinyDNSBackend::getLocations()
{
- vector<string> ret;
-
- if (! d_dnspacket) {
- return ret;
- }
-
- //TODO: We do not have IPv6 support.
- Netmask remote = d_dnspacket->getRealRemote();
- if (remote.getBits() != 32) {
- return ret;
- }
-
- unsigned long addr = remote.getNetwork().sin4.sin_addr.s_addr;
-
- char key[6];
- key[0] = '\000';
- key[1] = '\045';
- key[2] = (addr )&0xff;
- key[3] = (addr >> 8)&0xff;
- key[4] = (addr >> 16)&0xff;
- key[5] = (addr >> 24)&0xff;
-
- for (int i=4;i>=0;i--) {
- string searchkey(key, i+2);
- CDB *reader = new CDB(getArg("dbfile"));
- ret = reader->findall(searchkey);
- delete reader;
-
- //Biggest item wins, so when we find something, we can jump out.
- if (ret.size() > 0) {
- break;
- }
- }
-
- return ret;
+ vector<string> ret;
+
+ if (! d_dnspacket) {
+ return ret;
+ }
+
+ //TODO: We do not have IPv6 support.
+ Netmask remote = d_dnspacket->getRealRemote();
+ if (remote.getBits() != 32) {
+ return ret;
+ }
+
+ unsigned long addr = remote.getNetwork().sin4.sin_addr.s_addr;
+
+ char key[6];
+ key[0] = '\000';
+ key[1] = '\045';
+ key[2] = (addr )&0xff;
+ key[3] = (addr >> 8)&0xff;
+ key[4] = (addr >> 16)&0xff;
+ key[5] = (addr >> 24)&0xff;
+
+ for (int i=4;i>=0;i--) {
+ string searchkey(key, i+2);
+ CDB *reader = new CDB(getArg("dbfile"));
+ ret = reader->findall(searchkey);
+ delete reader;
+
+ //Biggest item wins, so when we find something, we can jump out.
+ if (ret.size() > 0) {
+ break;
+ }
+ }
+
+ return ret;
}
TinyDNSBackend::TinyDNSBackend(const string &suffix)
{
- setArgPrefix("tinydns"+suffix);
- d_suffix = suffix;
- d_locations = mustDo("locations");
- d_ignorebogus = mustDo("ignore-bogus-records");
- d_taiepoch = 4611686018427387904ULL + getArgAsNum("tai-adjust");
- d_dnspacket = NULL;
- d_cdbReader = NULL;
- d_isAxfr = false;
- d_isWildcardQuery = false;
+ setArgPrefix("tinydns"+suffix);
+ d_suffix = suffix;
+ d_locations = mustDo("locations");
+ d_ignorebogus = mustDo("ignore-bogus-records");
+ d_taiepoch = 4611686018427387904ULL + getArgAsNum("tai-adjust");
+ d_dnspacket = NULL;
+ d_cdbReader = NULL;
+ d_isAxfr = false;
+ d_isWildcardQuery = false;
}
void TinyDNSBackend::getUpdatedMasters(vector<DomainInfo>* retDomains) {
- Lock l(&s_domainInfoLock); //TODO: We could actually lock less if we do it per suffix.
-
- if (! s_domainInfo.count(d_suffix)) {
- TDI_t tmp;
- s_domainInfo.insert( make_pair(d_suffix,tmp) );
- }
- TDI_t *domains = &s_domainInfo[d_suffix];
-
- vector<DomainInfo> allDomains;
- getAllDomains(&allDomains);
- if (domains->size() == 0 && !mustDo("notify-on-startup")) {
- for (vector<DomainInfo>::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) {
- di->notified_serial = 0;
- }
- }
-
- for(vector<DomainInfo>::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) {
- TDIByZone_t& zone_index = domains->get<tag_zone>();
- TDIByZone_t::iterator itByZone = zone_index.find(di->zone);
- if (itByZone == zone_index.end()) {
- s_lastId++;
-
- TinyDomainInfo tmp;
- tmp.zone = di->zone;
- tmp.id = s_lastId;
- tmp.notified_serial = di->serial;
- domains->insert(tmp);
-
- di->id = s_lastId;
- if (di->notified_serial > 0) {
- retDomains->push_back(*di);
- }
- } else {
- if (itByZone->notified_serial < di->serial) {
- di->id = itByZone->id;
- retDomains->push_back(*di);
- }
- }
- }
+ Lock l(&s_domainInfoLock); //TODO: We could actually lock less if we do it per suffix.
+
+ if (! s_domainInfo.count(d_suffix)) {
+ TDI_t tmp;
+ s_domainInfo.insert( make_pair(d_suffix,tmp) );
+ }
+
+ TDI_t *domains = &s_domainInfo[d_suffix];
+
+ vector<DomainInfo> allDomains;
+ getAllDomains(&allDomains);
+ if (domains->size() == 0 && !mustDo("notify-on-startup")) {
+ for (vector<DomainInfo>::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) {
+ di->notified_serial = 0;
+ }
+ }
+
+ for(vector<DomainInfo>::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) {
+ TDIByZone_t& zone_index = domains->get<tag_zone>();
+ TDIByZone_t::iterator itByZone = zone_index.find(di->zone);
+ if (itByZone == zone_index.end()) {
+ s_lastId++;
+
+ TinyDomainInfo tmp;
+ tmp.zone = di->zone;
+ tmp.id = s_lastId;
+ tmp.notified_serial = di->serial;
+ domains->insert(tmp);
+
+ di->id = s_lastId;
+ if (di->notified_serial > 0) {
+ retDomains->push_back(*di);
+ }
+ } else {
+ if (itByZone->notified_serial < di->serial) {
+ di->id = itByZone->id;
+ retDomains->push_back(*di);
+ }
+ }
+ }
}
void TinyDNSBackend::setNotified(uint32_t id, uint32_t serial) {
- Lock l(&s_domainInfoLock);
- if (!s_domainInfo.count(d_suffix)) {
- throw new PDNSException("Can't get list of domains to set the serial.");
- }
- TDI_t *domains = &s_domainInfo[d_suffix];
- TDIById_t& domain_index = domains->get<tag_domainid>();
- TDIById_t::iterator itById = domain_index.find(id);
- if (itById == domain_index.end()) {
- L<<Logger::Error<<backendname<<"Received updated serial("<<serial<<"), but domain ID ("<<id<<") is not known in this backend."<<endl;
- } else {
- DLOG(L<<Logger::Debug<<backendname<<"Setting serial for "<<itById->zone<<" to "<<serial<<endl);
- domain_index.modify(itById, TDI_SerialModifier(serial));
- }
- s_domainInfo[d_suffix] = *domains;
+ Lock l(&s_domainInfoLock);
+ if (!s_domainInfo.count(d_suffix)) {
+ throw new PDNSException("Can't get list of domains to set the serial.");
+ }
+ TDI_t *domains = &s_domainInfo[d_suffix];
+ TDIById_t& domain_index = domains->get<tag_domainid>();
+ TDIById_t::iterator itById = domain_index.find(id);
+ if (itById == domain_index.end()) {
+ L<<Logger::Error<<backendname<<"Received updated serial("<<serial<<"), but domain ID ("<<id<<") is not known in this backend."<<endl;
+ } else {
+ DLOG(L<<Logger::Debug<<backendname<<"Setting serial for "<<itById->zone<<" to "<<serial<<endl);
+ domain_index.modify(itById, TDI_SerialModifier(serial));
+ }
+ s_domainInfo[d_suffix] = *domains;
}
void TinyDNSBackend::getAllDomains(vector<DomainInfo> *domains, bool include_disabled) {
- d_isAxfr=true;
- d_dnspacket = NULL;
-
- d_cdbReader=new CDB(getArg("dbfile"));
- d_cdbReader->searchAll();
- DNSResourceRecord rr;
-
- while (get(rr)) {
- if (rr.qtype.getCode() == QType::SOA) {
- SOAData sd;
- fillSOAData(rr.content, sd);
-
- DomainInfo di;
- di.id = -1; //TODO: Check if this is ok.
- di.backend=this;
- di.zone = rr.qname;
- di.serial = sd.serial;
- di.notified_serial = sd.serial;
- di.kind = DomainInfo::Master;
- di.last_check = time(0);
- domains->push_back(di);
- }
- }
+ d_isAxfr=true;
+ d_dnspacket = NULL;
+
+ d_cdbReader=new CDB(getArg("dbfile"));
+ d_cdbReader->searchAll();
+ DNSResourceRecord rr;
+
+ while (get(rr)) {
+ if (rr.qtype.getCode() == QType::SOA) {
+ SOAData sd;
+ fillSOAData(rr.content, sd);
+
+ DomainInfo di;
+ di.id = -1; //TODO: Check if this is ok.
+ di.backend=this;
+ di.zone = rr.qname;
+ di.serial = sd.serial;
+ di.notified_serial = sd.serial;
+ di.kind = DomainInfo::Master;
+ di.last_check = time(0);
+ domains->push_back(di);
+ }
+ }
}
bool TinyDNSBackend::list(const DNSName &target, int domain_id, bool include_disabled) {
- d_isAxfr=true;
- string key = target.toDNSString(); // FIXME400 bug: no lowercase here? or promise that from core?
- d_cdbReader=new CDB(getArg("dbfile"));
- return d_cdbReader->searchSuffix(key);
+ d_isAxfr=true;
+ string key = target.toDNSString(); // FIXME400 bug: no lowercase here? or promise that from core?
+ d_cdbReader=new CDB(getArg("dbfile"));
+ return d_cdbReader->searchSuffix(key);
}
void TinyDNSBackend::lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p, int zoneId) {
- d_isAxfr = false;
- string queryDomain = toLowerCanonic(qdomain.toString());
+ d_isAxfr = false;
+ string queryDomain = toLowerCanonic(qdomain.toString());
- string key=simpleCompress(queryDomain);
+ string key=simpleCompress(queryDomain);
- DLOG(L<<Logger::Debug<<backendname<<"[lookup] query for qtype ["<<qtype.getName()<<"] qdomain ["<<qdomain<<"]"<<endl);
- DLOG(L<<Logger::Debug<<"[lookup] key ["<<makeHexDump(key)<<"]"<<endl);
+ DLOG(L<<Logger::Debug<<backendname<<"[lookup] query for qtype ["<<qtype.getName()<<"] qdomain ["<<qdomain<<"]"<<endl);
+ DLOG(L<<Logger::Debug<<"[lookup] key ["<<makeHexDump(key)<<"]"<<endl);
- d_isWildcardQuery = false;
- if (key[0] == '\001' && key[1] == '\052') {
- d_isWildcardQuery = true;
- key.erase(0,2);
- }
+ d_isWildcardQuery = false;
+ if (key[0] == '\001' && key[1] == '\052') {
+ d_isWildcardQuery = true;
+ key.erase(0,2);
+ }
- d_qtype=qtype;
+ d_qtype=qtype;
- d_cdbReader=new CDB(getArg("dbfile"));
- d_cdbReader->searchKey(key);
- d_dnspacket = pkt_p;
+ d_cdbReader=new CDB(getArg("dbfile"));
+ d_cdbReader->searchKey(key);
+ d_dnspacket = pkt_p;
}
bool TinyDNSBackend::get(DNSResourceRecord &rr)
{
- pair<string, string> record;
-
- while (d_cdbReader->readNext(record)) {
- string val = record.second;
- string key = record.first;
-
- //DLOG(L<<Logger::Debug<<"[GET] Key: "<<makeHexDump(key)<<endl);
- //DLOG(L<<Logger::Debug<<"[GET] Val: "<<makeHexDump(val)<<endl);
- if (key[0] == '\000' && key[1] == '\045') { // skip locations
- continue;
- }
-
- if (!d_isAxfr) {
- // If we have a wildcard query, but the record we got is not a wildcard, we skip.
- if (d_isWildcardQuery && val[2] != '\052' && val[2] != '\053') {
- continue;
- }
-
- // If it is NOT a wildcard query, but we do find a wildcard record, we skip it.
- if (!d_isWildcardQuery && (val[2] == '\052' || val[2] == '\053')) {
- continue;
- }
- }
-
-
- vector<uint8_t> bytes;
- const char *sval = val.c_str();
- unsigned int len = val.size();
- bytes.resize(len);
- copy(sval, sval+len, bytes.begin());
- PacketReader pr(bytes);
- rr.qtype = QType(pr.get16BitInt());
-
- if(d_isAxfr || d_qtype.getCode() == QType::ANY || rr.qtype == d_qtype) {
- char locwild = pr.get8BitInt();
- if(locwild != '\075' && (locwild == '\076' || locwild == '\053')) {
- if (d_isAxfr && d_locations) { // We skip records with a location in AXFR, unless we disable locations.
- continue;
- }
- char recloc[2];
- recloc[0] = pr.get8BitInt();
- recloc[1] = pr.get8BitInt();
-
- if (d_locations) {
- bool foundLocation = false;
- vector<string> locations = getLocations();
- while(locations.size() > 0) {
- string locId = locations.back();
- locations.pop_back();
-
- if (recloc[0] == locId[0] && recloc[1] == locId[1]) {
- foundLocation = true;
- break;
- }
- }
- if (!foundLocation) {
- continue;
- }
- }
- }
-
- if (d_isAxfr && (val[2] == '\052' || val[2] == '\053' )) { // Keys are not stored with wildcard character, with AXFR we need to add that.
- key.insert(0, 1, '\052');
- key.insert(0, 1, '\001');
- }
- // rr.qname.clear();
- rr.qname=DNSName(key.c_str(), key.size(), 0, false);
- rr.domain_id=-1;
- // 11:13.21 <@ahu> IT IS ALWAYS AUTH --- well not really because we are just a backend :-)
- // We could actually do NSEC3-NARROW DNSSEC according to Habbie, if we do, we need to change something ehre.
- rr.auth = true;
-
- rr.ttl = pr.get32BitInt();
- uint64_t timestamp = pr.get32BitInt();
- timestamp <<= 32;
- timestamp += pr.get32BitInt();
- if(timestamp) {
- uint64_t now = d_taiepoch + time(NULL);
- if (rr.ttl == 0) {
- if (timestamp < now) {
- continue;
- }
- rr.ttl = timestamp - now;
- } else if (now <= timestamp) {
- continue;
- }
- }
- try {
- DNSRecord dr;
- dr.d_class = 1;
- dr.d_type = rr.qtype.getCode();
- dr.d_clen = val.size()-pr.d_pos;
-
- DNSRecordContent *drc = DNSRecordContent::mastermake(dr, pr);
- rr.content = drc->getZoneRepresentation();
- cerr<<"CONTENT: "<<rr.content<<endl;
- delete drc;
- }
- catch (...) {
- if (d_ignorebogus) {
- L<<Logger::Error<<backendname<<"Failed to parse record content for "<<rr.qname<<" with type "<<rr.qtype.getName()<<". Ignoring!"<<endl;
- continue;
- } else
- throw;
- }
-// DLOG(L<<Logger::Debug<<backendname<<"Returning ["<<rr.content<<"] for ["<<rr.qname<<"] of RecordType ["<<rr.qtype.getName()<<"]"<<endl;);
- return true;
- }
- } // end of while
- DLOG(L<<Logger::Debug<<backendname<<"No more records to return."<<endl);
-
- delete d_cdbReader;
- return false;
+ pair<string, string> record;
+
+ while (d_cdbReader->readNext(record)) {
+ string val = record.second;
+ string key = record.first;
+
+ //DLOG(L<<Logger::Debug<<"[GET] Key: "<<makeHexDump(key)<<endl);
+ //DLOG(L<<Logger::Debug<<"[GET] Val: "<<makeHexDump(val)<<endl);
+ if (key[0] == '\000' && key[1] == '\045') { // skip locations
+ continue;
+ }
+
+ if (!d_isAxfr) {
+ // If we have a wildcard query, but the record we got is not a wildcard, we skip.
+ if (d_isWildcardQuery && val[2] != '\052' && val[2] != '\053') {
+ continue;
+ }
+
+ // If it is NOT a wildcard query, but we do find a wildcard record, we skip it.
+ if (!d_isWildcardQuery && (val[2] == '\052' || val[2] == '\053')) {
+ continue;
+ }
+ }
+
+
+ vector<uint8_t> bytes;
+ const char *sval = val.c_str();
+ unsigned int len = val.size();
+ bytes.resize(len);
+ copy(sval, sval+len, bytes.begin());
+ PacketReader pr(bytes);
+ rr.qtype = QType(pr.get16BitInt());
+
+ if(d_isAxfr || d_qtype.getCode() == QType::ANY || rr.qtype == d_qtype) {
+ char locwild = pr.get8BitInt();
+ if(locwild != '\075' && (locwild == '\076' || locwild == '\053')) {
+ if (d_isAxfr && d_locations) { // We skip records with a location in AXFR, unless we disable locations.
+ continue;
+ }
+ char recloc[2];
+ recloc[0] = pr.get8BitInt();
+ recloc[1] = pr.get8BitInt();
+
+ if (d_locations) {
+ bool foundLocation = false;
+ vector<string> locations = getLocations();
+ while(locations.size() > 0) {
+ string locId = locations.back();
+ locations.pop_back();
+
+ if (recloc[0] == locId[0] && recloc[1] == locId[1]) {
+ foundLocation = true;
+ break;
+ }
+ }
+ if (!foundLocation) {
+ continue;
+ }
+ }
+ }
+
+ if (d_isAxfr && (val[2] == '\052' || val[2] == '\053' )) { // Keys are not stored with wildcard character, with AXFR we need to add that.
+ key.insert(0, 1, '\052');
+ key.insert(0, 1, '\001');
+ }
+ // rr.qname.clear();
+ rr.qname=DNSName(key.c_str(), key.size(), 0, false);
+ rr.domain_id=-1;
+ // 11:13.21 <@ahu> IT IS ALWAYS AUTH --- well not really because we are just a backend :-)
+ // We could actually do NSEC3-NARROW DNSSEC according to Habbie, if we do, we need to change something ehre.
+ rr.auth = true;
+
+ rr.ttl = pr.get32BitInt();
+ uint64_t timestamp = pr.get32BitInt();
+ timestamp <<= 32;
+ timestamp += pr.get32BitInt();
+ if(timestamp) {
+ uint64_t now = d_taiepoch + time(NULL);
+ if (rr.ttl == 0) {
+ if (timestamp < now) {
+ continue;
+ }
+ rr.ttl = timestamp - now;
+ } else if (now <= timestamp) {
+ continue;
+ }
+ }
+ try {
+ DNSRecord dr;
+ dr.d_class = 1;
+ dr.d_type = rr.qtype.getCode();
+ dr.d_clen = val.size()-pr.d_pos;
+
+ DNSRecordContent *drc = DNSRecordContent::mastermake(dr, pr);
+ rr.content = drc->getZoneRepresentation();
+ cerr<<"CONTENT: "<<rr.content<<endl;
+ delete drc;
+ }
+ catch (...) {
+ if (d_ignorebogus) {
+ L<<Logger::Error<<backendname<<"Failed to parse record content for "<<rr.qname<<" with type "<<rr.qtype.getName()<<". Ignoring!"<<endl;
+ continue;
+ } else
+ throw;
+ }
+// DLOG(L<<Logger::Debug<<backendname<<"Returning ["<<rr.content<<"] for ["<<rr.qname<<"] of RecordType ["<<rr.qtype.getName()<<"]"<<endl;);
+ return true;
+ }
+ } // end of while
+ DLOG(L<<Logger::Debug<<backendname<<"No more records to return."<<endl);
+
+ delete d_cdbReader;
+ return false;
}
// boilerplate
class TinyDNSFactory: public BackendFactory
{
public:
- TinyDNSFactory() : BackendFactory("tinydns") {}
-
- void declareArguments(const string &suffix="") {
- declare(suffix, "notify-on-startup", "Tell the TinyDNSBackend to notify all the slave nameservers on startup. Default is no.", "no");
- declare(suffix, "dbfile", "Location of the cdb data file", "data.cdb");
- declare(suffix, "tai-adjust", "This adjusts the TAI value if timestamps are used. These seconds will be added to the start point (1970) and will allow you to adjust for leap seconds. The default is 11.", "11");
- declare(suffix, "locations", "Enable or Disable location support in the backend. Changing the value to 'no' will make the backend ignore the locations. This then returns all records!", "yes");
- declare(suffix, "ignore-bogus-records", "The data.cdb file might have some wront record data, this causes PowerDNS to fail, where tinydns would send out truncated data. This option makes powerdns ignore that data!", "no");
- }
-
-
- DNSBackend *make(const string &suffix="") {
- return new TinyDNSBackend(suffix);
- }
+ TinyDNSFactory() : BackendFactory("tinydns") {}
+
+ void declareArguments(const string &suffix="") {
+ declare(suffix, "notify-on-startup", "Tell the TinyDNSBackend to notify all the slave nameservers on startup. Default is no.", "no");
+ declare(suffix, "dbfile", "Location of the cdb data file", "data.cdb");
+ declare(suffix, "tai-adjust", "This adjusts the TAI value if timestamps are used. These seconds will be added to the start point (1970) and will allow you to adjust for leap seconds. The default is 11.", "11");
+ declare(suffix, "locations", "Enable or Disable location support in the backend. Changing the value to 'no' will make the backend ignore the locations. This then returns all records!", "yes");
+ declare(suffix, "ignore-bogus-records", "The data.cdb file might have some wront record data, this causes PowerDNS to fail, where tinydns would send out truncated data. This option makes powerdns ignore that data!", "no");
+ }
+
+ DNSBackend *make(const string &suffix="") {
+ return new TinyDNSBackend(suffix);
+ }
};
// boilerplate
class TinyDNSLoader
{
public:
- TinyDNSLoader() {
- BackendMakers().report(new TinyDNSFactory);
- L << Logger::Info << "[tinydnsbackend] This is the tinydns backend version " VERSION
+ TinyDNSLoader() {
+ BackendMakers().report(new TinyDNSFactory);
+ L << Logger::Info << "[tinydnsbackend] This is the tinydns backend version " VERSION
#ifndef REPRODUCIBLE
- << " (" __DATE__ " " __TIME__ ")"
+ << " (" __DATE__ " " __TIME__ ")"
#endif
- << " reporting" << endl;
- }
+ << " reporting" << endl;
+ }
};
static TinyDNSLoader tinydnsloader;
using namespace ::boost::multi_index;
struct TinyDomainInfo {
- uint32_t id;
- uint32_t notified_serial;
- DNSName zone;
+ uint32_t id;
+ uint32_t notified_serial;
+ DNSName zone;
- bool operator<(const TinyDomainInfo& tdi) const
- {
- return zone < tdi.zone;
- }
+ bool operator<(const TinyDomainInfo& tdi) const
+ {
+ return zone < tdi.zone;
+ }
};
struct TDI_SerialModifier {
- TDI_SerialModifier (const int newSerial) : d_newSerial(newSerial) {}
+ TDI_SerialModifier (const int newSerial) : d_newSerial(newSerial) {}
- void operator()(TinyDomainInfo& tdi)
- {
- tdi.notified_serial = d_newSerial;
- }
+ void operator()(TinyDomainInfo& tdi)
+ {
+ tdi.notified_serial = d_newSerial;
+ }
- private:
- int d_newSerial;
+ private:
+ int d_newSerial;
};
class TinyDNSBackend : public DNSBackend
{
public:
- // Methods for simple operation
- TinyDNSBackend(const string &suffix);
- void lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p=0, int zoneId=-1);
- bool list(const DNSName &target, int domain_id, bool include_disabled=false);
- bool get(DNSResourceRecord &rr);
- void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false);
+ // Methods for simple operation
+ TinyDNSBackend(const string &suffix);
+ void lookup(const QType &qtype, const DNSName &qdomain, DNSPacket *pkt_p=0, int zoneId=-1);
+ bool list(const DNSName &target, int domain_id, bool include_disabled=false);
+ bool get(DNSResourceRecord &rr);
+ void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false);
- //Master mode operation
- void getUpdatedMasters(vector<DomainInfo>* domains);
- void setNotified(uint32_t id, uint32_t serial);
+ //Master mode operation
+ void getUpdatedMasters(vector<DomainInfo>* domains);
+ void setNotified(uint32_t id, uint32_t serial);
private:
- vector<string> getLocations();
+ vector<string> getLocations();
- //TypeDefs
- struct tag_zone{};
- struct tag_domainid{};
- typedef multi_index_container<
- TinyDomainInfo,
- indexed_by<
- hashed_unique<tag<tag_zone>, member<TinyDomainInfo, DNSName, &TinyDomainInfo::zone> >,
- hashed_unique<tag<tag_domainid>, member<TinyDomainInfo, uint32_t, &TinyDomainInfo::id> >
- >
- > TDI_t;
- typedef map<string, TDI_t> TDI_suffix_t;
- typedef TDI_t::index<tag_zone>::type TDIByZone_t;
- typedef TDI_t::index<tag_domainid>::type TDIById_t;
+ //TypeDefs
+ struct tag_zone{};
+ struct tag_domainid{};
+ typedef multi_index_container<
+ TinyDomainInfo,
+ indexed_by<
+ hashed_unique<tag<tag_zone>, member<TinyDomainInfo, DNSName, &TinyDomainInfo::zone> >,
+ hashed_unique<tag<tag_domainid>, member<TinyDomainInfo, uint32_t, &TinyDomainInfo::id> >
+ >
+ > TDI_t;
+ typedef map<string, TDI_t> TDI_suffix_t;
+ typedef TDI_t::index<tag_zone>::type TDIByZone_t;
+ typedef TDI_t::index<tag_domainid>::type TDIById_t;
- //data member variables
- uint64_t d_taiepoch;
- QType d_qtype;
- CDB *d_cdbReader;
- DNSPacket *d_dnspacket; // used for location and edns-client support.
- bool d_isWildcardQuery; // Indicate if the query received was a wildcard query.
- bool d_isAxfr; // Indicate if we received a list() and not a lookup().
- bool d_locations;
- bool d_ignorebogus;
- string d_suffix;
-
+ //data member variables
+ uint64_t d_taiepoch;
+ QType d_qtype;
+ CDB *d_cdbReader;
+ DNSPacket *d_dnspacket; // used for location and edns-client support.
+ bool d_isWildcardQuery; // Indicate if the query received was a wildcard query.
+ bool d_isAxfr; // Indicate if we received a list() and not a lookup().
+ bool d_locations;
+ bool d_ignorebogus;
+ string d_suffix;
- // Statics
- static pthread_mutex_t s_domainInfoLock;
- static TDI_suffix_t s_domainInfo;
- static uint32_t s_lastId; // used to give a domain an id.
+ // Statics
+ static pthread_mutex_t s_domainInfoLock;
+ static TDI_suffix_t s_domainInfo;
+ static uint32_t s_lastId; // used to give a domain an id.
};
-#endif // TINYDNSBACKEND_HH
+#endif // TINYDNSBACKEND_HH