[svn] commit: r811 - in /branches/each-ds/src/lib: auth/cpp/data_source.cc auth/cpp/query.h dns/cpp/message.h
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat Feb 13 16:41:11 UTC 2010
Author: each
Date: Sat Feb 13 16:41:11 2010
New Revision: 811
Log:
checkpoint:
- much query API cleanup
- query state is now part of the QueryTask rather than the Query itself
(this will help support multiple-RRset answers)
- added some comments
Modified:
branches/each-ds/src/lib/auth/cpp/data_source.cc
branches/each-ds/src/lib/auth/cpp/query.h
branches/each-ds/src/lib/dns/cpp/message.h
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 Sat Feb 13 16:41:11 2010
@@ -24,36 +24,37 @@
const rdata::generic::NS& ns =
dynamic_cast<const rdata::generic::NS&>(rd);
const Name& nsname(ns.getNSName());
- bool add = false;
// Don't bother with A/AAAA record in the additional section
// if they match the qname/qtype that we've already answered.
if (nsname != q.qname() || q.qtype() != RRType::A()) {
- q.tasks().push(QueryTask(nsname, q.qclass(), RRType::A(),
- Section::ADDITIONAL()));
- add = true;
+ QueryTask t(nsname, q.qclass(), RRType::A(),
+ Section::ADDITIONAL());
+ t.state = QueryTask::GETADDITIONAL;
+ q.tasks().push(t);
}
if (nsname != q.qname() || q.qtype() != RRType::AAAA()) {
- q.tasks().push(QueryTask(nsname, q.qclass(), RRType::AAAA(),
- Section::ADDITIONAL()));
- add = true;
- }
- if (add) {
- q.setStatus(QUERY_GETADDITIONAL);
+ QueryTask t(nsname, q.qclass(), RRType::AAAA(),
+ Section::ADDITIONAL());
+ t.state = QueryTask::GETADDITIONAL;
+ q.tasks().push(t);
}
} else if (rrset->getType() == RRType::MX()) {
const rdata::generic::MX& mx =
dynamic_cast<const rdata::generic::MX&>(rd);
- const Name& mxname(mx.getMXName());
- q.tasks().push(QueryTask(mxname, q.qclass(), RRType::A(),
- Section::ADDITIONAL()));
- q.tasks().push(QueryTask(mxname, q.qclass(), RRType::AAAA(),
- Section::ADDITIONAL()));
- q.setStatus(QUERY_GETADDITIONAL);
+ QueryTask t(mx.getMXName(), q.qclass(), RRType::A(),
+ Section::ADDITIONAL(), QueryTask::ADDR_QUERY);
+ t.state = QueryTask::GETADDITIONAL;
+ q.tasks().push(t);
}
}
}
+//
+// doQuery: Processes a query.
+// On success, the query status is set to Query::SUCCESS and
+// on failure, Query::FAILURE.
+//
void
DataSrc::doQuery(Query q) {
Result result;
@@ -68,6 +69,7 @@
NameMatch match(task.qname);
findClosestEnclosure(match);
const DataSrc* ds = match.bestDataSrc();
+ const Name* zone = match.closestName();
if (ds == NULL) {
result = ZONE_NOT_FOUND;
@@ -75,7 +77,7 @@
result = ds->findRRset(q, task.qname, task.qclass, task.qtype,
data, sigs);
- // Check answer validity:
+ // 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.
@@ -85,110 +87,110 @@
}
switch (result) {
- case SUCCESS:
- m.addRRset(task.section, data[0]);
+ case SUCCESS:
+ m.addRRset(task.section, data[0]);
+ if (q.wantDnssec() && sigs.size() == 1) {
+ m.addRRset(task.section, sigs[0]);
+ }
+
+ switch (task.state) {
+ case QueryTask::GETANSWER:
+ case QueryTask::FOLLOWCNAME:
+ getAdditional(q, data[0]);
+ if (q.tasks().empty()) {
+ // No additional processing is needed, so now
+ // add the authority section.
+ if (data[0]->getType() != RRType::NS()) {
+ QueryTask t(Name(*zone), task.qclass,
+ RRType::NS(),
+ Section::AUTHORITY());
+ t.state = QueryTask::GETAUTHORITY;
+ q.tasks().push(t);
+ }
+ }
+ continue;
+
+ case QueryTask::GETADDITIONAL:
+ // If no more work items, add authority section now
+ if (q.tasks().empty()) {
+ q.setStatus(Query::Query::SUCCESS);
+ return;
+ }
+ continue;
+
+ case QueryTask::GETAUTHORITY:
+ getAdditional(q, data[0]);
+ if (q.tasks().empty()) {
+ q.setStatus(Query::SUCCESS);
+ return;
+ }
+ continue;
+
+ default:
+ dns_throw (Unexpected, "unexpected query state");
+ }
+
+ case CNAME_FOUND:
+ if (data.size() != 1 || data[0]->getType() != RRType::CNAME()) {
+ dns_throw (Unexpected, "invalid data");
+ }
+
+ 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()) {
+ 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());
+ t.state = QueryTask::FOLLOWCNAME;
+ q.tasks().push(t);
+ break;
+ }
+ continue;
+
+ case NAME_NOT_FOUND:
+ case TYPE_NOT_FOUND:
+ if (task.state == QueryTask::GETANSWER) {
+ if (result == NAME_NOT_FOUND) {
+ m.setRcode(Rcode::NXDOMAIN());
+ }
+
+ result = ds->findRRset(q, Name(*zone), task.qclass,
+ RRType::SOA(), data, sigs);
+ if (result != SUCCESS) {
+ m.setRcode(Rcode::SERVFAIL());
+ return;
+ }
+
+ m.addRRset(Section::AUTHORITY(), data[0]);
if (q.wantDnssec() && sigs.size() == 1) {
- m.addRRset(task.section, sigs[0]);
- }
-
- switch (q.status()) {
- case QUERY_GETANSWER:
- case QUERY_FOLLOWCNAME:
- getAdditional(q, data[0]);
- if (q.tasks().empty()) {
- // No additional processing is needed, so now
- // add the authority section.
- if (data[0]->getType() != RRType::NS()) {
- QueryTask qt(Name(*match.closestName()),
- task.qclass, RRType::NS(),
- Section::AUTHORITY());
- q.tasks().push(qt);
- }
- q.setStatus(QUERY_GETAUTHORITY);
- }
- continue;
-
- case QUERY_GETADDITIONAL:
- // If no more work items, add authority section now
- if (q.tasks().empty()) {
- q.setStatus(QUERY_SUCCESS);
- return;
- }
- continue;
-
- case QUERY_GETAUTHORITY:
- getAdditional(q, data[0]);
- if (q.tasks().empty()) {
- q.setStatus(QUERY_SUCCESS);
- return;
- }
- continue;
-
- default:
- dns_throw (Unexpected, "unexpected query status");
- }
-
- case CNAME_FOUND:
- if (data[0]->getType() != RRType::CNAME()) {
- dns_throw (Unexpected, "unexpected query status");
- }
-
- 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()) {
- const rdata::Rdata& rd(it->getCurrent());
- const rdata::generic::CNAME& cname =
- dynamic_cast<const rdata::generic::CNAME&>(rd);
- const Name& target(cname.getCname());
- q.tasks().push(QueryTask(target, task.qclass, task.qtype,
- Section::ANSWER()));
- q.setStatus(QUERY_FOLLOWCNAME);
- break;
- }
- continue;
-
- case NAME_NOT_FOUND:
- case TYPE_NOT_FOUND:
- if (q.status() == QUERY_GETANSWER) {
- if (result == NAME_NOT_FOUND) {
- m.setRcode(Rcode::NXDOMAIN());
- }
-
- result = ds->findRRset(q, Name(*match.closestName()),
- task.qclass, RRType::SOA(),
- data, sigs);
- 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]);
- }
-
- q.setStatus(QUERY_FAIL);
- return;
- }
- continue;
-
- case ZONE_NOT_FOUND:
- if (q.status() == QUERY_GETANSWER) {
- m.setRcode(Rcode::REFUSED());
- q.setStatus(QUERY_FAIL);
- return;
- }
- continue;
-
- case NOT_IMPLEMENTED:
- case ERROR:
- m.setRcode(Rcode::SERVFAIL());
- q.setStatus(QUERY_FAIL);
+ m.addRRset(Section::AUTHORITY(), sigs[0]);
+ }
+
+ q.setStatus(Query::FAILURE);
return;
+ }
+ continue;
+
+ case ZONE_NOT_FOUND:
+ if (task.state == QueryTask::GETANSWER) {
+ m.setRcode(Rcode::REFUSED());
+ q.setStatus(Query::FAILURE);
+ return;
+ }
+ continue;
+
+ case NOT_IMPLEMENTED:
+ case ERROR:
+ m.setRcode(Rcode::SERVFAIL());
+ q.setStatus(Query::FAILURE);
+ return;
}
}
};
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 Sat Feb 13 16:41:11 2010
@@ -31,15 +31,6 @@
namespace isc {
namespace auth {
-enum QueryStatus {
- QUERY_GETANSWER,
- QUERY_GETADDITIONAL,
- QUERY_GETAUTHORITY,
- QUERY_FOLLOWCNAME,
- QUERY_SUCCESS,
- QUERY_FAIL
-};
-
///
/// \brief exception to throw if a DNS Message is malformed
///
@@ -52,15 +43,75 @@
// An individual task to be carried out by the query logic
class QueryTask {
public:
- QueryTask(const Name& n, const RRClass& c,
- const RRType& t, const Section& s) :
- qname(n), qclass(c), qtype(t), section(s) {}
- virtual ~QueryTask() {}
+ // XXX: Members are currently public, but should probably be
+ // moved to private and wrapped in get() functions later.
+ // The standard query tuple: qname/qclass/qtype.
+ // Note that qtype is ignored in the ADDR_QUERY case.
const Name qname;
const RRClass& qclass;
const RRType& qtype;
+
+ // The section of the reply into which the data should be
+ // written after it has been fetched from the data source.
const Section& section;
+
+ // This indicates the operation to be carried out:
+ // - STD_QUERY: look for an authoritative match for
+ // qname/qclass/qtype, or for qname/qclass/CNAME,
+ // or for a zone cut/referral.
+ // - SIMPLE_QUERY: look for a match for qname/qclass/qtype
+ // in local data, regardless of authority
+ // - ADDR_QUERY: look for matches with qname/qclass/A
+ // OR qname/class/AAAA in local data, regardless of
+ // authority (this can be implemented with two successive
+ // SIMPLE_QUERY lookups or as a single lookup, depending
+ // on the Data Source implementation.
+
+ const enum Op {
+ STD_QUERY,
+ SIMPLE_QUERY,
+ ADDR_QUERY
+ } op;
+
+ // This indicates the state of the query as of the time when
+ // this answer should be processed.
+ // - GETANSWER: We are looking for the answer to a query.
+ // - FOLLOWCNAME: We are looking for the target of a CNAME RR that
+ // was found via a GETANSWER query task.
+ // - GETAUTHORITY: We are looking for the authority information.
+ // If a complete answer was previously found, this might be a
+ // query for NS records. If no complete answer has been found,
+ // this might be a query for an SOA, NSEC or NSEC3 records.
+ // - GETADDITIONAL: We are filling in additional data, either
+ // as a result of finding NS or MX records via a GETANSWER
+ // query task, or as a result of finding NS records via a
+ // GETAUTHORITY query task.
+ enum State {
+ GETANSWER,
+ GETADDITIONAL,
+ GETAUTHORITY,
+ FOLLOWCNAME
+ } state;
+
+ QueryTask(const Name& n, const RRClass& c,
+ const RRType& t, const Section& sect) :
+ qname(n), qclass(c), qtype(t),
+ section(sect), op(SIMPLE_QUERY), state(GETANSWER) {}
+ QueryTask(const Name& n, const RRClass& c,
+ const RRType& t, const Section& sect, const Op o) :
+ qname(n), qclass(c), qtype(t),
+ section(sect), op(o), state(GETANSWER) {}
+ QueryTask(const Name& n, const RRClass& c,
+ const RRType& t, const Section& sect, const State st) :
+ qname(n), qclass(c), qtype(t),
+ section(sect), op(SIMPLE_QUERY), state(st) {}
+ QueryTask(const Name& n, const RRClass& c,
+ const RRType& t, const Section& sect,
+ const Op o, const State st) :
+ qname(n), qclass(c), qtype(t),
+ section(sect), op(o), state(st) {}
+ virtual ~QueryTask() {}
};
typedef std::queue<QueryTask> QueryTaskQueue;
@@ -71,11 +122,17 @@
// Data Source query
class Query {
public:
+ enum Status {
+ RUNNING,
+ SUCCESS,
+ FAILURE
+ };
+
Query(Message& m, bool dnssec) {
message_ = &m;
want_additional = true;
want_dnssec = dnssec;
- status_ = QUERY_GETANSWER;
+ status_ = RUNNING;
// Check message formatting
QuestionIterator qid = message_->beginQuestion();
@@ -83,7 +140,7 @@
if (qid != message_->endQuestion())
dns_throw(MalformedMessage, "too many questions");
- // Populate the query tasks queue with the initial question
+ // Populate the query task queue with the initial question
QuestionPtr query = *message_->beginQuestion();
qname_ = &query->getName();
qclass_ = &query->getClass();
@@ -112,13 +169,12 @@
Message& message() { return *message_; }
QueryTaskQueue& tasks() { return querytasks; }
- QueryStatus status() { return status_; }
- void setStatus(QueryStatus s) { status_ = s; }
-
-protected:
- QueryStatus status_;
+ Status status() { return status_; }
+ void setStatus(Status s) { status_ = s; }
private:
+ Status status_;
+
const Name* qname_;
const RRClass* qclass_;
const RRType* qtype_;
Modified: branches/each-ds/src/lib/dns/cpp/message.h
==============================================================================
--- branches/each-ds/src/lib/dns/cpp/message.h (original)
+++ branches/each-ds/src/lib/dns/cpp/message.h Sat Feb 13 16:41:11 2010
@@ -528,6 +528,11 @@
static const rcode_t RCODE_NXDOMAIN = 3;
static const rcode_t RCODE_NOTIMP = 4;
static const rcode_t RCODE_REFUSED = 5;
+ static const rcode_t RCODE_YXDOMAIN = 6;
+ static const rcode_t RCODE_YXRRSET = 7;
+ static const rcode_t RCODE_NXRRSET = 8;
+ static const rcode_t RCODE_NOTAUTH = 9;
+ static const rcode_t RCODE_NOTZONE = 10;
// ...more to follow
static const opcode_t OPCODE_QUERY = 0;
More information about the bind10-changes
mailing list