BIND 10 master, updated. 1f051716bce3d7aa2545722ba41958df9758cadc Merge branch #1066

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Aug 25 10:11:20 UTC 2011


The branch, master has been updated
       via  1f051716bce3d7aa2545722ba41958df9758cadc (commit)
       via  27b3488b71a5c3b95652eab2720497d6d055346e (commit)
       via  4ff5e524a7f79ad7f4513ebed3ca0990392263af (commit)
       via  b4ae924f504e9749989059a14e6a5dc830c99e81 (commit)
       via  2384bcf387e93435658ec1ab92addbf28c9ab640 (commit)
       via  1d314b2544b8af8a936c90e00a0dbbb605410952 (commit)
       via  e3c81bd07046903b4b3bff8325024aafcdb35cba (commit)
       via  9001f1db99dfff10957dc2a971e7466a496f0f2f (commit)
       via  616fb3be8c0b3c266eaf0aa4ae399918fc7992ef (commit)
      from  d916aef6af6bb8506b1ff4756054a1697410982f (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 1f051716bce3d7aa2545722ba41958df9758cadc
Merge: d916aef6af6bb8506b1ff4756054a1697410982f 27b3488b71a5c3b95652eab2720497d6d055346e
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu Aug 25 12:03:32 2011 +0200

    Merge branch #1066

commit 27b3488b71a5c3b95652eab2720497d6d055346e
Merge: 4ff5e524a7f79ad7f4513ebed3ca0990392263af 087c6def9087019640a437b63c782a5c22de1feb
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Aug 24 12:02:48 2011 +0200

    Merge branch 'master' into #1066
    
    Just to bring in changes and solve conflicts, there was some refactoring
    elsewhere.
    
    Conflicts:
    	src/lib/datasrc/database.cc
    	src/lib/datasrc/datasrc_messages.mes
    	src/lib/datasrc/tests/database_unittest.cc

commit 4ff5e524a7f79ad7f4513ebed3ca0990392263af
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Aug 23 13:54:20 2011 +0200

    [1066] add one test and typo in comment

commit b4ae924f504e9749989059a14e6a5dc830c99e81
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Aug 17 15:23:21 2011 +0200

    [1066] Logging about wildcards

commit 2384bcf387e93435658ec1ab92addbf28c9ab640
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Aug 17 13:43:01 2011 +0200

    [1066] More wildcard cornercases
    
    Wildcard match below NS with GLUE_OK mode
    Empty non-terminal asterisk

commit 1d314b2544b8af8a936c90e00a0dbbb605410952
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Aug 17 11:49:00 2011 +0200

    [1066] Cancel wildcard match

commit e3c81bd07046903b4b3bff8325024aafcdb35cba
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 9001f1db99dfff10957dc2a971e7466a496f0f2f
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Mon Aug 15 13:00:28 2011 +0200

    [1066] Tests for some basic wildcards

commit 616fb3be8c0b3c266eaf0aa4ae399918fc7992ef
Merge: 44bd4bc6dc7df56905071933a542e00e91f84837 39a0a5c65d0802f40ab428474b1e6d981a91fbce
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Aug 17 10:44:14 2011 +0200

    Merge branch #1065 into master
    
    Conflicts:
    	src/lib/datasrc/tests/database_unittest.cc

-----------------------------------------------------------------------

Summary of changes:
 src/lib/datasrc/database.cc                |  134 ++++++++++++++++++++----
 src/lib/datasrc/database.h                 |   16 +++-
 src/lib/datasrc/datasrc_messages.mes       |   27 +++++
 src/lib/datasrc/tests/database_unittest.cc |  154 ++++++++++++++++++++++++++--
 4 files changed, 300 insertions(+), 31 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index 58d28ca..347e3ab 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -175,7 +175,8 @@ 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)
+                                 bool want_ns,
+                                 const isc::dns::Name* construct_name)
 {
     RRsigStore sig_store;
     bool records_found = false;
@@ -191,6 +192,9 @@ DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
     }
 
     std::string columns[DatabaseAccessor::COLUMN_COUNT];
+    if (construct_name == NULL) {
+        construct_name = &name;
+    }
     while (context->getNext(columns)) {
         if (!records_found) {
             records_found = true;
@@ -225,7 +229,8 @@ DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
                     isc_throw(DataSourceError, "NS found together with data"
                               " in non-apex domain " + name.toText());
                 }
-                addOrCreate(result_rrset, name, getClass(), cur_type, cur_ttl,
+                addOrCreate(result_rrset, *construct_name, getClass(),
+                            cur_type, cur_ttl,
                             columns[DatabaseAccessor::RDATA_COLUMN],
                             *database_);
             } else if (type != NULL && cur_type == *type) {
@@ -238,7 +243,8 @@ DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
                     isc_throw(DataSourceError, "NS found together with data"
                               " in non-apex domain " + name.toText());
                 }
-                addOrCreate(result_rrset, name, getClass(), cur_type, cur_ttl,
+                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()) {
@@ -248,7 +254,8 @@ DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
                     isc_throw(DataSourceError, "CNAME found but it is not "
                               "the only record for " + name.toText());
                 }
-                addOrCreate(result_rrset, name, getClass(), cur_type, cur_ttl,
+                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()) {
@@ -258,7 +265,8 @@ DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
                     isc_throw(DataSourceError, "DNAME with multiple RRs in " +
                               name.toText());
                 }
-                addOrCreate(result_rrset, name, getClass(), cur_type, cur_ttl,
+                addOrCreate(result_rrset, *construct_name, getClass(),
+                            cur_type, cur_ttl,
                             columns[DatabaseAccessor::RDATA_COLUMN],
                             *database_);
             } else if (cur_type == isc::dns::RRType::RRSIG()) {
@@ -292,6 +300,20 @@ DatabaseClient::Finder::getRRset(const isc::dns::Name& name,
     return (std::pair<bool, isc::dns::RRsetPtr>(records_found, result_rrset));
 }
 
+bool
+DatabaseClient::Finder::hasSubdomains(const std::string& name) {
+    // Request the context
+    DatabaseAccessor::IteratorContextPtr
+        context(database_->getRecords(name, zone_id_, true));
+    // It must not return NULL, that's a bug of the implementation
+    if (!context) {
+        isc_throw(isc::Unexpected, "Iterator context null at " + name);
+    }
+
+    std::string columns[DatabaseAccessor::COLUMN_COUNT];
+    return (context->getNext(columns));
+}
+
 ZoneFinder::FindResult
 DatabaseClient::Finder::find(const isc::dns::Name& name,
                              const isc::dns::RRType& type,
@@ -307,20 +329,35 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
     std::pair<bool, isc::dns::RRsetPtr> found;
     logger.debug(DBG_TRACE_DETAILED, DATASRC_DATABASE_FIND_RECORDS)
         .arg(database_->getDBName()).arg(name).arg(type);
+    // In case we are in GLUE_OK mode and start matching wildcards,
+    // we can't do it under NS, so we store it here to check
+    isc::dns::RRsetPtr first_ns;
 
     // First, do we have any kind of delegation (NS/DNAME) here?
-    const Name origin(getOrigin());
-    const size_t origin_label_count(origin.getLabelCount());
-    const size_t current_label_count(name.getLabelCount());
+    Name origin(getOrigin());
+    size_t origin_label_count(origin.getLabelCount());
+    // Number of labels in the last known non-empty domain
+    size_t last_known(origin_label_count);
+    size_t current_label_count(name.getLabelCount());
     // This is how many labels we remove to get origin
-    const size_t remove_labels(current_label_count - origin_label_count);
+    size_t remove_labels(current_label_count - origin_label_count);
 
     // Now go trough all superdomains from origin down
     for (int i(remove_labels); i > 0; --i) {
-        const Name superdomain(name.split(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 != remove_labels && !glue_ok);
+        if (found.first) {
+            // It contains some RRs, so it exists.
+            last_known = superdomain.getLabelCount();
+            // In case we are in GLUE_OK, we want to store the highest
+            // encountered RRset.
+            if (glue_ok && !first_ns && i != remove_labels) {
+                first_ns = getRRset(superdomain, NULL, false, false,
+                                    true).second;
+            }
+        }
         if (found.second) {
             // We found something redirecting somewhere else
             // (it can be only NS or DNAME here)
@@ -360,18 +397,73 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
         }
 
         if (!result_rrset && !records_found) {
-            // Request the context
-            DatabaseAccessor::IteratorContextPtr
-                context(database_->getRecords(name.toText(), zone_id_, true));
-            // It must not return NULL, that's a bug of the implementation
-            if (!context) {
-                isc_throw(isc::Unexpected, "Iterator context null at " +
-                          name.toText());
-            }
-
-            std::string columns[DatabaseAccessor::COLUMN_COUNT];
-            if (context->getNext(columns)) {
+            // Nothing lives here.
+            // But check if something lives below this
+            // domain and if so, pretend something is here as well.
+            if (hasSubdomains(name.toText())) {
+                LOG_DEBUG(logger, DBG_TRACE_DETAILED,
+                          DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL).
+                    arg(database_->getDBName()).arg(name);
                 records_found = true;
+            } 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.
+
+                remove_labels = current_label_count - last_known;
+                Name star("*");
+                for (size_t i(1); i <= remove_labels; ++ 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);
+                    if (found.first) {
+                        if (first_ns) {
+                            // In case we are under NS, we don't
+                            // wildcard-match, but return delegation
+                            result_rrset = first_ns;
+                            result_status = DELEGATION;
+                            records_found = true;
+                            // We pretend to switch to non-glue_ok mode
+                            glue_ok = false;
+                            LOG_DEBUG(logger, DBG_TRACE_DETAILED,
+                                      DATASRC_DATABASE_WILDCARD_CANCEL_NS).
+                                arg(database_->getDBName()).arg(wildcard).
+                                arg(first_ns->getName());
+                        } else if (!hasSubdomains(name.split(i - 1).toText()))
+                        {
+                            // Nothing we added as part of the * can exist
+                            // directly, as we go up only to first existing
+                            // domain, but it could be empty non-terminal. In
+                            // that case, we need to cancel the match.
+                            records_found = true;
+                            result_rrset = found.second;
+                            LOG_DEBUG(logger, DBG_TRACE_DETAILED,
+                                      DATASRC_DATABASE_WILDCARD).
+                                arg(database_->getDBName()).arg(wildcard).
+                                arg(name);
+                        } else {
+                            LOG_DEBUG(logger, DBG_TRACE_DETAILED,
+                                      DATASRC_DATABASE_WILDCARD_CANCEL_SUB).
+                                arg(database_->getDBName()).arg(wildcard).
+                                arg(name).arg(superdomain);
+                        }
+                        break;
+                    } else if (hasSubdomains(wildcard.toText())) {
+                        // Empty non-terminal asterisk
+                        records_found = true;
+                        LOG_DEBUG(logger, DBG_TRACE_DETAILED,
+                                  DATASRC_DATABASE_WILDCARD_EMPTY).
+                            arg(database_->getDBName()).arg(wildcard).
+                            arg(name);
+                        break;
+                    }
+                }
             }
         }
     }
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index e63de75..1120a3e 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -375,6 +375,9 @@ public:
          *     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
@@ -392,7 +395,18 @@ public:
                                                      type,
                                                      bool want_cname,
                                                      bool want_dname,
-                                                     bool want_ns);
+                                                     bool want_ns, const
+                                                     isc::dns::Name*
+                                                     construct_name = NULL);
+        /**
+         * \brief Checks if something lives below this domain.
+         *
+         * This looks if there's any subdomain of the given name. It can be
+         * used to test if domain is empty non-terminal.
+         *
+         * \param name The domain to check.
+         */
+        bool hasSubdomains(const std::string& name);
     };
     /**
      * \brief Find a zone in the database
diff --git a/src/lib/datasrc/datasrc_messages.mes b/src/lib/datasrc/datasrc_messages.mes
index 659d2bd..5f92407 100644
--- a/src/lib/datasrc/datasrc_messages.mes
+++ b/src/lib/datasrc/datasrc_messages.mes
@@ -87,6 +87,11 @@ When searching for a domain, the program met a DNAME redirection to a different
 place in the domain space at the given domain name. It will return that one
 instead.
 
+% DATASRC_DATABASE_FOUND_EMPTY_NONTERMINAL empty non-terminal %2 in %1
+The domain name doesn't have any RRs, so it doesn't exist in the database.
+However, it has a subdomain, so it exists in the DNS address space. So we
+return NXRRSET instead of NXDOMAIN.
+
 % DATASRC_DATABASE_FOUND_NXDOMAIN search in datasource %1 resulted in NXDOMAIN for %2/%3/%4
 The data returned by the database backend did not contain any data for the given
 domain name, class and type.
@@ -117,6 +122,28 @@ were found to be different. This isn't allowed on the wire and is considered
 an error, so we set it to the lowest value we found (but we don't modify the
 database). The data in database should be checked and fixed.
 
+% DATASRC_DATABASE_WILDCARD constructing RRset %3 from wildcard %2 in %1
+The database doesn't contain directly matching domain, but it does contain a
+wildcard one which is being used to synthesize the answer.
+
+% DATASRC_DATABASE_WILDCARD_CANCEL_NS canceled wildcard match on %2 because %3 contains NS in %1
+The database was queried to provide glue data and it didn't find direct match.
+It could create it from given wildcard, but matching wildcards is forbidden
+under a zone cut, which was found. Therefore the delegation will be returned
+instead.
+
+% DATASRC_DATABASE_WILDCARD_CANCEL_SUB wildcard %2 can't be used to construct %3 because %4 exists in %1
+The answer could be constructed using the wildcard, but the given subdomain
+exists, therefore this name is something like empty non-terminal (actually,
+from the protocol point of view, it is empty non-terminal, but the code
+discovers it differently).
+
+% DATASRC_DATABASE_WILDCARD_EMPTY implicit wildcard %2 used to construct %3 in %1
+The given wildcard exists implicitly in the domainspace, as empty nonterminal
+(eg. there's something like subdomain.*.example.org, so *.example.org exists
+implicitly, but is empty). This will produce NXRRSET, because the constructed
+domain is empty as well as the wildcard.
+
 % DATASRC_DO_QUERY handling query for '%1/%2'
 A debug message indicating that a query for the given name and RR type is being
 processed.
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index 7873277..13bda70 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -458,6 +458,20 @@ 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.");
+        addRecord("NS", "3600", "", "ns.example.com.");
+        addCurName("delegatedwild.example.org.");
+        addRecord("A", "3600", "", "192.0.2.5");
+        addCurName("*.delegatedwild.example.org.");
+        addRecord("A", "3600", "", "192.0.2.5");
+        addCurName("wild.*.foo.example.org.");
+        addRecord("A", "3600", "", "192.0.2.5");
+        addCurName("wild.*.foo.*.bar.example.org.");
     }
 };
 
@@ -670,12 +684,12 @@ doFindTest(shared_ptr<DatabaseClient::Finder> finder,
     ZoneFinder::FindResult result =
         finder->find(name, type, NULL, options);
     ASSERT_EQ(expected_result, result.code) << name << " " << type;
-    if (expected_rdatas.size() > 0) {
+    if (!expected_rdatas.empty()) {
         checkRRset(result.rrset, expected_name != Name(".") ? expected_name :
                    name, finder->getClass(), expected_type, expected_ttl,
                    expected_rdatas);
 
-        if (expected_sig_rdatas.size() > 0) {
+        if (!expected_sig_rdatas.empty()) {
             checkRRset(result.rrset->getRRsig(), expected_name != Name(".") ?
                        expected_name : name, finder->getClass(),
                        isc::dns::RRType::RRSIG(), expected_ttl,
@@ -1074,6 +1088,16 @@ TEST_F(DatabaseClientTest, findDelegation) {
                  DataSourceError);
 }
 
+TEST_F(DatabaseClientTest, emptyDomain) {
+    shared_ptr<DatabaseClient::Finder> finder(getFinder());
+
+    // 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_);
+}
+
 // Glue-OK mode. Just go trough NS delegations down (but not trough
 // DNAME) and pretend it is not there.
 TEST_F(DatabaseClientTest, glueOK) {
@@ -1133,15 +1157,127 @@ TEST_F(DatabaseClientTest, glueOK) {
                ZoneFinder::FIND_GLUE_OK);
 }
 
-TEST_F(DatabaseClientTest, empty) {
+TEST_F(DatabaseClientTest, wildcard) {
     shared_ptr<DatabaseClient::Finder> finder(getFinder());
 
-    // Check empty domain
-    // 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_);
+    // First, simple wildcard match
+    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_);
+    // Also make sure that the wildcard doesn't hurt the original data
+    // below the wildcard
+    expected_rdatas_.push_back("2001:db8::5");
+    doFindTest(finder, isc::dns::Name("cancel.here.wild.example.org"),
+               isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
+               isc::dns::RRTTL(3600), ZoneFinder::SUCCESS,
+               expected_rdatas_, expected_sig_rdatas_);
+    expected_rdatas_.clear();
+
+    // How wildcard go together with delegation
+    expected_rdatas_.push_back("ns.example.com.");
+    doFindTest(finder, isc::dns::Name("below.delegatedwild.example.org"),
+               isc::dns::RRType::A(), isc::dns::RRType::NS(),
+               isc::dns::RRTTL(3600), ZoneFinder::DELEGATION, expected_rdatas_,
+               expected_sig_rdatas_,
+               isc::dns::Name("delegatedwild.example.org"));
+    // FIXME: This doesn't look logically OK, GLUE_OK should make it transparent,
+    // so the match should either work or be canceled, but return NXDOMAIN
+    doFindTest(finder, isc::dns::Name("below.delegatedwild.example.org"),
+               isc::dns::RRType::A(), isc::dns::RRType::NS(),
+               isc::dns::RRTTL(3600), ZoneFinder::DELEGATION, expected_rdatas_,
+               expected_sig_rdatas_,
+               isc::dns::Name("delegatedwild.example.org"),
+               ZoneFinder::FIND_GLUE_OK);
+
+    expected_rdatas_.clear();
+    expected_rdatas_.push_back("192.0.2.5");
+    // These are direct matches
+    const char* positive_names[] = {
+        "wild.*.foo.example.org.",
+        "wild.*.foo.*.bar.example.org.",
+        NULL
+    };
+    for (const char** name(positive_names); *name != NULL; ++ name) {
+        doFindTest(finder, isc::dns::Name(*name), isc::dns::RRType::A(),
+                   isc::dns::RRType::A(), isc::dns::RRTTL(3600),
+                   ZoneFinder::SUCCESS, expected_rdatas_,
+                   expected_sig_rdatas_);
+    }
+
+    // These are wildcard matches against empty nonterminal asterisk
+    expected_rdatas_.clear();
+    const char* negative_names[] = {
+        "a.foo.example.org.",
+        "*.foo.example.org.",
+        "foo.example.org.",
+        "wild.bar.foo.example.org.",
+        "baz.foo.*.bar.example.org",
+        "baz.foo.baz.bar.example.org",
+        "*.foo.baz.bar.example.org",
+        "*.foo.*.bar.example.org",
+        "foo.*.bar.example.org",
+        "*.bar.example.org",
+        "bar.example.org",
+        NULL
+    };
+    for (const char** name(negative_names); *name != NULL; ++ name) {
+        doFindTest(finder, isc::dns::Name(*name), isc::dns::RRType::A(),
+                   isc::dns::RRType::A(), isc::dns::RRTTL(3600),
+                   ZoneFinder::NXRRSET, expected_rdatas_,
+                   expected_sig_rdatas_);
+    }
 }
 
 TEST_F(DatabaseClientTest, getOrigin) {




More information about the bind10-changes mailing list