Browse Source

temporary branch for example implementation of original data source proposal. Mainly for archival purposes, will be removed once definite design is agreed upon.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jelte-datasource1@446 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen 15 years ago
parent
commit
5546f52f59

+ 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 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

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

@@ -0,0 +1,121 @@
+
+#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)));
+}
+
+isc::dns::DataSource::result
+DataSourceParkingLot:: findRRset(isc::dns::RRsetPtr& target, isc::dns::Name name,
+                                isc::dns::RRClass clas, isc::dns::RRType type) {
+    Name authors_name("authors.bind");
+    Name version_name("version.bind");
+
+    std::cout << "findRRset()" << std::endl;
+    if (clas == RRClass::CH) {
+        if (type == RRType::TXT) {
+            if (name == authors_name) {
+                target->addRdata(Rdata::RdataPtr(TXT("JINMEI Tatuya").copy()));
+            } else if (name == version_name) {
+                target->addRdata(Rdata::RdataPtr(TXT("BIND10 0.0.1").copy()));
+            } else {
+                std::cout << "ch txt but unknown name" << std::endl;
+                return DataSource::name_not_found;
+            }
+            return DataSource::success;
+        } else {
+            std::cout << "ch but not txt" << std::endl;
+            return DataSource::name_not_found;
+        }
+    } else if (clas == RRClass::IN) {
+        // make zoneset contain Name instead of string?
+        std::cout << "Finding zone for " << name.toText() << std::endl;
+        if (zones.contains(name.toText(true))) {
+            if (type == RRType::A) {
+                BOOST_FOREACH(isc::dns::Rdata::RdataPtr a, a_records) {
+                    target->addRdata(a);
+                }
+            } else if (type == RRType::AAAA) {
+                BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) {
+                    target->addRdata(aaaa);
+                }
+            } else if (type == RRType::NS) {
+                BOOST_FOREACH(isc::dns::Rdata::RdataPtr ns, ns_records) {
+                    target->addRdata(ns);
+                }
+            } else if (type == RRType::SOA) {
+                target->addRdata(soa);
+            } else {
+                std::cout << "type not supported" << std::endl;
+                return name_not_found;
+            }
+            std::cout << "rrset: " << target->toText() << std::endl;
+            
+            std::cout << "success" << std::endl;
+            return success;
+        } else {
+            std::cout << "zone not in zoneset" << std::endl;
+            return DataSource::zone_not_found;
+        }
+    } else {
+        std::cout << "not ch or in" << std::endl;
+        return DataSource::zone_not_found;
+    }
+    // no match at all, error?
+    return DataSource::error;
+}
+
+}
+}

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

@@ -0,0 +1,78 @@
+
+// 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() {};
+    result findRRset(isc::dns::RRsetPtr& target, isc::dns::Name name,
+                 isc::dns::RRClass clas, 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(); };
+    bool has_zone(const std::string& zone_name) { return zones.contains(zone_name); };
+
+    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);
+
+
+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

+ 98 - 40
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,6 +72,68 @@ ParkingLot::ParkingLot(int port) {
 
 void
 ParkingLot::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;
+
+    if (msg.getBuffer().recvFrom(s, sa, &sa_len) > 0) {
+        try {
+            msg.fromWire();
+        } catch (...) {
+            cerr << "parse failed" << endl;
+            return;
+        }
+
+        cout << "received a message:\n" << msg.toText() << endl;
+
+        if (msg.getSection(SECTION_QUESTION).size() != 1)
+            return;
+
+        msg.makeResponse();
+        msg.setAA(true);
+
+        RRsetPtr query = msg.getSection(SECTION_QUESTION)[0];
+
+        DataSource::result result;
+
+        msg.makeResponse();
+        msg.setAA(true);
+        TTL default_ttl = TTL(3600);
+
+        // ok this part of the api needs improvenemt
+        RRset *rrset = new RRset(query->getName(), query->getClass(), query->getType(), default_ttl);
+        RRsetPtr answer = RRsetPtr(rrset);
+        RRset *ns_rrset = new RRset(query->getName(), query->getClass(), RRType::NS, default_ttl);
+        RRsetPtr ns_answer = RRsetPtr(ns_rrset);
+        RRset *soa_rrset = new RRset(query->getName(), query->getClass(), RRType::SOA, default_ttl);
+        RRsetPtr soa_answer = RRsetPtr(soa_rrset);
+        
+        result = data_source.findRRset(answer, query->getName(), query->getClass(), query->getType());
+        switch (result) {
+        case DataSource::success:
+            msg.addRRset(SECTION_ANSWER, answer);
+            if (data_source.findRRset(ns_answer, query->getName(), query->getClass(), RRType::NS) == DataSource::success) {
+                msg.addRRset(SECTION_AUTHORITY, ns_answer);
+            }
+            break;
+        case DataSource::zone_not_found:
+            msg.setRcode(Message::RCODE_NXDOMAIN);
+            break;
+        case DataSource::name_not_found:
+            if (data_source.findRRset(soa_answer, query->getName(), query->getClass(), RRType::SOA) == DataSource::success) {
+                msg.addRRset(SECTION_AUTHORITY, soa_answer);
+            }
+            break;
+        }
+        msg.toWire();
+        cout << "sending a response (" <<
+            boost::lexical_cast<string>(msg.getBuffer().getSize())
+                  << " bytes):\n" << msg.toText() << endl;
+        msg.getBuffer().sendTo(s, *sa, sa_len);
+    }
+/*
     Name authors_name("authors.bind");
     Name version_name("version.bind");
     struct sockaddr_storage ss;
@@ -223,6 +250,7 @@ ParkingLot::processMessage() {
                   << " bytes):\n" << msg.toText() << endl;
         msg.getBuffer().sendTo(s, *sa, sa_len);
     }
+*/
 }
 
 void
@@ -234,14 +262,44 @@ ParkingLot::command(pair<string,ElementPtr> cmd) {
         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();
+        //zones.clear_zones();
         BOOST_FOREACH(ElementPtr zone, zonelist_el->listValue()) {
-            zones.serve(zone->stringValue());
+            //zones.serve(zone->stringValue());
         }
     }
 }
 
-void
-ParkingLot::serve(std::string zone_name) {
-    zones.serve(zone_name);
+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] }");
 }
+
+

+ 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;
 };
 

+ 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 {
+
+DataSource::result
+DataSource::getData(isc::dns::RRsetPtr query, isc::dns::Message& answer)
+{
+    return DataSource::not_implemented;
+}
+
+}
+}

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

@@ -0,0 +1,81 @@
+// 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 {
+
+// 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?
+    result getData(const RRsetPtr query, Message& answer);
+
+    // how to provide highlevel update data?
+    //result handleUpdate()
+    
+
+    //
+    // mandatory 'low-level' methods, an implementation must overwrite these
+    //
+    virtual result findRRset(RRsetPtr& target, 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>