From f2c11a484eeccff13a0c8e91bfc363ccbb4860e5 Mon Sep 17 00:00:00 2001 From: Bert Hubert Date: Fri, 20 Dec 2002 14:25:29 +0000 Subject: [PATCH] heaps of work again git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@91 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- ChangeLog | 2 + TODO | 5 +- pdns/backends/bind/bindbackend.cc | 107 ++++++++++++++++++++++++------ pdns/backends/bind/bindbackend.hh | 6 +- pdns/communicator.cc | 28 ++++---- pdns/dnsbackend.hh | 4 +- pdns/dynhandler.cc | 3 + pdns/misc.cc | 19 ++++++ pdns/misc.hh | 1 + 9 files changed, 132 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ed88029c..45fc08a82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,8 @@ Changes since 2.9.2: - lots of bind backend work - we now ignore 'hint' 'forward' whatever zones - added 'bind-domain-status', 'bind-reload-now' + - added 'retrieve' + - bind zones are now way smaller on disk - 'notify' no longer prints out garbage to pdns_control - more verbose logging of AXFRs - is a heavy operation already, logging won't add much to that diff --git a/TODO b/TODO index ca31cea8e..06b5b4c29 100644 --- a/TODO +++ b/TODO @@ -20,11 +20,8 @@ Medium size things: non-resolving bind. We're 90% there. - improve atomic zone swapping right now we are SOL if we try to reload a broken zone - - write out $ORIGIN statements on file that came in over AXFR - - make sure its name can be changed and that everything - changes with it - - right now, bindbackend accepts out of zone records! - bind backend does not do proper notifications! + - writes tmp file to /tmp/wuh! - get PDNS into Red Hat 8.x needs very good RPMS diff --git a/pdns/backends/bind/bindbackend.cc b/pdns/backends/bind/bindbackend.cc index 5b8439fc8..492eef2da 100644 --- a/pdns/backends/bind/bindbackend.cc +++ b/pdns/backends/bind/bindbackend.cc @@ -3,9 +3,8 @@ Copyright (C) 2002 PowerDNS.COM BV This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,7 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// $Id: bindbackend.cc,v 1.7 2002/12/19 20:15:55 ahu Exp $ +// $Id: bindbackend.cc,v 1.8 2002/12/20 14:25:29 ahu Exp $ #include #include #include @@ -40,6 +39,7 @@ using namespace std; #include "qtype.hh" #include "misc.hh" #include "dynlistener.hh" +#include "lock.hh" using namespace std; @@ -51,6 +51,7 @@ HuffmanCodec BindBackend::s_hc; map BindBackend::d_bbds; int BindBackend::s_first=1; +pthread_mutex_t BindBackend::s_startup_lock=PTHREAD_MUTEX_INITIALIZER; BBDomainInfo::BBDomainInfo() { @@ -98,6 +99,10 @@ void BBDomainInfo::setCtime() d_ctime=buf.st_ctime; } +void BindBackend::setNotified(u_int32_t id, u_int32_t serial) +{ + d_bbds[id].d_lastnotified=serial; +} void BindBackend::setFresh(u_int32_t domain_id) { @@ -106,48 +111,69 @@ void BindBackend::setFresh(u_int32_t domain_id) bool BindBackend::startTransaction(const string &qname, int id) { - d_of=new ofstream("/tmp/juh"); - if(!d_of) - throw AhuException("Unable to open temporary zonefile!"); + BBDomainInfo &bbd=d_bbds[d_transaction_id=id]; + d_transaction_tmpname=bbd.d_filename+"."+itoa(random()); + d_of=new ofstream(d_transaction_tmpname.c_str()); + if(!*d_of) { + throw DBException("Unable to open temporary zonefile '"+d_transaction_tmpname+"': "+stringerror()); + unlink(d_transaction_tmpname.c_str()); + delete d_of; + d_of=0; + } *d_of<<"; Written by PowerDNS, don't edit!"< *changedDomains) { + SOAData soadata; + for(map::iterator i=d_bbds.begin();i!=d_bbds.end();++i) { + if(!i->second.d_master.empty()) + continue; + soadata.serial=0; + try { + getSOA(i->second.d_name,soadata); // we might not *have* a SOA yet + } + catch(...){} + DomainInfo di; + di.id=i->first; + di.serial=soadata.serial; + di.zone=i->second.d_name; + di.last_check=i->second.d_last_check; + di.backend=this; + di.kind=DomainInfo::Master; + if(!i->second.d_lastnotified) // don't do notification storm on startup + i->second.d_lastnotified=soadata.serial; + else + if(soadata.serial!=i->second.d_lastnotified) + changedDomains->push_back(di); + + } } void BindBackend::getUnfreshSlaveInfos(vector *unfreshDomains) @@ -177,6 +226,7 @@ void BindBackend::getUnfreshSlaveInfos(vector *unfreshDomains) soadata.serial=0; soadata.refresh=0; soadata.serial=0; + try { getSOA(i->second.d_name,soadata); // we might not *have* a SOA yet } @@ -197,6 +247,13 @@ bool BindBackend::getDomainInfo(const string &domain, DomainInfo &di) di.last_check=i->second.d_last_check; di.backend=this; di.kind=i->second.d_master.empty() ? DomainInfo::Master : DomainInfo::Slave; + di.serial=0; + try { + SOAData sd; + getSOA(i->second.d_name,sd); // we might not *have* a SOA yet + di.serial=sd.serial; + } + catch(...){} return true; } @@ -371,8 +428,11 @@ BindBackend::BindBackend(const string &suffix) { d_logprefix="[bind"+suffix+"backend]"; setArgPrefix("bind"+suffix); - if(!s_first) + Lock l(&s_startup_lock); + + if(!s_first) { return; + } s_first=0; if(!mustDo("enable-huffman")) @@ -465,9 +525,10 @@ void BindBackend::loadConfig(string* status) } if(j==d_bbds.end()) { // entirely new bbd.d_id=domain_id++; - bbd.setCtime(); + bbd.setCheckInterval(getArgAsNum("check-interval")); - nbbds[bbd.d_id].d_loaded=false; + bbd.d_lastnotified=0; + bbd.d_loaded=false; } bbd.d_name=i->name; @@ -480,8 +541,10 @@ void BindBackend::loadConfig(string* status) try { ZP.parse(i->filename,i->name,bbd.d_id); // calls callback for us + 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; diff --git a/pdns/backends/bind/bindbackend.hh b/pdns/backends/bind/bindbackend.hh index 28c501181..4f2d15a99 100644 --- a/pdns/backends/bind/bindbackend.hh +++ b/pdns/backends/bind/bindbackend.hh @@ -54,6 +54,7 @@ public: time_t d_last_check; string d_master; int d_confcount; + u_int32_t d_lastnotified; bool tryRLock() { @@ -181,13 +182,15 @@ public: static DNSBackend *maker(); static set s_contents; + static pthread_mutex_t s_startup_lock; void setFresh(u_int32_t domain_id); - + void setNotified(u_int32_t id, u_int32_t serial); bool startTransaction(const string &qname, int id); // bool BindBackend::stopTransaction(const string &qname, int id); bool feedRecord(const DNSResourceRecord &r); bool commitTransaction(); + bool abortTransaction(); void insert(int id, const string &qname, const string &qtype, const string &content, int ttl, int prio); void rediscover(string *status=0); static HuffmanCodec s_hc; @@ -236,6 +239,7 @@ private: string d_logprefix; int d_transaction_id; + string d_transaction_tmpname; ofstream *d_of; handle *d_handle; void queueReload(BBDomainInfo *bbd); diff --git a/pdns/communicator.cc b/pdns/communicator.cc index 0231a5fa4..81466b133 100644 --- a/pdns/communicator.cc +++ b/pdns/communicator.cc @@ -150,14 +150,18 @@ void CommunicatorClass::queueNotifyDomain(const string &domain, DNSBackend *B) } // make calls to d_nq.add(domain, ip); - for(set::const_iterator j=ips.begin();j!=ips.end();++j) + for(set::const_iterator j=ips.begin();j!=ips.end();++j) { + L<alsoNotify; B->alsoNotifies(domain, &alsoNotify); - for(set::const_iterator j=alsoNotify.begin();j!=alsoNotify.end();++j) + for(set::const_iterator j=alsoNotify.begin();j!=alsoNotify.end();++j) { + L<setNotified(di.id,di.serial); + di.backend->setNotified(di.id, di.serial); return true; } @@ -200,17 +204,11 @@ void CommunicatorClass::masterUpdateCheck(PacketHandler *P) // figure out A records of everybody needing notification // do this via the FindNS class, d_fns - for(vector::const_iterator i=cmdomains.begin();i!=cmdomains.end();++i) { + queueNotifyDomain(i->zone,P->getBackend()); i->backend->setNotified(i->id,i->serial); } - - - - // call it a day - // day() - } void CommunicatorClass::slaveRefresh(PacketHandler *P) @@ -233,7 +231,8 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P) for(vector::const_iterator i=sdomains.begin();i!=sdomains.end();++i) { d_slaveschanged=true; - u_int32_t theirserial=0; + u_int32_t ourserial=i->serial,theirserial=0; + try { Resolver resolver; int res=resolver.getSoaSerial(i->master,i->zone, &theirserial); @@ -243,7 +242,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P) } if(theirserialserial) { - L<zone<<" more recent than master, our serial "<serial<<" > their serial "<zone<<" more recent than master, our serial "< their serial "<backend->setFresh(i->id); } else if(theirserial==i->serial) { @@ -291,8 +290,9 @@ int CommunicatorClass::doNotifications() if(p.d.rcode) L<&parts, Utility::pid_t ppid) if(!P.getBackend()->getDomainInfo(domain, di)) return "Domain '"+domain+"' unknown"; + if(di.master.empty()) + return "Domain '"+domain+"' is not a slave domain (or has no master defined)"; + Communicator.addSuckRequest(domain,di.master); return "Added retrieval request for '"+domain+"' from master "+di.master; } diff --git a/pdns/misc.cc b/pdns/misc.cc index da4a0382c..be27c9e00 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -47,6 +47,25 @@ string nowTime() return t; } +/** strips a domain suffix from a domain, returns true if it stripped */ +bool stripDomainSuffix(string *qname, const string &domain) +{ + if((qname->size()-toLower(*qname).rfind(toLower(domain)))!=domain.size()) { + return false; + + } + if(*qname==domain) + *qname="@"; + else { + if((*qname)[qname->size()-domain.size()-1]!='.') + return false; + + qname->resize(qname->size()-domain.size()-1); + } + return true; +} + + int sendData(const char *buffer, int replen, int outsock) { u_int16_t nlen=htons(replen); diff --git a/pdns/misc.hh b/pdns/misc.hh index 35a896c5f..d7041273f 100644 --- a/pdns/misc.hh +++ b/pdns/misc.hh @@ -46,6 +46,7 @@ string nowTime(); int matchNetmask(const char *address, const char *omask); string humanDuration(time_t passed); void chomp(string &line, const string &delim); +bool stripDomainSuffix(string *qname, const string &domain); void stripLine(string &line); string getHostname(); string urlEncode(const string &text); -- 2.40.0