Browse Source

merged back branches/jelte_datasource1 branch

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/parkinglot@515 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen 15 years ago
parent
commit
f389d00070

+ 3 - 1
src/bin/parkinglot/Makefile.am

@@ -1,5 +1,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/ext
 
 bin_PROGRAMS = parkinglot
-parkinglot_SOURCES = common.cc common.h zoneset.h parkinglot.cc parkinglot.h ccsession.cc ccsession.h main.cc
+parkinglot_SOURCES = common.cc common.h zoneset.h zoneset.cc parkinglot.cc
+parkinglot_SOURCES += parkinglot.h ccsession.cc ccsession.h main.cc
+parkinglot_SOURCES += data_source_plot.h data_source_plot.cc
 parkinglot_LDADD = $(top_srcdir)/src/lib/dns/libdns.a $(top_srcdir)/src/lib/cc/cpp/libcc.a

+ 162 - 0
src/bin/parkinglot/data_source_plot.cc

@@ -0,0 +1,162 @@
+
+#include <boost/foreach.hpp>
+
+#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::IN;
+using namespace isc::dns::Rdata::Generic;
+using namespace isc::data;
+
+void
+DataSourceParkingLot::serve(std::string zone_name) {
+    zones.serve(zone_name);
+}
+
+void
+DataSourceParkingLot::addARecord(std::string data) {
+    a_records.push_back(Rdata::RdataPtr(new A(data)));
+}
+
+void
+DataSourceParkingLot::addAAAARecord(std::string data) {
+    aaaa_records.push_back(Rdata::RdataPtr(new AAAA(data)));
+}
+
+void
+DataSourceParkingLot::addNSRecord(std::string data) {
+    ns_records.push_back(Rdata::RdataPtr(new NS(data)));
+}
+
+void
+DataSourceParkingLot::setSOARecord(isc::dns::Rdata::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 = Rdata::RdataPtr(new SOA("parking.example", "noc.parking.example",
+                                        1, 1800, 900, 604800, TTL(86400)));
+}
+
+bool
+DataSourceParkingLot::hasZoneFor(const Name& name, Name &zone_name)
+{
+    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) {
+    SearchResult result;
+    Name authors_name("authors.bind");
+    Name version_name("version.bind");
+    
+    if (clas == RRClass::CH) {
+        if (type == RRType::TXT) {
+            if (name == authors_name) {
+                RRsetPtr rrset = RRsetPtr(new RRset(authors_name, RRClass::CH, RRType::TXT, TTL(3600)));
+                rrset->addRdata(Rdata::RdataPtr(TXT("JINMEI Tatuya").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Han Feng").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Kazunori Fujiwara").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Michael Graff").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Evan Hunt").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Jelte Jansen").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Jin Jian").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("JINMEI Tatuya").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Naoki Kambe").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Shane Kerr").copy())); 
+                rrset->addRdata(Rdata::RdataPtr(TXT("Zhang Likun").copy()));
+                rrset->addRdata(Rdata::RdataPtr(TXT("Jeremy C. Reed").copy())); 
+
+                result.addRRset(rrset);
+                result.setStatus(SearchResult::success);
+            } else if (name == version_name) {
+                RRsetPtr rrset = RRsetPtr(new RRset(version_name, RRClass::CH, RRType::TXT, TTL(3600)));
+                rrset->addRdata(Rdata::RdataPtr(TXT("BIND10 0.0.1").copy()));
+                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, TTL(3600)));
+            result.setStatus(SearchResult::success);
+            if (type == RRType::A) {
+                BOOST_FOREACH(isc::dns::Rdata::RdataPtr a, a_records) {
+                    rrset->addRdata(a);
+                }
+            } else if (type == RRType::AAAA) {
+                BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) {
+                    rrset->addRdata(aaaa);
+                }
+            } else if (type == RRType::NS) {
+                BOOST_FOREACH(isc::dns::Rdata::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,
+             section_t section,
+             const Name& zone_name,
+             const Name& name,
+             const isc::dns::RRClass& clas,
+             const isc::dns::RRType& type)
+{
+    SearchResult result = findRRsets(zone_name, name, clas, type);
+    BOOST_FOREACH(RRsetPtr rrset, result) {
+        msg.addRRset(section, rrset);
+    }
+    return result.getStatus();
+}
+
+
+}
+}

+ 90 - 0
src/bin/parkinglot/data_source_plot.h

@@ -0,0 +1,90 @@
+
+// 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/buffer.h>
+#include <dns/name.h>
+#include <dns/rrset.h>
+#include <dns/message.h>
+
+#include <cc/cpp/data.h>
+
+#include "common.h"
+
+#include "dns/data_source.h"
+#include "dns/rrset.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);
+
+    /* 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,
+                 section_t section,
+                 const Name& zone_name,
+                 const Name& name,
+                 const isc::dns::RRClass& clas,
+                 const isc::dns::RRType& type);
+
+private:
+    //
+    void setDefaultZoneData();
+
+    std::vector<isc::dns::Rdata::RdataPtr> a_records, aaaa_records, ns_records;
+    isc::dns::Rdata::RdataPtr soa;
+    ZoneSet zones;
+
+};
+
+}
+}
+
+#endif

+ 1 - 30
src/bin/parkinglot/main.cc

@@ -61,36 +61,7 @@ usage() {
 isc::data::ElementPtr
 my_config_handler(isc::data::ElementPtr config)
 {
-    cout << "[XX] Handle config: " << endl << config->str() << endl;
-    if (config->contains("zones")) {
-        plot.clear_zones();
-        BOOST_FOREACH(isc::data::ElementPtr zone_el, config->get("zones")->listValue()) {
-            plot.serve(zone_el->stringValue());
-        }
-    }
-    if (config->contains("port")) {
-        // todo: what to do with port change. restart automatically?
-        // ignore atm
-    }
-    if (config->contains("a_records")) {
-        plot.clearARecords();
-        BOOST_FOREACH(isc::data::ElementPtr rel, config->get("a_records")->listValue()) {
-            plot.addARecord(rel->stringValue());
-        }
-    }
-    if (config->contains("aaaa_records")) {
-        plot.clearAAAARecords();
-        BOOST_FOREACH(isc::data::ElementPtr rel, config->get("aaaa_records")->listValue()) {
-            plot.addAAAARecord(rel->stringValue());
-        }
-    }
-    if (config->contains("ns_records")) {
-        plot.clearNSRecords();
-        BOOST_FOREACH(isc::data::ElementPtr rel, config->get("ns_records")->listValue()) {
-            plot.addNSRecord(rel->stringValue());
-        }
-    }
-    return isc::data::Element::createFromString("{ \"result\": [0] }");
+    return plot.updateConfig(config);
 }
 
 isc::data::ElementPtr

+ 74 - 131
src/bin/parkinglot/parkinglot.cc

@@ -42,48 +42,13 @@ using namespace isc::dns::Rdata::IN;
 using namespace isc::dns::Rdata::Generic;
 using namespace isc::data;
 
-void
-ParkingLot::addARecord(std::string data) {
-    a_records.push_back(Rdata::RdataPtr(new A(data)));
-}
-
-void
-ParkingLot::addAAAARecord(std::string data) {
-    aaaa_records.push_back(Rdata::RdataPtr(new AAAA(data)));
-}
-
-void
-ParkingLot::addNSRecord(std::string data) {
-    ns_records.push_back(Rdata::RdataPtr(new NS(data)));
-}
-
-void
-ParkingLot::setSOARecord(isc::dns::Rdata::RdataPtr soa_record) {
-}
-
-void
-ParkingLot::setDefaultZoneData() {
-    clearARecords();
-    clearAAAARecords();
-    clearNSRecords();
-
-    addARecord("127.0.0.1");
-    addAAAARecord("::1");
-    addNSRecord("ns1.parking.example");
-    addNSRecord("ns2.parking.example");
-    addNSRecord("ns3.parking.example");
-}
-
 ParkingLot::ParkingLot(int port) {
-    setDefaultZoneData();
     /*ns1 = Rdata::RdataPtr(new NS("ns1.parking.example"));
     ns2 = Rdata::RdataPtr(new NS("ns2.parking.example"));
     ns3 = Rdata::RdataPtr(new NS("ns3.parking.example"));
     a = Rdata::RdataPtr(new A("127.0.0.1"));
     aaaa = Rdata::RdataPtr(new AAAA("::1"));
     */
-    soa = Rdata::RdataPtr(new SOA("parking.example", "noc.parking.example",
-                                        1, 1800, 900, 604800, TTL(86400)));
 
     int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     if (s < 0)
@@ -107,8 +72,6 @@ ParkingLot::ParkingLot(int port) {
 
 void
 ParkingLot::processMessage() {
-    Name authors_name("authors.bind");
-    Name version_name("version.bind");
     struct sockaddr_storage ss;
     socklen_t sa_len = sizeof(ss);
     struct sockaddr* sa = static_cast<struct sockaddr*>((void*)&ss);
@@ -133,90 +96,56 @@ ParkingLot::processMessage() {
 
         RRsetPtr query = msg.getSection(SECTION_QUESTION)[0];
 
-        string name = query->getName().toText(true);
-        if (query->getClass() == RRClass::CH &&
-            query->getType() == RRType::TXT &&
-            query->getName() == authors_name) {
-            msg.setRcode(Message::RCODE_NOERROR);
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Han Feng")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Kazunori Fujiwara")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Michael Graff")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
-                                         RRType::TXT, TTL(0),
-                                         TXT("Evan Hunt")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
-                                         RRType::TXT, TTL(0),
-                                         TXT("Jelte Jansen")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Jin Jian")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH,
-                                         RRType::TXT, TTL(0),
-                                         TXT("JINMEI Tatuya")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Naoki Kambe")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Shane Kerr"))); 
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Zhang Likun")));
-            msg.addRR(SECTION_ANSWER, RR(authors_name, RRClass::CH, 
-                                         RRType::TXT, TTL(0), 
-                                         TXT("Jeremy C. Reed"))); 
-            msg.addRR(SECTION_AUTHORITY, RR(authors_name, RRClass::CH,
-                                            RRType::NS, TTL(0),
-                                            NS("authors.bind")));
-        } else if (query->getClass() == RRClass::CH &&
-                   query->getType() == RRType::TXT &&
-                   query->getName() == version_name) {            
-            msg.setRcode(Message::RCODE_NOERROR);
-            msg.addRR(SECTION_ANSWER, RR(version_name, RRClass::CH,
-                                         RRType::TXT, TTL(0),
-                                         TXT("10.0.0s20091030")));
-            msg.addRR(SECTION_AUTHORITY, RR(version_name, RRClass::CH,
-                                            RRType::NS, TTL(0),
-                                            NS("version.bind")));
-        } else if (zones.contains(name)) {
-            msg.setRcode(Message::RCODE_NOERROR);
-            RRset* nsset = new RRset(query->getName(), RRClass::IN,
-                                     RRType::NS, TTL(3600));
-            BOOST_FOREACH(isc::dns::Rdata::RdataPtr ns, ns_records) {
-                nsset->addRdata(ns);
+        msg.makeResponse();
+        msg.setAA(true);
+        TTL default_ttl = TTL(3600);
+
+        Name zname;
+        Name name = query->getName();
+        RRClass qclass = query->getClass();
+        RRType qtype = query->getType();
+        SearchResult::status_type status;
+        bool included_ns = false;
+        if (data_source.hasZoneFor(query->getName(), zname)) {
+            status = data_source.addToMessage(msg, SECTION_ANSWER, zname, name, qclass, qtype);
+            // rcode is based on this result?
+            if (status == SearchResult::name_not_found) {
+                msg.setRcode(Message::RCODE_NXDOMAIN);
+                if (qtype != RRType::NS) {
+                    status = data_source.addToMessage(msg, SECTION_AUTHORITY, zname, zname, qclass, RRType::SOA);
+                }
+            } else {
+                if (qtype != RRType::NS) {
+                    status = data_source.addToMessage(msg, SECTION_AUTHORITY, zname, zname, qclass, RRType::NS);
+                }
+                included_ns = true;
             }
-
-            if (query->getType() == RRType::NS)
-                msg.addRRset(SECTION_ANSWER, RRsetPtr(nsset));
-            else if (query->getType() == RRType::A) {
-                msg.addRRset(SECTION_AUTHORITY, RRsetPtr(nsset));
-
-                BOOST_FOREACH(isc::dns::Rdata::RdataPtr a, a_records) {
-                    RR arr(query->getName(), RRClass::IN, RRType::A, TTL(3600), a);
-                    msg.addRR(SECTION_ANSWER, arr);
+            // If we included NS records, and their target falls below the zone, add glue
+            if (included_ns) {
+                BOOST_FOREACH(RRsetPtr rrset, msg.getSection(SECTION_ANSWER)) {
+                    if (rrset->getType() == RRType::NS) {
+                        BOOST_FOREACH(Rdata::RdataPtr rdata, rrset->getRdatalist()) {
+                            /* no direct way to get the Name from the rdata fields? */
+                            Name ns_name = Name(rdata->toText());
+                            data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::A);
+                            data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::AAAA);
+                        }
+                    }
                 }
-            } else if (query->getType() == RRType::AAAA) {
-                msg.addRRset(SECTION_AUTHORITY, RRsetPtr(nsset));
-                BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) {
-                    RR aaaarr(query->getName(), RRClass::IN, RRType::AAAA,
-                              TTL(3600), aaaa);
-                    msg.addRR(SECTION_ANSWER, aaaarr);
+                BOOST_FOREACH(RRsetPtr rrset, msg.getSection(SECTION_AUTHORITY)) {
+                    if (rrset->getType() == RRType::NS) {
+                        BOOST_FOREACH(Rdata::RdataPtr rdata, rrset->getRdatalist()) {
+                            /* no direct way to get the Name from the rdata fields? */
+                            Name ns_name = Name(rdata->toText());
+                            data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::A);
+                            data_source.addToMessage(msg, SECTION_ADDITIONAL, zname, ns_name, qclass, RRType::AAAA);
+                        }
+                    }
                 }
-            } else {
-                RR soarr(query->getName(), RRClass::IN, RRType::SOA,
-                         TTL(3600), soa);
-                msg.addRR(SECTION_AUTHORITY, soarr);
             }
         } else {
-            msg.setRcode(Message::RCODE_NXDOMAIN);
+            msg.setRcode(Message::RCODE_SERVFAIL);
         }
-
         msg.toWire();
         cout << "sending a response (" <<
             boost::lexical_cast<string>(msg.getBuffer().getSize())
@@ -225,23 +154,37 @@ ParkingLot::processMessage() {
     }
 }
 
-void
-ParkingLot::command(pair<string,ElementPtr> cmd) {
-    if (cmd.first == "shutdown")
-        exit(0);
-    else if (cmd.first == "config_update") {
-        // what to do with port settings?
-        ElementPtr zonelist_el = (cmd.second)->get("zones");
-        // We could walk through both lists and remove and serve
-        // accordingly, or simply clear all and add everything
-        zones.clear_zones();
-        BOOST_FOREACH(ElementPtr zone, zonelist_el->listValue()) {
-            zones.serve(zone->stringValue());
+ElementPtr
+ParkingLot::updateConfig(isc::data::ElementPtr config) {
+    if (config->contains("zones")) {
+        data_source.clear_zones();
+        BOOST_FOREACH(isc::data::ElementPtr zone_el, config->get("zones")->listValue()) {
+            data_source.serve(zone_el->stringValue());
         }
     }
+    if (config->contains("port")) {
+        // todo: what to do with port change. restart automatically?
+        // ignore atm
+    }
+    if (config->contains("a_records")) {
+        data_source.clearARecords();
+        BOOST_FOREACH(isc::data::ElementPtr rel, config->get("a_records")->listValue()) {
+            data_source.addARecord(rel->stringValue());
+        }
+    }
+    if (config->contains("aaaa_records")) {
+        data_source.clearAAAARecords();
+        BOOST_FOREACH(isc::data::ElementPtr rel, config->get("aaaa_records")->listValue()) {
+            data_source.addAAAARecord(rel->stringValue());
+        }
+    }
+    if (config->contains("ns_records")) {
+        data_source.clearNSRecords();
+        BOOST_FOREACH(isc::data::ElementPtr rel, config->get("ns_records")->listValue()) {
+            data_source.addNSRecord(rel->stringValue());
+        }
+    }
+    return isc::data::Element::createFromString("{ \"result\": [0] }");
 }
 
-void
-ParkingLot::serve(std::string zone_name) {
-    zones.serve(zone_name);
-}
+

+ 3 - 15
src/bin/parkinglot/parkinglot.h

@@ -19,6 +19,7 @@
 
 #include "zoneset.h"
 #include <cc/cpp/data.h>
+#include "data_source_plot.h"
 
 class ParkingLot {
 public:
@@ -28,24 +29,11 @@ public:
     void processMessage();
     void command(std::pair<std::string,isc::data::ElementPtr>);
     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);
 
+    isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
 private:
-    void setDefaultZoneData();
 
-    std::vector<isc::dns::Rdata::RdataPtr> a_records, aaaa_records, ns_records;
-    isc::dns::Rdata::RdataPtr soa;
-    ZoneSet zones;
+    isc::dns::DataSourceParkingLot data_source;
     int sock;
 };
 

+ 37 - 0
src/bin/parkinglot/zoneset.cc

@@ -0,0 +1,37 @@
+#include "zoneset.h"
+
+// see findClosest()
+static bool
+stripLabel(isc::dns::Name& n) {
+    std::string str = n.toText(false);
+    size_t pos = str.find('.');
+    if (pos + 1 < str.size()) {
+        n = isc::dns::Name(str.substr(pos+1));
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool
+ZoneSet::findClosest(const isc::dns::Name& n, isc::dns::Name& closest) {
+
+    // name compare doesnt work in this branch, so we convert and
+    // strip labels
+    isc::dns::Name cur = n;
+    if (contains(n)) {
+        closest = n;
+        return true;
+    }
+
+    bool labels_left = stripLabel(cur);
+    while(labels_left) {
+        if (contains(cur)) {
+            closest = cur;
+            return true;
+        } else {
+            labels_left = stripLabel(cur);
+        }
+    }
+    return false;
+}

+ 36 - 16
src/bin/parkinglot/zoneset.h

@@ -18,23 +18,43 @@
 #define __ZONESET_H 1
 
 #include <set>
+#include <dns/buffer.h>
+#include <dns/name.h>
 
-class ZoneSet : std::set<std::string> {
-    public:
-        void serve(std::string s) {
-            std::cout << "now serving: " << s << std::endl;
-            this->insert(s);
-        }
-        void forget(std::string s) {
-            std::cout << "no longer serving: " << s << std::endl;
-            this->erase(s);
-        }
-        void clear_zones() {
-            this->clear();
-        }
-        bool contains(std::string s) {
-            return (this->find(s) != this->end());
-        }
+class ZoneSet {
+public:
+    void serve(const std::string& s) {
+        serve(isc::dns::Name(s));
+    }
+
+    void serve(const isc::dns::Name& n) {
+        elements.insert(n);
+    }
+    
+    void forget(const std::string& s) {
+        forget(isc::dns::Name(s));
+    }
+
+    void forget(const isc::dns::Name& n) {
+        elements.erase(n);
+    }
+
+    void clear_zones() {
+        elements.clear();
+    }
+
+    bool contains(const std::string& s) {
+        return contains(isc::dns::Name(s));
+    }
+
+    bool contains(const isc::dns::Name& n) {
+        return (elements.find(n) != elements.end());
+    }
+
+    bool findClosest(const isc::dns::Name& n, isc::dns::Name& closest);
+
+private:
+    std::set<isc::dns::Name> elements;
 };
 
 #endif // __ZONESET_H

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

@@ -2,7 +2,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/ext
 
 lib_LIBRARIES = libdns.a
 libdns_a_SOURCES = name.cc buffer.cc rrset.cc message.cc \
-	name.h buffer.h rrset.h message.h
+	name.h buffer.h rrset.h message.h data_source.cc data_source.h
 
 TESTS =
 if HAVE_GTEST

+ 22 - 0
src/lib/dns/data_source.cc

@@ -0,0 +1,22 @@
+#include <dns/buffer.h>
+#include <dns/name.h>
+#include <dns/rrset.h>
+#include <dns/message.h>
+
+#include <cc/cpp/data.h>
+
+#include "name.h"
+
+#include "data_source.h"
+
+namespace isc {
+namespace dns {
+
+void
+DataSource::getData(isc::dns::RRsetPtr query, isc::dns::Message& answer)
+{
+    return;
+}
+
+}
+}

+ 122 - 0
src/lib/dns/data_source.h

@@ -0,0 +1,122 @@
+// 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 "name.h"
+#include "rrset.h"
+
+namespace isc {
+namespace dns {
+
+// do we need to make a template for this?
+// i.e. do we want this to be able to hold more types than RRset?
+class SearchResult {
+public:
+    enum status_type { success, error, not_implemented,
+                       zone_not_found, name_not_found };
+
+    void addRRset(RRsetPtr rrset) { rrsets.push_back(rrset); }
+
+    status_type getStatus() { return status; }
+    void setStatus(status_type s) { status = s; }
+    
+    /* forward iterator interface */
+    typedef std::vector<RRsetPtr>::iterator iterator;
+    typedef std::vector<RRsetPtr>::const_iterator const_iterator;
+    std::vector<RRsetPtr>::iterator begin() { return rrsets.begin(); }
+    std::vector<RRsetPtr>::iterator end() { return rrsets.end(); }
+    std::vector<RRsetPtr>::const_iterator begin() const { return rrsets.begin(); }
+    std::vector<RRsetPtr>::const_iterator end() const { return rrsets.end(); }
+    
+private:
+    status_type status;
+    std::vector<RRsetPtr> rrsets;
+};
+
+// Base class for a DNS Data Source
+class DataSource {
+public:
+    //enum result { success, not_implemented, error, zone_not_found,
+    //              name_not_found };
+
+    DataSource() {};
+    virtual ~DataSource() {};
+
+    //
+    // 'high-level' methods, these may or may not be overwritten;
+    // depending on the data source the default implementation
+    // may not be most efficient, but should at least provide
+    // the needed functionality
+    //
+
+    // fill in separate lists or simple fill in an answer Message object?
+    void getData(const RRsetPtr query, Message& answer);
+
+    // how to provide highlevel update data?
+    //result handleUpdate()
+    
+
+    //
+    // mandatory 'low-level' methods, an implementation must overwrite these
+    //
+    //
+    // for a 'catch-all' datasource, we need to be able to find
+    // out if it has a zone for a given name
+    //
+    // perhaps this should not set a zone Name, but rather a specific
+    // ZoneRef option (which could be datasource-specific, as it will
+    // only be used to pass along to other calls)
+    // Or even more abstract;
+    // SomeHandler initFind(name, whatever else);
+    virtual bool hasZoneFor(const Name& name, Name& zone_name) = 0;
+
+    // for the zone_name, see getZoneFor, perhaps this needs to be a more
+    // general handle
+    // And perhaps we need a function that does not have that argument too
+    virtual SearchResult findRRsets(const Name& zone_name,
+                                    const Name& name,
+                                    const RRClass& clas,
+                                    const RRType& type) = 0;
+
+    //
+    // optional 'low-level' methods, an implementation may overwrite these,
+    // by default they return not_implemented
+    //
+    virtual void init() {};
+    virtual void close() {};
+    //virtual result addRR(Name name, int clas, int type,
+    //                     int ttl, Rdata::RdataPtr data)
+    //                    { return not_implemented; };
+    //virtual result delRR(isc::dns::Name name, int clas, int type) = 0;
+    // on name/class/type again? or use an already constructed object?
+    //virtual result getRRSigs(RRsetPtr target, const RRsetPtr rrset)
+    //                        { return not_implemented; };
+    //virtual result getNSECs(RRsetPtr target, const RRsetPtr rrset)
+    //                        { return not_implemented; };
+
+    // check if the zone exists, and if so, return something that could
+    // be used as a pointer for the rest of these functions?
+    // do we need this? do we want this?
+    //virtual int getZone(void* zone, isc::dns::Name name);
+    
+};
+
+}
+}
+
+#endif

+ 2 - 0
src/lib/dns/message.cc

@@ -21,6 +21,8 @@
 #include <functional>
 #include <algorithm>
 
+#include <iostream>
+
 #include <boost/lexical_cast.hpp>
 
 #include <dns/buffer.h>

+ 12 - 0
src/lib/dns/name.cc

@@ -550,3 +550,15 @@ operator<<(ostream& os, const Name& name)
     os << name.toText();
     return (os);
 }
+
+// temp (bad) comparison, compare not merged yet; needed for zoneset
+// in parkinglot, real version is in trunk, but currently incompatible
+// with this branch
+bool
+Name::operator<(const Name&other) const
+{
+    std::string a = toText();
+    std::string b = other.toText();
+    return a.compare(b);
+}
+