Index: modules/gmysqlbackend/gmysqlbackend.cc
===================================================================
--- modules/gmysqlbackend/gmysqlbackend.cc	(.../Original%20sources.)	(revision 13)
+++ modules/gmysqlbackend/gmysqlbackend.cc	(.../withAXFRpatch)	(revision 13)
@@ -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 {
+      setDBSlave(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: pdns/ueberbackend.cc
===================================================================
--- pdns/ueberbackend.cc	(.../Original%20sources.)	(revision 13)
+++ pdns/ueberbackend.cc	(.../withAXFRpatch)	(revision 13)
@@ -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	(.../Original%20sources.)	(revision 13)
+++ pdns/tcpreceiver.cc	(.../withAXFRpatch)	(revision 13)
@@ -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	(.../Original%20sources.)	(revision 13)
+++ pdns/common_startup.cc	(.../withAXFRpatch)	(revision 13)
@@ -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	(.../Original%20sources.)	(revision 13)
+++ pdns/backends/gsql/gsqlbackend.cc	(.../withAXFRpatch)	(revision 13)
@@ -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);
+    getDBSlave()->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);
+    getDBSlave()->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);
+    getDBSlave()->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);
+    getDBSlave()->doQuery(output,d_result);
   }
   catch(SSqlException &e) {
     throw AhuException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason());
@@ -239,6 +307,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 +360,7 @@
   DLOG(L<< "Query: '" << output << "'"<<endl);
 
   try {
-    d_db->doQuery(output);
+    getDBSlave()->doQuery(output);
   }
   catch(SSqlException &e) {
     throw AhuException(e.txtReason());
@@ -309,7 +378,7 @@
   char output[1024];
   snprintf(output,sizeof(output)-1,d_listQuery.c_str(),domain_id);
   try {
-    d_db->doQuery(output);
+    getDBSlave()->doQuery(output);
   }
   catch(SSqlException &e) {
     throw AhuException("GSQLBackend list query: "+e.txtReason());
@@ -329,7 +398,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);
+      getDBSlave()->doQuery(output, d_result);
     }
     catch (SSqlException &e) {
       throw AhuException("GSQLBackend unable to search for a domain: "+e.txtReason());
@@ -364,7 +433,7 @@
 {
   // L << "GSQLBackend get() was called for "<<qtype.getName() << " record: ";
   SSql::row_t row;
-  if(d_db->getRow(row)) {
+  if(getDBSlave()->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	(.../Original%20sources.)	(revision 13)
+++ pdns/backends/gsql/gsqlbackend.hh	(.../withAXFRpatch)	(revision 13)
@@ -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 setDBSlave(SSql *db)
+  {
+    d_db_slave=db;
+  }
+
+  SSql *getDBSlave()
+  {
+    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;        
 
 };

Index: pdns/dnsbackend.hh
===================================================================
--- pdns/dnsbackend.hh	(.../Original%20sources.)	(revision 13)
+++ pdns/dnsbackend.hh	(.../withAXFRpatch)	(revision 13)
@@ -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	(.../Original%20sources.)	(revision 13)
+++ pdns/misc.cc	(.../withAXFRpatch)	(revision 13)
@@ -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	(.../Original%20sources.)	(revision 13)
+++ pdns/ueberbackend.hh	(.../withAXFRpatch)	(revision 13)
@@ -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	(.../Original%20sources.)	(revision 13)
+++ pdns/dnsbackend.cc	(.../withAXFRpatch)	(revision 13)
@@ -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();

