From 13f9e28063d4de4f4dc786e878084c02cea29bab Mon Sep 17 00:00:00 2001 From: Christian Hofstaedtler Date: Fri, 7 Oct 2016 00:10:16 +0200 Subject: [PATCH] Remove serializeSOAData, refactor calculate/edit/increaseSOA --- modules/luabackend/luabackend.hh | 2 +- modules/luabackend/minimal.cc | 2 +- modules/mydnsbackend/mydnsbackend.cc | 2 +- modules/mydnsbackend/mydnsbackend.hh | 3 +- modules/opendbxbackend/odbxbackend.cc | 4 +- modules/opendbxbackend/odbxbackend.hh | 2 +- pdns/dns.hh | 2 - pdns/dnsbackend.cc | 14 +--- pdns/dnsbackend.hh | 2 +- pdns/dnsrecords.cc | 2 +- pdns/dnsseckeeper.hh | 11 +-- pdns/packethandler.cc | 8 +- pdns/pdnsutil.cc | 49 ++--------- pdns/rfc2136handler.cc | 55 +++++------- pdns/serialtweaker.cc | 116 ++++++++++++-------------- pdns/tcpreceiver.cc | 52 +++++------- pdns/ueberbackend.cc | 8 +- pdns/ueberbackend.hh | 4 +- pdns/ws-auth.cc | 42 +++------- 19 files changed, 139 insertions(+), 241 deletions(-) diff --git a/modules/luabackend/luabackend.hh b/modules/luabackend/luabackend.hh index 52e26ea96..b96fdadff 100644 --- a/modules/luabackend/luabackend.hh +++ b/modules/luabackend/luabackend.hh @@ -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 diff --git a/modules/luabackend/minimal.cc b/modules/luabackend/minimal.cc index 1f7015881..24b3e7e4a 100644 --- a/modules/luabackend/minimal.cc +++ b/modules/luabackend/minimal.cc @@ -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; diff --git a/modules/mydnsbackend/mydnsbackend.cc b/modules/mydnsbackend/mydnsbackend.cc index ec521ceb4..0a4f86e28 100644 --- a/modules/mydnsbackend/mydnsbackend.cc +++ b/modules/mydnsbackend/mydnsbackend.cc @@ -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; diff --git a/modules/mydnsbackend/mydnsbackend.hh b/modules/mydnsbackend/mydnsbackend.hh index 6bd1e13d3..434b51f2e 100644 --- a/modules/mydnsbackend/mydnsbackend.hh +++ b/modules/mydnsbackend/mydnsbackend.hh @@ -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 *domains, bool include_disabled=false) override; + private: SMySQL *d_db; diff --git a/modules/opendbxbackend/odbxbackend.cc b/modules/opendbxbackend/odbxbackend.cc index 06fb890a8..e8d37f1cc 100644 --- a/modules/opendbxbackend/odbxbackend.cc +++ b/modules/opendbxbackend/odbxbackend.cc @@ -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 ); } diff --git a/modules/opendbxbackend/odbxbackend.hh b/modules/opendbxbackend/odbxbackend.hh index 97cae1207..6ebaf5e35 100644 --- a/modules/opendbxbackend/odbxbackend.hh +++ b/modules/opendbxbackend/odbxbackend.hh @@ -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; diff --git a/pdns/dns.hh b/pdns/dns.hh index 88a658c5a..837e23519 100644 --- a/pdns/dns.hh +++ b/pdns/dns.hh @@ -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 diff --git a/pdns/dnsbackend.cc b/pdns/dnsbackend.cc index 5fca2b903..c9705f7db 100644 --- a/pdns/dnsbackend.cc +++ b/pdns/dnsbackend.cc @@ -213,8 +213,9 @@ vectorBackendMakerClass::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< 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; diff --git a/pdns/pdnsutil.cc b/pdns/pdnsutil.cc index 1d677f445..d0fbb99c9 100644 --- a/pdns/pdnsutil.cc +++ b/pdns/pdnsutil.cc @@ -586,53 +586,16 @@ int increaseSerial(const DNSName& zone, DNSSECKeeper &dk) cerr<<"Serial increase of presigned zone '"<lookup(QType(QType::SOA), zone); - vector 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<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(1, rr))) { sd.db->abortTransaction(); cerr<<"Backend did not replace SOA record. Backend might not support this operation."< '"<< ordername <<"'"<updateDNSSECOrderNameAndAuth(sd.domain_id, rrs[0].qname, ordername, true); + cerr<<"'"< '"<< ordername <<"'"<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()); diff --git a/pdns/rfc2136handler.cc b/pdns/rfc2136handler.cc index b4d0ab963..d6a7d6463 100644 --- a/pdns/rfc2136handler.cc +++ b/pdns/rfc2136handler.cc @@ -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<zone.toLogString()<<"\", not updating SOA serial."<zone, soaEditSetting); if (soaEditSetting.empty()) { - L<zone <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"<zone.toLogString() <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"< rrset; - rrset.push_back(newRec); - di->backend->replaceRRSet(di->id, newRec.qname, newRec.qtype, rrset); - L< "<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(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); + } } } diff --git a/pdns/serialtweaker.cc b/pdns/serialtweaker.cc index fa7a0fd69..a8a0a01c7 100644 --- a/pdns/serialtweaker.cc +++ b/pdns/serialtweaker.cc @@ -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(rr.dr); - src->d_st.serial=calculateEditSOA(rr, kind); - - return true; -} - -uint32_t calculateEditSOA(const DNSZoneRecord& rr, const string& kind) -{ - auto src = getRR(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 00 */ + if(old_serial < inception_serial - 1) { /* less than 00 */ return inception_serial; /* return 01 (skipping 00 as possible value) */ - } else if(src->d_st.serial <= dont_increment_after) { /* >= 00 but <= 99 */ - return (src->d_st.serial + 2); /* "00" and "01" are reserved for inception increasing, so increment sd.serial by two */ + } else if(old_serial <= dont_increment_after) { /* >= 00 but <= 99 */ + return (old_serial + 2); /* "00" and "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<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(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(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(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; } diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index eece6994f..3e4c00e59 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -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 getFreshAXFRPacket(shared_ptr q) @@ -655,16 +662,8 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou // SOA *must* go out first, our signing pipe might reorder DLOG(L<<"Sending out SOA"<addRecord(dzrsoa); + DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd); + outpacket->addRecord(soa); if(securedZone && !presignedZone) { set authSet; authSet.insert(target); @@ -1052,7 +1051,7 @@ int TCPNameserver::doAXFR(const DNSName &target, shared_ptr q, int ou DLOG(L<<"Done writing out records"<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 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 q, int outsock) // SOA *must* go out first, our signing pipe might reorder DLOG(L<<"Sending out SOA"<addRecord(dzrsoa); - editSOA(dk, sd.qname, outpacket.get()); + DNSZoneRecord soa = makeEditedDNSZRFromSOAData(dk, sd); + outpacket->addRecord(soa); if(securedZone) { set authSet; authSet.insert(target); diff --git a/pdns/ueberbackend.cc b/pdns/ueberbackend.cc index b30783d8b..9c299be55 100644 --- a/pdns/ueberbackend.cc +++ b/pdns/ueberbackend.cc @@ -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::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; diff --git a/pdns/ueberbackend.hh b/pdns/ueberbackend.hh index 63729d4a6..9ce54b0c1 100644 --- a/pdns/ueberbackend.hh +++ b/pdns/ueberbackend.hh @@ -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 *domains, bool include_disabled=false); diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index f6b56eb84..9f8b9e7ac 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -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& 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(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(1, rr))) { + throw ApiException("Hosting backend does not support editing records."); + } } // return old and new serials in headers -- 2.40.0