Commit a29df115 authored by Michal 'vorner' Vaner's avatar Michal 'vorner' Vaner
Browse files

[1577] Port the in-memory loop to database findNSEC3

The high-level logic of finding it is similar, so we take the loop from
the in-memory data source and adapt it to the database.
parent a98fc157
......@@ -940,7 +940,7 @@ DatabaseClient::Finder::findInternal(const Name& name, const RRType& type,
}
ZoneFinder::FindNSEC3Result
DatabaseClient::Finder::findNSEC3(const Name& name, bool) {
DatabaseClient::Finder::findNSEC3(const Name& name, bool recursive) {
// TODO: Some logging.
// First, validate the input
......@@ -969,19 +969,66 @@ DatabaseClient::Finder::findNSEC3(const Name& name, bool) {
dynamic_cast<const generic::NSEC3PARAM&>(
param->second->getRdataIterator()->getCurrent())));
// Compute the hash and find the corresponding NSEC3
const string hash(calculator->calculate(name));
DatabaseAccessor::IteratorContextPtr
context(accessor_->getNSEC3Records(hash, zone_id_));
const unsigned olabels(getOrigin().getLabelCount());
const unsigned qlabels(name.getLabelCount());
const string otext(getOrigin().toText());
ConstRRsetPtr covering_proof;
for (unsigned labels(qlabels); labels >= olabels; -- labels) {
const string hash(calculator->calculate(labels == qlabels ? name :
name.split(qlabels - labels,
labels)));
DatabaseAccessor::IteratorContextPtr
context(accessor_->getNSEC3Records(hash, zone_id_));
const FoundRRsets nsec3(getRRsets(hash + "." + getOrigin().toText(),
NSEC3_TYPES(), false, NULL, false,
context));
if (!context) {
isc_throw(Unexpected, "Iterator context null for hash " + hash);
}
const FoundRRsets nsec3(getRRsets(hash + "." + otext, NSEC3_TYPES(),
false, NULL, false, context));
if (nsec3.first) {
// We found an exact match against the current label.
const FoundIterator it(nsec3.second.find(RRType::NSEC3()));
if (it == nsec3.second.end()) {
isc_throw(DataSourceError, "Hash " + hash +
"exists, but no NSEC3 there");
}
return (FindNSEC3Result(true, labels, it->second, covering_proof));
} else {
const string prevHash(accessor_->findPreviousNSEC3Hash(zone_id_,
hash));
context = accessor_->getNSEC3Records(prevHash, zone_id_);
const FoundRRsets prev_nsec3(getRRsets(prevHash + "." + otext,
NSEC3_TYPES(), false, NULL,
false, context));
if (!prev_nsec3.first) {
isc_throw(DataSourceError, "Hash " + prevHash + " returned "
"from findPreviousNSEC3Hash, but it is empty");
}
const FoundIterator
prev_it(prev_nsec3.second.find(RRType::NSEC3()));
if (prev_it == prev_nsec3.second.end()) {
isc_throw(DataSourceError, "The previous hash " + prevHash +
"exists, but does not contain the NSEC3");
}
covering_proof = prev_it->second;
if (!recursive) {
return (FindNSEC3Result(false, labels, covering_proof,
ConstRRsetPtr()));
}
}
}
// Return an expected exact match for now
return (FindNSEC3Result(true, name.getLabelCount(),
nsec3.second.find(RRType::NSEC3())->second,
ConstRRsetPtr()));
isc_throw(DataSourceError, "recursive findNSEC3 mode didn't stop, likely a "
"broken NSEC3 zone: " << otext << "/" << getClass());
}
Name
......
......@@ -684,7 +684,7 @@ public:
/// This is used to find previous NSEC3 hashes, to find covering NSEC3 in
/// case none match exactly.
///
/// In case a hash before before the lowest or the lowest is provided,
/// In case a hash before the lowest or the lowest is provided,
/// this should return the largest one in the zone (NSEC3 needs a
/// wrap-around semantics).
///
......
......@@ -211,8 +211,14 @@ const char* const TEST_RECORDS[][5] = {
// FIXME: Taken from a different test. Fill with proper data when creating a test.
const char* TEST_NSEC3_RECORDS[][5] = {
{"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", "NSEC3", "300", "", "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"},
{"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", "RRSIG", "300", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
{apex_hash, "NSEC3", "300", "", "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"},
{apex_hash, "RRSIG", "300", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
{ns1_hash, "NSEC3", "300", "", "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"},
{ns1_hash, "RRSIG", "300", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
{w_hash, "NSEC3", "300", "", "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"},
{w_hash, "RRSIG", "300", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
{zzz_hash, "NSEC3", "300", "", "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"},
{zzz_hash, "RRSIG", "300", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
{NULL, NULL, NULL, NULL, NULL}
};
......@@ -3595,6 +3601,12 @@ TEST_F(MockDatabaseClientTest, findNSEC3) {
Name origin("example.org");
const string apex_nsec3_text = string(apex_hash) + ".example.org." +
string(nsec3_common);
const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
string(nsec3_common);
const string w_nsec3_text = string(w_hash) + ".example.org." +
string(nsec3_common);
const string zzz_nsec3_text = string(zzz_hash) + ".example.org." +
string(nsec3_common);
// Apex name. It should have a matching NSEC3.
{
......@@ -3603,21 +3615,21 @@ TEST_F(MockDatabaseClientTest, findNSEC3) {
finder->findNSEC3(origin, false));
}
#if 0
// Recursive mode doesn't change the result in this case.
{
SCOPED_TRACE("apex, recursive mode");
findNSEC3Check(true, origin_.getLabelCount(), apex_nsec3_text, "",
zone_finder_.findNSEC3(origin_, true));
findNSEC3Check(true, origin.getLabelCount(), apex_nsec3_text, "",
finder->findNSEC3(origin, true));
}
// Non existent name. Disabling recursion, a covering NSEC3 should be
// returned.
// Non existent name (in the NSEC3 namespace -- the findNSEC3 does
// not look into the normal data). Disabling recursion, a covering
// NSEC3 should be returned.
const Name www_name("www.example.org");
{
SCOPED_TRACE("non existent name, non recursive mode");
findNSEC3Check(false, www_name.getLabelCount(), apex_nsec3_text, "",
zone_finder_.findNSEC3(www_name, false));
finder->findNSEC3(www_name, false));
}
// Non existent name. The closest provable encloser is the apex,
......@@ -3626,9 +3638,9 @@ TEST_F(MockDatabaseClientTest, findNSEC3) {
// H(ns1) = 2T... < H(xxx) = Q0... < H(zzz) = R5...
{
SCOPED_TRACE("non existent name, recursive mode");
findNSEC3Check(true, origin_.getLabelCount(), apex_nsec3_text,
findNSEC3Check(true, origin.getLabelCount(), apex_nsec3_text,
ns1_nsec3_text,
zone_finder_.findNSEC3(Name("xxx.example.org"), true));
finder->findNSEC3(Name("xxx.example.org"), true));
}
// Similar to the previous case, but next closer name is different
......@@ -3639,8 +3651,8 @@ TEST_F(MockDatabaseClientTest, findNSEC3) {
SCOPED_TRACE("non existent name, non qname next closer");
findNSEC3Check(true, Name("w.example.org").getLabelCount(),
w_nsec3_text, ns1_nsec3_text,
zone_finder_.findNSEC3(Name("x.y.w.example.org"),
true));
finder->findNSEC3(Name("x.y.w.example.org"),
true));
}
// In the rest of test we check hash comparison for wrap around cases.
......@@ -3649,16 +3661,15 @@ TEST_F(MockDatabaseClientTest, findNSEC3) {
const Name smallest_name("smallest.example.org");
findNSEC3Check(false, smallest_name.getLabelCount(),
zzz_nsec3_text, "",
zone_finder_.findNSEC3(smallest_name, false));
finder->findNSEC3(smallest_name, false));
}
{
SCOPED_TRACE("very large hash");
const Name largest_name("largest.example.org");
findNSEC3Check(false, largest_name.getLabelCount(),
zzz_nsec3_text, "",
zone_finder_.findNSEC3(largest_name, false));
finder->findNSEC3(largest_name, false));
}
#endif
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment