Commit db3d9fdf authored by Jeremy C. Reed's avatar Jeremy C. Reed
Browse files

[master]Merge branch 'master' of ssh://

parents 6bb65848 2858b209
......@@ -257,13 +257,27 @@ Query::addAuthAdditional(ZoneFinder& finder) {
namespace {
// A simple wrapper for DataSourceClient::findZone(). Normally we can simply
// check the closest zone to the qname, but for type DS query we need to
// look into the parent zone. Nevertheless, if there is no "parent" (i.e.,
// the qname consists of a single label, which also means it's the root name),
// we should search the deepest zone we have (which should be the root zone;
// otherwise it's a query error).
findZone(const DataSourceClient& client, const Name& qname, RRType qtype) {
if (qtype != RRType::DS() || qname.getLabelCount() == 1) {
return (client.findZone(qname));
return (client.findZone(qname.split(1)));
Query::process() {
const bool qtype_is_any = (qtype_ == RRType::ANY());
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
const DataSourceClient::FindResult result =
// Found a zone which is the nearest ancestor to QNAME
const DataSourceClient::FindResult result = findZone(datasrc_client_,
qname_, qtype_);
// If we have no matching authoritative zone for the query name, return
// REFUSED. In short, this is to be compatible with BIND 9, but the
......@@ -272,16 +286,26 @@ Query::process() {
if (result.code != result::SUCCESS &&
result.code != result::PARTIALMATCH) {
// If we tried to find a "parent zone" for a DS query and failed,
// we may still have authority at the child side. If we do, the query
// has to be handled there.
if (qtype_ == RRType::DS() && qname_.getLabelCount() > 1 &&
processDSAtChild()) {
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
ZoneFinder& zfinder = *result.zone_finder;
// Found a zone which is the nearest ancestor to QNAME, set the AA bit
// We have authority for a zone that contain the query name (possibly
// indirectly via delegation). Look into the zone.
std::vector<ConstRRsetPtr> target;
boost::function0<ZoneFinder::FindResult> find;
const bool qtype_is_any = (qtype_ == RRType::ANY());
if (qtype_is_any) {
find = boost::bind(&ZoneFinder::findAll, &zfinder, qname_,
boost::ref(target), dnssec_opt_);
......@@ -389,6 +413,14 @@ Query::process() {
case ZoneFinder::DELEGATION:
// If a DS query resulted in delegation, we also need to check
// if we are an authority of the child, too. If so, we need to
// complete the process in the child as specified in Section
// of RFC3658.
if (qtype_ == RRType::DS() && processDSAtChild()) {
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
......@@ -422,5 +454,37 @@ Query::process() {
Query::processDSAtChild() {
const DataSourceClient::FindResult zresult =
if (zresult.code != result::SUCCESS) {
return (false);
// We are receiving a DS query at the child side of the owner name,
// where the DS isn't supposed to belong. We should return a "no data"
// response as described in Section of RFC4035 and Section
// of RFC 3658. find(DS) should result in NXRRSET, in which
// case (and if DNSSEC is required) we also add the proof for that,
// but even if find() returns an unexpected result, we don't bother.
// The important point in this case is to return SOA so that the resolver
// that happens to contact us can hunt for the appropriate parent zone
// by seeing the SOA.
const ZoneFinder::FindResult ds_result =
zresult.zone_finder->find(qname_, RRType::DS(), dnssec_opt_);
if (ds_result.code == ZoneFinder::NXRRSET) {
if (dnssec_) {
addNXRRsetProof(*zresult.zone_finder, ds_result);
return (true);
......@@ -178,6 +178,23 @@ private:
/// data for the query are to be found.
void addAuthAdditional(isc::datasrc::ZoneFinder& finder);
/// \brief Process a DS query possible at the child side of zone cut.
/// This private method is a subroutine of process(), and is called if
/// there's a possibility that this server has authority for the child
/// side of the DS's owner name (and it's detected that the server at
/// least doesn't have authority at the parent side). This method
/// first checks if it has authority for the child, and if does,
/// just build a "no data" response with SOA for the zone origin
/// (possibly with a proof for the no data) as specified in Section
/// of RFC3658.
/// It returns true if this server has authority of the child; otherwise
/// it returns false. In the former case, the caller is expected to
/// terminate the query processing, because it should have been completed
/// within this method.
bool processDSAtChild();
/// Constructor from query parameters.
This diff is collapsed.
......@@ -762,11 +762,13 @@ TEST_F(InMemoryZoneFinderTest, delegationWithDS) {
EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ds_));
// Normal types of query should result in delegation, but DS query
// should be considered in-zone.
// should be considered in-zone (but only exactly at the delegation point).
findTest(Name(""), RRType::A(), ZoneFinder::DELEGATION,
true, rr_child_ns_);
findTest(Name(""), RRType::DS(), ZoneFinder::SUCCESS,
true, rr_child_ds_);
findTest(Name(""), RRType::DS(),
ZoneFinder::DELEGATION, true, rr_child_ns_);
// There's nothing special for DS query at the zone apex. It would
// normally result in NXRRSET.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment