[svn] commit: r1111 - in /branches/each-nsec3/src: bin/auth/ lib/auth/cpp/ lib/dns/cpp/ lib/dns/cpp/rdata/generic/ lib/dns/cpp/tests/ lib/dns/cpp/tests/testdata/

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Mar 4 19:14:07 UTC 2010


Author: each
Date: Thu Mar  4 19:14:07 2010
New Revision: 1111

Log:
sync libdns, libauth, and b10-auth with recent changes in trunk

Modified:
    branches/each-nsec3/src/bin/auth/auth_srv.cc
    branches/each-nsec3/src/bin/auth/auth_srv.h
    branches/each-nsec3/src/bin/auth/common.cc
    branches/each-nsec3/src/bin/auth/common.h
    branches/each-nsec3/src/bin/auth/main.cc
    branches/each-nsec3/src/lib/auth/cpp/TODO
    branches/each-nsec3/src/lib/auth/cpp/data_source.cc
    branches/each-nsec3/src/lib/auth/cpp/data_source.h
    branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.cc
    branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.h
    branches/each-nsec3/src/lib/auth/cpp/data_source_static.cc
    branches/each-nsec3/src/lib/auth/cpp/data_source_static.h
    branches/each-nsec3/src/lib/auth/cpp/datasrc_unittest.cc
    branches/each-nsec3/src/lib/auth/cpp/query.cc
    branches/each-nsec3/src/lib/auth/cpp/query.h
    branches/each-nsec3/src/lib/auth/cpp/unittest_ds.cc
    branches/each-nsec3/src/lib/auth/cpp/unittest_ds.h
    branches/each-nsec3/src/lib/auth/cpp/unittest_util.h
    branches/each-nsec3/src/lib/dns/cpp/Makefile.am
    branches/each-nsec3/src/lib/dns/cpp/buffer.h
    branches/each-nsec3/src/lib/dns/cpp/dnstime.cc
    branches/each-nsec3/src/lib/dns/cpp/message.cc
    branches/each-nsec3/src/lib/dns/cpp/message.h
    branches/each-nsec3/src/lib/dns/cpp/messagerenderer.h
    branches/each-nsec3/src/lib/dns/cpp/rdata.cc
    branches/each-nsec3/src/lib/dns/cpp/rdata/generic/dnskey_48.cc
    branches/each-nsec3/src/lib/dns/cpp/rdata/generic/ds_43.cc
    branches/each-nsec3/src/lib/dns/cpp/rdata/generic/nsec_47.cc
    branches/each-nsec3/src/lib/dns/cpp/rdata/generic/rrsig_46.cc
    branches/each-nsec3/src/lib/dns/cpp/tests/Makefile.am
    branches/each-nsec3/src/lib/dns/cpp/tests/buffer_unittest.cc
    branches/each-nsec3/src/lib/dns/cpp/tests/message_unittest.cc
    branches/each-nsec3/src/lib/dns/cpp/tests/rdata_nsec_unittest.cc
    branches/each-nsec3/src/lib/dns/cpp/tests/rdata_rrsig_unittest.cc
    branches/each-nsec3/src/lib/dns/cpp/tests/testdata/gen-wiredata.py.in

Modified: branches/each-nsec3/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/each-nsec3/src/bin/auth/auth_srv.cc (original)
+++ branches/each-nsec3/src/bin/auth/auth_srv.cc Thu Mar  4 19:14:07 2010
@@ -12,7 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-// $Id$
+// $Id: auth_srv.cc 1110 2010-03-04 17:57:39Z jinmei $
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -21,8 +21,6 @@
 #include <netdb.h>
 #include <stdlib.h>
 
-#include <algorithm>
-#include <set>
 #include <iostream>
 
 #include <dns/buffer.h>
@@ -34,13 +32,14 @@
 #include <dns/message.h>
 #include <config/ccsession.h>
 
+#include <auth/query.h>
+
 #include <cc/data.h>
 
 #include "common.h"
 #include "auth_srv.h"
 
 #include <boost/lexical_cast.hpp>
-#include <boost/foreach.hpp>
 
 using namespace std;
 
@@ -50,10 +49,13 @@
 using namespace isc::data;
 using namespace isc::config;
 
-AuthSrv::AuthSrv(int port) {
+AuthSrv::AuthSrv(int port) :
+    data_src(NULL), sock(-1)
+{
     int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    if (s < 0)
+    if (s < 0) {
         throw FatalError("failed to open socket");
+    }
 
     struct sockaddr_in sin;
     sin.sin_family = AF_INET;
@@ -65,22 +67,39 @@
     sin.sin_len = sa_len;
 #endif
 
-    if (bind(s, (struct sockaddr *)&sin, sa_len) < 0)
+    if (bind(s, (struct sockaddr *)&sin, sa_len) < 0) {
+        close(s);
         throw FatalError("could not bind socket");
+    }
 
     sock = s;
 
+    // XXX: the following code is not exception-safe.  Will address in the
+    // next phase.
+
+    data_src = new(MetaDataSrc);
+
     // add static data source
-    data_src.addDataSrc(new StaticDataSrc);
+    data_src->addDataSrc(new StaticDataSrc);
 
     // add SQL data source
     Sqlite3DataSrc* sd = new Sqlite3DataSrc;
     sd->init();
-    data_src.addDataSrc(sd);
+    data_src->addDataSrc(sd);
+}
+
+AuthSrv::~AuthSrv()
+{
+    if (sock >= 0) {
+        close(sock);
+    }
+
+    delete data_src;
 }
 
 void
-AuthSrv::processMessage() {
+AuthSrv::processMessage()
+{
     struct sockaddr_storage ss;
     socklen_t sa_len = sizeof(ss);
     struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
@@ -89,7 +108,7 @@
     int cc;
 
     if ((cc = recvfrom(s, recvbuf, sizeof(recvbuf), 0, sa, &sa_len)) > 0) {
-        Message msg;
+        Message msg(Message::PARSE);
         InputBuffer buffer(recvbuf, cc);
 
         try {
@@ -105,17 +124,19 @@
             return;
         }
 
-        QuestionPtr query = *msg.beginQuestion();
+        bool dnssec_ok = msg.isDNSSECSupported();
+        uint16_t remote_bufsize = msg.getUDPSize();
 
         msg.makeResponse();
         msg.setHeaderFlag(MessageFlag::AA());
         msg.setRcode(Rcode::NOERROR());
+        msg.setDNSSECSupported(dnssec_ok);
+        msg.setUDPSize(sizeof(recvbuf));
 
-        // do the DataSource call here
-        Query q = Query(msg, false);
-        data_src.doQuery(q);
+        Query query(msg, dnssec_ok);
+        data_src->doQuery(query);
 
-        OutputBuffer obuffer(4096);
+        OutputBuffer obuffer(remote_bufsize);
         MessageRenderer renderer(obuffer);
         msg.toWire(renderer);
         cout << "sending a response (" <<
@@ -133,7 +154,8 @@
 }
 
 ElementPtr
-AuthSrv::updateConfig(isc::data::ElementPtr new_config) {
+AuthSrv::updateConfig(isc::data::ElementPtr new_config)
+{
     if (new_config) {
         // the ModuleCCSession has already checked if we have
         // the correct ElementPtr type as specified in our .spec file

Modified: branches/each-nsec3/src/bin/auth/auth_srv.h
==============================================================================
--- branches/each-nsec3/src/bin/auth/auth_srv.h (original)
+++ branches/each-nsec3/src/bin/auth/auth_srv.h Thu Mar  4 19:14:07 2010
@@ -12,10 +12,12 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-// $Id$
+// $Id: auth_srv.h 1110 2010-03-04 17:57:39Z jinmei $
 
 #ifndef __AUTH_SRV_H
 #define __AUTH_SRV_H 1
+
+#include <string>
 
 #include <cc/data.h>
 #include <auth/data_source_static.h>
@@ -24,6 +26,7 @@
 class AuthSrv {
 public:
     explicit AuthSrv(int port);
+    ~AuthSrv();
     int getSocket() { return (sock); }
     void processMessage();
     void serve(std::string zone_name);
@@ -31,10 +34,13 @@
     isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
 private:
     std::string _db_file;
-    
-    isc::auth::MetaDataSrc data_src;
+
+    isc::auth::MetaDataSrc* data_src;
     int sock;
 };
 
 #endif // __AUTH_SRV_H
 
+// Local Variables: 
+// mode: c++
+// End: 

Modified: branches/each-nsec3/src/bin/auth/common.cc
==============================================================================
--- branches/each-nsec3/src/bin/auth/common.cc (original)
+++ branches/each-nsec3/src/bin/auth/common.cc Thu Mar  4 19:14:07 2010
@@ -12,7 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-// $Id$
+// $Id: common.cc 1072 2010-03-02 18:42:39Z jinmei $
 #include "common.h"
 #include <iostream>
 

Modified: branches/each-nsec3/src/bin/auth/common.h
==============================================================================
--- branches/each-nsec3/src/bin/auth/common.h (original)
+++ branches/each-nsec3/src/bin/auth/common.h Thu Mar  4 19:14:07 2010
@@ -12,7 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-// $Id$
+// $Id: common.h 1072 2010-03-02 18:42:39Z jinmei $
 
 #ifndef __COMMON_H
 #define __COMMON_H 1

Modified: branches/each-nsec3/src/bin/auth/main.cc
==============================================================================
--- branches/each-nsec3/src/bin/auth/main.cc (original)
+++ branches/each-nsec3/src/bin/auth/main.cc Thu Mar  4 19:14:07 2010
@@ -12,7 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-// $Id$
+// $Id: main.cc 1072 2010-03-02 18:42:39Z jinmei $
 
 #include <sys/types.h>
 #include <sys/socket.h>

Modified: branches/each-nsec3/src/lib/auth/cpp/TODO
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/TODO (original)
+++ branches/each-nsec3/src/lib/auth/cpp/TODO Thu Mar  4 19:14:07 2010
@@ -1,3 +1,20 @@
 - change filenames so we don't have everything starting with "data_source_"?
 - clean up SQL data source code
 - store rdata in the database as binary blobs instead of text
+
+NSEC3:
+- new nsec3 table in SQL schema:
+  id zone_id name (rname?) owner rowner rdata
+
+| add findCoveringNSEC3() API
+- add findCoveringNSEC3() routine, implementing:
+
+          select * from nsec3
+          where rowner <= name.reverse()
+          order by rowner desc
+          limit 1;
+
+- need to determine whether zone is signed nsec or nsec3 -- where?
+
+- add base32
+- add sha-1

Modified: branches/each-nsec3/src/lib/auth/cpp/data_source.cc
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/data_source.cc (original)
+++ branches/each-nsec3/src/lib/auth/cpp/data_source.cc Thu Mar  4 19:14:07 2010
@@ -17,6 +17,8 @@
 #include <iostream>
 #include <vector>
 
+#include <boost/foreach.hpp>
+
 #include <dns/buffer.h>
 #include <dns/message.h>
 #include <dns/name.h>
@@ -27,6 +29,7 @@
 #include <cc/data.h>
 
 #include "data_source.h"
+#include "query.h"
 
 using namespace std;
 using namespace isc::dns;
@@ -71,9 +74,9 @@
 // Synthesize a CNAME answer, for the benefit of clients that don't
 // understand DNAME
 static void
-synthesizeCname(Query& q, QueryTaskPtr task, RRsetPtr rrset, RRsetList& target) {
-    RdataIteratorPtr it;
-    it = rrset->getRdataIterator();
+synthesizeCname(Query& q, QueryTaskPtr task, RRsetPtr rrset, RRsetList& target)
+{
+    RdataIteratorPtr it = rrset->getRdataIterator();
 
     // More than one DNAME RR in the RRset is illegal, so we only have
     // to process the first one.
@@ -102,9 +105,9 @@
 // Add a task to the query task queue to look up the data pointed
 // to by a CNAME record
 static void
-chaseCname(Query& q, QueryTaskPtr task, RRsetPtr rrset) {
-    RdataIteratorPtr it;
-    it = rrset->getRdataIterator();
+chaseCname(Query& q, QueryTaskPtr task, RRsetPtr rrset)
+{
+    RdataIteratorPtr it = rrset->getRdataIterator();
 
     // More than one CNAME RR in the RRset is illegal, so we only have
     // to process the first one.
@@ -113,20 +116,19 @@
         return;
     }
 
-    const Rdata& rd(it->getCurrent());
-    const generic::CNAME& cname = dynamic_cast<const generic::CNAME&>(rd);
-    const Name& target(cname.getCname());
-
-    QueryTaskPtr newtask = QueryTaskPtr(new QueryTask(target, task->qclass,
-                                                      task->qtype,
-                                                      Section::ANSWER(),
-                                                      QueryTask::FOLLOWCNAME)); 
-    q.tasks().push(newtask);
+    q.tasks().push(QueryTaskPtr(
+                       new QueryTask(dynamic_cast<const generic::CNAME&>
+                                     (it->getCurrent()).getCname(),
+                                     task->qclass,
+                                     task->qtype,
+                                     Section::ANSWER(),
+                                     QueryTask::FOLLOWCNAME)));
 }
 
 // Perform the query specified in a QueryTask object
 DataSrc::Result
-doQueryTask(const DataSrc* ds, Query& q, QueryTask& task, RRsetList& target) {
+doQueryTask(const DataSrc* ds, Query& q, QueryTask& task, RRsetList& target)
+{
     switch (task.op) {
     case QueryTask::AUTH_QUERY:
         return (ds->findRRset(q, task.qname, task.qclass, task.qtype,
@@ -152,13 +154,13 @@
 
 // Copy referral information into the authority section of a message
 static inline void
-copyAuth(Query& q, RRsetList& auth) {
-    Message& m = q.message();
+copyAuth(Query& q, RRsetList& auth)
+{
     BOOST_FOREACH(RRsetPtr rrset, auth) {
         if (rrset->getType() == RRType::DNAME()) {
             continue;
         }
-        m.addRRset(Section::AUTHORITY(), rrset, q.wantDnssec());
+        q.message().addRRset(Section::AUTHORITY(), rrset, q.wantDnssec());
         getAdditional(q, rrset);
     }
 }
@@ -166,7 +168,8 @@
 // Query for referrals (i.e., NS/DS or DNAME) at a given name
 static inline bool
 refQuery(const Name& name, Query& q, QueryTaskPtr task,
-         const DataSrc* ds, RRsetList& target) {
+         const DataSrc* ds, RRsetList& target)
+{
     QueryTask newtask(name, q.qclass(), QueryTask::REF_QUERY);
     newtask.zone = task->zone;
 
@@ -188,14 +191,14 @@
 // Match downward, from the zone apex to the query name, looking for
 // referrals.
 static inline bool
-hasDelegation(const DataSrc* ds, Query& q, QueryTaskPtr task) {
-    Message& m = q.message();
+hasDelegation(const DataSrc* ds, Query& q, QueryTaskPtr task)
+{
     int nlen = task->qname.getLabelCount();
     int diff = nlen - task->zone->getLabelCount();
     if (diff > 1) {
         bool found = false;
         RRsetList ref;
-        for(int i = diff; i > 1; i--) {
+        for(int i = diff; i > 1; --i) {
             Name sub(task->qname.split(i - 1, nlen - i));
             if (refQuery(sub, q, task, ds, ref)) {
                 found = true;
@@ -214,13 +217,13 @@
         if (found) {
             if (RRsetPtr r = ref[RRType::DNAME()]) {
                 RRsetList syn;
-                m.addRRset(Section::ANSWER(), r, q.wantDnssec());
-                m.setHeaderFlag(MessageFlag::AA());
+                q.message().addRRset(Section::ANSWER(), r, q.wantDnssec());
+                q.message().setHeaderFlag(MessageFlag::AA());
                 synthesizeCname(q, task, r, syn);
                 if (syn.size() == 1) {
-                    m.addRRset(Section::ANSWER(),
-                               syn[RRType::CNAME()],
-                               q.wantDnssec());
+                    q.message().addRRset(Section::ANSWER(),
+                                         syn[RRType::CNAME()],
+                                         q.wantDnssec());
                     chaseCname(q, task, syn[RRType::CNAME()]);
                     return (true);
                 }
@@ -236,7 +239,7 @@
     // at the actual qname node.)
     if (task->op == QueryTask::AUTH_QUERY &&
         task->state == QueryTask::GETANSWER) {
-        m.setHeaderFlag(MessageFlag::AA());
+        q.message().setHeaderFlag(MessageFlag::AA());
     }
 
     return (false);
@@ -244,7 +247,8 @@
 
 // Attempt a wildcard lookup
 static inline DataSrc::Result
-tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found) {
+tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
+{
     Message& m = q.message();
     DataSrc::Result result;
     found = false;
@@ -265,7 +269,7 @@
     Name star("*");
     uint32_t rflags = 0;
 
-    for(int i = 1; i <= diff; i++) {
+    for (int i = 1; i <= diff; ++i) {
         const Name& wname(star.concatenate(task->qname.split(i, nlen - i)));
         QueryTask newtask(wname, task->qclass, task->qtype,
                           QueryTask::SIMPLE_QUERY); 
@@ -307,8 +311,8 @@
     } else if (q.wantDnssec()) {
         // No wildcard found; add an NSEC to prove it
         RRsetList nsec;
-        QueryTask newtask = QueryTask(*task->zone, task->qclass, RRType::NSEC(),
-                                QueryTask::SIMPLE_QUERY); 
+        QueryTask newtask(*task->zone, task->qclass, RRType::NSEC(),
+                          QueryTask::SIMPLE_QUERY); 
         newtask.zone = task->zone;
         result = doQueryTask(ds, q, newtask, nsec);
         if (result != DataSrc::SUCCESS) {
@@ -327,19 +331,13 @@
 // doQuery: Processes a query.
 // 
 void
-DataSrc::doQuery(Query q) {
-    Result result;
+DataSrc::doQuery(Query& q)
+{
     Message& m = q.message();
     vector<RRsetPtr> additional;
 
-    // XXX: this is for testing purposes; it should be done when 
-    // parsing the message for EDNS0 options
-    q.setWantDnssec(true);
-
     m.clearHeaderFlag(MessageFlag::AA());
     while (!q.tasks().empty()) {
-        RRsetList data;
-
         QueryTaskPtr task = q.tasks().front();
         q.tasks().pop();
 
@@ -353,19 +351,17 @@
         // Find the closest enclosing zone for which we are authoritative,
         // and the concrete data source which is authoritative for it.
         // (Note that RRtype DS queries need to go to the parent.)
-        Name search(".");
-        if (task->qtype == RRType::DS()) {
-            search = task->qname.split(1, task->qname.getLabelCount() - 1);
-        } else {
-            search = task->qname;
-        }
-
-        NameMatch match(search);
+        NameMatch match(task->qtype == RRType::DS() ?
+                        task->qname.split(1, task->qname.getLabelCount() - 1) :
+                        task->qname);
         findClosestEnclosure(match);
-        const DataSrc* ds = match.bestDataSrc();
+        const DataSrc* datasource = match.bestDataSrc();
         const Name* zone = match.closestName();
 
-        if (ds) {
+        RRsetList data;
+        Result result = SUCCESS;
+
+        if (datasource) {
             task->zone = new Name(*zone);
 
             // For these query task types, if there is more than
@@ -373,11 +369,11 @@
             // check the intermediate nodes for referrals.
             if ((task->op == QueryTask::AUTH_QUERY ||
                  task->op == QueryTask::NOGLUE_QUERY) &&
-                  hasDelegation(ds, q, task)) {
+                  hasDelegation(datasource, q, task)) {
                 continue;
             }
 
-            result = doQueryTask(ds, q, *task, data);
+            result = doQueryTask(datasource, q, *task, data);
             if (result != SUCCESS) {
                 m.setRcode(Rcode::SERVFAIL());
                 return;
@@ -386,7 +382,7 @@
             // Query found a referral; let's find out if that was expected--
             // i.e., if an NS was at the zone apex, or if we were querying
             // specifically for the NS, DS or DNAME record.
-            if ((task->flags & REFERRAL) &&
+            if ((task->flags & REFERRAL) != 0 &&
                 (zone->getLabelCount() == task->qname.getLabelCount() ||
                  task->qtype == RRType::NS() ||
                  task->qtype == RRType::DS() ||
@@ -418,7 +414,7 @@
                     // Add the NS records for the enclosing zone to
                     // the authority section.
                     RRsetList auth;
-                    if (! refQuery(Name(*zone), q, task, ds, auth)) {
+                    if (! refQuery(Name(*zone), q, task, datasource, auth)) {
                         m.setRcode(Rcode::SERVFAIL());
                         return;
                     }
@@ -447,7 +443,7 @@
         } else if (result == ERROR || result == NOT_IMPLEMENTED) {
             m.setRcode(Rcode::SERVFAIL());
             return;
-        } else if (task->flags & CNAME_FOUND) {
+        } else if ((task->flags & CNAME_FOUND) != 0) {
             // The qname node contains a CNAME.  Add a new task to the
             // queue to look up its target.
             if (RRsetPtr rrset = data[RRType::CNAME()]) {
@@ -455,12 +451,12 @@
                 chaseCname(q, task, rrset);
             }
             continue;
-        } else if (task->flags & REFERRAL) {
+        } else if ((task->flags & REFERRAL) != 0) {
             // The qname node contains an out-of-zone referral.
             if (task->state == QueryTask::GETANSWER) {
                 RRsetList auth;
                 m.clearHeaderFlag(MessageFlag::AA());
-                if (! refQuery(task->qname, q, task, ds, auth)) {
+                if (! refQuery(task->qname, q, task, datasource, auth)) {
                     m.setRcode(Rcode::SERVFAIL());
                     return;
                 }
@@ -478,7 +474,7 @@
                 }
             } 
             continue;
-        } else if (task->flags & NO_SUCH_ZONE) {
+        } else if ((task->flags & NO_SUCH_ZONE) != 0) {
             // No such zone.  If we're chasing cnames or adding additional
             // data, that's okay, but if doing an original query, return
             // REFUSED.
@@ -487,13 +483,13 @@
                 return;
             }
             continue;
-        } else if (task->flags & (NAME_NOT_FOUND|TYPE_NOT_FOUND)) {
+        } else if ((task->flags & (NAME_NOT_FOUND|TYPE_NOT_FOUND)) != 0) {
             // No data found at this qname/qtype.
             // If we were looking for answer data, not additional,
             // and the name was not found, we need to find out whether
             // there are any relevant wildcards.
             bool wildcard_found = false;
-            result = tryWildcard(q, task, ds, wildcard_found);
+            result = tryWildcard(q, task, datasource, wildcard_found);
             if (result != SUCCESS) {
                 m.setRcode(Rcode::SERVFAIL());
                 return;
@@ -511,8 +507,9 @@
             // section.  For TYPE_NOT_FOUND, do not set an error rcode,
             // and send the current NSEC in the authority section.
             Name nsecname(task->qname);
-            if (task->flags & NAME_NOT_FOUND) {
-                ds->findPreviousName(q, task->qname, nsecname, task->zone);
+            if ((task->flags & NAME_NOT_FOUND) != 0) {
+                datasource->findPreviousName(q, task->qname, nsecname,
+                                             task->zone);
             }
 
             if (task->state == QueryTask::GETANSWER) {
@@ -524,7 +521,7 @@
                 QueryTask newtask(Name(*zone), task->qclass, RRType::SOA(), 
                                   QueryTask::SIMPLE_QUERY); 
                 newtask.zone = task->zone;
-                result = doQueryTask(ds, q, newtask, soa);
+                result = doQueryTask(datasource, q, newtask, soa);
                 if (result != SUCCESS || newtask.flags != 0) {
                     m.setRcode(Rcode::SERVFAIL());
                     return;
@@ -536,11 +533,10 @@
 
             if (q.wantDnssec()) {
                 RRsetList nsec;
-                QueryTask newtask = QueryTask(nsecname, task->qclass,
-                                              RRType::NSEC(), 
-                                              QueryTask::SIMPLE_QUERY); 
+                QueryTask newtask(nsecname, task->qclass,
+                                  RRType::NSEC(), QueryTask::SIMPLE_QUERY);  
                 newtask.zone = task->zone;
-                result = doQueryTask(ds, q, newtask, nsec);
+                result = doQueryTask(datasource, q, newtask, nsec);
                 if (result != SUCCESS) {
                     m.setRcode(Rcode::SERVFAIL());
                     return;
@@ -577,5 +573,118 @@
     }
 }
 
-}
-}
+DataSrc::Result
+DataSrc::findAddrs(const Query& q, const Name& qname, const RRClass& qclass,
+                   RRsetList& target, uint32_t& flags, Name* zone) const
+{
+    Result r;
+    bool a = false, aaaa = false;
+
+    flags = 0;
+    r = findExactRRset(q, qname, qclass, RRType::A(), target, flags, zone);
+    if (r == SUCCESS && flags == 0) {
+        a = true;
+    }
+
+    flags = 0;
+    r = findExactRRset(q, qname, qclass, RRType::AAAA(), target, flags, zone);
+    if (r == SUCCESS && flags == 0) {
+        aaaa = true;
+    }
+
+    if (!a && !aaaa) {
+        flags = TYPE_NOT_FOUND;
+    } else {
+        flags = 0;
+    }
+
+    return (SUCCESS);
+}
+
+DataSrc::Result
+DataSrc::findReferral(const Query& q, const Name& qname, const RRClass& qclass,
+                      RRsetList& target, uint32_t& flags, Name* zone) const
+{
+    Result r;
+    bool ns = false, ds = false, dname = false;
+
+    flags = 0;
+    r = findExactRRset(q, qname, qclass, RRType::NS(), target, flags, zone);
+    if (r == SUCCESS && flags == 0) {
+        ns = true;
+    } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
+        return (SUCCESS);
+    }
+
+    flags = 0;
+    r = findExactRRset(q, qname, qclass, RRType::DS(), target, flags, zone);
+    if (r == SUCCESS && flags == 0) {
+        ds = true;
+    } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
+        return (SUCCESS);
+    }
+
+    flags = 0;
+    r = findExactRRset(q, qname, qclass, RRType::DNAME(), target, flags, zone);
+    if (r == SUCCESS && flags == 0) {
+        dname = true;
+    } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
+        return (SUCCESS);
+    }
+
+    if (!ns && !dname && !ds) {
+        flags = TYPE_NOT_FOUND;
+    } else {
+        flags = 0;
+    }
+
+    return (SUCCESS);
+}
+
+void
+MetaDataSrc::addDataSrc(DataSrc* ds)
+{
+    if (getClass() != RRClass::ANY() && ds->getClass() != getClass()) {
+        dns_throw(Unexpected, "class mismatch");
+    }
+
+    data_sources.push_back(ds);
+}
+
+void
+MetaDataSrc::findClosestEnclosure(NameMatch& match) const
+{
+    BOOST_FOREACH (DataSrc* ds, data_sources) {
+        if (getClass() != RRClass::ANY() && ds->getClass() != getClass()) {
+            continue;
+        }
+
+        ds->findClosestEnclosure(match);
+    }
+}
+
+NameMatch::~NameMatch()
+{
+    delete closest_name_;
+}
+
+void
+NameMatch::update(const DataSrc& new_source, const Name& container)
+{
+    if (closest_name_ == NULL) {
+        closest_name_ = new Name(container);
+        best_source_ = &new_source;
+        return;
+    }
+
+    if (container.compare(*closest_name_).getRelation() ==
+        NameComparisonResult::SUBDOMAIN) {
+        Name* newname = new Name(container);
+        delete closest_name_;
+        closest_name_ = newname;
+        best_source_ = &new_source;
+    }
+}
+
+}
+}

Modified: branches/each-nsec3/src/lib/auth/cpp/data_source.h
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/data_source.h (original)
+++ branches/each-nsec3/src/lib/auth/cpp/data_source.h Thu Mar  4 19:14:07 2010
@@ -17,23 +17,45 @@
 #ifndef __DATA_SOURCE_H
 #define __DATA_SOURCE_H
 
-#include <boost/foreach.hpp>
+#include <vector>
+
 #include <dns/name.h>
-#include <dns/rrset.h>
-#include <dns/rrsetlist.h>
-#include <auth/query.h>
-#include <iostream>
-
-using namespace isc::dns;
+#include <dns/rrclass.h>
 
 namespace isc {
+
+namespace dns {
+class Name;
+class RRType;
+class RRset;
+class RRsetList;
+}
+
 namespace auth {
 
-class DataSrc;
 class NameMatch;
+class Query;
 
 class AbstractDataSrc {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private to make it explicit that this is a pure base class.
+private:
+    AbstractDataSrc(const AbstractDataSrc& source);
+    AbstractDataSrc& operator=(const AbstractDataSrc& source);
+protected:
+    /// \brief The default constructor.
+    ///
+    /// This is intentionally defined as \c protected as this base class should
+    /// never be instantiated (except as part of a derived class).
+    AbstractDataSrc() {}
 public:
+    /// \brief The destructor.
+    virtual ~AbstractDataSrc() {};
+    //@}
+
     enum Result {
         SUCCESS,
         ERROR,
@@ -55,11 +77,9 @@
         NO_SUCH_ZONE = 0x10
     };
 
-    virtual ~AbstractDataSrc() {};
-
     // 'High-level' methods.  These will be implemented by the
     // general DataSrc class, and SHOULD NOT be overwritten by subclasses.
-    virtual void doQuery(Query query) = 0;
+    virtual void doQuery(Query& query) = 0;
 
     // XXX: High-level methods to be implemented later:
     // virtual void doUpdate(Update update) = 0;
@@ -77,185 +97,131 @@
     // Mandatory 'low-level' methods: These will NOT be implemented by
     // the general DataSrc class; subclasses MUST implement them.
     virtual Result findRRset(const Query& q,
-                             const Name& qname,
-                             const RRClass& qclass,
-                             const RRType& qtype,
-                             RRsetList& target,
+                             const isc::dns::Name& qname,
+                             const isc::dns::RRClass& qclass,
+                             const isc::dns::RRType& qtype,
+                             isc::dns::RRsetList& target,
                              uint32_t& flags,
-                             Name* zone = NULL) const = 0;
+                             isc::dns::Name* zone = NULL) const = 0;
 
     virtual Result findExactRRset(const Query& q,
-                                  const Name& qname,
-                                  const RRClass& qclass,
-                                  const RRType& qtype,
-                                  RRsetList& target,
+                                  const isc::dns::Name& qname,
+                                  const isc::dns::RRClass& qclass,
+                                  const isc::dns::RRType& qtype,
+                                  isc::dns::RRsetList& target,
                                   uint32_t& flags,
-                                  Name* zone = NULL) const = 0;
+                                  isc::dns::Name* zone = NULL) const = 0;
 
     // These will have dumb implementations in the general DataSrc
     // class, and SHOULD be overwritten by subclasses.
     virtual Result findAddrs(const Query& q,
-                             const Name& qname,
-                             const RRClass& qclass,
-                             RRsetList& target,
+                             const isc::dns::Name& qname,
+                             const isc::dns::RRClass& qclass,
+                             isc::dns::RRsetList& target,
                              uint32_t& flags,
-                             Name* zone = NULL) const = 0;
+                             isc::dns::Name* zone = NULL) const = 0;
 
      virtual Result findReferral(const Query& q,
-                                const Name& qname,
-                                const RRClass& qclass,
-                                RRsetList& target,
+                                const isc::dns::Name& qname,
+                                const isc::dns::RRClass& qclass,
+                                isc::dns::RRsetList& target,
                                 uint32_t& flags,
-                                Name* zone = NULL) const = 0;
+                                isc::dns::Name* zone = NULL) const = 0;
 
     // This MUST be implemented by concrete data sources which support
     // DNSSEC, but is optional for others (e.g., the static data source).
     virtual Result findPreviousName(const Query& q,
-                                    const Name& qname,
-                                    Name& target,
-                                    Name* zone) const = 0;
+                                    const isc::dns::Name& qname,
+                                    isc::dns::Name& target,
+                                    isc::dns::Name* zone) const = 0;
 
 };
 
 // Base class for a DNS Data Source
 class DataSrc : public AbstractDataSrc {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+private:
+    DataSrc(const DataSrc& source);
+    DataSrc& operator=(const DataSrc& source);
 public:
-    DataSrc() : rrclass(RRClass::IN()) {}
-    DataSrc(const RRClass& c) : rrclass(c) {}
+    DataSrc() : rrclass(isc::dns::RRClass::IN()) {}
+    DataSrc(const isc::dns::RRClass& c) : rrclass(c) {}
+    /// \brief The destructor.
     virtual ~DataSrc() {};
-
-    void doQuery(Query q);
+    //@}
+
+    virtual void doQuery(Query& q);
 
     virtual void findClosestEnclosure(NameMatch& match) const = 0;
 
-    const RRClass& getClass() const { return rrclass; }
-    void setClass(RRClass& c) { rrclass = c; }
-    void setClass(const RRClass& c) { rrclass = c; }
+    const isc::dns::RRClass& getClass() const { return rrclass; }
+    void setClass(isc::dns::RRClass& c) { rrclass = c; }
+    void setClass(const isc::dns::RRClass& c) { rrclass = c; }
 
     Result init() { return NOT_IMPLEMENTED; }
     Result close() { return NOT_IMPLEMENTED; }
 
     virtual Result findRRset(const Query& q,
-                             const Name& qname,
-                             const RRClass& qclass,
-                             const RRType& qtype,
-                             RRsetList& target,
+                             const isc::dns::Name& qname,
+                             const isc::dns::RRClass& qclass,
+                             const isc::dns::RRType& qtype,
+                             isc::dns::RRsetList& target,
                              uint32_t& flags,
-                             Name* zone = NULL) const = 0;
+                             isc::dns::Name* zone = NULL) const = 0;
 
     virtual Result findExactRRset(const Query& q,
-                                  const Name& qname,
-                                  const RRClass& qclass,
-                                  const RRType& qtype,
-                                  RRsetList& target,
+                                  const isc::dns::Name& qname,
+                                  const isc::dns::RRClass& qclass,
+                                  const isc::dns::RRType& qtype,
+                                  isc::dns::RRsetList& target,
                                   uint32_t& flags,
-                                  Name* zone = NULL) const = 0;
+                                  isc::dns::Name* zone = NULL) const = 0;
 
     virtual Result findAddrs(const Query& q,
-                               const Name& qname,
-                               const RRClass& qclass,
-                               RRsetList& target,
+                               const isc::dns::Name& qname,
+                               const isc::dns::RRClass& qclass,
+                               isc::dns::RRsetList& target,
                                uint32_t& flags,
-                               Name* zone = NULL) const {
-        Result r;
-        bool a = false, aaaa = false;
-
-        flags = 0;
-        r = findExactRRset(q, qname, qclass, RRType::A(), target, flags, zone);
-        if (r == SUCCESS && flags == 0) {
-            a = true;
-        }
-
-        flags = 0;
-        r = findExactRRset(q, qname, qclass, RRType::AAAA(), target,
-                           flags, zone);
-        if (r == SUCCESS && flags == 0) {
-            aaaa = true;
-        }
-
-        if (!a && !aaaa) {
-            flags = TYPE_NOT_FOUND;
-        } else {
-            flags = 0;
-        }
-
-        return (SUCCESS);
-    }
+                             isc::dns::Name* zone = NULL) const;
 
     virtual Result findReferral(const Query& q,
-                                const Name& qname,
-                                const RRClass& qclass,
-                                RRsetList& target,
+                                const isc::dns::Name& qname,
+                                const isc::dns::RRClass& qclass,
+                                isc::dns::RRsetList& target,
                                 uint32_t& flags,
-                                Name* zone = NULL) const {
-        Result r;
-        bool ns = false, ds = false, dname = false;
-
-        flags = 0;
-        r = findExactRRset(q, qname, qclass, RRType::NS(), target, flags, zone);
-        if (r == SUCCESS && flags == 0) {
-            ns = true;
-        } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
-            return (SUCCESS);
-        }
-
-        flags = 0;
-        r = findExactRRset(q, qname, qclass, RRType::DS(), target, flags, zone);
-        if (r == SUCCESS && flags == 0) {
-            ds = true;
-        } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
-            return (SUCCESS);
-        }
-
-        flags = 0;
-        r = findExactRRset(q, qname, qclass, RRType::DNAME(), target,
-                           flags, zone);
-        if (r == SUCCESS && flags == 0) {
-            dname = true;
-        } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
-            return (SUCCESS);
-        }
-
-        if (!ns && !dname && !ds) {
-            flags = TYPE_NOT_FOUND;
-        } else {
-            flags = 0;
-        }
-
-        return (SUCCESS);
-    }
+                                isc::dns::Name* zone = NULL) const;
 
     virtual Result findPreviousName(const Query& q,
-                                    const Name& qname,
-                                    Name& target,
-                                    Name* zone) const = 0;
-private:
-    RRClass rrclass;
+                                    const isc::dns::Name& qname,
+                                    isc::dns::Name& target,
+                                    isc::dns::Name* zone) const = 0;
+private:
+    isc::dns::RRClass rrclass;
 };
 
 class MetaDataSrc : public DataSrc {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+    //@{
+private:
+    MetaDataSrc(const MetaDataSrc& source);
+    MetaDataSrc& operator=(const MetaDataSrc& source);
 public:
-    MetaDataSrc() : DataSrc(RRClass::ANY()) {}
-    MetaDataSrc(const RRClass& c) : DataSrc(c) {}
+    MetaDataSrc() : DataSrc(isc::dns::RRClass::ANY()) {}
+    MetaDataSrc(const isc::dns::RRClass& c) : DataSrc(c) {}
+    /// \brief The destructor.
     virtual ~MetaDataSrc() {}
-
-    void addDataSrc(DataSrc* ds) {
-        if (getClass() != RRClass::ANY() && ds->getClass() != getClass()) {
-            dns_throw(Unexpected, "class mismatch");
-        }
-
-        data_sources.push_back(ds);
-    }
-
-    void findClosestEnclosure(NameMatch& match) const {
-        BOOST_FOREACH (DataSrc* ds, data_sources) {
-            if (getClass() != RRClass::ANY() && ds->getClass() != getClass()) {
-                continue;
-            }
-
-            ds->findClosestEnclosure(match);
-        }
-    }
+    //@}
+
+    void addDataSrc(DataSrc* ds);
+    void findClosestEnclosure(NameMatch& match) const;
 
     // Actual queries for data should not be sent to a MetaDataSrc object,
     // so we return NOT_IMPLEMENTED if we receive any.
@@ -264,38 +230,45 @@
     // to get a pointer to the best concrete data source for the specified
     // zone, then send all queries directly to that data source.
 
-    Result findRRset(const Query& q, const Name& qname,
-                     const RRClass& qclass, const RRType& qtype,
-                     RRsetList& target, uint32_t& flags,
-                     Name* zone = NULL) const {
-        return (NOT_IMPLEMENTED);
-    }
-
-    Result findExactRRset(const Query& q, const Name& qname,
-                          const RRClass& qclass, const RRType& qtype,
-                          RRsetList& target, uint32_t& flags,
-                          Name* zone = NULL) const {
-        return (NOT_IMPLEMENTED);
-    }
-
-    Result findAddrs(const Query& q,
-                     const Name& qname, const RRClass& qclass,
-                     RRsetList& target, uint32_t& flags,
-                     Name* zone = NULL) const {
-        return (NOT_IMPLEMENTED);
-    }
-
-    Result findReferral(const Query& q,
-                        const Name& qname, const RRClass& qclass,
-                        RRsetList& target, uint32_t& flags,
-                        Name* zone = NULL) const {
+    Result findRRset(const Query& q, const isc::dns::Name& qname,
+                     const isc::dns::RRClass& qclass,
+                     const isc::dns::RRType& qtype,
+                     isc::dns::RRsetList& target, uint32_t& flags,
+                     isc::dns::Name* zone = NULL) const
+    {
+        return (NOT_IMPLEMENTED);
+    }
+
+    Result findExactRRset(const Query& q, const isc::dns::Name& qname,
+                          const isc::dns::RRClass& qclass,
+                          const isc::dns::RRType& qtype,
+                          isc::dns::RRsetList& target, uint32_t& flags,
+                          isc::dns::Name* zone = NULL) const
+    {
+        return (NOT_IMPLEMENTED);
+    }
+
+    Result findAddrs(const Query& q, const isc::dns::Name& qname,
+                     const isc::dns::RRClass& qclass,
+                     isc::dns::RRsetList& target, uint32_t& flags,
+                     isc::dns::Name* zone = NULL) const
+    {
+        return (NOT_IMPLEMENTED);
+    }
+
+    Result findReferral(const Query& q, const isc::dns::Name& qname,
+                        const isc::dns::RRClass& qclass,
+                        isc::dns::RRsetList& target, uint32_t& flags,
+                        isc::dns::Name* zone = NULL) const
+    {
         return (NOT_IMPLEMENTED);
     }
 
     virtual Result findPreviousName(const Query& q,
-                                    const Name& qname,
-                                    Name& target,
-                                    Name* zone) const {
+                                    const isc::dns::Name& qname,
+                                    isc::dns::Name& target,
+                                    isc::dns::Name* zone) const
+    {
         return (NOT_IMPLEMENTED);
     }
 
@@ -305,39 +278,20 @@
 
 class NameMatch {
 public:
-    NameMatch(const Name& qname) :
+    NameMatch(const isc::dns::Name& qname) :
         closest_name_(NULL), best_source_(NULL), qname_(qname) {}
-
-    ~NameMatch() {
-        delete closest_name_;
-    }
-
-    void update(const DataSrc& new_source, const Name& container) {
-        if (closest_name_ == NULL) {
-            closest_name_ = new Name(container);
-            best_source_ = &new_source;
-            return;
-        }
-
-        NameComparisonResult::NameRelation cmp = 
-            container.compare(*closest_name_).getRelation();
-
-        if (cmp == NameComparisonResult::SUBDOMAIN) {
-            Name* newname = new Name(container);
-            delete closest_name_;
-            closest_name_ = newname;
-            best_source_ = &new_source;
-        }
-    }
-
-    const Name& qname() { return (qname_); }
-    const Name* closestName() { return (closest_name_); }
+    ~NameMatch();
+
+    void update(const DataSrc& new_source, const isc::dns::Name& container);
+
+    const isc::dns::Name& qname() { return (qname_); }
+    const isc::dns::Name* closestName() { return (closest_name_); }
     const DataSrc* bestDataSrc() { return (best_source_); }
 
 private:
-    const Name* closest_name_;
+    const isc::dns::Name* closest_name_;
     const DataSrc* best_source_;
-    const Name& qname_;
+    const isc::dns::Name qname_;
 };
 
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.cc
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.cc (original)
+++ branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.cc Thu Mar  4 19:14:07 2010
@@ -34,7 +34,8 @@
 //  Prepare a statement.  Can call release() or sqlite3_finalize()
 //  directly.
 //
-sqlite3_stmt* Sqlite3DataSrc::prepare(const char *statement) {
+sqlite3_stmt* Sqlite3DataSrc::prepare(const char *statement)
+{
     int rc;
     sqlite3_stmt *prepared = NULL;
 
@@ -55,7 +56,8 @@
 //
 //  Get the database schema version.
 //
-int Sqlite3DataSrc::getVersion(void) {
+int Sqlite3DataSrc::getVersion(void)
+{
     if (database_version == -1) {
         loadVersion();
     }
@@ -66,7 +68,8 @@
 //  Find the exact zone match.  Return -1 if not found, or the zone's
 //  ID if found.  This will always be >= 0 if found.
 //
-int Sqlite3DataSrc::hasExactZone(const char *name) const {
+int Sqlite3DataSrc::hasExactZone(const char* name) const
+{
     int rc, i;
     sqlite3_reset(q_zone);
     rc = sqlite3_bind_text(q_zone, 1, name, -1, SQLITE_STATIC);
@@ -263,7 +266,8 @@
 //  >= 0 if found.  If position is not NULL, it will be filled in with the
 //  longest match found.
 //
-int Sqlite3DataSrc::findClosest(const char *name, const char **position) const {
+int Sqlite3DataSrc::findClosest(const char *name, const char **position) const
+{
     int rc;
     const char *current = name;
     
@@ -286,7 +290,9 @@
     return (-1);
 }
 
-void Sqlite3DataSrc::loadVersion(void) {
+void
+Sqlite3DataSrc::loadVersion(void)
+{
     int rc;
 
     const char *q = "SELECT version FROM schema_version";
@@ -299,49 +305,51 @@
     release(prepared);
 }
 
-void Sqlite3DataSrc::setupPreparedStatements(void) {
-
-    const char *q_zone_str = "SELECT id FROM zones WHERE name=?1";
+void
+Sqlite3DataSrc::setupPreparedStatements(void)
+{
+
+    const char* q_zone_str = "SELECT id FROM zones WHERE name=?1";
     try {
         q_zone = prepare(q_zone_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_zone_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
     }
 
-    const char *q_record_str = "SELECT rdtype, ttl, sigtype, rdata "
+    const char* q_record_str = "SELECT rdtype, ttl, sigtype, rdata "
                                "FROM records WHERE zone_id=?1 AND name=?2 AND "
                                "((rdtype=?3 OR sigtype=?3) OR "
                                "(rdtype='CNAME' OR sigtype='CNAME') OR "
                                "(rdtype='NS' OR sigtype='NS'))";
     try {
         q_record = prepare(q_record_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_record_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
     }
 
-    const char *q_addrs_str = "SELECT rdtype, ttl, sigtype, rdata "
+    const char* q_addrs_str = "SELECT rdtype, ttl, sigtype, rdata "
                                "FROM records WHERE zone_id=?1 AND name=?2 AND "
                                "(rdtype='A' OR sigtype='A' OR "
                                "rdtype='AAAA' OR sigtype='AAAA')";
     try {
         q_addrs = prepare(q_addrs_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_addrs_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
     }
-    const char *q_referral_str = "SELECT rdtype, ttl, sigtype, rdata FROM "
+    const char* q_referral_str = "SELECT rdtype, ttl, sigtype, rdata FROM "
                                  "records WHERE zone_id=?1 AND name=?2 AND"
                                  "(rdtype='NS' OR sigtype='NS' OR "
                                  "rdtype='DS' OR sigtype='DS' OR "
                                  "rdtype='DNAME' OR sigtype='DNAME')";
     try {
         q_referral = prepare(q_referral_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_referral_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
@@ -350,29 +358,29 @@
                              "FROM records WHERE zone_id=?1 AND name=?2";
     try {
         q_any = prepare(q_any_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_any_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
     }
 
-    const char *q_count_str = "SELECT COUNT(*) FROM records "
+    const char* q_count_str = "SELECT COUNT(*) FROM records "
                               "WHERE zone_id=?1 AND (name=?2 OR "
                               "name LIKE '%.' || ?2);";
     try {
         q_count = prepare(q_count_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_count_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
     }
 
-    const char *q_previous_str = "SELECT name FROM records "
+    const char* q_previous_str = "SELECT name FROM records "
                                  "WHERE zone_id=?1 AND rdtype = 'NSEC' AND "
                                  "rname < $2 ORDER BY rname DESC LIMIT 1";
     try {
         q_previous = prepare(q_previous_str);
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl << q_previous_str << endl;
         cout << sqlite3_errmsg(db) << endl;
         throw(e);
@@ -380,7 +388,9 @@
 
 }
 
-void Sqlite3DataSrc::execSetupQuery(const char *query) {
+void
+Sqlite3DataSrc::execSetupQuery(const char *query)
+{
     int rc;
 
     rc = sqlite3_exec(db, query, NULL, NULL, NULL);
@@ -389,7 +399,9 @@
     }
 }
 
-void Sqlite3DataSrc::checkAndSetupSchema(void) {
+void
+Sqlite3DataSrc::checkAndSetupSchema(void)
+{
     try {
         loadVersion();
         setupPreparedStatements();
@@ -446,7 +458,7 @@
         open("/tmp/zone.sqlite3");
     
         cout << "Schema version: " << getVersion() << endl;
-    } catch (const char *e) {
+    } catch (const char* e) {
         cout << e << endl;
     }
 
@@ -454,7 +466,8 @@
 }
 
 void
-Sqlite3DataSrc::findClosestEnclosure(NameMatch& match) const {
+Sqlite3DataSrc::findClosestEnclosure(NameMatch& match) const
+{
     const Name& qname = match.qname();
     const string target_string = qname.toText();
     const char *position = NULL;
@@ -473,14 +486,14 @@
                                  Name& target,
                                  Name* zone) const
 {
-    const char *c_rname = qname.reverse().toText().c_str();
+    const char* c_rname = qname.reverse().toText().c_str();
 
     int zone_id;
     if (zone == NULL) {
-        const char *c_name = qname.toText().c_str();
+        const char* c_name = qname.toText().c_str();
         zone_id = findClosest(c_name, NULL);
     } else {
-        const char *c_zone = zone->toText().c_str();
+        const char* c_zone = zone->toText().c_str();
         zone_id = findClosest(c_zone, NULL);
     }
 
@@ -554,18 +567,20 @@
                           const RRClass& qclass,
                           RRsetList& target,
                           uint32_t& flags,
-                          Name* zone) const {
+                          Name* zone) const
+{
     findRecords(qname, RRType::ANY(), target, zone, ADDRESS, flags);
     return (SUCCESS);
 }
 
 DataSrc::Result
 Sqlite3DataSrc::findReferral(const Query& q,
-                            const Name& qname,
-                            const RRClass& qclass,
-                            RRsetList& target,
-                            uint32_t& flags,
-                            Name* zone) const {
+                             const Name& qname,
+                             const RRClass& qclass,
+                             RRsetList& target,
+                             uint32_t& flags,
+                             Name* zone) const
+{
     findRecords(qname, RRType::ANY(), target, zone, DELEGATION, flags);
     return (SUCCESS);
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.h
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.h (original)
+++ branches/each-nsec3/src/lib/auth/cpp/data_source_sqlite3.h Thu Mar  4 19:14:07 2010
@@ -14,59 +14,79 @@
 
 // $Id$
 
-#ifndef __SQLITE3_DATA_SOURCE_H
-#define __SQLITE3_DATA_SOURCE_H
+#ifndef __DATA_SOURCE_SQLITE3_H
+#define __DATA_SOURCE_SQLITE3_H
+
+#include <string>
 
 #include <sqlite3.h>
 
 #include "data_source.h"
 
-using namespace isc::dns;
+namespace isc {
 
-namespace isc {
+namespace dns {
+class Name;
+class RRClass;
+class RRType;
+class RRsetList;
+}
+
 namespace auth {
 
+class Query;
+
 class Sqlite3DataSrc : public DataSrc {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+    //@{
+private:
+    Sqlite3DataSrc(const Sqlite3DataSrc& source);
+    Sqlite3DataSrc& operator=(const Sqlite3DataSrc& source);
 public:
     Sqlite3DataSrc();
     virtual ~Sqlite3DataSrc();
+    //@}
 
     virtual void findClosestEnclosure(NameMatch& match) const;
 
     virtual Result findRRset(const Query& q,
-                             const Name& qname,
-                             const RRClass& qclass,
-                             const RRType& qtype,
-                             RRsetList& target,
+                             const isc::dns::Name& qname,
+                             const isc::dns::RRClass& qclass,
+                             const isc::dns::RRType& qtype,
+                             isc::dns::RRsetList& target,
                              uint32_t& flags,
-                             Name* zone = NULL) const;
+                             isc::dns::Name* zone = NULL) const;
 
     virtual Result findExactRRset(const Query& q,
-                                  const Name& qname,
-                                  const RRClass& qclass,
-                                  const RRType& qtype,
-                                  RRsetList& target,
+                                  const isc::dns::Name& qname,
+                                  const isc::dns::RRClass& qclass,
+                                  const isc::dns::RRType& qtype,
+                                  isc::dns::RRsetList& target,
                                   uint32_t& flags,
-                                  Name* zone = NULL) const;
+                                  isc::dns::Name* zone = NULL) const;
 
     virtual Result findAddrs(const Query& q,
-                               const Name& qname,
-                               const RRClass& qclass,
-                               RRsetList& target,
+                               const isc::dns::Name& qname,
+                               const isc::dns::RRClass& qclass,
+                               isc::dns::RRsetList& target,
                                uint32_t& flags,
-                               Name* zone = NULL) const;
+                               isc::dns::Name* zone = NULL) const;
 
     virtual Result findReferral(const Query& q,
-                                const Name& qname,
-                                const RRClass& qclass,
-                                RRsetList& target,
+                                const isc::dns::Name& qname,
+                                const isc::dns::RRClass& qclass,
+                                isc::dns::RRsetList& target,
                                 uint32_t& flags,
-                                Name* zone = NULL) const;
+                                isc::dns::Name* zone = NULL) const;
 
     virtual DataSrc::Result findPreviousName(const Query& q,
-                                             const Name& qname,
-                                             Name& target,
-                                             Name* zone) const;
+                                             const isc::dns::Name& qname,
+                                             isc::dns::Name& target,
+                                             isc::dns::Name* zone) const;
 
     virtual Result init();
     virtual Result close();
@@ -83,8 +103,8 @@
     void release(sqlite3_stmt* prepared);
     int getVersion(void);
     int hasExactZone(const char *name) const;
-    int findRecords(const Name& name, const RRType& rdtype,
-                    RRsetList& target, Name* zone,
+    int findRecords(const isc::dns::Name& name, const isc::dns::RRType& rdtype,
+                    isc::dns::RRsetList& target, isc::dns::Name* zone,
                     const Mode mode, uint32_t& flags) const;
     int findClosest(const char *name, const char **position) const;
     void loadVersion(void);
@@ -111,7 +131,7 @@
 }
 }
 
-#endif // __SQLITE3_DATA_SOURCE_H
+#endif // __DATA_SOURCE_SQLITE3_H
 
 // Local Variables: 
 // mode: c++

Modified: branches/each-nsec3/src/lib/auth/cpp/data_source_static.cc
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/data_source_static.cc (original)
+++ branches/each-nsec3/src/lib/auth/cpp/data_source_static.cc Thu Mar  4 19:14:07 2010
@@ -14,17 +14,16 @@
 
 // $Id$
 
-#include "data_source_static.h"
-
 #include <dns/name.h>
-#include <dns/rdata.h>
 #include <dns/rdataclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrset.h>
+#include <dns/rrsetlist.h>
 #include <dns/rrtype.h>
 #include <dns/rrttl.h>
 
-#include <iostream>
+#include "data_source.h"
+#include "data_source_static.h"
 
 using namespace std;
 using namespace isc::dns;
@@ -33,36 +32,62 @@
 namespace isc {
 namespace auth {
 
-StaticDataSrc::StaticDataSrc() : authors_name("authors.bind"),
-                                 version_name("version.bind")
+// There's no mutable internal state in StaticDataSrcImpl, so define it
+// as a struct.
+
+namespace {
+
+// All data in this class is literally static and can be generated at
+// initialization time (and won't be changed).  Names can be statically
+// initialized.  For RRsets, a helper class (StaticDataInitializer) and its
+// only instance will be used for initialization.
+const Name authors_name("authors.bind");
+const Name version_name("version.bind");
+// XXX: unfortunately these can't be RRsetPtr because they'll be passed to
+// RRsetList::addRRset(), which expect non const RRsetPtr.  We should revisit
+// this design later.
+RRsetPtr authors;
+RRsetPtr authors_ns;
+RRsetPtr version;
+RRsetPtr version_ns;
+
+class StaticDataInitializer {
+public:
+    StaticDataInitializer()
+    {
+        authors = RRsetPtr(new RRset(authors_name, RRClass::CH(),
+                                     RRType::TXT(), RRTTL(0)));
+        authors->addRdata(generic::TXT("Evan Hunt"));
+        authors->addRdata(generic::TXT("Han Feng"));
+        authors->addRdata(generic::TXT("Jelte Jansen"));
+        authors->addRdata(generic::TXT("Jeremy C. Reed")); 
+        authors->addRdata(generic::TXT("Jin Jian"));
+        authors->addRdata(generic::TXT("JINMEI Tatuya"));
+        authors->addRdata(generic::TXT("Kazunori Fujiwara"));
+        authors->addRdata(generic::TXT("Michael Graff"));
+        authors->addRdata(generic::TXT("Naoki Kambe"));
+        authors->addRdata(generic::TXT("Shane Kerr"));
+        authors->addRdata(generic::TXT("Zhang Likun"));
+
+        authors_ns = RRsetPtr(new RRset(authors_name, RRClass::CH(),
+                                        RRType::NS(), RRTTL(0)));
+        authors_ns->addRdata(generic::NS(authors_name));
+
+        version = RRsetPtr(new RRset(version_name, RRClass::CH(),
+                                     RRType::TXT(), RRTTL(0)));
+        version->addRdata(generic::TXT("BIND10 0.0.0 (pre-alpha)"));
+
+        version_ns = RRsetPtr(new RRset(version_name, RRClass::CH(),
+                                        RRType::NS(), RRTTL(0)));
+        version_ns->addRdata(generic::NS(version_name));
+    }
+};
+const StaticDataInitializer initialier_object;
+}
+
+StaticDataSrc::StaticDataSrc()
 {
     setClass(RRClass::CH());
-
-    authors = RRsetPtr(new RRset(authors_name, RRClass::CH(),
-                                          RRType::TXT(), RRTTL(0)));
-    authors->addRdata(generic::TXT("Evan Hunt"));
-    authors->addRdata(generic::TXT("Han Feng"));
-    authors->addRdata(generic::TXT("Jelte Jansen"));
-    authors->addRdata(generic::TXT("Jeremy C. Reed")); 
-    authors->addRdata(generic::TXT("Jin Jian"));
-    authors->addRdata(generic::TXT("JINMEI Tatuya"));
-    authors->addRdata(generic::TXT("Kazunori Fujiwara"));
-    authors->addRdata(generic::TXT("Michael Graff"));
-    authors->addRdata(generic::TXT("Naoki Kambe"));
-    authors->addRdata(generic::TXT("Shane Kerr"));
-    authors->addRdata(generic::TXT("Zhang Likun"));
-
-    authors_ns = RRsetPtr(new RRset(authors_name, RRClass::CH(),
-                                    RRType::NS(), RRTTL(0)));
-    authors_ns->addRdata(generic::NS(authors_name));
-
-    version = RRsetPtr(new RRset(version_name, RRClass::CH(),
-                                          RRType::TXT(), RRTTL(0)));
-    version->addRdata(generic::TXT("BIND10 0.0.0 (pre-alpha)"));
-
-    version_ns = RRsetPtr(new RRset(version_name, RRClass::CH(),
-                                    RRType::NS(), RRTTL(0)));
-    version_ns->addRdata(generic::NS(version_name));
 }
 
 void
@@ -86,13 +111,9 @@
 }
 
 DataSrc::Result
-StaticDataSrc::findRRset(const Query& q,
-                         const Name& qname,
-                         const RRClass& qclass,
-                         const RRType& qtype,
-                         RRsetList& target,
-                         uint32_t& flags,
-                         Name* zone) const
+StaticDataSrc::findRRset(const Query& q, const Name& qname,
+                         const RRClass& qclass, const RRType& qtype,
+                         RRsetList& target, uint32_t& flags, Name* zone) const
 {
     flags = 0;
     if (qclass != getClass()) {
@@ -126,5 +147,33 @@
     return (SUCCESS);
 }
 
+DataSrc::Result
+StaticDataSrc::findExactRRset(const Query& q, const Name& qname,
+                              const RRClass& qclass, const RRType& qtype,
+                              RRsetList& target, uint32_t& flags,
+                              Name* zone) const
+{
+    return (findRRset(q, qname, qclass, qtype, target, flags, zone));
+}
+
+DataSrc::Result
+StaticDataSrc::findPreviousName(const Query& q, const Name& qname,
+                                Name& target, Name* zone) const
+{
+    return (NOT_IMPLEMENTED);
+}
+
+DataSrc::Result
+StaticDataSrc::init()
+{
+    return (SUCCESS);
+}
+
+DataSrc::Result
+StaticDataSrc::close()
+{
+    return (SUCCESS);
+}
+
 }
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/data_source_static.h
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/data_source_static.h (original)
+++ branches/each-nsec3/src/lib/auth/cpp/data_source_static.h Thu Mar  4 19:14:07 2010
@@ -27,54 +27,61 @@
 
 #include "data_source.h"
 
-using namespace isc::dns;
+namespace isc {
 
-namespace isc {
+namespace dns {
+class Name;
+class RRClass;
+class RRType;
+class RRType;
+class RRsetList;
+}
+
 namespace auth {
 
+class Query;
+class NameMatch;
+
 class StaticDataSrc : public DataSrc {
+private:
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+    //@{
+    StaticDataSrc(const StaticDataSrc& source);
+    StaticDataSrc& operator=(const StaticDataSrc& source);
 public:
     StaticDataSrc();
     ~StaticDataSrc() {}
+    //@}
 
     void findClosestEnclosure(NameMatch& match) const;
 
     Result findRRset(const Query& q,
-                     const Name& qname,
-                     const RRClass& qclass,
-                     const RRType& qtype,
-                     RRsetList& target,
+                     const isc::dns::Name& qname,
+                     const isc::dns::RRClass& qclass,
+                     const isc::dns::RRType& qtype,
+                     isc::dns::RRsetList& target,
                      uint32_t& flags,
-                     Name* zone = NULL) const;
+                     isc::dns::Name* zone = NULL) const;
 
     Result findExactRRset(const Query& q,
-                         const Name& qname,
-                         const RRClass& qclass,
-                         const RRType& qtype,
-                         RRsetList& target,
-                         uint32_t& flags,
-                         Name* zone = NULL) const
-    {
-        return (findRRset(q, qname, qclass, qtype, target, flags, zone));
-    }
+                          const isc::dns::Name& qname,
+                          const isc::dns::RRClass& qclass,
+                          const isc::dns::RRType& qtype,
+                          isc::dns::RRsetList& target,
+                          uint32_t& flags,
+                          isc::dns::Name* zone = NULL) const;
 
     Result findPreviousName(const Query& q,
-                            const Name& qname,
-                            Name& target,
-                            Name* zone) const {
-        return (NOT_IMPLEMENTED);
-    }
+                            const isc::dns::Name& qname,
+                            isc::dns::Name& target,
+                            isc::dns::Name* zone) const;
 
-    Result init() { return (SUCCESS); }
-    Result close() { return (SUCCESS); }
-
-private:
-    const Name authors_name;
-    const Name version_name;
-    RRsetPtr authors;
-    RRsetPtr authors_ns;
-    RRsetPtr version;
-    RRsetPtr version_ns;
+    Result init();
+    Result close();
 };
 
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/datasrc_unittest.cc
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/datasrc_unittest.cc (original)
+++ branches/each-nsec3/src/lib/auth/cpp/datasrc_unittest.cc Thu Mar  4 19:14:07 2010
@@ -31,6 +31,7 @@
 #include <dns/rrttl.h>
 #include <dns/rrtype.h>
 
+#include "query.h"
 #include "unittest_util.h"
 #include "unittest_ds.h"
 
@@ -42,7 +43,8 @@
 namespace {
 class DataSrcTest : public ::testing::Test {
 protected:
-    DataSrcTest() : obuffer(0), renderer(obuffer) {}
+    DataSrcTest() : obuffer(0), renderer(obuffer), msg(Message::PARSE)
+    {}
     TestDataSrc ds;
     OutputBuffer obuffer;
     MessageRenderer renderer;
@@ -65,7 +67,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -126,7 +128,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -161,7 +163,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -185,7 +187,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -211,7 +213,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -227,7 +229,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -286,7 +288,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -345,7 +347,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -406,7 +408,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -437,7 +439,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -476,7 +478,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -513,7 +515,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 
@@ -556,7 +558,7 @@
     msg.makeResponse();
     msg.setHeaderFlag(MessageFlag::AA());
     msg.setRcode(Rcode::NOERROR());
-    Query q = Query(msg, false);
+    Query q(msg, true);
     ds.doQuery(q);
     Message* m = &(q.message());
 

Modified: branches/each-nsec3/src/lib/auth/cpp/query.cc
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/query.cc (original)
+++ branches/each-nsec3/src/lib/auth/cpp/query.cc Thu Mar  4 19:14:07 2010
@@ -23,12 +23,94 @@
 
 #include "query.h"
 
+using namespace isc::dns;
+
 namespace isc {
 namespace auth {
 
 // Destructors defined here to avoid confusing the linker
+Query::~Query() {}
 QueryTask::~QueryTask() {}
-Query::~Query() {}
+
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const isc::dns::RRType& t, const isc::dns::Section& sect) :
+    qname(n), qclass(c), qtype(t), zone(NULL),
+        section(sect), op(AUTH_QUERY), state(GETANSWER), flags(0)
+{}
+
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const isc::dns::RRType& t, const isc::dns::Section& sect,
+                     const Op o) :
+    qname(n), qclass(c), qtype(t), zone(NULL),
+    section(sect), op(o), state(GETANSWER), flags(0)
+{}
+
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const isc::dns::RRType& t, const isc::dns::Section& sect,
+                     const State st) :
+    qname(n), qclass(c), qtype(t), zone(NULL),
+    section(sect), op(AUTH_QUERY), state(st), flags(0)
+{}
+
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const isc::dns::RRType& t, const isc::dns::Section& sect,
+                     const Op o, const State st) :
+    qname(n), qclass(c), qtype(t), zone(NULL),
+    section(sect), op(o), state(st), flags(0) 
+{}
+
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const isc::dns::RRType& t, const Op o) :
+    qname(n), qclass(c), qtype(t), zone(NULL),
+    section(Section::ANSWER()),
+    op(o), state(GETANSWER), flags(0)
+{
+    if (op != SIMPLE_QUERY) {
+        dns_throw(Unexpected, "invalid constructor for this task operation");
+    }
+}
+
+// A referral query doesn't need to specify section, state, or type.
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const Op o) :
+    qname(n), qclass(c), qtype(RRType::ANY()), zone(NULL),
+    section(Section::ANSWER()), op(o), state(GETANSWER),
+    flags(0)
+{
+    if (op != REF_QUERY) {
+        dns_throw(Unexpected, "invalid constructor for this task operation");
+    }
+}
+
+QueryTask::QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+                     const isc::dns::Section& sect, const Op o,
+                     const State st) :
+        qname(n), qclass(c), qtype(RRType::ANY()), zone(NULL),
+        section(sect), op(o), state(st), flags(0)
+{
+    if (op != GLUE_QUERY && op != NOGLUE_QUERY) {
+        dns_throw(Unexpected, "invalid constructor for this task operation");
+    }
+}
+
+Query::Query(Message& m, bool dnssec) :
+    status_(PENDING), qname_(NULL), qclass_(NULL), qtype_(NULL),
+    message_(&m), want_additional_(true), want_dnssec_(dnssec)
+{
+    // Check message formatting
+    if (message_->getRRCount(Section::QUESTION()) != 1) {
+        dns_throw(Unexpected, "malformed message: too many questions");
+    }
+
+    // Populate the query task queue with the initial question
+    QuestionPtr question = *message_->beginQuestion();
+    qname_ = &question->getName();
+    qclass_ = &question->getClass();
+    qtype_ = &question->getType();
+
+    querytasks_.push(QueryTaskPtr(new QueryTask(*qname_, *qclass_, *qtype_,
+                                                Section::ANSWER())));
+}
 
 }
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/query.h
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/query.h (original)
+++ branches/each-nsec3/src/lib/auth/cpp/query.h Thu Mar  4 19:14:07 2010
@@ -19,40 +19,45 @@
 
 #include <queue>
 
-#include <exceptions/exceptions.h>
-#include <dns/name.h>
-#include <dns/message.h>
-#include <dns/rrset.h>
-#include <dns/rrclass.h>
-#include <dns/rrtype.h>
-
-using namespace isc::dns;
-
 namespace isc {
+
+namespace dns {
+class Name;
+class Message;
+class Section;
+class RRClass;
+class RRType;
+}
+
 namespace auth {
 
 // An individual task to be carried out by the query logic
 class QueryTask {
+private:
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+    QueryTask(const QueryTask& source);
+    QueryTask& operator=(const QueryTask& source);
 public:
     // XXX: Members are currently public, but should probably be
     // moved to private and wrapped in get() functions later.
 
     // The standard query tuple: qname/qclass/qtype.
     // Note that qtype is ignored in the GLUE_QUERY/NOGLUE_QUERY case.
-    const Name& qname;
-    const RRClass& qclass;
-    const RRType& qtype;
+    const isc::dns::Name& qname;
+    const isc::dns::RRClass& qclass;
+    const isc::dns::RRType& qtype;
 
     // Optional: name for the containing zone, if known.
     // This is particularly needed when looking up data in a
     // zone other than the closest enclosure (such as getting
     // DS queries from a parent zone on a server which serves
     // both parent and child).
-    Name* zone;
+    isc::dns::Name* zone;
 
     // The section of the reply into which the data should be
     // written after it has been fetched from the data source.
-    const Section& section;
+    const isc::dns::Section& section;
 
     // The op field indicates the operation to be carried out by
     // this query task:
@@ -121,54 +126,31 @@
     uint32_t flags;
 
     // Constructors
-    QueryTask(const Name& n, const RRClass& c,
-              const RRType& t, const Section& sect) :
-        qname(n), qclass(c), qtype(t), zone(NULL),
-        section(sect), op(AUTH_QUERY), state(GETANSWER), flags(0) {}
-    QueryTask(const Name& n, const RRClass& c,
-              const RRType& t, const Section& sect, const Op o) :
-        qname(n), qclass(c), qtype(t), zone(NULL),
-        section(sect), op(o), state(GETANSWER), flags(0) {}
-    QueryTask(const Name& n, const RRClass& c,
-              const RRType& t, const Section& sect, const State st) :
-        qname(n), qclass(c), qtype(t), zone(NULL),
-        section(sect), op(AUTH_QUERY), state(st), flags(0) {}
-    QueryTask(const Name& n, const RRClass& c,
-              const RRType& t, const Section& sect,
-              const Op o, const State st) :
-        qname(n), qclass(c), qtype(t), zone(NULL),
-        section(sect), op(o), state(st), flags(0) {}
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+              const isc::dns::RRType& t, const isc::dns::Section& sect);
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+              const isc::dns::RRType& t, const isc::dns::Section& sect,
+              Op o);
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+              const isc::dns::RRType& t, const isc::dns::Section& sect,
+              const State st);
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+              const isc::dns::RRType& t, const isc::dns::Section& sect,
+              Op o, State st);
 
     // These are special constructors for particular query task types,
     // to simplify the code.
     //
     // A simple query doesn't need to specify section or state.
-    QueryTask(const Name& n, const RRClass& c, const RRType& t, const Op o) :
-        qname(n), qclass(c), qtype(t), zone(NULL),
-        section(Section::ANSWER()), op(o), state(GETANSWER), flags(0) {
-        if (op != SIMPLE_QUERY) {
-            throw "invalid constructor for this task operation";
-        }
-    }
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+              const isc::dns::RRType& t, Op o);
     // A referral query doesn't need to specify section, state, or type.
-    QueryTask(const Name& n, const RRClass& c, const Op o) :
-        qname(n), qclass(c), qtype(RRType::ANY()), zone(NULL),
-        section(Section::ANSWER()), op(o), state(GETANSWER), flags(0) {
-        if (op != REF_QUERY) {
-            throw "invalid constructor for this task operation";
-        }
-    }
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c, Op o);
     // A glue (or noglue) query doesn't need to specify type.
-    QueryTask(const Name& n, const RRClass& c,
-              const Section& sect, const Op o, const State st) :
-        qname(n), qclass(c), qtype(RRType::ANY()), zone(NULL),
-        section(sect), op(o), state(st), flags(0) {
-        if (op != GLUE_QUERY && op != NOGLUE_QUERY) {
-            throw "invalid constructor for this task operation";
-        }
-    }
-
-    virtual ~QueryTask();
+    QueryTask(const isc::dns::Name& n, const isc::dns::RRClass& c,
+              const isc::dns::Section& sect, Op o, State st);
+
+    ~QueryTask();
 };
 
 typedef boost::shared_ptr<QueryTask> QueryTaskPtr;
@@ -186,64 +168,61 @@
         ANSWERED
     };
 
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+    //@{
+private:
+    Query(const Query& source);
+    Query& operator=(const Query& source);
+public:
     // Query constructor
-    Query(Message& m, bool dnssec) {
-        message_ = &m;
-        want_additional = true;
-        want_dnssec = dnssec;
-        status_ = PENDING;
-
-        // Check message formatting
-        if (message_->getRRCount(Section::QUESTION()) != 1) {
-            dns_throw(Unexpected, "malformed message: too many questions");
-        }
-
-        // Populate the query task queue with the initial question
-        QuestionPtr query = *message_->beginQuestion();
-        qname_ = &query->getName();
-        qclass_ = &query->getClass();
-        qtype_ = &query->getType();
-
-        QueryTaskPtr initial_task(new QueryTask(*qname_, *qclass_, *qtype_,
-                                                Section::ANSWER()));
-        querytasks.push(initial_task);
-    };
-
+    Query(isc::dns::Message& m, bool dnssec);
+    /// \brief The destructor.
     virtual ~Query();
+    //@}
 
     // wantAdditional() == true indicates that additional-section data
     // should be looked up while processing this query.  false indicates
     // that we're only interested in answer-section data
-    bool wantAdditional() { return want_additional; }
-    void setWantAdditional(bool d) { want_additional = d; }
+    bool wantAdditional() { return want_additional_; }
+    void setWantAdditional(bool d) { want_additional_ = d; }
 
     // wantDnssec() == true indicates that DNSSEC data should be retrieved
     // from the data source when this query is being processed
-    bool wantDnssec() { return want_dnssec; }
-    void setWantDnssec(bool d) { want_dnssec = d; }
-
-    const Name& qname() { return *qname_; }
-    const RRClass& qclass() { return *qclass_; }
-    const RRType& qtype() { return *qtype_; }
-
-    Message& message() { return *message_; }
-    QueryTaskQueue& tasks() { return querytasks; }
-
-    Status status() { return status_; }
+    bool wantDnssec() const { return want_dnssec_; }
+    void setWantDnssec(bool d) { want_dnssec_ = d; }
+
+    const isc::dns::Name& qname() const { return *qname_; }
+    const isc::dns::RRClass& qclass() const { return *qclass_; }
+    const isc::dns::RRType& qtype() const { return *qtype_; }
+
+    // Note: these can't be constant member functions because they expose
+    // writable 'handles' of internal member variables.  It's questionable
+    // whether we need these accessors in the first place because the
+    // corresponding members are public (which itself is not a good practice
+    // but it's a different topic), but at the moment we keep them.
+    // We should definitely revisit the design later.
+    isc::dns::Message& message() { return *message_; }
+    QueryTaskQueue& tasks() { return querytasks_; }
+
+    Status status() const { return status_; }
     void setStatus(Status s) { status_ = s; }
 
 private:
     Status status_;
 
-    const Name* qname_;
-    const RRClass* qclass_;
-    const RRType* qtype_;
-
-    Message* message_;
-    QueryTaskQueue querytasks;
-
-    bool want_additional;
-    bool want_dnssec;
+    const isc::dns::Name* qname_;
+    const isc::dns::RRClass* qclass_;
+    const isc::dns::RRType* qtype_;
+
+    isc::dns::Message* message_;
+    QueryTaskQueue querytasks_;
+
+    bool want_additional_;
+    bool want_dnssec_;
 };
 
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/unittest_ds.cc
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/unittest_ds.cc (original)
+++ branches/each-nsec3/src/lib/auth/cpp/unittest_ds.cc Thu Mar  4 19:14:07 2010
@@ -25,6 +25,7 @@
 #include <dns/rdataclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrset.h>
+#include <dns/rrsetlist.h>
 #include <dns/rrtype.h>
 #include <dns/rrttl.h>
 

Modified: branches/each-nsec3/src/lib/auth/cpp/unittest_ds.h
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/unittest_ds.h (original)
+++ branches/each-nsec3/src/lib/auth/cpp/unittest_ds.h Thu Mar  4 19:14:07 2010
@@ -17,57 +17,75 @@
 #ifndef __TEST_DATA_SOURCE_H
 #define __TEST_DATA_SOURCE_H
 
+#include <dns/name.h>
+#include <dns/rrset.h>
+
 #include <gtest/gtest.h>
-#include "unittest_util.h"
-
-using isc::UnitTestUtil;
-using namespace isc::dns;
 
 #include "data_source.h"
 
 namespace isc {
+
+namespace dns {
+class RRClass;
+class RRType;
+class RRsetList;
+}
+
 namespace auth {
+class Query;
+
 class TestDataSrc : public DataSrc {
+    ///
+    /// \name Constructors, Assignment Operator and Destructor.
+    ///
+    /// Note: The copy constructor and the assignment operator are intentionally
+    /// defined as private.
+    //@{
+private:
+    TestDataSrc(const TestDataSrc& source);
+    TestDataSrc operator=(const TestDataSrc& source); 
 public:
     TestDataSrc();
     ~TestDataSrc() {}
+    //@}
 
     void findClosestEnclosure(NameMatch& match) const;
 
     Result findRRset(const Query& q,
-                     const Name& qname,
-                     const RRClass& qclass,
-                     const RRType& qtype,
-                     RRsetList& target,
+                     const isc::dns::Name& qname,
+                     const isc::dns::RRClass& qclass,
+                     const isc::dns::RRType& qtype,
+                     isc::dns::RRsetList& target,
                      uint32_t& flags,
-                     Name* zone = NULL) const;
+                     isc::dns::Name* zone = NULL) const;
 
     Result findExactRRset(const Query& q,
-                          const Name& qname,
-                          const RRClass& qclass,
-                          const RRType& qtype,
-                          RRsetList& target,
+                          const isc::dns::Name& qname,
+                          const isc::dns::RRClass& qclass,
+                          const isc::dns::RRType& qtype,
+                          isc::dns::RRsetList& target,
                           uint32_t& flags,
-                          Name* zone = NULL) const;
+                          isc::dns::Name* zone = NULL) const;
 
     Result findAddrs(const Query& q,
-                     const Name& qname,
-                     const RRClass& qclass,
-                     RRsetList& target,
+                     const isc::dns::Name& qname,
+                     const isc::dns::RRClass& qclass,
+                     isc::dns::RRsetList& target,
                      uint32_t& flags,
-                     Name* zone = NULL) const;
+                     isc::dns::Name* zone = NULL) const;
 
     Result findReferral(const Query& q,
-                        const Name& qname,
-                        const RRClass& qclass,
-                        RRsetList& target,
+                        const isc::dns::Name& qname,
+                        const isc::dns::RRClass& qclass,
+                        isc::dns::RRsetList& target,
                         uint32_t& flags,
-                        Name* zone = NULL) const;
+                        isc::dns::Name* zone = NULL) const;
 
     Result findPreviousName(const Query& q,
-                            const Name& qname,
-                            Name& target,
-                            Name* zone) const;
+                            const isc::dns::Name& qname,
+                            isc::dns::Name& target,
+                            isc::dns::Name* zone) const;
 
     Result init() { return (SUCCESS); }
     Result close() { return (SUCCESS); }
@@ -79,56 +97,56 @@
         DELEGATION
     };
 
-    void findRecords(const Name& name, const RRType& rdtype,
-                     RRsetList& target, Name* zone, const Mode mode,
-                     uint32_t& flags) const;
+    void findRecords(const isc::dns::Name& name, const isc::dns::RRType& rdtype,
+                     isc::dns::RRsetList& target, isc::dns::Name* zone,
+                     const Mode mode, uint32_t& flags) const;
 
-    const Name example;
-    const Name sql1;
-    const Name www_sql1;
-    const Name www;
-    const Name foo;
-    const Name dns01;
-    const Name dns02;
-    const Name dns03;
-    const Name cnameint;
-    const Name cnameext;
-    const Name dname;
-    const Name wild;
-    const Name subzone;
-    RRsetPtr example_ns;
-    RRsetPtr example_soa;
-    RRsetPtr example_nsec;
-    RRsetPtr www_a;
-    RRsetPtr www_nsec;
-    RRsetPtr foo_cname;
-    RRsetPtr foo_nsec;
-    RRsetPtr cnameint_cname;
-    RRsetPtr cnameint_nsec;
-    RRsetPtr cnameext_cname;
-    RRsetPtr cnameext_nsec;
-    RRsetPtr dns01_a;
-    RRsetPtr dns01_nsec;
-    RRsetPtr dns02_a;
-    RRsetPtr dns02_nsec;
-    RRsetPtr dns03_a;
-    RRsetPtr dns03_nsec;
-    RRsetPtr wild_a;
-    RRsetPtr wild_nsec;
-    RRsetPtr dname_dname;
-    RRsetPtr dname_nsec;
-    RRsetPtr sql1_ns;
-    RRsetPtr sql1_soa;
-    RRsetPtr sql1_nsec;
-    RRsetPtr sql1_ds;
-    RRsetPtr sql1_ds_nsec;
-    RRsetPtr www_sql1_a;
-    RRsetPtr www_sql1_nsec;
-    RRsetPtr subzone_ns;
-    RRsetPtr subzone_nsec;
-    RRsetPtr subzone_glue1;
-    RRsetPtr subzone_glue2;
-    RRsetPtr subzone_ds;
+    const isc::dns::Name example;
+    const isc::dns::Name sql1;
+    const isc::dns::Name www_sql1;
+    const isc::dns::Name www;
+    const isc::dns::Name foo;
+    const isc::dns::Name dns01;
+    const isc::dns::Name dns02;
+    const isc::dns::Name dns03;
+    const isc::dns::Name cnameint;
+    const isc::dns::Name cnameext;
+    const isc::dns::Name dname;
+    const isc::dns::Name wild;
+    const isc::dns::Name subzone;
+    isc::dns::RRsetPtr example_ns;
+    isc::dns::RRsetPtr example_soa;
+    isc::dns::RRsetPtr example_nsec;
+    isc::dns::RRsetPtr www_a;
+    isc::dns::RRsetPtr www_nsec;
+    isc::dns::RRsetPtr foo_cname;
+    isc::dns::RRsetPtr foo_nsec;
+    isc::dns::RRsetPtr cnameint_cname;
+    isc::dns::RRsetPtr cnameint_nsec;
+    isc::dns::RRsetPtr cnameext_cname;
+    isc::dns::RRsetPtr cnameext_nsec;
+    isc::dns::RRsetPtr dns01_a;
+    isc::dns::RRsetPtr dns01_nsec;
+    isc::dns::RRsetPtr dns02_a;
+    isc::dns::RRsetPtr dns02_nsec;
+    isc::dns::RRsetPtr dns03_a;
+    isc::dns::RRsetPtr dns03_nsec;
+    isc::dns::RRsetPtr wild_a;
+    isc::dns::RRsetPtr wild_nsec;
+    isc::dns::RRsetPtr dname_dname;
+    isc::dns::RRsetPtr dname_nsec;
+    isc::dns::RRsetPtr sql1_ns;
+    isc::dns::RRsetPtr sql1_soa;
+    isc::dns::RRsetPtr sql1_nsec;
+    isc::dns::RRsetPtr sql1_ds;
+    isc::dns::RRsetPtr sql1_ds_nsec;
+    isc::dns::RRsetPtr www_sql1_a;
+    isc::dns::RRsetPtr www_sql1_nsec;
+    isc::dns::RRsetPtr subzone_ns;
+    isc::dns::RRsetPtr subzone_nsec;
+    isc::dns::RRsetPtr subzone_glue1;
+    isc::dns::RRsetPtr subzone_glue2;
+    isc::dns::RRsetPtr subzone_ds;
 };
 
 }

Modified: branches/each-nsec3/src/lib/auth/cpp/unittest_util.h
==============================================================================
--- branches/each-nsec3/src/lib/auth/cpp/unittest_util.h (original)
+++ branches/each-nsec3/src/lib/auth/cpp/unittest_util.h Thu Mar  4 19:14:07 2010
@@ -23,9 +23,6 @@
 #include <dns/name.h>
 
 #include <gtest/gtest.h>
-
-using namespace std;
-using namespace isc::dns;
 
 namespace isc {
 
@@ -77,7 +74,7 @@
     ///
     static ::testing::AssertionResult
     matchName(const char* nameexp1, const char* nameexp2,
-              const Name& name1, const Name& name2);
+              const isc::dns::Name& name1, const isc::dns::Name& name2);
 };
 }
 #endif // __UNITTEST_UTIL_H

Modified: branches/each-nsec3/src/lib/dns/cpp/Makefile.am
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/Makefile.am (original)
+++ branches/each-nsec3/src/lib/dns/cpp/Makefile.am Thu Mar  4 19:14:07 2010
@@ -18,8 +18,8 @@
 libdns_la_SOURCES += rrsetlist.h rrsetlist.cc
 libdns_la_SOURCES += question.h question.cc
 libdns_la_SOURCES += message.h message.cc
+libdns_la_SOURCES += base32.h base32.cc
 libdns_la_SOURCES += base64.h base64.cc
-libdns_la_SOURCES += base32.h base32.cc
 libdns_la_SOURCES += sha1.h sha1.cc
 libdns_la_SOURCES += tsig.h tsig.cc
 libdns_la_SOURCES += dnstime.h dnstime.cc

Modified: branches/each-nsec3/src/lib/dns/cpp/buffer.h
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/buffer.h (original)
+++ branches/each-nsec3/src/lib/dns/cpp/buffer.h Thu Mar  4 19:14:07 2010
@@ -358,7 +358,7 @@
     /// \param pos The beginning position in the buffer to write the data.
     void writeUint16At(uint16_t data, size_t pos)
     {
-        if (pos + sizeof(data) >= data_.size()) {
+        if (pos + sizeof(data) > data_.size()) {
             dns_throw(InvalidBufferPosition, "write at invalid position");
         }
 

Modified: branches/each-nsec3/src/lib/dns/cpp/dnstime.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/dnstime.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/dnstime.cc Thu Mar  4 19:14:07 2010
@@ -99,21 +99,20 @@
             day, "day");
     checkRange(0, 23, hour, "hour");
     checkRange(0, 59, minute, "minute");
-    checkRange(0, 60, second, "second");
+    checkRange(0, 60, second, "second"); // 60 == leap second.
 
     timeval = second + (60 * minute) + (3600 * hour) + ((day - 1) * 86400);
-    for (int m = 0; m < (month - 1); m++)
+    for (int m = 0; m < (month - 1); m++) {
             timeval += days[m] * 86400;
-    if (isLeap(year) && month > 2)
+    }
+    if (isLeap(year) && month > 2) {
             timeval += 86400;
-    for (int y = 1970; y < year; y++) {
+    }
+    for (int y = 1970; y < year; ++y) {
         timeval += ((isLeap(y) ? 366 : 365 ) * 86400);
     }
 
     return (timeval);
 }
-
-
-
 }
 }

Modified: branches/each-nsec3/src/lib/dns/cpp/message.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/message.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/message.cc Thu Mar  4 19:14:07 2010
@@ -31,6 +31,7 @@
 #include "messagerenderer.h"
 #include "name.h"
 #include "question.h"
+#include "rdataclass.h"
 #include "rrclass.h"
 #include "rrtype.h"
 #include "rrttl.h"
@@ -59,7 +60,7 @@
 static const flags_t FLAG_CD = 0x0010;
 
 //
-// EDNS0 related constants
+// EDNS related constants
 //
 static const flags_t EXTFLAG_MASK = 0xffff;
 static const flags_t EXTFLAG_DO = 0x8000;
@@ -189,9 +190,10 @@
 
 class MessageImpl {
 public:
-    MessageImpl();
+    MessageImpl(Message::Mode mode);
     // Open issues: should we rather have a header in wire-format
     // for efficiency?
+    Message::Mode mode_;
     qid_t qid_;
     Rcode rcode_;
     const Opcode* opcode_;
@@ -202,7 +204,9 @@
     int counts_[SECTION_MAX];   // TODO: revisit this definition
     vector<QuestionPtr> questions_;
     vector<RRsetPtr> rrsets_[SECTION_MAX];
-    RRsetPtr edns_;
+    RRsetPtr remote_edns_;
+    uint16_t remote_udpsize_;
+    RRsetPtr local_edns_;
     uint16_t udpsize_;
 
 #ifdef notyet
@@ -211,13 +215,13 @@
 #endif
 
     void init();
-    void parseQuestion(Message& message, InputBuffer& buffer);
-    void parseSection(Message& messge, const Section& section,
-                      InputBuffer& buffer);
+    int parseQuestion(Message& message, InputBuffer& buffer);
+    int parseSection(Message& messge, const Section& section,
+                     InputBuffer& buffer);
 };
 
-MessageImpl::MessageImpl() :
-    rcode_(Rcode::NOERROR())
+MessageImpl::MessageImpl(Message::Mode mode) :
+    mode_(mode), rcode_(Rcode::NOERROR())
 {
     init();
 }
@@ -230,7 +234,9 @@
     rcode_ = Rcode::NOERROR();  // XXX
     opcode_ = NULL;
     dnssec_ok_ = false;
-    edns_ = RRsetPtr();
+    remote_edns_ = RRsetPtr();
+    remote_udpsize_ = Message::DEFAULT_MAX_UDPSIZE;
+    local_edns_ = RRsetPtr();
     udpsize_ = Message::DEFAULT_MAX_UDPSIZE;
 
     for (int i = 0; i < SECTION_MAX; i++) {
@@ -243,8 +249,8 @@
     rrsets_[sectionCodeToId(Section::ADDITIONAL())].clear();
 }
 
-Message::Message() :
-    impl_(new MessageImpl())
+Message::Message(Mode mode) :
+    impl_(new MessageImpl(mode))
 {
 }
 
@@ -277,10 +283,34 @@
     return (impl_->dnssec_ok_);
 }
 
+void
+Message::setDNSSECSupported(bool on)
+{
+    if (impl_->mode_ != Message::RENDER) {
+        dns_throw(InvalidMessageOperation,
+                  "setDNSSECSupported performed in non-render mode");
+    }
+    impl_->dnssec_ok_ = on;
+}
+
 uint16_t
 Message::getUDPSize() const
 {
     return (impl_->udpsize_);
+}
+
+void
+Message::setUDPSize(uint16_t size)
+{
+    if (impl_->mode_ != Message::RENDER) {
+        dns_throw(InvalidMessageOperation,
+                  "setUDPSize performed in non-render mode");
+    }
+    if (size < DEFAULT_MAX_UDPSIZE) {
+        dns_throw(InvalidMessageUDPSize,
+                  "Specified UDP message size is too small");
+    }
+    impl_->udpsize_ = size;
 }
 
 qid_t
@@ -370,6 +400,44 @@
 };
 }
 
+namespace {
+bool
+addEDNS(MessageImpl* mimpl, MessageRenderer& renderer)
+{
+    bool is_query = ((mimpl->flags_ & MessageFlag::QR().getBit()) == 0); 
+
+    // If this is a reply and the request didn't have EDNS, we shouldn't add it.
+    if (mimpl->remote_edns_ == NULL && !is_query) {
+        return (false);
+    }
+
+    // For queries, we add EDNS only when necessary:
+    // Local UDP size is not the default value, or
+    // DNSSEC DO bit is to be set, or
+    // Extended Rcode is to be specified.
+    if (is_query && mimpl->udpsize_ == Message::DEFAULT_MAX_UDPSIZE &&
+        !mimpl->dnssec_ok_ &&
+        mimpl->rcode_.getCode() < 0x10) {
+        return (false);
+    }
+
+    // Render EDNS OPT RR
+    uint32_t extrcode_flags = ((mimpl->rcode_.getCode() & 0xff0) << 24);
+    if (mimpl->dnssec_ok_) {
+        extrcode_flags |= 0x8000; // set DO bit
+    }
+    mimpl->local_edns_ = RRsetPtr(new RRset(Name::ROOT_NAME(),
+                                            RRClass(mimpl->udpsize_),
+                                            RRType::OPT(),
+                                            RRTTL(extrcode_flags)));
+    // We don't support any options in this simple implementation
+    mimpl->local_edns_->addRdata(ConstRdataPtr(new generic::OPT()));
+    mimpl->local_edns_->toWire(renderer);
+
+    return (true);
+}
+}
+
 void
 Message::toWire(MessageRenderer& renderer)
 {
@@ -378,7 +446,7 @@
     // reserve room for the header
     renderer.skip(HEADERLEN);
 
-    uint16_t qrcount =
+    uint16_t qdcount =
         for_each(impl_->questions_.begin(), impl_->questions_.end(),
                  RenderSection<QuestionPtr>(renderer)).getTotalCount();
 
@@ -396,6 +464,12 @@
                  impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
                  RenderSection<RRsetPtr>(renderer)).getTotalCount();
 
+    // Added EDNS OPT RR if necessary (we want to avoid hardcoding specialized
+    // logic, see the parser case)
+    if (addEDNS(this->impl_, renderer)) {
+        ++arcount;
+    }
+
     // TBD: EDNS, TSIG, etc.
 
     // fill in the header
@@ -408,7 +482,7 @@
     renderer.writeUint16At(codes_and_flags, header_pos);
     header_pos += sizeof(uint16_t);
     // XXX: should avoid repeated pattern (TODO)
-    renderer.writeUint16At(qrcount, header_pos);
+    renderer.writeUint16At(qdcount, header_pos);
     header_pos += sizeof(uint16_t);
     renderer.writeUint16At(ancount, header_pos);
     header_pos += sizeof(uint16_t);
@@ -435,15 +509,21 @@
     impl_->counts_[Section::AUTHORITY().getCode()] = buffer.readUint16();
     impl_->counts_[Section::ADDITIONAL().getCode()] = buffer.readUint16();
 
-    impl_->parseQuestion(*this, buffer);
-    impl_->parseSection(*this, Section::ANSWER(), buffer);
-    impl_->parseSection(*this, Section::AUTHORITY(), buffer);
-    impl_->parseSection(*this, Section::ADDITIONAL(), buffer);
-}
-
-void
+    impl_->counts_[Section::QUESTION().getCode()] =
+        impl_->parseQuestion(*this, buffer);
+    impl_->counts_[Section::ANSWER().getCode()] =
+        impl_->parseSection(*this, Section::ANSWER(), buffer);
+    impl_->counts_[Section::AUTHORITY().getCode()] =
+        impl_->parseSection(*this, Section::AUTHORITY(), buffer);
+    impl_->counts_[Section::ADDITIONAL().getCode()] =
+        impl_->parseSection(*this, Section::ADDITIONAL(), buffer);
+}
+
+int
 MessageImpl::parseQuestion(Message& message, InputBuffer& buffer)
 {
+    unsigned int added = 0;
+
     for (unsigned int count = 0;
          count < counts_[Section::QUESTION().getCode()];
          count++) {
@@ -460,8 +540,11 @@
         // algorithm that requires the question section contain exactly one
         // RR.
 
-        questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype))); 
-    }
+        questions_.push_back(QuestionPtr(new Question(name, rrclass, rrtype)));
+        ++added;
+    }
+
+    return (added);
 }
 
 namespace {
@@ -480,10 +563,12 @@
 };
 }
 
-void
+int
 MessageImpl::parseSection(Message& message, const Section& section,
                           InputBuffer& buffer)
 {
+    unsigned int added = 0;
+
     for (unsigned int count = 0; count < counts_[section.getCode()]; count++) {
         Name name(buffer);
 
@@ -507,17 +592,17 @@
                 dns_throw(DNSMessageFORMERR,
                           "EDNS OPT RR found in an invalid section");
             }
-            if (edns_ != NULL) {
+            if (remote_edns_ != NULL) {
                 dns_throw(DNSMessageFORMERR, "multiple EDNS OPT RR found");
             }
             if (((ttl.getValue() & EDNSVERSION_MASK) >> 16) >
+                Message::EDNS_SUPPORTED_VERSION) {
                 // XXX: we should probably not reject the message yet, because
                 // it's better to let the requestor know the responder-side
                 // highest version as indicated in Section 4.6 of RFC2671.
                 // This is probably because why BIND 9 does the version check
                 // in the client code.
                 // This is a TODO item.  Right now we simply reject it.
-                Message::EDNS0_SUPPORTED_VERSION) {
                 dns_throw(DNSMessageBADVERS, "unsupported EDNS version");
             }
             if (name != Name::ROOT_NAME()) {
@@ -525,8 +610,8 @@
                           "invalid owner name for EDNS OPT RR");
             }
 
-            edns_ = RRsetPtr(new RRset(name, rrclass, rrtype, ttl));
-            edns_->addRdata(rdata);
+            remote_edns_ = RRsetPtr(new RRset(name, rrclass, rrtype, ttl));
+            remote_edns_->addRdata(rdata);
 
             dnssec_ok_ = (((ttl.getValue() & EXTFLAG_MASK) & EXTFLAG_DO) != 0);
             if (rrclass.getCode() > Message::DEFAULT_MAX_UDPSIZE) {
@@ -549,7 +634,10 @@
             rrset->addRdata(rdata);
             rrsets_[sectionCodeToId(section)].push_back(rrset);
         }
-    }
+        ++added;
+    }
+
+    return (added);
 }
 
 namespace {
@@ -609,9 +697,36 @@
         lexical_cast<string>(impl_->counts_[Section::ANSWER().getCode()]);
     s += ", AUTHORITY: " +
         lexical_cast<string>(impl_->counts_[Section::AUTHORITY().getCode()]);
-    s += ", ADDITIONAL: " +
-        lexical_cast<string>(impl_->counts_[Section::ADDITIONAL().getCode()])
-        + "\n";
+
+    unsigned int arcount = impl_->counts_[Section::ADDITIONAL().getCode()];
+    RRsetPtr edns_rrset;
+    if (!getHeaderFlag(MessageFlag::QR()) && impl_->remote_edns_ != NULL) {
+        edns_rrset = impl_->remote_edns_;
+        ++arcount;
+    } else if (getHeaderFlag(MessageFlag::QR()) && impl_->local_edns_ != NULL) {
+        edns_rrset = impl_->local_edns_;
+        ++arcount;
+    }
+    s += ", ADDITIONAL: " + lexical_cast<string>(arcount) + "\n";
+
+    if (edns_rrset != NULL) {
+        s += "\n;; OPT PSEUDOSECTION:\n";
+        s += "; EDNS: version: ";
+        s += lexical_cast<string>(
+            (edns_rrset->getTTL().getValue() & 0x00ff0000) >> 16);
+        s += ", flags:";
+        if ((edns_rrset->getTTL().getValue() & 0x8000) != 0) {
+            s += " do";
+        }
+        uint32_t mbz = edns_rrset->getTTL().getValue() & ~0x8000 & 0xffff;
+        if (mbz != 0) {
+            s += "; MBZ: " + lexical_cast<string>(mbz) + ", udp: ";
+        } else {
+            s += "; udp: " +
+                lexical_cast<string>(edns_rrset->getClass().getCode());
+        }
+        s += "\n";
+    }
 
     if (!impl_->questions_.empty()) {
         s += "\n;; " +
@@ -654,8 +769,20 @@
 void
 Message::makeResponse()
 {
+    if (impl_->mode_ != Message::PARSE) {
+        dns_throw(InvalidMessageOperation,
+                  "makeResponse() is performed in non-parse mode");
+    }
+
+    impl_->dnssec_ok_ = false;
+    impl_->remote_udpsize_ = impl_->udpsize_;
+    impl_->local_edns_ = RRsetPtr();
+    impl_->udpsize_ = DEFAULT_MAX_UDPSIZE;
+
     impl_->flags_ &= MESSAGE_REPLYPRESERVE;
     setHeaderFlag(MessageFlag::QR());
+
+    impl_->mode_ = Message::RENDER;
 
     impl_->rrsets_[sectionCodeToId(Section::ANSWER())].clear();
     impl_->counts_[Section::ANSWER().getCode()] = 0;

Modified: branches/each-nsec3/src/lib/dns/cpp/message.h
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/message.h (original)
+++ branches/each-nsec3/src/lib/dns/cpp/message.h Thu Mar  4 19:14:07 2010
@@ -60,6 +60,18 @@
 class InvalidMessageSection : public Exception {
 public:
     InvalidMessageSection(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+class InvalidMessageOperation : public Exception {
+public:
+    InvalidMessageOperation(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
+class InvalidMessageUDPSize : public Exception {
+public:
+    InvalidMessageUDPSize(const char* file, size_t line, const char* what) :
         isc::Exception(file, line, what) {}
 };
 
@@ -503,7 +515,12 @@
 
 class Message {
 public:
-    Message();
+    enum Mode {
+        PARSE = 0,
+        RENDER = 1
+    };
+public:
+    Message(Mode mode);
     ~Message();
 private:
     Message(const Message& source);
@@ -513,8 +530,9 @@
     void setHeaderFlag(const MessageFlag& flag);
     void clearHeaderFlag(const MessageFlag& flag);
     bool isDNSSECSupported() const;
-    void setDNSSECSupported(bool on); // not yet
+    void setDNSSECSupported(bool on);
     uint16_t getUDPSize() const;
+    void setUDPSize(uint16_t size);
     qid_t getQid() const;
     void setQid(qid_t qid);
     const Rcode& getRcode() const;
@@ -566,11 +584,11 @@
     /// \brief The default maximum size of UDP DNS messages that don't cause
     /// truncation.
     ///
-    /// With EDNS0 the maximum size can be increases per message.
+    /// With EDNS the maximum size can be increases per message.
     static const uint16_t DEFAULT_MAX_UDPSIZE = 512;
 
-    /// \brief The highest EDNS0 version this implementation supports.
-    static const uint8_t EDNS0_SUPPORTED_VERSION = 0;
+    /// \brief The highest EDNS version this implementation supports.
+    static const uint8_t EDNS_SUPPORTED_VERSION = 0;
     //@}
 
 private:

Modified: branches/each-nsec3/src/lib/dns/cpp/messagerenderer.h
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/messagerenderer.h (original)
+++ branches/each-nsec3/src/lib/dns/cpp/messagerenderer.h Thu Mar  4 19:14:07 2010
@@ -77,7 +77,7 @@
     /// \param buffer An \c OutputBuffer object to which wire format data is
     /// written.
     MessageRenderer(OutputBuffer& buffer);
-    /// \brief The default destructor.
+    /// \brief The destructor.
     ///
     /// The destructor does nothing on the given \c buffer on construction;
     /// in fact, it is expected that the user will use the resulting buffer

Modified: branches/each-nsec3/src/lib/dns/cpp/rdata.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/rdata.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/rdata.cc Thu Mar  4 19:14:07 2010
@@ -115,7 +115,6 @@
 
     vector<uint8_t> data(rdata_len);
     buffer.readData(&data[0], rdata_len);
-    data.resize(rdata_len);
 
     impl_ = new GenericImpl(data);
 }

Modified: branches/each-nsec3/src/lib/dns/cpp/rdata/generic/dnskey_48.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/rdata/generic/dnskey_48.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/rdata/generic/dnskey_48.cc Thu Mar  4 19:14:07 2010
@@ -58,7 +58,7 @@
     stringbuf keydatabuf;
 
     iss >> flags >> protocol >> algorithm >> &keydatabuf;
-    if (iss.bad() || iss.fail() || !iss.eof()) {
+    if (iss.bad() || iss.fail()) {
         dns_throw(InvalidRdataText, "Invalid DNSKEY text");
     }
     if (flags > 0xffff) {
@@ -90,12 +90,10 @@
     uint16_t flags = buffer.readUint16();
     uint16_t protocol = buffer.readUint8();
     uint16_t algorithm = buffer.readUint8();
-    vector<uint8_t> keydata;
 
     rdata_len -= 4;
-    for (int i = 0; i < rdata_len; i++) {
-        keydata.push_back(buffer.readUint8());
-    }
+    vector<uint8_t> keydata(rdata_len);
+    buffer.readData(&keydata[0], rdata_len);
 
     impl_ = new DNSKEYImpl(flags, protocol, algorithm, keydata);
 }

Modified: branches/each-nsec3/src/lib/dns/cpp/rdata/generic/ds_43.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/rdata/generic/ds_43.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/rdata/generic/ds_43.cc Thu Mar  4 19:14:07 2010
@@ -57,7 +57,7 @@
     stringbuf digestbuf;
 
     iss >> tag >> algorithm >> digest_type >> &digestbuf;
-    if (iss.bad() || iss.fail() || !iss.eof()) {
+    if (iss.bad() || iss.fail()) {
         dns_throw(InvalidRdataText, "Invalid DS text");
     }
     if (tag > 0xffff) {
@@ -71,8 +71,7 @@
     }
 
     vector<uint8_t> digest;
-    string digest_string = digestbuf.str();
-    decodeHex(digest_string, digest);
+    decodeHex(digestbuf.str(), digest);
 
     impl_ = new DSImpl(tag, algorithm, digest_type, digest);
 }
@@ -86,12 +85,10 @@
     uint16_t tag = buffer.readUint16();
     uint16_t algorithm = buffer.readUint8();
     uint16_t digest_type = buffer.readUint8();
-    vector<uint8_t> digest;
 
     rdata_len -= 4;
-    for (int i = 0; i < rdata_len; i++) {
-        digest.push_back(buffer.readUint8());
-    }
+    vector<uint8_t> digest(rdata_len);
+    buffer.readData(&digest[0], rdata_len);
 
     impl_ = new DSImpl(tag, algorithm, digest_type, digest);
 }

Modified: branches/each-nsec3/src/lib/dns/cpp/rdata/generic/nsec_47.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/rdata/generic/nsec_47.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/rdata/generic/nsec_47.cc Thu Mar  4 19:14:07 2010
@@ -68,7 +68,7 @@
         bitmap[code / 8] |= (0x80 >> (code % 8));
     } while(!iss.eof());
 
-    for(int window = 0; window < 256; window++) {
+    for (int window = 0; window < 256; window++) {
         int octet;
         for (octet = 31; octet >= 0; octet--) {
             if (bitmap[window * 32 + octet] != 0) {
@@ -91,16 +91,17 @@
 {
     size_t pos = buffer.getPosition();
     Name nextname(buffer);
+
+    // rdata_len must be sufficiently large to hold non empty bitmap.
+    if (rdata_len <= buffer.getPosition() - pos) {
+        dns_throw(InvalidRdataLength, "NSEC too short");
+    }
     rdata_len -= (buffer.getPosition() - pos);
 
-    if (rdata_len == 0) {
-        dns_throw(InvalidRdataLength, "NSEC too short");
-    }
-
-    vector<uint8_t> typebits;
-    for (int i = 0; i < rdata_len; i++) {
-        typebits.push_back(buffer.readUint8());
-    }
+    // FIXIT: we cannot naively copy the data because the bitmaps have
+    // semantics and other part of this class assumes they are valid.
+    vector<uint8_t> typebits(rdata_len);
+    buffer.readData(&typebits[0], rdata_len);
 
     impl_ = new NSECImpl(nextname, typebits);
 }

Modified: branches/each-nsec3/src/lib/dns/cpp/rdata/generic/rrsig_46.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/rdata/generic/rrsig_46.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/rdata/generic/rrsig_46.cc Thu Mar  4 19:14:07 2010
@@ -39,6 +39,15 @@
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 
+namespace {
+// This is the minimum necessary length of all wire-format RRSIG RDATA:
+// - two 8-bit fields (algorithm and labels)
+// - two 16-bit fields (covered and tag)
+// - three 32-bit fields (original TTL, expire and inception)
+const size_t RRSIG_MINIMUM_LEN = 2 * sizeof(uint8_t) + 2 * sizeof(uint16_t) +
+    3 * sizeof(uint32_t);
+}
+
 struct RRSIGImpl {
     // straightforward representation of RRSIG RDATA fields
     RRSIGImpl(const RRType& covered, uint8_t algorithm, uint8_t labels,
@@ -75,7 +84,7 @@
     iss >> covered_txt >> algorithm >> labels >> originalttl
         >> expire_txt >> inception_txt >> tag >> signer_txt
         >> &signaturebuf;
-    if (iss.bad() || iss.fail() || !iss.eof()) {
+    if (iss.bad() || iss.fail()) {
         dns_throw(InvalidRdataText, "Invalid RRSIG text");
     }
     if (algorithm > 0xff) {
@@ -100,12 +109,11 @@
 {
     size_t pos = buffer.getPosition();
 
-    if (rdata_len < 18) {
+    if (rdata_len < RRSIG_MINIMUM_LEN) {
         dns_throw(InvalidRdataLength, "RRSIG too short");
     }
 
-    uint16_t typecode = buffer.readUint16();
-    RRType covered(typecode);
+    RRType covered(buffer);
     uint8_t algorithm = buffer.readUint8();
     uint8_t labels = buffer.readUint8();
     uint32_t originalttl = buffer.readUint32();
@@ -114,15 +122,14 @@
     uint16_t tag = buffer.readUint16();
     Name signer(buffer);
 
+    // rdata_len must be sufficiently large to hold non empty signature data.
+    if (rdata_len <= buffer.getPosition() - pos) {
+        dns_throw(InvalidRdataLength, "RRSIG too short");
+    }
     rdata_len -= (buffer.getPosition() - pos);
-    if (rdata_len == 0) {
-        dns_throw(InvalidRdataLength, "DS too short");
-    }
-
-    vector<uint8_t> signature;
-    for (int i = 0; i < rdata_len; i++) {
-        signature.push_back(buffer.readUint8());
-    }
+
+    vector<uint8_t> signature(rdata_len);
+    buffer.readData(&signature[0], rdata_len);
 
     impl_ = new RRSIGImpl(covered, algorithm, labels,
                           originalttl, timeexpire, timeinception, tag,

Modified: branches/each-nsec3/src/lib/dns/cpp/tests/Makefile.am
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/tests/Makefile.am (original)
+++ branches/each-nsec3/src/lib/dns/cpp/tests/Makefile.am Thu Mar  4 19:14:07 2010
@@ -11,17 +11,18 @@
 run_unittests_SOURCES += messagerenderer_unittest.cc
 run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc
 run_unittests_SOURCES += rrttl_unittest.cc
-#run_unittests_SOURCES += rdata_unittest.h rdata_unittest.cc
-#run_unittests_SOURCES += rdata_in_a_unittest.cc rdata_in_aaaa_unittest.cc
-#run_unittests_SOURCES += rdata_ns_unittest.cc rdata_soa_unittest.cc
-#run_unittests_SOURCES += rdata_txt_unittest.cc rdata_mx_unittest.cc
-#run_unittests_SOURCES += rdata_cname_unittest.cc
-#run_unittests_SOURCES += rdata_dname_unittest.cc
-#run_unittests_SOURCES += rdata_opt_unittest.cc
-#run_unittests_SOURCES += rdata_dnskey_unittest.cc
-#run_unittests_SOURCES += rdata_ds_unittest.cc
-#run_unittests_SOURCES += rdata_nsec_unittest.cc
-#run_unittests_SOURCES += rdata_rrsig_unittest.cc
+run_unittests_SOURCES += dnstime_unittest.cc
+run_unittests_SOURCES += rdata_unittest.h rdata_unittest.cc
+run_unittests_SOURCES += rdata_in_a_unittest.cc rdata_in_aaaa_unittest.cc
+run_unittests_SOURCES += rdata_ns_unittest.cc rdata_soa_unittest.cc
+run_unittests_SOURCES += rdata_txt_unittest.cc rdata_mx_unittest.cc
+run_unittests_SOURCES += rdata_cname_unittest.cc
+run_unittests_SOURCES += rdata_dname_unittest.cc
+run_unittests_SOURCES += rdata_opt_unittest.cc
+run_unittests_SOURCES += rdata_dnskey_unittest.cc
+run_unittests_SOURCES += rdata_ds_unittest.cc
+run_unittests_SOURCES += rdata_nsec_unittest.cc
+run_unittests_SOURCES += rdata_rrsig_unittest.cc
 run_unittests_SOURCES += rrset_unittest.cc rrsetlist_unittest.cc
 run_unittests_SOURCES += question_unittest.cc
 run_unittests_SOURCES += rrparamregistry_unittest.cc

Modified: branches/each-nsec3/src/lib/dns/cpp/tests/buffer_unittest.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/tests/buffer_unittest.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/tests/buffer_unittest.cc Thu Mar  4 19:14:07 2010
@@ -126,12 +126,20 @@
 {
     obuffer.writeUint32(data32);
     expected_size += sizeof(data32);
+
+    // overwrite 2nd and 3rd bytes
     obuffer.writeUint16At(data16, 1);
     EXPECT_EQ(expected_size, obuffer.getLength()); // length shouldn't change
-
     const uint8_t* cp = static_cast<const uint8_t*>(obuffer.getData());
     EXPECT_EQ(2, *(cp + 1));
     EXPECT_EQ(3, *(cp + 2));
+
+    // overwrite 3rd and 4th bytes
+    obuffer.writeUint16At(data16, 2);
+    EXPECT_EQ(expected_size, obuffer.getLength());
+    cp = static_cast<const uint8_t*>(obuffer.getData());
+    EXPECT_EQ(2, *(cp + 2));
+    EXPECT_EQ(3, *(cp + 3));
 
     EXPECT_THROW(obuffer.writeUint16At(data16, 3),
                  isc::dns::InvalidBufferPosition);

Modified: branches/each-nsec3/src/lib/dns/cpp/tests/message_unittest.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/tests/message_unittest.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/tests/message_unittest.cc Thu Mar  4 19:14:07 2010
@@ -39,11 +39,16 @@
 namespace {
 class MessageTest : public ::testing::Test {
 protected:
-    MessageTest() : obuffer(0), renderer(obuffer) {}
+    MessageTest() : obuffer(0), renderer(obuffer),
+                    message_parse(Message::PARSE),
+                    message_render(Message::RENDER)
+    {}
+    
     static Question factoryFromFile(const char* datafile);
     OutputBuffer obuffer;
     MessageRenderer renderer;
-    Message message;
+    Message message_parse;
+    Message message_render;
     static void factoryFromFile(Message& message, const char* datafile);
 };
 
@@ -80,24 +85,24 @@
 
 TEST_F(MessageTest, fromWire)
 {
-    factoryFromFile(message, "testdata/message_fromWire1");
-    EXPECT_EQ(0x1035, message.getQid());
-    EXPECT_EQ(Opcode::QUERY(), message.getOpcode());
-    EXPECT_EQ(Rcode::NOERROR(), message.getRcode());
-    EXPECT_TRUE(message.getHeaderFlag(MessageFlag::QR()));
-    EXPECT_TRUE(message.getHeaderFlag(MessageFlag::RD()));
-    EXPECT_TRUE(message.getHeaderFlag(MessageFlag::AA()));
-
-    QuestionPtr q = *message.beginQuestion();
+    factoryFromFile(message_parse, "testdata/message_fromWire1");
+    EXPECT_EQ(0x1035, message_parse.getQid());
+    EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
+    EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode());
+    EXPECT_TRUE(message_parse.getHeaderFlag(MessageFlag::QR()));
+    EXPECT_TRUE(message_parse.getHeaderFlag(MessageFlag::RD()));
+    EXPECT_TRUE(message_parse.getHeaderFlag(MessageFlag::AA()));
+
+    QuestionPtr q = *message_parse.beginQuestion();
     EXPECT_EQ(test_name, q->getName());
     EXPECT_EQ(RRType::A(), q->getType());
     EXPECT_EQ(RRClass::IN(), q->getClass());
-    EXPECT_EQ(1, message.getRRCount(Section::QUESTION()));
-    EXPECT_EQ(2, message.getRRCount(Section::ANSWER()));
-    EXPECT_EQ(0, message.getRRCount(Section::AUTHORITY()));
-    EXPECT_EQ(0, message.getRRCount(Section::ADDITIONAL()));
-
-    RRsetPtr rrset = *message.beginSection(Section::ANSWER());
+    EXPECT_EQ(1, message_parse.getRRCount(Section::QUESTION()));
+    EXPECT_EQ(2, message_parse.getRRCount(Section::ANSWER()));
+    EXPECT_EQ(0, message_parse.getRRCount(Section::AUTHORITY()));
+    EXPECT_EQ(0, message_parse.getRRCount(Section::ADDITIONAL()));
+
+    RRsetPtr rrset = *message_parse.beginSection(Section::ANSWER());
     EXPECT_EQ(test_name, rrset->getName());
     EXPECT_EQ(RRType::A(), rrset->getType());
     EXPECT_EQ(RRClass::IN(), rrset->getClass());
@@ -112,98 +117,144 @@
     EXPECT_TRUE(it->isLast());
 }
 
-TEST_F(MessageTest, EDNS0DOBit)
+TEST_F(MessageTest, GetEDNS0DOBit)
 {
     // Without EDNS0, DNSSEC is considered to be unsupported.
-    factoryFromFile(message, "testdata/message_fromWire1");
-    EXPECT_FALSE(message.isDNSSECSupported());
+    factoryFromFile(message_parse, "testdata/message_fromWire1");
+    EXPECT_FALSE(message_parse.isDNSSECSupported());
 
     // If DO bit is on, DNSSEC is considered to be supported.
-    message.clear();
-    factoryFromFile(message, "testdata/message_fromWire2");
-    EXPECT_TRUE(message.isDNSSECSupported());
+    message_parse.clear();
+    factoryFromFile(message_parse, "testdata/message_fromWire2");
+    EXPECT_TRUE(message_parse.isDNSSECSupported());
 
     // If DO bit is off, DNSSEC is considered to be unsupported.
-    message.clear();
-    factoryFromFile(message, "testdata/message_fromWire3");
-    EXPECT_FALSE(message.isDNSSECSupported());
-}
-
-TEST_F(MessageTest, EDNS0UDPSize)
+    message_parse.clear();
+    factoryFromFile(message_parse, "testdata/message_fromWire3");
+    EXPECT_FALSE(message_parse.isDNSSECSupported());
+}
+
+TEST_F(MessageTest, SetEDNS0DOBit)
+{
+    // By default, it's false, and we can enable/disable it.
+    EXPECT_FALSE(message_render.isDNSSECSupported());
+    message_render.setDNSSECSupported(true);
+    EXPECT_TRUE(message_render.isDNSSECSupported());
+    message_render.setDNSSECSupported(false);
+    EXPECT_FALSE(message_render.isDNSSECSupported());
+
+    // A message in the parse mode doesn't allow this flag to be set.
+    EXPECT_THROW(message_parse.setDNSSECSupported(true),
+                 InvalidMessageOperation);
+    // Once converted to the render mode, it works as above
+    message_parse.makeResponse();
+    EXPECT_FALSE(message_parse.isDNSSECSupported());
+    message_parse.setDNSSECSupported(true);
+    EXPECT_TRUE(message_parse.isDNSSECSupported());
+    message_parse.setDNSSECSupported(false);
+    EXPECT_FALSE(message_parse.isDNSSECSupported());
+}
+
+TEST_F(MessageTest, GetEDNS0UDPSize)
 {
     // Without EDNS0, the default max UDP size is used.
-    factoryFromFile(message, "testdata/message_fromWire1");
-    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message.getUDPSize());
+    factoryFromFile(message_parse, "testdata/message_fromWire1");
+    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message_parse.getUDPSize());
 
     // If the size specified in EDNS0 > default max, use it.
-    message.clear();
-    factoryFromFile(message, "testdata/message_fromWire2");
-    EXPECT_EQ(4096, message.getUDPSize());
+    message_parse.clear();
+    factoryFromFile(message_parse, "testdata/message_fromWire2");
+    EXPECT_EQ(4096, message_parse.getUDPSize());
 
     // If the size specified in EDNS0 < default max, keep using the default.
-    message.clear();
-    factoryFromFile(message, "testdata/message_fromWire8");
-    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message.getUDPSize());
+    message_parse.clear();
+    factoryFromFile(message_parse, "testdata/message_fromWire8");
+    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message_parse.getUDPSize());
+}
+
+TEST_F(MessageTest, SetEDNS0UDPSize)
+{
+    // The default size if unspecified
+    EXPECT_EQ(Message::DEFAULT_MAX_UDPSIZE, message_render.getUDPSize());
+    // A common buffer size with EDNS, should succeed
+    message_render.setUDPSize(4096);
+    EXPECT_EQ(4096, message_render.getUDPSize());
+    // Unusual large value, but accepted
+    message_render.setUDPSize(0xffff);
+    EXPECT_EQ(0xffff, message_render.getUDPSize());
+    // Too small is value is rejected
+    EXPECT_THROW(message_render.setUDPSize(511), InvalidMessageUDPSize);
+
+    // A message in the parse mode doesn't allow the set operation.
+    EXPECT_THROW(message_parse.setUDPSize(4096), InvalidMessageOperation);
+    // Once converted to the render mode, it works as above.
+    message_parse.makeResponse();
+    message_parse.setUDPSize(4096);
+    EXPECT_EQ(4096, message_parse.getUDPSize());
+    message_parse.setUDPSize(0xffff);
+    EXPECT_EQ(0xffff, message_parse.getUDPSize());
+    EXPECT_THROW(message_parse.setUDPSize(511), InvalidMessageUDPSize);
 }
 
 TEST_F(MessageTest, EDNS0ExtCode)
 {
     // Extended Rcode = BADVERS
-    factoryFromFile(message, "testdata/message_fromWire10");
-    EXPECT_EQ(Rcode::BADVERS(), message.getRcode());
+    factoryFromFile(message_parse, "testdata/message_fromWire10");
+    EXPECT_EQ(Rcode::BADVERS(), message_parse.getRcode());
 
     // Maximum extended Rcode
-    message.clear();
-    factoryFromFile(message, "testdata/message_fromWire11");
-    EXPECT_EQ(0xfff, message.getRcode().getCode());
+    message_parse.clear();
+    factoryFromFile(message_parse, "testdata/message_fromWire11");
+    EXPECT_EQ(0xfff, message_parse.getRcode().getCode());
 }
 
 TEST_F(MessageTest, BadEDNS0)
 {
     // OPT RR in the answer section
-    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire4"),
+    EXPECT_THROW(factoryFromFile(message_parse, "testdata/message_fromWire4"),
                  DNSMessageFORMERR);
     // multiple OPT RRs (in the additional section)
-    message.clear();
-    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire5"),
+    message_parse.clear();
+    EXPECT_THROW(factoryFromFile(message_parse, "testdata/message_fromWire5"),
                  DNSMessageFORMERR);
     // OPT RR of a non root name
-    message.clear();
-    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire6"),
+    message_parse.clear();
+    EXPECT_THROW(factoryFromFile(message_parse, "testdata/message_fromWire6"),
                  DNSMessageFORMERR);
     // Compressed owner name of OPT RR points to a root name.
     // Not necessarily bogus, but very unusual and mostly pathological.
     // We accept it, but is it okay?
-    message.clear();
-    EXPECT_NO_THROW(factoryFromFile(message, "testdata/message_fromWire7"));
+    message_parse.clear();
+    EXPECT_NO_THROW(factoryFromFile(message_parse,
+                                    "testdata/message_fromWire7"));
     // Unsupported Version
-    message.clear();
-    EXPECT_THROW(factoryFromFile(message, "testdata/message_fromWire9"),
+    message_parse.clear();
+    EXPECT_THROW(factoryFromFile(message_parse, "testdata/message_fromWire9"),
                  DNSMessageBADVERS);
 }
 
 TEST_F(MessageTest, toWire)
 {
-    message.setQid(0x1035);
-    message.setOpcode(Opcode::QUERY());
-    message.setRcode(Rcode::NOERROR());
-    message.setHeaderFlag(MessageFlag::QR());
-    message.setHeaderFlag(MessageFlag::RD());
-    message.setHeaderFlag(MessageFlag::AA());
-    message.addQuestion(Question(Name("test.example.com"), RRClass::IN(),
-                                     RRType::A()));
+    message_render.setQid(0x1035);
+    message_render.setOpcode(Opcode::QUERY());
+    message_render.setRcode(Rcode::NOERROR());
+    message_render.setHeaderFlag(MessageFlag::QR());
+    message_render.setHeaderFlag(MessageFlag::RD());
+    message_render.setHeaderFlag(MessageFlag::AA());
+    message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(),
+                                        RRType::A()));
     RRsetPtr rrset = RRsetPtr(new RRset(Name("test.example.com"), RRClass::IN(),
                                         RRType::A(), RRTTL(3600)));
     rrset->addRdata(in::A("192.0.2.1"));
     rrset->addRdata(in::A("192.0.2.2"));
-    message.addRRset(Section::ANSWER(), rrset);
-
-    EXPECT_EQ(1, message.getRRCount(Section::QUESTION()));
-    EXPECT_EQ(2, message.getRRCount(Section::ANSWER()));
-    EXPECT_EQ(0, message.getRRCount(Section::AUTHORITY()));
-    EXPECT_EQ(0, message.getRRCount(Section::ADDITIONAL()));
-
-    message.toWire(renderer);
+    message_render.addRRset(Section::ANSWER(), rrset);
+
+    EXPECT_EQ(1, message_render.getRRCount(Section::QUESTION()));
+    EXPECT_EQ(2, message_render.getRRCount(Section::ANSWER()));
+    EXPECT_EQ(0, message_render.getRRCount(Section::AUTHORITY()));
+    EXPECT_EQ(0, message_render.getRRCount(Section::ADDITIONAL()));
+
+    message_render.toWire(renderer);
     vector<unsigned char> data;
     UnitTestUtil::readWireData("testdata/message_toWire1", data);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),

Modified: branches/each-nsec3/src/lib/dns/cpp/tests/rdata_nsec_unittest.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/tests/rdata_nsec_unittest.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/tests/rdata_nsec_unittest.cc Thu Mar  4 19:14:07 2010
@@ -58,8 +58,17 @@
 {
     const generic::NSEC rdata_nsec(nsec_txt);
     EXPECT_EQ(0, rdata_nsec.compare(
-                  *rdataFactoryFromFile(RRType("NSEC"), RRClass("IN"),
-                                        "testdata/rdata_nsec_fromWire")));
+                  *rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+                                        "testdata/rdata_nsec_fromWire1")));
+
+    // Too short RDLENGTH
+    EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+                                      "testdata/rdata_nsec_fromWire2"),
+                 InvalidRdataLength);
+
+    // This should be rejected
+    //rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+    //                   "testdata/rdata_nsec_fromWire3")->toText();
 }
 
 TEST_F(Rdata_NSEC_Test, toWireRenderer_NSEC)
@@ -69,7 +78,7 @@
     rdata_nsec.toWire(renderer);
 
     vector<unsigned char> data;
-    UnitTestUtil::readWireData("testdata/rdata_nsec_fromWire", data);
+    UnitTestUtil::readWireData("testdata/rdata_nsec_fromWire1", data);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
                         static_cast<const uint8_t *>(obuffer.getData()) + 2,
                         obuffer.getLength() - 2, &data[2], data.size() - 2);

Modified: branches/each-nsec3/src/lib/dns/cpp/tests/rdata_rrsig_unittest.cc
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/tests/rdata_rrsig_unittest.cc (original)
+++ branches/each-nsec3/src/lib/dns/cpp/tests/rdata_rrsig_unittest.cc Thu Mar  4 19:14:07 2010
@@ -38,7 +38,7 @@
     // there's nothing to specialize
 };
 
-TEST_F(Rdata_RRSIG_Test, fromText_RRSIG)
+TEST_F(Rdata_RRSIG_Test, fromText)
 {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
@@ -50,7 +50,7 @@
 
 }
 
-TEST_F(Rdata_RRSIG_Test, badText_RRSIG)
+TEST_F(Rdata_RRSIG_Test, badText)
 {
     EXPECT_THROW(const generic::RRSIG sig("SPORK"), InvalidRdataText);
     EXPECT_THROW(const generic::RRSIG sig("A 555 4 43200 "
@@ -78,12 +78,6 @@
                      "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
                      "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidTime);
     EXPECT_THROW(const generic::RRSIG sig("A 5 4 43200 "
-                     "19100223214617 19100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc="), InvalidTime);
-    EXPECT_THROW(const generic::RRSIG sig("A 5 4 43200 "
                      "20100223214617 20100222214617 999999 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
                      "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
@@ -95,7 +89,7 @@
                      BadBase64String);
 }
 
-TEST_F(Rdata_RRSIG_Test, toWireRenderer_RRSIG)
+TEST_F(Rdata_RRSIG_Test, toWireRenderer)
 {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
@@ -106,7 +100,7 @@
     rdata_rrsig.toWire(renderer);
 }
 
-TEST_F(Rdata_RRSIG_Test, toWireBuffer_RRSIG)
+TEST_F(Rdata_RRSIG_Test, toWireBuffer)
 {
     string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
                      "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
@@ -117,19 +111,22 @@
     rdata_rrsig.toWire(obuffer);
 }
 
-TEST_F(Rdata_RRSIG_Test, createFromWire_RRSIG)
+TEST_F(Rdata_RRSIG_Test, createFromWire)
 {
     string rrsig_txt("A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
                 "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
                 "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"
                 "m36Mo2/Gdxjj8lJ/IjPVkdpKyBpcnYND8KEIma5MyNCNeyO1UkfPQZGHNSQ=");
     EXPECT_EQ(rrsig_txt, rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
-                             "testdata/rdata_rrsig_fromWire")->toText());
+                             "testdata/rdata_rrsig_fromWire1")->toText());
     generic::RRSIG rdata_rrsig(rrsig_txt);
     EXPECT_EQ(0, rdata_rrsig.compare(
                       *rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
-                                          "testdata/rdata_rrsig_fromWire")));
+                                          "testdata/rdata_rrsig_fromWire1")));
+
+    // RDLEN is too short
+    EXPECT_THROW(rdataFactoryFromFile(RRType::RRSIG(), RRClass::IN(),
+                                      "testdata/rdata_rrsig_fromWire2"),
+                 InvalidRdataLength);
 }
-
-
 }

Modified: branches/each-nsec3/src/lib/dns/cpp/tests/testdata/gen-wiredata.py.in
==============================================================================
--- branches/each-nsec3/src/lib/dns/cpp/tests/testdata/gen-wiredata.py.in (original)
+++ branches/each-nsec3/src/lib/dns/cpp/tests/testdata/gen-wiredata.py.in Thu Mar  4 19:14:07 2010
@@ -1,11 +1,14 @@
 #!@PYTHON@
 
-import configparser, re, sys
+import configparser, re, time, sys
+from datetime import datetime
 from optparse import OptionParser
 
 re_hex = re.compile('0x[0-9a-fA-F]+')
-re_decimal = re.compile('\d+')
-re_ = re.compile('\d+$')
+re_decimal = re.compile('\d+$')
+
+dnssec_timefmt = '%Y%m%d%H%M%S'
+
 dict_qr = { 'query' : 0, 'response' : 1 }
 dict_opcode = { 'query' : 0, 'iquery' : 1, 'status' : 2, 'notify' : 4,
                 'update' : 5 }
@@ -30,9 +33,13 @@
 rdict_rrtype = dict([(dict_rrtype[k], k.upper()) for k in dict_rrtype.keys()])
 dict_rrclass = { 'in' : 1, 'ch' : 3, 'hs' : 4, 'any' : 255 }
 rdict_rrclass = dict([(dict_rrclass[k], k.upper()) for k in dict_rrclass.keys()])
+dict_algorithm = { 'rsamd5' : 1, 'dh' : 2, 'dsa' : 3, 'ecc' : 4, 'rsasha1' : 5 }
+rdict_algorithm = dict([(dict_algorithm[k], k.upper()) for k in dict_algorithm.keys()])
+
 header_xtables = { 'qr' : dict_qr, 'opcode' : dict_opcode,
                    'rcode' : dict_rcode }
 question_xtables = { 'rrtype' : dict_rrtype, 'rrclass' : dict_rrclass }
+rrsig_xtables = { 'algorithm' : dict_algorithm }
 
 def parse_value(value, xtable = {}):
     if re.search(re_hex, value):
@@ -61,6 +68,14 @@
         if len(l) == 0:
             break
     return wire
+
+def count_namelabels(name):
+    if name == '.':             # special case
+        return 0
+    m = re.match('^(.*)\.$', name)
+    if m:
+        name = m.group(1)
+    return len(name.split('.'))
 
 def get_config(config, section, configobj, xtables = {}):
     try:
@@ -148,6 +163,46 @@
         f.write('# RDLEN=%d\n' % self.rdlen)
         f.write('%04x\n' % self.rdlen)
 
+class RRSIG:
+    rdlen = -1                  # auto-calculate
+    covered = 1                 # A
+    algorithm = 5               # RSA-SHA1
+    labels = -1                 # auto-calculate (#labels of signer)
+    originalttl = 3600
+    expiration = int(time.mktime(datetime.strptime('20100131120000',
+                                                   dnssec_timefmt).timetuple()))
+    inception = int(time.mktime(datetime.strptime('20100101120000',
+                                                  dnssec_timefmt).timetuple()))
+    tag = 0x1035
+    signer = 'example.com'
+    signature = 0x123456789abcdef123456789abcdef
+    def dump(self, f):
+        name_wire = encode_name(self.signer)
+        sig_wire = '%x' % self.signature 
+        rdlen = self.rdlen
+        if rdlen < 0:
+            rdlen = int(18 + len(name_wire) / 2 + len(str(sig_wire)) / 2)
+        labels = self.labels
+        if labels < 0:
+            labels = count_namelabels(self.signer)
+        f.write('\n# RRSIG RDATA (RDLEN=%d)\n' % rdlen)
+        f.write('%04x\n' % rdlen);
+        f.write('# Covered=%s Algorithm=%s Labels=%d OrigTTL=%d\n' %
+                (code_totext(self.covered, rdict_rrtype),
+                 code_totext(self.algorithm, rdict_algorithm), labels,
+                 self.originalttl))
+        f.write('%04x %02x %02x %08x\n' % (self.covered, self.algorithm, labels,
+                                           self.originalttl))
+        f.write('# Expiration=%s, Inception=%s\n' %
+                (str(self.expiration), str(self.inception)))
+        f.write('%08x %08x\n' % (self.expiration, self.inception))
+        f.write('# Tag=%d Signer=%s and Signature\n' % (self.tag, self.signer))
+        f.write('%04x %s %s\n' % (self.tag, name_wire, sig_wire))
+
+config_param = {'header' : (DNSHeader, header_xtables),
+                'question' : (DNSQuestion, question_xtables),
+                'edns' : (EDNS, {}), 'rrsig' : (RRSIG, {}) }
+
 usage = '''usage: %prog [options] input_file'''
 
 if __name__ == "__main__":
@@ -155,6 +210,9 @@
     parser.add_option('-o', '--output', action='store', dest='output',
                       default=None, metavar='FILE',
                       help='output file name [default: prefix of input_file]')
+    parser.add_option('-m', '--mode', action='store', dest='mode',
+                      default='message', metavar='[message|custom]',
+                      help='specify dump mode [default: %default]')
     (options, args) = parser.parse_args()
 
     if len(args) == 0:
@@ -163,7 +221,7 @@
 
     outputfile = options.output
     if not outputfile:
-        m = re.match('(.*)\.[^.]+$', sys.argv[1])
+        m = re.match('(.*)\.[^.]+$', configfile)
         if m:
             outputfile = m.group(1)
         else:
@@ -176,16 +234,15 @@
 
     print_header(output, configfile)
 
-    header = DNSHeader()
-    if get_config(config, 'header', header, header_xtables):
-        header.dump(output)
-
-    question = DNSQuestion()
-    if get_config(config, 'question', question, question_xtables):
-        question.dump(output)
-
-    edns = EDNS()
-    if get_config(config, 'edns', edns):
-        edns.dump(output)
+    if options.mode == 'custom':
+        sections = config.get('custom', 'sections').split(':')
+    else:
+        sections = ['header', 'question', 'edns']
+
+    for s in sections:
+        section_param = config_param[s]
+        (obj, xtables) = (section_param[0](), section_param[1])
+        if get_config(config, s, obj, xtables):
+            obj.dump(output)
 
     output.close()




More information about the bind10-changes mailing list