result = dns_resolver_createfetch(
tat->view->resolver, tatname, dns_rdatatype_null,
domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL,
- tat->loop, tat_done, tat, NULL, &tat->rdataset,
+ NULL, tat->loop, tat_done, tat, NULL, &tat->rdataset,
&tat->sigrdataset, &tat->fetch);
}
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,
- isc_counter_t *gqc, dns_rdatatype_t);
+ isc_counter_t *gqc, fetchctx_t *parent, dns_rdatatype_t);
static void
destroy(dns_adb_t *);
static void
dns_rdatatype_t qtype ISC_ATTR_UNUSED, unsigned int options,
isc_stdtime_t now, dns_name_t *target, in_port_t port,
unsigned int depth, isc_counter_t *qc, isc_counter_t *gqc,
- dns_adbfind_t **findp) {
+ fetchctx_t *parent, dns_adbfind_t **findp) {
isc_result_t result = ISC_R_UNEXPECTED;
dns_adbfind_t *find = NULL;
dns_adbname_t *adbname = NULL;
* Start V4.
*/
if (WANT_INET(wanted_fetches) &&
- fetch_name(adbname, start_at_zone, depth, qc, gqc,
+ fetch_name(adbname, start_at_zone, depth, qc, gqc, parent,
dns_rdatatype_a) == ISC_R_SUCCESS)
{
DP(DEF_LEVEL,
* Start V6.
*/
if (WANT_INET6(wanted_fetches) &&
- fetch_name(adbname, start_at_zone, depth, qc, gqc,
+ fetch_name(adbname, start_at_zone, depth, qc, gqc, parent,
dns_rdatatype_aaaa) == ISC_R_SUCCESS)
{
DP(DEF_LEVEL,
static isc_result_t
fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth,
- isc_counter_t *qc, isc_counter_t *gqc, dns_rdatatype_t type) {
+ isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
+ dns_rdatatype_t type) {
isc_result_t result;
dns_adbfetch_t *fetch = NULL;
dns_adb_t *adb = NULL;
dns_adbname_ref(adbname);
result = dns_resolver_createfetch(
adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0,
- options, depth, qc, gqc, isc_loop(), fetch_callback, adbname,
- NULL, &fetch->rdataset, NULL, &fetch->fetch);
+ options, depth, qc, gqc, parent, isc_loop(), fetch_callback,
+ adbname, NULL, &fetch->rdataset, NULL, &fetch->fetch);
if (result != ISC_R_SUCCESS) {
DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s",
isc_result_totext(result));
result = dns_resolver_createfetch(
rctx->view->resolver, dns_fixedname_name(&rctx->name),
rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL, rctx->qc,
- rctx->client->loop, fetch_done, rctx, NULL, rctx->rdataset,
- rctx->sigrdataset, &rctx->fetch);
+ NULL, rctx->client->loop, fetch_done, rctx, NULL,
+ rctx->rdataset, rctx->sigrdataset, &rctx->fetch);
return result;
}
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, isc_counter_t *gqc,
- dns_adbfind_t **find);
+ fetchctx_t *parent, dns_adbfind_t **find);
/*%<
* Main interface for clients. The adb will look up the name given in
* "name" and will build up a list of found addresses, and perhaps start
const isc_sockaddr_t *client, dns_messageid_t id,
unsigned int options, unsigned int depth,
isc_counter_t *qc, isc_counter_t *gqc,
- isc_loop_t *loop, isc_job_cb cb, void *arg,
- dns_edectx_t *edectx, dns_rdataset_t *rdataset,
- dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp);
+ fetchctx_t *parent, isc_loop_t *loop, isc_job_cb cb,
+ void *arg, dns_edectx_t *edectx,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp);
/*%<
* Recurse to answer a question.
*
isc_counter_t *nfails;
isc_counter_t *qc;
isc_counter_t *gqc;
+ fetchctx_t *parent_fetch;
dns_edectx_t edectx;
dns_message_t *message, unsigned int options,
isc_loop_t *loop, isc_job_cb cb, void *arg,
isc_counter_t *nvalidations, isc_counter_t *nfails,
- isc_counter_t *qc, isc_counter_t *gqc,
+ isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
dns_edectx_t *edectx, dns_validator_t **validatorp);
/*%<
* Start a DNSSEC validation.
dns__nta_ref(nta); /* for dns_resolver_createfetch */
result = dns_resolver_createfetch(
resolver, &nta->name, dns_rdatatype_nsec, NULL, NULL, NULL,
- NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, NULL, nta->loop,
+ NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, NULL, NULL, nta->loop,
fetch_done, nta, NULL, &nta->rdataset, &nta->sigrdataset,
&nta->fetch);
if (result != ISC_R_SUCCESS) {
isc_counter_t *nvalidations;
isc_counter_t *nfails;
+
+ fetchctx_t *parent;
};
#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
dns_rdatatype_t type, const dns_name_t *domain,
dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
unsigned int options, unsigned int depth, isc_counter_t *qc,
- isc_counter_t *gqc, fetchctx_t **fctxp, bool *new_fctx);
+ isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
+ bool *new_fctx);
/*%
* The structure and functions defined below implement the resolver
result = dns_validator_create(
fctx->res->view, name, type, rdataset, sigrdataset, message,
valoptions, fctx->loop, validated, valarg, fctx->nvalidations,
- fctx->nfails, fctx->qc, fctx->gqc, &fctx->edectx, &validator);
+ fctx->nfails, fctx->qc, fctx->gqc, fctx, &fctx->edectx,
+ &validator);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
inc_stats(fctx->res, dns_resstatscounter_val);
if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
result = dns_adb_createfind(fctx->adb, fctx->loop, fctx_finddone, fctx,
name, fctx->name, fctx->type, options, now,
NULL, res->view->dstport, fctx->depth + 1,
- fctx->qc, fctx->gqc, &find);
+ fctx->qc, fctx->gqc, fctx, &find);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
result = dns_resolver_createfetch(
fctx->res, fctx->qminname, fctx->qmintype, fctx->domain,
&fctx->nameservers, NULL, NULL, 0, options, 0, fctx->qc,
- fctx->gqc, fctx->loop, resume_qmin, fctx, &fctx->edectx,
- &fctx->qminrrset, NULL, &fctx->qminfetch);
+ fctx->gqc, fctx, fctx->loop, resume_qmin, fctx,
+ &fctx->edectx, &fctx->qminrrset, NULL,
+ &fctx->qminfetch);
if (result != ISC_R_SUCCESS) {
fetchctx_unref(fctx);
goto done;
if (fctx->gqc != NULL) {
isc_counter_detach(&fctx->gqc);
}
+ if (fctx->parent != NULL) {
+ fetchctx_detach(&fctx->parent);
+ }
fcount_decr(fctx);
dns_message_detach(&fctx->qmessage);
if (dns_rdataset_isassociated(&fctx->nameservers)) {
dns_rdatatype_t type, const dns_name_t *domain,
dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
unsigned int options, unsigned int depth, isc_counter_t *qc,
- isc_counter_t *gqc, fetchctx_t **fctxp) {
+ isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp) {
fetchctx_t *fctx = NULL;
isc_result_t result;
isc_result_t iresult;
fctx->start = isc_time_now();
fctx->now = (isc_stdtime_t)fctx->start.seconds;
+ if (parent != NULL) {
+ fetchctx_attach(parent, &fctx->parent);
+ }
+
if (client != NULL) {
isc_sockaddr_format(client, fctx->clientstr,
sizeof(fctx->clientstr));
if (fctx->gqc != NULL) {
isc_counter_detach(&fctx->gqc);
}
+ if (fctx->parent != NULL) {
+ fetchctx_detach(&fctx->parent);
+ }
cleanup_fetch:
dns_resolver_detach(&fctx->res);
result = dns_resolver_createfetch(
res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset,
NULL, NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc,
- loop, resume_dslookup, fctx, &fctx->edectx,
+ fctx, loop, resume_dslookup, fctx, &fctx->edectx,
&fctx->nsrrset, NULL, &fctx->nsfetch);
if (result != ISC_R_SUCCESS) {
fetchctx_unref(fctx);
fetchctx_ref(fctx);
result = dns_resolver_createfetch(
fctx->res, fctx->nsname, dns_rdatatype_ns, NULL, NULL, NULL,
- NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc, fctx->loop,
- resume_dslookup, fctx, &fctx->edectx, &fctx->nsrrset, NULL,
- &fctx->nsfetch);
+ NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc, fctx,
+ fctx->loop, resume_dslookup, fctx, &fctx->edectx,
+ &fctx->nsrrset, NULL, &fctx->nsfetch);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_DUPLICATE) {
result = DNS_R_SERVFAIL;
LOCK(&res->primelock);
result = dns_resolver_createfetch(
res, dns_rootname, dns_rdatatype_ns, NULL, NULL, NULL,
- NULL, 0, DNS_FETCHOPT_NOFORWARD, 0, NULL, NULL,
+ NULL, 0, DNS_FETCHOPT_NOFORWARD, 0, NULL, NULL, NULL,
isc_loop(), prime_done, res, NULL, rdataset, NULL,
&res->primefetch);
UNLOCK(&res->primelock);
dns_rdatatype_t type, const dns_name_t *domain,
dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
unsigned int options, unsigned int depth, isc_counter_t *qc,
- isc_counter_t *gqc, fetchctx_t **fctxp, bool *new_fctx) {
+ isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
+ bool *new_fctx) {
isc_result_t result;
fetchctx_t key = {
.name = UNCONST(name),
break;
case ISC_R_NOTFOUND:
result = fctx_create(res, loop, name, type, domain, nameservers,
- client, options, depth, qc, gqc, &fctx);
+ client, options, depth, qc, gqc, parent,
+ &fctx);
if (result != ISC_R_SUCCESS) {
RWUNLOCK(&res->fctxs_lock, locktype);
return result;
return result;
}
+static bool
+waiting_for_fetch(fetchctx_t *fctx, const dns_name_t *name,
+ dns_rdatatype_t type) {
+ while (fctx != NULL) {
+ if (type == fctx->type && !dns_name_compare(name, fctx->name)) {
+ return true;
+ }
+ fctx = fctx->parent;
+ }
+ return false;
+}
+
isc_result_t
dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
const isc_sockaddr_t *client, dns_messageid_t id,
unsigned int options, unsigned int depth,
isc_counter_t *qc, isc_counter_t *gqc,
- isc_loop_t *loop, isc_job_cb cb, void *arg,
- dns_edectx_t *edectx, dns_rdataset_t *rdataset,
- dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) {
+ fetchctx_t *parent, isc_loop_t *loop, isc_job_cb cb,
+ void *arg, dns_edectx_t *edectx,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp) {
dns_fetch_t *fetch = NULL;
fetchctx_t *fctx = NULL;
isc_result_t result = ISC_R_SUCCESS;
log_fetch(name, type);
+ if (waiting_for_fetch(parent, name, type)) {
+ if (isc_log_wouldlog(dns_lctx, ISC_LOG_INFO)) {
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(2),
+ "fetch loop detected resolving '%s/%s'",
+ namebuf, typebuf);
+ }
+ return DNS_R_LOOPDETECTED;
+ }
+
fetch = isc_mem_get(mctx, sizeof(*fetch));
*fetch = (dns_fetch_t){ 0 };
result = get_attached_fctx(res, loop, name, type, domain,
nameservers, client, options, depth,
- qc, gqc, &fctx, &new_fctx);
+ qc, gqc, parent, &fctx, &new_fctx);
if (result != ISC_R_SUCCESS) {
goto fail;
}
}
} else {
result = fctx_create(res, loop, name, type, domain, nameservers,
- client, options, depth, qc, gqc, &fctx);
+ client, options, depth, qc, gqc, parent,
+ &fctx);
if (result != ISC_R_SUCCESS) {
goto fail;
}
dns_validator_ref(val);
result = dns_resolver_createfetch(
val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0,
- fopts, 0, val->qc, val->gqc, val->loop, callback, val,
- &val->edectx, &val->frdataset, &val->fsigrdataset, &val->fetch);
+ fopts, 0, val->qc, val->gqc, val->parent_fetch, val->loop,
+ callback, val, &val->edectx, &val->frdataset,
+ &val->fsigrdataset, &val->fetch);
if (result != ISC_R_SUCCESS) {
dns_validator_detach(&val);
}
result = dns_validator_create(
val->view, name, type, rdataset, sig, NULL, vopts, val->loop,
cb, val, val->nvalidations, val->nfails, val->qc, val->gqc,
- &val->edectx, &val->subvalidator);
+ val->parent_fetch, &val->edectx, &val->subvalidator);
if (result == ISC_R_SUCCESS) {
dns_validator_attach(val, &val->subvalidator->parent);
val->subvalidator->depth = val->depth + 1;
dns_message_t *message, unsigned int options,
isc_loop_t *loop, isc_job_cb cb, void *arg,
isc_counter_t *nvalidations, isc_counter_t *nfails,
- isc_counter_t *qc, isc_counter_t *gqc,
+ isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
dns_edectx_t *edectx, dns_validator_t **validatorp) {
isc_result_t result = ISC_R_FAILURE;
dns_validator_t *val = NULL;
.arg = arg,
.rdata = DNS_RDATA_INIT,
.cb_edectx = edectx,
+ .parent_fetch = parent,
};
dns_ede_init(view->mctx, &val->edectx);
*/
result = dns_resolver_createfetch(
resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, NULL,
- 0, options, 0, NULL, NULL, zone->loop, keyfetch_done, kfetch,
- NULL, &kfetch->dnskeyset, &kfetch->dnskeysigset,
+ 0, options, 0, NULL, NULL, NULL, zone->loop, keyfetch_done,
+ kfetch, NULL, &kfetch->dnskeyset, &kfetch->dnskeysigset,
&kfetch->fetch);
dns_resolver_detach(&resolver);
goto destroy;
}
- result = dns_adb_createfind(
- adb, notify->zone->loop, process_notify_adb_event, notify,
- ¬ify->ns, dns_rootname, 0, options, 0, NULL,
- notify->zone->view->dstport, 0, NULL, NULL, ¬ify->find);
+ result = dns_adb_createfind(adb, notify->zone->loop,
+ process_notify_adb_event, notify,
+ ¬ify->ns, dns_rootname, 0, options, 0,
+ NULL, notify->zone->view->dstport, 0, NULL,
+ NULL, NULL, ¬ify->find);
dns_adb_detach(&adb);
/* Something failed? */
goto destroy;
}
- result = dns_adb_createfind(
- adb, checkds->zone->loop, process_checkds_adb_event, checkds,
- &checkds->ns, dns_rootname, 0, options, 0, NULL,
- checkds->zone->view->dstport, 0, NULL, NULL, &checkds->find);
+ result = dns_adb_createfind(adb, checkds->zone->loop,
+ process_checkds_adb_event, checkds,
+ &checkds->ns, dns_rootname, 0, options, 0,
+ NULL, checkds->zone->view->dstport, 0, NULL,
+ NULL, NULL, &checkds->find);
dns_adb_detach(&adb);
/* Something failed? */
*/
result = dns_resolver_createfetch(
resolver, &nsfetch->pname, dns_rdatatype_ns, NULL, NULL, NULL,
- NULL, 0, options, 0, NULL, NULL, zone->loop, nsfetch_done,
+ NULL, 0, options, 0, NULL, NULL, NULL, zone->loop, nsfetch_done,
nsfetch, NULL, &nsfetch->nsrrset, &nsfetch->nssigset,
&nsfetch->fetch);
DNS_R_NODOHPATH,
DNS_R_NOSKRFILE,
DNS_R_NOSKRBUNDLE,
+ DNS_R_LOOPDETECTED,
DST_R_UNSUPPORTEDALG,
DST_R_CRYPTOFAILURE,
#include <stdlib.h>
#include <isc/once.h>
+#include <isc/result.h>
#include <isc/util.h>
static const char *description[ISC_R_NRESULTS] = {
[DNS_R_NODOHPATH] = "no DOHPATH",
[DNS_R_NOSKRFILE] = "no SKR file",
[DNS_R_NOSKRBUNDLE] = "no available SKR bundle",
+ [DNS_R_LOOPDETECTED] = "fetch loop detected",
[DST_R_UNSUPPORTEDALG] = "algorithm is unsupported",
[DST_R_CRYPTOFAILURE] = "crypto failure",
[DNS_R_NODOHPATH] = "DNS_R_NODOHPATH",
[DNS_R_NOSKRFILE] = "DNS_R_NOSKRFILE",
[DNS_R_NOSKRBUNDLE] = "DNS_R_NOSKRBUNDLE",
+ [DNS_R_LOOPDETECTED] = "DNS_R_LOOPDETECTED",
[DST_R_UNSUPPORTEDALG] = "DST_R_UNSUPPORTEDALG",
[DST_R_CRYPTOFAILURE] = "DST_R_CRYPTOFAILURE",
result = dns_resolver_createfetch(
client->view->resolver, qname, qtype, NULL, NULL, NULL,
peeraddr, client->message->id, options, 0, NULL,
- client->query.qc, client->manager->loop, cb, client, NULL,
+ client->query.qc, NULL, client->manager->loop, cb, client, NULL,
tmprdataset, NULL, fetchp);
if (result != ISC_R_SUCCESS) {
ns_client_putrdataset(client, &tmprdataset);
result = dns_resolver_createfetch(
client->view->resolver, qname, qtype, qdomain, nameservers,
NULL, peeraddr, client->message->id, client->query.fetchoptions,
- 0, NULL, client->query.qc, client->manager->loop,
+ 0, NULL, client->query.qc, NULL, client->manager->loop,
fetch_callback, client, &client->edectx, rdataset, sigrdataset,
&FETCH_RECTYPE_NORMAL(client));
if (result != ISC_R_SUCCESS) {