BIND 10 trac1066, updated. 77affdfde7a5728072827e27d5c168425434ce74 [1066] Basic wildcard matching
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Aug 15 13:58:39 UTC 2011
The branch, trac1066 has been updated
via 77affdfde7a5728072827e27d5c168425434ce74 (commit)
via c70458739e229aa5112005a0cb99d1e8e74a4af6 (commit)
via 55b9da3b0386c12d6ef2525cdf943198222c840e (commit)
via e021b84f7fc20b3e3927093ed87e9c873d33a443 (commit)
via 62432e71ef943744fd4ca9ce216da1b0a7250573 (commit)
via 005c77dfe53b54cef92ce51d91f615eb9c2769c4 (commit)
via ce3bc8504d765ecc9b453398efb18662bd4f277a (commit)
via 94fc6d8d303053c47064c9408947cd49a8e11975 (commit)
via c5cf3cc081042fec0e2baea7cdf7f22a8a84664a (commit)
via adcbbb141bdb09a6fd999f3369e15c2881f843ba (commit)
via 80014655d76e758868e8e1ed36472be9a606eb2a (commit)
from 39a0a5c65d0802f40ab428474b1e6d981a91fbce (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 77affdfde7a5728072827e27d5c168425434ce74
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Aug 15 15:55:14 2011 +0200
[1066] Basic wildcard matching
Still, some canceling needs to be done properly.
commit c70458739e229aa5112005a0cb99d1e8e74a4af6
Merge: 55b9da3b0386c12d6ef2525cdf943198222c840e e021b84f7fc20b3e3927093ed87e9c873d33a443
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Aug 15 13:20:20 2011 +0200
Merge branch #1063 into #1066
Because this will need both the look for subdomains (when canceling
wildcard match due to existing subdomains) from #1065 and the extracted
method for scanning single domain.
Conflicts:
src/lib/datasrc/tests/database_unittest.cc
commit 55b9da3b0386c12d6ef2525cdf943198222c840e
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Aug 15 13:00:28 2011 +0200
[1066] Tests for some basic wildcards
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/database.cc | 280 ++++++++++++++++++++--------
src/lib/datasrc/database.h | 55 ++++++-
src/lib/datasrc/tests/database_unittest.cc | 267 +++++++++++++++++++++++++--
3 files changed, 508 insertions(+), 94 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index 70ce62f..f42ee12 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -49,16 +49,18 @@ DatabaseClient::findZone(const Name& name) const {
if (zone.first) {
return (FindResult(result::SUCCESS,
ZoneFinderPtr(new Finder(database_,
- zone.second))));
+ zone.second, name))));
}
// Than super domains
// Start from 1, as 0 is covered above
for (size_t i(1); i < name.getLabelCount(); ++i) {
- zone = database_->getZone(name.split(i));
+ isc::dns::Name superdomain(name.split(i));
+ zone = database_->getZone(superdomain);
if (zone.first) {
return (FindResult(result::PARTIALMATCH,
ZoneFinderPtr(new Finder(database_,
- zone.second))));
+ zone.second,
+ superdomain))));
}
}
// No, really nothing
@@ -66,9 +68,11 @@ DatabaseClient::findZone(const Name& name) const {
}
DatabaseClient::Finder::Finder(boost::shared_ptr<DatabaseAccessor>
- database, int zone_id) :
+ database, int zone_id,
+ const isc::dns::Name& origin) :
database_(database),
- zone_id_(zone_id)
+ zone_id_(zone_id),
+ origin_(origin)
{ }
namespace {
@@ -162,6 +166,127 @@ private:
};
}
+std::pair<bool, isc::dns::RRsetPtr>
+DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
+ const isc::dns::RRType* type,
+ bool want_cname, bool want_dname,
+ bool want_ns,
+ const isc::dns::Name* construct_name)
+{
+ RRsigStore sig_store;
+ database_->searchForRecords(zone_id_, name.toText());
+ bool records_found = false;
+ isc::dns::RRsetPtr result_rrset;
+
+ std::string columns[DatabaseAccessor::COLUMN_COUNT];
+ if (construct_name == NULL) {
+ construct_name = &name;
+ }
+ while (database_->getNextRecord(columns, DatabaseAccessor::COLUMN_COUNT)) {
+ if (!records_found) {
+ records_found = true;
+ }
+
+ try {
+ const isc::dns::RRType cur_type(columns[DatabaseAccessor::
+ TYPE_COLUMN]);
+ const isc::dns::RRTTL cur_ttl(columns[DatabaseAccessor::
+ TTL_COLUMN]);
+ // Ths sigtype column was an optimization for finding the
+ // relevant RRSIG RRs for a lookup. Currently this column is
+ // not used in this revised datasource implementation. We
+ // should either start using it again, or remove it from use
+ // completely (i.e. also remove it from the schema and the
+ // backend implementation).
+ // Note that because we don't use it now, we also won't notice
+ // it if the value is wrong (i.e. if the sigtype column
+ // contains an rrtype that is different from the actual value
+ // of the 'type covered' field in the RRSIG Rdata).
+ //cur_sigtype(columns[SIGTYPE_COLUMN]);
+
+ // Check for delegations before checking for the right type.
+ // This is needed to properly delegate request for the NS
+ // record itself.
+ //
+ // This happens with NS only, CNAME must be alone and DNAME
+ // is not checked in the exact queried domain.
+ if (want_ns && cur_type == isc::dns::RRType::NS()) {
+ if (result_rrset &&
+ result_rrset->getType() != isc::dns::RRType::NS()) {
+ isc_throw(DataSourceError, "NS found together with data"
+ " in non-apex domain " + name.toText());
+ }
+ addOrCreate(result_rrset, *construct_name, getClass(),
+ cur_type, cur_ttl,
+ columns[DatabaseAccessor::RDATA_COLUMN],
+ *database_);
+ } else if (type != NULL && cur_type == *type) {
+ if (result_rrset &&
+ result_rrset->getType() == isc::dns::RRType::CNAME()) {
+ isc_throw(DataSourceError, "CNAME found but it is not "
+ "the only record for " + name.toText());
+ } else if (result_rrset && want_ns &&
+ result_rrset->getType() == isc::dns::RRType::NS()) {
+ isc_throw(DataSourceError, "NS found together with data"
+ " in non-apex domain " + name.toText());
+ }
+ addOrCreate(result_rrset, *construct_name, getClass(),
+ cur_type, cur_ttl,
+ columns[DatabaseAccessor::RDATA_COLUMN],
+ *database_);
+ } else if (want_cname && cur_type == isc::dns::RRType::CNAME()) {
+ // There should be no other data, so result_rrset should
+ // be empty.
+ if (result_rrset) {
+ isc_throw(DataSourceError, "CNAME found but it is not "
+ "the only record for " + name.toText());
+ }
+ addOrCreate(result_rrset, *construct_name, getClass(),
+ cur_type, cur_ttl,
+ columns[DatabaseAccessor::RDATA_COLUMN],
+ *database_);
+ } else if (want_dname && cur_type == isc::dns::RRType::DNAME()) {
+ // There should be max one RR of DNAME present
+ if (result_rrset &&
+ result_rrset->getType() == isc::dns::RRType::DNAME()) {
+ isc_throw(DataSourceError, "DNAME with multiple RRs in " +
+ name.toText());
+ }
+ addOrCreate(result_rrset, *construct_name, getClass(),
+ cur_type, cur_ttl,
+ columns[DatabaseAccessor::RDATA_COLUMN],
+ *database_);
+ } else if (cur_type == isc::dns::RRType::RRSIG()) {
+ // If we get signatures before we get the actual data, we
+ // can't know which ones to keep and which to drop...
+ // So we keep a separate store of any signature that may be
+ // relevant and add them to the final RRset when we are
+ // done.
+ // A possible optimization here is to not store them for
+ // types we are certain we don't need
+ sig_store.addSig(isc::dns::rdata::createRdata(cur_type,
+ getClass(), columns[DatabaseAccessor::RDATA_COLUMN]));
+ }
+ } catch (const isc::dns::InvalidRRType& irt) {
+ isc_throw(DataSourceError, "Invalid RRType in database for " <<
+ name << ": " << columns[DatabaseAccessor::
+ TYPE_COLUMN]);
+ } catch (const isc::dns::InvalidRRTTL& irttl) {
+ isc_throw(DataSourceError, "Invalid TTL in database for " <<
+ name << ": " << columns[DatabaseAccessor::
+ TTL_COLUMN]);
+ } catch (const isc::dns::rdata::InvalidRdataText& ird) {
+ isc_throw(DataSourceError, "Invalid rdata in database for " <<
+ name << ": " << columns[DatabaseAccessor::
+ RDATA_COLUMN]);
+ }
+ }
+ if (result_rrset) {
+ sig_store.appendSignatures(result_rrset);
+ }
+ return std::pair<bool, isc::dns::RRsetPtr>(records_found, result_rrset);
+}
+
ZoneFinder::FindResult
DatabaseClient::Finder::find(const isc::dns::Name& name,
@@ -174,97 +299,92 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
bool records_found = false;
isc::dns::RRsetPtr result_rrset;
ZoneFinder::Result result_status = SUCCESS;
- RRsigStore sig_store;
+ std::pair<bool, isc::dns::RRsetPtr> found;
logger.debug(DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
.arg(database_->getDBName()).arg(name).arg(type);
try {
- database_->searchForRecords(zone_id_, name.toText());
-
- std::string columns[DatabaseAccessor::COLUMN_COUNT];
- while (database_->getNextRecord(columns,
- DatabaseAccessor::COLUMN_COUNT)) {
- if (!records_found) {
- records_found = true;
+ // First, do we have any kind of delegation (NS/DNAME) here?
+ Name origin(getOrigin());
+ size_t originLabelCount(origin.getLabelCount());
+ // Number of labels in the last known non-empty domain
+ size_t lastKnown(originLabelCount);
+ size_t currentLabelCount(name.getLabelCount());
+ // This is how many labels we remove to get origin
+ size_t removeLabels(currentLabelCount - originLabelCount);
+ // Now go trough all superdomains from origin down
+ for (int i(removeLabels); i > 0; -- i) {
+ Name superdomain(name.split(i));
+ // Look if there's NS or DNAME (but ignore the NS in origin)
+ found = getRRset(superdomain, NULL, false, true,
+ i != removeLabels);
+ if (found.first) {
+ // It contains some RRs, so it exists.
+ lastKnown = superdomain.getLabelCount();
}
-
- try {
- const isc::dns::RRType cur_type(columns[DatabaseAccessor::
- TYPE_COLUMN]);
- const isc::dns::RRTTL cur_ttl(columns[DatabaseAccessor::
- TTL_COLUMN]);
- // Ths sigtype column was an optimization for finding the
- // relevant RRSIG RRs for a lookup. Currently this column is
- // not used in this revised datasource implementation. We
- // should either start using it again, or remove it from use
- // completely (i.e. also remove it from the schema and the
- // backend implementation).
- // Note that because we don't use it now, we also won't notice
- // it if the value is wrong (i.e. if the sigtype column
- // contains an rrtype that is different from the actual value
- // of the 'type covered' field in the RRSIG Rdata).
- //cur_sigtype(columns[SIGTYPE_COLUMN]);
-
- if (cur_type == type) {
- if (result_rrset &&
- result_rrset->getType() == isc::dns::RRType::CNAME()) {
- isc_throw(DataSourceError, "CNAME found but it is not "
- "the only record for " + name.toText());
- }
- addOrCreate(result_rrset, name, getClass(), cur_type,
- cur_ttl, columns[DatabaseAccessor::
- RDATA_COLUMN],
- *database_);
- } else if (cur_type == isc::dns::RRType::CNAME()) {
- // There should be no other data, so result_rrset should
- // be empty.
- if (result_rrset) {
- isc_throw(DataSourceError, "CNAME found but it is not "
- "the only record for " + name.toText());
- }
- addOrCreate(result_rrset, name, getClass(), cur_type,
- cur_ttl, columns[DatabaseAccessor::
- RDATA_COLUMN],
- *database_);
- result_status = CNAME;
- } else if (cur_type == isc::dns::RRType::RRSIG()) {
- // If we get signatures before we get the actual data, we
- // can't know which ones to keep and which to drop...
- // So we keep a separate store of any signature that may be
- // relevant and add them to the final RRset when we are
- // done.
- // A possible optimization here is to not store them for
- // types we are certain we don't need
- sig_store.addSig(isc::dns::rdata::createRdata(cur_type,
- getClass(),
- columns[DatabaseAccessor::
- RDATA_COLUMN]));
+ if (found.second) {
+ // We found something redirecting somewhere else
+ // (it can be only NS or DNAME here)
+ result_rrset = found.second;
+ if (result_rrset->getType() == isc::dns::RRType::NS()) {
+ result_status = DELEGATION;
+ } else {
+ result_status = DNAME;
}
- } catch (const isc::dns::InvalidRRType& irt) {
- isc_throw(DataSourceError, "Invalid RRType in database for " <<
- name << ": " << columns[DatabaseAccessor::
- TYPE_COLUMN]);
- } catch (const isc::dns::InvalidRRTTL& irttl) {
- isc_throw(DataSourceError, "Invalid TTL in database for " <<
- name << ": " << columns[DatabaseAccessor::
- TTL_COLUMN]);
- } catch (const isc::dns::rdata::InvalidRdataText& ird) {
- isc_throw(DataSourceError, "Invalid rdata in database for " <<
- name << ": " << columns[DatabaseAccessor::
- RDATA_COLUMN]);
+ // Don't search more
+ break;
}
}
+
+ if (!result_rrset) { // Only if we didn't find a redirect already
+ // Try getting the final result and extract it
+ // It is special if there's a CNAME or NS, DNAME is ignored here
+ // And we don't consider the NS in origin
+ found = getRRset(name, &type, true, false, name != origin);
+ records_found = found.first;
+ result_rrset = found.second;
+ }
if (!result_rrset && !records_found) {
- // Nothing lives here. But check if something lives below this
+ // Nothing lives here.
+ // But check if something lives below this
// domain and if so, pretend something is here as well.
database_->searchForRecords(zone_id_, name.toText(), true);
+ std::string columns[DatabaseAccessor::COLUMN_COUNT];
if (database_->getNextRecord(columns,
DatabaseAccessor::COLUMN_COUNT)) {
records_found = true;
// We don't consume everything, so get rid of the rest
database_->resetSearch();
+ } else {
+ // It's not empty non-terminal. So check for wildcards.
+ // We remove labels one by one and look for the wildcard there.
+ // Go up to first non-empty domain.
+ removeLabels = currentLabelCount - lastKnown;
+ Name star("*");
+ for (size_t i(1); i < removeLabels; ++ i) {
+ // Construct the name with *
+ // TODO: Once the underlying DatabaseAccessor takes string,
+ // do the concatenation on strings, not Names
+ Name superdomain(name.split(i));
+ Name wildcard(star.concatenate(superdomain));
+ // TODO What do we do about DNAME here?
+ found = getRRset(wildcard, &type, true, false, true,
+ &name);
+ result_rrset = found.second;
+ if (found.first) {
+ records_found = true;
+ break;
+ }
+ }
}
}
+ if (result_rrset && name != origin &&
+ result_rrset->getType() == isc::dns::RRType::NS()) {
+ result_status = DELEGATION;
+ } else if (result_rrset && type != isc::dns::RRType::CNAME() &&
+ result_rrset->getType() == isc::dns::RRType::CNAME()) {
+ result_status = CNAME;
+ }
} catch (const DataSourceError& dse) {
logger.error(DATASRC_DATABASE_FIND_ERROR)
.arg(database_->getDBName()).arg(dse.what());
@@ -299,7 +419,6 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
result_status = NXDOMAIN;
}
} else {
- sig_store.appendSignatures(result_rrset);
logger.debug(DBG_TRACE_DETAILED,
DATASRC_DATABASE_FOUND_RRSET)
.arg(database_->getDBName()).arg(*result_rrset);
@@ -309,8 +428,7 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
Name
DatabaseClient::Finder::getOrigin() const {
- // TODO Implement
- return (Name("."));
+ return (origin_);
}
isc::dns::RRClass
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index 187f5b1..58cb13f 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -17,6 +17,8 @@
#include <datasrc/client.h>
+#include <dns/name.h>
+
namespace isc {
namespace datasrc {
@@ -224,8 +226,12 @@ public:
* \param zone_id The zone ID which was returned from
* DatabaseAccessor::getZone and which will be passed to further
* calls to the database.
+ * \param origin The name of the origin of this zone. It could query
+ * it from database, but as the DatabaseClient just searched for
+ * the zone using the name, it should have it.
*/
- Finder(boost::shared_ptr<DatabaseAccessor> database, int zone_id);
+ Finder(boost::shared_ptr<DatabaseAccessor> database, int zone_id,
+ const isc::dns::Name& origin);
// The following three methods are just implementations of inherited
// ZoneFinder's pure virtual methods.
virtual isc::dns::Name getOrigin() const;
@@ -296,6 +302,53 @@ public:
private:
boost::shared_ptr<DatabaseAccessor> database_;
const int zone_id_;
+ const isc::dns::Name origin_;
+ /**
+ * \brief Searches database for an RRset
+ *
+ * This method scans RRs of single domain specified by name and finds
+ * RRset with given type or any of redirection RRsets that are
+ * requested.
+ *
+ * This function is used internally by find(), because this part is
+ * called multiple times with slightly different parameters.
+ *
+ * \param name Which domain name should be scanned.
+ * \param type The RRType which is requested. This can be NULL, in
+ * which case the method will look for the redirections only.
+ * \param want_cname If this is true, CNAME redirection may be returned
+ * instead of the RRset with given type. If there's CNAME and
+ * something else or the CNAME has multiple RRs, it throws
+ * DataSourceError.
+ * \param want_dname If this is true, DNAME redirection may be returned
+ * instead. This is with type = NULL only and is not checked in
+ * other circumstances. If the DNAME has multiple RRs, it throws
+ * DataSourceError.
+ * \param want_ns This allows redirection by NS to be returned. If
+ * any other data is met as well, DataSourceError is thrown.
+ * \param construct_name If set to non-NULL, the resulting RRset will
+ * be constructed for this name instead of the queried one. This
+ * is useful for wildcards.
+ * \note It may happen that some of the above error conditions are not
+ * detected in some circumstances. The goal here is not to validate
+ * the domain in DB, but to avoid bad behaviour resulting from
+ * broken data.
+ * \return First part of the result tells if the domain contains any
+ * RRs. This can be used to decide between NXDOMAIN and NXRRSET.
+ * The second part is the RRset found (if any) with any relevant
+ * signatures attached to it.
+ * \todo This interface doesn't look very elegant. Any better idea
+ * would be nice.
+ */
+ std::pair<bool, isc::dns::RRsetPtr> getRRset(const isc::dns::Name&
+ name,
+ const isc::dns::RRType*
+ type,
+ bool want_cname,
+ bool want_dname,
+ bool want_ns, const
+ isc::dns::Name*
+ construct_name = NULL);
};
/**
* \brief Find a zone in the database
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index e6a208e..cf90812 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -286,6 +286,50 @@ private:
// This is because of empty domain test
addRecord("A", "3600", "", "192.0.2.1");
addCurName("a.b.example.org.");
+
+ // Something for wildcards
+ addRecord("A", "3600", "", "192.0.2.5");
+ addCurName("*.wild.example.org.");
+ addRecord("AAAA", "3600", "", "2001:db8::5");
+ addCurName("cancel.here.wild.example.org.");
+
+ // Data for testing delegation (with NS and DNAME)
+ addRecord("NS", "3600", "", "ns.example.com.");
+ addRecord("NS", "3600", "", "ns.delegation.example.org.");
+ addRecord("RRSIG", "3600", "", "NS 5 3 3600 20000101000000 "
+ "20000201000000 12345 example.org. FAKEFAKEFAKE");
+ addCurName("delegation.example.org.");
+ addRecord("A", "3600", "", "192.0.2.1");
+ addCurName("ns.delegation.example.org.");
+
+ addRecord("A", "3600", "", "192.0.2.1");
+ addRecord("DNAME", "3600", "", "dname.example.com.");
+ addRecord("RRSIG", "3600", "", "DNAME 5 3 3600 20000101000000 "
+ "20000201000000 12345 example.org. FAKEFAKEFAKE");
+ addCurName("dname.example.org.");
+ addRecord("A", "3600", "", "192.0.2.1");
+ addCurName("below.dname.example.org.");
+
+ // Broken NS
+ addRecord("A", "3600", "", "192.0.2.1");
+ addRecord("NS", "3600", "", "ns.example.com.");
+ addCurName("brokenns1.example.org.");
+ addRecord("NS", "3600", "", "ns.example.com.");
+ addRecord("A", "3600", "", "192.0.2.1");
+ addCurName("brokenns2.example.org.");
+
+ // Now double DNAME, to test failure mode
+ addRecord("DNAME", "3600", "", "dname1.example.com.");
+ addRecord("DNAME", "3600", "", "dname2.example.com.");
+ addCurName("baddname.example.org.");
+
+ // Put some data into apex (including NS) so we can check our NS
+ // doesn't break anything
+ addRecord("NS", "3600", "", "ns.example.com.");
+ addRecord("A", "3600", "", "192.0.2.1");
+ addRecord("RRSIG", "3600", "", "NS 5 3 3600 20000101000000 "
+ "20000201000000 12345 example.org. FAKEFAKEFAKE");
+ addCurName("example.org.");
}
};
@@ -376,19 +420,23 @@ doFindTest(shared_ptr<DatabaseClient::Finder> finder,
const isc::dns::RRTTL expected_ttl,
ZoneFinder::Result expected_result,
const std::vector<std::string>& expected_rdatas,
- const std::vector<std::string>& expected_sig_rdatas)
+ const std::vector<std::string>& expected_sig_rdatas,
+ const isc::dns::Name& expected_name = isc::dns::Name::ROOT_NAME())
{
+ SCOPED_TRACE("doFindTest " + name.toText() + " " + type.toText());
ZoneFinder::FindResult result =
finder->find(name, type, NULL, ZoneFinder::FIND_DEFAULT);
ASSERT_EQ(expected_result, result.code) << name << " " << type;
if (expected_rdatas.size() > 0) {
- checkRRset(result.rrset, name, finder->getClass(),
- expected_type, expected_ttl, expected_rdatas);
+ checkRRset(result.rrset, expected_name != Name(".") ? expected_name :
+ name, finder->getClass(), expected_type, expected_ttl,
+ expected_rdatas);
if (expected_sig_rdatas.size() > 0) {
- checkRRset(result.rrset->getRRsig(), name,
- finder->getClass(), isc::dns::RRType::RRSIG(),
- expected_ttl, expected_sig_rdatas);
+ checkRRset(result.rrset->getRRsig(), expected_name != Name(".") ?
+ expected_name : name, finder->getClass(),
+ isc::dns::RRType::RRSIG(), expected_ttl,
+ expected_sig_rdatas);
} else {
EXPECT_EQ(isc::dns::RRsetPtr(), result.rrset->getRRsig());
}
@@ -706,14 +754,209 @@ TEST_F(DatabaseClientTest, find) {
expected_rdatas, expected_sig_rdatas);
EXPECT_FALSE(current_database_->searchRunning());
- // Check empty domain
+ {
+ SCOPED_TRACE("Empty nonterminal");
+ // Check empty domain
+ expected_rdatas.clear();
+ expected_sig_rdatas.clear();
+ // This domain doesn't exist, but a subdomain of it does.
+ // Therefore we should pretend the domain is there, but contains no RRsets
+ doFindTest(finder, isc::dns::Name("b.example.org."),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET, expected_rdatas,
+ expected_sig_rdatas);
+ }
+
+ {
+ SCOPED_TRACE("Wildcard");
+ // First, simple wildcard match
+ expected_rdatas.clear();
+ expected_sig_rdatas.clear();
+ expected_rdatas.push_back("192.0.2.5");
+ doFindTest(finder, isc::dns::Name("a.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+ doFindTest(finder, isc::dns::Name("b.a.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+ expected_rdatas.clear();
+ doFindTest(finder, isc::dns::Name("a.wild.example.org"),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET, expected_rdatas,
+ expected_sig_rdatas);
+ doFindTest(finder, isc::dns::Name("b.a.wild.example.org"),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET, expected_rdatas,
+ expected_sig_rdatas);
+
+ // Direct request for thi wildcard
+ expected_rdatas.push_back("192.0.2.5");
+ doFindTest(finder, isc::dns::Name("*.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+ expected_rdatas.clear();
+ doFindTest(finder, isc::dns::Name("*.wild.example.org"),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET, expected_rdatas,
+ expected_sig_rdatas);
+ // This is nonsense, but check it doesn't match by some stupid accident
+ doFindTest(finder, isc::dns::Name("a.*.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXDOMAIN,
+ expected_rdatas, expected_sig_rdatas);
+ // These should be canceled, since it is below a domain which exitsts
+ doFindTest(finder, isc::dns::Name("nothing.here.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXDOMAIN,
+ expected_rdatas, expected_sig_rdatas);
+ doFindTest(finder, isc::dns::Name("cancel.here.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET,
+ expected_rdatas, expected_sig_rdatas);
+ doFindTest(finder,
+ isc::dns::Name("below.cancel.here.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXDOMAIN,
+ expected_rdatas, expected_sig_rdatas);
+ // And this should be just plain empty non-terminal domain, check
+ // the wildcard doesn't hurt it
+ doFindTest(finder, isc::dns::Name("here.wild.example.org"),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET, expected_rdatas,
+ expected_sig_rdatas);
+
+ // TODO Check delegation, multiple wildcards and wildcards somewhere
+ // in the middle.
+ }
+
+ // The apex should not be considered delegation point and we can access
+ // data
+ expected_rdatas.clear();
+ expected_sig_rdatas.clear();
+ expected_rdatas.push_back("192.0.2.1");
+ doFindTest(finder, isc::dns::Name("example.org."),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ expected_rdatas.clear();
+ expected_rdatas.push_back("ns.example.com.");
+ expected_sig_rdatas.push_back("NS 5 3 3600 20000101000000 20000201000000 "
+ "12345 example.org. FAKEFAKEFAKE");
+ doFindTest(finder, isc::dns::Name("example.org."),
+ isc::dns::RRType::NS(), isc::dns::RRType::NS(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // Check when we ask for something below delegation point, we get the NS
+ // (Both when the RRset there exists and doesn't)
expected_rdatas.clear();
expected_sig_rdatas.clear();
- // This domain doesn't exist, but a subdomain of it does.
- // Therefore we should pretend the domain is there, but contains no RRsets
- doFindTest(finder, isc::dns::Name("b.example.org."), isc::dns::RRType::A(),
- isc::dns::RRType::A(), isc::dns::RRTTL(3600),
- ZoneFinder::NXRRSET, expected_rdatas, expected_sig_rdatas);
+ expected_rdatas.push_back("ns.example.com.");
+ expected_rdatas.push_back("ns.delegation.example.org.");
+ expected_sig_rdatas.push_back("NS 5 3 3600 20000101000000 20000201000000 "
+ "12345 example.org. FAKEFAKEFAKE");
+ doFindTest(finder, isc::dns::Name("ns.delegation.example.org."),
+ isc::dns::RRType::A(), isc::dns::RRType::NS(),
+ isc::dns::RRTTL(3600), ZoneFinder::DELEGATION, expected_rdatas,
+ expected_sig_rdatas, isc::dns::Name("delegation.example.org."));
+ EXPECT_FALSE(current_database_->searchRunning());
+ doFindTest(finder, isc::dns::Name("ns.delegation.example.org."),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::NS(),
+ isc::dns::RRTTL(3600), ZoneFinder::DELEGATION, expected_rdatas,
+ expected_sig_rdatas, isc::dns::Name("delegation.example.org."));
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // Even when we check directly at the delegation point, we should get
+ // the NS
+ doFindTest(finder, isc::dns::Name("delegation.example.org."),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::NS(),
+ isc::dns::RRTTL(3600), ZoneFinder::DELEGATION, expected_rdatas,
+ expected_sig_rdatas);
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // And when we ask direcly for the NS, we should still get delegation
+ doFindTest(finder, isc::dns::Name("delegation.example.org."),
+ isc::dns::RRType::NS(), isc::dns::RRType::NS(),
+ isc::dns::RRTTL(3600), ZoneFinder::DELEGATION, expected_rdatas,
+ expected_sig_rdatas);
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // Now test delegation. If it is below the delegation point, we should get
+ // the DNAME (the one with data under DNAME is invalid zone, but we test
+ // the behaviour anyway just to make sure)
+ expected_rdatas.clear();
+ expected_rdatas.push_back("dname.example.com.");
+ expected_sig_rdatas.clear();
+ expected_sig_rdatas.push_back("DNAME 5 3 3600 20000101000000 "
+ "20000201000000 12345 example.org. "
+ "FAKEFAKEFAKE");
+ doFindTest(finder, isc::dns::Name("below.dname.example.org."),
+ isc::dns::RRType::A(), isc::dns::RRType::DNAME(),
+ isc::dns::RRTTL(3600), ZoneFinder::DNAME, expected_rdatas,
+ expected_sig_rdatas, isc::dns::Name("dname.example.org."));
+ EXPECT_FALSE(current_database_->searchRunning());
+ doFindTest(finder, isc::dns::Name("below.dname.example.org."),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::DNAME(),
+ isc::dns::RRTTL(3600), ZoneFinder::DNAME, expected_rdatas,
+ expected_sig_rdatas, isc::dns::Name("dname.example.org."));
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // Asking direcly for DNAME should give SUCCESS
+ doFindTest(finder, isc::dns::Name("dname.example.org."),
+ isc::dns::RRType::DNAME(), isc::dns::RRType::DNAME(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+
+ // But we don't delegate at DNAME point
+ expected_rdatas.clear();
+ expected_rdatas.push_back("192.0.2.1");
+ expected_sig_rdatas.clear();
+ doFindTest(finder, isc::dns::Name("dname.example.org."),
+ isc::dns::RRType::A(), isc::dns::RRType::A(),
+ isc::dns::RRTTL(3600), ZoneFinder::SUCCESS, expected_rdatas,
+ expected_sig_rdatas);
+ EXPECT_FALSE(current_database_->searchRunning());
+ expected_rdatas.clear();
+ doFindTest(finder, isc::dns::Name("dname.example.org."),
+ isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
+ isc::dns::RRTTL(3600), ZoneFinder::NXRRSET, expected_rdatas,
+ expected_sig_rdatas);
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // This is broken dname, it contains two targets
+ EXPECT_THROW(finder->find(isc::dns::Name("below.baddname.example.org."),
+ isc::dns::RRType::A(), NULL,
+ ZoneFinder::FIND_DEFAULT),
+ DataSourceError);
+ EXPECT_FALSE(current_database_->searchRunning());
+
+ // Broken NS - it lives together with something else
+ EXPECT_FALSE(current_database_->searchRunning());
+ EXPECT_THROW(finder->find(isc::dns::Name("brokenns1.example.org."),
+ isc::dns::RRType::A(), NULL,
+ ZoneFinder::FIND_DEFAULT),
+ DataSourceError);
+ EXPECT_FALSE(current_database_->searchRunning());
+ EXPECT_THROW(finder->find(isc::dns::Name("brokenns2.example.org."),
+ isc::dns::RRType::A(), NULL,
+ ZoneFinder::FIND_DEFAULT),
+ DataSourceError);
+ EXPECT_FALSE(current_database_->searchRunning());
+}
+
+TEST_F(DatabaseClientTest, getOrigin) {
+ DataSourceClient::FindResult zone(client_->findZone(Name("example.org")));
+ ASSERT_EQ(result::SUCCESS, zone.code);
+ shared_ptr<DatabaseClient::Finder> finder(
+ dynamic_pointer_cast<DatabaseClient::Finder>(zone.zone_finder));
+ EXPECT_EQ(42, finder->zone_id());
+ EXPECT_EQ(isc::dns::Name("example.org"), finder->getOrigin());
}
}
More information about the bind10-changes
mailing list