* The const-cast is wrong, but the Message interface seems
* to insist.
*/
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(soa_ctx->rrset), dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ soa_ctx->rrset));
}
}
}
// Add the NSEC proving NXDOMAIN to the authority section.
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(nsec), dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(nsec));
// Next, identify the best possible wildcard name that would match
// the query name. It's the longer common suffix with the qname
// stage of performance optimization, we should consider optimizing this
// for some optimized data source implementations.
if (nsec->getName() != fcontext->rrset->getName()) {
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(fcontext->rrset),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ fcontext->rrset));
}
}
}
if (add_closest) {
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- result.closest_proof),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ result.closest_proof));
}
if (result.next_proof) {
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- result.next_proof),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ result.next_proof));
}
return (result.closest_labels);
}
<< (result.matched ? "matching" : "covering")
<< " NSEC3 found for " << name);
}
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- result.closest_proof),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ result.closest_proof));
}
void
isc_throw(BadNSEC,
"Unexpected NSEC result for wildcard proof");
}
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- fcontext->rrset),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ fcontext->rrset));
} else if (db_context.isNSEC3Signed()) {
// Case for RFC 5155 Section 7.2.6.
//
if (nsec->getName() != fcontext->rrset->getName()) {
// one NSEC RR proves wildcard_nxrrset that no matched QNAME.
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(fcontext->rrset),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ fcontext->rrset));
}
}
ConstZoneFinderContextPtr ds_context =
finder.find(dname, RRType::DS(), dnssec_opt_);
if (ds_context->code == ZoneFinder::SUCCESS) {
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- ds_context->rrset),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ ds_context->rrset));
} else if (ds_context->code == ZoneFinder::NXRRSET &&
ds_context->isNSECSigned()) {
addNXRRsetProof(finder, *ds_context);
const ZoneFinder::Context& db_context)
{
if (db_context.isNSECSigned() && db_context.rrset) {
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- db_context.rrset),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ db_context.rrset));
if (db_context.isWildcard()) {
addWildcardNXRRSETProof(finder, db_context.rrset);
}
isc_throw(NoApexNS, "There's no apex NS records in zone " <<
finder.getOrigin().toText());
}
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(
- ns_context->rrset), dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ ns_context->rrset));
getAdditional(qname_, qtype_, *ns_context, additionals);
}
Query::process() {
if (datasrc_client_ == NULL) {
isc_throw(isc::InvalidOperation,
- "Query::process called before setting data source");
+ "Query::process() called before initialize()");
}
// Found a zone which is the nearest ancestor to QNAME
// has to be handled there.
if (qtype_ == RRType::DS() && qname_.getLabelCount() > 1 &&
processDSAtChild()) {
+ createResponse();
return;
}
response_->setHeaderFlag(Message::HEADERFLAG_AA, false);
response_->setRcode(Rcode::REFUSED());
+ createResponse();
return;
}
ZoneFinder& zfinder = *result.zone_finder;
const bool qtype_is_any = (qtype_ == RRType::ANY());
if (qtype_is_any) {
find = boost::bind(&ZoneFinder::findAll, &zfinder, qname_,
- boost::ref(target_), dnssec_opt_);
+ boost::ref(answer_), dnssec_opt_);
} else {
find = boost::bind(&ZoneFinder::find, &zfinder, qname_, qtype_,
dnssec_opt_);
switch (db_context->code) {
case ZoneFinder::DNAME: {
// First, put the dname into the answer
- response_->addRRset(Message::SECTION_ANSWER,
- boost::const_pointer_cast<AbstractRRset>(db_context->rrset),
- dnssec_);
+ answer_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ db_context->rrset));
/*
* Empty DNAME should never get in, as it is impossible to
* create one in master file.
* of RFC 2672 mandates we return YXDOMAIN.
*/
response_->setRcode(Rcode::YXDOMAIN());
- return;
+ break;
}
// The new CNAME we are creating (it will be unsigned even
// with DNSSEC, the DNAME is signed and it can be validated
qname_.getLabelCount() -
db_context->rrset->getName().getLabelCount()).
concatenate(dname.getDname())));
- response_->addRRset(Message::SECTION_ANSWER, cname, dnssec_);
+ answer_.push_back(cname);
break;
}
case ZoneFinder::CNAME:
*
* So, just put it there.
*/
- response_->addRRset(Message::SECTION_ANSWER,
- boost::const_pointer_cast<AbstractRRset>(db_context->rrset),
- dnssec_);
+ answer_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ db_context->rrset));
// If the answer is a result of wildcard substitution,
// add a proof that there's no closer name.
if (qtype_is_any) {
// If quety type is ANY, insert all RRs under the domain
// into answer section.
- BOOST_FOREACH(ConstRRsetPtr rrset, target_) {
- response_->addRRset(Message::SECTION_ANSWER,
- boost::const_pointer_cast<AbstractRRset>(rrset), dnssec_);
- }
+ // err THIS WILL FAIL
+ //BOOST_FOREACH(ConstRRsetPtr rrset, answer_) {
+ // answer_.push_back(
+ // boost::const_pointer_cast<AbstractRRset>(rrset));
+ //}
} else {
- response_->addRRset(Message::SECTION_ANSWER,
- boost::const_pointer_cast<AbstractRRset>(db_context->rrset),
- dnssec_);
+ answer_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ db_context->rrset));
}
// Retrieve additional records for the answer
// complete the process in the child as specified in Section
// 2.2.1.2. of RFC3658.
if (qtype_ == RRType::DS() && processDSAtChild()) {
- return;
+ break;
}
response_->setHeaderFlag(Message::HEADERFLAG_AA, false);
- response_->addRRset(Message::SECTION_AUTHORITY,
- boost::const_pointer_cast<AbstractRRset>(db_context->rrset),
- dnssec_);
+ authority_.push_back(boost::const_pointer_cast<AbstractRRset>(
+ db_context->rrset));
// Retrieve additional records for the name servers
db_context->getAdditional(A_AND_AAAA(), additionals_);
break;
}
+ createResponse();
+}
+
+void
+Query::createResponse() {
+ for_each(answer_.begin(), answer_.end(),
+ RRsetInserter(*response_, Message::SECTION_ANSWER,
+ dnssec_));
+ answer_.clear();
+ for_each(authority_.begin(), authority_.end(),
+ RRsetInserter(*response_, Message::SECTION_AUTHORITY,
+ dnssec_));
+ authority_.clear();
for_each(additionals_.begin(), additionals_.end(),
RRsetInserter(*response_, Message::SECTION_ADDITIONAL,
dnssec_));
+ additionals_.clear();
}
bool
void addNSEC3ForName(isc::datasrc::ZoneFinder& finder,
const isc::dns::Name& name, bool match);
+ /// \brief Fill in the response sections
+ ///
+ /// This is the final step of the process() method, and within
+ /// that method, it should be called before it returns (if any
+ /// response data is to be added)
+ ///
+ /// This will take each RRset collected in answer_, authority_, and
+ /// additionals_, and add them to their corresponding sections in
+ /// the response packet.
+ ///
+ /// After they are added, the vectors are cleared.
+ void createResponse();
+
public:
/// Constructor from query parameters.
///
{}
};
+ /// Set up the Query object for a new query lookup
+ ///
+ /// If the empty constructor, has been used to initialize the
+ /// query instance, of if the instance is reused, it should
+ /// be initialized with data to look up.
+ ///
void
- reset(datasrc::DataSourceClient* datasrc_client,
+ initialize(datasrc::DataSourceClient* datasrc_client,
const isc::dns::Name qname, const isc::dns::RRType qtype,
isc::dns::Message* response, bool dnssec = false) {
datasrc_client_ = datasrc_client;
dnssec_ = dnssec;
dnssec_opt_ = (dnssec ? isc::datasrc::ZoneFinder::FIND_DNSSEC :
isc::datasrc::ZoneFinder::FIND_DEFAULT);
+ // The call to reset() could in theory be ommitted, but
+ // seems prudent, just in case a previous process() left
+ // data in here.
+ reset();
+ }
- target_.clear();
+ /// \brief Reset any partly built response data
+ ///
+ /// In theory, this is not necessary if the process() call finishes
+ /// successfully, but if it does not, reset() can be used to clean up.
+ void
+ reset() {
+ answer_.clear();
+ authority_.clear();
additionals_.clear();
}
bool dnssec_;
isc::datasrc::ZoneFinder::FindOptions dnssec_opt_;
- std::vector<isc::dns::ConstRRsetPtr> target_;
+ std::vector<isc::dns::ConstRRsetPtr> answer_;
+ std::vector<isc::dns::ConstRRsetPtr> authority_;
std::vector<isc::dns::ConstRRsetPtr> additionals_;
};