Search
j0ke.net Open Build Service
>
Projects
>
home:jg
:
dns
>
pdns
> pdns-2.9.22-axfr_slavedb.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File pdns-2.9.22-axfr_slavedb.patch of Package pdns
Index: modules/gmysqlbackend/gmysqlbackend.cc =================================================================== --- modules/gmysqlbackend/gmysqlbackend.cc (.../trunk) (revision 25) +++ modules/gmysqlbackend/gmysqlbackend.cc (.../branches/axfr-slavedb) (revision 25) @@ -35,6 +35,24 @@ throw AhuException("Unable to launch "+mode+" connection: "+e.txtReason()); } L<<Logger::Warning<<mode<<" Connection succesful"<<endl; + + if(!getArg("slave-socket").empty() || !getArg("slave-host").empty()) { + try { + setDBReadonly(new SMySQL(getArg("slave-dbname"), + getArg("slave-host"), + getArgAsNum("slave-port"), + getArg("slave-socket"), + getArg("slave-user"), + getArg("slave-password"))); + L<<Logger::Warning<<mode<<" Slave connection successful."<<endl; + } catch(ArgException &e) { + // Ignore exception, slave not + L<<Logger::Warning<<mode<<" Slave configuration."<<endl; + } catch(SSqlException &e) { + // Ignore exception, slave not + L<<Logger::Warning<<mode<<" Unable to connect to slave."<<endl; + } + } } class gMySQLFactory : public BackendFactory @@ -51,6 +69,13 @@ declare(suffix,"socket","Pdns backend socket to connect to",""); declare(suffix,"password","Pdns backend password to connect with",""); + declare(suffix,"slave-dbname","Pdns backend database name to connect to",""); + declare(suffix,"slave-user","Database backend user to connect as",""); + declare(suffix,"slave-host","Database backend host to connect to",""); + declare(suffix,"slave-port","Database backend port to connect to","0"); + declare(suffix,"slave-socket","Pdns backend socket to connect to",""); + declare(suffix,"slave-password","Pdns backend password to connect with",""); + declare(suffix,"basic-query","Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'"); declare(suffix,"id-query","Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d"); declare(suffix,"wildcard-query","Wildcard query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name like '%s'"); @@ -75,6 +100,7 @@ declare(suffix,"info-all-master-query","", "select id,name,master,last_check,notified_serial,type from domains where type='MASTER'"); declare(suffix,"delete-zone-query","", "delete from records where domain_id=%d"); + declare(suffix,"lookup-axfr-allow","", "select zone_grants from domains where name='%s'"); } Index: debian-pdns/rules =================================================================== --- debian-pdns/rules (.../trunk) (revision 25) +++ debian-pdns/rules (.../branches/axfr-slavedb) (revision 25) @@ -2,8 +2,8 @@ tmpdir := $(shell pwd)/debian-pdns/tmp be_tmpdir := $(shell pwd)/debian-pdns/tmp-backend -backends := opendbx ldap mysql pipe gmysql gpgsql gsqlite gsqlite3 -debs := opendbx ldap mysql pipe pgsql sqlite sqlite3 +backends := gmysql +debs := mysql binary-doc: -make -C pdns/docs html/index.html Index: pdns/ueberbackend.cc =================================================================== --- pdns/ueberbackend.cc (.../trunk) (revision 25) +++ pdns/ueberbackend.cc (.../branches/axfr-slavedb) (revision 25) @@ -60,6 +60,15 @@ #define RTLD_NOW RTLD_LAZY #endif +bool UeberBackend::checkAXFRByZone( const std::string& name , const std::string& ip) +{ + for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) + { + if(( *i )->checkAXFRByZone( name , ip) ) return true; + } + return false; +} + //! Loads a module and reports it to all UeberBackend threads bool UeberBackend::loadmodule(const string &name) { Index: pdns/tcpreceiver.cc =================================================================== --- pdns/tcpreceiver.cc (.../trunk) (revision 25) +++ pdns/tcpreceiver.cc (.../branches/axfr-slavedb) (revision 25) @@ -346,16 +346,42 @@ if(::arg().mustDo("disable-axfr")) return false; - if( ::arg()["allow-axfr-ips"].empty() || d_ng.match( (ComboAddress *) &q->remote ) ) - return true; + if(::arg().mustDo("axfr-by-zone") ) + { + //DNSBackend *backend = s_P->getBackend(); + PacketHandler P; + DNSBackend *backend = P.getBackend(); + if(backend->checkAXFRByZone( q->qdomain , q->getRemote()) ) + { + L << Logger::Warning + <<"Approved zone-based AXFR of '"<<q->qdomain + << q->getRemote()<<endl; + return true; + } + //a empty list is a failure in case of 'axfr-by-zone' + else if(d_ng.match( (ComboAddress *) &q->remote ) ) + { + L << Logger::Warning << "allowed by config file" << endl; + return true; + } + } + else + { + // L << Logger::Warning<< "no axfr-by-zone" <<endl; + if(::arg()["allow-axfr-ips"].empty() + || d_ng.match( (ComboAddress *) &q->remote ) ) + return true; + } extern CommunicatorClass Communicator; if(Communicator.justNotified(q->qdomain, q->getRemote())) { // we just notified this ip - L<<Logger::Warning<<"Approved AXFR of '"<<q->qdomain<<"' from recently notified slave "<<q->getRemote()<<endl; + L << Logger::Warning << "Approved AXFR of '" << q->qdomain << "' from recently notified slave " << q->getRemote() << endl; return true; } + L << Logger::Warning << "AXFR FAILED" << endl; + return false; } Index: pdns/common_startup.cc =================================================================== --- pdns/common_startup.cc (.../trunk) (revision 25) +++ pdns/common_startup.cc (.../branches/axfr-slavedb) (revision 25) @@ -127,6 +127,9 @@ ::arg().set("max-cache-entries", "Maximum number of cache entries")="1000000"; ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom"; + + ::arg().set("axfr-by-zone","allows configuration of axfr-allows by zone")="yes"; + ::arg().setSwitch("axfr-by-zone","allows configuration of axfr-allows by zone")="yes"; } void declareStats(void) Index: pdns/backends/gsql/gsqlbackend.cc =================================================================== --- pdns/backends/gsql/gsqlbackend.cc (.../trunk) (revision 25) +++ pdns/backends/gsql/gsqlbackend.cc (.../branches/axfr-slavedb) (revision 25) @@ -16,10 +16,78 @@ #include "pdns/ahuexception.hh" #include "pdns/logger.hh" #include "pdns/arguments.hh" +#include "pdns/iputils.hh" #include <boost/algorithm/string.hpp> #include <sstream> + using namespace boost; +bool GSQLBackend::checkAXFRByZone(const std::string& name , const std::string& ip) +{ +// L << Logger::Warning +// << "ZONE-AXFR: checking " << name << " with " << ip << std::endl; + + char output[1024]; + + snprintf( output,sizeof(output)-1, + d_LookupAxfrAllow.c_str(),name.c_str() + ); + + L << Logger::Warning + << "ZONE-AXFR: checking " << name << " with " << ip << std::endl + << "STATEMENT: "<< output << std::endl; + + try + { + d_db->doQuery(output, d_result); + } + catch(SSqlException &e) + { + throw AhuException("GSQLBackend unable to select AXFR-by Zone . name " + + name + + " with ip " + + ip + + " : " + + e.txtReason()); + } + + if(!d_result.size()) + return false; + + if(d_result.size() > 1) + throw AhuException("Ambigous entries ' " + + name + + "' exists more than once"); + + SSql::row_t row(d_result[0]); + SSql::row_t::const_reverse_iterator zone_str_iter(row.rbegin()); + std::vector<std::string> allowed_ips; + + stringtok(allowed_ips, *zone_str_iter, ";"); + std::vector<std::string>::iterator iter(allowed_ips.begin()), + end(allowed_ips.end()); + + for(;iter!=end;++iter) + { + trim(*iter); + + L << Logger::Warning << "ZONE-AXFR: comparing '" << *iter << "' with '" << ip << "'"<< std::endl; + + if(*iter == ip) return true; + + // check for netmasks + if( (*iter).find_first_of('/') != std::string::npos ) // found a mask + { + L << Logger::Warning << "detected mask " << std::endl; + Netmask mask(*iter); + if(mask.match(ip)) return true; + } + + + } + return false; +} + void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial) { char output[1024]; @@ -57,7 +125,7 @@ d_MasterOfDomainsZoneQuery.c_str(), sqlEscape(domain).c_str()); try { - d_db->doQuery(output, d_result); + getDBReadonly()->doQuery(output, d_result); } catch (SSqlException &e) { throw AhuException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason()); @@ -77,7 +145,7 @@ snprintf(output,sizeof(output)-1,d_InfoOfDomainsZoneQuery.c_str(), sqlEscape(domain).c_str()); try { - d_db->doQuery(output,d_result); + getDBReadonly()->doQuery(output,d_result); } catch(SSqlException &e) { throw AhuException("GSQLBackend unable to retrieve information about a domain: "+e.txtReason()); @@ -125,7 +193,7 @@ snprintf(output,sizeof(output)-1,d_InfoOfAllSlaveDomainsQuery.c_str()); try { - d_db->doQuery(output,d_result); + getDBReadonly()->doQuery(output,d_result); } catch (SSqlException &e) { throw AhuException("GSQLBackend unable to retrieve list of slave domains: "+e.txtReason()); @@ -164,7 +232,7 @@ snprintf(output, sizeof(output)-1, d_InfoOfAllMasterDomainsQuery.c_str()); try { - d_db->doQuery(output,d_result); + getDBReadonly()->doQuery(output,d_result); } catch(SSqlException &e) { throw AhuException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason()); @@ -215,6 +283,7 @@ { setArgPrefix(mode+suffix); d_db=0; + d_db_slave=NULL; d_logprefix="["+mode+"Backend"+suffix+"] "; d_noWildCardNoIDQuery=getArg("basic-query"); @@ -239,6 +308,7 @@ d_UpdateLastCheckofZoneQuery=getArg("update-lastcheck-query"); d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query"); d_DeleteZoneQuery=getArg("delete-zone-query"); + d_LookupAxfrAllow=getArg("lookup-axfr-allow"); } @@ -291,7 +361,7 @@ DLOG(L<< "Query: '" << output << "'"<<endl); try { - d_db->doQuery(output); + getDBReadonly()->doQuery(output); } catch(SSqlException &e) { throw AhuException(e.txtReason()); @@ -309,7 +379,7 @@ char output[1024]; snprintf(output,sizeof(output)-1,d_listQuery.c_str(),domain_id); try { - d_db->doQuery(output); + getDBReadonly()->doQuery(output); } catch(SSqlException &e) { throw AhuException("GSQLBackend list query: "+e.txtReason()); @@ -329,7 +399,7 @@ for(vector<DNSResourceRecord>::const_iterator i=nsset.begin();i!=nsset.end();++i) { try { snprintf(output,sizeof(output)-1,format.c_str(),sqlEscape(ip).c_str(),sqlEscape(i->content).c_str()); - d_db->doQuery(output, d_result); + getDBReadonly()->doQuery(output, d_result); } catch (SSqlException &e) { throw AhuException("GSQLBackend unable to search for a domain: "+e.txtReason()); @@ -364,7 +434,7 @@ { // L << "GSQLBackend get() was called for "<<qtype.getName() << " record: "; SSql::row_t row; - if(d_db->getRow(row)) { + if(getDBReadonly()->getRow(row)) { r.content=row[0]; if (row[1].empty()) r.ttl = ::arg().asNum( "default-ttl" ); Index: pdns/backends/gsql/gsqlbackend.hh =================================================================== --- pdns/backends/gsql/gsqlbackend.hh (.../trunk) (revision 25) +++ pdns/backends/gsql/gsqlbackend.hh (.../branches/axfr-slavedb) (revision 25) @@ -14,6 +14,8 @@ { if(d_db) delete d_db; + if(d_db_slave) + delete d_db_slave; } void setDB(SSql *db) @@ -21,6 +23,19 @@ d_db=db; } + void setDBReadonly(SSql *db) + { + d_db_slave=db; + } + + SSql *getDBReadonly() + { + return d_db_slave != NULL ? d_db_slave : d_db; + } + + //checks if a zone is allowed to check axfr-data + bool checkAXFRByZone(const std::string& name , const std::string& ip); + string sqlEscape(const string &name); void lookup(const QType &, const string &qdomain, DNSPacket *p=0, int zoneId=-1); bool list(const string &target, int domain_id); @@ -43,6 +58,7 @@ QType d_qtype; int d_count; SSql *d_db; + SSql *d_db_slave; SSql::result_t d_result; string d_wildCardNoIDQuery; @@ -65,6 +81,7 @@ string d_UpdateSerialOfZoneQuery; string d_UpdateLastCheckofZoneQuery; string d_InfoOfAllMasterDomainsQuery; - string d_DeleteZoneQuery; + string d_DeleteZoneQuery; + string d_LookupAxfrAllow; }; Property changes on: pdns/backends/gsql/gsqlbackend.hh ___________________________________________________________________ Added: svn:mergeinfo Merged /pdns-2.9.22/branches/slavedb/pdns/backends/gsql/gsqlbackend.hh:r8-23 Merged /pdns-2.9.22/trunk/pdns/backends/gsql/gsqlbackend.hh:r7 Index: pdns/dnsbackend.hh =================================================================== --- pdns/dnsbackend.hh (.../trunk) (revision 25) +++ pdns/dnsbackend.hh (.../branches/axfr-slavedb) (revision 25) @@ -77,6 +77,8 @@ if the backend does not consider itself responsible for the id passed. \param domain_id ID of which a list is requested */ + virtual bool checkAXFRByZone(const std::string& name , const std::string& ip); + virtual bool list(const string &target, int domain_id)=0; virtual ~DNSBackend(){}; Index: pdns/misc.cc =================================================================== --- pdns/misc.cc (.../trunk) (revision 25) +++ pdns/misc.cc (.../branches/axfr-slavedb) (revision 25) @@ -232,6 +232,10 @@ while (replen) { ret = write(outsock, buffer, replen); + while(ret == -1 && errno == EAGAIN) { + Utility::usleep(1); + ret = write(outsock, buffer, replen); + } if(ret < 0) { if(errno==EAGAIN) { // wait, we might've exhausted the window while(waitForRWData(outsock, false, 1, 0)==0) Index: pdns/ueberbackend.hh =================================================================== --- pdns/ueberbackend.hh (.../trunk) (revision 25) +++ pdns/ueberbackend.hh (.../branches/axfr-slavedb) (revision 25) @@ -57,6 +57,7 @@ UeberBackend(); UeberBackend(const string &); ~UeberBackend(); + virtual bool checkAXFRByZone(const std::string& name , const std::string& ip); typedef DNSBackend *BackendMaker(); //!< typedef for functions returning pointers to new backends bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db); Index: pdns/dnsbackend.cc =================================================================== --- pdns/dnsbackend.cc (.../trunk) (revision 25) +++ pdns/dnsbackend.cc (.../branches/axfr-slavedb) (revision 25) @@ -25,6 +25,11 @@ #include <sys/types.h> #include "dnspacket.hh" +bool DNSBackend::checkAXFRByZone(const std::string& name , const std::string& ip) +{ + return false; +} + string DNSBackend::getRemote(DNSPacket *p) { return p->getRemote();