if (previous.content == rec.content) {
errors.emplace_back(std::make_pair(rec, std::string{"duplicate record with content \""} + rec.content + "\""));
}
+ // Enforce identical TTLs for all records with the same name and type,
+ // if required. This is optional because some callers are able to
+ // compute allrrs in a way which already enforces this, and therefore
+ // it is useless to check a second time.
+ if ((flags & RRSET_CHECK_TTL) != 0) {
+ if (rec.ttl != previous.ttl) {
+ // This error message may be misleading if a TTL discrepancy already
+ // exists in the RRset, as it might blame an existing record rather
+ // than those being added. ¯\_(ツ)_/¯
+ errors.emplace_back(std::make_pair(rec, std::string{"uses a different TTL value than the remainder of the RRset"}));
+ }
+ }
}
else {
if (QType::exclusiveEntryTypes.count(rec.qtype.getCode()) != 0
// Wrapper around checkRRSet; returns true if all checks successful, false if
// not, in which case the response body and status have been filled up.
-static bool checkNewRecords(HttpResponse* resp, vector<DNSResourceRecord>& records, const ZoneName& zone, bool allowUnderscores)
+static bool checkNewRecords(HttpResponse* resp, vector<DNSResourceRecord>& records, const ZoneName& zone, Check::RRSetFlags flags)
{
std::vector<std::pair<DNSResourceRecord, string>> errors;
- Check::RRSetFlags flags{0};
- if (allowUnderscores) {
- flags = Check::RRSET_ALLOW_UNDERSCORES;
- }
Check::checkRRSet({}, records, zone, flags, errors);
if (errors.empty()) {
return true;
}
}
- if (!checkNewRecords(resp, new_records, zonename, false)) { // no RFC1123-CONFORMANCE metadata on new zones
+ // Flags = 0, as new zones do not have RFC1123-CONFORMANCE metadata yet, and
+ // all records use the same default ttl value.
+ if (!checkNewRecords(resp, new_records, zonename, static_cast<Check::RRSetFlags>(0))) {
return;
}
}
bool allowUnderscores = areUnderscoresAllowed(zoneData.zoneName, *zoneData.domainInfo.backend);
- if (!checkNewRecords(resp, new_records, zoneData.zoneName, allowUnderscores)) {
+ Check::RRSetFlags flags{Check::RRSET_CHECK_TTL};
+ if (allowUnderscores) {
+ flags = static_cast<Check::RRSetFlags>(flags | Check::RRSET_ALLOW_UNDERSCORES);
+ }
+ if (!checkNewRecords(resp, new_records, zoneData.zoneName, flags)) {
return;
}
soa.edit_done = increaseSOARecord(resourceRecord, soa.edit_api_kind, soa.edit_kind, zonename);
}
}
- if (!checkNewRecords(resp, new_records, zonename, allowUnderscores)) {
+ // All records use the same TTL, no need to check for discrepancy.
+ Check::RRSetFlags flags{0};
+ if (allowUnderscores) {
+ flags = Check::RRSET_ALLOW_UNDERSCORES;
+ }
+ if (!checkNewRecords(resp, new_records, zonename, flags)) {
// Proper error response has been set up, no need to do anything further.
return ABORT;
}
return SUCCESS;
}
+// Apply a PRUNE or EXTEND changetype.
static applyResult applyPruneOrExtend(const DomainInfo& domainInfo, const ZoneName& zonename, const Json& container, DNSName& qname, QType& qtype, bool allowUnderscores, soaEditSettings& soa, HttpResponse* resp, changeType operationType, std::vector<DNSResourceRecord>& rrset)
{
if (!container["records"].is_array()) {
soa.edit_done = increaseSOARecord(new_record, soa.edit_api_kind, soa.edit_kind, zonename);
}
- if (!checkNewRecords(resp, new_records, zonename, allowUnderscores)) {
+ Check::RRSetFlags flags{Check::RRSET_CHECK_TTL};
+ if (allowUnderscores) {
+ flags = static_cast<Check::RRSetFlags>(flags | Check::RRSET_ALLOW_UNDERSCORES);
+ }
+ if (!checkNewRecords(resp, new_records, zonename, flags)) {
// Proper error response has been set up, no need to do anything further.
return ABORT;
}