Browse Source

implement ANY query logic

chenzhengzhang 14 years ago
parent
commit
239c969495
2 changed files with 59 additions and 15 deletions
  1. 23 6
      src/bin/auth/query.cc
  2. 36 9
      src/bin/auth/tests/query_unittest.cc

+ 23 - 6
src/bin/auth/query.cc

@@ -122,6 +122,10 @@ Query::getAuthAdditional(const Zone& zone) const {
 void
 Query::process() const {
     bool keep_doing = true;
+    const bool qtype_is_any = (qtype_ == RRType::ANY());
+    RRsetList result_rrsets;
+    RRsetList* target = NULL;
+
     response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
     const MemoryDataSrc::FindResult result =
         memory_datasrc_.findZone(qname_);
@@ -141,20 +145,33 @@ Query::process() const {
     response_.setHeaderFlag(Message::HEADERFLAG_AA);
     while (keep_doing) {
         keep_doing = false;
-        Zone::FindResult db_result = result.zone->find(qname_, qtype_);
+        if (qtype_is_any) {
+            target = &result_rrsets;
+        }
+
+        Zone::FindResult db_result = result.zone->find(qname_, qtype_, target);
+
         switch (db_result.code) {
             case Zone::SUCCESS:
                 response_.setRcode(Rcode::NOERROR());
-                response_.addRRset(Message::SECTION_ANSWER,
-                    boost::const_pointer_cast<RRset>(db_result.rrset));
-                // Handle additional for answer section
-                getAdditional(*result.zone, *db_result.rrset);
+                if (qtype_is_any) {
+                    // If quety type is ANY, insert all RRs under the domain
+                    // into answer section.
+                    BOOST_FOREACH(RRsetPtr rrset, *target) {
+                        response_.addRRset(Message::SECTION_ANSWER, rrset);
+                    }
+                } else {
+                    response_.addRRset(Message::SECTION_ANSWER,
+                        boost::const_pointer_cast<RRset>(db_result.rrset));
+                    // Handle additional for answer section
+                    getAdditional(*result.zone, *db_result.rrset);
+                }
                 // If apex NS records haven't been provided in the answer
                 // section, insert apex NS records into the authority section
                 // and AAAA/A RRS of each of the NS RDATA into the additional
                 // section.
                 if (qname_ != result.zone->getOrigin() ||
-                    (qtype_ != RRType::NS() && qtype_ != RRType::ANY()))
+                    (qtype_ != RRType::NS() && !qtype_is_any))
                 {
                     getAuthAdditional(*result.zone);
                 }

+ 36 - 9
src/bin/auth/tests/query_unittest.cc

@@ -59,10 +59,10 @@ const char* const ns_addrs_txt =
     "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n"
     "noglue.example.com. 3600 IN A 192.0.2.53\n";
 const char* const delegation_txt =
-        "delegation.example.com. 3600 IN NS glue.delegation.example.com.\n"
-        "delegation.example.com. 3600 IN NS noglue.example.com.\n"
-        "delegation.example.com. 3600 IN NS cname.example.com.\n"
-        "delegation.example.com. 3600 IN NS example.org.\n";
+    "delegation.example.com. 3600 IN NS glue.delegation.example.com.\n"
+    "delegation.example.com. 3600 IN NS noglue.example.com.\n"
+    "delegation.example.com. 3600 IN NS cname.example.com.\n"
+    "delegation.example.com. 3600 IN NS example.org.\n";
 const char* const mx_txt =
     "mx.example.com. 3600 IN MX 10 www.example.com.\n"
     "mx.example.com. 3600 IN MX 20 mailer.example.org.\n"
@@ -172,10 +172,8 @@ MockZone::find(const Name& name, const RRType& type,
                  found_rrset != found_domain->second.end(); found_rrset++)
             {
                 // Insert RRs under the domain name into target
-                if (target) {
-                    target->addRRset(
-                        boost::const_pointer_cast<RRset>(found_rrset->second));
-                }
+                target->addRRset(
+                    boost::const_pointer_cast<RRset>(found_rrset->second));
             }
             return (FindResult(SUCCESS, found_domain->second.begin()->second));
         }
@@ -238,7 +236,8 @@ responseCheck(Message& response, const isc::dns::Rcode& rcode,
     if (expected_answer != NULL) {
         rrsetsCheck(expected_answer,
                     response.beginSection(Message::SECTION_ANSWER),
-                    response.endSection(Message::SECTION_ANSWER));
+                    response.endSection(Message::SECTION_ANSWER),
+                    check_origin);
     }
     if (expected_authority != NULL) {
         rrsetsCheck(expected_authority,
@@ -292,6 +291,7 @@ TEST_F(QueryTest, apexNSMatch) {
                   zone_ns_txt, NULL, ns_addrs_txt);
 }
 
+// test type any query logic
 TEST_F(QueryTest, exactAnyMatch) {
     // find match rrset, omit additional data which has already been provided
     // in the answer section from the additional.
@@ -305,6 +305,33 @@ TEST_F(QueryTest, exactAnyMatch) {
                   "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
 }
 
+TEST_F(QueryTest, apexAnyMatch) {
+    // find match rrset, omit additional data which has already been provided
+    // in the answer section from the additional.
+    EXPECT_NO_THROW(Query(memory_datasrc, Name("example.com"),
+                          RRType::ANY(), response).process());
+    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 4, 0, 0,
+                  "example.com. 3600 IN SOA . . 0 0 0 0 0\n"
+                  "example.com. 3600 IN NS glue.delegation.example.com.\n"
+                  "example.com. 3600 IN NS noglue.example.com.\n"
+                  "example.com. 3600 IN NS example.net.\n",
+                  NULL, NULL, mock_zone->getOrigin());
+}
+
+TEST_F(QueryTest, glueANYMatch) {
+    EXPECT_NO_THROW(Query(memory_datasrc, Name("delegation.example.com"),
+                          RRType::ANY(), response).process());
+    responseCheck(response, Rcode::NOERROR(), 0, 0, 4, 3,
+                  NULL, delegation_txt, ns_addrs_txt);
+}
+
+TEST_F(QueryTest, nodomainANY) {
+    EXPECT_NO_THROW(Query(memory_datasrc, Name("nxdomain.example.com"),
+                          RRType::ANY(), response).process());
+    responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 1, 0,
+                  NULL, soa_txt, NULL, mock_zone->getOrigin());
+}
+
 // This tests that when we need to look up Zone's apex NS records for
 // authoritative answer, and there is no apex NS records. It should
 // throw in that case.