return DNSRecordContent::deserialize(qname, qtype, content, QClass::IN, true);
}
+// For the few places where we are only interested in the hasOrderName field,
+// this cheap routine is faster than doing:
+// {
+// LMDBResourceRecord lrr;
+// deserializeFromBuffer(buffer, lrr);
+// return lrr.hasOrderName;
+// }
+static bool peekAtHasOrderName(const string_view& buffer)
+{
+ uint16_t len;
+ memcpy(&len, &buffer[0], 2);
+ bool hasOrderName = buffer[2 + len + 4 + 2] != 0;
+ return hasOrderName;
+}
+
+// Similar to the above, but for the auth field.
+static bool peekAtAuth(const string_view& buffer)
+{
+ uint16_t len;
+ memcpy(&len, &buffer[0], 2);
+ bool auth = buffer[2 + len + 4] != 0;
+ return auth;
+}
+
+// Similar to the above, but for the ttl.
+static uint32_t peekAtTtl(const string_view& buffer)
+{
+ uint16_t len;
+ memcpy(&len, &buffer[0], 2);
+ uint32_t ttl;
+ memcpy(&ttl, &buffer[2] + len, 4);
+ return ttl;
+}
+
/* A note on the design.
If you ask a question without a zone id (this can be the case for lookup(),
match = co(domain_id, relative, qt.getCode());
// There should be at most one exact match here.
if (cursor.find(match, key, val) == 0) {
- LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
- hadOrderName = lrr.hasOrderName;
+ hadOrderName = peekAtHasOrderName(val.get<string_view>());
cursor.del(key);
}
// If we are not going to add any new records, check if there are any
}
// Return true if the key points to an NSEC3 back chain record (ttl == 0).
-// Updates lrr if this is an NSEC3 record (regardless of its kind).
-bool LMDBBackend::isNSEC3BackRecord(LMDBResourceRecord& lrr, const MDBOutVal& key, const MDBOutVal& val)
+bool LMDBBackend::isNSEC3BackRecord(const MDBOutVal& key, const MDBOutVal& val)
{
if (compoundOrdername::getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
- deserializeFromBuffer(val.get<StringView>(), lrr);
- if (lrr.ttl == 0) {
+ if (peekAtTtl(val.get<StringView>()) == 0) {
return true;
}
}
// NOLINTNEXTLINE(readability-identifier-length)
bool LMDBBackend::getAfterForward(MDBROCursor& cursor, MDBOutVal& key, MDBOutVal& val, domainid_t id, DNSName& after)
{
- LMDBResourceRecord lrr;
-
- while (!isNSEC3BackRecord(lrr, key, val)) {
+ while (!isNSEC3BackRecord(key, val)) {
if (cursor.next(key, val) != 0 || compoundOrdername::getDomainID(key.getNoStripHeader<StringView>()) != id) {
// cout<<"hit end of zone or database when we shouldn't"<<endl;
return false;
auto cursor = txn->txn->getCursor(txn->db->dbi);
MDBOutVal key, val;
- LMDBResourceRecord lrr;
-
string matchkey = co(id, qname, QType::NSEC3);
if (cursor.lower_bound(matchkey, key, val)) {
// this is beyond the end of the database
return false;
}
- if (isNSEC3BackRecord(lrr, key, val)) {
+ if (isNSEC3BackRecord(key, val)) {
break; // the kind of NSEC3 we need
}
if (cursor.prev(key, val)) {
}
}
before = co.getQName(key.getNoStripHeader<StringView>());
- unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone.operator const DNSName&();
-
+ {
+ LMDBResourceRecord lrr;
+ deserializeFromBuffer(val.get<StringView>(), lrr);
+ unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone.operator const DNSName&();
+ }
// now to find after .. at the beginning of the zone
return getAfterForwardFromStart(cursor, key, val, id, after);
}
int count = 0;
for (;;) {
if (compoundOrdername::getQName(key.getNoStripHeader<StringView>()).canonCompare(qname)) {
- if (isNSEC3BackRecord(lrr, key, val)) {
+ if (isNSEC3BackRecord(key, val)) {
break;
}
}
return false;
}
- if (isNSEC3BackRecord(lrr, key, val)) {
+ if (isNSEC3BackRecord(key, val)) {
break;
}
if (cursor.prev(key, val)) {
}
}
before = co.getQName(key.getNoStripHeader<StringView>());
- unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone.operator const DNSName&();
+ {
+ LMDBResourceRecord lrr;
+ deserializeFromBuffer(val.get<StringView>(), lrr);
+ unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone.operator const DNSName&();
+ }
// cout <<"Should still find 'after'!"<<endl;
// for 'after', we need to find the first hash of this zone
++count;
}
before = co.getQName(key.getNoStripHeader<StringView>());
- unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone.operator const DNSName&();
+ {
+ LMDBResourceRecord lrr;
+ deserializeFromBuffer(val.get<StringView>(), lrr);
+ unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone.operator const DNSName&();
+ }
// cout<<"Went backwards, found "<<before<<endl;
// return us to starting point
- while (count--)
+ while (count--) {
cursor.next(key, val);
+ }
}
// cout<<"Now going forward"<<endl;
if (getAfterForward(cursor, key, val, id, after)) {
// non terminal records.
bool LMDBBackend::isValidAuthRecord(const MDBOutVal& key, const MDBOutVal& val)
{
- LMDBResourceRecord lrr;
-
- deserializeFromBuffer(val.get<StringView>(), lrr);
QType qtype = compoundOrdername::getQType(key.getNoStripHeader<string_view>()).getCode();
- return qtype != QType::ENT && (lrr.auth || qtype == QType::NS);
+ switch (qtype) {
+ case QType::ENT:
+ return false;
+ case QType::NS:
+ return true;
+ default:
+ return peekAtAuth(val.get<string_view>());
+ }
}
bool LMDBBackend::getBeforeAndAfterNames(domainid_t domainId, const ZoneName& zonenameU, const DNSName& qname, DNSName& before, DNSName& after)
// as to remove the matching NSEC3 records, if any.
// (we can't invoke deleteNSEC3RecordPair here as doing this
// could make our cursor invalid)
- LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
- if (lrr.hasOrderName) {
+ if (peekAtHasOrderName(val.get<string_view>())) {
DNSName qname = compoundOrdername::getQName(key.getNoStripHeader<StringView>());
names.emplace_back(qname);
}
std::string match = order(domain_id, name, QType::ENT);
MDBOutVal val{};
if (txn->txn->get(txn->db->dbi, match, val) == 0) {
- LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
+ bool hadOrderName = peekAtHasOrderName(val.get<string_view>());
txn->txn->del(txn->db->dbi, match);
- if (lrr.hasOrderName) {
+ if (hadOrderName) {
deleteNSEC3RecordPair(txn, domain_id, name);
}
}