Browse Source

sync with master
Merge branch 'master' into trac467

Conflicts:
src/bin/auth/tests/auth_srv_unittest.cc

JINMEI Tatuya 14 years ago
parent
commit
4f7e1f46da
49 changed files with 1336 additions and 625 deletions
  1. 1 0
      AUTHORS
  2. 22 6
      ChangeLog
  3. 2 1
      README
  4. 23 5
      configure.ac
  5. 1 1
      src/bin/Makefile.am
  6. 1 1
      src/bin/auth/auth_srv.h
  7. 93 3
      src/bin/auth/query.cc
  8. 78 9
      src/bin/auth/query.h
  9. 1 0
      src/bin/auth/tests/Makefile.am
  10. 21 10
      src/bin/auth/tests/auth_srv_unittest.cc
  11. 331 22
      src/bin/auth/tests/query_unittest.cc
  12. 17 17
      src/bin/bind10/bind10.py.in
  13. 1 1
      src/bin/bind10/bob.spec
  14. 1 1
      src/bin/bind10/run_bind10.sh.in
  15. 20 20
      src/bin/bind10/tests/bind10_test.py
  16. 0 57
      src/bin/recurse/Makefile.am
  17. 57 0
      src/bin/resolver/Makefile.am
  18. 10 10
      src/bin/recurse/b10-recurse.8
  19. 8 8
      src/bin/recurse/b10-recurse.xml
  20. 16 16
      src/bin/recurse/main.cc
  21. 30 30
      src/bin/recurse/recursor.cc
  22. 11 11
      src/bin/recurse/recursor.h
  23. 1 1
      src/bin/recurse/recurse.spec.pre.in
  24. 1 1
      src/bin/recurse/spec_config.h.pre.in
  25. 4 3
      src/bin/recurse/tests/Makefile.am
  26. 30 16
      src/bin/recurse/tests/recursor_config_unittest.cc
  27. 33 24
      src/bin/recurse/tests/recursor_unittest.cc
  28. 0 0
      src/bin/resolver/tests/run_unittests.cc
  29. 1 1
      src/lib/asiolink/Makefile.am
  30. 1 1
      src/lib/asiolink/README
  31. 1 1
      src/lib/asiolink/asiolink.h
  32. 1 0
      src/lib/asiolink/internal/Makefile.am
  33. 37 0
      src/lib/asiolink/internal/tests/Makefile.am
  34. 21 0
      src/lib/asiolink/internal/tests/run_unittests.cc
  35. 0 0
      src/lib/asiolink/internal/tests/udpdns_unittest.cc
  36. 0 1
      src/lib/asiolink/tests/Makefile.am
  37. 72 40
      src/lib/asiolink/tests/asiolink_unittest.cc
  38. 2 2
      src/lib/datasrc/cache.h
  39. 2 2
      src/lib/datasrc/data_source.cc
  40. 2 2
      src/lib/datasrc/rbtree.h
  41. 1 1
      src/lib/nsas/README
  42. 1 1
      src/lib/nsas/asiolink.h
  43. 10 9
      src/lib/python/isc/config/module_spec.py
  44. 4 0
      src/lib/python/isc/config/tests/module_spec_test.py
  45. 12 4
      src/lib/testutils/Makefile.am
  46. 0 2
      src/lib/testutils/README
  47. 272 0
      src/lib/testutils/srv_test.cc
  48. 82 126
      src/lib/testutils/srv_test.h
  49. 0 158
      src/lib/testutils/srv_unittest.h

+ 1 - 0
AUTHORS

@@ -0,0 +1 @@
+jreed

+ 22 - 6
ChangeLog

@@ -1,3 +1,17 @@
+  144.	[build]		jinmei
+	Introduced a workaround for clang++ build on FreeBSD (and probably
+	some other OSes).  If building BIND 10 fails with clang++ due to
+	a link error about "__dso_handle", try again from the configure
+	script with CXX_LIBTOOL_LDFLAGS=-L/usr/lib (the path actually
+	doesn't matter; the important part is the -L flag).  This
+	workaround is not automatically enabled as it's difficult to
+	detect the need for it dynamically, and must be enabled via the
+	variable by hand. (Trac #474, git cfde436)
+
+  143.	[build]		jinmei
+	Fixed build problems with clang++ in unit tests due to recent
+	changes.  No behavior change. (Trac #448, svn r4133)
+
   142.	[func]		jinmei
   142.	[func]		jinmei
 	b10-auth: updated query benchmark so that it can test in memory
 	b10-auth: updated query benchmark so that it can test in memory
 	data source.  Also fixed a bug that the output buffer isn't
 	data source.  Also fixed a bug that the output buffer isn't
@@ -58,21 +72,21 @@
 	(Trac #202, svn r3967)
 	(Trac #202, svn r3967)
 
 
   135.  [func]      each
   135.  [func]      each
-	Add b10-recurse. This is an example recursive server that
+	Add b10-resolver. This is an example recursive server that
 	currently does forwarding only and no caching.
 	currently does forwarding only and no caching.
 	(Trac #327, svn r3903)
 	(Trac #327, svn r3903)
 
 
   134.  [func]      vorner
   134.  [func]      vorner
-	b10-recurse supports timeouts and retries in forwarder mode.
+	b10-resolver supports timeouts and retries in forwarder mode.
 	(Trac #401, svn r3660)
 	(Trac #401, svn r3660)
 
 
   133.  [func]      vorner
   133.  [func]      vorner
 	New temporary logging function available in isc::log. It is used by
 	New temporary logging function available in isc::log. It is used by
-	b10-recurse.
+	b10-resolver.
 	(Trac #393, r3602)
 	(Trac #393, r3602)
 
 
   132.  [func]      vorner
   132.  [func]      vorner
-	The b10-recurse is configured through config manager.
+	The b10-resolver is configured through config manager.
 	It has "listen_on" and "forward_addresses" options.
 	It has "listen_on" and "forward_addresses" options.
 	(Trac #389, r3448)
 	(Trac #389, r3448)
 
 
@@ -135,7 +149,7 @@ bind10-devel-20101201 released on December 01, 2010
   122.  [func]		stephen
   122.  [func]		stephen
 	src/bin/bind10: Added configuration options to Boss to determine
 	src/bin/bind10: Added configuration options to Boss to determine
 	whether to start the authoritative server, recursive server (or
 	whether to start the authoritative server, recursive server (or
-	both). A dummy recursor has been provided for test purposes.
+	both). A dummy program has been provided for test purposes.
 	(Trac #412, svn r3676)
 	(Trac #412, svn r3676)
 
 
   121.  [func]		jinmei
   121.  [func]		jinmei
@@ -777,8 +791,10 @@ bind10-devel-20100421 released on April 21, 2010
 bind10-devel-20100319 released on March 19, 2010
 bind10-devel-20100319 released on March 19, 2010
 
 
 For complete code revision history, see http://bind10.isc.org/browser
 For complete code revision history, see http://bind10.isc.org/browser
-Specific subversion changesets can be accessed at:
+Specific git changesets can be accessed at:
 	http://bind10.isc.org/changeset/rrrr
 	http://bind10.isc.org/changeset/rrrr
+Subversion changesets are not accessible any more.  The subversion
+revision numbers will be replaced with corresponding git revisions.
 Trac tickets can be accessed at: https://bind10.isc.org/ticket/nnn
 Trac tickets can be accessed at: https://bind10.isc.org/ticket/nnn
 
 
 LEGEND
 LEGEND

+ 2 - 1
README

@@ -15,7 +15,7 @@ five year plan are described here:
 
 
 This release includes the bind10 master process, b10-msgq message
 This release includes the bind10 master process, b10-msgq message
 bus, b10-auth authoritative DNS server (with SQLite3 backend),
 bus, b10-auth authoritative DNS server (with SQLite3 backend),
-b10-recurse forwarding DNS server, b10-cmdctl remote control daemon,
+b10-resolver forwarding DNS server, b10-cmdctl remote control daemon,
 b10-cfgmgr configuration manager, b10-xfrin AXFR inbound service,
 b10-cfgmgr configuration manager, b10-xfrin AXFR inbound service,
 b10-xfrout outgoing AXFR service, b10-zonemgr secondary manager,
 b10-xfrout outgoing AXFR service, b10-zonemgr secondary manager,
 b10-stats statistics collection and reporting daemon, and a new
 b10-stats statistics collection and reporting daemon, and a new
@@ -193,6 +193,7 @@ config revert:	Revert all changes that have not been committed
 config commit: Commit all changes
 config commit: Commit all changes
 config diff: Show the changes that have not been committed yet
 config diff: Show the changes that have not been committed yet
 
 
+
 EXAMPLE SESSION
 EXAMPLE SESSION
 
 
 ~> bindctl
 ~> bindctl

+ 23 - 5
configure.ac

@@ -9,7 +9,23 @@ AC_CONFIG_HEADERS([config.h])
 
 
 # Checks for programs.
 # Checks for programs.
 AC_PROG_CXX
 AC_PROG_CXX
+
+# Libtool configuration
+#
+# On FreeBSD (and probably some others), clang++ does not meet an autoconf
+# assumption in identifying libtool configuration regarding shared library:
+# the configure script will execute "$CC -shared $CFLAGS -v -o" and expect
+# the output contains -Lxxx or -Ryyy.  This is the case for g++, but not for
+# clang++, and, as a result, it will cause various errors in linking programs
+# or running them with a shared object (such as some of our python scripts).
+# To work around this problem we define a temporary variable
+# "CXX_LIBTOOL_LDFLAGS".  It's expected to be defined as, e.g, "-L/usr/lib"
+# to temporarily fake the output so that it will be compatible with that of
+# g++.
+CFLAGS_SAVED=$CFLAGS
+CFLAGS="$CFLAGS $CXX_LIBTOOL_LDFLAGS"
 AC_PROG_LIBTOOL
 AC_PROG_LIBTOOL
+CFLAGS=$CFLAGS_SAVED
 
 
 # Use C++ language
 # Use C++ language
 AC_LANG([C++])
 AC_LANG([C++])
@@ -577,8 +593,8 @@ AC_CONFIG_FILES([Makefile
                  src/bin/auth/Makefile
                  src/bin/auth/Makefile
                  src/bin/auth/tests/Makefile
                  src/bin/auth/tests/Makefile
                  src/bin/auth/benchmarks/Makefile
                  src/bin/auth/benchmarks/Makefile
-                 src/bin/recurse/Makefile
+                 src/bin/resolver/Makefile
-                 src/bin/recurse/tests/Makefile
+                 src/bin/resolver/tests/Makefile
                  src/bin/xfrin/Makefile
                  src/bin/xfrin/Makefile
                  src/bin/xfrin/tests/Makefile
                  src/bin/xfrin/tests/Makefile
                  src/bin/xfrout/Makefile
                  src/bin/xfrout/Makefile
@@ -597,6 +613,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/Makefile
                  src/lib/Makefile
                  src/lib/asiolink/Makefile
                  src/lib/asiolink/Makefile
                  src/lib/asiolink/tests/Makefile
                  src/lib/asiolink/tests/Makefile
+                 src/lib/asiolink/internal/Makefile
+                 src/lib/asiolink/internal/tests/Makefile
                  src/lib/bench/Makefile
                  src/lib/bench/Makefile
                  src/lib/bench/example/Makefile
                  src/lib/bench/example/Makefile
                  src/lib/bench/tests/Makefile
                  src/lib/bench/tests/Makefile
@@ -650,8 +668,8 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            src/bin/xfrout/xfrout.spec.pre
            src/bin/xfrout/xfrout.spec.pre
            src/bin/xfrout/tests/xfrout_test
            src/bin/xfrout/tests/xfrout_test
            src/bin/xfrout/run_b10-xfrout.sh
            src/bin/xfrout/run_b10-xfrout.sh
-           src/bin/recurse/recurse.spec.pre
+           src/bin/resolver/resolver.spec.pre
-           src/bin/recurse/spec_config.h.pre
+           src/bin/resolver/spec_config.h.pre
            src/bin/zonemgr/zonemgr.py
            src/bin/zonemgr/zonemgr.py
            src/bin/zonemgr/zonemgr.spec.pre
            src/bin/zonemgr/zonemgr.spec.pre
            src/bin/zonemgr/tests/zonemgr_test
            src/bin/zonemgr/tests/zonemgr_test
@@ -694,7 +712,7 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
            chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
            chmod +x src/bin/xfrin/run_b10-xfrin.sh
            chmod +x src/bin/xfrin/run_b10-xfrin.sh
            chmod +x src/bin/xfrout/run_b10-xfrout.sh
            chmod +x src/bin/xfrout/run_b10-xfrout.sh
-           chmod +x src/bin/recurse/run_b10-recurse.sh
+           chmod +x src/bin/resolver/run_b10-resolver.sh
            chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
            chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
            chmod +x src/bin/stats/tests/stats_test
            chmod +x src/bin/stats/tests/stats_test
            chmod +x src/bin/stats/run_b10-stats.sh
            chmod +x src/bin/stats/run_b10-stats.sh

+ 1 - 1
src/bin/Makefile.am

@@ -1,4 +1,4 @@
 SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout \
 SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout \
-	usermgr zonemgr stats tests recurse
+	usermgr zonemgr stats tests resolver
 
 
 check-recursive: all-recursive
 check-recursive: all-recursive

+ 1 - 1
src/bin/auth/auth_srv.h

@@ -194,7 +194,7 @@ public:
     /// control commands and configuration updates.
     /// control commands and configuration updates.
     void setConfigSession(isc::config::ModuleCCSession* config_session);
     void setConfigSession(isc::config::ModuleCCSession* config_session);
 
 
-    /// \brief Assign an ASIO IO Service queue to this Recursor object
+    /// \brief Assign an ASIO IO Service queue to this Resolver object
     void setIOService(asiolink::IOService& ios) { io_service_ = &ios; }
     void setIOService(asiolink::IOService& ios) { io_service_ = &ios; }
 
 
     /// \brief Return this object's ASIO IO Service queue
     /// \brief Return this object's ASIO IO Service queue

+ 93 - 3
src/bin/auth/query.cc

@@ -12,8 +12,12 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
+#include <vector>
+#include <boost/foreach.hpp>
+
 #include <dns/message.h>
 #include <dns/message.h>
 #include <dns/rcode.h>
 #include <dns/rcode.h>
+#include <dns/rdataclass.h>
 
 
 #include <datasrc/memory_datasrc.h>
 #include <datasrc/memory_datasrc.h>
 
 
@@ -21,11 +25,66 @@
 
 
 using namespace isc::dns;
 using namespace isc::dns;
 using namespace isc::datasrc;
 using namespace isc::datasrc;
+using namespace isc::dns::rdata;
 
 
 namespace isc {
 namespace isc {
 namespace auth {
 namespace auth {
 
 
 void
 void
+Query::getAdditional(const Zone& zone, const RRset& rrset) const {
+    RdataIteratorPtr rdata_iterator(rrset.getRdataIterator());
+    for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
+        const Rdata& rdata(rdata_iterator->getCurrent());
+        if (rrset.getType() == RRType::NS()) {
+            // Need to perform the search in the "GLUE OK" mode.
+            const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
+            findAddrs(zone, ns.getNSName(), Zone::FIND_GLUE_OK);
+        } else if (rrset.getType() == RRType::MX()) {
+            const generic::MX& mx(dynamic_cast<const generic::MX&>(rdata));
+            findAddrs(zone, mx.getMXName());
+        }
+    }
+}
+
+void
+Query::findAddrs(const Zone& zone, const Name& qname,
+                 const Zone::FindOptions options) const
+{
+    // Out of zone name
+    NameComparisonResult result = zone.getOrigin().compare(qname);
+    if ((result.getRelation() != NameComparisonResult::SUPERDOMAIN) &&
+        (result.getRelation() != NameComparisonResult::EQUAL))
+        return;
+
+    // Omit additional data which has already been provided in the answer
+    // section from the additional.
+    //
+    // All the address rrset with the owner name of qname have been inserted
+    // into ANSWER section.
+    if (qname_ == qname && qtype_ == RRType::ANY())
+        return;
+
+    // Find A rrset
+    if (qname_ != qname || qtype_ != RRType::A()) {
+        Zone::FindResult a_result = zone.find(qname, RRType::A(), options);
+        if (a_result.code == Zone::SUCCESS) {
+            response_.addRRset(Message::SECTION_ADDITIONAL,
+                    boost::const_pointer_cast<RRset>(a_result.rrset));
+        }
+    }
+
+    // Find AAAA rrset
+    if (qname_ != qname || qtype_ != RRType::AAAA()) {
+        Zone::FindResult aaaa_result =
+            zone.find(qname, RRType::AAAA(), options);
+        if (aaaa_result.code == Zone::SUCCESS) {
+            response_.addRRset(Message::SECTION_ADDITIONAL,
+                    boost::const_pointer_cast<RRset>(aaaa_result.rrset));
+        }
+    }
+}
+
+void
 Query::putSOA(const Zone& zone) const {
 Query::putSOA(const Zone& zone) const {
     Zone::FindResult soa_result(zone.find(zone.getOrigin(),
     Zone::FindResult soa_result(zone.find(zone.getOrigin(),
         RRType::SOA()));
         RRType::SOA()));
@@ -44,6 +103,22 @@ Query::putSOA(const Zone& zone) const {
 }
 }
 
 
 void
 void
+Query::getAuthAdditional(const Zone& zone) const {
+    // Fill in authority and addtional sections.
+    Zone::FindResult ns_result = zone.find(zone.getOrigin(), RRType::NS());
+    // zone origin name should have NS records
+    if (ns_result.code != Zone::SUCCESS) {
+        isc_throw(NoApexNS, "There's no apex NS records in zone " <<
+                zone.getOrigin().toText());
+    } else {
+        response_.addRRset(Message::SECTION_AUTHORITY,
+            boost::const_pointer_cast<RRset>(ns_result.rrset));
+        // Handle additional for authority section
+        getAdditional(zone, *ns_result.rrset);
+    }
+}
+
+void
 Query::process() const {
 Query::process() const {
     bool keep_doing = true;
     bool keep_doing = true;
     response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
     response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
@@ -70,11 +145,25 @@ Query::process() const {
             case Zone::SUCCESS:
             case Zone::SUCCESS:
                 response_.setRcode(Rcode::NOERROR());
                 response_.setRcode(Rcode::NOERROR());
                 response_.addRRset(Message::SECTION_ANSWER,
                 response_.addRRset(Message::SECTION_ANSWER,
-                            boost::const_pointer_cast<RRset>(db_result.rrset));
+                    boost::const_pointer_cast<RRset>(db_result.rrset));
-                // TODO : fill in authority and addtional sections.
+                // 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()))
+                {
+                    getAuthAdditional(*result.zone);
+                }
                 break;
                 break;
             case Zone::DELEGATION:
             case Zone::DELEGATION:
-                // TODO : add NS to authority section, fill in additional section.
+                response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
+                response_.setRcode(Rcode::NOERROR());
+                response_.addRRset(Message::SECTION_AUTHORITY,
+                    boost::const_pointer_cast<RRset>(db_result.rrset));
+                getAdditional(*result.zone, *db_result.rrset);
                 break;
                 break;
             case Zone::NXDOMAIN:
             case Zone::NXDOMAIN:
                 // Just empty answer with SOA in authority section
                 // Just empty answer with SOA in authority section
@@ -93,5 +182,6 @@ Query::process() const {
         }
         }
     }
     }
 }
 }
+
 }
 }
 }
 }

+ 78 - 9
src/bin/auth/query.h

@@ -15,17 +15,18 @@
  */
  */
 
 
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
+#include <datasrc/zone.h>
 
 
 namespace isc {
 namespace isc {
 namespace dns {
 namespace dns {
 class Message;
 class Message;
 class Name;
 class Name;
 class RRType;
 class RRType;
+class RRset;
 }
 }
 
 
 namespace datasrc {
 namespace datasrc {
 class MemoryDataSrc;
 class MemoryDataSrc;
-class Zone;
 }
 }
 
 
 namespace auth {
 namespace auth {
@@ -63,6 +64,72 @@ namespace auth {
 /// accidentally, and since it's considered a temporary development state,
 /// accidentally, and since it's considered a temporary development state,
 /// we keep this name at the moment.
 /// we keep this name at the moment.
 class Query {
 class Query {
+private:
+
+    /// \brief Adds a SOA.
+    ///
+    /// Adds a SOA of the zone into the authority zone of response_.
+    /// Can throw NoSOA.
+    ///
+    void putSOA(const isc::datasrc::Zone& zone) const;
+
+    /// \brief Look up additional data (i.e., address records for the names
+    /// included in NS or MX records).
+    ///
+    /// Note: Any additional data which has already been provided in the
+    /// answer section (i.e., if the original query happend to be for the
+    /// address of the DNS server), it should be omitted from the additional.
+    ///
+    /// This method may throw a exception because its underlying methods may
+    /// throw exceptions.
+    ///
+    /// \param zone The Zone wherein the additional data to the query is bo be
+    /// found.
+    /// \param rrset The RRset (i.e., NS or MX rrset) which require additional
+    /// processing.
+    void getAdditional(const isc::datasrc::Zone& zone,
+                       const isc::dns::RRset& rrset) const;
+
+    /// \brief Find address records for a specified name.
+    ///
+    /// Search the specified zone for AAAA/A RRs of each of the NS/MX RDATA
+    /// (domain name), and insert the found ones into the additional section
+    /// if address records are available. By default the search will stop
+    /// once it encounters a zone cut.
+    ///
+    /// Note: we need to perform the search in the "GLUE OK" mode for NS RDATA,
+    /// which means that we should include A/AAAA RRs under a zone cut.
+    /// The glue records must exactly match the name in the NS RDATA, without
+    /// CNAME or wildcard processing.
+    ///
+    /// \param zone The \c Zone wherein the address records is to be found.
+    /// \param qname The name in rrset RDATA.
+    /// \param options The search options.
+    void findAddrs(const isc::datasrc::Zone& zone,
+                   const isc::dns::Name& qname,
+                   const isc::datasrc::Zone::FindOptions options
+                   = isc::datasrc::Zone::FIND_DEFAULT) const;
+
+    /// \brief Look up \c Zone's NS and address records for the NS RDATA
+    /// (domain name) for authoritative answer.
+    ///
+    /// On returning an authoritative answer, insert the \c Zone's NS into the
+    /// authority section and AAAA/A RRs of each of the NS RDATA into the
+    /// additional section.
+    ///
+    /// <b>Notes to developer:</b>
+    ///
+    /// We should omit address records which has already been provided in the
+    /// answer section from the additional.
+    ///
+    /// For now, in order to optimize the additional section processing, we
+    /// include AAAA/A RRs under a zone cut in additional section. (BIND 9
+    /// excludes under-cut RRs; NSD include them.)
+    ///
+    /// \param zone The \c Zone wherein the additional data to the query is to
+    /// be found.
+    void getAuthAdditional(const isc::datasrc::Zone& zone) const;
+
 public:
 public:
     /// Constructor from query parameters.
     /// Constructor from query parameters.
     ///
     ///
@@ -130,19 +197,21 @@ public:
         {}
         {}
     };
     };
 
 
+    /// \short Zone is missing its apex NS records.
+    ///
+    /// We tried to add apex NS records into the authority section, but the
+    /// zone does not contain any.
+    struct NoApexNS: public BadZone {
+        NoApexNS(const char* file, size_t line, const char* what) :
+            BadZone(file, line, what)
+        {}
+    };
+
 private:
 private:
     const isc::datasrc::MemoryDataSrc& memory_datasrc_;
     const isc::datasrc::MemoryDataSrc& memory_datasrc_;
     const isc::dns::Name& qname_;
     const isc::dns::Name& qname_;
     const isc::dns::RRType& qtype_;
     const isc::dns::RRType& qtype_;
     isc::dns::Message& response_;
     isc::dns::Message& response_;
-
-    /**
-     * \short Adds a SOA.
-     *
-     * Adds a SOA of the zone into the authority zone of response_.
-     * Can throw NoSOA.
-     */
-    void putSOA(const isc::datasrc::Zone& zone) const;
 };
 };
 
 
 }
 }

+ 1 - 0
src/bin/auth/tests/Makefile.am

@@ -36,6 +36,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
 run_unittests_LDADD += $(SQLITE_LIBS)
+run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la

+ 21 - 10
src/bin/auth/tests/auth_srv_unittest.cc

@@ -33,14 +33,17 @@
 #include <auth/common.h>
 #include <auth/common.h>
 #include <auth/statistics.h>
 #include <auth/statistics.h>
 
 
-#include <testutils/srv_unittest.h>
+#include <dns/tests/unittest_util.h>
+#include <testutils/srv_test.h>
 
 
+using namespace std;
 using namespace isc::cc;
 using namespace isc::cc;
 using namespace isc::dns;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 using namespace isc::dns::rdata;
 using namespace isc::data;
 using namespace isc::data;
 using namespace isc::xfr;
 using namespace isc::xfr;
 using namespace asiolink;
 using namespace asiolink;
+using namespace isc::testutils;
 using isc::UnitTestUtil;
 using isc::UnitTestUtil;
 
 
 namespace {
 namespace {
@@ -57,6 +60,10 @@ protected:
         server.setXfrinSession(&notify_session);
         server.setXfrinSession(&notify_session);
         server.setStatisticsSession(&statistics_session);
         server.setStatisticsSession(&statistics_session);
     }
     }
+    virtual void processMessage() {
+        server.processMessage(*io_message, parse_message, response_obuffer,
+                              &dnsserv);
+    }
     MockSession statistics_session;
     MockSession statistics_session;
     MockXfroutClient xfrout;
     MockXfroutClient xfrout;
     AuthSrv server;
     AuthSrv server;
@@ -161,48 +168,52 @@ TEST_F(AuthSrvTest, iqueryViaDNSServer) {
 
 
 // Unsupported requests.  Should result in NOTIMP.
 // Unsupported requests.  Should result in NOTIMP.
 TEST_F(AuthSrvTest, unsupportedRequest) {
 TEST_F(AuthSrvTest, unsupportedRequest) {
-    UNSUPPORTED_REQUEST_TEST;
+    unsupportedRequest();
 }
 }
 
 
 // Simple API check
 // Simple API check
 TEST_F(AuthSrvTest, verbose) {
 TEST_F(AuthSrvTest, verbose) {
-    VERBOSE_TEST;
+    EXPECT_FALSE(server.getVerbose());
+    server.setVerbose(true);
+    EXPECT_TRUE(server.getVerbose());
+    server.setVerbose(false);
+    EXPECT_FALSE(server.getVerbose());
 }
 }
 
 
 // Multiple questions.  Should result in FORMERR.
 // Multiple questions.  Should result in FORMERR.
 TEST_F(AuthSrvTest, multiQuestion) {
 TEST_F(AuthSrvTest, multiQuestion) {
-    MULTI_QUESTION_TEST;
+    multiQuestion();
 }
 }
 
 
 // Incoming data doesn't even contain the complete header.  Must be silently
 // Incoming data doesn't even contain the complete header.  Must be silently
 // dropped.
 // dropped.
 TEST_F(AuthSrvTest, shortMessage) {
 TEST_F(AuthSrvTest, shortMessage) {
-    SHORT_MESSAGE_TEST;
+    shortMessage();
 }
 }
 
 
 // Response messages.  Must be silently dropped, whether it's a valid response
 // Response messages.  Must be silently dropped, whether it's a valid response
 // or malformed or could otherwise cause a protocol error.
 // or malformed or could otherwise cause a protocol error.
 TEST_F(AuthSrvTest, response) {
 TEST_F(AuthSrvTest, response) {
-    RESPONSE_TEST;
+    response();
 }
 }
 
 
 // Query with a broken question
 // Query with a broken question
 TEST_F(AuthSrvTest, shortQuestion) {
 TEST_F(AuthSrvTest, shortQuestion) {
-    SHORT_QUESTION_TEST;
+    shortQuestion();
 }
 }
 
 
 // Query with a broken answer section
 // Query with a broken answer section
 TEST_F(AuthSrvTest, shortAnswer) {
 TEST_F(AuthSrvTest, shortAnswer) {
-    SHORT_ANSWER_TEST;
+    shortAnswer();
 }
 }
 
 
 // Query with unsupported version of EDNS.
 // Query with unsupported version of EDNS.
 TEST_F(AuthSrvTest, ednsBadVers) {
 TEST_F(AuthSrvTest, ednsBadVers) {
-    EDNS_BADVERS_TEST;
+    ednsBadVers();
 }
 }
 
 
 TEST_F(AuthSrvTest, AXFROverUDP) {
 TEST_F(AuthSrvTest, AXFROverUDP) {
-    AXFR_OVER_UDP_TEST;
+    axfrOverUDP();
 }
 }
 
 
 TEST_F(AuthSrvTest, AXFRSuccess) {
 TEST_F(AuthSrvTest, AXFRSuccess) {

+ 331 - 22
src/bin/auth/tests/query_unittest.cc

@@ -17,6 +17,7 @@
 #include <dns/rcode.h>
 #include <dns/rcode.h>
 #include <dns/rrttl.h>
 #include <dns/rrttl.h>
 #include <dns/rrtype.h>
 #include <dns/rrtype.h>
+#include <dns/rdataclass.h>
 
 
 #include <datasrc/memory_datasrc.h>
 #include <datasrc/memory_datasrc.h>
 
 
@@ -36,19 +37,70 @@ RRsetPtr a_rrset = RRsetPtr(new RRset(Name("www.example.com"),
 RRsetPtr soa_rrset = RRsetPtr(new RRset(Name("example.com"),
 RRsetPtr soa_rrset = RRsetPtr(new RRset(Name("example.com"),
                                         RRClass::IN(), RRType::SOA(),
                                         RRClass::IN(), RRType::SOA(),
                                         RRTTL(3600)));
                                         RRTTL(3600)));
+RRsetPtr ns_rrset(RRsetPtr(new RRset(Name("ns.example.com"),
+                                     RRClass::IN(), RRType::NS(),
+                                     RRTTL(3600))));
+RRsetPtr glue_a_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
+                                         RRClass::IN(), RRType::A(),
+                                         RRTTL(3600))));
+RRsetPtr glue_aaaa_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
+                                            RRClass::IN(), RRType::AAAA(),
+                                            RRTTL(3600))));
+RRsetPtr noglue_a_rrset(RRsetPtr(new RRset(Name("noglue.example.com"),
+                                           RRClass::IN(), RRType::A(),
+                                           RRTTL(3600))));
+RRsetPtr delegated_mx_a_rrset(RRsetPtr(new RRset(
+    Name("mx.delegation.example.com"), RRClass::IN(), RRType::A(),
+    RRTTL(3600))));
+
 // This is a mock Zone class for testing.
 // This is a mock Zone class for testing.
-// It is a derived class of Zone, and simply hardcode the results of find()
+// It is a derived class of Zone, and simply hardcodes the results of find()
-// return SUCCESS for "www.example.com",
+// See the find() implementation if you want to know its content.
-// return NXDOMAIN for "nxdomain.example.com",
-// return NXRRSET for "nxrrset.example.com",
-// return CNAME for "cname.example.com",
-// else return DNAME
 class MockZone : public Zone {
 class MockZone : public Zone {
 public:
 public:
-    MockZone(bool has_SOA = true) :
+    MockZone(bool has_SOA = true, bool has_apex_NS = true) :
         origin_(Name("example.com")),
         origin_(Name("example.com")),
-        has_SOA_(has_SOA)
+        has_SOA_(has_SOA),
-    {}
+        has_apex_NS_(has_apex_NS),
+        delegation_rrset(RRsetPtr(new RRset(Name("delegation.example.com"),
+                                            RRClass::IN(), RRType::NS(),
+                                            RRTTL(3600)))),
+        cname_rrset(RRsetPtr(new RRset(Name("cname.example.com"),
+                                       RRClass::IN(), RRType::CNAME(),
+                                       RRTTL(3600)))),
+        auth_ns_rrset(RRsetPtr(new RRset(Name("example.com"),
+                                         RRClass::IN(), RRType::NS(),
+                                         RRTTL(3600)))),
+        mx_cname_rrset_(new RRset(Name("cnamemailer.example.com"),
+            RRClass::IN(), RRType::CNAME(), RRTTL(3600))),
+        mx_rrset_(new RRset(Name("mx.example.com"), RRClass::IN(),
+            RRType::MX(), RRTTL(3600)))
+    {
+        delegation_rrset->addRdata(rdata::generic::NS(
+                          Name("glue.ns.example.com")));
+        delegation_rrset->addRdata(rdata::generic::NS(
+                          Name("noglue.example.com")));
+        delegation_rrset->addRdata(rdata::generic::NS(
+                          Name("cname.example.com")));
+        delegation_rrset->addRdata(rdata::generic::NS(
+                          Name("example.org")));
+        cname_rrset->addRdata(rdata::generic::CNAME(
+                          Name("www.example.com")));
+        auth_ns_rrset->addRdata(rdata::generic::NS(
+                          Name("glue.ns.example.com")));
+        auth_ns_rrset->addRdata(rdata::generic::NS(
+                          Name("noglue.example.com")));
+        auth_ns_rrset->addRdata(rdata::generic::NS(
+                          Name("example.net")));
+        mx_rrset_->addRdata(isc::dns::rdata::generic::MX(10,
+            Name("www.example.com")));
+        mx_rrset_->addRdata(isc::dns::rdata::generic::MX(20,
+            Name("mailer.example.org")));
+        mx_rrset_->addRdata(isc::dns::rdata::generic::MX(30,
+            Name("mx.delegation.example.com")));
+        mx_cname_rrset_->addRdata(rdata::generic::CNAME(
+            Name("mx.example.com")));
+    }
     virtual const isc::dns::Name& getOrigin() const;
     virtual const isc::dns::Name& getOrigin() const;
     virtual const isc::dns::RRClass& getClass() const;
     virtual const isc::dns::RRClass& getClass() const;
 
 
@@ -59,6 +111,12 @@ public:
 private:
 private:
     Name origin_;
     Name origin_;
     bool has_SOA_;
     bool has_SOA_;
+    bool has_apex_NS_;
+    RRsetPtr delegation_rrset;
+    RRsetPtr cname_rrset;
+    RRsetPtr auth_ns_rrset;
+    RRsetPtr mx_cname_rrset_;
+    RRsetPtr mx_rrset_;
 };
 };
 
 
 const Name&
 const Name&
@@ -72,22 +130,52 @@ MockZone::getClass() const {
 }
 }
 
 
 Zone::FindResult
 Zone::FindResult
-MockZone::find(const Name& name, const RRType& type, const FindOptions) const {
+MockZone::find(const Name& name, const RRType& type,
+               const FindOptions options) const
+{
     // hardcode the find results
     // hardcode the find results
-    if (name == Name("www.example.com")) {
+    if (name == Name("www.example.com") && type == RRType::A()) {
         return (FindResult(SUCCESS, a_rrset));
         return (FindResult(SUCCESS, a_rrset));
+    } else if (name == Name("www.example.com")) {
+        return (FindResult(NXRRSET, RRsetPtr()));
+    } else if (name == Name("glue.ns.example.com") && type == RRType::A() &&
+        (options & FIND_GLUE_OK) != 0) {
+        return (FindResult(SUCCESS, glue_a_rrset));
+    } else if (name == Name("noglue.example.com") && (type == RRType::A() ||
+        type == RRType::ANY())) {
+        return (FindResult(SUCCESS, noglue_a_rrset));
+    } else if (name == Name("glue.ns.example.com") && type == RRType::AAAA() &&
+        (options & FIND_GLUE_OK) != 0) {
+        return (FindResult(SUCCESS, glue_aaaa_rrset));
     } else if (name == Name("example.com") && type == RRType::SOA() &&
     } else if (name == Name("example.com") && type == RRType::SOA() &&
         has_SOA_)
         has_SOA_)
     {
     {
         return (FindResult(SUCCESS, soa_rrset));
         return (FindResult(SUCCESS, soa_rrset));
-    } else if (name == Name("delegation.example.com")) {
+    } else if (name == Name("example.com") && type == RRType::NS() &&
-        return (FindResult(DELEGATION, RRsetPtr()));
+        has_apex_NS_)
+    {
+        return (FindResult(SUCCESS, auth_ns_rrset));
+    } else if (name == Name("mx.delegation.example.com") &&
+        type == RRType::A() && (options & FIND_GLUE_OK) != 0)
+    {
+        return (FindResult(SUCCESS, delegated_mx_a_rrset));
+    } else if (name == Name("delegation.example.com") ||
+        name.compare(Name("delegation.example.com")).getRelation() ==
+        NameComparisonResult::SUBDOMAIN)
+    {
+        return (FindResult(DELEGATION, delegation_rrset));
+    } else if (name == Name("ns.example.com")) {
+        return (FindResult(DELEGATION, ns_rrset));
     } else if (name == Name("nxdomain.example.com")) {
     } else if (name == Name("nxdomain.example.com")) {
         return (FindResult(NXDOMAIN, RRsetPtr()));
         return (FindResult(NXDOMAIN, RRsetPtr()));
     } else if (name == Name("nxrrset.example.com")) {
     } else if (name == Name("nxrrset.example.com")) {
         return (FindResult(NXRRSET, RRsetPtr()));
         return (FindResult(NXRRSET, RRsetPtr()));
-    } else if (name == Name("cname.example.com")) {
+    } else if ((name == Name("cname.example.com"))) {
-        return (FindResult(CNAME, RRsetPtr()));
+        return (FindResult(CNAME, cname_rrset));
+    } else if (name == Name("cnamemailer.example.com")) {
+        return (FindResult(CNAME, mx_cname_rrset_));
+    } else if (name == Name("mx.example.com")) {
+        return (FindResult(SUCCESS, mx_rrset_));
     } else {
     } else {
         return (FindResult(DNAME, RRsetPtr()));
         return (FindResult(DNAME, RRsetPtr()));
     }
     }
@@ -113,33 +201,175 @@ protected:
 TEST_F(QueryTest, noZone) {
 TEST_F(QueryTest, noZone) {
     // There's no zone in the memory datasource.  So the response should have
     // There's no zone in the memory datasource.  So the response should have
     // REFUSED.
     // REFUSED.
-    query.process();
+    EXPECT_NO_THROW(query.process());
     EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
     EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
 }
 }
 
 
-TEST_F(QueryTest, matchZone) {
+TEST_F(QueryTest, exactMatch) {
     // add a matching zone.
     // add a matching zone.
     memory_datasrc.addZone(ZonePtr(new MockZone()));
     memory_datasrc.addZone(ZonePtr(new MockZone()));
-    query.process();
+    EXPECT_NO_THROW(query.process());
+    // find match rrset
+    EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
     EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
     EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
     EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
     EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
                                   Name("www.example.com"), RRClass::IN(),
                                   Name("www.example.com"), RRClass::IN(),
                                   RRType::A()));
                                   RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
+                                  Name("example.com"), RRClass::IN(),
+                                  RRType::NS()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::AAAA()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("noglue.example.com"),
+                                  RRClass::IN(), RRType::A()));
+}
+
+TEST_F(QueryTest, exactAddrMatch) {
+    // find match rrset, omit additional data which has already been provided
+    // in the answer section from the additional.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    const Name noglue_name(Name("noglue.example.com"));
+    Query noglue_query(memory_datasrc, noglue_name, qtype, response);
+    EXPECT_NO_THROW(noglue_query.process());
+    EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
+                                  Name("noglue.example.com"), RRClass::IN(),
+                                  RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
+                                  Name("example.com"), RRClass::IN(),
+                                  RRType::NS()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::AAAA()));
+    EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("noglue.example.com"),
+                                  RRClass::IN(), RRType::A()));
+}
+
+TEST_F(QueryTest, apexNSMatch) {
+    // find match rrset, omit authority data which has already been provided
+    // in the answer section from the authority section.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    const Name apex_name(Name("example.com"));
+    Query apex_ns_query(memory_datasrc, apex_name, RRType::NS(), response);
+    EXPECT_NO_THROW(apex_ns_query.process());
+    EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
+                                  Name("example.com"), RRClass::IN(),
+                                  RRType::NS()));
+    EXPECT_FALSE(response.hasRRset(Message::SECTION_AUTHORITY,
+                                  Name("example.com"), RRClass::IN(),
+                                  RRType::NS()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::AAAA()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("noglue.example.com"),
+                                  RRClass::IN(), RRType::A()));
+}
+
+TEST_F(QueryTest, exactAnyMatch) {
+    // find match rrset, omit additional data which has already been provided
+    // in the answer section from the additional.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    const Name noglue_name(Name("noglue.example.com"));
+    Query noglue_query(memory_datasrc, noglue_name, RRType::ANY(), response);
+    EXPECT_NO_THROW(noglue_query.process());
+    EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
+                                  Name("noglue.example.com"), RRClass::IN(),
+                                  RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
+                                  Name("example.com"), RRClass::IN(),
+                                  RRType::NS()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::AAAA()));
+    EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("noglue.example.com"),
+                                  RRClass::IN(), RRType::A()));
+}
+
+// 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.
+TEST_F(QueryTest, noApexNS) {
+    // Add a zone without apex NS records
+    memory_datasrc.addZone(ZonePtr(new MockZone(true, false)));
+    const Name noglue_name(Name("noglue.example.com"));
+    Query noglue_query(memory_datasrc, noglue_name, qtype, response);
+    EXPECT_THROW(noglue_query.process(), Query::NoApexNS);
+    // We don't look into the response, as it throwed
+}
 
 
-    // NXDOMAIN
+TEST_F(QueryTest, delegation) {
+    // add a matching zone.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    const Name delegation_name(Name("delegation.example.com"));
+    Query delegation_query(memory_datasrc, delegation_name, qtype, response);
+    EXPECT_NO_THROW(delegation_query.process());
+    EXPECT_FALSE(response.getHeaderFlag(Message::HEADERFLAG_AA));
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
+                                  Name("delegation.example.com"),
+                                  RRClass::IN(), RRType::NS()));
+    // glue address records
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("glue.ns.example.com"),
+                                  RRClass::IN(), RRType::AAAA()));
+    // noglue address records
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("noglue.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    // NS name has a CNAME
+    EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("www.example.com"),
+                                  RRClass::IN(), RRType::A()));
+    // NS name is out of zone
+    EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
+                                  Name("example.org"),
+                                  RRClass::IN(), RRType::A()));
+}
+
+TEST_F(QueryTest, nxdomain) {
+    // add a matching zone.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
     const Name nxdomain_name(Name("nxdomain.example.com"));
     const Name nxdomain_name(Name("nxdomain.example.com"));
     Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
     Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
-    nxdomain_query.process();
+    EXPECT_NO_THROW(nxdomain_query.process());
     EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
     EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
     EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
     EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
         Name("example.com"), RRClass::IN(), RRType::SOA()));
         Name("example.com"), RRClass::IN(), RRType::SOA()));
+}
 
 
-    // NXRRSET
+TEST_F(QueryTest, nxrrset) {
+    // add a matching zone.
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
     const Name nxrrset_name(Name("nxrrset.example.com"));
     const Name nxrrset_name(Name("nxrrset.example.com"));
     Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
     Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
-    nxrrset_query.process();
+    EXPECT_NO_THROW(nxrrset_query.process());
     EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
     EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
     EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
@@ -176,4 +406,83 @@ TEST_F(QueryTest, noMatchZone) {
     EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
     EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
 }
 }
 
 
+/*
+ * Test MX additional processing.
+ *
+ * The MX RRset has two RRs, one pointing to a known domain with
+ * A record, other to unknown out of zone one.
+ */
+TEST_F(QueryTest, MX) {
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    Name qname("mx.example.com");
+    Query mx_query(memory_datasrc, qname, RRType::MX(), response);
+    EXPECT_NO_THROW(mx_query.process());
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
+        Name("mx.example.com"), RRClass::IN(), RRType::MX()));
+    EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
+        Name("www.example.com"), RRClass::IN(), RRType::A()));
+    // We want to skip the additional ones related to authoritative
+    RRsetPtr ns;
+    for (SectionIterator<RRsetPtr> ai(response.beginSection(
+        Message::SECTION_AUTHORITY)); ai != response.endSection(
+        Message::SECTION_AUTHORITY); ++ai)
+    {
+        if ((*ai)->getName() == Name("example.com") && (*ai)->getType() ==
+            RRType::NS())
+        {
+            ns = *ai;
+            break;
+        }
+    }
+    /*
+     * In fact, the MX RRset mentions three names, but we don't know anything
+     * about one of them and one is under a zone cut, so we should have just
+     * one RRset (A for www.example.com)
+     */
+    // We can't use getRRCount, as it counts RRs, not RRsets
+    unsigned additional_count(0);
+    for (SectionIterator<RRsetPtr> ai(response.beginSection(
+        Message::SECTION_ADDITIONAL)); ai != response.endSection(
+        Message::SECTION_ADDITIONAL); ++ai)
+    {
+        // Skip the ones for the NS record
+        if (ns) {
+            for (RdataIteratorPtr nsi(ns->getRdataIterator()); !nsi->isLast();
+                nsi->next())
+            {
+                if ((*ai)->getName() ==
+                    dynamic_cast<const isc::dns::rdata::generic::NS&>(
+                    nsi->getCurrent()).getNSName())
+                {
+                    goto NS_ADDITIONAL_DATA;
+                }
+            }
+        }
+        // It is not related to the NS, then it must be related to the MX
+        ++additional_count;
+        EXPECT_EQ(Name("www.example.com"), (*ai)->getName());
+        EXPECT_EQ(RRType::A(), (*ai)->getType());
+        NS_ADDITIONAL_DATA:;
+    }
+    EXPECT_EQ(1, additional_count);
+}
+
+/*
+ * Test when we ask for MX and encounter an alias (CNAME in this case).
+ *
+ * This should not trigger the additional processing.
+ */
+TEST_F(QueryTest, MXAlias) {
+    memory_datasrc.addZone(ZonePtr(new MockZone()));
+    Name qname("cnamemailer.example.com");
+    Query mx_query(memory_datasrc, qname, RRType::MX(), response);
+    EXPECT_NO_THROW(mx_query.process());
+    EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
+    // We should not have the IP address in additional section
+    // Currently, the section should be completely empty
+    EXPECT_TRUE(response.beginSection(Message::SECTION_ADDITIONAL) ==
+        response.endSection(Message::SECTION_ADDITIONAL));
+}
+
 }
 }

+ 17 - 17
src/bin/bind10/bind10.py.in

@@ -208,13 +208,13 @@ class BoB:
         self.dns_port = dns_port
         self.dns_port = dns_port
         self.forward = forward
         self.forward = forward
         if forward:
         if forward:
-            self.recursive = True
+            self.resolver = True
         else:
         else:
-            self.recursive = False
+            self.resolver = False
         self.cc_session = None
         self.cc_session = None
         self.ccs = None
         self.ccs = None
         self.cfg_start_auth = True
         self.cfg_start_auth = True
-        self.cfg_start_recurse = False
+        self.cfg_start_resolver = False
         self.curproc = None
         self.curproc = None
         self.dead_processes = {}
         self.dead_processes = {}
         self.msgq_socket_file = msgq_socket_file
         self.msgq_socket_file = msgq_socket_file
@@ -278,13 +278,13 @@ class BoB:
 
 
         config_data = self.ccs.get_full_config()
         config_data = self.ccs.get_full_config()
         self.cfg_start_auth = config_data.get("start_auth")
         self.cfg_start_auth = config_data.get("start_auth")
-        self.cfg_start_recurse = config_data.get("start_recurse")
+        self.cfg_start_resolver = config_data.get("start_resolver")
 
 
         if self.verbose:
         if self.verbose:
             sys.stdout.write("[bind10] - start_auth: %s\n" %
             sys.stdout.write("[bind10] - start_auth: %s\n" %
                 str(self.cfg_start_auth))
                 str(self.cfg_start_auth))
-            sys.stdout.write("[bind10] - start_recurse: %s\n" %
+            sys.stdout.write("[bind10] - start_resolver: %s\n" %
-                str(self.cfg_start_recurse))
+                str(self.cfg_start_resolver))
 
 
     def log_starting(self, process, port = None, address = None):
     def log_starting(self, process, port = None, address = None):
         """
         """
@@ -423,13 +423,13 @@ class BoB:
             Start the Authoritative server
             Start the Authoritative server
         """
         """
         # XXX: this must be read from the configuration manager in the future
         # XXX: this must be read from the configuration manager in the future
-        if self.recursive:
+        if self.resolver:
-            dns_prog = 'b10-recurse'
+            dns_prog = 'b10-resolver'
         else:
         else:
             dns_prog = 'b10-auth'
             dns_prog = 'b10-auth'
         dnsargs = [dns_prog]
         dnsargs = [dns_prog]
-        if not self.recursive:
+        if not self.resolver:
-            # The recursive uses configuration manager for these
+            # The resolver uses configuration manager for these
             dnsargs += ['-p', str(self.dns_port)]
             dnsargs += ['-p', str(self.dns_port)]
             if self.address:
             if self.address:
                 dnsargs += ['-a', str(self.address)]
                 dnsargs += ['-a', str(self.address)]
@@ -444,22 +444,22 @@ class BoB:
         self.start_process("b10-auth", dnsargs, c_channel_env,
         self.start_process("b10-auth", dnsargs, c_channel_env,
             self.dns_port, self.address)
             self.dns_port, self.address)
 
 
-    def start_recurse(self, c_channel_env):
+    def start_resolver(self, c_channel_env):
         """
         """
             Start the Resolver.  At present, all these arguments and switches
             Start the Resolver.  At present, all these arguments and switches
             are pure speculation.  As with the auth daemon, they should be
             are pure speculation.  As with the auth daemon, they should be
             read from the configuration database.
             read from the configuration database.
         """
         """
-        self.curproc = "b10-recurse"
+        self.curproc = "b10-resolver"
         # XXX: this must be read from the configuration manager in the future
         # XXX: this must be read from the configuration manager in the future
-        resargs = ['b10-recurse']
+        resargs = ['b10-resolver']
         if self.uid:
         if self.uid:
             resargs += ['-u', str(self.uid)]
             resargs += ['-u', str(self.uid)]
         if self.verbose:
         if self.verbose:
             resargs += ['-v']
             resargs += ['-v']
 
 
         # ... and start
         # ... and start
-        self.start_process("b10-recurse", resargs, c_channel_env)
+        self.start_process("b10-resolver", resargs, c_channel_env)
 
 
     def start_xfrout(self, c_channel_env):
     def start_xfrout(self, c_channel_env):
         self.start_simple("b10-xfrout", c_channel_env)
         self.start_simple("b10-xfrout", c_channel_env)
@@ -496,8 +496,8 @@ class BoB:
             self.start_auth(c_channel_env)
             self.start_auth(c_channel_env)
 
 
         # ... and resolver (if selected):
         # ... and resolver (if selected):
-        if self.cfg_start_recurse:
+        if self.cfg_start_resolver:
-            self.start_recurse(c_channel_env)
+            self.start_resolver(c_channel_env)
 
 
         # Everything after the main components can run as non-root.
         # Everything after the main components can run as non-root.
         # TODO: this is only temporary - once the privileged socket creator is
         # TODO: this is only temporary - once the privileged socket creator is
@@ -557,7 +557,7 @@ class BoB:
         self.cc_session.group_sendmsg(cmd, 'Cmdctl', 'Cmdctl')
         self.cc_session.group_sendmsg(cmd, 'Cmdctl', 'Cmdctl')
         self.cc_session.group_sendmsg(cmd, "ConfigManager", "ConfigManager")
         self.cc_session.group_sendmsg(cmd, "ConfigManager", "ConfigManager")
         self.cc_session.group_sendmsg(cmd, "Auth", "Auth")
         self.cc_session.group_sendmsg(cmd, "Auth", "Auth")
-        self.cc_session.group_sendmsg(cmd, "Recurse", "Recurse")
+        self.cc_session.group_sendmsg(cmd, "Resolver", "Resolver")
         self.cc_session.group_sendmsg(cmd, "Xfrout", "Xfrout")
         self.cc_session.group_sendmsg(cmd, "Xfrout", "Xfrout")
         self.cc_session.group_sendmsg(cmd, "Xfrin", "Xfrin")
         self.cc_session.group_sendmsg(cmd, "Xfrin", "Xfrin")
         self.cc_session.group_sendmsg(cmd, "Zonemgr", "Zonemgr")
         self.cc_session.group_sendmsg(cmd, "Zonemgr", "Zonemgr")

+ 1 - 1
src/bin/bind10/bob.spec

@@ -10,7 +10,7 @@
         "item_default": true
         "item_default": true
       },
       },
       {
       {
-        "item_name": "start_recurse",
+        "item_name": "start_resolver",
         "item_type": "boolean",
         "item_type": "boolean",
         "item_optional": false,
         "item_optional": false,
         "item_default": false
         "item_default": false

+ 1 - 1
src/bin/bind10/run_bind10.sh.in

@@ -20,7 +20,7 @@ export PYTHON_EXEC
 
 
 BIND10_PATH=@abs_top_builddir@/src/bin/bind10
 BIND10_PATH=@abs_top_builddir@/src/bin/bind10
 
 
-PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/recurse:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:$PATH
+PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:$PATH
 export PATH
 export PATH
 
 
 PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs
 PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs

+ 20 - 20
src/bin/bind10/tests/bind10_test.py

@@ -89,7 +89,7 @@ class TestBoB(unittest.TestCase):
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.cfg_start_auth, True)
         self.assertEqual(bob.cfg_start_auth, True)
-        self.assertEqual(bob.cfg_start_recurse, False)
+        self.assertEqual(bob.cfg_start_resolver, False)
 
 
     def test_init_alternate_socket(self):
     def test_init_alternate_socket(self):
         bob = BoB("alt_socket_file")
         bob = BoB("alt_socket_file")
@@ -106,7 +106,7 @@ class TestBoB(unittest.TestCase):
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.cfg_start_auth, True)
         self.assertEqual(bob.cfg_start_auth, True)
-        self.assertEqual(bob.cfg_start_recurse, False)
+        self.assertEqual(bob.cfg_start_resolver, False)
 
 
     def test_init_alternate_dns_port(self):
     def test_init_alternate_dns_port(self):
         bob = BoB(None, 9999)
         bob = BoB(None, 9999)
@@ -123,7 +123,7 @@ class TestBoB(unittest.TestCase):
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.cfg_start_auth, True)
         self.assertEqual(bob.cfg_start_auth, True)
-        self.assertEqual(bob.cfg_start_recurse, False)
+        self.assertEqual(bob.cfg_start_resolver, False)
 
 
     def test_init_alternate_address(self):
     def test_init_alternate_address(self):
         bob = BoB(None, 1234, IPAddr('127.127.127.127'))
         bob = BoB(None, 1234, IPAddr('127.127.127.127'))
@@ -140,7 +140,7 @@ class TestBoB(unittest.TestCase):
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.username, None)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.nocache, False)
         self.assertEqual(bob.cfg_start_auth, True)
         self.assertEqual(bob.cfg_start_auth, True)
-        self.assertEqual(bob.cfg_start_recurse, False)
+        self.assertEqual(bob.cfg_start_resolver, False)
 
 
 # Class for testing the Bob.start_all_processes() method call.
 # Class for testing the Bob.start_all_processes() method call.
 #
 #
@@ -157,7 +157,7 @@ class StartAllProcessesBob(BoB):
         self.cfgmgr = False
         self.cfgmgr = False
         self.ccsession = False
         self.ccsession = False
         self.auth = False
         self.auth = False
-        self.recurse = False
+        self.resolver = False
         self.xfrout = False
         self.xfrout = False
         self.xfrin = False
         self.xfrin = False
         self.zonemgr = False
         self.zonemgr = False
@@ -180,8 +180,8 @@ class StartAllProcessesBob(BoB):
     def start_auth(self, c_channel_env):
     def start_auth(self, c_channel_env):
         self.auth = True
         self.auth = True
 
 
-    def start_recurse(self, c_channel_env):
+    def start_resolver(self, c_channel_env):
-        self.recurse = True
+        self.resolver = True
 
 
     def start_xfrout(self, c_channel_env):
     def start_xfrout(self, c_channel_env):
         self.xfrout = True
         self.xfrout = True
@@ -206,14 +206,14 @@ class TestStartAllProcessesBob(unittest.TestCase):
         self.assertEqual(bob.cfgmgr, False)
         self.assertEqual(bob.cfgmgr, False)
         self.assertEqual(bob.ccsession, False)
         self.assertEqual(bob.ccsession, False)
         self.assertEqual(bob.auth, False)
         self.assertEqual(bob.auth, False)
-        self.assertEqual(bob.recurse, False)
+        self.assertEqual(bob.resolver, False)
         self.assertEqual(bob.xfrout, False)
         self.assertEqual(bob.xfrout, False)
         self.assertEqual(bob.xfrin, False)
         self.assertEqual(bob.xfrin, False)
         self.assertEqual(bob.zonemgr, False)
         self.assertEqual(bob.zonemgr, False)
         self.assertEqual(bob.stats, False)
         self.assertEqual(bob.stats, False)
         self.assertEqual(bob.cmdctl, False)
         self.assertEqual(bob.cmdctl, False)
 
 
-    # Checks the processes started when starting neither auth nor recurse
+    # Checks the processes started when starting neither auth nor resolver
     # is specified.
     # is specified.
     def test_start_none(self):
     def test_start_none(self):
         # Created Bob and ensure initialization correct
         # Created Bob and ensure initialization correct
@@ -223,7 +223,7 @@ class TestStartAllProcessesBob(unittest.TestCase):
         # Start processes and check what was started
         # Start processes and check what was started
         c_channel_env = {}
         c_channel_env = {}
         bob.cfg_start_auth = False
         bob.cfg_start_auth = False
-        bob.cfg_start_recurse = False
+        bob.cfg_start_resolver = False
 
 
         bob.start_all_processes(c_channel_env)
         bob.start_all_processes(c_channel_env)
 
 
@@ -231,7 +231,7 @@ class TestStartAllProcessesBob(unittest.TestCase):
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.auth, False)
         self.assertEqual(bob.auth, False)
-        self.assertEqual(bob.recurse, False)
+        self.assertEqual(bob.resolver, False)
         self.assertEqual(bob.xfrout, False)
         self.assertEqual(bob.xfrout, False)
         self.assertEqual(bob.xfrin, False)
         self.assertEqual(bob.xfrin, False)
         self.assertEqual(bob.zonemgr, False)
         self.assertEqual(bob.zonemgr, False)
@@ -247,7 +247,7 @@ class TestStartAllProcessesBob(unittest.TestCase):
         # Start processes and check what was started
         # Start processes and check what was started
         c_channel_env = {}
         c_channel_env = {}
         bob.cfg_start_auth = True
         bob.cfg_start_auth = True
-        bob.cfg_start_recurse = False
+        bob.cfg_start_resolver = False
 
 
         bob.start_all_processes(c_channel_env)
         bob.start_all_processes(c_channel_env)
 
 
@@ -255,15 +255,15 @@ class TestStartAllProcessesBob(unittest.TestCase):
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.auth, True)
         self.assertEqual(bob.auth, True)
-        self.assertEqual(bob.recurse, False)
+        self.assertEqual(bob.resolver, False)
         self.assertEqual(bob.xfrout, True)
         self.assertEqual(bob.xfrout, True)
         self.assertEqual(bob.xfrin, True)
         self.assertEqual(bob.xfrin, True)
         self.assertEqual(bob.zonemgr, True)
         self.assertEqual(bob.zonemgr, True)
         self.assertEqual(bob.stats, True)
         self.assertEqual(bob.stats, True)
         self.assertEqual(bob.cmdctl, True)
         self.assertEqual(bob.cmdctl, True)
 
 
-    # Checks the processes started when starting only the recurse process
+    # Checks the processes started when starting only the resolver process
-    def test_start_recurse(self):
+    def test_start_resolver(self):
         # Created Bob and ensure initialization correct
         # Created Bob and ensure initialization correct
         bob = StartAllProcessesBob()
         bob = StartAllProcessesBob()
         self.check_preconditions(bob)
         self.check_preconditions(bob)
@@ -271,7 +271,7 @@ class TestStartAllProcessesBob(unittest.TestCase):
         # Start processes and check what was started
         # Start processes and check what was started
         c_channel_env = {}
         c_channel_env = {}
         bob.cfg_start_auth = False
         bob.cfg_start_auth = False
-        bob.cfg_start_recurse = True
+        bob.cfg_start_resolver = True
 
 
         bob.start_all_processes(c_channel_env)
         bob.start_all_processes(c_channel_env)
 
 
@@ -279,14 +279,14 @@ class TestStartAllProcessesBob(unittest.TestCase):
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.auth, False)
         self.assertEqual(bob.auth, False)
-        self.assertEqual(bob.recurse, True)
+        self.assertEqual(bob.resolver, True)
         self.assertEqual(bob.xfrout, False)
         self.assertEqual(bob.xfrout, False)
         self.assertEqual(bob.xfrin, False)
         self.assertEqual(bob.xfrin, False)
         self.assertEqual(bob.zonemgr, False)
         self.assertEqual(bob.zonemgr, False)
         self.assertEqual(bob.stats, True)
         self.assertEqual(bob.stats, True)
         self.assertEqual(bob.cmdctl, True)
         self.assertEqual(bob.cmdctl, True)
 
 
-    # Checks the processes started when starting both auth and recurse process
+    # Checks the processes started when starting both auth and resolver process
     def test_start_both(self):
     def test_start_both(self):
         # Created Bob and ensure initialization correct
         # Created Bob and ensure initialization correct
         bob = StartAllProcessesBob()
         bob = StartAllProcessesBob()
@@ -295,7 +295,7 @@ class TestStartAllProcessesBob(unittest.TestCase):
         # Start processes and check what was started
         # Start processes and check what was started
         c_channel_env = {}
         c_channel_env = {}
         bob.cfg_start_auth = True
         bob.cfg_start_auth = True
-        bob.cfg_start_recurse = True
+        bob.cfg_start_resolver = True
 
 
         bob.start_all_processes(c_channel_env)
         bob.start_all_processes(c_channel_env)
 
 
@@ -303,7 +303,7 @@ class TestStartAllProcessesBob(unittest.TestCase):
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.cfgmgr, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.ccsession, True)
         self.assertEqual(bob.auth, True)
         self.assertEqual(bob.auth, True)
-        self.assertEqual(bob.recurse, True)
+        self.assertEqual(bob.resolver, True)
         self.assertEqual(bob.xfrout, True)
         self.assertEqual(bob.xfrout, True)
         self.assertEqual(bob.xfrin, True)
         self.assertEqual(bob.xfrin, True)
         self.assertEqual(bob.zonemgr, True)
         self.assertEqual(bob.zonemgr, True)

+ 0 - 57
src/bin/recurse/Makefile.am

@@ -1,57 +0,0 @@
-SUBDIRS = . tests
-
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
-AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
-AM_CPPFLAGS += $(BOOST_INCLUDES)
-
-AM_CXXFLAGS = $(B10_CXXFLAGS)
-
-if USE_STATIC_LINK
-AM_LDFLAGS = -static
-endif
-
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-
-CLEANFILES = *.gcno *.gcda recurse.spec spec_config.h
-
-man_MANS = b10-recurse.8
-EXTRA_DIST = $(man_MANS) b10-recurse.xml
-
-if ENABLE_MAN
-
-b10-recurse.8: b10-recurse.xml
-	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-recurse.xml
-
-endif
-
-recurse.spec: recurse.spec.pre
-	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" recurse.spec.pre >$@
-
-spec_config.h: spec_config.h.pre
-	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
-
-BUILT_SOURCES = spec_config.h 
-pkglibexec_PROGRAMS = b10-recurse
-b10_recurse_SOURCES = recursor.cc recursor.h
-b10_recurse_SOURCES += $(top_builddir)/src/bin/auth/change_user.h
-b10_recurse_SOURCES += $(top_builddir)/src/bin/auth/common.h
-b10_recurse_SOURCES += main.cc
-b10_recurse_LDADD =  $(top_builddir)/src/lib/dns/libdns++.la
-b10_recurse_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
-b10_recurse_LDADD += $(top_builddir)/src/lib/cc/libcc.la
-b10_recurse_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-b10_recurse_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
-b10_recurse_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
-b10_recurse_LDADD += $(top_builddir)/src/lib/log/liblog.la
-b10_recurse_LDADD += $(top_builddir)/src/bin/auth/change_user.o
-b10_recurse_LDFLAGS = -pthread
-
-# TODO: config.h.in is wrong because doesn't honor pkgdatadir
-# and can't use @datadir@ because doesn't expand default ${prefix}
-b10_recursedir = $(DESTDIR)$(pkgdatadir)
-b10_recurse_DATA = recurse.spec
-

+ 57 - 0
src/bin/resolver/Makefile.am

@@ -0,0 +1,57 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+
+CLEANFILES = *.gcno *.gcda resolver.spec spec_config.h
+
+man_MANS = b10-resolver.8
+EXTRA_DIST = $(man_MANS) b10-resolver.xml
+
+if ENABLE_MAN
+
+b10-resolver.8: b10-resolver.xml
+	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-resolver.xml
+
+endif
+
+resolver.spec: resolver.spec.pre
+	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" resolver.spec.pre >$@
+
+spec_config.h: spec_config.h.pre
+	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" spec_config.h.pre >$@
+
+BUILT_SOURCES = spec_config.h 
+pkglibexec_PROGRAMS = b10-resolver
+b10_resolver_SOURCES = resolver.cc resolver.h
+b10_resolver_SOURCES += $(top_builddir)/src/bin/auth/change_user.h
+b10_resolver_SOURCES += $(top_builddir)/src/bin/auth/common.h
+b10_resolver_SOURCES += main.cc
+b10_resolver_LDADD =  $(top_builddir)/src/lib/dns/libdns++.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
+b10_resolver_LDADD += $(top_builddir)/src/lib/log/liblog.la
+b10_resolver_LDADD += $(top_builddir)/src/bin/auth/change_user.o
+b10_resolver_LDFLAGS = -pthread
+
+# TODO: config.h.in is wrong because doesn't honor pkgdatadir
+# and can't use @datadir@ because doesn't expand default ${prefix}
+b10_resolverdir = $(DESTDIR)$(pkgdatadir)
+b10_resolver_DATA = resolver.spec
+

+ 10 - 10
src/bin/recurse/b10-recurse.8

@@ -1,13 +1,13 @@
 '\" t
 '\" t
-.\"     Title: b10-recurse
+.\"     Title: b10-resolver
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: December 27, 2010
+.\"      Date: January 3, 2011
 .\"    Manual: BIND10
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"  Language: English
 .\"
 .\"
-.TH "B10\-RECURSE" "8" "December 27, 2010" "BIND10" "BIND10"
+.TH "B10\-RESOLVER" "8" "January 3, 2011" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
@@ -19,14 +19,14 @@
 .\" * MAIN CONTENT STARTS HERE *
 .\" * MAIN CONTENT STARTS HERE *
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
 .SH "NAME"
 .SH "NAME"
-b10-recurse \- Recursive DNS server
+b10-resolver \- Recursive DNS server
 .SH "SYNOPSIS"
 .SH "SYNOPSIS"
-.HP \w'\fBb10\-recurse\fR\ 'u
+.HP \w'\fBb10\-resolver\fR\ 'u
-\fBb10\-recurse\fR [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
+\fBb10\-resolver\fR [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
 .SH "DESCRIPTION"
 .SH "DESCRIPTION"
 .PP
 .PP
 The
 The
-\fBb10\-recurse\fR
+\fBb10\-resolver\fR
 daemon provides the BIND 10 recursive DNS server\&. Normally it is started by the
 daemon provides the BIND 10 recursive DNS server\&. Normally it is started by the
 \fBbind10\fR(8)
 \fBbind10\fR(8)
 boss process\&.
 boss process\&.
@@ -34,7 +34,7 @@ boss process\&.
 This daemon communicates with other BIND 10 components over a
 This daemon communicates with other BIND 10 components over a
 \fBb10-msgq\fR(8)
 \fBb10-msgq\fR(8)
 C\-Channel connection\&. If this connection is not established,
 C\-Channel connection\&. If this connection is not established,
-\fBb10\-recurse\fR
+\fBb10\-resolver\fR
 will exit\&.
 will exit\&.
 .PP
 .PP
 It also receives its configurations from
 It also receives its configurations from
@@ -63,7 +63,7 @@ The arguments are as follows:
 \fB\-u \fR\fB\fIusername\fR\fR
 \fB\-u \fR\fB\fIusername\fR\fR
 .RS 4
 .RS 4
 The user name of the
 The user name of the
-\fBb10\-recurse\fR
+\fBb10\-resolver\fR
 daemon\&. If specified, the daemon changes the process owner to the specified user\&. The
 daemon\&. If specified, the daemon changes the process owner to the specified user\&. The
 \fIusername\fR
 \fIusername\fR
 must be either a valid numeric user ID or a valid user name\&. By default the daemon runs as the user who invokes it\&.
 must be either a valid numeric user ID or a valid user name\&. By default the daemon runs as the user who invokes it\&.
@@ -87,7 +87,7 @@ BIND 10 Guide\&.
 .SH "HISTORY"
 .SH "HISTORY"
 .PP
 .PP
 The
 The
-\fBb10\-recurse\fR
+\fBb10\-resolver\fR
 daemon was first coded in September 2010\&.
 daemon was first coded in September 2010\&.
 .SH "COPYRIGHT"
 .SH "COPYRIGHT"
 .br
 .br

+ 8 - 8
src/bin/recurse/b10-recurse.xml

@@ -21,17 +21,17 @@
 <refentry>
 <refentry>
 
 
   <refentryinfo>
   <refentryinfo>
-    <date>December 27, 2010</date>
+    <date>January 3, 2011</date>
   </refentryinfo>
   </refentryinfo>
 
 
   <refmeta>
   <refmeta>
-    <refentrytitle>b10-recurse</refentrytitle>
+    <refentrytitle>b10-resolver</refentrytitle>
     <manvolnum>8</manvolnum>
     <manvolnum>8</manvolnum>
     <refmiscinfo>BIND10</refmiscinfo>
     <refmiscinfo>BIND10</refmiscinfo>
   </refmeta>
   </refmeta>
 
 
   <refnamediv>
   <refnamediv>
-    <refname>b10-recurse</refname>
+    <refname>b10-resolver</refname>
     <refpurpose>Recursive DNS server</refpurpose>
     <refpurpose>Recursive DNS server</refpurpose>
   </refnamediv>
   </refnamediv>
 
 
@@ -44,7 +44,7 @@
 
 
   <refsynopsisdiv>
   <refsynopsisdiv>
     <cmdsynopsis>
     <cmdsynopsis>
-      <command>b10-recurse</command>
+      <command>b10-resolver</command>
       <arg><option>-u <replaceable>username</replaceable></option></arg>
       <arg><option>-u <replaceable>username</replaceable></option></arg>
       <arg><option>-v</option></arg>
       <arg><option>-v</option></arg>
     </cmdsynopsis>
     </cmdsynopsis>
@@ -52,7 +52,7 @@
 
 
   <refsect1>
   <refsect1>
     <title>DESCRIPTION</title>
     <title>DESCRIPTION</title>
-    <para>The <command>b10-recurse</command> daemon provides the BIND 10
+    <para>The <command>b10-resolver</command> daemon provides the BIND 10
       recursive DNS server.  Normally it is started by the
       recursive DNS server.  Normally it is started by the
       <citerefentry><refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       <citerefentry><refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       boss process.
       boss process.
@@ -62,7 +62,7 @@
       This daemon communicates with other BIND 10 components over a
       This daemon communicates with other BIND 10 components over a
       <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       <citerefentry><refentrytitle>b10-msgq</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       C-Channel connection.  If this connection is not established,
       C-Channel connection.  If this connection is not established,
-      <command>b10-recurse</command> will exit.
+      <command>b10-resolver</command> will exit.
     </para>
     </para>
 
 
     <para>
     <para>
@@ -89,7 +89,7 @@
         <term><option>-u <replaceable>username</replaceable></option></term>
         <term><option>-u <replaceable>username</replaceable></option></term>
         <listitem>
         <listitem>
 	  <para>
 	  <para>
-	    The user name of the <command>b10-recurse</command> daemon.
+	    The user name of the <command>b10-resolver</command> daemon.
 	    If specified, the daemon changes the process owner to the
 	    If specified, the daemon changes the process owner to the
 	    specified user.
 	    specified user.
 	    The <replaceable>username</replaceable> must be either a
 	    The <replaceable>username</replaceable> must be either a
@@ -141,7 +141,7 @@
   <refsect1>
   <refsect1>
     <title>HISTORY</title>
     <title>HISTORY</title>
     <para>
     <para>
-      The <command>b10-recurse</command> daemon was first coded in
+      The <command>b10-resolver</command> daemon was first coded in
       September 2010.
       September 2010.
     </para>
     </para>
   </refsect1>
   </refsect1>

+ 16 - 16
src/bin/recurse/main.cc

@@ -44,8 +44,8 @@
 #include <auth/change_user.h>
 #include <auth/change_user.h>
 #include <auth/common.h>
 #include <auth/common.h>
 
 
-#include <recurse/spec_config.h>
+#include <resolver/spec_config.h>
-#include <recurse/recursor.h>
+#include <resolver/resolver.h>
 
 
 #include <log/dummylog.h>
 #include <log/dummylog.h>
 
 
@@ -59,14 +59,14 @@ using namespace asiolink;
 namespace {
 namespace {
 
 
 // Default port current 5300 for testing purposes
 // Default port current 5300 for testing purposes
-static const string PROGRAM = "Recurse";
+static const string PROGRAM = "Resolver";
 
 
 IOService io_service;
 IOService io_service;
-static Recursor *recursor;
+static Resolver *resolver;
 
 
 ConstElementPtr
 ConstElementPtr
 my_config_handler(ConstElementPtr new_config) {
 my_config_handler(ConstElementPtr new_config) {
-    return (recursor->updateConfig(new_config));
+    return (resolver->updateConfig(new_config));
 }
 }
 
 
 ConstElementPtr
 ConstElementPtr
@@ -86,7 +86,7 @@ my_command_handler(const string& command, ConstElementPtr args) {
 
 
 void
 void
 usage() {
 usage() {
-    cerr << "Usage:  b10-recurse [-u user] [-v]" << endl;
+    cerr << "Usage:  b10-resolver [-u user] [-v]" << endl;
     cerr << "\t-u: change process UID to the specified user" << endl;
     cerr << "\t-u: change process UID to the specified user" << endl;
     cerr << "\t-v: verbose output" << endl;
     cerr << "\t-v: verbose output" << endl;
     exit(1);
     exit(1);
@@ -95,7 +95,7 @@ usage() {
 
 
 int
 int
 main(int argc, char* argv[]) {
 main(int argc, char* argv[]) {
-    isc::log::dprefix = "b10-recurse";
+    isc::log::dprefix = "b10-resolver";
     int ch;
     int ch;
     const char* uid = NULL;
     const char* uid = NULL;
 
 
@@ -133,21 +133,21 @@ main(int argc, char* argv[]) {
         string specfile;
         string specfile;
         if (getenv("B10_FROM_BUILD")) {
         if (getenv("B10_FROM_BUILD")) {
             specfile = string(getenv("B10_FROM_BUILD")) +
             specfile = string(getenv("B10_FROM_BUILD")) +
-                "/src/bin/recurse/recurse.spec";
+                "/src/bin/resolver/resolver.spec";
         } else {
         } else {
-            specfile = string(RECURSE_SPECFILE_LOCATION);
+            specfile = string(RESOLVER_SPECFILE_LOCATION);
         }
         }
 
 
-        recursor = new Recursor();
+        resolver = new Resolver();
         dlog("Server created.");
         dlog("Server created.");
 
 
-        SimpleCallback* checkin = recursor->getCheckinProvider();
+        SimpleCallback* checkin = resolver->getCheckinProvider();
-        DNSLookup* lookup = recursor->getDNSLookupProvider();
+        DNSLookup* lookup = resolver->getDNSLookupProvider();
-        DNSAnswer* answer = recursor->getDNSAnswerProvider();
+        DNSAnswer* answer = resolver->getDNSAnswerProvider();
 
 
         DNSService dns_service(io_service, checkin, lookup, answer);
         DNSService dns_service(io_service, checkin, lookup, answer);
 
 
-        recursor->setDNSService(dns_service);
+        resolver->setDNSService(dns_service);
         dlog("IOService created.");
         dlog("IOService created.");
 
 
         cc_session = new Session(io_service.get_io_service());
         cc_session = new Session(io_service.get_io_service());
@@ -163,7 +163,7 @@ main(int argc, char* argv[]) {
             changeUser(uid);
             changeUser(uid);
         }
         }
 
 
-        recursor->setConfigSession(config_session);
+        resolver->setConfigSession(config_session);
         dlog("Config loaded");
         dlog("Config loaded");
 
 
         dlog("Server started.");
         dlog("Server started.");
@@ -175,7 +175,7 @@ main(int argc, char* argv[]) {
 
 
     delete config_session;
     delete config_session;
     delete cc_session;
     delete cc_session;
-    delete recursor;
+    delete resolver;
 
 
     return (ret);
     return (ret);
 }
 }

+ 30 - 30
src/bin/recurse/recursor.cc

@@ -45,7 +45,7 @@
 
 
 #include <log/dummylog.h>
 #include <log/dummylog.h>
 
 
-#include <recurse/recursor.h>
+#include <resolver/resolver.h>
 
 
 using namespace std;
 using namespace std;
 
 
@@ -58,18 +58,18 @@ using namespace asiolink;
 
 
 typedef pair<string, uint16_t> addr_t;
 typedef pair<string, uint16_t> addr_t;
 
 
-class RecursorImpl {
+class ResolverImpl {
 private:
 private:
     // prohibit copy
     // prohibit copy
-    RecursorImpl(const RecursorImpl& source);
+    ResolverImpl(const ResolverImpl& source);
-    RecursorImpl& operator=(const RecursorImpl& source);
+    ResolverImpl& operator=(const ResolverImpl& source);
 public:
 public:
-    RecursorImpl() :
+    ResolverImpl() :
         config_session_(NULL),
         config_session_(NULL),
         rec_query_(NULL)
         rec_query_(NULL)
     {}
     {}
 
 
-    ~RecursorImpl() {
+    ~ResolverImpl() {
         queryShutdown();
         queryShutdown();
     }
     }
 
 
@@ -112,7 +112,7 @@ public:
     /// Currently non-configurable, but will be.
     /// Currently non-configurable, but will be.
     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
 
 
-    /// These members are public because Recursor accesses them directly.
+    /// These members are public because Resolver accesses them directly.
     ModuleCCSession* config_session_;
     ModuleCCSession* config_session_;
     /// Addresses of the forward nameserver
     /// Addresses of the forward nameserver
     vector<addr_t> upstream_;
     vector<addr_t> upstream_;
@@ -201,10 +201,10 @@ makeErrorMessage(MessagePtr message, OutputBufferPtr buffer,
 
 
 // This is a derived class of \c DNSLookup, to serve as a
 // This is a derived class of \c DNSLookup, to serve as a
 // callback in the asiolink module.  It calls
 // callback in the asiolink module.  It calls
-// Recursor::processMessage() on a single DNS message.
+// Resolver::processMessage() on a single DNS message.
 class MessageLookup : public DNSLookup {
 class MessageLookup : public DNSLookup {
 public:
 public:
-    MessageLookup(Recursor* srv) : server_(srv) {}
+    MessageLookup(Resolver* srv) : server_(srv) {}
 
 
     // \brief Handle the DNS Lookup
     // \brief Handle the DNS Lookup
     virtual void operator()(const IOMessage& io_message, MessagePtr message,
     virtual void operator()(const IOMessage& io_message, MessagePtr message,
@@ -213,7 +213,7 @@ public:
         server_->processMessage(io_message, message, buffer, server);
         server_->processMessage(io_message, message, buffer, server);
     }
     }
 private:
 private:
-    Recursor* server_;
+    Resolver* server_;
 };
 };
 
 
 // This is a derived class of \c DNSAnswer, to serve as a
 // This is a derived class of \c DNSAnswer, to serve as a
@@ -300,50 +300,50 @@ public:
 // configuration messages, and executes them if found.
 // configuration messages, and executes them if found.
 class ConfigCheck : public SimpleCallback {
 class ConfigCheck : public SimpleCallback {
 public:
 public:
-    ConfigCheck(Recursor* srv) : server_(srv) {}
+    ConfigCheck(Resolver* srv) : server_(srv) {}
     virtual void operator()(const IOMessage&) const {
     virtual void operator()(const IOMessage&) const {
         if (server_->getConfigSession()->hasQueuedMsgs()) {
         if (server_->getConfigSession()->hasQueuedMsgs()) {
             server_->getConfigSession()->checkCommand();
             server_->getConfigSession()->checkCommand();
         }
         }
     }
     }
 private:
 private:
-    Recursor* server_;
+    Resolver* server_;
 };
 };
 
 
-Recursor::Recursor() :
+Resolver::Resolver() :
-    impl_(new RecursorImpl()),
+    impl_(new ResolverImpl()),
     checkin_(new ConfigCheck(this)),
     checkin_(new ConfigCheck(this)),
     dns_lookup_(new MessageLookup(this)),
     dns_lookup_(new MessageLookup(this)),
     dns_answer_(new MessageAnswer)
     dns_answer_(new MessageAnswer)
 {}
 {}
 
 
-Recursor::~Recursor() {
+Resolver::~Resolver() {
     delete impl_;
     delete impl_;
     delete checkin_;
     delete checkin_;
     delete dns_lookup_;
     delete dns_lookup_;
     delete dns_answer_;
     delete dns_answer_;
-    dlog("Deleting the Recursor");
+    dlog("Deleting the Resolver");
 }
 }
 
 
 void
 void
-Recursor::setDNSService(asiolink::DNSService& dnss) {
+Resolver::setDNSService(asiolink::DNSService& dnss) {
     impl_->queryShutdown();
     impl_->queryShutdown();
     impl_->querySetup(dnss);
     impl_->querySetup(dnss);
     dnss_ = &dnss;
     dnss_ = &dnss;
 }
 }
 
 
 void
 void
-Recursor::setConfigSession(ModuleCCSession* config_session) {
+Resolver::setConfigSession(ModuleCCSession* config_session) {
     impl_->config_session_ = config_session;
     impl_->config_session_ = config_session;
 }
 }
 
 
 ModuleCCSession*
 ModuleCCSession*
-Recursor::getConfigSession() const {
+Resolver::getConfigSession() const {
     return (impl_->config_session_);
     return (impl_->config_session_);
 }
 }
 
 
 void
 void
-Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
+Resolver::processMessage(const IOMessage& io_message, MessagePtr message,
                         OutputBufferPtr buffer, DNSServer* server)
                         OutputBufferPtr buffer, DNSServer* server)
 {
 {
     dlog("Got a DNS message");
     dlog("Got a DNS message");
@@ -422,7 +422,7 @@ Recursor::processMessage(const IOMessage& io_message, MessagePtr message,
 }
 }
 
 
 void
 void
-RecursorImpl::processNormalQuery(const Question& question, MessagePtr message,
+ResolverImpl::processNormalQuery(const Question& question, MessagePtr message,
                                  OutputBufferPtr buffer, DNSServer* server)
                                  OutputBufferPtr buffer, DNSServer* server)
 {
 {
     dlog("Processing normal query");
     dlog("Processing normal query");
@@ -435,7 +435,7 @@ RecursorImpl::processNormalQuery(const Question& question, MessagePtr message,
     if (edns) {
     if (edns) {
         EDNSPtr edns_response(new EDNS());
         EDNSPtr edns_response(new EDNS());
         edns_response->setDNSSECAwareness(dnssec_ok);
         edns_response->setDNSSECAwareness(dnssec_ok);
-        edns_response->setUDPSize(RecursorImpl::DEFAULT_LOCAL_UDPSIZE);
+        edns_response->setUDPSize(ResolverImpl::DEFAULT_LOCAL_UDPSIZE);
         message->setEDNS(edns_response);
         message->setEDNS(edns_response);
     }
     }
     rec_query_->sendQuery(question, buffer, server);
     rec_query_->sendQuery(question, buffer, server);
@@ -482,7 +482,7 @@ parseAddresses(ConstElementPtr addresses) {
 }
 }
 
 
 ConstElementPtr
 ConstElementPtr
-Recursor::updateConfig(ConstElementPtr config) {
+Resolver::updateConfig(ConstElementPtr config) {
     dlog("New config comes: " + config->toWire());
     dlog("New config comes: " + config->toWire());
 
 
     try {
     try {
@@ -531,18 +531,18 @@ Recursor::updateConfig(ConstElementPtr config) {
 }
 }
 
 
 void
 void
-Recursor::setForwardAddresses(const vector<addr_t>& addresses)
+Resolver::setForwardAddresses(const vector<addr_t>& addresses)
 {
 {
     impl_->setForwardAddresses(addresses, dnss_);
     impl_->setForwardAddresses(addresses, dnss_);
 }
 }
 
 
 bool
 bool
-Recursor::isForwarding() const {
+Resolver::isForwarding() const {
     return (!impl_->upstream_.empty());
     return (!impl_->upstream_.empty());
 }
 }
 
 
 vector<addr_t>
 vector<addr_t>
-Recursor::getForwardAddresses() const {
+Resolver::getForwardAddresses() const {
     return (impl_->upstream_);
     return (impl_->upstream_);
 }
 }
 
 
@@ -559,7 +559,7 @@ setAddresses(DNSService *service, const vector<addr_t>& addresses) {
 }
 }
 
 
 void
 void
-Recursor::setListenAddresses(const vector<addr_t>& addresses) {
+Resolver::setListenAddresses(const vector<addr_t>& addresses) {
     try {
     try {
         dlog("Setting listen addresses:");
         dlog("Setting listen addresses:");
         BOOST_FOREACH(const addr_t& addr, addresses) {
         BOOST_FOREACH(const addr_t& addr, addresses) {
@@ -591,7 +591,7 @@ Recursor::setListenAddresses(const vector<addr_t>& addresses) {
 }
 }
 
 
 void
 void
-Recursor::setTimeouts(int timeout, unsigned retries) {
+Resolver::setTimeouts(int timeout, unsigned retries) {
     dlog("Setting timeout to " + boost::lexical_cast<string>(timeout) +
     dlog("Setting timeout to " + boost::lexical_cast<string>(timeout) +
         " and retry count to " + boost::lexical_cast<string>(retries));
         " and retry count to " + boost::lexical_cast<string>(retries));
     impl_->timeout_ = timeout;
     impl_->timeout_ = timeout;
@@ -600,11 +600,11 @@ Recursor::setTimeouts(int timeout, unsigned retries) {
     impl_->querySetup(*dnss_);
     impl_->querySetup(*dnss_);
 }
 }
 pair<int, unsigned>
 pair<int, unsigned>
-Recursor::getTimeouts() const {
+Resolver::getTimeouts() const {
     return (pair<int, unsigned>(impl_->timeout_, impl_->retries_));
     return (pair<int, unsigned>(impl_->timeout_, impl_->retries_));
 }
 }
 
 
 vector<addr_t>
 vector<addr_t>
-Recursor::getListenAddresses() const {
+Resolver::getListenAddresses() const {
     return (impl_->listen_);
     return (impl_->listen_);
 }
 }

+ 11 - 11
src/bin/recurse/recursor.h

@@ -14,8 +14,8 @@
 
 
 // $Id$
 // $Id$
 
 
-#ifndef __RECURSOR_H
+#ifndef __RESOLVER_H
-#define __RECURSOR_H 1
+#define __RESOLVER_H 1
 
 
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
@@ -26,7 +26,7 @@
 
 
 #include <asiolink/asiolink.h>
 #include <asiolink/asiolink.h>
 
 
-class RecursorImpl;
+class ResolverImpl;
 
 
 /**
 /**
  * \short The recursive nameserver.
  * \short The recursive nameserver.
@@ -37,7 +37,7 @@ class RecursorImpl;
  * answer. It doesn't really know about chasing referrals and similar, it
  * answer. It doesn't really know about chasing referrals and similar, it
  * simply plugs the parts that know into the network handling code.
  * simply plugs the parts that know into the network handling code.
  */
  */
-class Recursor {
+class Resolver {
     ///
     ///
     /// \name Constructors, Assignment Operator and Destructor.
     /// \name Constructors, Assignment Operator and Destructor.
     ///
     ///
@@ -45,12 +45,12 @@ class Recursor {
     /// intentionally defined as private.
     /// intentionally defined as private.
     //@{
     //@{
 private:
 private:
-    Recursor(const Recursor& source);
+    Resolver(const Resolver& source);
-    Recursor& operator=(const Recursor& source);
+    Resolver& operator=(const Resolver& source);
 public:
 public:
     /// The constructor.
     /// The constructor.
-    Recursor();
+    Resolver();
-    ~Recursor();
+    ~Resolver();
     //@}
     //@}
 
 
     /// \brief Process an incoming DNS message, then signal 'server' to resume 
     /// \brief Process an incoming DNS message, then signal 'server' to resume 
@@ -76,7 +76,7 @@ public:
     /// \brief Handle commands from the config session
     /// \brief Handle commands from the config session
     isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
     isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
 
 
-    /// \brief Assign an ASIO IO Service queue to this Recursor object
+    /// \brief Assign an ASIO IO Service queue to this Resolver object
     void setDNSService(asiolink::DNSService& dnss);
     void setDNSService(asiolink::DNSService& dnss);
 
 
     /// \brief Return this object's ASIO IO Service queue
     /// \brief Return this object's ASIO IO Service queue
@@ -137,14 +137,14 @@ public:
     std::pair<int, unsigned> getTimeouts() const;
     std::pair<int, unsigned> getTimeouts() const;
 
 
 private:
 private:
-    RecursorImpl* impl_;
+    ResolverImpl* impl_;
     asiolink::DNSService* dnss_;
     asiolink::DNSService* dnss_;
     asiolink::SimpleCallback* checkin_;
     asiolink::SimpleCallback* checkin_;
     asiolink::DNSLookup* dns_lookup_;
     asiolink::DNSLookup* dns_lookup_;
     asiolink::DNSAnswer* dns_answer_;
     asiolink::DNSAnswer* dns_answer_;
 };
 };
 
 
-#endif // __RECURSOR_H
+#endif // __RESOLVER_H
 
 
 // Local Variables: 
 // Local Variables: 
 // mode: c++
 // mode: c++

+ 1 - 1
src/bin/recurse/recurse.spec.pre.in

@@ -1,6 +1,6 @@
 {
 {
   "module_spec": {
   "module_spec": {
-    "module_name": "Recurse",
+    "module_name": "Resolver",
     "module_description": "Recursive service",
     "module_description": "Recursive service",
     "config_data": [
     "config_data": [
       {
       {

+ 1 - 1
src/bin/recurse/spec_config.h.pre.in

@@ -12,4 +12,4 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
-#define RECURSE_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/recurse.spec"
+#define RESOLVER_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/resolver.spec"

+ 4 - 3
src/bin/recurse/tests/Makefile.am

@@ -19,14 +19,15 @@ if HAVE_GTEST
 TESTS += run_unittests
 TESTS += run_unittests
 run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
-run_unittests_SOURCES += ../recursor.h ../recursor.cc
+run_unittests_SOURCES += ../resolver.h ../resolver.cc
-run_unittests_SOURCES += recursor_unittest.cc
+run_unittests_SOURCES += resolver_unittest.cc
-run_unittests_SOURCES += recursor_config_unittest.cc
+run_unittests_SOURCES += resolver_config_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
 run_unittests_LDADD += $(SQLITE_LIBS)
+run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD +=  $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la

+ 30 - 16
src/bin/recurse/tests/recursor_config_unittest.cc

@@ -12,18 +12,32 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
-// $Id$
+#include <string>
 
 
-#include <recurse/recursor.h>
+#include <gtest/gtest.h>
-#include <testutils/srv_unittest.h>
+
+#include <cc/data.h>
+
+#include <asiolink/asiolink.h>
+
+#include <resolver/resolver.h>
+
+#include <dns/tests/unittest_util.h>
+#include <testutils/srv_test.h>
+
+using namespace std;
+using namespace isc::data;
+using namespace isc::testutils;
+using namespace asiolink;
+using isc::UnitTestUtil;
 
 
 namespace {
 namespace {
-class RecursorConfig : public ::testing::Test {
+class ResolverConfig : public ::testing::Test {
     public:
     public:
         IOService ios;
         IOService ios;
         DNSService dnss;
         DNSService dnss;
-        Recursor server;
+        Resolver server;
-        RecursorConfig() :
+        ResolverConfig() :
             dnss(ios, NULL, NULL, NULL)
             dnss(ios, NULL, NULL, NULL)
         {
         {
             server.setDNSService(dnss);
             server.setDNSService(dnss);
@@ -31,7 +45,7 @@ class RecursorConfig : public ::testing::Test {
         void invalidTest(const string &JOSN);
         void invalidTest(const string &JOSN);
 };
 };
 
 
-TEST_F(RecursorConfig, forwardAddresses) {
+TEST_F(ResolverConfig, forwardAddresses) {
     // Default value should be fully recursive
     // Default value should be fully recursive
     EXPECT_TRUE(server.getForwardAddresses().empty());
     EXPECT_TRUE(server.getForwardAddresses().empty());
     EXPECT_FALSE(server.isForwarding());
     EXPECT_FALSE(server.isForwarding());
@@ -55,7 +69,7 @@ TEST_F(RecursorConfig, forwardAddresses) {
     EXPECT_FALSE(server.isForwarding());
     EXPECT_FALSE(server.isForwarding());
 }
 }
 
 
-TEST_F(RecursorConfig, forwardAddressConfig) {
+TEST_F(ResolverConfig, forwardAddressConfig) {
     // Try putting there some address
     // Try putting there some address
     ElementPtr config(Element::fromJSON("{"
     ElementPtr config(Element::fromJSON("{"
         "\"forward_addresses\": ["
         "\"forward_addresses\": ["
@@ -83,13 +97,13 @@ TEST_F(RecursorConfig, forwardAddressConfig) {
 }
 }
 
 
 void
 void
-RecursorConfig::invalidTest(const string &JOSN) {
+ResolverConfig::invalidTest(const string &JOSN) {
     ElementPtr config(Element::fromJSON(JOSN));
     ElementPtr config(Element::fromJSON(JOSN));
     EXPECT_FALSE(server.updateConfig(config)->equals(
     EXPECT_FALSE(server.updateConfig(config)->equals(
         *isc::config::createAnswer())) << "Accepted config " << JOSN << endl;
         *isc::config::createAnswer())) << "Accepted config " << JOSN << endl;
 }
 }
 
 
-TEST_F(RecursorConfig, invalidForwardAddresses) {
+TEST_F(ResolverConfig, invalidForwardAddresses) {
     // Try torturing it with some invalid inputs
     // Try torturing it with some invalid inputs
     invalidTest("{"
     invalidTest("{"
         "\"forward_addresses\": \"error\""
         "\"forward_addresses\": \"error\""
@@ -114,7 +128,7 @@ TEST_F(RecursorConfig, invalidForwardAddresses) {
         "}]}");
         "}]}");
 }
 }
 
 
-TEST_F(RecursorConfig, listenAddresses) {
+TEST_F(ResolverConfig, listenAddresses) {
     // Default value should be fully recursive
     // Default value should be fully recursive
     EXPECT_TRUE(server.getListenAddresses().empty());
     EXPECT_TRUE(server.getListenAddresses().empty());
 
 
@@ -135,7 +149,7 @@ TEST_F(RecursorConfig, listenAddresses) {
     EXPECT_TRUE(server.getListenAddresses().empty());
     EXPECT_TRUE(server.getListenAddresses().empty());
 }
 }
 
 
-TEST_F(RecursorConfig, DISABLED_listenAddressConfig) {
+TEST_F(ResolverConfig, DISABLED_listenAddressConfig) {
     // Try putting there some address
     // Try putting there some address
     ElementPtr config(Element::fromJSON("{"
     ElementPtr config(Element::fromJSON("{"
         "\"listen_on\": ["
         "\"listen_on\": ["
@@ -171,7 +185,7 @@ TEST_F(RecursorConfig, DISABLED_listenAddressConfig) {
     EXPECT_EQ(5300, server.getListenAddresses()[0].second);
     EXPECT_EQ(5300, server.getListenAddresses()[0].second);
 }
 }
 
 
-TEST_F(RecursorConfig, invalidListenAddresses) {
+TEST_F(ResolverConfig, invalidListenAddresses) {
     // Try torturing it with some invalid inputs
     // Try torturing it with some invalid inputs
     invalidTest("{"
     invalidTest("{"
         "\"listen_on\": \"error\""
         "\"listen_on\": \"error\""
@@ -197,7 +211,7 @@ TEST_F(RecursorConfig, invalidListenAddresses) {
 }
 }
 
 
 // Just test it sets and gets the values correctly
 // Just test it sets and gets the values correctly
-TEST_F(RecursorConfig, timeouts) {
+TEST_F(ResolverConfig, timeouts) {
     server.setTimeouts(0, 1);
     server.setTimeouts(0, 1);
     EXPECT_EQ(0, server.getTimeouts().first);
     EXPECT_EQ(0, server.getTimeouts().first);
     EXPECT_EQ(1, server.getTimeouts().second);
     EXPECT_EQ(1, server.getTimeouts().second);
@@ -206,7 +220,7 @@ TEST_F(RecursorConfig, timeouts) {
     EXPECT_EQ(0, server.getTimeouts().second);
     EXPECT_EQ(0, server.getTimeouts().second);
 }
 }
 
 
-TEST_F(RecursorConfig, timeoutsConfig) {
+TEST_F(ResolverConfig, timeoutsConfig) {
     ElementPtr config = Element::fromJSON("{"
     ElementPtr config = Element::fromJSON("{"
             "\"timeout\": 1000,"
             "\"timeout\": 1000,"
             "\"retries\": 3"
             "\"retries\": 3"
@@ -217,7 +231,7 @@ TEST_F(RecursorConfig, timeoutsConfig) {
     EXPECT_EQ(3, server.getTimeouts().second);
     EXPECT_EQ(3, server.getTimeouts().second);
 }
 }
 
 
-TEST_F(RecursorConfig, invalidTimeoutsConfig) {
+TEST_F(ResolverConfig, invalidTimeoutsConfig) {
     invalidTest("{"
     invalidTest("{"
         "\"timeout\": \"error\""
         "\"timeout\": \"error\""
         "}");
         "}");

+ 33 - 24
src/bin/recurse/tests/recursor_unittest.cc

@@ -12,62 +12,71 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
-// $Id$
+#include <dns/name.h>
 
 
-#include <recurse/recursor.h>
+#include <resolver/resolver.h>
-#include <testutils/srv_unittest.h>
+#include <dns/tests/unittest_util.h>
+#include <testutils/srv_test.h>
+
+using namespace isc::dns;
+using namespace isc::testutils;
+using isc::UnitTestUtil;
 
 
 namespace {
 namespace {
 const char* const TEST_PORT = "53535";
 const char* const TEST_PORT = "53535";
 
 
-class RecursorTest : public SrvTestBase{
+class ResolverTest : public SrvTestBase{
 protected:
 protected:
-    RecursorTest() : server(){}
+    ResolverTest() : server(){}
-    Recursor server;
+    virtual void processMessage() {
+        server.processMessage(*io_message, parse_message, response_obuffer,
+                              &dnsserv);
+    }
+    Resolver server;
 };
 };
 
 
 // Unsupported requests.  Should result in NOTIMP.
 // Unsupported requests.  Should result in NOTIMP.
-TEST_F(RecursorTest, unsupportedRequest) {
+TEST_F(ResolverTest, unsupportedRequest) {
-    UNSUPPORTED_REQUEST_TEST;
+    unsupportedRequest();
 }
 }
 
 
 // Multiple questions.  Should result in FORMERR.
 // Multiple questions.  Should result in FORMERR.
-TEST_F(RecursorTest, multiQuestion) {
+TEST_F(ResolverTest, multiQuestion) {
-    MULTI_QUESTION_TEST; 
+    multiQuestion(); 
 }
 }
 
 
 // Incoming data doesn't even contain the complete header.  Must be silently
 // Incoming data doesn't even contain the complete header.  Must be silently
 // dropped.
 // dropped.
-TEST_F(RecursorTest, shortMessage) {
+TEST_F(ResolverTest, shortMessage) {
-    SHORT_MESSAGE_TEST;
+    shortMessage();
 }
 }
 
 
 // Response messages.  Must be silently dropped, whether it's a valid response
 // Response messages.  Must be silently dropped, whether it's a valid response
 // or malformed or could otherwise cause a protocol error.
 // or malformed or could otherwise cause a protocol error.
-TEST_F(RecursorTest, response) {
+TEST_F(ResolverTest, response) {
-    RESPONSE_TEST;
+     response();
 }
 }
 
 
 // Query with a broken question
 // Query with a broken question
-TEST_F(RecursorTest, shortQuestion) {
+TEST_F(ResolverTest, shortQuestion) {
-    SHORT_QUESTION_TEST;
+    shortQuestion();
 }
 }
 
 
 // Query with a broken answer section
 // Query with a broken answer section
-TEST_F(RecursorTest, shortAnswer) {
+TEST_F(ResolverTest, shortAnswer) {
-    SHORT_ANSWER_TEST;
+    shortAnswer();
 }
 }
 
 
 // Query with unsupported version of EDNS.
 // Query with unsupported version of EDNS.
-TEST_F(RecursorTest, ednsBadVers) {
+TEST_F(ResolverTest, ednsBadVers) {
-    EDNS_BADVERS_TEST;
+    ednsBadVers();
 }
 }
 
 
-TEST_F(RecursorTest, AXFROverUDP) {
+TEST_F(ResolverTest, AXFROverUDP) {
-    AXFR_OVER_UDP_TEST;
+    axfrOverUDP();
 }
 }
 
 
-TEST_F(RecursorTest, AXFRFail) {
+TEST_F(ResolverTest, AXFRFail) {
     UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
     UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
                                        Name("example.com"), RRClass::IN(),
                                        Name("example.com"), RRClass::IN(),
                                        RRType::AXFR());
                                        RRType::AXFR());
@@ -79,7 +88,7 @@ TEST_F(RecursorTest, AXFRFail) {
                 QR_FLAG, 1, 0, 0, 0);
                 QR_FLAG, 1, 0, 0, 0);
 }
 }
 
 
-TEST_F(RecursorTest, notifyFail) {
+TEST_F(ResolverTest, notifyFail) {
     // Notify should always return NOTAUTH
     // Notify should always return NOTAUTH
     request_message.clear(Message::RENDER);
     request_message.clear(Message::RENDER);
     request_message.setOpcode(Opcode::NOTIFY());
     request_message.setOpcode(Opcode::NOTIFY());

src/bin/recurse/tests/run_unittests.cc → src/bin/resolver/tests/run_unittests.cc


+ 1 - 1
src/lib/asiolink/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = . tests
+SUBDIRS = . tests internal
 
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CPPFLAGS += $(BOOST_INCLUDES)

+ 1 - 1
src/lib/asiolink/README

@@ -17,7 +17,7 @@ including:
     leaving it in place elsewhere.
     leaving it in place elsewhere.
 
 
 Currently, the asiolink library only supports DNS servers (i.e., b10-auth
 Currently, the asiolink library only supports DNS servers (i.e., b10-auth
-and b10-recurse).  The plan is to make it more generic and allow it to
+and b10-resolver).  The plan is to make it more generic and allow it to
 support other modules as well.
 support other modules as well.
 
 
 Some of the classes defined here--for example, IOSocket, IOEndpoint,
 Some of the classes defined here--for example, IOSocket, IOEndpoint,

+ 1 - 1
src/lib/asiolink/asiolink.h

@@ -77,7 +77,7 @@ class io_service;
 ///
 ///
 /// Notes to developers:
 /// Notes to developers:
 /// Currently the wrapper interface is fairly specific to use by a
 /// Currently the wrapper interface is fairly specific to use by a
-/// DNS server, i.e., b10-auth or b10-recurse.  But the plan is to
+/// DNS server, i.e., b10-auth or b10-resolver.  But the plan is to
 /// generalize it and have other modules use it as well.
 /// generalize it and have other modules use it as well.
 ///
 ///
 /// One obvious drawback of this approach is performance overhead
 /// One obvious drawback of this approach is performance overhead

+ 1 - 0
src/lib/asiolink/internal/Makefile.am

@@ -0,0 +1 @@
+SUBDIRS = tests

+ 37 - 0
src/lib/asiolink/internal/tests/Makefile.am

@@ -0,0 +1,37 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+run_unittests_SOURCES = udpdns_unittest.cc
+run_unittests_SOURCES += run_unittests.cc
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+run_unittests_LDADD = $(GTEST_LDADD)
+run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
+run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
+# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
+# B10_CXXFLAGS)
+run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_GXX
+run_unittests_CXXFLAGS += -Wno-unused-parameter
+endif
+if USE_CLANGPP
+# We need to disable -Werror for any test that uses internal definitions of
+# ASIO when using clang++
+run_unittests_CXXFLAGS += -Wno-error
+endif
+endif
+
+noinst_PROGRAMS = $(TESTS)

+ 21 - 0
src/lib/asiolink/internal/tests/run_unittests.cc

@@ -0,0 +1,21 @@
+// 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 <gtest/gtest.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return (RUN_ALL_TESTS());
+}

src/lib/asiolink/tests/udpdns_unittest.cc → src/lib/asiolink/internal/tests/udpdns_unittest.cc


+ 0 - 1
src/lib/asiolink/tests/Makefile.am

@@ -18,7 +18,6 @@ TESTS += run_unittests
 run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES += asiolink_unittest.cc
 run_unittests_SOURCES += asiolink_unittest.cc
-run_unittests_SOURCES += udpdns_unittest.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_SOURCES += run_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)

+ 72 - 40
src/lib/asiolink/tests/asiolink_unittest.cc

@@ -17,6 +17,9 @@
 
 
 #include <config.h>
 #include <config.h>
 
 
+#include <sys/socket.h>
+#include <sys/time.h>
+
 #include <string.h>
 #include <string.h>
 
 
 #include <boost/lexical_cast.hpp>
 #include <boost/lexical_cast.hpp>
@@ -32,19 +35,21 @@
 #include <dns/buffer.h>
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/message.h>
 
 
+// IMPORTANT: We shouldn't directly use ASIO definitions in this test.
+// In particular, we must not include asio.hpp in this file.
+// The asiolink module is primarily intended to be a wrapper that hide the
+// details of the underlying implementations.  We need to test the wrapper
+// level behaviors.  In addition, some compilers reject to compile this file
+// if we include asio.hpp unless we specify a special compiler option.
+// If we need to test something at the level of underlying ASIO and need
+// their definition, that test should go to asiolink/internal/tests.
 #include <asiolink/asiolink.h>
 #include <asiolink/asiolink.h>
 #include <asiolink/iosocket.h>
 #include <asiolink/iosocket.h>
-#include <asiolink/internal/tcpdns.h>
-#include <asiolink/internal/udpdns.h>
-
-#include <asio.hpp>
 
 
 using isc::UnitTestUtil;
 using isc::UnitTestUtil;
 using namespace std;
 using namespace std;
 using namespace asiolink;
 using namespace asiolink;
 using namespace isc::dns;
 using namespace isc::dns;
-using namespace asio;
-using asio::ip::udp;
 
 
 namespace {
 namespace {
 const char* const TEST_SERVER_PORT = "53535";
 const char* const TEST_SERVER_PORT = "53535";
@@ -330,10 +335,30 @@ protected:
         // ... and this one will block until the send has completed
         // ... and this one will block until the send has completed
         io_service_->run_one();
         io_service_->run_one();
 
 
-        // Now we attempt to recv() whatever was sent
+        // Now we attempt to recv() whatever was sent.
-        const int ret = recv(sock_, buffer, size, MSG_DONTWAIT);
+        // XXX: there's no guarantee the receiving socket can immediately get
+        // the packet.  Normally we can perform blocking recv to wait for it,
+        // but in theory it's even possible that the packet is lost.
+        // In order to prevent the test from hanging in such a worst case
+        // we add an ad hoc timeout.
+        const struct timeval timeo = { 10, 0 };
+        int recv_options = 0;
+        if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
+                       sizeof(timeo))) {
+            if (errno == ENOPROTOOPT) {
+                // Workaround for Solaris: it doesn't accept SO_RCVTIMEO
+                // with the error of ENOPROTOOPT.  Since this is a workaround
+                // for rare error cases anyway, we simply switch to the
+                // "don't wait" mode.  If we still find an error in recv()
+                // can happen often we'll consider a more complete solution.
+                recv_options = MSG_DONTWAIT;
+            } else {
+                isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
+            }
+        }
+        const int ret = recv(sock_, buffer, size, recv_options);
         if (ret < 0) {
         if (ret < 0) {
-            isc_throw(IOError, "recvfrom failed");
+            isc_throw(IOError, "recvfrom failed: " << strerror(errno));
         }
         }
         
         
         // Pass the message size back via the size parameter
         // Pass the message size back via the size parameter
@@ -411,8 +436,7 @@ protected:
     // has completed.
     // has completed.
     class MockServer : public DNSServer {
     class MockServer : public DNSServer {
     public:
     public:
-        explicit MockServer(asio::io_service& io_service,
+        explicit MockServer(IOService& io_service,
-                            const asio::ip::address& addr, const uint16_t port,
                             SimpleCallback* checkin = NULL,
                             SimpleCallback* checkin = NULL,
                             DNSLookup* lookup = NULL,
                             DNSLookup* lookup = NULL,
                             DNSAnswer* answer = NULL) :
                             DNSAnswer* answer = NULL) :
@@ -426,9 +450,7 @@ protected:
                         size_t length = 0)
                         size_t length = 0)
         {}
         {}
 
 
-        void resume(const bool done) {
+        void resume(const bool) { // in our test this shouldn't be called
-            done_ = done;
-            io_.post(*this);
         }
         }
 
 
         DNSServer* clone() {
         DNSServer* clone() {
@@ -443,7 +465,7 @@ protected:
         }
         }
 
 
     protected:
     protected:
-        asio::io_service& io_;
+        IOService& io_;
         bool done_;
         bool done_;
 
 
     private:
     private:
@@ -462,8 +484,8 @@ protected:
     // This version of mock server just stops the io_service when it is resumed
     // This version of mock server just stops the io_service when it is resumed
     class MockServerStop : public MockServer {
     class MockServerStop : public MockServer {
         public:
         public:
-            explicit MockServerStop(asio::io_service& io_service, bool* done) :
+            explicit MockServerStop(IOService& io_service, bool* done) :
-                MockServer(io_service, asio::ip::address(), 0),
+                MockServer(io_service),
                 done_(done)
                 done_(done)
             {}
             {}
 
 
@@ -511,7 +533,6 @@ protected:
     string callback_address_;
     string callback_address_;
     vector<uint8_t> callback_data_;
     vector<uint8_t> callback_data_;
     int sock_;
     int sock_;
-private:
     struct addrinfo* res_;
     struct addrinfo* res_;
 };
 };
 
 
@@ -640,14 +661,12 @@ TEST_F(ASIOLinkTest, recursiveSetupV6) {
 // full code coverage including error cases.
 // full code coverage including error cases.
 TEST_F(ASIOLinkTest, recursiveSend) {
 TEST_F(ASIOLinkTest, recursiveSend) {
     setDNSService(true, false);
     setDNSService(true, false);
-    asio::io_service& io = io_service_->get_io_service();
 
 
     // Note: We use the test prot plus one to ensure we aren't binding
     // Note: We use the test prot plus one to ensure we aren't binding
     // to the same port as the actual server
     // to the same port as the actual server
     uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
     uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
-    asio::ip::address addr = asio::ip::address::from_string(TEST_IPV4_ADDR);
 
 
-    MockServer server(io, addr, port, NULL, NULL, NULL);
+    MockServer server(*io_service_);
     RecursiveQuery rq(*dns_service_, singleAddress(TEST_IPV4_ADDR, port));
     RecursiveQuery rq(*dns_service_, singleAddress(TEST_IPV4_ADDR, port));
 
 
     Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
     Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
@@ -656,7 +675,7 @@ TEST_F(ASIOLinkTest, recursiveSend) {
 
 
     char data[4096];
     char data[4096];
     size_t size = sizeof(data);
     size_t size = sizeof(data);
-    EXPECT_NO_THROW(recvUDP(AF_INET, data, size));
+    ASSERT_NO_THROW(recvUDP(AF_INET, data, size));
 
 
     Message m(Message::PARSE);
     Message m(Message::PARSE);
     InputBuffer ibuf(data, size);
     InputBuffer ibuf(data, size);
@@ -672,34 +691,27 @@ TEST_F(ASIOLinkTest, recursiveSend) {
     EXPECT_EQ(q.getClass(), q2->getClass());
     EXPECT_EQ(q.getClass(), q2->getClass());
 }
 }
 
 
-void
-receive_and_inc(udp::socket* socket, int* num) {
-    (*num) ++;
-    static char inbuff[512];
-    socket->async_receive(asio::buffer(inbuff, 512),
-        boost::bind(receive_and_inc, socket, num));
-}
-
 // Test it tries the correct amount of times before giving up
 // Test it tries the correct amount of times before giving up
 TEST_F(ASIOLinkTest, recursiveTimeout) {
 TEST_F(ASIOLinkTest, recursiveTimeout) {
     // Prepare the service (we do not use the common setup, we do not answer
     // Prepare the service (we do not use the common setup, we do not answer
     setDNSService();
     setDNSService();
-    asio::io_service& service = io_service_->get_io_service();
 
 
     // Prepare the socket
     // Prepare the socket
-    uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
+    res_ = resolveAddress(AF_INET, IPPROTO_UDP, true);
-    udp::socket socket(service, udp::v4());
+    sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
-    socket.set_option(socket_base::reuse_address(true));
+    if (sock_ < 0) {
-    socket.bind(udp::endpoint(ip::address::from_string(TEST_IPV4_ADDR), port));
+        isc_throw(IOError, "failed to open test socket");
-    // And count the answers
+    }
-    int num = -1; // One is counted before the receipt of the first one
+    if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
-    receive_and_inc(&socket, &num);
+        isc_throw(IOError, "failed to bind test socket");
+    }
 
 
     // Prepare the server
     // Prepare the server
     bool done(true);
     bool done(true);
-    MockServerStop server(service, &done);
+    MockServerStop server(*io_service_, &done);
 
 
     // Do the answer
     // Do the answer
+    const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
     RecursiveQuery query(*dns_service_, singleAddress(TEST_IPV4_ADDR, port),
     RecursiveQuery query(*dns_service_, singleAddress(TEST_IPV4_ADDR, port),
         10, 2);
         10, 2);
     Question question(Name("example.net"), RRClass::IN(), RRType::A());
     Question question(Name("example.net"), RRClass::IN(), RRType::A());
@@ -707,7 +719,27 @@ TEST_F(ASIOLinkTest, recursiveTimeout) {
     query.sendQuery(question, buffer, &server);
     query.sendQuery(question, buffer, &server);
 
 
     // Run the test
     // Run the test
-    service.run();
+    io_service_->run();
+
+    // Read up to 3 packets.  Use some ad hoc timeout to prevent an infinite
+    // block (see also recvUDP()).
+    const struct timeval timeo = { 10, 0 };
+    int recv_options = 0;
+    if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
+        if (errno == ENOPROTOOPT) { // see ASIOLinkTest::recvUDP()
+            recv_options = MSG_DONTWAIT;
+        } else {
+            isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
+        }
+    }
+    int num = 0;
+    do {
+        char inbuff[512];
+        if (recv(sock_, inbuff, sizeof(inbuff), recv_options) < 0) {
+            num = -1;
+            break;
+        }
+    } while (++num < 3);
 
 
     // The query should fail
     // The query should fail
     EXPECT_FALSE(done);
     EXPECT_FALSE(done);

+ 2 - 2
src/lib/datasrc/cache.h

@@ -81,7 +81,7 @@ class HotCacheImpl;
 /// from the tail of the list.  This operation is not locked.  BIND 10
 /// from the tail of the list.  This operation is not locked.  BIND 10
 /// does not currently use threads, but if it ever does (or if libdatasrc
 /// does not currently use threads, but if it ever does (or if libdatasrc
 /// is ever used by a threaded application), this will need to be
 /// is ever used by a threaded application), this will need to be
-//revisited.
+/// revisited.
 class HotCache {
 class HotCache {
 private:
 private:
     /// \name Static definitions
     /// \name Static definitions
@@ -164,7 +164,7 @@ public:
     ///
     ///
     /// Retrieves a record from the cache matching the given 
     /// Retrieves a record from the cache matching the given 
     /// query-tuple.  Returns true if one is found.  If it is a
     /// query-tuple.  Returns true if one is found.  If it is a
-    /// posiitve cache entry, then 'rrset' is set to the cached
+    /// positive cache entry, then 'rrset' is set to the cached
     /// RRset.  For both positive and negative cache entries, 'flags'
     /// RRset.  For both positive and negative cache entries, 'flags'
     /// is set to the query response flags.  The cache entry is 
     /// is set to the query response flags.  The cache entry is 
     /// then promoted to the head of the LRU queue.  (NOTE: Because
     /// then promoted to the head of the LRU queue.  (NOTE: Because

+ 2 - 2
src/lib/datasrc/data_source.cc

@@ -103,14 +103,14 @@ getAdditional(Query& q, ConstRRsetPtr rrset) {
                                new QueryTask(q, ns.getNSName(),
                                new QueryTask(q, ns.getNSName(),
                                              Message::SECTION_ADDITIONAL,
                                              Message::SECTION_ADDITIONAL,
                                              QueryTask::GLUE_QUERY,
                                              QueryTask::GLUE_QUERY,
-                                             QueryTask::GETADDITIONAL))); 
+                                             QueryTask::GETADDITIONAL)));
         } else if (rrset->getType() == RRType::MX()) {
         } else if (rrset->getType() == RRType::MX()) {
             const generic::MX& mx = dynamic_cast<const generic::MX&>(rd);
             const generic::MX& mx = dynamic_cast<const generic::MX&>(rd);
             q.tasks().push(QueryTaskPtr(
             q.tasks().push(QueryTaskPtr(
                                new QueryTask(q, mx.getMXName(),
                                new QueryTask(q, mx.getMXName(),
                                              Message::SECTION_ADDITIONAL,
                                              Message::SECTION_ADDITIONAL,
                                              QueryTask::NOGLUE_QUERY,
                                              QueryTask::NOGLUE_QUERY,
-                                             QueryTask::GETADDITIONAL))); 
+                                             QueryTask::GETADDITIONAL)));
         }
         }
     }
     }
 }
 }

+ 2 - 2
src/lib/datasrc/rbtree.h

@@ -672,7 +672,7 @@ void
 RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
 RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
     using namespace helper;
     using namespace helper;
     const isc::dns::Name sub_name = node.name_ - base_name;
     const isc::dns::Name sub_name = node.name_ - base_name;
-    // using auto_ptr here is to avoid memory leak in case of exceptoin raised
+    // using auto_ptr here is to avoid memory leak in case of exception raised
     // after the RBNode creation
     // after the RBNode creation
     std::auto_ptr<RBNode<T> > down_node(new RBNode<T>(sub_name));
     std::auto_ptr<RBNode<T> > down_node(new RBNode<T>(sub_name));
     std::swap(node.data_, down_node->data_);
     std::swap(node.data_, down_node->data_);
@@ -680,7 +680,7 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
     down_node->down_ = node.down_;
     down_node->down_ = node.down_;
     node.name_ = base_name;
     node.name_ = base_name;
     node.down_ = down_node.get();
     node.down_ = down_node.get();
-    //root node of sub tree, the initial color is BLACK
+    // root node of sub tree, the initial color is BLACK
     down_node->color_ = RBNode<T>::BLACK;
     down_node->color_ = RBNode<T>::BLACK;
     ++node_count_;
     ++node_count_;
     down_node.release();
     down_node.release();

+ 1 - 1
src/lib/nsas/README

@@ -2,6 +2,6 @@ For an overview of the Nameserver Address Store, see the requirements and design
 documents at http://bind10.isc.org/wiki/Resolver.
 documents at http://bind10.isc.org/wiki/Resolver.
 
 
 At the time of writing (19 October 2010), the file asiolink.h is present in this
 At the time of writing (19 October 2010), the file asiolink.h is present in this
-directory only for the purposes of development.  When the recursor's
+directory only for the purposes of development.  When the resolver's
 asynchronous I/O code has been finished, this will be removed and the NSAS will
 asynchronous I/O code has been finished, this will be removed and the NSAS will
 use the "real" code.
 use the "real" code.

+ 1 - 1
src/lib/nsas/asiolink.h

@@ -24,7 +24,7 @@ namespace asiolink {
 
 
 /// \brief IO Address Dummy Class
 /// \brief IO Address Dummy Class
 ///
 ///
-/// As part of ther recursor, Evan has written the asiolink.h file, which
+/// As part of ther resolver, Evan has written the asiolink.h file, which
 /// encapsulates some of the boost::asio classes.  Until these are checked
 /// encapsulates some of the boost::asio classes.  Until these are checked
 /// into trunk and merged with this branch, these dummy classes should fulfill
 /// into trunk and merged with this branch, these dummy classes should fulfill
 /// their function.
 /// their function.

+ 10 - 9
src/lib/python/isc/config/module_spec.py

@@ -339,13 +339,14 @@ def _validate_spec_list(module_spec, full, data, errors):
 
 
     # check if there are items in our data that are not in the
     # check if there are items in our data that are not in the
     # specification
     # specification
-    for item_name in data:
+    if data is not None:
-        found = False
+        for item_name in data:
-        for spec_item in module_spec:
+            found = False
-            if spec_item["item_name"] == item_name:
+            for spec_item in module_spec:
-                found = True
+                if spec_item["item_name"] == item_name:
-        if not found:
+                    found = True
-            if errors != None:
+            if not found:
-                errors.append("unknown item " + item_name)
+                if errors != None:
-            validated = False
+                    errors.append("unknown item " + item_name)
+                validated = False
     return validated
     return validated

+ 4 - 0
src/lib/python/isc/config/tests/module_spec_test.py

@@ -109,6 +109,9 @@ class TestModuleSpec(unittest.TestCase):
         return dd.validate_command(cmd_name, params)
         return dd.validate_command(cmd_name, params)
 
 
     def test_command_validation(self):
     def test_command_validation(self):
+        # tests for a command that doesn't take an argument
+        self.assertEqual(True, self.read_spec_file("spec2.spec").validate_command("shutdown", None));
+        self.assertEqual(False, self.read_spec_file("spec2.spec").validate_command("shutdown", '{"val": 1}'));
         self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_1.data", 'cmd1'))
         self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_1.data", 'cmd1'))
         self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_2.data",'cmd1'))
         self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_2.data",'cmd1'))
         self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_3.data", 'cmd1'))
         self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_3.data", 'cmd1'))
@@ -321,6 +324,7 @@ class TestModuleSpec(unittest.TestCase):
                }]
                }]
 
 
         errors = []
         errors = []
+        self.assertEqual(True, isc.config.module_spec._validate_spec_list(spec, True, None, None))
         self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, None))
         self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, None))
         self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, errors))
         self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, errors))
         self.assertEqual(['unknown item does_not_exist'], errors)
         self.assertEqual(['unknown item does_not_exist'], errors)

+ 12 - 4
src/lib/testutils/Makefile.am

@@ -1,5 +1,13 @@
-SUBDIRS = testdata
+SUBDIRS = . testdata
 
 
-EXTRA_DIST = srv_test.h
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-EXTRA_DIST += srv_unittest.h
+AM_CPPFLAGS += $(BOOST_INCLUDES)
-EXTRA_DIST += mockups.h
+AM_CXXFLAGS=$(B10_CXXFLAGS)
+
+if HAVE_GTEST
+lib_LTLIBRARIES = libtestutils.la
+
+libtestutils_la_SOURCES = srv_test.h srv_test.cc
+libtestutils_la_SOURCES += mockups.h
+libtestutils_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+endif

+ 0 - 2
src/lib/testutils/README

@@ -1,4 +1,2 @@
 Here is some code used by more than one test. No code is used for bind10
 Here is some code used by more than one test. No code is used for bind10
 itself, only for testing.
 itself, only for testing.
-
-As it contains headers only currently, it does not compile here.

+ 272 - 0
src/lib/testutils/srv_test.cc

@@ -0,0 +1,272 @@
+// 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 <netinet/in.h>
+
+#include <dns/message.h>
+#include <dns/rcode.h>
+
+#include <asiolink/asiolink.h>
+
+#include <dns/tests/unittest_util.h>
+
+#include <testutils/srv_test.h>
+
+using namespace isc::dns;
+using namespace asiolink;
+
+namespace isc {
+namespace testutils {
+const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
+
+const unsigned int QR_FLAG = 0x1;
+const unsigned int AA_FLAG = 0x2;
+const unsigned int TC_FLAG = 0x4;
+const unsigned int RD_FLAG = 0x8;
+const unsigned int RA_FLAG = 0x10;
+const unsigned int AD_FLAG = 0x20;
+const unsigned int CD_FLAG = 0x40;
+
+SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
+                             parse_message(new Message(Message::PARSE)),
+                             default_qid(0x1035),
+                             opcode(Opcode(Opcode::QUERY())),
+                             qname("www.example.com"),
+                             qclass(RRClass::IN()),
+                             qtype(RRType::A()), io_sock(NULL),
+                             io_message(NULL), endpoint(NULL),
+                             request_obuffer(0),
+                             request_renderer(request_obuffer),
+                             response_obuffer(new OutputBuffer(0))
+{}
+
+SrvTestBase::~SrvTestBase() {
+    delete io_message;
+    delete endpoint;
+}
+
+void
+SrvTestBase::createDataFromFile(const char* const datafile,
+                                const int protocol)
+{
+    delete io_message;
+    data.clear();
+
+    delete endpoint;
+
+    endpoint = IOEndpoint::create(protocol,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
+    UnitTestUtil::readWireData(datafile, data);
+    io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
+        &IOSocket::getDummyTCPSocket();
+    io_message = new IOMessage(&data[0], data.size(), *io_sock, *endpoint);
+}
+
+void
+SrvTestBase::createRequestPacket(Message& message,
+                                 const int protocol)
+{
+    message.toWire(request_renderer);
+
+    delete io_message;
+
+    endpoint = IOEndpoint::create(protocol,
+                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
+    io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
+        &IOSocket::getDummyTCPSocket();
+    io_message = new IOMessage(request_renderer.getData(),
+                               request_renderer.getLength(),
+                               *io_sock, *endpoint);
+}
+
+// Unsupported requests.  Should result in NOTIMP.
+void
+SrvTestBase::unsupportedRequest() {
+    for (unsigned int i = 0; i < 16; ++i) {
+        // set Opcode to 'i', which iterators over all possible codes except
+        // the standard query and notify 
+        if (i == isc::dns::Opcode::QUERY().getCode() ||
+            i == isc::dns::Opcode::NOTIFY().getCode()) {
+            continue;
+        }
+        createDataFromFile("simplequery_fromWire.wire");
+        data[2] = ((i << 3) & 0xff);
+
+        parse_message->clear(isc::dns::Message::PARSE);
+        processMessage();
+        EXPECT_TRUE(dnsserv.hasAnswer());
+        headerCheck(*parse_message, default_qid, isc::dns::Rcode::NOTIMP(), i,
+                    QR_FLAG, 0, 0, 0, 0);
+    }
+}
+
+// Multiple questions.  Should result in FORMERR.
+void
+SrvTestBase::multiQuestion() {
+    createDataFromFile("multiquestion_fromWire.wire");
+    processMessage();
+    EXPECT_TRUE(dnsserv.hasAnswer());
+    headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
+                opcode.getCode(), QR_FLAG, 2, 0, 0, 0);
+
+    isc::dns::QuestionIterator qit = parse_message->beginQuestion();
+    EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
+    EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
+    EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
+    ++qit;
+    EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
+    EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
+    EXPECT_EQ(isc::dns::RRType::AAAA(), (*qit)->getType());
+    ++qit;
+    EXPECT_TRUE(qit == parse_message->endQuestion());
+}
+
+// Incoming data doesn't even contain the complete header.  Must be silently
+// dropped.
+void
+SrvTestBase::shortMessage() {
+    createDataFromFile("shortmessage_fromWire");
+    processMessage();
+    EXPECT_FALSE(dnsserv.hasAnswer());
+}
+
+// Response messages.  Must be silently dropped, whether it's a valid response
+// or malformed or could otherwise cause a protocol error.
+void
+SrvTestBase::response() {
+    // A valid (although unusual) response 
+    createDataFromFile("simpleresponse_fromWire.wire");
+    processMessage();
+    EXPECT_FALSE(dnsserv.hasAnswer());
+
+    // A response with a broken question section.  must be dropped rather than
+    //returning FORMERR.
+    createDataFromFile("shortresponse_fromWire");
+    processMessage();
+    EXPECT_FALSE(dnsserv.hasAnswer());
+
+    // A response to iquery.  must be dropped rather than returning NOTIMP.
+    createDataFromFile("iqueryresponse_fromWire.wire");
+    processMessage();
+    EXPECT_FALSE(dnsserv.hasAnswer());
+}
+
+// Query with a broken question
+void
+SrvTestBase::shortQuestion() {
+    createDataFromFile("shortquestion_fromWire");
+    processMessage();
+    EXPECT_TRUE(dnsserv.hasAnswer());
+    // Since the query's question is broken, the question section of the
+    // response should be empty.
+    headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
+                opcode.getCode(), QR_FLAG, 0, 0, 0, 0);
+}
+
+// Query with a broken answer section
+void
+SrvTestBase::shortAnswer() {
+    createDataFromFile("shortanswer_fromWire.wire");
+    processMessage();
+    EXPECT_TRUE(dnsserv.hasAnswer());
+
+    // This is a bogus query, but question section is valid.  So the response
+    // should copy the question section.
+    headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+
+    isc::dns::QuestionIterator qit = parse_message->beginQuestion();
+    EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
+    EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
+    EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
+    ++qit;
+    EXPECT_TRUE(qit == parse_message->endQuestion());
+}
+
+// Query with unsupported version of EDNS.
+void
+SrvTestBase::ednsBadVers() {
+    createDataFromFile("queryBadEDNS_fromWire.wire");
+    processMessage();
+    EXPECT_TRUE(dnsserv.hasAnswer());
+
+    // The response must have an EDNS OPT RR in the additional section,
+    // it will be added automatically at the render time.
+    // Note that the DNSSEC DO bit is cleared even if this bit in the query
+    // is set.  This is a limitation of the current implementation.
+    headerCheck(*parse_message, default_qid, isc::dns::Rcode::BADVERS(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 1);
+    EXPECT_FALSE(parse_message->getEDNS()); // EDNS isn't added at this point
+
+    isc::dns::InputBuffer ib(response_obuffer->getData(),
+                             response_obuffer->getLength());
+    isc::dns::Message parsed(isc::dns::Message::PARSE);
+    parsed.fromWire(ib);
+    EXPECT_EQ(isc::dns::Rcode::BADVERS(), parsed.getRcode());
+    isc::dns::ConstEDNSPtr edns(parsed.getEDNS());
+    ASSERT_TRUE(edns);
+    EXPECT_FALSE(edns->getDNSSECAwareness());
+}
+
+void
+SrvTestBase::axfrOverUDP() {
+    // AXFR over UDP is invalid and should result in FORMERR.
+    UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
+                                       isc::dns::Name("example.com"),
+                                       isc::dns::RRClass::IN(),
+                                       isc::dns::RRType::AXFR());
+    createRequestPacket(request_message, IPPROTO_UDP);
+    processMessage();
+    EXPECT_TRUE(dnsserv.hasAnswer());
+    headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
+                opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
+}
+
+void
+headerCheck(const Message& message, const qid_t qid, const Rcode& rcode,
+            const uint16_t opcodeval, const unsigned int flags,
+            const unsigned int qdcount,
+            const unsigned int ancount, const unsigned int nscount,
+            const unsigned int arcount)
+{
+    EXPECT_EQ(qid, message.getQid());
+    EXPECT_EQ(rcode, message.getRcode());
+    EXPECT_EQ(opcodeval, message.getOpcode().getCode());
+    EXPECT_EQ((flags & QR_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_QR));
+    EXPECT_EQ((flags & AA_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_AA));
+    EXPECT_EQ((flags & TC_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_TC));
+    EXPECT_EQ((flags & RA_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_RA));
+    EXPECT_EQ((flags & RD_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_RD));
+    EXPECT_EQ((flags & AD_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_AD));
+    EXPECT_EQ((flags & CD_FLAG) != 0,
+              message.getHeaderFlag(Message::HEADERFLAG_CD));
+
+    EXPECT_EQ(qdcount, message.getRRCount(Message::SECTION_QUESTION));
+    EXPECT_EQ(ancount, message.getRRCount(Message::SECTION_ANSWER));
+    EXPECT_EQ(nscount, message.getRRCount(Message::SECTION_AUTHORITY));
+    EXPECT_EQ(arcount, message.getRRCount(Message::SECTION_ADDITIONAL));
+}
+} // end of namespace testutils
+} // end of namespace isc
+
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 82 - 126
src/lib/testutils/srv_test.h

@@ -12,10 +12,6 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
-// $Id: auth_srv_unittest.cc 3310 2010-10-21 23:10:24Z each $
-
-#include <config.h>
-
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
 #include <dns/buffer.h>
 #include <dns/buffer.h>
@@ -27,139 +23,99 @@
 #include <dns/rrclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrtype.h>
 #include <dns/rrtype.h>
 
 
-#include <cc/data.h>
-#include <cc/session.h>
-
-#include <xfr/xfrout_client.h>
-
-#include <auth/auth_srv.h>
-#include <asiolink/asiolink.h>
-
-#include <dns/tests/unittest_util.h>
 #include "mockups.h"
 #include "mockups.h"
 
 
-using namespace std;
+namespace asiolink {
-using namespace isc::cc;
+class IOSocket;
-using namespace isc::dns;
+class IOMessage;
-using namespace isc::data;
+class IOEndpoint;
-using namespace isc::xfr;
-using namespace asiolink;
-using isc::UnitTestUtil;
-
-namespace {
-const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
-
-// The base class for Auth and Recurse test case
-class SrvTestBase : public ::testing::Test {
-protected:
-    SrvTestBase() : request_message(Message::RENDER),
-                    parse_message(new Message(Message::PARSE)),
-                    default_qid(0x1035), opcode(Opcode(Opcode::QUERY())),
-                    qname("www.example.com"), qclass(RRClass::IN()),
-                    qtype(RRType::A()), io_sock(NULL), 
-                    io_message(NULL), endpoint(NULL),
-                    request_obuffer(0), request_renderer(request_obuffer),
-                    response_obuffer(new OutputBuffer(0))
-    {}
-    ~SrvTestBase() {
-        delete io_message;
-        delete endpoint;
-    }
-    MockSession notify_session;
-    MockServer dnsserv;
-    Message request_message;
-    MessagePtr parse_message;
-    const qid_t default_qid;
-    const Opcode opcode;
-    const Name qname;
-    const RRClass qclass;
-    const RRType qtype;
-    IOSocket* io_sock;
-    IOMessage* io_message;
-    const IOEndpoint* endpoint;
-    OutputBuffer request_obuffer;
-    MessageRenderer request_renderer;
-    OutputBufferPtr response_obuffer;
-    vector<uint8_t> data;
-
-    void createDataFromFile(const char* const datafile, int protocol);
-    void createRequestPacket(Message& message, const int protocol);
-};
-
-void
-SrvTestBase::createDataFromFile(const char* const datafile,
-                                const int protocol = IPPROTO_UDP)
-{
-    delete io_message;
-    data.clear();
-
-    delete endpoint;
-
-    endpoint = IOEndpoint::create(protocol,
-                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
-    UnitTestUtil::readWireData(datafile, data);
-    io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
-        &IOSocket::getDummyTCPSocket();
-    io_message = new IOMessage(&data[0], data.size(), *io_sock, *endpoint);
 }
 }
 
 
-void
+namespace isc {
-SrvTestBase::createRequestPacket(Message& message,
+namespace testutils {
-                                 const int protocol = IPPROTO_UDP)
+extern const char* const DEFAULT_REMOTE_ADDRESS;
-{
-    message.toWire(request_renderer);
-
-    delete io_message;
-
-    endpoint = IOEndpoint::create(protocol,
-                                  IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
-    io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
-        &IOSocket::getDummyTCPSocket();
-    io_message = new IOMessage(request_renderer.getData(),
-                               request_renderer.getLength(),
-                               *io_sock, *endpoint);
-}
 
 
 // These are flags to indicate whether the corresponding flag bit of the
 // These are flags to indicate whether the corresponding flag bit of the
-// DNS header is to be set in the test cases.  (Note that the flag values
+// DNS header is to be set in the test cases.  (The flag values
 // is irrelevant to their wire-format values)
 // is irrelevant to their wire-format values)
-const unsigned int QR_FLAG = 0x1;
+extern const unsigned int QR_FLAG;
-const unsigned int AA_FLAG = 0x2;
+extern const unsigned int AA_FLAG;
-const unsigned int TC_FLAG = 0x4;
+extern const unsigned int TC_FLAG;
-const unsigned int RD_FLAG = 0x8;
+extern const unsigned int RD_FLAG;
-const unsigned int RA_FLAG = 0x10;
+extern const unsigned int RA_FLAG;
-const unsigned int AD_FLAG = 0x20;
+extern const unsigned int AD_FLAG;
-const unsigned int CD_FLAG = 0x40;
+extern const unsigned int CD_FLAG;
 
 
 void
 void
-headerCheck(const Message& message, const qid_t qid, const Rcode& rcode,
+headerCheck(const isc::dns::Message& message, const isc::dns::qid_t qid,
+            const isc::dns::Rcode& rcode,
             const uint16_t opcodeval, const unsigned int flags,
             const uint16_t opcodeval, const unsigned int flags,
             const unsigned int qdcount,
             const unsigned int qdcount,
             const unsigned int ancount, const unsigned int nscount,
             const unsigned int ancount, const unsigned int nscount,
-            const unsigned int arcount)
+            const unsigned int arcount);
-{
-    EXPECT_EQ(qid, message.getQid());
-    EXPECT_EQ(rcode, message.getRcode());
-    EXPECT_EQ(opcodeval, message.getOpcode().getCode());
-    EXPECT_EQ((flags & QR_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_QR));
-    EXPECT_EQ((flags & AA_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_AA));
-    EXPECT_EQ((flags & TC_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_TC));
-    EXPECT_EQ((flags & RA_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_RA));
-    EXPECT_EQ((flags & RD_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_RD));
-    EXPECT_EQ((flags & AD_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_AD));
-    EXPECT_EQ((flags & CD_FLAG) != 0,
-              message.getHeaderFlag(Message::HEADERFLAG_CD));
 
 
-    EXPECT_EQ(qdcount, message.getRRCount(Message::SECTION_QUESTION));
+// The base class for Auth and Recurse test case
-    EXPECT_EQ(ancount, message.getRRCount(Message::SECTION_ANSWER));
+class SrvTestBase : public ::testing::Test {
-    EXPECT_EQ(nscount, message.getRRCount(Message::SECTION_AUTHORITY));
+protected:
-    EXPECT_EQ(arcount, message.getRRCount(Message::SECTION_ADDITIONAL));
+    SrvTestBase();
-}
+    virtual ~SrvTestBase();
+
+    /// Let the server process a DNS message.
+    ///
+    /// The derived class implementation is expected to pass \c io_message,
+    /// \c parse_message, \c response_obuffer, and \c dnsserv to the server
+    /// implementation it is testing.
+    virtual void processMessage() = 0;
+
+    /// The following methods implement server independent test logic using
+    /// the template method pattern.  Each test calls \c processMessage()
+    /// to delegate the server-dependent behavior to the actual implementation
+    /// classes.
+    void unsupportedRequest();
+    void multiQuestion();
+    void shortMessage();
+    void response();
+    void shortQuestion();
+    void shortAnswer();
+    void ednsBadVers();
+    void axfrOverUDP();
+
+    /// Create DNS packet data from a file.
+    ///
+    /// It constructs wire-format DNS packet data from \c datafile in the
+    /// form of \c IOMessage in \c io_message.
+    /// The existing content of \c io_message, if any, will be deleted.
+    void createDataFromFile(const char* const datafile,
+                            int protocol = IPPROTO_UDP);
+
+    ///  Create DNS packet data from a message.
+    ///
+    /// It constructs wire-format DNS packet data from \c message in the
+    /// form of \c IOMessage in \c io_message.
+    /// The existing content of \c io_message, if any, will be deleted.
+    void createRequestPacket(isc::dns::Message& message,
+                             const int protocol = IPPROTO_UDP);
 
 
-}
+    MockSession notify_session;
+    MockServer dnsserv;
+    isc::dns::Message request_message;
+    isc::dns::MessagePtr parse_message;
+    const isc::dns::qid_t default_qid;
+    const isc::dns::Opcode opcode;
+    const isc::dns::Name qname;
+    const isc::dns::RRClass qclass;
+    const isc::dns::RRType qtype;
+    asiolink::IOSocket* io_sock;
+    asiolink::IOMessage* io_message;
+    const asiolink::IOEndpoint* endpoint;
+    isc::dns::OutputBuffer request_obuffer;
+    isc::dns::MessageRenderer request_renderer;
+    isc::dns::OutputBufferPtr response_obuffer;
+    std::vector<uint8_t> data;
+};
+} // end of namespace testutils
+} // end of namespace isc
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 0 - 158
src/lib/testutils/srv_unittest.h

@@ -1,158 +0,0 @@
-// 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.
-
-// $Id: auth_srv_unittest.cc 3310 2010-10-21 23:10:24Z each $
-
-#include "srv_test.h"
-
-namespace {
-
-// Unsupported requests.  Should result in NOTIMP.
-#define UNSUPPORTED_REQUEST_TEST \
-    for (unsigned int i = 0; i < 16; ++i) { \
-        /* set Opcode to 'i', which iterators over all possible codes except \
-           the standard query and notify */ \
-        if (i == Opcode::QUERY().getCode() || \
-            i == Opcode::NOTIFY().getCode()) { \
-            continue; \
-        } \
-        createDataFromFile("simplequery_fromWire.wire"); \
-        data[2] = ((i << 3) & 0xff); \
- \
-        parse_message->clear(Message::PARSE); \
-        server.processMessage(*io_message, parse_message, response_obuffer, \
-                              &dnsserv); \
-        EXPECT_TRUE(dnsserv.hasAnswer()); \
-        headerCheck(*parse_message, default_qid, Rcode::NOTIMP(), i, QR_FLAG, \
-                    0, 0, 0, 0); \
-    }
-
-// Simple API check
-#define VERBOSE_TEST \
-    EXPECT_FALSE(server.getVerbose()); \
-    server.setVerbose(true); \
-    EXPECT_TRUE(server.getVerbose()); \
-    server.setVerbose(false); \
-    EXPECT_FALSE(server.getVerbose()); \
-
-
-// Multiple questions.  Should result in FORMERR.
-#define MULTI_QUESTION_TEST \
-    createDataFromFile("multiquestion_fromWire.wire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_TRUE(dnsserv.hasAnswer()); \
-    headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
-                QR_FLAG, 2, 0, 0, 0); \
- \
-    QuestionIterator qit = parse_message->beginQuestion(); \
-    EXPECT_EQ(Name("example.com"), (*qit)->getName()); \
-    EXPECT_EQ(RRClass::IN(), (*qit)->getClass()); \
-    EXPECT_EQ(RRType::A(), (*qit)->getType()); \
-    ++qit; \
-    EXPECT_EQ(Name("example.com"), (*qit)->getName()); \
-    EXPECT_EQ(RRClass::IN(), (*qit)->getClass()); \
-    EXPECT_EQ(RRType::AAAA(), (*qit)->getType()); \
-    ++qit; \
-    EXPECT_TRUE(qit == parse_message->endQuestion());
-
-// Incoming data doesn't even contain the complete header.  Must be silently
-// dropped.
-#define SHORT_MESSAGE_TEST \
-    createDataFromFile("shortmessage_fromWire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_FALSE(dnsserv.hasAnswer());
-
-// Response messages.  Must be silently dropped, whether it's a valid response
-// or malformed or could otherwise cause a protocol error.
-#define RESPONSE_TEST \
-    /* A valid (although unusual) response */\
-    createDataFromFile("simpleresponse_fromWire.wire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_FALSE(dnsserv.hasAnswer()); \
- \
-    /* A response with a broken question section.  must be dropped rather than \
-       returning FORMERR. */\
-    createDataFromFile("shortresponse_fromWire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_FALSE(dnsserv.hasAnswer()); \
- \
-    /* A response to iquery.  must be dropped rather than returning NOTIMP. */\
-    createDataFromFile("iqueryresponse_fromWire.wire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_FALSE(dnsserv.hasAnswer());
-
-// Query with a broken question
-#define SHORT_QUESTION_TEST \
-    createDataFromFile("shortquestion_fromWire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_TRUE(dnsserv.hasAnswer()); \
-    /* Since the query's question is broken, the question section of the \
-       response should be empty. */\
-    headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
-                QR_FLAG, 0, 0, 0, 0);
-
-// Query with a broken answer section
-#define SHORT_ANSWER_TEST \
-    createDataFromFile("shortanswer_fromWire.wire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_TRUE(dnsserv.hasAnswer()); \
- \
-    /* This is a bogus query, but question section is valid.  So the response \
-       should copy the question section. */ \
-    headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
-                QR_FLAG, 1, 0, 0, 0); \
- \
-    QuestionIterator qit = parse_message->beginQuestion(); \
-    EXPECT_EQ(Name("example.com"), (*qit)->getName()); \
-    EXPECT_EQ(RRClass::IN(), (*qit)->getClass()); \
-    EXPECT_EQ(RRType::A(), (*qit)->getType()); \
-    ++qit; \
-    EXPECT_TRUE(qit == parse_message->endQuestion());
-
-// Query with unsupported version of EDNS.
-#define EDNS_BADVERS_TEST \
-    createDataFromFile("queryBadEDNS_fromWire.wire"); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_TRUE(dnsserv.hasAnswer()); \
- \
-    /* The response must have an EDNS OPT RR in the additional section, \
-       it will be added automatically at the render time.
-       Note that the DNSSEC DO bit is cleared even if this bit in the query \
-       is set.  This is a limitation of the current implementation. */ \
-    headerCheck(*parse_message, default_qid, Rcode::BADVERS(), opcode.getCode(), \
-                QR_FLAG, 1, 0, 0, 1); \
-    EXPECT_FALSE(parse_message->getEDNS()); /* EDNS isn't added at this point */ \
- \
-    InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength()); \
-    Message parsed(Message::PARSE); \
-    parsed.fromWire(ib); \
-    EXPECT_EQ(Rcode::BADVERS(), parsed.getRcode()); \
-    ConstEDNSPtr edns(parsed.getEDNS()); \
-    ASSERT_TRUE(edns); \
-    EXPECT_FALSE(edns->getDNSSECAwareness());
-
-
-#define AXFR_OVER_UDP_TEST \
-    /* AXFR over UDP is invalid and should result in FORMERR. */\
-    UnitTestUtil::createRequestMessage(request_message, opcode, default_qid, \
-                         Name("example.com"), RRClass::IN(), \
-                         RRType::AXFR()); \
-    createRequestPacket(request_message, IPPROTO_UDP); \
-    server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
-    EXPECT_TRUE(dnsserv.hasAnswer()); \
-    headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
-                QR_FLAG, 1, 0, 0, 0);
-
-}
-