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
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;
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;
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;
-bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd)
+bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd, bool unmodifiedSerial)
{
const char* tmp;
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 );
}
~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;
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
\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);
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;
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();
-}
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);
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);
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);
DNSZoneRecord rr;
SOAData sd;
- // string subdomain="";
- string soa;
int retargetcount=0;
set<DNSName> authSet;
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;
/* 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;
return 0;
}
- editSOA(d_dk, sd.qname, r);
-
for(const auto& loopRR: r->getRRS()) {
if(loopRR.scopeMask) {
noCache=true;
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;
} 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();
).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());
}
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;
}
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);
+ }
}
}
#include "dnspacket.hh"
#include "namespaces.hh"
-
uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq)
{
struct tm tm;
+ 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);
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;
}
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)
// 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);
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);
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;
// 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);
}
// 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;
/** 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);
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;
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);
}
} 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");
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);
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);
// 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