[svn] commit: r815 - in /branches/each-ds/src/lib/auth/cpp: TODO data_source.cc data_source.h data_source_sqlite3.cc data_source_sqlite3.h data_source_static.h

BIND 10 source code commits bind10-changes at lists.isc.org
Sun Feb 14 02:42:56 UTC 2010


Author: each
Date: Sun Feb 14 02:42:55 2010
New Revision: 815

Log:
checkpoint:
 - added findReferral() and findExactRRset() functions in data source classes
 - added doQueryTask() helper function
 - replaced calls to findRRset() in doQuery() with calls to doQueryTask()
 - added incomplete support for zone cuts.  (as of now, referrals are done
   correctly if you query for the exact name of the referred zone, but
   not if you query for any subdomain.)

Modified:
    branches/each-ds/src/lib/auth/cpp/TODO
    branches/each-ds/src/lib/auth/cpp/data_source.cc
    branches/each-ds/src/lib/auth/cpp/data_source.h
    branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.cc
    branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.h
    branches/each-ds/src/lib/auth/cpp/data_source_static.h

Modified: branches/each-ds/src/lib/auth/cpp/TODO
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/TODO (original)
+++ branches/each-ds/src/lib/auth/cpp/TODO Sun Feb 14 02:42:55 2010
@@ -3,3 +3,7 @@
   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.
+
+- Implement "match-down" search with REF_QUERY tasks and name-label
+  iteration.
+

Modified: branches/each-ds/src/lib/auth/cpp/data_source.cc
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/data_source.cc (original)
+++ branches/each-ds/src/lib/auth/cpp/data_source.cc Sun Feb 14 02:42:55 2010
@@ -48,6 +48,27 @@
     }
 }
 
+DataSrc::Result
+doQueryTask(const DataSrc* ds, Query q, QueryTask task, RRsetList& target) {
+    RRsetList sigs;     // XXX: only needed until the lower-level api changes 
+
+    switch (task.op) {
+    case QueryTask::AUTH_QUERY:
+        return (ds->findRRset(q, task.qname, task.qclass, task.qtype,
+                              target, sigs));
+
+    case QueryTask::SIMPLE_QUERY:
+        return (ds->findExactRRset(q, task.qname, task.qclass, task.qtype,
+                                   target, sigs));
+
+    case QueryTask::ADDR_QUERY:
+        return (ds->findAddrs(q, task.qname, task.qclass, target, sigs));
+
+    case QueryTask::REF_QUERY:
+        return (ds->findReferral(q, task.qname, task.qclass, target, sigs));
+    }
+}
+
 //
 // doQuery: Processes a query.
 // On success, the query status is set to Query::SUCCESS and
@@ -64,32 +85,48 @@
         QueryTask task = q.tasks().front();
         q.tasks().pop();
 
+        // Other task types should never be pushed onto the task queue.
+        if (task.op != QueryTask::AUTH_QUERY &&
+            task.op != QueryTask::ADDR_QUERY) {
+            m.setRcode(Rcode::SERVFAIL());
+            q.setStatus(Query::FAILURE);
+            return;
+        }
+
+        // Find the closest enclosing zone for which we are authoritative
+        // (and the concrete data source which is authoritative for it).
         NameMatch match(task.qname);
         findClosestEnclosure(match);
         const DataSrc* ds = match.bestDataSrc();
         const Name* zone = match.closestName();
 
-        if (ds == NULL) {
+        if (ds != NULL) {
+            m.setHeaderFlag(MessageFlag::AA());
+            result = doQueryTask(ds, q, task, data);
+            if (result == SUCCESS) {
+                if (task.op == QueryTask::ADDR_QUERY) {
+                    BOOST_FOREACH (RRsetPtr rrset, data) {
+                        m.addRRset(task.section, rrset);
+                    }
+                    continue;
+                }
+            } else if (result == REFERRAL_FOUND) {
+                if (zone->getLabelCount() == task.qname.getLabelCount()) {
+                    // An NS at the zone apex is expected.
+                    result = SUCCESS;
+                }
+            }
+        } else {
             result = ZONE_NOT_FOUND;
-        } else {
-            result = ds->findRRset(q, task.qname, task.qclass, task.qtype,
-                                   data, sigs);
-
-            // XXX:
-            // For this version, there should only be one RRset in data,
-            // and no more than one RRset in sigs.  We will address other
-            // cases (e.g. ANY queries) later.
-            if (result == SUCCESS && (data.size() != 1 || sigs.size() > 1)) {
-                result = ERROR;
-            }
         }
 
         switch (result) {
         case SUCCESS:
+            // This will need to be able to handle multiple RRsets
+            // once RRType ANY and/or DNSSEC are supported.  For right
+            // now, however, we assume that an auth query will return
+            // only one RRset: either the data requested or a CNAME.
             m.addRRset(task.section, data[0]);
-            if (q.wantDnssec() && sigs.size() == 1) {
-                m.addRRset(task.section, sigs[0]);
-            }
 
             switch (task.state) {
             case QueryTask::GETANSWER:
@@ -100,27 +137,25 @@
                     // Add the NS records for the enclosing zone to
                     // the authority section.
                     if (data[0]->getType() != RRType::NS()) {
-                        RRsetList auth, asigs;
-                        result = ds->findRRset(q, Name(*zone), task.qclass,
-                                               RRType::NS(), auth, asigs);
+                        RRsetList auth;
+                        QueryTask t(Name(*zone), task.qclass, RRType::NS(), 
+                                    Section::AUTHORITY(),
+                                    QueryTask::SIMPLE_QUERY); 
+                        result = doQueryTask(ds, q, t, auth);
                         if (result != SUCCESS) {
                             m.setRcode(Rcode::SERVFAIL());
                             return;
                         }
 
                         m.addRRset(Section::AUTHORITY(), auth[0]);
-                        if (q.wantDnssec() && asigs.size() == 1) {
-                            m.addRRset(Section::AUTHORITY(), asigs[0]);
-                        }
                         getAdditional(q, auth[0]);
                     }
                 }
                 continue;
 
             case QueryTask::GETADDITIONAL:
-                // If no more work items, add authority section now
                 if (q.tasks().empty()) {
-                    q.setStatus(Query::Query::SUCCESS);
+                    q.setStatus(Query::SUCCESS);
                     return;
                 }
                 continue;
@@ -143,9 +178,6 @@
             }
 
             m.addRRset(task.section, data[0]);
-            if (q.wantDnssec() && sigs.size() == 1) {
-                m.addRRset(task.section, sigs[0]);
-            }
 
             it = data[0]->getRdataIterator();
             for (it->first(); !it->isLast(); it->next()) {
@@ -160,6 +192,23 @@
             }
             continue;
 
+        case REFERRAL_FOUND:
+            m.clearHeaderFlag(MessageFlag::AA());
+            if (task.state == QueryTask::GETANSWER) {
+                RRsetList auth;
+                QueryTask t(task.qname, task.qclass, RRType::NS(), 
+                            Section::AUTHORITY(),
+                            QueryTask::SIMPLE_QUERY); 
+                result = doQueryTask(ds, q, t, auth);
+                if (result != SUCCESS) {
+                    m.setRcode(Rcode::SERVFAIL());
+                    return;
+                }
+                m.addRRset(Section::AUTHORITY(), auth[0]);
+                getAdditional(q, auth[0]);
+            }
+            continue;
+
         case NAME_NOT_FOUND:
         case TYPE_NOT_FOUND:
             if (task.state == QueryTask::GETANSWER) {
@@ -167,18 +216,16 @@
                     m.setRcode(Rcode::NXDOMAIN());
                 }
 
-                result = ds->findRRset(q, Name(*zone), task.qclass,
-                                       RRType::SOA(), data, sigs);
+                RRsetList soa;
+                QueryTask t(Name(*zone), task.qclass, RRType::SOA(), 
+                            Section::AUTHORITY(), QueryTask::SIMPLE_QUERY); 
+                result = doQueryTask(ds, q, t, soa);
                 if (result != SUCCESS) {
                     m.setRcode(Rcode::SERVFAIL());
                     return;
                 }
 
-                m.addRRset(Section::AUTHORITY(), data[0]);
-                if (q.wantDnssec() && sigs.size() == 1) {
-                    m.addRRset(Section::AUTHORITY(), sigs[0]);
-                }
-
+                m.addRRset(Section::AUTHORITY(), soa[0]);
                 q.setStatus(Query::FAILURE);
                 return;
             }
@@ -192,6 +239,7 @@
             }
             continue;
 
+        case DNAME_FOUND:       // XXX: not yet implemented
         case NOT_IMPLEMENTED:
         case ERROR:
             m.setRcode(Rcode::SERVFAIL());
@@ -201,6 +249,5 @@
     }
 };
 
-
-}
-}
+}
+}

Modified: branches/each-ds/src/lib/auth/cpp/data_source.h
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/data_source.h (original)
+++ branches/each-ds/src/lib/auth/cpp/data_source.h Sun Feb 14 02:42:55 2010
@@ -40,6 +40,8 @@
         ERROR,
         NOT_IMPLEMENTED,
         CNAME_FOUND,
+        DNAME_FOUND,
+        REFERRAL_FOUND,
         ZONE_NOT_FOUND,
         NAME_NOT_FOUND,
         TYPE_NOT_FOUND
@@ -48,26 +50,51 @@
     virtual ~AbstractDataSrc() {};
 
     // 'High-level' methods.  These will be implemented by the
-    // general DataSrc class, but MAY be overwritten by subclasses.
+    // general DataSrc class, and SHOULD NOT be overwritten by subclasses.
     virtual void doQuery(Query query) = 0;
+
+    // XXX: High-level methods to be implemented later:
     // virtual void doUpdate(Update update) = 0;
     // virtual void doXfr(Query query) = 0;
 
-    // Mandatory 'low-level' methods: These will NOT be implemented by
-    // the general DataSrc class; subclasses MUST implement them.
-    virtual Result findRRset(const Query& q,
-                               const Name& qname,
-                               const RRClass& qclass,
-                               const RRType& qtype,
-                               RRsetList& target,
-                               RRsetList& sigs) const = 0;
-
+    // 'Medium-level' methods.  This will be implemented by the general
+    // DataSrc class but MAY be overwritten by subclasses.
     virtual void findClosestEnclosure(NameMatch& match) const = 0;
 
     // Optional 'low-level' methods.  These will have stub implementations
     // in the general DataSrc class but MAY be overwritten by subclasses
     virtual Result init() = 0;
     virtual Result close() = 0;
+
+    // Mandatory 'low-level' methods: These will NOT be implemented by
+    // the general DataSrc class; subclasses MUST implement them.
+    virtual Result findRRset(const Query& q,
+                             const Name& qname,
+                             const RRClass& qclass,
+                             const RRType& qtype,
+                             RRsetList& target,
+                             RRsetList& sigs) const = 0;
+
+    virtual Result findExactRRset(const Query& q,
+                                  const Name& qname,
+                                  const RRClass& qclass,
+                                  const RRType& qtype,
+                                  RRsetList& target,
+                                  RRsetList& sigs) const = 0;
+
+    // These will have dumb implementations in the general DataSrc
+    // class, and SHOULD be overwritten by subclasses.
+    virtual Result findAddrs(const Query& q,
+                             const Name& qname,
+                             const RRClass& qclass,
+                             RRsetList& target,
+                             RRsetList& sigs) const = 0;
+
+     virtual Result findReferral(const Query& q,
+                                const Name& qname,
+                                const RRClass& qclass,
+                                RRsetList& target,
+                                RRsetList& sigs) const = 0;
 };
 
 // Base class for a DNS Data Source
@@ -79,12 +106,27 @@
 
     void doQuery(Query q);
 
+    virtual void findClosestEnclosure(NameMatch& match) const = 0;
+
+    const RRClass& getClass() const { return rrclass; }
+    void setClass(RRClass& c) { rrclass = c; }
+
+    Result init() { return NOT_IMPLEMENTED; }
+    Result close() { return NOT_IMPLEMENTED; }
+
     virtual Result findRRset(const Query& q,
-                               const Name& qname,
-                               const RRClass& qclass,
-                               const RRType& qtype,
-                               RRsetList& target,
-                               RRsetList& sigs) const = 0;
+                             const Name& qname,
+                             const RRClass& qclass,
+                             const RRType& qtype,
+                             RRsetList& target,
+                             RRsetList& sigs) const = 0;
+
+    virtual Result findExactRRset(const Query& q,
+                                  const Name& qname,
+                                  const RRClass& qclass,
+                                  const RRType& qtype,
+                                  RRsetList& target,
+                                  RRsetList& sigs) const = 0;
 
     virtual Result findAddrs(const Query& q,
                                const Name& qname,
@@ -101,13 +143,48 @@
         return (r);
     }
 
-    virtual void findClosestEnclosure(NameMatch& match) const = 0;
-
-    const RRClass& getClass() const { return rrclass; }
-    void setClass(RRClass& c) { rrclass = c; }
-
-    Result init() { return NOT_IMPLEMENTED; }
-    Result close() { return NOT_IMPLEMENTED; }
+    virtual Result findReferral(const Query& q,
+                                const Name& qname,
+                                const RRClass& qclass,
+                                RRsetList& target,
+                                RRsetList& sigs) const {
+        Result r;
+        bool found_ns = false;
+        bool found_ds = false;
+        bool found_dname = false;
+
+        r = findRRset(q, qname, qclass, RRType::NS(), target, sigs);
+        if (r == SUCCESS) {
+            found_ns = true;
+        } else if (r != TYPE_NOT_FOUND) {
+            return (r);
+        }
+
+        // XXX: The following code requires new rdata types to be
+        // implemented.
+
+#if 0
+        r = findRRset(q, qname, qclass, RRType::DS(), target, sigs);
+        if (r == SUCCESS) {
+            found_ds = true;
+        } else if (r != TYPE_NOT_FOUND) {
+            return (r);
+        }
+
+        r = findRRset(q, qname, qclass, RRType::DNAME(), target, sigs);
+        if (r == SUCCESS) {
+            found_dname = true;
+        } else if (r != TYPE_NOT_FOUND) {
+            return (r);
+        }
+#endif
+
+        if (found_ns || found_dname || found_ds) {
+            return (SUCCESS);
+        } else {
+            return (TYPE_NOT_FOUND);
+        }
+    }
 
 private:
     RRClass rrclass;
@@ -140,18 +217,31 @@
     // Actual queries for data should not be sent to a MetaDataSrc object,
     // so we return NOT_IMPLEMENTED if we receive any.
     //
-    // Instead, use findClosestEnclosure() to get a pointer to the best
-    // concrete data source, then send all queries directly there.
+    // The proper way to use the MetaDataSrc is to run findClosestEnclosure()
+    // to get a pointer to the best concrete data source for the specified
+    // zone, then send all queries directly to that data source.
 
     Result findRRset(const Query& q, const Name& qname,
-                       const RRClass& qclass, const RRType& qtype,
-                       RRsetList& target, RRsetList& sigs) const {
+                     const RRClass& qclass, const RRType& qtype,
+                     RRsetList& target, RRsetList& sigs) const {
+        return (NOT_IMPLEMENTED);
+    }
+
+    Result findExactRRset(const Query& q, const Name& qname,
+                          const RRClass& qclass, const RRType& qtype,
+                          RRsetList& target, RRsetList& sigs) const {
         return (NOT_IMPLEMENTED);
     }
 
     Result findAddrs(const Query& q,
-                       const Name& qname, const RRClass& qclass,
-                       RRsetList& target, RRsetList& sigs) const {
+                     const Name& qname, const RRClass& qclass,
+                     RRsetList& target, RRsetList& sigs) const {
+        return (NOT_IMPLEMENTED);
+    }
+
+    Result findReferral(const Query& q,
+                        const Name& qname, const RRClass& qclass,
+                        RRsetList& target, RRsetList& sigs) const {
         return (NOT_IMPLEMENTED);
     }
 

Modified: branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.cc
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.cc (original)
+++ branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.cc Sun Feb 14 02:42:55 2010
@@ -67,8 +67,8 @@
 
 int
 Sqlite3DataSrc::
-findRecords(const Name& name, const RRType& rdtype,
-            RRsetList& target, bool& node_exists, bool& found_cname) const
+findRecords(const Name& name, const RRType& rdtype, RRsetList& target,
+            bool& node_exists, bool& found_cname, bool& found_ns) const
 {
     int rc;
     const string s_name = name.toText();
@@ -102,16 +102,28 @@
     int sig_ttl = -1;
     int rows = 0;
     found_cname = false;
+    found_ns = false;
     RRsetPtr rrset;
 
     rc = sqlite3_step(q_record);
     while (rc == SQLITE_ROW) {
-        rows++;
-
         const char *type = (const char *)sqlite3_column_text(q_record, 0);
         int ttl = sqlite3_column_int(q_record, 1);
         const char *sigtype = (const char *)sqlite3_column_text(q_record, 2);
         const char *rdata = (const char *)sqlite3_column_text(q_record, 3);
+
+        // looking for something else but found NS; we need to inform
+        // the caller that this is a referral, but we do not return the
+        // NS RRset to the caller.
+        if (strcmp(c_rdtype, "NS") != 0 &&
+            (strcmp(type, "NS") == 0 ||
+             (sigtype != NULL && strcmp(sigtype, "NS") == 0))) {
+            found_ns = true;
+            rc = sqlite3_step(q_record);
+            continue;
+        }
+
+        rows++;
 
         // looking for something else but found a CNAME
         if (strcmp(type, "CNAME") == 0 && strcmp(c_rdtype, "CNAME") != 0) {
@@ -232,7 +244,8 @@
     const char *q_record_str = "SELECT rdtype, ttl, sigtype, rdata "
                                "FROM records WHERE zone_id=?1 AND name=?2 AND "
                                "((rdtype=?3 OR sigtype=?3) OR "
-                               "(rdtype='CNAME' OR sigtype='CNAME'))";
+                               "(rdtype='CNAME' OR sigtype='CNAME') OR "
+                               "(rdtype='NS' OR sigtype='NS'))";
     try {
         q_record = prepare(q_record_str);
     } catch (const char *e) {
@@ -242,7 +255,8 @@
     }
 
     const char *q_count_str = "SELECT COUNT(*) FROM records "
-                              "WHERE zone_id=?1 AND name=?2";
+                              "WHERE zone_id=?1 AND (name=?2 OR "
+                              "name LIKE ?2 || '.%');";
     try {
         q_count = prepare(q_count_str);
     } catch (const char *e) {
@@ -343,9 +357,13 @@
                           RRsetList& target,
                           RRsetList& sigs) const
 {
-    bool node_exists, found_cname;
-    int rows = findRecords(qname, qtype, target, node_exists, found_cname);
-    if (rows == 0 && node_exists) {
+    bool node_exists, found_cname, found_ns;
+    int rows = findRecords(qname, qtype, target, node_exists,
+                           found_cname, found_ns);
+
+    if (found_ns) {
+        return (REFERRAL_FOUND);
+    } else if (rows == 0 && node_exists) {
         return (TYPE_NOT_FOUND);
     } else if (rows == 0) {
         return (NAME_NOT_FOUND);
@@ -356,6 +374,28 @@
     }
 }
 
+DataSrc::Result
+Sqlite3DataSrc::findExactRRset(const Query& q,
+                               const Name& qname,
+                               const RRClass& qclass,
+                               const RRType& qtype,
+                               RRsetList& target,
+                               RRsetList& sigs) const
+{
+    bool node_exists, found_cname, found_ns;
+    int rows = findRecords(qname, qtype, target, node_exists,
+                           found_cname, found_ns);
+
+    // We ignore found_cname and found_ns in this version.
+    if (found_cname || (rows == 0 && node_exists)) {
+        return (TYPE_NOT_FOUND);
+    } else if (rows == 0) {
+        return (NAME_NOT_FOUND);
+    } else {
+        return (SUCCESS);
+    }
+}
+
 //
 //  Open the database.
 //

Modified: branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.h
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.h (original)
+++ branches/each-ds/src/lib/auth/cpp/data_source_sqlite3.h Sun Feb 14 02:42:55 2010
@@ -39,6 +39,12 @@
                              const RRType& qtype,
                              RRsetList& target, RRsetList& sigs) const;
 
+    virtual Result findExactRRset(const Query& q,
+                                  const Name& qname,
+                                  const RRClass& qclass,
+                                  const RRType& qtype,
+                                  RRsetList& target, RRsetList& sigs) const;
+
     virtual Result init();
     virtual Result close();
 
@@ -49,7 +55,7 @@
     int getVersion(void);
     int hasExactZone(const char *name) const;
     int findRecords(const Name& name, const RRType& rdtype, RRsetList& target,
-                    bool& node_exists, bool& found_cname) const;
+                    bool& node_exists, bool& found_cname, bool& found_ns) const;
     int findClosest(const char *name, const char **position) const;
     void loadVersion(void);
     void setupPreparedStatements(void);

Modified: branches/each-ds/src/lib/auth/cpp/data_source_static.h
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/data_source_static.h (original)
+++ branches/each-ds/src/lib/auth/cpp/data_source_static.h Sun Feb 14 02:42:55 2010
@@ -35,7 +35,7 @@
 class StaticDataSrc : public DataSrc {
 public:
     StaticDataSrc();
-    ~StaticDataSrc() {};
+    ~StaticDataSrc() {}
 
     void findClosestEnclosure(NameMatch& match) const;
 
@@ -46,8 +46,18 @@
                      RRsetList& target,
                      RRsetList& sigs) const;
 
-    Result init() { return (SUCCESS); };
-    Result close() { return (SUCCESS); } ;
+    Result findExactRRset(const Query& q,
+                         const Name& qname,
+                         const RRClass& qclass,
+                         const RRType& qtype,
+                         RRsetList& target,
+                         RRsetList& sigs) const
+    {
+        return (findRRset(q, qname, qclass, qtype, target, sigs));
+    }
+
+    Result init() { return (SUCCESS); }
+    Result close() { return (SUCCESS); }
 
 private:
     const Name authors_name;




More information about the bind10-changes mailing list