[svn] commit: r822 - in /branches/each-ds/src/lib: auth/cpp/TODO auth/cpp/data_source.cc auth/cpp/data_source.h auth/cpp/query.h dns/cpp/rdata/generic/dname_39.cc dns/cpp/rdata/generic/dname_39.h

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Feb 15 01:10:39 UTC 2010


Author: each
Date: Mon Feb 15 01:10:38 2010
New Revision: 822

Log:
checkpoint:
 - added DNAME rrtype
 - added DNAME support in query
 - refactored cname-chasing code a helper function

Added:
    branches/each-ds/src/lib/dns/cpp/rdata/generic/dname_39.cc
    branches/each-ds/src/lib/dns/cpp/rdata/generic/dname_39.h
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/query.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 Mon Feb 15 01:10:38 2010
@@ -1,16 +1,20 @@
+Data source:
+- change RRsetList to something that can be indexed by the RRType
+- improve support for multiple-RRset answers from the data source
+- add support for type-ANY queries
+- consider altering the "task queue" design (at this point it's relatively
+  rare for it to have more than one item).
+- check want_additional before adding additional data
+- omit additional data that's already in the answer section
+- make sure glue is not returned in additional section except for NS
+
+DNSSEC:
+- add at least minimal EDNS0 support sufficient to recognize the DO bit
 - change RRset API to include a pointer to signatures (BasicRRset will
   remain for the cases when we want to deal with an RRset that isn't
   signed).
-- change RRsetList to something that can be indexed by the RRType
-- add DNAME rdata type 
-- add DNAME/CNAME synthesis
-- refactor code that is repeated into helper functions
-- consider altering the "task queue" design (at this point it's relatively
-  rare for it to have more than one item).
-
-DNSSEC:
-- add at least minimal EDNS0 support sufficient to recognize the DO bit
-- add signatures to positive answers
+- wherever RRsets are being added to a section of the reply, if DNSSEC
+  is wanted and signatures are availale, add them as well
 - add NSEC/NSEC3 to authority section in negative answers
 - add DS to authority in referrals
 
@@ -21,3 +25,7 @@
 - we need to use the name-reversal trick so we can use an index on the
   reverse name during lookups (probably best done with a Name API change)
 - findRecords() should handle the Name-to-c_str conversion, not the caller
+
+Other changes:
+- add Message method getSectionCount() so it isn't necessary to iterate
+  over the question section to find out how many there are.

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 Mon Feb 15 01:10:38 2010
@@ -11,6 +11,7 @@
 #include "data_source.h"
 
 using namespace isc::dns;
+using namespace isc::dns::rdata;
 
 namespace isc {
 namespace auth {
@@ -19,27 +20,75 @@
 getAdditional(Query& q, RRsetPtr rrset) {
     RdataIteratorPtr it = rrset->getRdataIterator();
     for (it->first(); !it->isLast(); it->next()) {
-        const rdata::Rdata& rd(it->getCurrent());
+        const Rdata& rd(it->getCurrent());
+        QueryTask* t = NULL;
         if (rrset->getType() == RRType::NS()) {
-            const rdata::generic::NS& ns =
-                dynamic_cast<const rdata::generic::NS&>(rd);
+            const generic::NS& ns = dynamic_cast<const generic::NS&>(rd);
 
             // XXX: For smaller responses, we should try to omit A/AAAA
             // in the additional section if they are already in the answer
             // section, but for now we don't.
-            QueryTask t(ns.getNSName(), q.qclass(), RRType::ANY(),
-                        Section::ADDITIONAL(), QueryTask::ADDR_QUERY,
-                        QueryTask::GETADDITIONAL); 
-            q.tasks().push(t);
+            t = new QueryTask(ns.getNSName(), q.qclass(), Section::ADDITIONAL(),
+                              QueryTask::ADDR_QUERY, QueryTask::GETADDITIONAL); 
         } else if (rrset->getType() == RRType::MX()) {
-            const rdata::generic::MX& mx =
-                dynamic_cast<const rdata::generic::MX&>(rd);
-            QueryTask t(mx.getMXName(), q.qclass(), RRType::ANY(),
-                        Section::ADDITIONAL(), QueryTask::ADDR_QUERY,
-                        QueryTask::GETADDITIONAL); 
-            q.tasks().push(t);
-        }
-    }
+            const generic::MX& mx = dynamic_cast<const generic::MX&>(rd);
+            t = new QueryTask(mx.getMXName(), q.qclass(), Section::ADDITIONAL(),
+                              QueryTask::ADDR_QUERY, QueryTask::GETADDITIONAL); 
+        }
+        if (t != NULL) {
+            q.tasks().push(*t);
+        }
+    }
+}
+
+static void
+synthesizeCname(Query& q, QueryTask& task, RRsetPtr rrset, RRsetList& target) {
+    RdataIteratorPtr it;
+    it = rrset->getRdataIterator();
+
+    // More than one DNAME RR in the RRset is illegal, so we only have
+    // to process the first one.
+    it->first();
+    if (it->isLast()) {
+        return;
+    }
+
+    const Rdata& rd(it->getCurrent());
+    const generic::DNAME& dname = dynamic_cast<const generic::DNAME&>(rd);
+    const Name& dname_target(dname.getDname());
+
+    try {
+        int qnlen = task.qname.getLabelCount();
+        int dnlen = rrset->getName().getLabelCount();
+        const Name& prefix(task.qname.split(0, qnlen - dnlen));
+        const Name& newname(prefix.concatenate(dname_target));
+        RRsetPtr cname(new RRset(task.qname, task.qclass, RRType::CNAME(),
+                                 rrset->getTTL()));
+        cname->addRdata(generic::CNAME(newname));
+        cname->setTTL(rrset->getTTL());
+        target.push_back(cname);
+    } catch (...) {}
+}
+
+static void
+chaseCname(Query& q, QueryTask& task, RRsetPtr rrset) {
+    RdataIteratorPtr it;
+    it = rrset->getRdataIterator();
+
+    // More than one DNAME RR in the RRset is illegal, so we only have
+    // to process the first one.
+    it->first();
+    if (it->isLast()) {
+        return;
+    }
+
+    const Rdata& rd(it->getCurrent());
+    const generic::CNAME& cname = dynamic_cast<const generic::CNAME&>(rd);
+    const Name& target(cname.getCname());
+
+    QueryTask* t = new QueryTask(target, task.qclass, task.qtype,
+                                 Section::ANSWER(), QueryTask::FOLLOWCNAME);
+    q.tasks().push(*t);
 }
 
 DataSrc::Result
@@ -110,27 +159,39 @@
                         RRsetList ref;
                         for(int i = diff; i > 1; i--) {
                             QueryTask t(task.qname.split(i - 1, nlen - i),
-                                        task.qclass, RRType::ANY(),
-                                        Section::AUTHORITY(),
-                                        QueryTask::REF_QUERY); 
+                                        task.qclass, QueryTask::REF_QUERY); 
                             result = doQueryTask(ds, q, t, ref);
                             if (result == SUCCESS) {
                                 found = true;
                                 break;
                             }
                         }
-                        // XXX: Currently ref will only have NS;
-                        // later it must handle NS, DS, or DNAME
+
                         if (found) {
-                            m.addRRset(Section::AUTHORITY(), ref[0]);
-                            getAdditional(q, ref[0]);
+                            BOOST_FOREACH (RRsetPtr r, ref) {
+                                if (r->getType() == RRType::NS()) {
+                                    // XXX: eventually also handle DS
+                                    m.addRRset(Section::AUTHORITY(), r);
+                                    getAdditional(q, r);
+                                } else if (r->getType() == RRType::DNAME()) {
+                                    m.addRRset(Section::ANSWER(), r);
+                                    RRsetList syn;
+                                    synthesizeCname(q, task, r, syn);
+                                    if (syn.size() == 1) {
+                                        m.addRRset(Section::ANSWER(), syn[0]);
+                                        chaseCname(q, task, syn[0]);
+                                    }
+                                }
+                            }
                             continue;
                         }
                     }
-
-                    // We appear to have authoritative data; set the header
-                    // flag.  (We may clear it later if we find a referral
-                    // at the actual qname node.)
+                }
+
+                // We appear to have authoritative data; set the header
+                // flag.  (We may clear it later if we find a referral
+                // at the actual qname node.)
+                if (task.state == QueryTask::GETANSWER) {
                     m.setHeaderFlag(MessageFlag::AA());
                 }
             }
@@ -170,7 +231,6 @@
                     if (data[0]->getType() != RRType::NS()) {
                         RRsetList auth;
                         QueryTask t(Name(*zone), task.qclass, RRType::NS(), 
-                                    Section::AUTHORITY(),
                                     QueryTask::SIMPLE_QUERY); 
                         result = doQueryTask(ds, q, t, auth);
                         if (result != SUCCESS) {
@@ -211,28 +271,16 @@
             }
 
             m.addRRset(task.section, data[0]);
-
-            it = data[0]->getRdataIterator();
-            for (it->first(); !it->isLast(); it->next()) {
-                const rdata::Rdata& rd(it->getCurrent());
-                const rdata::generic::CNAME& cname =
-                    dynamic_cast<const rdata::generic::CNAME&>(rd);
-                const Name& target(cname.getCname());
-                QueryTask t(target, task.qclass, task.qtype,
-                            Section::ANSWER(), QueryTask::FOLLOWCNAME);
-                q.tasks().push(t);
-                break;
-            }
+            chaseCname(q, task, data[0]);
             continue;
 
         case REFERRAL_FOUND:
             // The qname node contains an out-of-zone referral.
-            m.clearHeaderFlag(MessageFlag::AA());
             if (task.state == QueryTask::GETANSWER) {
                 RRsetList auth;
-                QueryTask t(task.qname, task.qclass, RRType::NS(), 
-                            Section::AUTHORITY(),
-                            QueryTask::SIMPLE_QUERY); 
+                m.clearHeaderFlag(MessageFlag::AA());
+                QueryTask t(task.qname, task.qclass, RRType::NS(),
+                            QueryTask::SIMPLE_QUERY);
                 result = doQueryTask(ds, q, t, auth);
                 if (result != SUCCESS) {
                     m.setRcode(Rcode::SERVFAIL());
@@ -259,10 +307,9 @@
                     Name star("*");
 
                     for(int i = 1; i <= diff; i++) {
-                        Name wname(star.concatenate(task.qname.split(i,
-                                                    nlen - i)));
+                        const Name& wname(star.concatenate(task.qname.split(i,
+                                                           nlen - i)));
                         QueryTask t(wname, task.qclass, task.qtype,
-                                    Section::ANSWER(),
                                     QueryTask::SIMPLE_QUERY); 
                         r = doQueryTask(ds, q, t, wild);
                         if (r == SUCCESS || r == CNAME_FOUND) {
@@ -282,22 +329,10 @@
                         m.addRRset(Section::ANSWER(), wild[0]);
 
                         if (r == CNAME_FOUND) {
-                            it = wild[0]->getRdataIterator();
-                            for (it->first(); !it->isLast(); it->next()) {
-                                const rdata::Rdata& rd(it->getCurrent());
-                                const rdata::generic::CNAME& cname =
-                                 dynamic_cast<const rdata::generic::CNAME&>(rd);
-                                const Name& target(cname.getCname());
-                                QueryTask t(target, task.qclass, task.qtype,
-                                            Section::ANSWER(),
-                                            QueryTask::FOLLOWCNAME);
-                                q.tasks().push(t);
-                                break;
-                            }
+                            chaseCname(q, task, wild[0]);
                         } else {
                             RRsetList auth;
                             QueryTask t(Name(*zone), task.qclass, RRType::NS(), 
-                                        Section::AUTHORITY(),
                                         QueryTask::SIMPLE_QUERY); 
                             r = doQueryTask(ds, q, t, auth);
                             if (r != SUCCESS) {
@@ -324,7 +359,7 @@
 
                 RRsetList soa;
                 QueryTask t(Name(*zone), task.qclass, RRType::SOA(), 
-                            Section::AUTHORITY(), QueryTask::SIMPLE_QUERY); 
+                            QueryTask::SIMPLE_QUERY); 
                 result = doQueryTask(ds, q, t, soa);
                 if (result != SUCCESS) {
                     m.setRcode(Rcode::SERVFAIL());

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 Mon Feb 15 01:10:38 2010
@@ -171,9 +171,7 @@
             return (r);
         }
 
-        // XXX: The following code requires new rdata types to be
-        // implemented.
-
+        // XXX: The following code requires new rdata type implementation.
 #if 0
         r = findExactRRset(q, qname, qclass, RRType::DS(), target, sigs);
         if (r == SUCCESS) {
@@ -181,6 +179,7 @@
         } else if (r != TYPE_NOT_FOUND) {
             return (r);
         }
+#endif
 
         r = findExactRRset(q, qname, qclass, RRType::DNAME(), target, sigs);
         if (r == SUCCESS) {
@@ -188,7 +187,6 @@
         } else if (r != TYPE_NOT_FOUND) {
             return (r);
         }
-#endif
 
         if (ns || dname || ds) {
             return (SUCCESS);

Modified: branches/each-ds/src/lib/auth/cpp/query.h
==============================================================================
--- branches/each-ds/src/lib/auth/cpp/query.h (original)
+++ branches/each-ds/src/lib/auth/cpp/query.h Mon Feb 15 01:10:38 2010
@@ -122,6 +122,35 @@
         qname(n), qclass(c), qtype(t),
         section(sect), op(o), state(st) {}
 
+    // These are special constructors for particular query task types,
+    // to simplify the code.
+    //
+    // A simple query doesn't need to specify section or state.
+    QueryTask(const Name& n, const RRClass& c, const RRType& t, const Op o) :
+        qname(n), qclass(c), qtype(t), section(Section::ANSWER()),
+        op(o), state(GETANSWER) {
+        if (op != SIMPLE_QUERY) {
+            throw "invalid constructor for this task operation";
+        }
+    }
+    // A referral query doesn't need to specify section, state, or type.
+    QueryTask(const Name& n, const RRClass& c, const Op o) :
+        qname(n), qclass(c), qtype(RRType::ANY()), section(Section::ANSWER()),
+        op(o), state(GETANSWER) {
+        if (op != REF_QUERY) {
+            throw "invalid constructor for this task operation";
+        }
+    }
+    // An address query doesn't need to specify type.
+    QueryTask(const Name& n, const RRClass& c,
+              const Section& sect, const Op o, const State st) :
+        qname(n), qclass(c), qtype(RRType::ANY()),
+        section(sect), op(o), state(st) {
+        if (op != ADDR_QUERY) {
+            throw "invalid constructor for this task operation";
+        }
+    }
+
     virtual ~QueryTask() {}
 };
 
@@ -134,7 +163,6 @@
 class Query {
 public:
     // The state of a query: running, succeeded, or failed.
-    // (XXX: Not sure this is needed.)
     enum Status {
         RUNNING,
         SUCCESS,




More information about the bind10-changes mailing list