]> granicus.if.org Git - pdns/commitdiff
Remove serializeSOAData, refactor calculate/edit/increaseSOA
authorChristian Hofstaedtler <christian.hofstaedtler@deduktiva.com>
Thu, 6 Oct 2016 22:10:16 +0000 (00:10 +0200)
committerChris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
Fri, 5 Jan 2018 22:32:05 +0000 (23:32 +0100)
19 files changed:
modules/luabackend/luabackend.hh
modules/luabackend/minimal.cc
modules/mydnsbackend/mydnsbackend.cc
modules/mydnsbackend/mydnsbackend.hh
modules/opendbxbackend/odbxbackend.cc
modules/opendbxbackend/odbxbackend.hh
pdns/dns.hh
pdns/dnsbackend.cc
pdns/dnsbackend.hh
pdns/dnsrecords.cc
pdns/dnsseckeeper.hh
pdns/packethandler.cc
pdns/pdnsutil.cc
pdns/rfc2136handler.cc
pdns/serialtweaker.cc
pdns/tcpreceiver.cc
pdns/ueberbackend.cc
pdns/ueberbackend.hh
pdns/ws-auth.cc

index 52e26ea96f4ab8a2b317ca5af575a410772d542a..b96fdadff4d12de29eea13c69f7b6da70dbaf4d6 100644 (file)
@@ -58,7 +58,7 @@ public:
     void lookup(const QType &qtype, const DNSName &qname, DNSPacket *p, int domain_id) override;
     bool get(DNSResourceRecord &rr) override;
     //! fills the soadata struct with the SOA details. Returns false if there is no SOA.
-    bool getSOA(const DNSName &name, SOAData &soadata) override;
+    bool getSOA(const DNSName &name, SOAData &soadata, bool unmodifiedSerial) override;
 
 
 //  MASTER BACKEND
index 1f7015881458e45b78d19914ab0127879bed1f68..24b3e7e4afe581c7d864b0a3615234f7247ff662 100644 (file)
@@ -176,7 +176,7 @@ bool LUABackend::get(DNSResourceRecord &rr) {
     return !rr.content.empty();
 }
 
-bool LUABackend::getSOA(const DNSName &name, SOAData &soadata) {
+bool LUABackend::getSOA(const DNSName &name, SOAData &soadata, bool unmodifiedSerial) {
     if (logging)
        L << Logger::Info << backend_name << "(getsoa) BEGIN" << endl;
 
index ec521ceb49a2e7b4b085a039efd0b0722683151e..0a4f86e28de85a06f3269836a962d963eff991aa 100644 (file)
@@ -196,7 +196,7 @@ bool MyDNSBackend::list(const DNSName &target, int zoneId, bool include_disabled
   return true;
 }
 
-bool MyDNSBackend::getSOA(const DNSName& name, SOAData& soadata) {
+bool MyDNSBackend::getSOA(const DNSName& name, SOAData& soadata, bool unmodifiedSerial) {
   string query;
   SSqlStatement::row_t rrow;
 
index 6bd1e13d3401e6a59cebb4a25e7ba6e5d28ab8ed..434b51f2e88c48f1b3b387f937c733d564888e39 100644 (file)
@@ -39,8 +39,9 @@ public:
   void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1) override;
   bool list(const DNSName &target, int domain_id, bool include_disabled=false) override;
   bool get(DNSResourceRecord &r) override;
-  bool getSOA(const DNSName& name, SOAData& soadata) override;
+  bool getSOA(const DNSName& name, SOAData& soadata, bool unmodifiedSerial) override;
   void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false) override;
+
 private:
   SMySQL *d_db; 
 
index 06fb890a892a1225d7d562c11ea1e69b3d70b3f3..e8d37f1cc99d0442cf342dc08ca98f26a1697916 100644 (file)
@@ -179,7 +179,7 @@ bool OdbxBackend::getDomainInfo( const DNSName& domain, DomainInfo& di )
 
 
 
-bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd)
+bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd, bool unmodifiedSerial)
 {
         const char* tmp;
 
@@ -210,7 +210,7 @@ bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd)
                                sd.ttl = strtoul( tmp, NULL, 10 );
                        }
 
-                       if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
+                       if( !unmodifiedSerial && sd.serial == 0 && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
                        {
                                sd.serial = strtol( tmp, NULL, 10 );
                        }
index 97cae120702b758c468fb9456000563e0fe83d8f..6ebaf5e356299a03ede2ffeca41fad626f3ea6c9 100644 (file)
@@ -77,7 +77,7 @@ public:
         ~OdbxBackend();
 
         void lookup( const QType& qtype, const DNSName& qdomain, DNSPacket* p = 0, int zoneid = -1 ) override;
-        bool getSOA( const DNSName& domain, SOAData& sd ) override;
+        bool getSOA( const DNSName& domain, SOAData& sd, bool unmodifiedSerial ) override;
         bool list( const DNSName& target, int domain_id, bool include_disabled=false ) override;
         bool get( DNSResourceRecord& rr ) override;
 
index 88a658c5a52ff384a06382bbd4b7998d101d2b78..837e235198bc26abf692f58b2c4edf8de284598e 100644 (file)
@@ -236,6 +236,4 @@ struct TSIGTriplet
   string secret;
 };
 
-/** for use by DNSPacket, converts a SOAData class to a ascii line again */
-string serializeSOAData(const SOAData &data);
 string &attodot(string &str);  //!< for when you need to insert an email address in the SOA
index 5fca2b903de903a6480c3c3b47fededcdc7bbe8d..c9705f7dbe2ff4769bd55b5cf94f6f296ebdc359 100644 (file)
@@ -213,8 +213,9 @@ vector<DNSBackend *>BackendMakerClass::all(bool metadataOnly)
 
     \param domain Domain we want to get the SOA details of
     \param sd SOAData which is filled with the SOA details
+    \param unmodifiedSerial bool if set, serial will be returned as stored in the backend (maybe 0)
 */
-bool DNSBackend::getSOA(const DNSName &domain, SOAData &sd)
+bool DNSBackend::getSOA(const DNSName &domain, SOAData &sd, bool unmodifiedSerial)
 {
   this->lookup(QType(QType::SOA),domain);
 
@@ -247,7 +248,7 @@ bool DNSBackend::getSOA(const DNSName &domain, SOAData &sd)
       sd.hostmaster=DNSName("hostmaster")+domain;
   }
 
-  if(!sd.serial) { // magic time!
+  if(!unmodifiedSerial && !sd.serial) { // magic time!
     DLOG(L<<Logger::Warning<<"Doing SOA serial number autocalculation for "<<rr.qname<<endl);
 
     time_t serial;
@@ -416,12 +417,3 @@ void fillSOAData(const string &content, SOAData &data)
     throw PDNSException("Out of range exception parsing "+content);
   }
 }
-
-string serializeSOAData(const SOAData &d)
-{
-  ostringstream o;
-  //  nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
-  o<<d.nameserver.toString()<<" "<< d.hostmaster.toString() <<" "<< d.serial <<" "<< d.refresh << " "<< d.retry << " "<< d.expire << " "<< d.default_ttl;
-
-  return o.str();
-}
index 16ec7c5c4a5ab8820b1b70d5c1674cab6f442328..1c7c22a8735c2b6a9ee9f2b3ee37a58339d0b2ba 100644 (file)
@@ -125,7 +125,7 @@ public:
   virtual ~DNSBackend(){};
 
   //! fills the soadata struct with the SOA details. Returns false if there is no SOA.
-  virtual bool getSOA(const DNSName &name, SOAData &soadata);
+  virtual bool getSOA(const DNSName &name, SOAData &soadata, bool unmodifiedSerial=false);
 
   //! Calculates a SOA serial for the zone and stores it in the third argument.
   virtual bool calculateSOASerial(const DNSName& domain, const SOAData& sd, time_t& serial);
index 418cead8df9adfca7d10b9c10620b32ee05a472c..6bce4901300adf8897d94a9d2198bc9aa22762bb 100644 (file)
@@ -268,7 +268,7 @@ SOARecordContent::SOARecordContent(const DNSName& mname, const DNSName& rname, c
   d_st=st;
 }
 
-boilerplate_conv(SOA, QType::SOA, 
+boilerplate_conv(SOA, QType::SOA,
                  conv.xfrName(d_mname, true);
                  conv.xfrName(d_rname, true);
                  conv.xfr32BitInt(d_st.serial);
index 61b17ae571fb07b4cffbc0143071740909b658f5..3e50a584f37d88557bc6bdf39a243368e4a8f703 100644 (file)
@@ -298,11 +298,8 @@ public:
 class DNSPacket;
 uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq);
 // for SOA-EDIT
-uint32_t calculateEditSOA(const DNSZoneRecord& rr, const string& kind);
-uint32_t calculateEditSOA(const SOAData& sd, const string& kind);
-bool editSOA(DNSSECKeeper& dk, const DNSName& qname, DNSPacket* dp);
-bool editSOARecord(DNSZoneRecord& rr, const string& kind);
+uint32_t calculateEditSOA(uint32_t old_serial, DNSSECKeeper& dk, const DNSName& zonename);
+uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename);
 // for SOA-EDIT-DNSUPDATE/API
-uint32_t calculateIncreaseSOA(SOAData sd, const string& increaseKind, const string& editKind);
-bool increaseSOARecord(DNSResourceRecord& rr, const string& increaseKind, const string& editKind);
-bool increaseSOARecord(DNSZoneRecord& rr, const string& increaseKind, const string& editKind);
+bool increaseSOARecord(DNSResourceRecord& dr, const string& increaseKind, const string& editKind);
+bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout);
index 2d4451f3088bc40a12d32eb9d282b8ff64977417..6f18b63d0e31d4ca9daa2df80a78fe0473ab7f69 100644 (file)
@@ -1058,8 +1058,6 @@ DNSPacket *PacketHandler::doQuestion(DNSPacket *p)
   DNSZoneRecord rr;
   SOAData sd;
 
-  // string subdomain="";
-  string soa;
   int retargetcount=0;
   set<DNSName> authSet;
 
@@ -1253,6 +1251,7 @@ DNSPacket *PacketHandler::doQuestion(DNSPacket *p)
     if(p->qtype.getCode() == QType::SOA && sd.qname==p->qdomain) {
       rr.dr.d_name=sd.qname;
       rr.dr.d_type=QType::SOA;
+      sd.serial = calculateEditSOA(sd.serial, d_dk, sd.qname);
       rr.dr.d_content=makeSOAContent(sd);
       rr.dr.d_ttl=sd.ttl;
       rr.domain_id=sd.domain_id;
@@ -1322,9 +1321,10 @@ DNSPacket *PacketHandler::doQuestion(DNSPacket *p)
 
     /* Add in SOA if required */
     if(target==sd.qname) {
+        rr.dr.d_name = sd.qname;
         rr.dr.d_type = QType::SOA;
+        sd.serial = calculateEditSOA(sd.serial, d_dk, sd.qname);
         rr.dr.d_content = makeSOAContent(sd);
-        rr.dr.d_name = sd.qname;
         rr.dr.d_ttl = sd.ttl;
         rr.domain_id = sd.domain_id;
         rr.auth = true;
@@ -1435,8 +1435,6 @@ DNSPacket *PacketHandler::doQuestion(DNSPacket *p)
       return 0;
     }
 
-    editSOA(d_dk, sd.qname, r);
-    
     for(const auto& loopRR: r->getRRS()) {
       if(loopRR.scopeMask) {
         noCache=true;
index 1d677f445befcc3b69c2b85891101ecb978747c9..d0fbb99c9fcc163fd5e8832370061fa6cbebaf1e 100644 (file)
@@ -586,53 +586,16 @@ int increaseSerial(const DNSName& zone, DNSSECKeeper &dk)
     cerr<<"Serial increase of presigned zone '"<<zone<<"' is not allowed."<<endl;
     return -1;
   }
-  
+
   string soaEditKind;
   dk.getSoaEdit(zone, soaEditKind);
 
-  sd.db->lookup(QType(QType::SOA), zone);
-  vector<DNSResourceRecord> rrs;
   DNSResourceRecord rr;
-  DNSZoneRecord szr;
-  while (sd.db->get(rr)) {
-    if (rr.qtype.getCode() == QType::SOA) {
-      rrs.push_back(rr);
-      szr.dr=DNSRecord(rr) ;
-    }
-  } 
-
-  if (rrs.size() > 1) {
-    cerr<<rrs.size()<<" SOA records found for "<<zone<<"!"<<endl;
-    return -1;
-  }
-  if (rrs.size() < 1) {
-     cerr<<zone<<" not found!"<<endl;
-  }
-  
-  if (soaEditKind.empty()) {
-    sd.serial++;
-  }
-  else if(pdns_iequals(soaEditKind,"INCREMENT-WEEKS")) {
-    sd.serial++;
-  }
-  else if(pdns_iequals(soaEditKind,"INCEPTION-INCREMENT")) {
-    uint32_t today_serial = localtime_format_YYYYMMDDSS(time(NULL), 1);
-
-    if (sd.serial < today_serial) {
-      sd.serial = today_serial;
-    }
-    else {
-      sd.serial++;
-    }
-  }
-  else {
-    sd.serial = calculateEditSOA(szr, soaEditKind) + 1;
-  }
-  rrs[0].content = serializeSOAData(sd);
+  makeIncreasedSOARecord(sd, "SOA-EDIT-INCREASE", soaEditKind, rr);
 
   sd.db->startTransaction(zone, -1);
 
-  if (! sd.db->replaceRRSet(sd.domain_id, zone, rr.qtype, rrs)) {
+  if (!sd.db->replaceRRSet(sd.domain_id, zone, rr.qtype, vector<DNSResourceRecord>(1, rr))) {
    sd.db->abortTransaction();
    cerr<<"Backend did not replace SOA record. Backend might not support this operation."<<endl;
    return -1;
@@ -650,8 +613,8 @@ int increaseSerial(const DNSName& zone, DNSSECKeeper &dk)
     } else
       ordername=zone;
     if(g_verbose)
-      cerr<<"'"<<rrs[0].qname<<"' -> '"<< ordername <<"'"<<endl;
-    sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, rrs[0].qname, ordername, true);
+      cerr<<"'"<<rr.qname<<"' -> '"<< ordername <<"'"<<endl;
+    sd.db->updateDNSSECOrderNameAndAuth(sd.domain_id, rr.qname, ordername, true);
   }
 
   sd.db->commitTransaction();
@@ -1045,7 +1008,7 @@ int createZone(const DNSName &zone, const DNSName& nsname) {
   ).str();
   SOAData sd;
   fillSOAData(soa, sd);  // fills out default values for us
-  rr.content = DNSRecordContent::mastermake(rr.qtype.getCode(), 1, serializeSOAData(sd))->getZoneRepresentation(true);
+  rr.content = makeSOAContent(sd)->getZoneRepresentation(true);
   rr.domain_id = di.id;
   di.backend->startTransaction(zone, di.id);
   di.backend->feedRecord(rr, DNSName());
index b4d0ab963c1a25b19763f82ae4456e1dfa6b5dc4..d6a7d64637c51fa389195b8764b7b587e797042b 100644 (file)
@@ -1015,22 +1015,14 @@ int PacketHandler::processUpdate(DNSPacket *p) {
 }
 
 void PacketHandler::increaseSerial(const string &msgPrefix, const DomainInfo *di, bool haveNSEC3, bool narrow, const NSEC3PARAMRecordContent *ns3pr) {
-  DNSResourceRecord rec, newRec;
-  di->backend->lookup(QType(QType::SOA), di->zone);
-  bool foundSOA=false;
-  while (di->backend->get(rec)) {
-    newRec = rec;
-    foundSOA=true;
-  }
-  if (!foundSOA) {
+  SOAData sd;
+  if (!di->backend->getSOA(di->zone, sd, true)) {
     throw PDNSException("SOA-Serial update failed because there was no SOA. Wowie.");
   }
-  SOAData soa2Update;
-  fillSOAData(rec.content, soa2Update);
-  uint32_t oldSerial = soa2Update.serial;
 
+  uint32_t oldSerial = sd.serial;
   if (oldSerial == 0) { // using Autoserial, leave the serial alone.
-    L<<Logger::Notice<<msgPrefix<<"AutoSerial being used, not updating SOA serial."<<endl;
+    L<<Logger::Notice<<msgPrefix<<"AutoSerial in use in domain \""<<di->zone.toLogString()<<"\", not updating SOA serial."<<endl;
     return;
   }
 
@@ -1044,33 +1036,28 @@ void PacketHandler::increaseSerial(const string &msgPrefix, const DomainInfo *di
       string soaEditSetting;
       d_dk.getSoaEdit(di->zone, soaEditSetting);
       if (soaEditSetting.empty()) {
-        L<<Logger::Error<<msgPrefix<<"Using "<<soaEdit2136<<" for SOA-EDIT-DNSUPDATE increase on DNS update, but SOA-EDIT is not set for domain \""<< di->zone <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"<<endl;
+        L<<Logger::Error<<msgPrefix<<"Using "<<soaEdit2136<<" for SOA-EDIT-DNSUPDATE increase on DNS update, but SOA-EDIT is not set for domain \""<< di->zone.toLogString() <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"<<endl;
         soaEdit2136 = "DEFAULT";
       } else
         soaEdit = soaEditSetting;
     }
   }
 
-  soa2Update.serial = calculateIncreaseSOA(soa2Update, soaEdit2136, soaEdit);
-
-  newRec.content = serializeSOAData(soa2Update);
-  vector<DNSResourceRecord> rrset;
-  rrset.push_back(newRec);
-  di->backend->replaceRRSet(di->id, newRec.qname, newRec.qtype, rrset);
-  L<<Logger::Notice<<msgPrefix<<"Increasing SOA serial ("<<oldSerial<<" -> "<<soa2Update.serial<<")"<<endl;
-
-  //Correct ordername + auth flag
-  if (haveNSEC3 && narrow)
-    di->backend->updateDNSSECOrderNameAndAuth(di->id, newRec.qname, DNSName(), true);
-  else if (haveNSEC3) {
-    DNSName ordername;
-    if (!narrow)
-      ordername = DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, newRec.qname)));
-
-    di->backend->updateDNSSECOrderNameAndAuth(di->id, newRec.qname, ordername, true);
-  }
-  else { // NSEC
-    DNSName ordername=newRec.qname.makeRelative(di->zone);
-    di->backend->updateDNSSECOrderNameAndAuth(di->id, newRec.qname, ordername, true);
+  DNSResourceRecord rr;
+  if (makeIncreasedSOARecord(sd, soaEdit2136, soaEdit, rr)) {
+    di->backend->replaceRRSet(di->id, rr.qname, rr.qtype, vector<DNSResourceRecord>(1, rr));
+    L << Logger::Notice << msgPrefix << "Increasing SOA serial (" << oldSerial << " -> " << sd.serial << ")" << endl;
+
+    //Correct ordername + auth flag
+    if (haveNSEC3) {
+      DNSName ordername;
+      if (!narrow)
+        ordername = DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr, rr.qname)));
+
+      di->backend->updateDNSSECOrderNameAndAuth(di->id, rr.qname, ordername, true);
+    } else { // NSEC
+      DNSName ordername = rr.qname.makeRelative(di->zone);
+      di->backend->updateDNSSECOrderNameAndAuth(di->id, rr.qname, ordername, true);
+    }
   }
 }
index fa7a0fd69f3cdedf0d2de08f42460993a85bfa52..a8a0a01c7426706caf5a53ddca237d5396e37a0d 100644 (file)
@@ -27,7 +27,6 @@
 #include "dnspacket.hh"
 #include "namespaces.hh"
 
-
 uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq)
 {
   struct tm tm;
@@ -39,87 +38,62 @@ uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq)
     + seq;
 }
 
-bool editSOA(DNSSECKeeper& dk, const DNSName& qname, DNSPacket* dp)
+uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename)
 {
-  for(auto& rr :  dp->getRRS()) {
-    if(rr.dr.d_type == QType::SOA && rr.dr.d_name == qname) {
-      string kind;
-      dk.getSoaEdit(qname, kind);
-      return editSOARecord(rr, kind);
-    }
-  }
-  return false;
-}
-
-bool editSOARecord(DNSZoneRecord& rr, const string& kind) {
-  if(kind.empty())
-    return false;
-  auto src = getRR<SOARecordContent>(rr.dr);
-  src->d_st.serial=calculateEditSOA(rr, kind);
-
-  return true;
-}
-
-uint32_t calculateEditSOA(const DNSZoneRecord& rr, const string& kind)
-{
-  auto src = getRR<SOARecordContent>(rr.dr);
   if(pdns_iequals(kind,"INCEPTION-INCREMENT")) {
     time_t inception = getStartOfWeek();
     uint32_t inception_serial = localtime_format_YYYYMMDDSS(inception, 1);
     uint32_t dont_increment_after = localtime_format_YYYYMMDDSS(inception + 2*86400, 99);
 
-    if(src->d_st.serial < inception_serial - 1) { /* less than <inceptionday>00 */
+    if(old_serial < inception_serial - 1) { /* less than <inceptionday>00 */
       return inception_serial; /* return <inceptionday>01   (skipping <inceptionday>00 as possible value) */
-    } else if(src->d_st.serial <= dont_increment_after) { /* >= <inceptionday>00 but <= <inceptionday+2>99 */
-      return (src->d_st.serial + 2); /* "<inceptionday>00" and "<inceptionday>01" are reserved for inception increasing, so increment sd.serial by two */
+    } else if(old_serial <= dont_increment_after) { /* >= <inceptionday>00 but <= <inceptionday+2>99 */
+      return (old_serial + 2); /* "<inceptionday>00" and "<inceptionday>01" are reserved for inception increasing, so increment sd.serial by two */
     }
   }
   else if(pdns_iequals(kind,"INCREMENT-WEEKS")) {
     time_t inception = getStartOfWeek();
-    return (src->d_st.serial + (inception / (7*86400)));
+    return (old_serial + (inception / (7*86400)));
   }
   else if(pdns_iequals(kind,"EPOCH")) {
     return time(0);
   }
   else if(pdns_iequals(kind,"INCEPTION-EPOCH")) {
     uint32_t inception = getStartOfWeek();
-    if (src->d_st.serial < inception)
+    if (old_serial < inception)
       return inception;
   } else if(!kind.empty()) {
-    L<<Logger::Warning<<"SOA-EDIT type '"<<kind<<"' for zone "<<rr.dr.d_name<<" is unknown."<<endl;
+    L<<Logger::Warning<<"SOA-EDIT type '"<<kind<<"' for zone "<<zonename<<" is unknown."<<endl;
   }
-  return src->d_st.serial;
+  return old_serial;
 }
 
-uint32_t calculateEditSOA(const SOAData& sd, const string& kind)
-{
-  DNSZoneRecord dzr;
-  dzr.dr.d_name=sd.qname;
-  struct soatimes st;
-  st.serial = sd.serial;
-  dzr.dr.d_content = std::make_shared<SOARecordContent>(sd.nameserver, sd.hostmaster, st);
-  return calculateEditSOA(dzr, kind);
+uint32_t calculateEditSOA(uint32_t old_serial, DNSSECKeeper& dk, const DNSName& zonename) {
+  string kind;
+  dk.getSoaEdit(zonename, kind);
+  if(kind.empty())
+    return old_serial;
+  return calculateEditSOA(old_serial, kind, zonename);
 }
 
-// Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API.
-uint32_t calculateIncreaseSOA(DNSZoneRecord& dzr, const string& increaseKind, const string& editKind) {
-  auto src = getRR<SOARecordContent>(dzr.dr);
+/** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API. */
+static uint32_t calculateIncreaseSOA(uint32_t old_serial, const string& increaseKind, const string& editKind, const DNSName& zonename) {
   // These only work when SOA-EDIT is set, otherwise fall back to default.
   if (!editKind.empty()) {
     if (pdns_iequals(increaseKind, "SOA-EDIT-INCREASE")) {
-      uint32_t new_serial = calculateEditSOA(dzr, editKind);
-      if (new_serial <= src->d_st.serial) {
-        new_serial = src->d_st.serial + 1;
+      uint32_t new_serial = calculateEditSOA(old_serial, editKind, zonename);
+      if (new_serial <= old_serial) {
+        new_serial = old_serial + 1;
       }
       return new_serial;
     }
     else if (pdns_iequals(increaseKind, "SOA-EDIT")) {
-      return calculateEditSOA(dzr, editKind);
+      return calculateEditSOA(old_serial, editKind, zonename);
     }
   }
 
   if (pdns_iequals(increaseKind, "INCREASE")) {
-    return src->d_st.serial + 1;
+    return old_serial + 1;
   }
   else if (pdns_iequals(increaseKind, "EPOCH")) {
     return time(0);
@@ -132,31 +106,47 @@ uint32_t calculateIncreaseSOA(DNSZoneRecord& dzr, const string& increaseKind, co
   boost::format fmt("%04d%02d%02d%02d");
   string newdate = (fmt % (tm.tm_year + 1900) % (tm.tm_mon + 1) % tm.tm_mday % 1).str();
   uint32_t new_serial = pdns_stou(newdate);
-  if (new_serial <= src->d_st.serial) {
-    new_serial = src->d_st.serial + 1;
+  if (new_serial <= old_serial) {
+      new_serial = old_serial + 1;
   }
   return new_serial;
 }
 
-// Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API.
-uint32_t calculateIncreaseSOA(SOAData sd, const string& increaseKind, const string& editKind) {
-  DNSZoneRecord dzr;
-  dzr.dr.d_name=sd.qname;
-  struct soatimes st;
-  st.serial = sd.serial;
-  dzr.dr.d_content = std::make_shared<SOARecordContent>(sd.nameserver, sd.hostmaster, st);
-  return calculateIncreaseSOA(dzr, increaseKind, editKind);
-}
-
-
-
+/** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API.
+ * Good if you already *have* a DNSResourceRecord.
+ * Content in rr is suitable for writing into a backend.
+ *
+ * @return true if changes may have been made
+ */
 bool increaseSOARecord(DNSResourceRecord& rr, const string& increaseKind, const string& editKind) {
   if (increaseKind.empty())
     return false;
 
   SOAData sd;
   fillSOAData(rr.content, sd);
-  sd.serial = calculateIncreaseSOA(sd, increaseKind, editKind);
-  rr.content = serializeSOAData(sd);
+
+  sd.serial = calculateIncreaseSOA(sd.serial, increaseKind, editKind, rr.qname);
+  rr.content = makeSOAContent(sd)->getZoneRepresentation(true);
+  return true;
+}
+
+/** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API.
+ * Makes a mostly reset DNSResourceRecord for you in @param rrout.
+ * Content in rrout is suitable for writing into a backend.
+ *
+ * @return true if rrout is now valid
+ */
+bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout) {
+  if (increaseKind.empty())
+    return false;
+
+  sd.serial = calculateIncreaseSOA(sd.serial, increaseKind, editKind, sd.qname);
+  rrout.qname = sd.qname;
+  rrout.content = makeSOAContent(sd)->getZoneRepresentation(true);
+  rrout.qtype = QType::SOA;
+  rrout.domain_id = sd.domain_id;
+  rrout.auth = 1;
+  rrout.ttl = sd.ttl;
+
   return true;
 }
index eece6994ff90a3fe28a2ea3f3f6b072bffd47169..3e4c00e5967acdf8cc8a1a78cf75673c3f06d982 100644 (file)
@@ -535,16 +535,23 @@ namespace {
     bool d_auth;
   };
 
-  DNSResourceRecord makeDNSRRFromSOAData(const SOAData& sd)
+  DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd)
   {
-    DNSResourceRecord soa;
-    soa.qname= sd.qname;
-    soa.qtype=QType::SOA;
-    soa.content=serializeSOAData(sd);
-    soa.ttl=sd.ttl;
-    soa.domain_id=sd.domain_id;
-    soa.auth = true;
-    return soa;
+    SOAData edited = sd;
+    edited.serial = calculateEditSOA(sd.serial, dk, sd.qname);
+
+    DNSRecord soa;
+    soa.d_name = sd.qname;
+    soa.d_type = QType::SOA;
+    soa.d_ttl = sd.ttl;
+    soa.d_place = DNSResourceRecord::ANSWER;
+    soa.d_content = makeSOAContent(edited);
+
+    DNSZoneRecord dzr;
+    dzr.auth = true;
+    dzr.dr = soa;
+
+    return dzr;
   }
 
   shared_ptr<DNSPacket> getFreshAXFRPacket(shared_ptr<DNSPacket> q)
@@ -655,16 +662,8 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr<DNSPacket> q, int ou
   
   // SOA *must* go out first, our signing pipe might reorder
   DLOG(L<<"Sending out SOA"<<endl);
-  DNSResourceRecord soa = makeDNSRRFromSOAData(sd);
-  DNSZoneRecord dzrsoa;
-  dzrsoa.auth=true;
-  dzrsoa.dr=DNSRecord(soa);
-
-  string kind;
-  dk.getSoaEdit(sd.qname, kind);
-  editSOARecord(dzrsoa, kind);
-
-  outpacket->addRecord(dzrsoa);
+  DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd);
+  outpacket->addRecord(soa);
   if(securedZone && !presignedZone) {
     set<DNSName> authSet;
     authSet.insert(target);
@@ -1052,7 +1051,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr<DNSPacket> q, int ou
   DLOG(L<<"Done writing out records"<<endl);
   /* and terminate with yet again the SOA record */
   outpacket=getFreshAXFRPacket(q);
-  outpacket->addRecord(dzrsoa);
+  outpacket->addRecord(soa);
   if(haveTSIGDetails && !tsigkeyname.empty())
     outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); 
   
@@ -1148,9 +1147,7 @@ int TCPNameserver::doIXFR(shared_ptr<DNSPacket> q, int outsock)
     return 0;
   }
 
-  string soaedit;
-  dk.getSoaEdit(target, soaedit);
-  if (!rfc1982LessThan(serial, calculateEditSOA(sd, soaedit))) {
+  if (!rfc1982LessThan(serial, calculateEditSOA(sd.serial, dk, sd.qname))) {
     TSIGRecordContent trc;
     DNSName tsigkeyname;
     string tsigsecret;
@@ -1177,13 +1174,8 @@ int TCPNameserver::doIXFR(shared_ptr<DNSPacket> q, int outsock)
 
     // SOA *must* go out first, our signing pipe might reorder
     DLOG(L<<"Sending out SOA"<<endl);
-    DNSResourceRecord soa = makeDNSRRFromSOAData(sd);
-    DNSZoneRecord dzrsoa;
-    dzrsoa.dr=DNSRecord(soa);
-    dzrsoa.auth=true;
-    
-    outpacket->addRecord(dzrsoa);
-    editSOA(dk, sd.qname, outpacket.get());
+    DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd);
+    outpacket->addRecord(soa);
     if(securedZone) {
       set<DNSName> authSet;
       authSet.insert(target);
index b30783d8bb697eef04c60b8c88018bb28b60e5d1..9c299be55633abd04227f9c51582005595f19468 100644 (file)
@@ -378,18 +378,18 @@ bool UeberBackend::getSOA(const DNSName &domain, SOAData &sd)
   }
 
   // not found in neg. or pos. cache, look it up
-  return getSOAUncached(domain, sd);
+  return getSOAUncached(domain, sd, false);
 }
 
-bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd)
+bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd, bool unmodifiedSerial)
 {
   d_question.qtype=QType::SOA;
   d_question.qname=domain;
   d_question.zoneId=-1;
 
   for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
-    if((*i)->getSOA(domain, sd)) {
-      if( d_cache_ttl ) {
+    if((*i)->getSOA(domain, sd, unmodifiedSerial)) {
+      if(d_cache_ttl && !unmodifiedSerial) {
         DNSZoneRecord rr;
         rr.dr.d_name = sd.qname;
         rr.dr.d_type = QType::SOA;
index 63729d4a6ce2afd52ce3829856452740b45deccf..9ce54b0c1aa1dd2f6af03a96d3bf777af82ecbdd 100644 (file)
@@ -101,7 +101,9 @@ public:
   /** Determines if we are authoritative for a zone, and at what level */
   bool getAuth(const DNSName &target, const QType &qtype, SOAData* sd, bool cachedOk=true);
   bool getSOA(const DNSName &domain, SOAData &sd);
-  bool getSOAUncached(const DNSName &domain, SOAData &sd);  // same, but ignores cache
+  /** Load SOA info from backends, ignoring the cache. Callers that will write to the backend should use this
+   * function, possibly setting unmodifiedSerial=true when editing the SOA Serial. */
+  bool getSOAUncached(const DNSName &domain, SOAData &sd, bool unmodifiedSerial=false);
   bool get(DNSZoneRecord &r);
   void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false);
 
index f6b56eb84d1a2d3491acdeb1cfc698e4e5b4d6a5..9f8b9e7ac2f09779a279a5550d8dbe4cd221fcea 100644 (file)
@@ -1255,8 +1255,6 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp) {
       if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) {
         have_soa = true;
         increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
-        // fixup dots after serializeSOAData/increaseSOARecord
-        rr.content = makeBackendRecordContent(rr.qtype, rr.content);
       }
       if (rr.qtype.getCode() == QType::NS && rr.qname==zonename) {
         have_zone_ns = true;
@@ -1271,18 +1269,16 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp) {
 
     if (!have_soa && zonekind != DomainInfo::Slave) {
       // synthesize a SOA record so the zone "really" exists
-      string soa = (boost::format("%s %s %lu")
+      string soa = (boost::format("%s %s %ul")
         % ::arg()["default-soa-name"]
         % (::arg().isEmpty("default-soa-mail") ? (DNSName("hostmaster.") + zonename).toString() : ::arg()["default-soa-mail"])
         % document["serial"].int_value()
       ).str();
       SOAData sd;
       fillSOAData(soa, sd);  // fills out default values for us
-      autorr.qtype = "SOA";
-      autorr.content = serializeSOAData(sd);
+      autorr.qtype = QType::SOA;
+      autorr.content = makeSOAContent(sd)->getZoneRepresentation(true);
       increaseSOARecord(autorr, soa_edit_api_kind, soa_edit_kind);
-      // fixup dots after serializeSOAData/increaseSOARecord
-      autorr.content = makeBackendRecordContent(autorr.qtype, autorr.content);
       new_records.push_back(autorr);
     }
 
@@ -1299,7 +1295,7 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp) {
       } catch (...) {
         throw ApiException("Unable to parse DNS Name for NS '" + nameserver + "'");
       }
-      autorr.qtype = "NS";
+      autorr.qtype = QType::NS;
       new_records.push_back(autorr);
       if (have_zone_ns) {
         throw ApiException("Nameservers list MUST NOT be mixed with zone-level NS in rrsets");
@@ -1557,16 +1553,7 @@ static void storeChangedPTRs(UeberBackend& B, vector<DNSResourceRecord>& new_ptr
     sd.db->getDomainMetadataOne(sd.qname, "SOA-EDIT-API", soa_edit_api_kind);
     sd.db->getDomainMetadataOne(sd.qname, "SOA-EDIT", soa_edit_kind);
     if (!soa_edit_api_kind.empty()) {
-      soarr.qname = sd.qname;
-      soarr.content = serializeSOAData(sd);
-      soarr.qtype = "SOA";
-      soarr.domain_id = sd.domain_id;
-      soarr.auth = 1;
-      soarr.ttl = sd.ttl;
-      increaseSOARecord(soarr, soa_edit_api_kind, soa_edit_kind);
-      // fixup dots after serializeSOAData/increaseSOARecord
-      soarr.content = makeBackendRecordContent(soarr.qtype, soarr.content);
-      soa_changed = true;
+      soa_changed = makeIncreasedSOARecord(sd, soa_edit_api_kind, soa_edit_kind, soarr);
     }
 
     sd.db->startTransaction(sd.qname);
@@ -1652,7 +1639,6 @@ static void patchZone(HttpRequest* req, HttpResponse* resp) {
             rr.domain_id = di.id;
             if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) {
               soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
-              rr.content = makeBackendRecordContent(rr.qtype, rr.content);
             }
           }
           checkDuplicateRecords(new_records);
@@ -1694,22 +1680,14 @@ static void patchZone(HttpRequest* req, HttpResponse* resp) {
     // edit SOA (if needed)
     if (!soa_edit_api_kind.empty() && !soa_edit_done) {
       SOAData sd;
-      if (!B.getSOA(zonename, sd))
+      if (!B.getSOAUncached(zonename, sd, true))
         throw ApiException("No SOA found for domain '"+zonename.toString()+"'");
 
       DNSResourceRecord rr;
-      rr.qname = zonename;
-      rr.content = serializeSOAData(sd);
-      rr.qtype = "SOA";
-      rr.domain_id = di.id;
-      rr.auth = 1;
-      rr.ttl = sd.ttl;
-      increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
-      // fixup dots after serializeSOAData/increaseSOARecord
-      rr.content = makeBackendRecordContent(rr.qtype, rr.content);
-
-      if (!di.backend->replaceRRSet(di.id, rr.qname, rr.qtype, vector<DNSResourceRecord>(1, rr))) {
-        throw ApiException("Hosting backend does not support editing records.");
+      if (makeIncreasedSOARecord(sd, soa_edit_api_kind, soa_edit_kind, rr)) {
+        if (!di.backend->replaceRRSet(di.id, rr.qname, rr.qtype, vector<DNSResourceRecord>(1, rr))) {
+          throw ApiException("Hosting backend does not support editing records.");
+        }
       }
 
       // return old and new serials in headers