Fix looping issues

This commit is contained in:
Witold Kręcicki 2018-07-14 20:11:03 +02:00
parent 0246ea14c4
commit f2af336dc4
8 changed files with 83 additions and 33 deletions

View file

@ -6764,8 +6764,8 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
*/
domain = dns_fixedname_initname(&fdomain);
dns_rdataset_init(&nameservers);
result = dns_view_findzonecut(view, origin, domain, 0, 0, true,
true, &nameservers, NULL);
result = dns_view_findzonecut(view, origin, domain, NULL, 0, 0,
true, true, &nameservers, NULL);
if (result == ISC_R_SUCCESS) {
result = dns_resolver_createfetch(view->resolver, tatname,
dns_rdatatype_null, domain,

View file

@ -258,7 +258,7 @@ lookup(const char *target) {
result = dns_adb_createfind(adb, t2, lookup_callback, client,
&client->name, dns_rootname, 0, options,
now, NULL, view->dstport, 0, NULL,
&client->find);
NULL, 0, &client->find);
if (result != ISC_R_SUCCESS)
printf("DNS_ADB_CREATEFIND -> %s\n", dns_result_totext(result));
dns_adb_dumpfind(client->find, stderr);

View file

@ -117,7 +117,7 @@ do_find(bool want_event) {
dns_fixedname_name(&fixed),
dns_rootname, 0, options, 0,
dns_fixedname_name(&target), 0,
0, NULL, &find);
0, NULL, NULL, 0, &find);
if (result == ISC_R_SUCCESS) {
if (!ISC_LIST_EMPTY(find->list)) {
/*

View file

@ -239,7 +239,6 @@ NS boing.slow.
NS zoop.boing.slow.
ADDR ns3.slow.
ADDR ns3.slow.
NS icky.ptang.zoop.boing.slow.
ADDR a.bit.longer.ns.name.slow.
ADDR a.bit.longer.ns.name.slow.
__EOF

View file

@ -195,6 +195,8 @@ struct dns_adbname {
isc_stdtime_t last_used;
ISC_LINK(dns_adbname_t) plink;
isc_sockaddr_t client;
dns_messageid_t id;
};
/*% The adbfetch structure */
@ -337,7 +339,8 @@ static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
dns_rdatatype_t);
static isc_result_t fetch_name(dns_adbname_t *, bool,
unsigned int, isc_counter_t *qc,
dns_rdatatype_t);
dns_rdatatype_t, const isc_sockaddr_t *client,
dns_messageid_t id);
static inline void check_exit(dns_adb_t *);
static void destroy(dns_adb_t *);
static bool shutdown_names(dns_adb_t *);
@ -1539,6 +1542,8 @@ clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
isc_task_sendanddetach(&task, (isc_event_t **)&ev);
find->flags |= FIND_EVENT_SENT;
memset(&name->client, 0, sizeof(name->client));
name->id = 0;
} else {
DP(DEF_LEVEL, "cfan: skipping find %p", find);
}
@ -1546,7 +1551,6 @@ clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
UNLOCK(&find->lock);
find = next_find;
}
DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
}
@ -1696,6 +1700,8 @@ new_adbname(dns_adb_t *adb, const dns_name_t *dnsname) {
name->fetch_aaaa = NULL;
name->fetch_err = FIND_ERR_UNEXPECTED;
name->fetch6_err = FIND_ERR_UNEXPECTED;
memset(&name->client, 0, sizeof(name->client));
name->id = 0;
ISC_LIST_INIT(name->finds);
ISC_LINK_INIT(name, plink);
@ -2936,6 +2942,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target,
in_port_t port, unsigned int depth, isc_counter_t *qc,
const isc_sockaddr_t *client, dns_messageid_t id,
dns_adbfind_t **findp)
{
dns_adbfind_t *find;
@ -3025,6 +3032,18 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
result = ISC_R_SHUTTINGDOWN;
goto out;
}
if (adbname != NULL && client != NULL &&
isc_sockaddr_equal(client, &adbname->client) && id == adbname->id) {
char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
dns_name_format(qname, buf, sizeof(buf));
dns_rdatatype_format(qtype, typebuf, sizeof(typebuf));
result = DNS_R_DUPLICATE;
DP(DEF_LEVEL,
"dns_adb_createfind: duplicate query (possible loop) for %s/%s", buf, typebuf);
RUNTIME_CHECK(!free_adbfind(adb, &find));
goto out;
}
/*
* Nothing found. Allocate a new adbname structure for this name.
@ -3175,7 +3194,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
*/
if (WANT_INET(wanted_fetches) &&
fetch_name(adbname, start_at_zone, depth, qc,
dns_rdatatype_a) == ISC_R_SUCCESS) {
dns_rdatatype_a, client, id) == ISC_R_SUCCESS) {
DP(DEF_LEVEL, "dns_adb_createfind: "
"started A fetch for name %s (%p)",
namebuf, adbname);
@ -3186,7 +3205,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
*/
if (WANT_INET6(wanted_fetches) &&
fetch_name(adbname, start_at_zone, depth, qc,
dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
dns_rdatatype_aaaa, client, id) == ISC_R_SUCCESS) {
DP(DEF_LEVEL, "dns_adb_createfind: "
"started AAAA fetch for name %s (%p)",
namebuf, adbname);
@ -3221,12 +3240,20 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
if (want_event) {
find->adbname = adbname;
find->name_bucket = bucket;
bool empty = ISC_LIST_EMPTY(adbname->finds);
/* If there are no finds pending take ownership of adbname */
if (adbname->client.length == 0 && client != NULL) {
adbname->client = *client;
adbname->id = id;
}
ISC_LIST_APPEND(adbname->finds, find, plink);
find->query_pending = (query_pending & wanted_addresses);
find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
find, adbname);
DP(DEF_LEVEL, "createfind: attaching find %p to adbname "
"%p (%d/%d) %d",
find, adbname, isc_sockaddr_hash(&adbname->client, true),
adbname->id, empty);
} else {
/*
* Remove the flag so the caller knows there will never
@ -3993,7 +4020,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
static isc_result_t
fetch_name(dns_adbname_t *adbname, bool start_at_zone,
unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type,
const isc_sockaddr_t *client, dns_messageid_t id)
{
isc_result_t result;
dns_adbfetch_t *fetch = NULL;
@ -4046,15 +4074,18 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone,
* createfetch to find deepest cached name when we're providing
* domain and nameservers.
*/
result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
type, name, nameservers, NULL,
NULL, 0, options, depth, qc,
client, id, options, depth, qc,
adb->task, fetch_callback, adbname,
&fetch->rdataset, NULL,
&fetch->fetch);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
DP(ENTER_LEVEL,
"fetch_name: createfetch failed with %s",
isc_result_totext(result));
goto cleanup;
}
if (type == dns_rdatatype_a) {
adbname->fetch_a = fetch;

View file

@ -337,6 +337,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
dns_rdatatype_t qtype, unsigned int options,
isc_stdtime_t now, dns_name_t *target, in_port_t port,
unsigned int depth, isc_counter_t *qc,
const isc_sockaddr_t *client, dns_messageid_t id,
dns_adbfind_t **find);
/*%<
* Main interface for clients. The adb will look up the name given in

View file

@ -68,7 +68,6 @@
#include <dns/stats.h>
#include <dns/tsig.h>
#include <dns/validator.h>
#ifdef WANT_QUERYTRACE
#define RTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
@ -385,6 +384,7 @@ struct fetchctx {
bool timeout;
dns_adbaddrinfo_t *addrinfo;
const isc_sockaddr_t *client;
dns_messageid_t id;
unsigned int depth;
};
@ -3317,6 +3317,7 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
bool unshared;
isc_result_t result;
FCTXTRACE("FINDNAME");
res = fctx->res;
unshared = (fctx->options & DNS_FETCHOPT_UNSHARED);
/*
@ -3341,8 +3342,13 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
&fctx->name, fctx->type,
options, now, NULL,
res->view->dstport,
fctx->depth + 1, fctx->qc, &find);
fctx->depth + 1, fctx->qc, fctx->client,
fctx->id, &find);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
"fctx %p(%s): createfind for %p/%d - %s",
fctx, fctx->info, fctx->client, fctx->id,
isc_result_totext(result));
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_ALIAS) {
char namebuf[DNS_NAME_FORMATSIZE];
@ -3967,12 +3973,15 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
fctx_increference(fctx);
task = res->buckets[bucketnum].task;
result = dns_resolver_createfetch(fctx->res, &fctx->qminname,
fctx->qmintype, NULL,
NULL, NULL, NULL, 0,
options, 0, fctx->qc,
task, resume_qmin, fctx,
&fctx->qminrrset, NULL,
&fctx->qminfetch);
fctx->qmintype, &fctx->domain,
&fctx->nameservers, NULL, fctx->client,
fctx->id, options, 0,
fctx->qc, task, resume_qmin,
fctx, &fctx->qminrrset,
NULL, &fctx->qminfetch);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
}
return;
}
@ -4559,7 +4568,6 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, const isc_sockaddr_t *client,
else
ISC_LIST_APPEND(fctx->events, event, ev_link);
fctx->references++;
fctx->client = client;
fetch->magic = DNS_FETCH_MAGIC;
fetch->private = fctx;
@ -4585,7 +4593,8 @@ static isc_result_t
fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
const dns_name_t *domain, dns_rdataset_t *nameservers,
unsigned int options, unsigned int bucketnum, unsigned int depth,
isc_counter_t *qc, fetchctx_t **fctxp)
isc_counter_t *qc, const isc_sockaddr_t *client, dns_messageid_t id,
fetchctx_t **fctxp)
{
fetchctx_t *fctx;
isc_result_t result;
@ -4705,7 +4714,8 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
fctx->rand_bits = 0;
fctx->timeout = false;
fctx->addrinfo = NULL;
fctx->client = NULL;
fctx->client = client;
fctx->id = id;
fctx->ns_ttl = 0;
fctx->ns_ttl_ok = false;
@ -7032,7 +7042,8 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
dns_rdatatype_ns, domain,
nsrdataset, NULL, NULL, 0,
nsrdataset, NULL,
fctx->client, fctx->id,
fctx->options, 0, NULL, task,
resume_dslookup, fctx,
&fctx->nsrrset, NULL,
@ -7043,6 +7054,9 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
* another thread concurrently processing the fetch.
*/
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_DUPLICATE) {
result = DNS_R_SERVFAIL;
}
fctx_done(fctx, result, __LINE__);
} else {
LOCK(&res->buckets[bucketnum].lock);
@ -9303,14 +9317,18 @@ rctx_chaseds(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo, isc_result_t result)
result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
dns_rdatatype_ns,
NULL, NULL, NULL, NULL, 0,
NULL, NULL, NULL,
fctx->client, fctx->id,
fctx->options, 0, NULL, rctx->task,
resume_dslookup, fctx,
&fctx->nsrrset, NULL,
&fctx->nsfetch);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_DUPLICATE) {
result = DNS_R_SERVFAIL;
}
fctx_done(fctx, result, __LINE__);
else {
} else {
fctx_increference(fctx);
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
@ -10469,7 +10487,8 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
if (fctx == NULL) {
result = fctx_create(res, name, type, domain, nameservers,
options, bucketnum, depth, qc, &fctx);
options, bucketnum, depth, qc, client,
id, &fctx);
if (result != ISC_R_SUCCESS)
goto unlock;
new_fctx = true;

View file

@ -10991,7 +10991,7 @@ notify_find_address(dns_notify_t *notify) {
&notify->ns, dns_rootname, 0,
options, 0, NULL,
notify->zone->view->dstport,
0, NULL, &notify->find);
0, NULL, NULL, 0, &notify->find);
/* Something failed? */
if (result != ISC_R_SUCCESS)