[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