Index: bindbackend2.cc
===================================================================
RCS file: /var/cvsroot/pdns/pdns/backends/bind/bindbackend2.cc,v
retrieving revision 1.3
diff -u -B -b -r1.3 bindbackend2.cc
--- bindbackend2.cc	20 Mar 2003 13:29:29 -0000	1.3
+++ bindbackend2.cc	22 Jun 2003 20:50:45 -0000
@@ -23,6 +23,8 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fstream.h>
+#include <strstream.h>
 
 using namespace std;
 
@@ -50,6 +52,7 @@
 map<u_int32_t,BB2DomainInfo* > Bind2Backend::s_id_zone_map;
 int Bind2Backend::s_first=1;
 pthread_mutex_t Bind2Backend::s_startup_lock=PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Bind2Backend::s_zonemap_lock=PTHREAD_MUTEX_INITIALIZER;
 
 /* when a query comes in, we find the most appropriate zone and answer from that */
 
@@ -440,6 +443,9 @@
 
 void Bind2Backend::loadConfig(string* status)
 {
+  // Interference with createSlaveDomain()
+  Lock l(&s_zonemap_lock);
+  
   static int domain_id=1;
   nbbds.clear();
   if(!getArg("config").empty()) {
@@ -764,6 +770,90 @@
   return false;
 }
 
+bool Bind2Backend::superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db)
+{
+  // Check whether we have a configfile available.
+  if (getArg("supermaster-config").empty())
+    return false;
+
+  ifstream c_if(getArg("supermasters").c_str(), ios::nocreate);
+  if (!c_if) {
+    L << Logger::Error << "Unable to open supermasters file for read: " << stringerror() << endl;
+    return false;
+  }
+
+  // Format:
+  // <ip> <accountname>
+  string line, sip, saccount;
+  while (getline(c_if, line)) {
+    istrstream ii(line.c_str());
+    ii >> sip;
+    if (sip == ip) {
+      ii >> saccount;
+      break;
+    }
+  } 
+  c_if.close();
+
+  if (sip != ip)  // ip not found in authorization list - reject
+    return false;
+  
+  // ip authorized as supermaster - accept
+  *db = this;
+  if (saccount.length() > 0)
+      *account = saccount.c_str();
+
+  return true;
+}
+
+bool Bind2Backend::createSlaveDomain(const string &ip, const string &domain, const string &account)
+{
+  // Interference with loadConfig(), use locking
+  Lock l(&s_zonemap_lock);
+
+  string filename = getArg("supermaster-destdir")+'/'+domain;
+  
+  L << Logger::Warning << d_logprefix
+    << " Writing bind config zone statement for superslave zone '" << domain
+    << "' from supermaster " << ip << endl;
+        
+  ofstream c_of(getArg("supermaster-config").c_str(), ios::nocreate | ios::app);
+  if (!c_of) {
+    L << Logger::Error << "Unable to open supermaster configfile for append: " << stringerror() << endl;
+    throw DBException("Unable to open supermaster configfile for append: "+stringerror());
+  }
+  
+  c_of << endl;
+  c_of << "# Superslave zone " << domain << " (added: " << nowTime() << ") (account: " << account << ')' << endl;
+  c_of << "zone \"" << domain << "\" {" << endl;
+  c_of << "\ttype slave;" << endl;
+  c_of << "\tfile \"" << filename << "\";" << endl;
+  c_of << "\tmasters { " << ip << "; };" << endl;
+  c_of << "};" << endl;
+  c_of.close();
+  
+  BB2DomainInfo *bbd = new BB2DomainInfo;
+
+  bbd->d_records = new vector<DNSResourceRecord>;
+  bbd->d_name = domain;
+  bbd->setCheckInterval(getArgAsNum("check-interval"));
+  bbd->d_master = ip;
+  bbd->d_filename = filename;
+
+  // Find a free zone id nr.    
+  if (!s_id_zone_map.empty()) {
+    map<unsigned int, BB2DomainInfo*>::reverse_iterator i = s_id_zone_map.rbegin();
+    bbd->d_id = i->second->d_id + 1;
+  }
+  else
+    bbd->d_id = 0;
+
+  s_id_zone_map[bbd->d_id] = bbd;
+  s_name_id_map[domain] = bbd->d_id;
+  
+  return true;
+}
+
 class Bind2Factory : public BackendFactory
 {
    public:
@@ -774,6 +864,9 @@
          declare(suffix,"config","Location of named.conf","");
          declare(suffix,"example-zones","Install example zones","no");
          declare(suffix,"check-interval","Interval for zonefile changes","0");
+         declare(suffix,"supermaster-config","Location of (part of) named.conf where pdns can write zone-statements to","");
+         declare(suffix,"supermasters","List of IP-addresses of supermasters","");
+         declare(suffix,"supermaster-destdir","Destination directory for newly added slave zones",arg()["config-dir"]);
       }
 
       DNSBackend *make(const string &suffix="")
Index: bindbackend2.hh
===================================================================
RCS file: /var/cvsroot/pdns/pdns/backends/bind/bindbackend2.hh,v
retrieving revision 1.1
diff -u -B -b -r1.1 bindbackend2.hh
--- bindbackend2.hh	9 Mar 2003 15:39:18 -0000	1.1
+++ bindbackend2.hh	22 Jun 2003 20:50:45 -0000
@@ -195,6 +195,11 @@
   void rediscover(string *status=0);
 
   bool isMaster(const string &name, const string &ip);
+
+  // for supermaster support
+  bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db);
+  bool createSlaveDomain(const string &ip, const string &domain, const string &account);
+  
 private:
   class handle
   {
@@ -231,6 +236,7 @@
   static map<string,int> s_name_id_map;
   static map<u_int32_t,BB2DomainInfo* > s_id_zone_map;
   static int s_first;
+  static pthread_mutex_t s_zonemap_lock;
 
   string d_logprefix;
   int d_transaction_id;
