BIND 10 trac497, updated. cd6beb6ccd33f33efbb6ac078a53fa9e0de7f3d0 [trac497] added a Message::clearSection() and resolve::makeErrorMessage

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Feb 7 11:13:02 UTC 2011


The branch, trac497 has been updated
       via  cd6beb6ccd33f33efbb6ac078a53fa9e0de7f3d0 (commit)
      from  0c303cb20840f80038f98f023ebd6903a452efdf (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 cd6beb6ccd33f33efbb6ac078a53fa9e0de7f3d0
Author: Jelte Jansen <jelte at isc.org>
Date:   Mon Feb 7 12:11:39 2011 +0100

    [trac497] added a Message::clearSection() and resolve::makeErrorMessage
    
    clearSection is a convenience function to clear all RRsets in a message
    used by makeErrorMessage, which is a helper function to quickly clear
    any data built up in the answer so far, and set an error Rcode

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

Summary of changes:
 src/lib/asiolink/asiolink.cc                       |    8 +-
 src/lib/dns/message.cc                             |    8 ++
 src/lib/dns/message.h                              |    5 +
 src/lib/dns/tests/message_unittest.cc              |   69 ++++++++++++
 src/lib/resolve/Makefile.am                        |    2 +-
 .../resolve/{resolver_callback.cc => resolve.cc}   |   35 ++++--
 src/lib/resolve/resolve.h                          |   26 +++++
 src/lib/resolve/tests/Makefile.am                  |    1 +
 src/lib/resolve/tests/resolve_unittest.cc          |  112 ++++++++++++++++++++
 9 files changed, 252 insertions(+), 14 deletions(-)
 copy src/lib/resolve/{resolver_callback.cc => resolve.cc} (53%)
 create mode 100644 src/lib/resolve/tests/resolve_unittest.cc

-----------------------------------------------------------------------
diff --git a/src/lib/asiolink/asiolink.cc b/src/lib/asiolink/asiolink.cc
index 31b069b..8cecc50 100644
--- a/src/lib/asiolink/asiolink.cc
+++ b/src/lib/asiolink/asiolink.cc
@@ -52,6 +52,7 @@ using namespace boost;
 
 // Is this something we can use in libdns++?
 namespace {
+    // TODO: remove
     class SectionInserter {
     public:
         SectionInserter(MessagePtr message, const Message::Section sect) :
@@ -65,6 +66,7 @@ namespace {
     };
 
 
+    // TODO: move to resolve.cc
     /// \brief Copies the parts relevant for a DNS answer to the
     /// target message
     ///
@@ -431,7 +433,8 @@ private:
     // Note that the footprint may change as this function may
     // need to append data to the answer we are building later.
     //
-    // returns true if we are done
+    // returns true if we are done (either we have an answer or an
+    //              error message)
     // returns false if we are not done
     bool handleRecursiveAnswer(const Message& incoming) {
         dlog("Handle response");
@@ -458,7 +461,8 @@ private:
                 // TODO: make SERVFAIL? clear currently read answers?
                 // just copy for now.
                 dlog("CNAME chain too long");
-                copyAnswerMessage(incoming, answer_message_);
+                isc::resolve::makeErrorMessage(answer_message_,
+                                               Rcode::SERVFAIL());
                 return true;
             }
 
diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc
index e9ab1b9..698508c 100644
--- a/src/lib/dns/message.cc
+++ b/src/lib/dns/message.cc
@@ -338,6 +338,14 @@ Message::removeRRset(const Section section, RRsetIterator& iterator) {
     return (removed);
 }
 
+void
+Message::clearSection(const Section section) {
+    if (section >= MessageImpl::NUM_SECTIONS) {
+        isc_throw(OutOfRange, "Invalid message section: " << section);
+    }
+    impl_->rrsets_[section].clear();
+    impl_->counts_[section] = 0;
+}
 
 void
 Message::addQuestion(const QuestionPtr question) {
diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h
index de82085..ad12855 100644
--- a/src/lib/dns/message.h
+++ b/src/lib/dns/message.h
@@ -483,6 +483,11 @@ public:
     /// found in the specified section.
     bool removeRRset(const Section section, RRsetIterator& iterator);
 
+    /// \brief Remove all RRSets from the given Section
+    ///
+    /// \param section Section to remove all rrsets from
+    void clearSection(const Section section);
+
     // The following methods are not currently implemented.
     //void removeQuestion(QuestionPtr question);
     // notyet:
diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc
index ee1375a..996ea3a 100644
--- a/src/lib/dns/tests/message_unittest.cc
+++ b/src/lib/dns/tests/message_unittest.cc
@@ -297,6 +297,75 @@ TEST_F(MessageTest, removeRRset) {
     EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER));
 }
 
+TEST_F(MessageTest, clearQuestionSection) {
+    QuestionPtr q(new Question(Name("www.example.com"), RRClass::IN(),
+                               RRType::A()));
+    message_render.addQuestion(q);
+    ASSERT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION));
+
+    message_render.clearSection(Message::SECTION_QUESTION);
+    EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_QUESTION));
+}
+
+
+TEST_F(MessageTest, clearAnswerSection) {
+    // Add two RRsets, check they are present, clear the section,
+    // check if they are gone.
+    message_render.addRRset(Message::SECTION_ANSWER, rrset_a);
+    message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa);
+    ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+        RRClass::IN(), RRType::A()));
+    ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+        RRClass::IN(), RRType::AAAA()));
+    ASSERT_EQ(3, message_render.getRRCount(Message::SECTION_ANSWER));
+
+    message_render.clearSection(Message::SECTION_ANSWER);
+    EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+        RRClass::IN(), RRType::A()));
+    EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name,
+        RRClass::IN(), RRType::AAAA()));
+    EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER));
+}
+
+TEST_F(MessageTest, clearAuthoritySection) {
+    // Add two RRsets, check they are present, clear the section,
+    // check if they are gone.
+    message_render.addRRset(Message::SECTION_AUTHORITY, rrset_a);
+    message_render.addRRset(Message::SECTION_AUTHORITY, rrset_aaaa);
+    ASSERT_TRUE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+        RRClass::IN(), RRType::A()));
+    ASSERT_TRUE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+        RRClass::IN(), RRType::AAAA()));
+    ASSERT_EQ(3, message_render.getRRCount(Message::SECTION_AUTHORITY));
+
+    message_render.clearSection(Message::SECTION_AUTHORITY);
+    EXPECT_FALSE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+        RRClass::IN(), RRType::A()));
+    EXPECT_FALSE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name,
+        RRClass::IN(), RRType::AAAA()));
+    EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY));
+}
+
+TEST_F(MessageTest, clearAdditionalSection) {
+    // Add two RRsets, check they are present, clear the section,
+    // check if they are gone.
+    message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_a);
+    message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_aaaa);
+    ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+        RRClass::IN(), RRType::A()));
+    ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+        RRClass::IN(), RRType::AAAA()));
+    ASSERT_EQ(3, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+
+    message_render.clearSection(Message::SECTION_ADDITIONAL);
+    EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+        RRClass::IN(), RRType::A()));
+    EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name,
+        RRClass::IN(), RRType::AAAA()));
+    EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL));
+}
+
+
 TEST_F(MessageTest, badBeginSection) {
     // valid cases are tested via other tests
     EXPECT_THROW(message_render.beginSection(Message::SECTION_QUESTION),
diff --git a/src/lib/resolve/Makefile.am b/src/lib/resolve/Makefile.am
index cd159f1..c9f1326 100644
--- a/src/lib/resolve/Makefile.am
+++ b/src/lib/resolve/Makefile.am
@@ -10,7 +10,7 @@ AM_CXXFLAGS = $(B10_CXXFLAGS)
 CLEANFILES = *.gcno *.gcda
 
 lib_LTLIBRARIES = libresolve.la
-libresolve_la_SOURCES = resolve.h
+libresolve_la_SOURCES = resolve.h resolve.cc
 libresolve_la_SOURCES += resolver_interface.h
 libresolve_la_SOURCES += resolver_callback.h resolver_callback.cc
 libresolve_la_SOURCES += response_classifier.cc response_classifier.h
diff --git a/src/lib/resolve/resolve.cc b/src/lib/resolve/resolve.cc
new file mode 100644
index 0000000..6be836e
--- /dev/null
+++ b/src/lib/resolve/resolve.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <resolve/resolve.h>
+
+using namespace isc::dns;
+
+namespace {
+    class SectionInserter {
+    public:
+        SectionInserter(MessagePtr message, const Message::Section sect) :
+            message_(message), section_(sect)
+        {}
+        void operator()(const RRsetPtr rrset) {
+            message_->addRRset(section_, rrset, true);
+        }
+        MessagePtr message_;
+        const Message::Section section_;
+    };
+}
+
+namespace isc {
+namespace resolve {
+
+void
+makeErrorMessage(MessagePtr answer_message,
+                 const Rcode::Rcode& error_code)
+{
+    answer_message->clearSection(Message::SECTION_ANSWER);
+    answer_message->clearSection(Message::SECTION_AUTHORITY);
+    answer_message->clearSection(Message::SECTION_ADDITIONAL);
+
+    answer_message->setRcode(error_code);
+}
+
+} // namespace resolve
+} // namespace isc
+
diff --git a/src/lib/resolve/resolve.h b/src/lib/resolve/resolve.h
index ac87fe9..7b8931c 100644
--- a/src/lib/resolve/resolve.h
+++ b/src/lib/resolve/resolve.h
@@ -15,7 +15,33 @@
 #ifndef _ISC_RESOLVE_H
 #define _ISC_RESOLVE_H 1
 
+/// This file includes all other libresolve headers, and provides
+/// several helper functions used in resolving.
+
 #include <resolve/resolver_interface.h>
 #include <resolve/resolver_callback.h>
 #include <resolve/response_classifier.h>
+
+namespace isc {
+namespace resolve {
+
+/// \brief Create an error response
+///
+/// Clears the answer, authority, and additional section of the
+/// given MessagePtr and sets the given error code
+///
+/// Notes: Assuming you have already done initial preparations
+/// on the given answer message (copy the opcode, qid and question
+/// section), you can simply use this to create an error response.
+///
+/// \param answer_message The message to clear and place the error in
+/// \param question The question to add to the
+/// \param error_code The error Rcode
+void
+makeErrorMessage(isc::dns::MessagePtr answer_message,
+                 const isc::dns::Rcode::Rcode& error_code);
+
+} // namespace resolve
+} // namespace isc
+
 #endif // ISC_RESOLVE_H_
diff --git a/src/lib/resolve/tests/Makefile.am b/src/lib/resolve/tests/Makefile.am
index 5df401b..3b5f41a 100644
--- a/src/lib/resolve/tests/Makefile.am
+++ b/src/lib/resolve/tests/Makefile.am
@@ -14,6 +14,7 @@ TESTS += run_unittests
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_SOURCES = run_unittests.cc
+run_unittests_SOURCES += resolve_unittest.cc
 run_unittests_SOURCES += resolver_callback_unittest.cc
 run_unittests_SOURCES += response_classifier_unittest.cc
 
diff --git a/src/lib/resolve/tests/resolve_unittest.cc b/src/lib/resolve/tests/resolve_unittest.cc
new file mode 100644
index 0000000..fddfa70
--- /dev/null
+++ b/src/lib/resolve/tests/resolve_unittest.cc
@@ -0,0 +1,112 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <iostream>
+#include <gtest/gtest.h>
+
+#include <dns/message.h>
+#include <dns/question.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+#include <resolve/resolve.h>
+
+using namespace isc::dns;
+
+namespace {
+
+class ResolveHelperFunctionsTest : public ::testing::Test {
+public:
+    ResolveHelperFunctionsTest() :
+        message_(new Message(Message::RENDER)),
+        question_(new Question(Name("www.example.com"), RRClass::IN(), RRType::A()))
+    {
+        message_->setOpcode(Opcode::QUERY());
+        message_->setRcode(Rcode::NOERROR());
+        message_->addQuestion(question_);
+    };
+
+    MessagePtr message_;
+    QuestionPtr question_;
+    
+};
+
+TEST_F(ResolveHelperFunctionsTest, makeErrorMessageEmptyMessage) {
+    ASSERT_EQ(Rcode::NOERROR(), message_->getRcode());
+    ASSERT_EQ(1, message_->getRRCount(Message::SECTION_QUESTION));
+    ASSERT_EQ(0, message_->getRRCount(Message::SECTION_ANSWER));
+    ASSERT_EQ(0, message_->getRRCount(Message::SECTION_AUTHORITY));
+    ASSERT_EQ(0, message_->getRRCount(Message::SECTION_ADDITIONAL));
+
+    isc::resolve::makeErrorMessage(message_, Rcode::SERVFAIL());
+    EXPECT_EQ(Rcode::SERVFAIL(), message_->getRcode());
+    EXPECT_EQ(1, message_->getRRCount(Message::SECTION_QUESTION));
+    EXPECT_EQ(0, message_->getRRCount(Message::SECTION_ANSWER));
+    EXPECT_EQ(0, message_->getRRCount(Message::SECTION_AUTHORITY));
+    EXPECT_EQ(0, message_->getRRCount(Message::SECTION_ADDITIONAL));
+}
+
+TEST_F(ResolveHelperFunctionsTest, makeErrorMessageNonEmptyMessage) {
+    // We could reuse the same rrset in the different sections,
+    // but to be sure, we create separate ones
+    RRsetPtr answer_rrset(new RRset(Name("www.example.com"),
+                                    RRClass::IN(), RRType::TXT(),
+                                    RRTTL(3600)));
+    answer_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+                                              RRClass::IN(),
+                                              "Answer"));
+    message_->addRRset(Message::SECTION_ANSWER, answer_rrset);
+
+    RRsetPtr auth_rrset(new RRset(Name("www.example.com"),
+                                    RRClass::IN(), RRType::TXT(),
+                                    RRTTL(3600)));
+    auth_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+                                              RRClass::IN(),
+                                              "Authority"));
+    auth_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+                                              RRClass::IN(),
+                                              "Rdata"));
+    message_->addRRset(Message::SECTION_AUTHORITY, auth_rrset);
+
+    RRsetPtr add_rrset(new RRset(Name("www.example.com"),
+                                 RRClass::IN(), RRType::TXT(),
+                                 RRTTL(3600)));
+    add_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+                                           RRClass::IN(),
+                                           "Additional"));
+    add_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+                                           RRClass::IN(),
+                                           "Rdata"));
+    add_rrset->addRdata(rdata::createRdata(RRType::TXT(),
+                                           RRClass::IN(),
+                                           "fields."));
+    message_->addRRset(Message::SECTION_ADDITIONAL, add_rrset);
+
+    ASSERT_EQ(Rcode::NOERROR(), message_->getRcode());
+    ASSERT_EQ(1, message_->getRRCount(Message::SECTION_QUESTION));
+    ASSERT_EQ(1, message_->getRRCount(Message::SECTION_ANSWER));
+    ASSERT_EQ(2, message_->getRRCount(Message::SECTION_AUTHORITY));
+    ASSERT_EQ(3, message_->getRRCount(Message::SECTION_ADDITIONAL));
+
+    isc::resolve::makeErrorMessage(message_, Rcode::FORMERR());
+    EXPECT_EQ(Rcode::FORMERR(), message_->getRcode());
+    EXPECT_EQ(1, message_->getRRCount(Message::SECTION_QUESTION));
+    EXPECT_EQ(0, message_->getRRCount(Message::SECTION_ANSWER));
+    EXPECT_EQ(0, message_->getRRCount(Message::SECTION_AUTHORITY));
+    EXPECT_EQ(0, message_->getRRCount(Message::SECTION_ADDITIONAL));
+}
+
+
+} // Anonymous namespace




More information about the bind10-changes mailing list