mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[master] Merge branch 'trac2060'
This commit is contained in:
@@ -1287,7 +1287,7 @@ public:
|
||||
if (fake_rrset_ && fake_rrset_->getName() == name &&
|
||||
fake_rrset_->getType() == type)
|
||||
{
|
||||
return (ZoneFinderContextPtr(new ZoneFinder::Context(
|
||||
return (ZoneFinderContextPtr(new ZoneFinder::GenericContext(
|
||||
*this, options,
|
||||
ResultContext(SUCCESS,
|
||||
fake_rrset_))));
|
||||
|
@@ -442,10 +442,9 @@ public:
|
||||
ConstRRsetPtr rrset)
|
||||
{
|
||||
nsec_name_ = nsec_name;
|
||||
nsec_context_.reset(new Context(*this,
|
||||
FIND_DEFAULT, // a fake value
|
||||
ResultContext(code, rrset,
|
||||
RESULT_NSEC_SIGNED)));
|
||||
nsec_context_.reset(
|
||||
new GenericContext(*this, FIND_DEFAULT, // a fake value
|
||||
ResultContext(code, rrset, RESULT_NSEC_SIGNED)));
|
||||
}
|
||||
|
||||
// Once called, the findNSEC3 will return the provided result for the next
|
||||
@@ -487,8 +486,8 @@ protected:
|
||||
{
|
||||
ConstRRsetPtr rp = stripRRsigs(rrset, options);
|
||||
return (ZoneFinderContextPtr(
|
||||
new Context(*this, options,
|
||||
ResultContext(code, rp, flags))));
|
||||
new GenericContext(*this, options,
|
||||
ResultContext(code, rp, flags))));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -604,9 +603,9 @@ MockZoneFinder::findAll(const Name& name, std::vector<ConstRRsetPtr>& target,
|
||||
target.push_back(stripRRsigs(found_rrset->second, options));
|
||||
}
|
||||
return (ZoneFinderContextPtr(
|
||||
new Context(*this, options,
|
||||
ResultContext(SUCCESS, RRsetPtr()),
|
||||
target)));
|
||||
new GenericContext(*this, options,
|
||||
ResultContext(SUCCESS, RRsetPtr()),
|
||||
target)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -386,10 +386,11 @@ DatabaseClient::Finder::findAll(const isc::dns::Name& name,
|
||||
std::vector<isc::dns::ConstRRsetPtr>& target,
|
||||
const FindOptions options)
|
||||
{
|
||||
return (ZoneFinderContextPtr(new Context(*this, options,
|
||||
findInternal(name, RRType::ANY(),
|
||||
&target, options),
|
||||
target)));
|
||||
return (ZoneFinderContextPtr(new GenericContext(
|
||||
*this, options,
|
||||
findInternal(name, RRType::ANY(),
|
||||
&target, options),
|
||||
target)));
|
||||
}
|
||||
|
||||
ZoneFinderContextPtr
|
||||
@@ -400,9 +401,10 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
|
||||
if (type == RRType::ANY()) {
|
||||
isc_throw(isc::Unexpected, "Use findAll to answer ANY");
|
||||
}
|
||||
return (ZoneFinderContextPtr(new Context(*this, options,
|
||||
findInternal(name, type, NULL,
|
||||
options))));
|
||||
return (ZoneFinderContextPtr(new GenericContext(
|
||||
*this, options,
|
||||
findInternal(name, type, NULL,
|
||||
options))));
|
||||
}
|
||||
|
||||
DatabaseClient::Finder::DelegationSearchResult
|
||||
|
@@ -534,17 +534,26 @@ FindNodeResult findNode(const ZoneData& zone_data,
|
||||
/// context.
|
||||
class InMemoryZoneFinder::Context : public ZoneFinder::Context {
|
||||
public:
|
||||
Context(ZoneFinder& finder, ZoneFinder::FindOptions options,
|
||||
Context(InMemoryZoneFinder& finder, ZoneFinder::FindOptions options,
|
||||
const RRClass& rrclass, const ZoneFinderResultContext& result) :
|
||||
ZoneFinder::Context(finder, options,
|
||||
ResultContext(result.code, result.rrset,
|
||||
result.flags)),
|
||||
ZoneFinder::Context(options, ResultContext(result.code, result.rrset,
|
||||
result.flags)),
|
||||
finder_(finder), // NOTE: when #2284 is done we won't need this
|
||||
rrclass_(rrclass), zone_data_(result.zone_data),
|
||||
found_node_(result.found_node),
|
||||
found_rdset_(result.found_rdset)
|
||||
{}
|
||||
|
||||
protected:
|
||||
// When #2284 is done this can simply return NULL.
|
||||
virtual ZoneFinder* getFinder() { return (&finder_); }
|
||||
|
||||
// We don't use the default protected methods that rely on this method,
|
||||
// so we can simply return NULL.
|
||||
virtual const std::vector<isc::dns::ConstRRsetPtr>* getAllRRsets() const {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
virtual void getAdditionalImpl(const std::vector<RRType>& requested_types,
|
||||
std::vector<ConstRRsetPtr>& result)
|
||||
{
|
||||
@@ -626,6 +635,7 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
InMemoryZoneFinder& finder_;
|
||||
const RRClass rrclass_;
|
||||
const ZoneData* const zone_data_;
|
||||
const ZoneNode* const found_node_;
|
||||
|
@@ -792,13 +792,19 @@ public:
|
||||
/// context.
|
||||
Context(ZoneFinder& finder, ZoneFinder::FindOptions options,
|
||||
const RBNodeResultContext& result) :
|
||||
ZoneFinder::Context(finder, options,
|
||||
ZoneFinder::Context(options,
|
||||
ResultContext(result.code, result.rrset,
|
||||
result.flags)),
|
||||
rrset_(result.rrset), found_node_(result.found_node)
|
||||
finder_(finder), rrset_(result.rrset), found_node_(result.found_node)
|
||||
{}
|
||||
|
||||
protected:
|
||||
virtual ZoneFinder* getFinder() { return (&finder_); }
|
||||
|
||||
virtual const std::vector<isc::dns::ConstRRsetPtr>* getAllRRsets() const {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
virtual void getAdditionalImpl(const vector<RRType>& requested_types,
|
||||
vector<ConstRRsetPtr>& result)
|
||||
{
|
||||
@@ -866,6 +872,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ZoneFinder& finder_;
|
||||
const ConstRBNodeRRsetPtr rrset_;
|
||||
const DomainNode* const found_node_;
|
||||
};
|
||||
|
@@ -1,9 +1,10 @@
|
||||
;; test zone file used for ZoneFinderContext tests.
|
||||
;; RRSIGs are (obviouslly) faked ones for testing.
|
||||
|
||||
example.org. 3600 IN SOA ns1.example.org. bugs.x.w.example.org. 71 3600 300 3600000 3600
|
||||
example.org. 3600 IN SOA ns1.example.org. bugs.x.w.example.org. 74 3600 300 3600000 3600
|
||||
example.org. 3600 IN NS ns1.example.org.
|
||||
example.org. 3600 IN NS ns2.example.org.
|
||||
example.org. 3600 IN RRSIG NS 7 3 3600 20150420235959 20051021000000 40430 example.org. FAKEFAKEFAKE
|
||||
example.org. 3600 IN MX 1 mx1.example.org.
|
||||
example.org. 3600 IN MX 2 mx2.example.org.
|
||||
example.org. 3600 IN MX 3 mx.a.example.org.
|
||||
|
@@ -416,4 +416,37 @@ TEST_P(ZoneFinderContextTest, getAdditionalForAny) {
|
||||
result_sets_.begin(), result_sets_.end());
|
||||
}
|
||||
|
||||
TEST_P(ZoneFinderContextTest, getAtOrigin) {
|
||||
ConstRRsetPtr expected_ns_rrset =
|
||||
textToRRset("example.org. 3600 IN NS ns1.example.org.\n"
|
||||
"example.org. 3600 IN NS ns2.example.org.\n");
|
||||
|
||||
// Try getAtOrigin for an existing type (NS) record at the origin that
|
||||
// has RRSIG. The RRSIG will be associated iff the original query
|
||||
// has the FIND_DNSSEC option.
|
||||
ZoneFinderContextPtr ctx = finder_->find(Name("ns1.example.org"),
|
||||
RRType::A());
|
||||
EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
|
||||
ConstRRsetPtr ns_rrset = ctx->getAtOrigin(RRType::NS());
|
||||
ASSERT_TRUE(ns_rrset);
|
||||
rrsetCheck(expected_ns_rrset, ns_rrset);
|
||||
EXPECT_FALSE(ns_rrset->getRRsig());
|
||||
|
||||
ctx = finder_->find(Name("ns1.example.org"), RRType::A(),
|
||||
ZoneFinder::FIND_DNSSEC);
|
||||
ns_rrset = ctx->getAtOrigin(RRType::NS());
|
||||
ASSERT_TRUE(ns_rrset);
|
||||
rrsetCheck(expected_ns_rrset, ns_rrset);
|
||||
ASSERT_TRUE(ns_rrset->getRRsig());
|
||||
rrsetCheck(textToRRset("example.org. 3600 IN RRSIG NS 7 3 3600 "
|
||||
"20150420235959 20051021000000 40430 "
|
||||
"example.org. FAKEFAKEFAKE"), ns_rrset->getRRsig());
|
||||
|
||||
// For non-existing type we simply get NULL.
|
||||
EXPECT_FALSE(ctx->getAtOrigin(RRType::TXT()));
|
||||
|
||||
// Type ANY query isn't allowed.
|
||||
EXPECT_THROW(ctx->getAtOrigin(RRType::ANY()), isc::InvalidParameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -168,48 +168,25 @@ public:
|
||||
/// can define a derived class of the base Context and override the
|
||||
/// specific virtual method.
|
||||
///
|
||||
/// This base class defines these common protected methods along with
|
||||
/// some helper pure virtual methods that would be necessary for the
|
||||
/// common methods. If a derived class wants to use the common version
|
||||
/// of the protected method, it needs to provide expected result through
|
||||
/// their implementation of the pure virtual methods.
|
||||
///
|
||||
/// This class object is generally expected to be associated with the
|
||||
/// ZoneFinder that originally performed the \c find() call, and expects
|
||||
/// the finder is valid throughout the lifetime of this object. It's
|
||||
/// caller's responsibility to ensure that assumption.
|
||||
class Context {
|
||||
public:
|
||||
/// \brief The constructor for the normal find call.
|
||||
/// \brief The constructor.
|
||||
///
|
||||
/// This constructor is expected to be called from the \c find()
|
||||
/// method when it constructs the return value.
|
||||
///
|
||||
/// \param finder The ZoneFinder on which find() is called.
|
||||
/// \param options The find options specified for the find() call.
|
||||
/// \param result The result of the find() call.
|
||||
Context(ZoneFinder& finder, FindOptions options,
|
||||
const ResultContext& result) :
|
||||
Context(FindOptions options, const ResultContext& result) :
|
||||
code(result.code), rrset(result.rrset),
|
||||
finder_(finder), flags_(result.flags), options_(options)
|
||||
{}
|
||||
|
||||
/// \brief The constructor for the normal findAll call.
|
||||
///
|
||||
/// This constructor is expected to be called from the \c findAll()
|
||||
/// method when it constructs the return value.
|
||||
///
|
||||
/// It copies the vector that is to be returned to the caller of
|
||||
/// \c findAll() for possible subsequent use. Note that it cannot
|
||||
/// simply hold a reference to the vector because the caller may
|
||||
/// alter it after the \c findAll() call.
|
||||
///
|
||||
/// \param finder The ZoneFinder on which findAll() is called.
|
||||
/// \param options The find options specified for the findAll() call.
|
||||
/// \param result The result of the findAll() call (whose rrset is
|
||||
/// expected to be NULL).
|
||||
/// \param all_set Reference to the vector given by the caller of
|
||||
/// \c findAll(), storing the RRsets to be returned.
|
||||
Context(ZoneFinder& finder, FindOptions options,
|
||||
const ResultContext& result,
|
||||
const std::vector<isc::dns::ConstRRsetPtr> &all_set) :
|
||||
code(result.code), rrset(result.rrset),
|
||||
finder_(finder), flags_(result.flags), options_(options),
|
||||
all_set_(all_set)
|
||||
flags_(result.flags), options_(options)
|
||||
{}
|
||||
|
||||
/// \brief The destructor.
|
||||
@@ -291,22 +268,181 @@ public:
|
||||
getAdditionalImpl(requested_types, result);
|
||||
}
|
||||
|
||||
/// \brief Find and return given type of RRset at the zone origin.
|
||||
///
|
||||
/// DNS query processing often requires supplemental RRsets at the
|
||||
/// zone origin; for example, for some negative answers we need to
|
||||
/// provide the zone's SOA record; a full positive response normally
|
||||
/// includes the zone's NS RRset. The application can easily get
|
||||
/// these using the generic \c ZoneFinder::find() interface, but
|
||||
/// depending on the underlying data source implementation, the generic
|
||||
/// version could be more expensive and/or it might be possible to
|
||||
/// substantially improve this particular case.
|
||||
///
|
||||
/// This method allows the underlying implementation to do such
|
||||
/// optimization. The interface is simplified; it just takes
|
||||
/// an `RRType` and returns the corresponding RRset if found;
|
||||
/// if not found it returns NULL.
|
||||
///
|
||||
/// This method tries to find and return RRSIGs of the found RRset
|
||||
/// if and only if the original lookup by \c ZoneFinder::find() has
|
||||
/// the \c FIND_DNSSEC option.
|
||||
///
|
||||
/// Type ANY must not be specified for this method. It will result
|
||||
/// in \c isc::InvalidParameter exception. If the application
|
||||
/// needs to get all types of RRsets at the origin, it should use
|
||||
/// the \c ZoneFinder::findAll() method with the zone name.
|
||||
///
|
||||
/// Note that the origin name should always exist, so there
|
||||
/// shouldn't be the case where the name itself is not found
|
||||
/// in the zone (i.e., the NXDOMAIN) case. But in any event
|
||||
/// it does not distinguish such a hypothetical case from the
|
||||
/// case where the specified type isn't found at the origin.
|
||||
/// It simply returns NULL when the required type isn't found.
|
||||
/// This also means it doesn't provide a DNSSEC proof of the
|
||||
/// non-existence. If the application needs that proof, it must use
|
||||
/// the generic \c find() method.
|
||||
///
|
||||
/// A CNAME RR shouldn't exist at the zone origin at any sanely
|
||||
/// configured zone (because there should be at least SOA there and
|
||||
/// CNAME cannot coexist with it), and it's generally expected
|
||||
/// the underlying implementation rejects the case where a CNAME
|
||||
/// somehow exists at the zone origin. Even if such a situation
|
||||
/// happens, this method does not return the CNAME when the given
|
||||
/// type of RRset isn't found; it will just return NULL like in the
|
||||
/// normal case.
|
||||
///
|
||||
/// \throw isc::InvalidParameter Type ANY is specified
|
||||
/// \throw std::bad_alloc Internal resource allocation failure
|
||||
///
|
||||
/// \param type The RR type for which an RRset at the origin is to be
|
||||
/// found.
|
||||
/// \return A shared pointer to the requested type of RRset or NULL
|
||||
/// if not found.
|
||||
dns::ConstRRsetPtr getAtOrigin(const dns::RRType& type) {
|
||||
// Perform common check, then delegate the actual work to
|
||||
// derived class implementation, if provided.
|
||||
if (type == dns::RRType::ANY()) {
|
||||
isc_throw(isc::InvalidParameter,
|
||||
"Type ANY isn't allowed for getAtOrigin");
|
||||
}
|
||||
return (getAtOriginImpl(type));
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \brief Return the \c ZoneFinder that created this \c Context.
|
||||
///
|
||||
/// A derived class implementation can return NULL if it defines
|
||||
/// other protected methods that require a non NULL result from
|
||||
/// this method. Otherwise it must return a valid, non NULL pointer
|
||||
/// to the \c ZoneFinder object.
|
||||
///
|
||||
/// When returning non NULL, the ownership of the pointed object
|
||||
/// was not transferred to the caller; it cannot be assumed to be
|
||||
/// valid after the originating \c Context object is destroyed.
|
||||
/// Also, the caller must not try to delete the returned object.
|
||||
virtual ZoneFinder* getFinder() = 0;
|
||||
|
||||
/// \brief Return a vector of RRsets corresponding to findAll() result.
|
||||
///
|
||||
/// This method returns a set of RRsets that correspond to the
|
||||
/// returned RRsets to a prior \c findAll() call.
|
||||
///
|
||||
/// A derived class implementation can return NULL if it defines
|
||||
/// other protected methods that require a non NULL result from
|
||||
/// this method. Otherwise it must return a valid, non NULL pointer
|
||||
/// to a vector that correspond to the expected set of RRsets.
|
||||
///
|
||||
/// When returning non NULL, the ownership of the pointed object
|
||||
/// was not transferred to the caller; it cannot be assumed to be
|
||||
/// valid after the originating \c Context object is destroyed.
|
||||
/// Also, the caller must not try to delete the returned object.
|
||||
virtual const std::vector<isc::dns::ConstRRsetPtr>*
|
||||
getAllRRsets() const = 0;
|
||||
|
||||
/// \brief Actual implementation of getAdditional().
|
||||
///
|
||||
/// This base class defines a default implementation that can be
|
||||
/// used for any type of data sources. A data source implementation
|
||||
/// can override it.
|
||||
///
|
||||
/// The default version of this implementation requires both
|
||||
/// \c getFinder() and \c getAllRRsets() return valid results.
|
||||
virtual void getAdditionalImpl(
|
||||
const std::vector<isc::dns::RRType>& requested_types,
|
||||
std::vector<isc::dns::ConstRRsetPtr>& result);
|
||||
|
||||
/// \brief Actual implementation of getAtOrigin().
|
||||
///
|
||||
/// This base class defines a default implementation that can be
|
||||
/// used for any type of data sources. A data source implementation
|
||||
/// can override it.
|
||||
///
|
||||
/// The default version of this implementation requires
|
||||
/// \c getFinder() return a valid result.
|
||||
virtual dns::ConstRRsetPtr getAtOriginImpl(const dns::RRType& type);
|
||||
|
||||
private:
|
||||
ZoneFinder& finder_;
|
||||
|
||||
const FindResultFlags flags_;
|
||||
protected:
|
||||
const FindOptions options_;
|
||||
};
|
||||
|
||||
/// \brief Generic ZoneFinder context that works for all implementations.
|
||||
///
|
||||
/// This is a concrete derived class of \c ZoneFinder::Context that
|
||||
/// only use the generic (default) versions of the protected methods
|
||||
/// and therefore work for any data source implementation.
|
||||
///
|
||||
/// A data source implementation can use this class to create a
|
||||
/// \c Context object as a return value of \c find() or \c findAll()
|
||||
/// method if it doesn't have to optimize specific protected methods.
|
||||
class GenericContext : public Context {
|
||||
public:
|
||||
/// \brief The constructor for the normal find call.
|
||||
///
|
||||
/// This constructor is expected to be called from the \c find()
|
||||
/// method when it constructs the return value.
|
||||
///
|
||||
/// \param finder The ZoneFinder on which find() is called.
|
||||
/// \param options See the \c Context class.
|
||||
/// \param result See the \c Context class.
|
||||
GenericContext(ZoneFinder& finder, FindOptions options,
|
||||
const ResultContext& result) :
|
||||
Context(options, result), finder_(finder)
|
||||
{}
|
||||
|
||||
/// \brief The constructor for the normal findAll call.
|
||||
///
|
||||
/// This constructor is expected to be called from the \c findAll()
|
||||
/// method when it constructs the return value.
|
||||
///
|
||||
/// It copies the vector that is to be returned to the caller of
|
||||
/// \c findAll() for possible subsequent use. Note that it cannot
|
||||
/// simply hold a reference to the vector because the caller may
|
||||
/// alter it after the \c findAll() call.
|
||||
///
|
||||
/// \param finder The ZoneFinder on which findAll() is called.
|
||||
/// \param options See the \c Context class.
|
||||
/// \param result See the \c Context class.
|
||||
/// \param all_set Reference to the vector given by the caller of
|
||||
/// \c findAll(), storing the RRsets to be returned.
|
||||
GenericContext(ZoneFinder& finder, FindOptions options,
|
||||
const ResultContext& result,
|
||||
const std::vector<isc::dns::ConstRRsetPtr>& all_set) :
|
||||
Context(options, result), finder_(finder), all_set_(all_set)
|
||||
{}
|
||||
|
||||
protected:
|
||||
virtual ZoneFinder* getFinder() { return (&finder_); }
|
||||
virtual const std::vector<isc::dns::ConstRRsetPtr>*
|
||||
getAllRRsets() const {
|
||||
return (&all_set_);
|
||||
}
|
||||
|
||||
private:
|
||||
ZoneFinder& finder_;
|
||||
std::vector<isc::dns::ConstRRsetPtr> all_set_;
|
||||
};
|
||||
|
||||
|
@@ -12,6 +12,8 @@
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rrset.h>
|
||||
#include <dns/rrtype.h>
|
||||
@@ -87,16 +89,45 @@ ZoneFinder::Context::getAdditionalImpl(const vector<RRType>& requested_types,
|
||||
{
|
||||
// If rrset is non NULL, it should have been SUCCESS/DELEGATION; otherwise
|
||||
// we should have responded to type ANY query.
|
||||
ZoneFinder* finder = getFinder();
|
||||
if (finder == NULL) {
|
||||
// This is a bug of the derived class implementation.
|
||||
isc_throw(isc::Unexpected, "NULL ZoneFinder in finder Context");
|
||||
}
|
||||
if (rrset) {
|
||||
getAdditionalForRRset(finder_, *rrset, requested_types, result,
|
||||
getAdditionalForRRset(*finder, *rrset, requested_types, result,
|
||||
options_);
|
||||
return;
|
||||
}
|
||||
BOOST_FOREACH(ConstRRsetPtr rrset_in_set, all_set_) {
|
||||
getAdditionalForRRset(finder_, *rrset_in_set, requested_types, result,
|
||||
const vector<ConstRRsetPtr>* all_sets = getAllRRsets();
|
||||
if (all_sets == NULL) { // bug of the derived class implementation.
|
||||
isc_throw(isc::Unexpected, "All RRsets is NULL in finder Context");
|
||||
}
|
||||
BOOST_FOREACH(ConstRRsetPtr rrset_in_set, *getAllRRsets()) {
|
||||
getAdditionalForRRset(*finder, *rrset_in_set, requested_types, result,
|
||||
options_);
|
||||
}
|
||||
}
|
||||
|
||||
ConstRRsetPtr
|
||||
ZoneFinder::Context::getAtOriginImpl(const dns::RRType& type) {
|
||||
const ZoneFinder::FindOptions options =
|
||||
(options_ & ZoneFinder::FIND_DNSSEC) != 0 ?
|
||||
ZoneFinder::FIND_DNSSEC : ZoneFinder::FIND_DEFAULT;
|
||||
|
||||
ZoneFinder* finder = getFinder();
|
||||
if (finder == NULL) {
|
||||
// This is a bug of the derived class implementation.
|
||||
isc_throw(isc::Unexpected, "NULL ZoneFinder in finder Context");
|
||||
}
|
||||
|
||||
ConstZoneFinderContextPtr ctx = finder->find(finder->getOrigin(), type,
|
||||
options);
|
||||
if (ctx->code == ZoneFinder::SUCCESS) {
|
||||
return (ctx->rrset);
|
||||
}
|
||||
return (ConstRRsetPtr());
|
||||
}
|
||||
|
||||
} // namespace datasrc
|
||||
} // datasrc isc
|
||||
|
Reference in New Issue
Block a user