Commit 1add5d52 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

fixed memory leak for QueryTask::zone

this led to a larger refactoring:
  - I figured out we actually don't have to have this information in QueryTask:
    everything can be passed directly as a function argument.
  - I've also changed 'Name* zone' method argument to 'const Name*' based on
    the policy of 'make things const as much as possible'
  - also changed variable name from zone to zonename (because we might want to
    have a more generic notion of "zone" like BIND9's lib/dns/zone module)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1113 e5f2f494-b856-4b98-b285-d166d9295462
parent 3ac7cb15
......@@ -14,12 +14,12 @@
// $Id$
#include <cassert>
#include <iostream>
#include <vector>
#include <boost/foreach.hpp>
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rdataclass.h>
......@@ -126,26 +126,27 @@ chaseCname(Query& q, QueryTaskPtr task, RRsetPtr rrset)
}
// Perform the query specified in a QueryTask object
DataSrc::Result
doQueryTask(const DataSrc* ds, Query& q, QueryTask& task, RRsetList& target)
static DataSrc::Result
doQueryTask(const DataSrc* ds, const Name* zonename, Query& q, QueryTask& task,
RRsetList& target)
{
switch (task.op) {
case QueryTask::AUTH_QUERY:
return (ds->findRRset(q, task.qname, task.qclass, task.qtype,
target, task.flags, task.zone));
target, task.flags, zonename));
case QueryTask::SIMPLE_QUERY:
return (ds->findExactRRset(q, task.qname, task.qclass, task.qtype,
target, task.flags, task.zone));
target, task.flags, zonename));
case QueryTask::GLUE_QUERY:
case QueryTask::NOGLUE_QUERY:
return (ds->findAddrs(q, task.qname, task.qclass, target,
task.flags, task.zone));
task.flags, zonename));
case QueryTask::REF_QUERY:
return (ds->findReferral(q, task.qname, task.qclass, target,
task.flags, task.zone));
task.flags, zonename));
}
// Not reached
......@@ -168,15 +169,12 @@ copyAuth(Query& q, RRsetList& auth)
// Query for referrals (i.e., NS/DS or DNAME) at a given name
static inline bool
refQuery(const Name& name, Query& q, QueryTaskPtr task,
const DataSrc* ds, RRsetList& target)
const DataSrc* ds, const Name* zonename, RRsetList& target)
{
QueryTask newtask(name, q.qclass(), QueryTask::REF_QUERY);
newtask.zone = task->zone;
DataSrc::Result result = doQueryTask(ds, q, newtask, target);
// Lookup failed
if (result != DataSrc::SUCCESS) {
if (doQueryTask(ds, zonename, q, newtask, target) != DataSrc::SUCCESS) {
// Lookup failed
return (false);
}
......@@ -191,16 +189,17 @@ refQuery(const Name& name, Query& q, QueryTaskPtr task,
// Match downward, from the zone apex to the query name, looking for
// referrals.
static inline bool
hasDelegation(const DataSrc* ds, Query& q, QueryTaskPtr task)
hasDelegation(const DataSrc* ds, const Name* zonename, Query& q,
QueryTaskPtr task)
{
int nlen = task->qname.getLabelCount();
int diff = nlen - task->zone->getLabelCount();
int diff = nlen - zonename->getLabelCount();
if (diff > 1) {
bool found = false;
RRsetList ref;
for(int i = diff; i > 1; --i) {
Name sub(task->qname.split(i - 1, nlen - i));
if (refQuery(sub, q, task, ds, ref)) {
if (refQuery(sub, q, task, ds, zonename, ref)) {
found = true;
break;
}
......@@ -247,7 +246,8 @@ hasDelegation(const DataSrc* ds, Query& q, QueryTaskPtr task)
// Attempt a wildcard lookup
static inline DataSrc::Result
tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds,
const Name* zonename, bool& found)
{
Message& m = q.message();
DataSrc::Result result;
......@@ -260,7 +260,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
}
int nlen = task->qname.getLabelCount();
int diff = nlen - task->zone->getLabelCount();
int diff = nlen - zonename->getLabelCount();
if (diff < 1) {
return (DataSrc::SUCCESS);
}
......@@ -273,8 +273,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
const Name& wname(star.concatenate(task->qname.split(i, nlen - i)));
QueryTask newtask(wname, task->qclass, task->qtype,
QueryTask::SIMPLE_QUERY);
newtask.zone = task->zone;
result = doQueryTask(ds, q, newtask, wild);
result = doQueryTask(ds, zonename, q, newtask, wild);
if (result == DataSrc::SUCCESS &&
(newtask.flags == 0 || (newtask.flags & DataSrc::CNAME_FOUND))) {
rflags = newtask.flags;
......@@ -289,7 +288,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
// answer: if a CNAME, chase the target, otherwise
// add authority.
if (found) {
if (rflags & DataSrc::CNAME_FOUND) {
if ((rflags & DataSrc::CNAME_FOUND) != 0) {
if (RRsetPtr rrset = wild[RRType::CNAME()]) {
rrset->setName(task->qname);
m.addRRset(Section::ANSWER(), rrset, q.wantDnssec());
......@@ -302,7 +301,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
}
RRsetList auth;
if (! refQuery(Name(*task->zone), q, task, ds, auth)) {
if (! refQuery(*zonename, q, task, ds, zonename, auth)) {
return (DataSrc::ERROR);
}
......@@ -311,10 +310,9 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds, bool& found)
} else if (q.wantDnssec()) {
// No wildcard found; add an NSEC to prove it
RRsetList nsec;
QueryTask newtask(*task->zone, task->qclass, RRType::NSEC(),
QueryTask newtask(*zonename, task->qclass, RRType::NSEC(),
QueryTask::SIMPLE_QUERY);
newtask.zone = task->zone;
result = doQueryTask(ds, q, newtask, nsec);
result = doQueryTask(ds, zonename, q, newtask, nsec);
if (result != DataSrc::SUCCESS) {
return (DataSrc::ERROR);
}
......@@ -356,24 +354,25 @@ DataSrc::doQuery(Query& q)
task->qname);
findClosestEnclosure(match);
const DataSrc* datasource = match.bestDataSrc();
const Name* zone = match.closestName();
const Name* zonename = match.closestName();
assert((datasource == NULL && zonename == NULL) ||
(datasource != NULL && zonename != NULL));
RRsetList data;
Result result = SUCCESS;
if (datasource) {
task->zone = new Name(*zone);
// For these query task types, if there is more than
// one level between the zone name and qname, we need to
// check the intermediate nodes for referrals.
if ((task->op == QueryTask::AUTH_QUERY ||
task->op == QueryTask::NOGLUE_QUERY) &&
hasDelegation(datasource, q, task)) {
hasDelegation(datasource, zonename, q, task)) {
continue;
}
result = doQueryTask(datasource, q, *task, data);
result = doQueryTask(datasource, zonename, q, *task, data);
if (result != SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
......@@ -383,7 +382,7 @@ DataSrc::doQuery(Query& q)
// i.e., if an NS was at the zone apex, or if we were querying
// specifically for the NS, DS or DNAME record.
if ((task->flags & REFERRAL) != 0 &&
(zone->getLabelCount() == task->qname.getLabelCount() ||
(zonename->getLabelCount() == task->qname.getLabelCount() ||
task->qtype == RRType::NS() ||
task->qtype == RRType::DS() ||
task->qtype == RRType::DNAME())) {
......@@ -391,6 +390,15 @@ DataSrc::doQuery(Query& q)
}
} else {
task->flags = NO_SUCH_ZONE;
// No such zone. If we're chasing cnames or adding additional
// data, that's okay, but if doing an original query, return
// REFUSED.
if (task->state == QueryTask::GETANSWER) {
m.setRcode(Rcode::REFUSED());
return;
}
continue;
}
if (result == SUCCESS && task->flags == 0) {
......@@ -414,7 +422,8 @@ DataSrc::doQuery(Query& q)
// Add the NS records for the enclosing zone to
// the authority section.
RRsetList auth;
if (! refQuery(Name(*zone), q, task, datasource, auth)) {
if (! refQuery(*zonename, q, task, datasource,
zonename, auth)) {
m.setRcode(Rcode::SERVFAIL());
return;
}
......@@ -456,7 +465,8 @@ DataSrc::doQuery(Query& q)
if (task->state == QueryTask::GETANSWER) {
RRsetList auth;
m.clearHeaderFlag(MessageFlag::AA());
if (! refQuery(task->qname, q, task, datasource, auth)) {
if (!refQuery(task->qname, q, task, datasource, zonename,
auth)) {
m.setRcode(Rcode::SERVFAIL());
return;
}
......@@ -474,22 +484,13 @@ DataSrc::doQuery(Query& q)
}
}
continue;
} else if ((task->flags & NO_SUCH_ZONE) != 0) {
// No such zone. If we're chasing cnames or adding additional
// data, that's okay, but if doing an original query, return
// REFUSED.
if (task->state == QueryTask::GETANSWER) {
m.setRcode(Rcode::REFUSED());
return;
}
continue;
} else if ((task->flags & (NAME_NOT_FOUND|TYPE_NOT_FOUND)) != 0) {
// No data found at this qname/qtype.
// If we were looking for answer data, not additional,
// and the name was not found, we need to find out whether
// there are any relevant wildcards.
bool wildcard_found = false;
result = tryWildcard(q, task, datasource, wildcard_found);
result = tryWildcard(q, task, datasource, zonename, wildcard_found);
if (result != SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
......@@ -509,19 +510,18 @@ DataSrc::doQuery(Query& q)
Name nsecname(task->qname);
if ((task->flags & NAME_NOT_FOUND) != 0) {
datasource->findPreviousName(q, task->qname, nsecname,
task->zone);
zonename);
}
if (task->state == QueryTask::GETANSWER) {
if (task->flags & NAME_NOT_FOUND) {
if ((task->flags & NAME_NOT_FOUND) != 0) {
m.setRcode(Rcode::NXDOMAIN());
}
RRsetList soa;
QueryTask newtask(Name(*zone), task->qclass, RRType::SOA(),
QueryTask newtask(*zonename, task->qclass, RRType::SOA(),
QueryTask::SIMPLE_QUERY);
newtask.zone = task->zone;
result = doQueryTask(datasource, q, newtask, soa);
result = doQueryTask(datasource, zonename, q, newtask, soa);
if (result != SUCCESS || newtask.flags != 0) {
m.setRcode(Rcode::SERVFAIL());
return;
......@@ -535,8 +535,7 @@ DataSrc::doQuery(Query& q)
RRsetList nsec;
QueryTask newtask(nsecname, task->qclass,
RRType::NSEC(), QueryTask::SIMPLE_QUERY);
newtask.zone = task->zone;
result = doQueryTask(datasource, q, newtask, nsec);
result = doQueryTask(datasource, zonename, q, newtask, nsec);
if (result != SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
......@@ -575,19 +574,21 @@ DataSrc::doQuery(Query& q)
DataSrc::Result
DataSrc::findAddrs(const Query& q, const Name& qname, const RRClass& qclass,
RRsetList& target, uint32_t& flags, Name* zone) const
RRsetList& target, uint32_t& flags,
const Name* zonename) const
{
Result r;
bool a = false, aaaa = false;
flags = 0;
r = findExactRRset(q, qname, qclass, RRType::A(), target, flags, zone);
r = findExactRRset(q, qname, qclass, RRType::A(), target, flags, zonename);
if (r == SUCCESS && flags == 0) {
a = true;
}
flags = 0;
r = findExactRRset(q, qname, qclass, RRType::AAAA(), target, flags, zone);
r = findExactRRset(q, qname, qclass, RRType::AAAA(), target, flags,
zonename);
if (r == SUCCESS && flags == 0) {
aaaa = true;
}
......@@ -603,13 +604,14 @@ DataSrc::findAddrs(const Query& q, const Name& qname, const RRClass& qclass,
DataSrc::Result
DataSrc::findReferral(const Query& q, const Name& qname, const RRClass& qclass,
RRsetList& target, uint32_t& flags, Name* zone) const
RRsetList& target, uint32_t& flags,
const Name* zonename) const
{
Result r;
bool ns = false, ds = false, dname = false;
flags = 0;
r = findExactRRset(q, qname, qclass, RRType::NS(), target, flags, zone);
r = findExactRRset(q, qname, qclass, RRType::NS(), target, flags, zonename);
if (r == SUCCESS && flags == 0) {
ns = true;
} else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
......@@ -617,7 +619,7 @@ DataSrc::findReferral(const Query& q, const Name& qname, const RRClass& qclass,
}
flags = 0;
r = findExactRRset(q, qname, qclass, RRType::DS(), target, flags, zone);
r = findExactRRset(q, qname, qclass, RRType::DS(), target, flags, zonename);
if (r == SUCCESS && flags == 0) {
ds = true;
} else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
......@@ -625,7 +627,8 @@ DataSrc::findReferral(const Query& q, const Name& qname, const RRClass& qclass,
}
flags = 0;
r = findExactRRset(q, qname, qclass, RRType::DNAME(), target, flags, zone);
r = findExactRRset(q, qname, qclass, RRType::DNAME(), target, flags,
zonename);
if (r == SUCCESS && flags == 0) {
dname = true;
} else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
......
......@@ -102,7 +102,7 @@ public:
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const = 0;
const isc::dns::Name* zonename) const = 0;
virtual Result findExactRRset(const Query& q,
const isc::dns::Name& qname,
......@@ -110,7 +110,7 @@ public:
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const = 0;
const isc::dns::Name* zonename) const = 0;
// These will have dumb implementations in the general DataSrc
// class, and SHOULD be overwritten by subclasses.
......@@ -119,21 +119,21 @@ public:
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const = 0;
const isc::dns::Name* zonename) const = 0;
virtual Result findReferral(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const = 0;
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const = 0;
// This MUST be implemented by concrete data sources which support
// DNSSEC, but is optional for others (e.g., the static data source).
virtual Result findPreviousName(const Query& q,
const isc::dns::Name& qname,
isc::dns::Name& target,
isc::dns::Name* zone) const = 0;
const isc::dns::Name* zonename) const = 0;
};
......@@ -171,7 +171,7 @@ public:
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const = 0;
const isc::dns::Name* zonename) const = 0;
virtual Result findExactRRset(const Query& q,
const isc::dns::Name& qname,
......@@ -179,26 +179,26 @@ public:
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const = 0;
const isc::dns::Name* zonename) const = 0;
virtual Result findAddrs(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const;
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
const isc::dns::Name* zonename) const;
virtual Result findReferral(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const;
const isc::dns::Name* zonename) const;
virtual Result findPreviousName(const Query& q,
const isc::dns::Name& qname,
isc::dns::Name& target,
isc::dns::Name* zone) const = 0;
const isc::dns::Name* zonename) const = 0;
private:
isc::dns::RRClass rrclass;
};
......@@ -234,7 +234,7 @@ public:
const isc::dns::RRClass& qclass,
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target, uint32_t& flags,
isc::dns::Name* zone = NULL) const
const isc::dns::Name* zonename) const
{
return (NOT_IMPLEMENTED);
}
......@@ -243,7 +243,7 @@ public:
const isc::dns::RRClass& qclass,
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target, uint32_t& flags,
isc::dns::Name* zone = NULL) const
const isc::dns::Name* zonename) const
{
return (NOT_IMPLEMENTED);
}
......@@ -251,7 +251,7 @@ public:
Result findAddrs(const Query& q, const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target, uint32_t& flags,
isc::dns::Name* zone = NULL) const
const isc::dns::Name* zonename) const
{
return (NOT_IMPLEMENTED);
}
......@@ -259,7 +259,7 @@ public:
Result findReferral(const Query& q, const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target, uint32_t& flags,
isc::dns::Name* zone = NULL) const
const isc::dns::Name* zonename) const
{
return (NOT_IMPLEMENTED);
}
......@@ -267,7 +267,7 @@ public:
virtual Result findPreviousName(const Query& q,
const isc::dns::Name& qname,
isc::dns::Name& target,
isc::dns::Name* zone) const
const isc::dns::Name* zonename) const
{
return (NOT_IMPLEMENTED);
}
......
......@@ -87,9 +87,9 @@ int Sqlite3DataSrc::hasExactZone(const char* name) const
}
int
Sqlite3DataSrc::
findRecords(const Name& name, const RRType& rdtype, RRsetList& target,
Name* zone, const Mode mode, uint32_t& flags) const
Sqlite3DataSrc::findRecords(const Name& name, const RRType& rdtype,
RRsetList& target, const Name* zonename,
const Mode mode, uint32_t& flags) const
{
int rc;
const string s_name = name.toText();
......@@ -117,12 +117,10 @@ findRecords(const Name& name, const RRType& rdtype, RRsetList& target,
flags = 0;
int zone_id;
if (zone == NULL) {
if (zonename == NULL) {
zone_id = findClosest(c_name, NULL);
} else {
const string s_zone = zone->toText();
const char *c_zone = s_zone.c_str();
zone_id = findClosest(c_zone, NULL);
zone_id = findClosest(zonename->toText().c_str(), NULL);
}
if (zone_id < 0) {
......@@ -484,16 +482,16 @@ DataSrc::Result
Sqlite3DataSrc::findPreviousName(const Query& q,
const Name& qname,
Name& target,
Name* zone) const
const Name* zonename) const
{
const char* c_rname = qname.reverse().toText().c_str();
int zone_id;
if (zone == NULL) {
if (zonename == NULL) {
const char* c_name = qname.toText().c_str();
zone_id = findClosest(c_name, NULL);
} else {
const char* c_zone = zone->toText().c_str();
const char* c_zone = zonename->toText().c_str();
zone_id = findClosest(c_zone, NULL);
}
......@@ -532,9 +530,9 @@ Sqlite3DataSrc::findRRset(const Query& q,
const RRType& qtype,
RRsetList& target,
uint32_t& flags,
Name* zone) const
const Name* zonename) const
{
findRecords(qname, qtype, target, zone, NORMAL, flags);
findRecords(qname, qtype, target, zonename, NORMAL, flags);
return (SUCCESS);
}
......@@ -545,9 +543,9 @@ Sqlite3DataSrc::findExactRRset(const Query& q,
const RRType& qtype,
RRsetList& target,
uint32_t& flags,
Name* zone) const
const Name* zonename) const
{
findRecords(qname, qtype, target, zone, NORMAL, flags);
findRecords(qname, qtype, target, zonename, NORMAL, flags);
// Ignore referrals in this case
flags &= ~REFERRAL;
......@@ -567,9 +565,9 @@ Sqlite3DataSrc::findAddrs(const Query& q,
const RRClass& qclass,
RRsetList& target,
uint32_t& flags,
Name* zone) const
const Name* zonename) const
{
findRecords(qname, RRType::ANY(), target, zone, ADDRESS, flags);
findRecords(qname, RRType::ANY(), target, zonename, ADDRESS, flags);
return (SUCCESS);
}
......@@ -579,9 +577,9 @@ Sqlite3DataSrc::findReferral(const Query& q,
const RRClass& qclass,
RRsetList& target,
uint32_t& flags,
Name* zone) const
const Name* zonename) const
{
findRecords(qname, RRType::ANY(), target, zone, DELEGATION, flags);
findRecords(qname, RRType::ANY(), target, zonename, DELEGATION, flags);
return (SUCCESS);
}
//
......
......@@ -59,7 +59,7 @@ public:
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const;
const isc::dns::Name* zonename) const;
virtual Result findExactRRset(const Query& q,
const isc::dns::Name& qname,
......@@ -67,26 +67,26 @@ public:
const isc::dns::RRType& qtype,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const;
const isc::dns::Name* zonename) const;
virtual Result findAddrs(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const;
const isc::dns::Name* zonename) const;
virtual Result findReferral(const Query& q,
const isc::dns::Name& qname,
const isc::dns::RRClass& qclass,
isc::dns::RRsetList& target,
uint32_t& flags,
isc::dns::Name* zone = NULL) const;
const isc::dns::Name* zonename) const;
virtual DataSrc::Result findPreviousName(const Query& q,
const isc::dns::Name& qname,