* `soa_edit_api` MAY be set. If it is set, on changes to the contents of
a zone made through the API, the SOA record will be edited according to
- the SOA-EDIT-API rules. (Which are the same as the SOA-EDIT rules.)
+ the SOA-EDIT-API rules. (Which are the same as the SOA-EDIT-DNSUPDATE rules.)
+ If not set at all during zone creation, defaults to `DEFAULT`.
**Note**: Authoritative only.
* `account` MAY be set. It's value is defined by local policy.
};
class DNSPacket;
-uint32_t calculateEditSOA(SOAData sd, const string& kind);
uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq);
+// for SOA-EDIT
+uint32_t calculateEditSOA(SOAData sd, const string& kind);
bool editSOA(DNSSECKeeper& dk, const string& qname, DNSPacket* dp);
bool editSOARecord(DNSResourceRecord& rr, const string& kind);
+// 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);
#endif
vector<string> soaEditSetting;
B.getDomainMetadata(di->zone, "SOA-EDIT", 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. 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 <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"<<endl;
soaEdit2136 = "DEFAULT";
} else
soaEdit = soaEditSetting[0];
}
}
-
- if (pdns_iequals(soaEdit2136, "INCREASE"))
- soa2Update.serial++;
- else if (pdns_iequals(soaEdit2136, "SOA-EDIT-INCREASE")) {
- uint32_t newSer = calculateEditSOA(soa2Update, soaEdit);
- if (newSer <= soa2Update.serial)
- soa2Update.serial++;
- else
- soa2Update.serial = newSer;
- } else if (pdns_iequals(soaEdit2136, "SOA-EDIT"))
- soa2Update.serial = calculateEditSOA(soa2Update, soaEdit);
- else if (pdns_iequals(soaEdit2136, "EPOCH"))
- soa2Update.serial = time(0);
- else {
- time_t now = time(0);
- struct tm tm;
- localtime_r(&now, &tm);
- boost::format fmt("%04d%02d%02d%02d");
- string newserdate=(fmt % (tm.tm_year+1900) % (tm.tm_mon +1 )% tm.tm_mday % 1).str();
- uint32_t newser = atol(newserdate.c_str());
- if (newser <= soa2Update.serial)
- soa2Update.serial++;
- else
- soa2Update.serial = newser;
- }
-
+ calculateIncreaseSOA(soa2Update, soaEdit2136, soaEdit);
newRec.content = serializeSOAData(soa2Update);
vector<DNSResourceRecord> rrset;
}
return sd.serial;
}
+
+// Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API.
+uint32_t calculateIncreaseSOA(SOAData sd, const string& increaseKind, const string& editKind) {
+ // 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(sd, editKind);
+ if (new_serial <= sd.serial) {
+ new_serial = sd.serial + 1;
+ }
+ return new_serial;
+ }
+ else if (pdns_iequals(increaseKind, "SOA-EDIT")) {
+ return calculateEditSOA(sd, editKind);
+ }
+ }
+
+ if (pdns_iequals(increaseKind, "INCREASE")) {
+ return sd.serial + 1;
+ }
+ else if (pdns_iequals(increaseKind, "EPOCH")) {
+ return time(0);
+ }
+
+ // DEFAULT case
+ time_t now = time(0);
+ struct tm tm;
+ localtime_r(&now, &tm);
+ 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 = atol(newdate.c_str());
+ if (new_serial <= sd.serial) {
+ new_serial = sd.serial + 1;
+ }
+ return new_serial;
+}
+
+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);
+ return true;
+}
throw ApiException("Nameservers list must be given (but can be empty if NS records are supplied)");
string soa_edit_api_kind;
- if (document["soa_edit_api"].IsString())
+ if (document["soa_edit_api"].IsString()) {
soa_edit_api_kind = document["soa_edit_api"].GetString();
+ }
+ else {
+ soa_edit_api_kind = "DEFAULT";
+ }
+ string soa_edit_kind;
+ if (document["soa_edit"].IsString())
+ soa_edit_kind = document["soa_edit"].GetString();
// if records/comments are given, load and check them
bool have_soa = false;
if (rr.qtype.getCode() == QType::SOA && pdns_iequals(rr.qname, zonename)) {
have_soa = true;
- editSOARecord(rr, soa_edit_api_kind);
+ increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
}
}
rr.content = serializeSOAData(sd);
rr.qtype = "SOA";
- editSOARecord(rr, soa_edit_api_kind);
+ increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
new_records.push_back(rr);
}
try {
string soa_edit_api_kind;
+ string soa_edit_kind;
di.backend->getDomainMetadataOne(zonename, "SOA-EDIT-API", soa_edit_api_kind);
+ di.backend->getDomainMetadataOne(zonename, "SOA-EDIT", soa_edit_kind);
bool soa_edit_done = false;
for(SizeType rrsetIdx = 0; rrsetIdx < rrsets.Size(); ++rrsetIdx) {
throw ApiException("Record "+rr.qname+"/"+rr.qtype.getName()+" "+rr.content+": Record wrongly bundled with RRset " + qname + "/" + qtype.getName());
if (rr.qtype.getCode() == QType::SOA && pdns_iequals(rr.qname, zonename)) {
- soa_edit_done = editSOARecord(rr, soa_edit_api_kind);
+ soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
}
}
rr.domain_id = di.id;
rr.auth = 1;
rr.ttl = sd.ttl;
- editSOARecord(rr, soa_edit_api_kind);
+ increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
if (!di.backend->replaceRRSet(di.id, rr.qname, rr.qtype, vector<DNSResourceRecord>(1, rr))) {
throw ApiException("Hosting backend does not support editing records.");