Parcourir la source

datasource updates, add zone concept (with temporary(?) getZoneFor()), removed old code

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jelte-datasource1@469 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen il y a 15 ans
Parent
commit
1ee5cfa470

+ 73 - 25
src/bin/parkinglot/data_source_plot.cc

@@ -57,65 +57,113 @@ DataSourceParkingLot::DataSourceParkingLot() {
                                         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) {
+bool
+DataSourceParkingLot::hasZoneFor(const Name& name, Name &zone_name)
+{
+    if (zones.contains(name.toText(true))) {
+        zone_name = Name(name);
+        return true;
+    } else {
+        /* try 1 level higher? i.e. www.asdf.nl? */
+        return false;
+    }
+}
+
+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");
-
+    
     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()));
+                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) {
-                target->addRdata(Rdata::RdataPtr(TXT("BIND10 0.0.1").copy()));
+                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 {
                 std::cout << "ch txt but unknown name" << std::endl;
-                return DataSource::name_not_found;
+                result.setStatus(SearchResult::name_not_found);
             }
-            return DataSource::success;
         } else {
-            std::cout << "ch but not txt" << std::endl;
-            return DataSource::name_not_found;
+            result.setStatus(SearchResult::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))) {
+            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) {
-                    target->addRdata(a);
+                    rrset->addRdata(a);
                 }
             } else if (type == RRType::AAAA) {
                 BOOST_FOREACH(isc::dns::Rdata::RdataPtr aaaa, aaaa_records) {
-                    target->addRdata(aaaa);
+                    rrset->addRdata(aaaa);
                 }
             } else if (type == RRType::NS) {
                 BOOST_FOREACH(isc::dns::Rdata::RdataPtr ns, ns_records) {
-                    target->addRdata(ns);
+                    rrset->addRdata(ns);
                 }
             } else if (type == RRType::SOA) {
-                target->addRdata(soa);
-            } else {
-                std::cout << "type not supported" << std::endl;
-                return name_not_found;
+                rrset->addRdata(soa);
             }
-            std::cout << "rrset: " << target->toText() << std::endl;
-            
-            std::cout << "success" << std::endl;
-            return success;
+            result.addRRset(rrset);
         } else {
             std::cout << "zone not in zoneset" << std::endl;
-            return DataSource::zone_not_found;
+            result.setStatus(SearchResult::zone_not_found);
         }
     } else {
         std::cout << "not ch or in" << std::endl;
-        return DataSource::zone_not_found;
+        result.setStatus(SearchResult::zone_not_found);
     }
-    // no match at all, error?
-    return DataSource::error;
+    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();
+}
+
+
 }
 }

+ 16 - 4
src/bin/parkinglot/data_source_plot.h

@@ -41,15 +41,16 @@ public:
     
     void init() {};
     void close() {};
-    result findRRset(isc::dns::RRsetPtr& target, isc::dns::Name name,
-                 isc::dns::RRClass clas, isc::dns::RRType type);
-
+    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(); };
-    bool has_zone(const std::string& zone_name) { return zones.contains(zone_name); };
 
     void clearARecords() { a_records.clear(); };
     void clearAAAARecords() { aaaa_records.clear(); };
@@ -61,6 +62,17 @@ public:
 
     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:
     //

+ 39 - 155
src/bin/parkinglot/parkinglot.cc

@@ -96,177 +96,61 @@ ParkingLot::processMessage() {
 
         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;
-    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];
-
-        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);
+        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) {
+                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())
                   << " bytes):\n" << msg.toText() << endl;
         msg.getBuffer().sendTo(s, *sa, sa_len);
     }
-*/
-}
-
-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

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

@@ -12,10 +12,10 @@
 namespace isc {
 namespace dns {
 
-DataSource::result
+void
 DataSource::getData(isc::dns::RRsetPtr query, isc::dns::Message& answer)
 {
-    return DataSource::not_implemented;
+    return;
 }
 
 }

+ 53 - 12
src/lib/dns/data_source.h

@@ -23,11 +23,36 @@
 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 };
+    //enum result { success, not_implemented, error, zone_not_found,
+    //              name_not_found };
 
     DataSource() {};
     virtual ~DataSource() {};
@@ -40,7 +65,7 @@ public:
     //
 
     // fill in separate lists or simple fill in an answer Message object?
-    result getData(const RRsetPtr query, Message& answer);
+    void getData(const RRsetPtr query, Message& answer);
 
     // how to provide highlevel update data?
     //result handleUpdate()
@@ -49,8 +74,24 @@ public:
     //
     // mandatory 'low-level' methods, an implementation must overwrite these
     //
-    virtual result findRRset(RRsetPtr& target, const Name name,
-                            const RRClass clas, const RRType type) = 0;
+    //
+    // 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,
@@ -58,15 +99,15 @@ public:
     //
     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 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; };
+    //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?