Commit 2528257c authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1431] introduced FindResultFlags so that we can separate find result codes

themselves and special attributes.  for now, provided a quick-hack wrapper
for auth::Query so we don't have to all data source implementations at once.
parent 3dabb15d
......@@ -30,6 +30,30 @@ using namespace isc::dns;
using namespace isc::datasrc;
using namespace isc::dns::rdata;
namespace {
// This is a temporary wrapper to convert old format of FindResult to new
// one, until we update all supported data source implementations.
ZoneFinder::FindResult
findWrapper(const ZoneFinder::FindResult& orig_result) {
ZoneFinder::FindResultFlags flags = ZoneFinder::RESULT_DEFAULT;
ZoneFinder::Result code = orig_result.code;
if (code == ZoneFinder::WILDCARD) {
code = ZoneFinder::SUCCESS;
flags = flags | ZoneFinder::RESULT_WILDCARD;
} else if (code == ZoneFinder::WILDCARD_CNAME) {
code = ZoneFinder::CNAME;
flags = flags | ZoneFinder::RESULT_WILDCARD;
} else if (code == ZoneFinder::WILDCARD_NXRRSET) {
code = ZoneFinder::NXRRSET;
flags = flags | ZoneFinder::RESULT_WILDCARD;
}
if (orig_result.rrset && orig_result.rrset->getType() == RRType::NSEC()) {
flags = flags | ZoneFinder::RESULT_NSEC_SIGNED;
}
return (ZoneFinder::FindResult(code, orig_result.rrset, flags));
}
}
namespace isc {
namespace auth {
......@@ -69,8 +93,8 @@ Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
// Find A rrset
if (qname_ != qname || qtype_ != RRType::A()) {
ZoneFinder::FindResult a_result = zone.find(qname, RRType::A(),
options | dnssec_opt_);
ZoneFinder::FindResult a_result =
findWrapper(zone.find(qname, RRType::A(), options | dnssec_opt_));
if (a_result.code == ZoneFinder::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(a_result.rrset), dnssec_);
......@@ -80,7 +104,8 @@ Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
// Find AAAA rrset
if (qname_ != qname || qtype_ != RRType::AAAA()) {
ZoneFinder::FindResult aaaa_result =
zone.find(qname, RRType::AAAA(), options | dnssec_opt_);
findWrapper(zone.find(qname, RRType::AAAA(),
options | dnssec_opt_));
if (aaaa_result.code == ZoneFinder::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(aaaa_result.rrset),
......@@ -91,8 +116,9 @@ Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
void
Query::addSOA(ZoneFinder& finder) {
ZoneFinder::FindResult soa_result(finder.find(finder.getOrigin(),
RRType::SOA(), dnssec_opt_));
ZoneFinder::FindResult soa_result =
findWrapper(finder.find(finder.getOrigin(),
RRType::SOA(), dnssec_opt_));
if (soa_result.code != ZoneFinder::SUCCESS) {
isc_throw(NoSOA, "There's no SOA record in zone " <<
finder.getOrigin().toText());
......@@ -147,9 +173,8 @@ Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
// Confirm the wildcard doesn't exist (this should result in NXDOMAIN;
// otherwise we shouldn't have got NXDOMAIN for the original query in
// the first place).
const ZoneFinder::FindResult fresult = finder.find(wildname,
RRType::NSEC(),
dnssec_opt_);
const ZoneFinder::FindResult fresult =
findWrapper(finder.find(wildname, RRType::NSEC(), dnssec_opt_));
if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
fresult.rrset->getRdataCount() == 0) {
isc_throw(BadNSEC, "Unexpected result for wildcard NXDOMAIN proof");
......@@ -173,8 +198,8 @@ Query::addWildcardProof(ZoneFinder& finder) {
// substitution. Confirm that by specifying NO_WILDCARD. It should result
// in NXDOMAIN and an NSEC RR that proves it should be returned.
const ZoneFinder::FindResult fresult =
finder.find(qname_, RRType::NSEC(),
dnssec_opt_ | ZoneFinder::NO_WILDCARD);
findWrapper(finder.find(qname_, RRType::NSEC(),
dnssec_opt_ | ZoneFinder::NO_WILDCARD));
if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
fresult.rrset->getRdataCount() == 0) {
isc_throw(BadNSEC, "Unexpected result for wildcard proof");
......@@ -191,13 +216,10 @@ Query::addWildcardNXRRSETProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
if (nsec->getRdataCount() == 0) {
isc_throw(BadNSEC, "NSEC for WILDCARD_NXRRSET is empty");
}
// Add this NSEC RR to authority section.
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(nsec), dnssec_);
const ZoneFinder::FindResult fresult =
finder.find(qname_, RRType::NSEC(),
dnssec_opt_ | ZoneFinder::NO_WILDCARD);
findWrapper(finder.find(qname_, RRType::NSEC(),
dnssec_opt_ | ZoneFinder::NO_WILDCARD));
if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
fresult.rrset->getRdataCount() == 0) {
isc_throw(BadNSEC, "Unexpected result for no match QNAME proof");
......@@ -214,8 +236,9 @@ Query::addWildcardNXRRSETProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
void
Query::addAuthAdditional(ZoneFinder& finder) {
// Fill in authority and addtional sections.
ZoneFinder::FindResult ns_result = finder.find(finder.getOrigin(),
RRType::NS(), dnssec_opt_);
ZoneFinder::FindResult ns_result =
findWrapper(finder.find(finder.getOrigin(), RRType::NS(),
dnssec_opt_));
// zone origin name should have NS records
if (ns_result.code != ZoneFinder::SUCCESS) {
isc_throw(NoApexNS, "There's no apex NS records in zone " <<
......@@ -260,7 +283,7 @@ Query::process() {
find = boost::bind(&ZoneFinder::find, &zfinder, qname_, qtype_,
dnssec_opt_);
}
ZoneFinder::FindResult db_result(find());
ZoneFinder::FindResult db_result(findWrapper(find()));
switch (db_result.code) {
case ZoneFinder::DNAME: {
// First, put the dname into the answer
......@@ -306,7 +329,6 @@ Query::process() {
break;
}
case ZoneFinder::CNAME:
case ZoneFinder::WILDCARD_CNAME:
/*
* We don't do chaining yet. Therefore handling a CNAME is
* mostly the same as handling SUCCESS, but we didn't get
......@@ -322,12 +344,11 @@ Query::process() {
// If the answer is a result of wildcard substitution,
// add a proof that there's no closer name.
if (dnssec_ && db_result.code == ZoneFinder::WILDCARD_CNAME) {
if (dnssec_ && db_result.isWildcard()) {
addWildcardProof(*result.zone_finder);
}
break;
case ZoneFinder::SUCCESS:
case ZoneFinder::WILDCARD:
if (qtype_is_any) {
// If quety type is ANY, insert all RRs under the domain
// into answer section.
......@@ -357,7 +378,7 @@ Query::process() {
// If the answer is a result of wildcard substitution,
// add a proof that there's no closer name.
if (dnssec_ && db_result.code == ZoneFinder::WILDCARD) {
if (dnssec_ && db_result.isWildcard()) {
addWildcardProof(*result.zone_finder);
}
break;
......@@ -377,17 +398,16 @@ Query::process() {
break;
case ZoneFinder::NXRRSET:
addSOA(*result.zone_finder);
if (dnssec_ && db_result.rrset) {
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(
db_result.rrset),
dnssec_);
}
break;
case ZoneFinder::WILDCARD_NXRRSET:
addSOA(*result.zone_finder);
if (dnssec_ && db_result.rrset) {
addWildcardNXRRSETProof(zfinder, db_result.rrset);
if (dnssec_) {
if (db_result.isNSECSigned()) {
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(
db_result.rrset),
dnssec_);
if (db_result.isWildcard()) {
addWildcardNXRRSETProof(zfinder, db_result.rrset);
}
}
}
break;
default:
......
......@@ -142,19 +142,41 @@ public:
WILDCARD_NXRRSET ///< NXRRSET on wildcard, for DNSSEC
};
/// Special attribute flags on the result of the \c find() method
///
/// The flag values defined here are intended to signal to the caller
/// that it may need special handling on the result. This is particularly
/// of concern when DNSSEC is requested. For example, for negative
/// responses the caller would want to know whether the zone is signed
/// with NSEC or NSEC3 so that it can subsequently provide necessary
/// proof of the result.
///
/// The caller is generally expected to get access to the information
/// via read-only getter methods of \c FindResult so that it won't rely
/// on specific details of the representation of the flags. So these
/// definitions are basically only meaningful for data source
/// implementations.
enum FindResultFlags {
RESULT_DEFAULT = 0, ///< The default flags
RESULT_WILDCARD = 1, ///< find() resulted in a wildcard match
RESULT_NSEC_SIGNED = 2, ///< The zone is signed with NSEC RRs
RESULT_NSEC3_SIGNED = 4 ///< The zone is signed with NSEC3 RRs
};
/// A helper structure to represent the search result of \c find().
///
/// This is a straightforward tuple of the result code and a pointer
/// to the found RRset to represent the result of \c find()
/// (there will be more members in the future - see the class
/// description).
/// (and optionally special flags) to the found RRset to represent the
/// result of \c find() (there will be more members in the future -
/// see the class description).
/// We use this in order to avoid overloading the return value for both
/// the result code ("success" or "not found") and the found object,
/// i.e., avoid using \c NULL to mean "not found", etc.
///
/// This is a simple value class whose internal state never changes,
/// so for convenience we allow the applications to refer to the members
/// directly.
/// so for convenience we allow the applications to refer to some of the
/// members directly. For others we provide read-only accessor methods
/// to hide specific representation.
///
/// Note: we should eventually include a notion of "zone node", which
/// corresponds to a particular domain name of the zone, so that we can
......@@ -165,11 +187,39 @@ public:
/// optimize including the NSEC for no-wildcard proof (FWIW NSD does that).
struct FindResult {
FindResult(Result param_code,
const isc::dns::ConstRRsetPtr param_rrset) :
code(param_code), rrset(param_rrset)
const isc::dns::ConstRRsetPtr param_rrset,
FindResultFlags param_flags = RESULT_DEFAULT) :
code(param_code), rrset(param_rrset), flags(param_flags)
{}
const Result code;
const isc::dns::ConstRRsetPtr rrset;
/// Return true iff find() results in a wildcard match.
bool isWildcard() const { return ((flags & RESULT_WILDCARD) != 0); }
/// Return true when the underlying zone is signed with NSEC.
///
/// The \c find() implementation allow this to return false if
/// \c FIND_DNSSEC isn't specified regardless of whether the zone
/// is signed or which of NSEC/NSEC3 is used.
///
/// When this is returned, the implementation of find() must ensure
/// that \c rrset be a valid NSEC RRset as described in \c find()
/// documentation.
bool isNSECSigned() const {
return ((flags & RESULT_NSEC_SIGNED) != 0);
}
/// Return true when the underlying zone is signed with NSEC3.
///
/// The \c find() implementation allow this to return false if
/// \c FIND_DNSSEC isn't specified regardless of whether the zone
/// is signed or which of NSEC/NSEC3 is used.
bool isNSEC3Signed() const {
return ((flags & RESULT_NSEC3_SIGNED) != 0);
}
private:
FindResultFlags flags;
};
/// Find options.
......@@ -375,7 +425,7 @@ public:
///
/// When looking for NSEC3, this method retrieves NSEC3 parameters from
/// the corresponding zone to calculate hash values. Actual implementation
/// of how to do this will defer in different data sources. If the
/// of how to do this will differ in different data sources. If the
/// NSEC3 parameters are not available \c DataSourceError exception
/// will be thrown.
///
......@@ -451,6 +501,18 @@ inline ZoneFinder::FindOptions operator |(ZoneFinder::FindOptions a,
static_cast<unsigned>(b)));
}
/// \brief Operator to combine FindResultFlags
///
/// Similar to the same operator for \c FindOptions. Refer to the description
/// of that function.
inline ZoneFinder::FindResultFlags operator |(
ZoneFinder::FindResultFlags a,
ZoneFinder::FindResultFlags b)
{
return (static_cast<ZoneFinder::FindResultFlags>(
static_cast<unsigned>(a) | static_cast<unsigned>(b)));
}
/// \brief A pointer-like type pointing to a \c ZoneFinder object.
typedef boost::shared_ptr<ZoneFinder> ZoneFinderPtr;
......
Markdown is supported
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