return ret;
}
+
+set<shared_ptr<string> > contents;
map<unsigned int, BB2DomainInfo*> nbbds;
/** This function adds a record to a domain with a certain id. */
void Bind2Backend::insert(int id, const string &qnameu, const string &qtype, const string &content, int ttl=300, int prio=25)
{
- DNSResourceRecord rr;
- rr.domain_id=id;
- rr.qname=canonic(qnameu);
- rr.qtype=qtype;
- rr.content=canonic(content); // I think this is wrong, the zoneparser should not come up with . terminated stuff XXX FIXME
- rr.ttl=ttl;
- rr.priority=prio;
- nbbds[id]->d_records->push_back(rr);
+ Bind2DNSRecord bdr;
+
+ // rr.domain_id=id;
+ bdr.qname=canonic(qnameu);
+
+ if(bdr.qname==nbbds[id]->d_name)
+ bdr.qname.clear();
+ else if(bdr.qname.length() > nbbds[id]->d_name.length())
+ bdr.qname.resize(bdr.qname.length() - (nbbds[id]->d_name.length() + 1));
+ else
+ throw AhuException("Trying to insert non-zone data, name='"+bdr.qname+"', zone='"+nbbds[id]->d_name+"'");
+
+ bdr.qname.swap(bdr.qname);
+ bdr.qtype=QType(qtype.c_str()).getCode();
+ // rr.content=canonic(content); // I think this is wrong, the zoneparser should not come up with . terminated stuff XXX FIXME
+ bdr.ttl=ttl;
+
+ // cout<<"Adding rr.qname: '"<<rr.qname<<"'"<<endl;
+ nbbds[id]->d_records->push_back(bdr);
}
}
if(j==s_id_zone_map.end()) { // entirely new
bbd=new BB2DomainInfo;
- bbd->d_records=new vector<DNSResourceRecord>;
+ bbd->d_records=new vector<Bind2DNSRecord>;
bbd->d_id=domain_id++;
s_name_id_map[i->name]=bbd->d_id;
try {
ZP.parse(i->filename,i->name,bbd->d_id); // calls callback for us
+ L<<Logger::Info<<d_logprefix<<" sorting '"<<i->name<<endl;
+ sort(nbbds[bbd->d_id]->d_records->begin(), nbbds[bbd->d_id]->d_records->end());
nbbds[bbd->d_id]->setCtime();
nbbds[bbd->d_id]->d_loaded=true; // does this perform locking for us?
nbbds[bbd->d_id]->d_status="parsed into memory at "+nowTime();
-
+
}
catch(AhuException &ae) {
ostringstream msg;
}
}
+bool operator<(const Bind2DNSRecord &a, const string &b)
+{
+ return a.qname < b;
+}
+
+bool operator<(const string &a, const Bind2DNSRecord &b)
+{
+ return a < b.qname;
+}
+
+
void Bind2Backend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int zoneId )
{
d_handle=new Bind2Backend::handle;
DLOG(L<<"Bind2Backend constructing handle for search for "<<qtype.getName()<<" for "<<
qname<<endl);
- d_handle->qname=qname;
+
+ d_handle->qname=qname.substr(0,qname.size()-domain.length()-1); // strip domain name
+ // cout<<"Reduced to '"<<d_handle->qname<<"'"<<endl;
d_handle->parent=this;
d_handle->qtype=qtype;
else {
DLOG(L<<"Query with no results"<<endl);
}
- d_handle->d_iter=d_handle->d_records->begin();
+ d_handle->d_iter=equal_range(d_handle->d_records->begin(), d_handle->d_records->end(), d_handle->qname).first;
d_handle->d_list=false;
}
qname<<"- "<<d_records->size()<<" available!"<<endl);
// this is a linear walk!!! XXX FIXME
- while(d_iter!=d_records->end() && (strcasecmp(d_iter->qname.c_str(),qname.c_str()) || !(qtype=="ANY" || (d_iter)->qtype==qtype))) {
+
+ while(d_iter!=d_records->end() && (strcasecmp(d_iter->qname.c_str(),qname.c_str()) || !(qtype.getCode()==QType::ANY || (d_iter)->qtype==qtype))) {
DLOG(L<<Logger::Warning<<"Skipped "<<qname<<"/"<<QType(d_iter->qtype).getName()<<": '"<<d_iter->content<<"'"<<endl);
d_iter++;
}
r.qname=qname;
- r.content=(d_iter)->content;
- r.domain_id=(d_iter)->domain_id;
+ //r.content=(d_iter)->content;
+ // r.domain_id=(d_iter)->domain_id;
r.qtype=(d_iter)->qtype;
r.ttl=(d_iter)->ttl;
- r.priority=(d_iter)->priority;
+ // r.priority=(d_iter)->priority;
d_iter++;
return true;
bool Bind2Backend::handle::get_list(DNSResourceRecord &r)
{
if(d_qname_iter!=d_qname_end) {
- r=*d_qname_iter;
+ // r=*d_qname_iter; // XXX FIXME WRONG WRONG WRONG
d_qname_iter++;
return true;
}
BB2DomainInfo *bbd = new BB2DomainInfo;
- bbd->d_records = new vector<DNSResourceRecord>;
+ bbd->d_records = new vector<Bind2DNSRecord>;
bbd->d_name = domain;
bbd->setCheckInterval(getArgAsNum("check-interval"));
bbd->d_master = ip;
#include <pthread.h>
#include <time.h>
#include <fstream>
-
+#include <boost/shared_ptr.hpp>
#include "huffman.hh"
+using namespace boost;
+using namespace std;
-#if __GNUC__ >= 3
-# include <ext/hash_map>
-using namespace __gnu_cxx;
-#else
-# include <hash_map>
-#endif
-
+struct Bind2DNSRecord
+{
+ string qname;
+ QType qtype;
+ uint32_t ttl;
+ shared_ptr<string> content;
-using namespace std;
+ bool operator<(const Bind2DNSRecord& rhs) const
+ {
+ return qname < rhs.qname;
+ }
+};
class BB2DomainInfo
{
}
void setCheckInterval(time_t seconds);
- vector <DNSResourceRecord>* d_records;
+ vector <Bind2DNSRecord>* d_records;
private:
time_t getCtime();
time_t d_checkinterval;
time_t d_lastcheck;
pthread_rwlock_t *d_rwlock;
};
-
-
-
-class BBResourceRecord
-{
-public:
- bool operator==(const BBResourceRecord &o) const
- {
- return (o.domain_id==domain_id && o.qtype==qtype && o.content==content &&
- o.ttl==ttl && o.priority==priority);
- }
-
- const string *qnameptr; // 4
- unsigned int domain_id; // 4
- unsigned short int qtype; // 2
- unsigned short int priority; // 2
- const string *content; // 4
- unsigned int ttl; // 4
-
-};
-
-struct compare_string
-{
- bool operator()(const string& s1, const string& s2) const
- {
- return s1 == s2;
- }
-};
-struct hash_string
-{
- size_t operator()(const string& s) const
- {
- return __stl_hash_string(s.c_str());
- }
-};
-
-typedef hash_map<string,vector<BBResourceRecord>, hash_string, compare_string> cmap_t;
-
-
-
-/** The Bind2Backend is a DNSBackend that can answer DNS related questions. It looks up data
- in a Bind-style zone file
-
- How this all works is quite complex and prone to change. There are a number of containers involved which,
- together, contain everything we need to know about a domain or a record.
-
- A domain consists of records. So, 'example.com' has 'www.example.com' as a record.
-
- All record names are stored in the hash_map d_qnames, with their name as index. Attached to that index
- is a vector of BBResourceRecords ('Bind2Backend') belonging to that qname. Each record contains a d_domainid,
- which is the ID of the domain it belongs to.
-
- Then there is the map called d_bbds which has as its key the Domain ID, and attached a BB2DomainInfo object, which
- tells us domain metadata (place on disk, if it is a master or a slave etc).
-
- To allow for AXFRs, there is yet another container, the d_zone_id_map, which contains per domain_id a vector
- of pointers to vectors of BBResourceRecords. When read in sequence, these deliver all records of a domain_id.
-
- As there is huge repitition in the right hand side of records, many records point to the same thing (IP address, nameserver),
- a list of these is kept in s_contents, and each BBResourceRecord only contains a pointer to a record in s_contents.
-
- So, summarizing:
-
- class BBResourceRecord:
- Everything you need to know about a record. In this context we call the name of a BBResourceRecord 'qname'
-
- class BB2DomainInfo:
- Domain metadata, like location on disk, last time zone was checked
-
- d_qnames<qname,vector<BBResourceRecord> >:
- If you know the qname of a record, this gives you all records under that name.
-
- set<string>s_contents:
- Set of all 'contents' of records, the right hand sides.
-
- map<int,vector<vector<BBResourceRecord>* > > d_zone_id_map:
- If you know the zone_id, this has a vector of pointers to vectors in d_qnames, for AXFR
-
- map<unsigned int, BB2DomainInfo>d_bbds:
- Map of all domains we know about and metadata about them.
-
-
-*/
class Bind2Backend : public DNSBackend
{
public:
Bind2Backend *parent;
- vector<DNSResourceRecord>* d_records;
- vector<DNSResourceRecord>::const_iterator d_iter;
+ vector<Bind2DNSRecord>* d_records;
+ vector<Bind2DNSRecord>::const_iterator d_iter;
- vector<DNSResourceRecord>::const_iterator d_rend;
+ vector<Bind2DNSRecord>::const_iterator d_rend;
- vector<DNSResourceRecord>::const_iterator d_qname_iter;
- vector<DNSResourceRecord>::const_iterator d_qname_end;
+ vector<Bind2DNSRecord>::const_iterator d_qname_iter;
+ vector<Bind2DNSRecord>::const_iterator d_qname_end;
bool d_list;
int id;
ofstream *d_of;
handle *d_handle;
void queueReload(BB2DomainInfo *bbd);
- BBResourceRecord resourceMaker(int id, const string &qtype, const string &content, int ttl, int prio);
+
void reload();
static string DLDomStatusHandler(const vector<string>&parts, Utility::pid_t ppid);
static string DLListRejectsHandler(const vector<string>&parts, Utility::pid_t ppid);