From: JINMEI Tatuya Date: Sat, 21 Jan 2012 01:18:52 +0000 (-0800) Subject: [1431] introduced FindResultFlags so that we can separate find result codes X-Git-Tag: trac2351_base~275^2~10^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2528257c4f3621822cdc030d0201453506c5a56b;p=thirdparty%2Fkea.git [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. --- diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc index 2bf8f5e8fb..023e35f1b8 100644 --- a/src/bin/auth/query.cc +++ b/src/bin/auth/query.cc @@ -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(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(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(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( - 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( + db_result.rrset), + dnssec_); + if (db_result.isWildcard()) { + addWildcardNXRRSETProof(zfinder, db_result.rrset); + } + } } break; default: diff --git a/src/lib/datasrc/zone.h b/src/lib/datasrc/zone.h index 9e51ce9889..dabac1b34b 100644 --- a/src/lib/datasrc/zone.h +++ b/src/lib/datasrc/zone.h @@ -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(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( + static_cast(a) | static_cast(b))); +} + /// \brief A pointer-like type pointing to a \c ZoneFinder object. typedef boost::shared_ptr ZoneFinderPtr;