Browse Source

Merged experiments/each-query branch into parkinglot.

(This now builds the b10-auth binary.  The b10-parkinglot binary is
still being built for reference purposes, but is expected to be removed.
Both programs use port 5300, so they cannot be run simultaneously.)


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@690 e5f2f494-b856-4b98-b285-d166d9295462
Evan Hunt 15 years ago
parent
commit
8399a64371

+ 4 - 0
configure.ac

@@ -151,6 +151,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/cfgmgr/Makefile
                  src/bin/host/Makefile
                  src/bin/msgq/Makefile
+                 src/bin/auth/Makefile
                  src/bin/parkinglot/Makefile
                  src/lib/Makefile
                  src/lib/cc/Makefile
@@ -166,6 +167,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/config/python/isc/config/Makefile
                  src/lib/dns/Makefile
                  src/lib/dns/cpp/Makefile
+                 src/lib/auth/Makefile
+                 src/lib/auth/cpp/Makefile
                ])
 AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            src/bin/cfgmgr/run_b10-cfgmgr.sh
@@ -179,6 +182,7 @@ AC_OUTPUT([src/bin/cfgmgr/b10-cfgmgr.py
            src/bin/msgq/msgq.py
            src/bin/msgq/msgq_test
            src/bin/msgq/run_msgq.sh
+           src/bin/auth/config.h
            src/bin/parkinglot/config.h
            src/lib/dns/cpp/gen-rdatacode.py
           ], [

+ 1 - 1
src/bin/Makefile.am

@@ -1 +1 @@
-SUBDIRS = bind10 bindctl cfgmgr msgq parkinglot host cmdctl
+SUBDIRS = bind10 bindctl cfgmgr msgq host cmdctl auth parkinglot

+ 10 - 0
src/bin/auth/Makefile.am

@@ -0,0 +1,10 @@
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_builddir)/src/lib/dns/cpp -I$(top_srcdir)/src/lib/dns/cpp -I$(top_srcdir)/src/lib -I$(top_srcdir)/ext
+
+bin_PROGRAMS = b10-auth
+b10_auth_SOURCES = auth_srv.cc auth_srv.h
+b10_auth_SOURCES += common.cc common.h
+b10_auth_SOURCES += main.cc
+b10_auth_LDADD =  $(top_builddir)/src/lib/dns/cpp/.libs/libdns.a
+b10_auth_LDADD +=  $(top_builddir)/src/lib/auth/cpp/.libs/libauth.a
+b10_auth_LDADD += $(top_builddir)/src/lib/config/cpp/libclient.a
+b10_auth_LDADD += $(top_builddir)/src/lib/cc/cpp/libcc.a

+ 6 - 0
src/bin/auth/auth.spec

@@ -0,0 +1,6 @@
+{
+  "data_specification": {
+    "module_name": "ParkingLot"
+  }
+}
+

+ 123 - 0
src/bin/auth/auth_srv.cc

@@ -0,0 +1,123 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <set>
+#include <iostream>
+
+#include <dns/cpp/buffer.h>
+#include <dns/cpp/messagerenderer.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/question.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/rrttl.h>
+#include <dns/cpp/message.h>
+
+#include <cc/cpp/data.h>
+
+#include "common.h"
+#include "auth_srv.h"
+
+#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace isc::data;
+
+AuthSrv::AuthSrv(int port) {
+    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (s < 0)
+        throw FatalError("failed to open socket");
+
+    struct sockaddr_in sin;
+    sin.sin_family = AF_INET;
+    sin.sin_addr.s_addr = INADDR_ANY;
+    sin.sin_port = htons(port);
+
+    socklen_t sa_len = sizeof(sin);
+#ifdef HAVE_SIN_LEN
+    sin.sin_len = sa_len;
+#endif
+
+    if (bind(s, (struct sockaddr *)&sin, sa_len) < 0)
+        throw FatalError("could not bind socket");
+
+    sock = s;
+}
+
+void
+AuthSrv::processMessage() {
+    struct sockaddr_storage ss;
+    socklen_t sa_len = sizeof(ss);
+    struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
+    int s = sock;
+    Message msg;
+    char recvbuf[4096];
+    int cc;
+
+    if ((cc = recvfrom(s, recvbuf, sizeof(recvbuf), 0, sa, &sa_len)) > 0) {
+        InputBuffer buffer(recvbuf, cc);
+        try {
+            msg.fromWire(buffer);
+        } catch (...) {
+            cerr << "[AuthSrv] parse failed" << endl;
+            return;
+        }
+
+        cout << "[AuthSrv] received a message:\n" << msg.toText() << endl;
+
+        if (msg.getRRCount(Section::QUESTION()) != 1) {
+            return;
+        }
+
+        QuestionPtr query = *msg.beginQuestion();
+
+        msg.makeResponse();
+        msg.setHeaderFlag(MessageFlag::AA());
+        msg.setRcode(Rcode::NOERROR());
+
+        // do the DataSource call here
+        Query q = Query(msg, false);
+        data_src.runQuery(q);
+
+        OutputBuffer obuffer(4096);
+        MessageRenderer renderer(obuffer);
+        msg.toWire(renderer);
+        cout << "sending a response (" <<
+            boost::lexical_cast<string>(obuffer.getLength())
+                  << " bytes):\n" << msg.toText() << endl;
+        sendto(s, obuffer.getData(), obuffer.getLength(), 0, sa, sa_len);
+    }
+}
+
+ElementPtr
+AuthSrv::updateConfig(isc::data::ElementPtr config) {
+    //if (config->contains("port")) {
+        // todo: what to do with port change. restart automatically?
+        // ignore atm
+    //}
+    return isc::data::Element::createFromString("{ \"result\": [0] }");
+}

+ 40 - 0
src/bin/auth/auth_srv.h

@@ -0,0 +1,40 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#ifndef __AUTH_SRV_H
+#define __AUTH_SRV_H 1
+
+#include <cc/cpp/data.h>
+#include <auth/cpp/data_source_static.h>
+
+class AuthSrv {
+public:
+    explicit AuthSrv(int port);
+    //~AuthSrv() {}
+    int getSocket() { return (sock); }
+    void processMessage();
+    void serve(std::string zone_name);
+
+    isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
+private:
+
+    // TODO: make this a MetaDataSrc, but that one is abstract...
+    isc::dns::StaticDataSrc data_src;
+    int sock;
+};
+
+#endif // __AUTH_SRV_H
+

+ 23 - 0
src/bin/auth/common.cc

@@ -0,0 +1,23 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+#include "common.h"
+#include <iostream>
+
+FatalError::FatalError(std::string m) {
+    msg = m;
+    std::cerr << msg << std::endl;
+    exit(1);
+}

+ 36 - 0
src/bin/auth/common.h

@@ -0,0 +1,36 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#ifndef __COMMON_H
+#define __COMMON_H 1
+
+#include <stdlib.h>
+#include <string>
+
+class FatalError : public std::exception {
+public:
+    FatalError(std::string m = "fatal error");
+    ~FatalError() throw() {}
+    const char* what() const throw() { return msg.c_str(); }
+private:
+    std::string msg;
+};
+
+#endif // __COMMON_H
+
+// Local Variables:
+// mode: c++
+// End:

+ 1 - 0
src/bin/auth/config.h.in

@@ -0,0 +1 @@
+#define AUTH_SPECFILE_LOCATION "@abs_top_srcdir@/src/bin/auth/auth.spec"

+ 140 - 0
src/bin/auth/main.cc

@@ -0,0 +1,140 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netdb.h>
+#include <stdlib.h>
+
+#include <set>
+#include <iostream>
+
+#include <boost/foreach.hpp>
+
+#include <dns/cpp/buffer.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/message.h>
+
+#include <cc/cpp/session.h>
+#include <cc/cpp/data.h>
+#include <config/cpp/ccsession.h>
+
+#include "common.h"
+#include "config.h"
+#include "auth_srv.h"
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+const string PROGRAM = "Auth";
+const int DNSPORT = 5300;
+
+/* need global var for config/command handlers.
+ * todo: turn this around, and put handlers in the authserver
+ * class itself? */
+AuthSrv auth = AuthSrv(DNSPORT);
+
+static void
+usage() {
+    cerr << "Usage: b10-auth [-p port]" << endl;
+    exit(1);
+}
+
+isc::data::ElementPtr
+my_config_handler(isc::data::ElementPtr config)
+{
+    return auth.updateConfig(config);
+}
+
+isc::data::ElementPtr
+my_command_handler(isc::data::ElementPtr command) {
+    isc::data::ElementPtr answer = isc::data::Element::createFromString("{ \"result\": [0] }");
+
+    cout << "[XX] Handle command: " << endl << command->str() << endl;
+    if (command->get(0)->stringValue() == "print_message") 
+    {
+        cout << command->get(1)->get("message") << endl;
+        /* let's add that message to our answer as well */
+        cout << "[XX] answer was: " << answer->str() << endl;
+        answer->get("result")->add(command->get(1));
+        cout << "[XX] answer now: " << answer->str() << endl;
+    }
+
+    return answer;
+}
+
+int
+main(int argc, char* argv[]) {
+    int ch;
+    int port = DNSPORT;
+
+    while ((ch = getopt(argc, argv, "p:")) != -1) {
+        switch (ch) {
+        case 'p':
+            port = atoi(optarg);
+            break;
+        case '?':
+        default:
+            usage();
+        }
+    }
+
+    if (argc - optind > 0)
+        usage();
+
+    // initialize command channel
+    try {
+        CommandSession cs = CommandSession(AUTH_SPECFILE_LOCATION,
+                                           my_config_handler,
+                                           my_command_handler);
+    
+        // main server loop
+        fd_set fds;
+        int ps = auth.getSocket();
+        int ss = cs.getSocket();
+        int nfds = max(ps, ss) + 1;
+        int counter = 0;
+    
+        cout << "Server started." << endl;
+        while (true) {
+            FD_ZERO(&fds);
+            FD_SET(ps, &fds);
+            FD_SET(ss, &fds);
+    
+            int n = select(nfds, &fds, NULL, NULL, NULL);
+            if (n < 0)
+                throw FatalError("select error");
+    
+            if (FD_ISSET(ps, &fds)) {
+                ++counter;
+                auth.processMessage();
+            }
+    
+            /* isset not really necessary, but keep it for now */
+            if (FD_ISSET(ss, &fds)) {
+                cs.check_command();
+            }
+        }
+    } catch (isc::cc::SessionError se) {
+        cout << se.what() << endl;
+        exit(1);
+    }
+    
+    return (0);
+}

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

@@ -194,16 +194,16 @@ class BoB:
         # XXX: this must be read from the configuration manager in the future
         # XXX: we hardcode port 5300
         if self.verbose:
-            sys.stdout.write("Starting b10-parkinglot on port 5300\n")
+            sys.stdout.write("Starting b10-auth  on port 5300\n")
         try:
-            parkinglot = ProcessInfo("b10-parkinglot", ["b10-parkinglot", "-p", "5300"])
+            auth = ProcessInfo("b10-auth", ["b10-auth", "-p", "5300"])
         except Exception as e:
             c_channel.process.kill()
             bind_cfgd.process.kill()
-            return "Unable to start b10-parkinglot; " + str(e)
-        self.processes[parkinglot.pid] = parkinglot
+            return "Unable to start b10-auth; " + str(e)
+        self.processes[auth.pid] = auth
         if self.verbose:
-            sys.stdout.write("Started b10-parkinglot (PID %d)\n" % parkinglot.pid)
+            sys.stdout.write("Started b10-auth (PID %d)\n" % auth.pid)
 
         # start the b10-cmdctl
         # XXX: we hardcode port 8080
@@ -214,7 +214,7 @@ class BoB:
         except Exception as e:
             c_channel.process.kill()
             bind_cfgd.process.kill()
-            parkinglot.process.kill()
+            auth.process.kill()
             return "Unable to start b10-cmdctl; " + str(e)
         self.processes[cmd_ctrld.pid] = cmd_ctrld
         if self.verbose:

+ 1 - 1
src/bin/bind10/bind10_test.in

@@ -5,7 +5,7 @@ export PYTHON_EXEC
 
 BIND10_PATH=@abs_top_srcdir@/src/bin/bind10
 
-PATH=@abs_top_srcdir@/src/bin/msgq:@abs_top_srcdir@/src/bin/parkinglot:@abs_top_srcdir@/src/bin/bind-cfgd:$PATH
+PATH=@abs_top_srcdir@/src/bin/msgq:@abs_top_srcdir@/src/bin/auth:@abs_top_srcdir@/src/bin/bind-cfgd:$PATH
 export PATH
 
 PYTHONPATH=@abs_top_srcdir@/src/lib/cc/python:${abs_top_src_dir}/lib/cc/python/ISC

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

@@ -5,7 +5,7 @@ export PYTHON_EXEC
 
 BIND10_PATH=@abs_top_builddir@/src/bin/bind10
 
-PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/parkinglot:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:$PATH
+PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:$PATH
 export PATH
 
 PYTHONPATH=@abs_top_srcdir@/src/lib/cc/python:@abs_top_srcdir@/src/lib/config/python

+ 1 - 1
src/lib/Makefile.am

@@ -1 +1 @@
-SUBDIRS = cc config dns
+SUBDIRS = cc config dns auth

+ 1 - 0
src/lib/auth/Makefile.am

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

+ 9 - 0
src/lib/auth/cpp/Makefile.am

@@ -0,0 +1,9 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/ext
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libauth.la
+libauth_la_SOURCES = data_source.h data_source.cc
+libauth_la_SOURCES += data_source_static.h data_source_static.cc
+#libauth_la_SOURCES += data_source_plot.h data_source_plot.cc
+libauth_la_SOURCES += query.h query.cc

+ 5 - 0
src/lib/auth/cpp/TODO

@@ -0,0 +1,5 @@
+- NXDOMAIN case must add NSEC/NSEC3 data when wantDnssec()
+- DataSrc should implement a method findAddrRRsets() which queries
+  for A and AAAA records.  at the high level this would be implemented
+  as two queries in serial; low level subclasses could override it with
+  a single query.

+ 118 - 0
src/lib/auth/cpp/data_source.cc

@@ -0,0 +1,118 @@
+#include <dns/cpp/buffer.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/message.h>
+
+#include <cc/cpp/data.h>
+
+#include "data_source.h"
+
+namespace isc {
+namespace dns {
+
+DSResult
+DataSrc::runQuery(Query q) {
+    DSResult result;
+    RRsetList data, sigs;
+    Name container(".");
+    Message& m = q.message();
+
+    while (!q.tasks().empty()) {
+        bool found = false;
+        QueryTaskPtr task = q.tasks().front();
+        q.tasks().pop();
+
+        const DataSrc* ds = findClosestEnclosure(task->qname, container, found);
+
+        if (ds == NULL) {
+            result = ZONE_NOT_FOUND;
+        } else if (q.wantDnssec()) {
+            result = ds->findRRset(task->qname, task->qclass, task->qtype,
+                                   data, sigs);
+            // XXX validity check:
+            // for now, there must only be exactly one RRset in data
+            // and no more than one RRset in sigs.  the rrtype of data
+            // must match the sigtype of sigs, if any
+        } else {
+            result = ds->findRRset(task->qname, task->qclass, task->qtype,
+                                   data);
+        }
+
+        switch (result) {
+            case SUCCESS:
+                m.addRRset(task->section, data[0]);
+                if (q.wantDnssec() && sigs.size() == 1) {
+                    m.addRRset(Section(task->section), sigs[0]);
+                }
+
+                if (q.status() == QUERY_FINISHING) {
+                    q.setStatus(QUERY_DONE);
+                    return (SUCCESS);
+                }
+
+                // if there are no more work items, add the authority section
+                if (q.tasks().empty() && q.status() == QUERY_INCOMPLETE) {
+                    QueryTask *qt = new QueryTask(container, task->qclass,
+                                                  RRType::NS(),
+                                                  Section::AUTHORITY());
+                    q.tasks().push(QueryTaskPtr(qt));
+                    q.setStatus(QUERY_FINISHING);
+                }
+                continue;
+
+            case CNAME:
+                m.addRRset(task->section, data[0]);
+                if (q.wantDnssec() && sigs.size() == 1) {
+                    m.addRRset(Section(task->section), sigs[0]);
+                }
+
+                // if (data[0].getType() == RRType::CNAME()) {
+                //     // take apart the CNAME rdata and re-query HERE
+                // }
+                continue;
+
+            case NAME_NOT_FOUND:
+                q.setStatus(QUERY_NODATA);
+                if (q.wantDnssec()) {
+                    result = ds->findRRset(container, task->qclass,
+                                           RRType::SOA(), data, sigs);
+                } else {
+                    result = ds->findRRset(container, task->qclass, 
+                                           RRType::SOA(), data);
+                }
+
+                if (result != SUCCESS) {
+                    m.setRcode(Rcode::SERVFAIL());
+                    return (ERROR);
+                }
+
+                m.setRcode(Rcode::NXDOMAIN());
+                m.addRRset(Section::AUTHORITY(), data[0]);
+                if (q.wantDnssec() && sigs.size() == 1) {
+                    m.addRRset(Section::AUTHORITY(), sigs[0]);
+                }
+                break;
+
+            case TYPE_NOT_FOUND:
+                m.setRcode(Rcode::NOERROR());
+                q.setStatus(QUERY_NODATA);
+                return (result);
+
+            case ZONE_NOT_FOUND:
+                m.setRcode(Rcode::REFUSED());
+                q.setStatus(QUERY_NODATA);
+                return (result);
+
+            default:
+                m.setRcode(Rcode::SERVFAIL());
+                q.setStatus(QUERY_NODATA);
+                return (result);
+        }
+    }
+
+    return (result);
+};
+
+
+}
+}

+ 154 - 0
src/lib/auth/cpp/data_source.h

@@ -0,0 +1,154 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#ifndef __DATA_SOURCE_H
+#define __DATA_SOURCE_H
+
+#include <boost/foreach.hpp>
+#include <dns/cpp/name.h>
+#include <dns/cpp/rrset.h>
+#include <auth/cpp/query.h>
+
+namespace isc {
+namespace dns {
+
+enum DSResult {
+    SUCCESS,
+    NOT_IMPLEMENTED,
+    ERROR,
+    CNAME,
+    ZONE_NOT_FOUND,
+    NAME_NOT_FOUND,
+    TYPE_NOT_FOUND
+};
+
+class DataSrc;
+
+class AbstractDataSrc {
+public:
+    virtual ~AbstractDataSrc() {};
+
+    // 'High-level' methods.  These will be implemented by the
+    // general DataSrc class, but MAY be overwritten by subclasses.
+    virtual DSResult runQuery(Query query) = 0;
+
+    // Mandatory 'low-level' methods: These will NOT be implemented by
+    // the general DataSrc class; subclasses MUST implement them.
+    virtual DSResult findRRset(const Name& qname,
+                               const RRClass& qclass,
+                               const RRType& qtype,
+                               RRsetList& target,
+                               RRsetList& sigs) const = 0;
+
+    virtual DSResult findRRset(const Name& qname,
+                               const RRClass& qclass,
+                               const RRType& qtype,
+                               RRsetList& target) const = 0;
+
+    virtual const DataSrc* findClosestEnclosure(const Name& qname,
+                                                Name& container,
+                                                bool& found) const = 0;
+
+    // Optional 'low-level' methods.  These will have stub implementations
+    // in the general DataSrc class but MAY be overwritten by subclasses
+    virtual DSResult init() = 0;
+    virtual DSResult close() = 0;
+
+    //virtual const RRClass& getClass() const = 0;
+    //virtual const RRClass& setClass() const = 0;
+};
+
+// Base class for a DNS Data Source
+class DataSrc : public AbstractDataSrc {
+public:
+    DataSrc() : rrclass(RRClass::IN()) {}
+    DataSrc(const RRClass& c) : rrclass(c) {}
+    virtual ~DataSrc() {};
+
+    DSResult runQuery(Query q);
+
+    virtual DSResult findRRset(const Name& qname,
+                               const RRClass& qclass,
+                               const RRType& qtype,
+                               RRsetList& target,
+                               RRsetList& sigs) const = 0;
+
+    virtual DSResult findRRset(const Name& qname,
+                               const RRClass& qclass,
+                               const RRType& qtype,
+                               RRsetList& target) const = 0;
+
+    virtual const DataSrc* findClosestEnclosure(const Name& qname,
+                                                Name& container,
+                                                bool& found) const = 0;
+
+    const RRClass& getClass() const { return rrclass; }
+    void setClass(RRClass& c) { rrclass = c; }
+
+    DSResult init() { return NOT_IMPLEMENTED; }
+    DSResult close() { return NOT_IMPLEMENTED; }
+
+protected:
+    RRClass rrclass;
+};
+
+class MetaDataSrc : public DataSrc {
+public:
+    MetaDataSrc() : DataSrc(RRClass::ANY()) {}
+    MetaDataSrc(const RRClass& c) : DataSrc(c) {}
+    virtual ~MetaDataSrc() {}
+
+    void addDataSrc(DataSrc* ds) {
+        if (getClass() != RRClass::ANY() && ds->getClass() != getClass()) {
+            dns_throw(Unexpected, "class mismatch");
+        }
+
+        data_sources.push_back(ds);
+    };
+
+    const DataSrc* findClosestEnclosure(const Name& qname,
+                                        Name& container,
+                                        bool& found) const
+    {
+        const DataSrc* best = NULL;
+        BOOST_FOREACH (DataSrc* ds, data_sources) {
+            const DataSrc* source;
+
+            if (getClass() != RRClass::ANY() && ds->getClass() != getClass()) {
+                continue;
+            }
+
+            source = ds->findClosestEnclosure(qname, container, found);
+            if (source != NULL) {
+                best = source;
+            }
+        }
+
+        return (best);
+    };
+
+private:
+    std::vector<DataSrc*> data_sources;
+};
+
+}
+}
+
+#endif
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 187 - 0
src/lib/auth/cpp/data_source_plot.cc

@@ -0,0 +1,187 @@
+
+#include <boost/foreach.hpp>
+
+#include <dns/cpp/rrttl.h>
+
+#include "data_source_plot.h"
+
+namespace isc {
+namespace dns {
+
+// this implementation returns fixed records,
+// and does not allow update statements
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using namespace isc::data;
+
+namespace {
+const Name authors_name("authors.bind");
+const Name version_name("version.bind");
+}
+
+void
+DataSourceParkingLot::serve(std::string zone_name) {
+    zones.serve(zone_name);
+}
+
+void
+DataSourceParkingLot::addARecord(std::string data) {
+    a_records.push_back(RdataPtr(new in::A(data)));
+}
+
+void
+DataSourceParkingLot::addAAAARecord(std::string data) {
+    aaaa_records.push_back(RdataPtr(new in::AAAA(data)));
+}
+
+void
+DataSourceParkingLot::addNSRecord(std::string data) {
+    ns_records.push_back(RdataPtr(new generic::NS(data)));
+}
+
+void
+DataSourceParkingLot::setSOARecord(RdataPtr soa_record) {
+}
+
+void
+DataSourceParkingLot::setDefaultZoneData() {
+    clearARecords();
+    clearAAAARecords();
+    clearNSRecords();
+
+    addARecord("127.0.0.1");
+    addAAAARecord("::1");
+    addNSRecord("ns1.parking.example");
+    addNSRecord("ns2.parking.example");
+    addNSRecord("ns3.parking.example");
+}
+
+DataSourceParkingLot::DataSourceParkingLot() {
+    setDefaultZoneData();
+    soa = RdataPtr(new generic::SOA(Name("parking.example"),
+                                    Name("noc.parking.example"),
+                                    1, 1800, 900, 604800, 86400));
+}
+
+bool
+DataSourceParkingLot::hasZoneFor(const Name& name, Name &zone_name)
+{
+    if (name == authors_name) {
+        zone_name = authors_name;
+        return (true);
+    } else if (name == version_name) {
+        zone_name = version_name;
+        return (true);
+    }
+    return zones.findClosest(name, zone_name);
+}
+
+SearchResult
+DataSourceParkingLot::findRRsets(const isc::dns::Name& zone_name,
+                                 const isc::dns::Name& name,
+                                 const isc::dns::RRClass& clas,
+                                 const isc::dns::RRType& type) const
+{
+    SearchResult result;
+    
+    if (clas == RRClass::CH()) {
+        if (type == RRType::TXT()) {
+            if (name == authors_name) {
+                RRsetPtr rrset = RRsetPtr(new RRset(authors_name, RRClass::CH(),
+                                                    RRType::TXT(), RRTTL(0)));
+                rrset->addRdata(generic::TXT("Han Feng"));
+                rrset->addRdata(generic::TXT("Kazunori Fujiwara"));
+                rrset->addRdata(generic::TXT("Michael Graff"));
+                rrset->addRdata(generic::TXT("Evan Hunt"));
+                rrset->addRdata(generic::TXT("Jelte Jansen"));
+                rrset->addRdata(generic::TXT("Jin Jian"));
+                rrset->addRdata(generic::TXT("JINMEI Tatuya"));
+                rrset->addRdata(generic::TXT("Naoki Kambe"));
+                rrset->addRdata(generic::TXT("Shane Kerr")); 
+                rrset->addRdata(generic::TXT("Zhang Likun"));
+                rrset->addRdata(generic::TXT("Jeremy C. Reed")); 
+
+                result.addRRset(rrset);
+                result.setStatus(SearchResult::success);
+            } else if (name == version_name) {
+                RRsetPtr rrset = RRsetPtr(new RRset(version_name, RRClass::CH(),
+                                                    RRType::TXT(), RRTTL(0)));
+                rrset->addRdata(generic::TXT("BIND10 0.0.1"));
+                result.addRRset(rrset);
+                result.setStatus(SearchResult::success);
+            } else {
+                result.setStatus(SearchResult::name_not_found);
+            }
+        } else if (type == RRType::NS()) {
+            if (name == authors_name || name == version_name) {
+                RRsetPtr rrset = RRsetPtr(new RRset(name, RRClass::CH(),
+                                                    RRType::NS(),
+                                                    RRTTL(0)));
+                rrset->addRdata(generic::NS(name));
+                result.addRRset(rrset);
+                result.setStatus(SearchResult::success);
+            } else {
+                result.setStatus(SearchResult::name_not_found);
+            }
+        } else {
+            result.setStatus(SearchResult::name_not_found);
+        }
+    } else if (clas == RRClass::IN()) {
+        if (zones.contains(name)) {
+            RRsetPtr rrset = RRsetPtr(new RRset(name, clas, type, RRTTL(3600)));
+            result.setStatus(SearchResult::success);
+            if (type == RRType::A()) {
+                BOOST_FOREACH(RdataPtr a, a_records) {
+                    rrset->addRdata(a);
+                }
+            } else if (type == RRType::AAAA()) {
+                BOOST_FOREACH(RdataPtr aaaa, aaaa_records) {
+                    rrset->addRdata(aaaa);
+                }
+            } else if (type == RRType::NS()) {
+                BOOST_FOREACH(RdataPtr ns, ns_records) {
+                    rrset->addRdata(ns);
+                }
+            } else if (type == RRType::SOA()) {
+                rrset->addRdata(soa);
+            }
+            result.addRRset(rrset);
+        } else {
+            // we don't have the name itself. Do we have the zone?
+            if (zones.contains(zone_name)) {
+                result.setStatus(SearchResult::name_not_found);
+            } else {
+                result.setStatus(SearchResult::zone_not_found);
+            }
+        }
+    } else {
+        result.setStatus(SearchResult::zone_not_found);
+    }
+    return result;
+}
+
+/// Do direct 'search' in database, no extra processing,
+/// and add the resulting rrsets to the specified section
+/// in the given message
+/// returns the status code of the searchresult
+/// Once the dns logic is moved from parkinglot to this class,
+/// we should probably make this private
+SearchResult::status_type
+DataSourceParkingLot::addToMessage(Message& msg,
+             const Section& section,
+             const Name& zone_name,
+             const Name& name,
+             const RRClass& clas,
+             const RRType& type) const
+{
+    SearchResult result = findRRsets(zone_name, name, clas, type);
+    BOOST_FOREACH(RRsetPtr rrset, result) {
+        msg.addRRset(section, rrset);
+    }
+    return result.getStatus();
+}
+
+
+}
+}

+ 96 - 0
src/lib/auth/cpp/data_source_plot.h

@@ -0,0 +1,96 @@
+
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#ifndef __DATA_SOURCE_SIMPLE_H
+#define __DATA_SOURCE_SIMPLE_H
+
+#include <dns/cpp/buffer.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/rdata.h>
+#include <dns/cpp/rrclass.h>
+#include <dns/cpp/rrtype.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/message.h>
+
+#include <cc/cpp/data.h>
+
+#include "common.h"
+
+#include "data_source.h"
+
+#include "zoneset.h"
+
+namespace isc {
+namespace dns {
+
+class DataSourceParkingLot : public DataSource {
+public:
+    DataSourceParkingLot();
+    
+    void init() {};
+    void close() {};
+    bool hasZoneFor(const Name& name, Name &zone_name);
+    SearchResult findRRsets(const isc::dns::Name& zone_name,
+                            const isc::dns::Name& name,
+                            const isc::dns::RRClass& clas,
+                            const isc::dns::RRType& type) const;
+
+    /* move these to private (or to zoneset) and the calling functions
+     * from parkinglot to here? */
+    void serve(std::string zone_name);
+    void clear_zones() { zones.clear_zones(); };
+
+    void clearARecords() { a_records.clear(); };
+    void clearAAAARecords() { aaaa_records.clear(); };
+    void clearNSRecords() { ns_records.clear(); };
+
+    void addARecord(std::string data);
+    void addAAAARecord(std::string data);
+    void addNSRecord(std::string data);
+
+    void setSOARecord(isc::dns::rdata::RdataPtr soa_record);
+
+    /// Do direct 'search' in database, no extra processing,
+    /// and add the resulting rrsets to the specified section
+    /// in the given message
+    /// Once the dns logic is moved from parkinglot to this class,
+    /// we should probably make this private
+    SearchResult::status_type addToMessage(Message& msg,
+                                           const isc::dns::Section& section,
+                                           const isc::dns::Name& zone_name,
+                                           const isc::dns::Name& name,
+                                           const isc::dns::RRClass& clas,
+                                           const isc::dns::RRType& type) const;
+
+private:
+    //
+    void setDefaultZoneData();
+
+    std::vector<isc::dns::rdata::RdataPtr> a_records, aaaa_records, ns_records;
+    isc::dns::rdata::RdataPtr soa;
+    ZoneSet zones;
+
+};
+
+}
+}
+
+#endif
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 114 - 0
src/lib/auth/cpp/data_source_static.cc

@@ -0,0 +1,114 @@
+
+
+#include "data_source_static.h"
+
+#include <dns/cpp/name.h>
+#include <dns/cpp/rdata.h>
+#include <dns/cpp/rdataclass.h>
+#include <dns/cpp/rrclass.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/rrtype.h>
+#include <dns/cpp/rrttl.h>
+
+#include <iostream>
+
+namespace isc {
+namespace dns {
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+StaticDataSrc::StaticDataSrc() : authors_name("authors.bind"),
+                                 version_name("version.bind")
+{
+    RRsetPtr authors = RRsetPtr(new RRset(authors_name, RRClass::CH(),
+                                          RRType::TXT(), RRTTL(3600)));
+    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"));
+
+    RRsetPtr version = RRsetPtr(new RRset(version_name, RRClass::CH(),
+                                          RRType::TXT(), RRTTL(3600)));
+    version->addRdata(generic::TXT("BIND10 0.0.0 (pre-alpha)"));
+}
+
+const DataSrc*
+StaticDataSrc::findClosestEnclosure(const Name& qname, Name& container, bool& found) const {
+    NameComparisonResult::NameRelation version_cmp = 
+        qname.compare(version_name).getRelation();
+
+    if (version_cmp == NameComparisonResult::EQUAL ||
+        version_cmp == NameComparisonResult::SUBDOMAIN) {
+        NameComparisonResult::NameRelation sub_cmp = 
+           version_name.compare(container).getRelation();
+
+        if (sub_cmp == NameComparisonResult::SUBDOMAIN) {
+            container = authors_name;
+            found = true;
+            return this;
+        } else if (!found && sub_cmp == NameComparisonResult::EQUAL) {
+            found = true;
+            return this;
+        } else {
+            return NULL;
+        }
+    }
+
+    NameComparisonResult::NameRelation authors_cmp = 
+        qname.compare(authors_name).getRelation();
+
+    if (authors_cmp == NameComparisonResult::EQUAL ||
+        authors_cmp == NameComparisonResult::SUBDOMAIN) {
+        NameComparisonResult::NameRelation sub_cmp = 
+            authors_name.compare(container).getRelation();
+
+        if (sub_cmp == NameComparisonResult::SUBDOMAIN) {
+            container = authors_name;
+            found = true;
+            return this;
+        } else if (!found && sub_cmp == NameComparisonResult::EQUAL) {
+            found = true;
+            return this;
+        } else {
+            return NULL;
+        }
+    }
+
+    return NULL;
+}
+
+DSResult
+StaticDataSrc::findRRset(const Name& qname,
+                         const RRClass& qclass,
+                         const RRType& qtype,
+                         RRsetList& target) const
+{
+    if (qname == version_name) {
+        target.push_back(version);
+        return SUCCESS;
+    } else if (qname == authors_name) {
+        target.push_back(authors);
+        return SUCCESS;
+    }
+    return NAME_NOT_FOUND;
+}
+
+DSResult
+StaticDataSrc::findRRset(const Name& qname,
+                         const RRClass& qclass,
+                         const RRType& qtype,
+                         RRsetList& target, RRsetList& sigs) const
+{
+    return findRRset(qname, qclass, qtype, target);
+}
+
+}
+}

+ 69 - 0
src/lib/auth/cpp/data_source_static.h

@@ -0,0 +1,69 @@
+// Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+//
+// Sample Datasource implementation; this datasource only returns
+// static content for the queries
+// CH TXT version.bind
+// and
+// CH TXT authors.bind
+//
+
+#ifndef __STATIC_DATA_SOURCE_H
+#define __STATIC_DATA_SOURCE_H
+
+#include "data_source.h"
+
+namespace isc {
+namespace dns {
+
+class StaticDataSrc : public DataSrc {
+public:
+    StaticDataSrc();
+    ~StaticDataSrc() {};
+
+    const DataSrc* findClosestEnclosure(const Name& qname,
+                                        Name& container,
+                                        bool& found) const;
+
+    DSResult findRRset(const Name& qname,
+                       const RRClass& qclass,
+                       const RRType& qtype,
+                       RRsetList& target, RRsetList& sigs) const;
+
+    DSResult findRRset(const Name& qname,
+                       const RRClass& qclass,
+                       const RRType& qtype,
+                       RRsetList& target) const;
+
+    DSResult init() { return SUCCESS; };
+    DSResult close() { return SUCCESS; } ;
+
+private:
+    const Name authors_name;
+    const Name version_name;
+    RRsetPtr authors;
+    RRsetPtr version;
+};
+
+}
+}
+
+#endif
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 43 - 0
src/lib/auth/cpp/query.cc

@@ -0,0 +1,43 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#include <dns/cpp/buffer.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/message.h>
+
+#include <cc/cpp/data.h>
+
+#include "query.h"
+
+namespace isc {
+namespace dns {
+
+QueryTask::QueryTask(const Name& n, const RRClass& c,
+                     const RRType& t, const Section& s) :
+    qname(n), qclass(c), qtype(t), section(s)
+{
+        // Empty constructor.  It is defined outside the class statement
+        // because otherwise the linker will be confused.
+}
+
+QueryTask::~QueryTask() {
+        // Empty destructor.  It is defined outside the class statement
+        // because otherwise the linker will be confused.
+}
+
+}
+}

+ 133 - 0
src/lib/auth/cpp/query.h

@@ -0,0 +1,133 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#ifndef __QUERY_H
+#define __QUERY_H
+
+#include <queue>
+
+#include <dns/cpp/exceptions.h>
+#include <dns/cpp/name.h>
+#include <dns/cpp/message.h>
+#include <dns/cpp/rrset.h>
+#include <dns/cpp/rrclass.h>
+#include <dns/cpp/rrtype.h>
+
+namespace isc {
+namespace dns {
+
+enum QueryStatus {
+    QUERY_INCOMPLETE,
+    QUERY_FINISHING,
+    QUERY_DONE,
+    QUERY_NODATA
+};
+
+///
+/// \brief exception to throw if a DNS Message is malformed
+/// 
+class MalformedMessage : public Exception {
+public:
+    MalformedMessage(const char* file, size_t line, const char* what) :
+        isc::dns::Exception(file, line, what) {}
+};
+
+// An individual task to be carried out by the query logic
+class QueryTask {
+public:
+    QueryTask(const Name& n, const RRClass& c,
+              const RRType& t, const Section& s);
+    virtual ~QueryTask();
+
+    const Name& qname;
+    const RRClass& qclass;
+    const RRType& qtype;
+    const Section& section;
+};
+
+typedef boost::shared_ptr<QueryTask> QueryTaskPtr;
+typedef std::queue<QueryTaskPtr> QueryTaskQueue;
+
+class Query;
+typedef boost::shared_ptr<Query> QueryPtr;
+
+// Data Source query
+class Query {
+public:
+    Query(Message& m, bool dnssec) {
+        message_ = &m;
+        want_additional = true;
+        want_dnssec = dnssec;
+        status_ = QUERY_INCOMPLETE;
+
+        // Check message formatting
+        QuestionIterator qid = message_->beginQuestion();
+        qid++;
+        if (qid != message_->endQuestion())
+                dns_throw(MalformedMessage, "too many questions");
+
+        // Populate the query tasks queue with the initial question
+        QuestionPtr query = *message_->beginQuestion();
+        qname_ = &query->getName();
+        qclass_ = &query->getClass();
+        qtype_ = &query->getType();
+        QueryTask *qt = new QueryTask(*qname_, *qclass_, *qtype_,
+                                      Section::ANSWER());
+        querytasks.push(QueryTaskPtr(qt));
+    };
+
+    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; }
+
+    // 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; }
+
+    QueryStatus status() { return status_; }
+    void setStatus(QueryStatus s) { status_ = s; }
+
+protected:
+    QueryStatus status_;
+
+private:
+    const Name* qname_;
+    const RRClass* qclass_;
+    const RRType* qtype_;
+
+    Message* message_;
+    QueryTaskQueue querytasks;
+
+    bool want_additional;
+    bool want_dnssec;
+};
+
+}
+}
+
+#endif

+ 13 - 5
src/lib/dns/cpp/message.h

@@ -401,7 +401,15 @@ class Section {
 public:
     unsigned int getCode() const { return (code_); }
     bool operator==(const Section& other) const
-    { return (code_ == other.code_); }
+        { return (code_ == other.code_); }
+
+    enum {
+        SECTION_QUESTION = 0U,
+        SECTION_ANSWER = 1U,
+        SECTION_AUTHORITY = 2U,
+        SECTION_ADDITIONAL = 3U
+    };
+
     static const Section& QUESTION();
     static const Section& ANSWER();
     static const Section& AUTHORITY();
@@ -414,28 +422,28 @@ private:
 inline const Section&
 Section::QUESTION()
 {
-    static Section s(0);
+    static Section s(SECTION_QUESTION);
     return (s);
 }
 
 inline const Section&
 Section::ANSWER()
 {
-    static Section s(1);
+    static Section s(SECTION_ANSWER);
     return (s);
 }
 
 inline const Section&
 Section::AUTHORITY()
 {
-    static Section s(2);
+    static Section s(SECTION_AUTHORITY);
     return (s);
 }
 
 inline const Section&
 Section::ADDITIONAL()
 {
-    static Section s(3);
+    static Section s(SECTION_ADDITIONAL);
     return (s);
 }
 

+ 71 - 0
src/lib/dns/cpp/rdata/hs_4/a_1.cc

@@ -0,0 +1,71 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+#include <string>
+
+#include "buffer.h"
+#include "exceptions.h"
+#include "messagerenderer.h"
+#include "rdata.h"
+#include "rdataclass.h"
+
+using namespace std;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+A::A(const string& addrstr)
+{
+    // TBD
+}
+
+A::A(InputBuffer& buffer, size_t rdata_len)
+{
+    // TBD
+}
+
+A::A(const A& source)
+{
+    // TBD
+}
+
+void
+A::toWire(OutputBuffer& buffer) const
+{
+    // TBD
+}
+
+void
+A::toWire(MessageRenderer& renderer) const
+{
+    // TBD
+}
+
+string
+A::toText() const
+{
+    // TBD
+    dns_throw(InvalidRdataText, "Not implemented yet");
+}
+
+int
+A::compare(const Rdata& other) const
+{
+    return (0);                 // dummy.  TBD
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE

+ 42 - 0
src/lib/dns/cpp/rdata/hs_4/a_1.h

@@ -0,0 +1,42 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// $Id$
+
+// BEGIN_HEADER_GUARD
+
+#include <string>
+
+#include "rdata.h"
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+class A : public Rdata {
+public:
+    // BEGIN_COMMON_MEMBERS
+    // END_COMMON_MEMBERS
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 25 - 0
src/lib/dns/cpp/rrclass-placeholder.h

@@ -237,6 +237,15 @@ public:
 
     // BEGIN_WELL_KNOWN_CLASS_DECLARATIONS
     // END_WELL_KNOWN_CLASS_DECLARATIONS
+    
+    // \brief Meta-classes
+    enum {
+        RRCLASS_RESERVED0 = 0,
+        RRCLASS_NONE = 254,
+        RRCLASS_ANY = 255
+    };
+    static const RRClass& NONE();
+    static const RRClass& ANY();
 
 private:
     uint16_t classcode_;
@@ -245,6 +254,22 @@ private:
 // BEGIN_WELL_KNOWN_CLASS_DEFINITIONS
 // END_WELL_KNOWN_CLASS_DEFINITIONS
 
+inline const RRClass&
+RRClass::NONE()
+{
+    static RRClass rrclass(RRCLASS_NONE);
+
+    return (rrclass);
+}
+
+inline const RRClass&
+RRClass::ANY()
+{
+    static RRClass rrclass(RRCLASS_ANY);
+
+    return (rrclass);
+}
+
 ///
 /// \brief Insert the \c RRClass as a string into stream.
 ///

+ 2 - 0
src/lib/dns/cpp/rrset.h

@@ -19,6 +19,7 @@
 
 #include <iostream>
 #include <string>
+#include <vector>
 
 #include <boost/shared_ptr.hpp>
 
@@ -38,6 +39,7 @@ class AbstractRRset;
 typedef boost::shared_ptr<AbstractRRset> RRsetPtr;
 class BasicRRset;
 typedef BasicRRset RRset;
+typedef std::vector<RRsetPtr> RRsetList;
 class BasicRRsetImpl;
 
 class RdataIterator;