} while (0)
#endif /* WANT_QUERYTRACE */
+/*
+ * Add or remove an extra fctx reference without setting or clearing
+ * the pointer.
+ */
+#define fctx_addref(f) fctx_attach((f), &(fetchctx_t *){ NULL })
+#define fctx_unref(f) fctx_detach(&(fetchctx_t *){ (f) })
+
#define US_PER_SEC 1000000U
#define US_PER_MSEC 1000U
#define NS_PER_US 1000U
fetchstate_init = 0, /*%< Start event has not run yet. */
fetchstate_active,
fetchstate_done /*%< FETCHDONE events posted. */
-} fetchstate;
+} fetchstate_t;
typedef enum {
badns_unreachable = 0,
isc_refcount_t references;
/*% Locked by appropriate bucket lock. */
- fetchstate state;
+ fetchstate_t state;
atomic_bool want_shutdown;
bool cloned;
bool spilled;
#define fctx_attach(fctx, fctxp) \
fctx__attach(fctx, fctxp, __FILE__, __LINE__, __func__)
#define fctx_detach(fctxp) fctx__detach(fctxp, __FILE__, __LINE__, __func__)
+#define fctx_done_detach(fctxp, result) \
+ fctx__done_detach(fctxp, result, __FILE__, __LINE__, __func__);
static void
fctx__attach(fetchctx_t *fctx, fetchctx_t **fctxp, const char *file,
fctx__detach(fetchctx_t **fctxp, const char *file, unsigned int line,
const char *func);
+static void
+fctx__done_detach(fetchctx_t **fctxp, isc_result_t result, const char *file,
+ unsigned int line, const char *func);
+
static void
resume_qmin(isc_task_t *task, isc_event_t *event);
dns_dispatch_cancel(&query->dispentry);
}
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
if (ISC_LINK_LINKED(query, link)) {
ISC_LIST_UNLINK(fctx->queries, query, link);
}
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
resquery_detach(queryp);
}
next_find = ISC_LIST_NEXT(find, publink);
ISC_LIST_UNLINK(fctx->finds, find, publink);
dns_adb_destroyfind(&find);
- fctx_detach(&(fetchctx_t *){ fctx });
+ fctx_unref(fctx);
}
fctx->find = NULL;
next_find = ISC_LIST_NEXT(find, publink);
ISC_LIST_UNLINK(fctx->altfinds, find, publink);
dns_adb_destroyfind(&find);
- fctx_detach(&(fetchctx_t *){ fctx });
+ fctx_unref(fctx);
}
fctx->altfind = NULL;
static void
fctx_cancelqueries(fetchctx_t *fctx, bool no_response, bool age_untried) {
resquery_t *query = NULL, *next_query = NULL;
+ ISC_LIST(resquery_t) queries;
FCTXTRACE("cancelqueries");
- for (query = ISC_LIST_HEAD(fctx->queries); query != NULL;
- query = next_query) {
+ ISC_LIST_INIT(queries);
+
+ /*
+ * Move the queries to a local list so we can cancel
+ * them without holding the lock.
+ */
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ ISC_LIST_MOVE(queries, fctx->queries);
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+
+ for (query = ISC_LIST_HEAD(queries); query != NULL; query = next_query)
+ {
next_query = ISC_LIST_NEXT(query, link);
+
+ /*
+ * Note that we have to unlink the query here,
+ * because if it's still linked in fctx_cancelquery(),
+ * then it will try to unlink it from fctx->queries.
+ */
+ ISC_LIST_UNLINK(queries, query, link);
fctx_cancelquery(&query, NULL, no_response, age_untried);
}
}
}
static void
-fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
- dns_resolver_t *res;
+fctx__done_detach(fetchctx_t **fctxp, isc_result_t result, const char *file,
+ unsigned int line, const char *func) {
+ fetchctx_t *fctx = NULL;
+ dns_resolver_t *res = NULL;
bool no_response = false;
bool age_untried = false;
- REQUIRE(line >= 0);
+ REQUIRE(fctxp != NULL && VALID_FCTX(*fctxp));
+
+ fctx = *fctxp;
+ res = fctx->res;
FCTXTRACE("done");
- res = fctx->res;
+#ifdef FCTX_TRACE
+ fprintf(stderr, "%s:%s:%u:%s(%p, %p): %s\n", func, file, line, __func__,
+ fctx, fctxp, isc_result_totext(result));
+#else
+ UNUSED(file);
+ UNUSED(line);
+ UNUSED(func);
+#endif
+
+ LOCK(&res->buckets[fctx->bucketnum].lock);
+ INSIST(fctx->state != fetchstate_done);
+ fctx->state = fetchstate_done;
+ UNLOCK(&res->buckets[fctx->bucketnum].lock);
if (result == ISC_R_SUCCESS) {
if (fctx->qmin_warning != ISC_R_SUCCESS) {
fctx_stoptimer(fctx);
LOCK(&res->buckets[fctx->bucketnum].lock);
- fctx->state = fetchstate_done;
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
fctx_sendevents(fctx, result, line);
fctx_shutdown(fctx);
UNLOCK(&res->buckets[fctx->bucketnum].lock);
- fctx_detach(&fctx);
+ fctx_detach(fctxp);
}
static void
"due to unexpected result; responding",
eresult);
fctx_cancelquery(©, NULL, false, false);
- fctx_done(fctx, eresult, __LINE__);
+ fctx_done_detach(&fctx, eresult);
break;
}
"responding");
fctx_cancelquery(©, NULL, false, false);
- fctx_done(fctx, result, __LINE__);
+ fctx_done_detach(&fctx, result);
break;
}
case ISC_R_SHUTTINGDOWN:
FCTXTRACE3("shutdown in resquery_connected()", eresult);
fctx_cancelquery(©, NULL, true, false);
- fctx_done(fctx, eresult, __LINE__);
+ fctx_done_detach(&fctx, eresult);
break;
case ISC_R_NETUNREACH:
eresult);
fctx_cancelquery(©, NULL, false, false);
- fctx_done(fctx, eresult, __LINE__);
+ fctx_done_detach(&fctx, eresult);
break;
}
dns_adb_destroyfind(&find);
- if (want_try) {
- fctx_try(fctx, true, false);
- } else if (want_done) {
+ if (want_done) {
FCTXTRACE("fetch failed in finddone(); return "
"ISC_R_FAILURE");
- fctx_done(fctx, ISC_R_FAILURE, __LINE__);
- }
- fctx_detach(&fctx);
+ /* Detach the extra reference from findname(). */
+ fctx_unref(fctx);
+ fctx_done_detach(&fctx, ISC_R_FAILURE);
+ } else if (want_try) {
+ fctx_try(fctx, true, false);
+ fctx_detach(&fctx);
+ } else {
+ fctx_detach(&fctx);
+ }
}
static bool
/*
* See what we know about this address.
*/
- fctx_attach(fctx, &(fetchctx_t *){ NULL });
+ fctx_addref(fctx);
result = dns_adb_createfind(
fctx->adb, res->buckets[fctx->bucketnum].task, fctx_finddone,
fctx, name, fctx->name, fctx->type, options, now, NULL,
dns_resolver_t *res;
isc_task_t *task;
unsigned int bucketnum;
- fetchctx_t *ev_fctx = NULL;
FCTXTRACE5("try", "fctx->qc=", isc_counter_used(fctx->qc));
"(querycount=%u, maxqueries=%u)",
fctx->info, isc_counter_used(fctx->qc),
res->maxqueries);
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&fctx, DNS_R_SERVFAIL);
return;
}
/*
* Something bad happened.
*/
- fctx_done(fctx, result, __LINE__);
+ fctx_done_detach(&fctx, result);
return;
}
* might be bad ones. In this case, return SERVFAIL.
*/
if (addrinfo == NULL) {
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&fctx, DNS_R_SERVFAIL);
return;
}
}
fctx->qminfetch,
validfctx ? fctx->qminfetch->private->info
: "<invalid>");
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&fctx, DNS_R_SERVFAIL);
return;
}
if ((options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
options |= DNS_FETCHOPT_NOFOLLOW;
}
- fctx_attach(fctx, &ev_fctx);
+ fctx_addref(fctx);
task = res->buckets[bucketnum].task;
result = dns_resolver_createfetch(
fctx->res, fctx->qminname, fctx->qmintype, fctx->domain,
&fctx->nameservers, NULL, NULL, 0, options, 0, fctx->qc,
- task, resume_qmin, ev_fctx, &fctx->qminrrset, NULL,
+ task, resume_qmin, fctx, &fctx->qminrrset, NULL,
&fctx->qminfetch);
if (result != ISC_R_SUCCESS) {
- fctx_detach(&ev_fctx);
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_unref(fctx);
+ fctx_done_detach(&fctx, DNS_R_SERVFAIL);
}
return;
}
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
"exceeded max queries resolving '%s'",
fctx->info);
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&fctx, DNS_R_SERVFAIL);
return;
}
result = fctx_query(fctx, addrinfo, fctx->options);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, result, __LINE__);
+ fctx_done_detach(&fctx, result);
} else if (retrying) {
inc_stats(res, dns_resstatscounter_retry);
}
static void
resume_qmin(isc_task_t *task, isc_event_t *event) {
- dns_fetchevent_t *fevent;
- dns_resolver_t *res;
- fetchctx_t *fctx;
+ dns_fetchevent_t *fevent = NULL;
+ dns_resolver_t *res = NULL;
+ fetchctx_t *fctx = NULL;
isc_result_t result;
unsigned int bucketnum;
unsigned int findoptions = 0;
- dns_name_t *fname, *dcname;
+ dns_name_t *fname = NULL, *dcname = NULL;
dns_fixedname_t ffixed, dcfixed;
- fname = dns_fixedname_initname(&ffixed);
- dcname = dns_fixedname_initname(&dcfixed);
+
+ UNUSED(task);
REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
fevent = (dns_fetchevent_t *)event;
REQUIRE(VALID_FCTX(fctx));
res = fctx->res;
- UNUSED(task);
FCTXTRACE("resume_qmin");
+ fname = dns_fixedname_initname(&ffixed);
+ dcname = dns_fixedname_initname(&dcfixed);
+
if (fevent->node != NULL) {
dns_db_detachnode(fevent->db, &fevent->node);
}
if (dns_rdataset_isassociated(fevent->rdataset)) {
dns_rdataset_disassociate(fevent->rdataset);
}
+
result = fevent->result;
- fevent = NULL;
isc_event_free(&event);
dns_resolver_destroyfetch(&fctx->qminfetch);
if (SHUTTINGDOWN(fctx)) {
maybe_destroy(fctx, true);
UNLOCK(&res->buckets[bucketnum].lock);
- goto cleanup;
+ fctx_detach(&fctx);
+ return;
}
UNLOCK(&res->buckets[bucketnum].lock);
- /*
- * Note: fevent->rdataset must be disassociated and
- * isc_event_free(&event) be called before resuming
- * processing of the 'fctx' to prevent use-after-free.
- * 'fevent' is set to NULL so as to not have a dangling
- * pointer.
- */
if (result == ISC_R_CANCELED) {
- fctx_done(fctx, result, __LINE__);
goto cleanup;
}
* Otherwise - either disable minimization if we're
* in relaxed mode or fail if we're in strict mode.
*/
-
if ((NXDOMAIN_RESULT(result) &&
(fctx->options & DNS_FETCHOPT_QMIN_USE_A) == 0) ||
result == DNS_R_FORMERR || result == DNS_R_REMOTEFORMERR ||
*/
fctx->qmin_warning = result;
} else {
- fctx_done(fctx, result, __LINE__);
goto cleanup;
}
}
}
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, result, __LINE__);
goto cleanup;
}
fcount_decr(fctx);
result = fcount_incr(fctx, false);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, result, __LINE__);
goto cleanup;
}
result = fctx_minimize_qname(fctx);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, result, __LINE__);
goto cleanup;
}
}
fctx_try(fctx, true, false);
+ fctx_detach(&fctx);
+ return;
cleanup:
- INSIST(event == NULL);
- INSIST(fevent == NULL);
-
- fctx_detach(&fctx);
+ /* Detach the extra reference from fctx_try() */
+ fctx_unref(fctx);
+ fctx_done_detach(&fctx, result);
}
static void
bool bucket_empty = false;
REQUIRE(VALID_FCTX(fctx));
- REQUIRE(fctx->state == fetchstate_done ||
- fctx->state == fetchstate_init);
REQUIRE(ISC_LIST_EMPTY(fctx->events));
REQUIRE(ISC_LIST_EMPTY(fctx->queries));
REQUIRE(ISC_LIST_EMPTY(fctx->finds));
bucketnum = fctx->bucketnum;
LOCK(&res->buckets[bucketnum].lock);
+ REQUIRE(fctx->state != fetchstate_active);
+
ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
INSIST(atomic_fetch_sub_release(&res->nfctx, 1) > 0);
static void
fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
fetchctx_t *fctx = event->ev_arg;
- dns_resolver_t *res;
+ dns_resolver_t *res = NULL;
unsigned int bucketnum;
- dns_validator_t *validator;
+ dns_validator_t *validator = NULL;
REQUIRE(VALID_FCTX(fctx));
FCTX_ATTR_SET(fctx, FCTX_ATTR_SHUTTINGDOWN);
- INSIST(fctx->state == fetchstate_active ||
- fctx->state == fetchstate_done);
+ INSIST(fctx->state != fetchstate_init);
INSIST(atomic_load_acquire(&fctx->want_shutdown));
- if (fctx->state != fetchstate_done) {
+ if (fctx->state == fetchstate_active) {
fctx->state = fetchstate_done;
+
fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
- fctx_detach(&(fetchctx_t *){ fctx });
+
+ /* Detach the extra ref from dns_resolver_createfetch(). */
+ fctx_unref(fctx);
}
UNLOCK(&res->buckets[bucketnum].lock);
UNLOCK(&res->buckets[bucketnum].lock);
FCTX_ATTR_SET(fctx, FCTX_ATTR_SHUTTINGDOWN);
- fctx_done(fctx, ISC_R_SHUTTINGDOWN, __LINE__);
- fctx_detach(&fctx);
+
+ /* Detach the extra ref from dns_resolver_createfetch(). */
+ fctx_unref(fctx);
+ fctx_done_detach(&fctx, ISC_R_SHUTTINGDOWN);
return;
}
* Normal fctx startup.
*/
fctx->state = fetchstate_active;
+
/*
* Reset the control event for later use in shutting
* down the fctx.
*/
result = fctx_starttimer(fctx);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, result, __LINE__);
+ fctx_done_detach(&fctx, result);
} else {
fctx_try(fctx, false, false);
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
"shut down hung fetch while resolving '%s'", fctx->info);
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
fctx_shutdown(fctx);
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
isc_event_free(&event);
}
*/
static void
validated(isc_task_t *task, isc_event_t *event) {
- dns_adbaddrinfo_t *addrinfo;
+ dns_adbaddrinfo_t *addrinfo = NULL;
dns_dbnode_t *node = NULL;
dns_dbnode_t *nsnode = NULL;
- dns_fetchevent_t *hevent;
- dns_name_t *name;
+ dns_fetchevent_t *hevent = NULL;
+ dns_name_t *name = NULL;
dns_rdataset_t *ardataset = NULL;
dns_rdataset_t *asigrdataset = NULL;
- dns_rdataset_t *rdataset;
- dns_rdataset_t *sigrdataset;
- dns_resolver_t *res;
- dns_valarg_t *valarg;
- dns_validatorevent_t *vevent;
- fetchctx_t *fctx = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdataset_t *sigrdataset = NULL;
+ dns_resolver_t *res = NULL;
+ dns_valarg_t *valarg = NULL;
+ dns_validatorevent_t *vevent = NULL;
+ fetchctx_t *fctx = NULL, *vfctx = NULL;
bool chaining;
bool negative;
bool sentresponse;
fctx = valarg->fctx;
valarg->fctx = NULL;
+ vfctx = fctx;
FCTXTRACE("received validation completion event");
if (fctx->validator != NULL) {
dns_validator_send(fctx->validator);
} else if (sentresponse) {
- fctx_done(fctx, result, __LINE__); /* Locks bucket */
+ fctx_done_detach(&fctx, result); /* Locks bucket */
} else if (result == DNS_R_BROKENCHAIN) {
isc_result_t tresult;
isc_time_t expire;
dns_resolver_addbadcache(res, fctx->name,
fctx->type, &expire);
}
- fctx_done(fctx, result, __LINE__); /* Locks bucket */
+ fctx_done_detach(&fctx, result); /* Locks bucket */
} else {
fctx_try(fctx, true, true); /* Locks bucket */
}
dns_message_detach(&message);
- fctx_detach(&fctx);
+ fctx_detach(&vfctx);
return;
}
}
UNLOCK(&res->buckets[bucketnum].lock);
- fctx_done(fctx, result, __LINE__); /* Locks bucket. */
+ fctx_done_detach(&fctx, result); /* Locks bucket. */
cleanup_event:
INSIST(node == NULL);
dns_message_detach(&message);
- fctx_detach(&fctx);
+ fctx_detach(&vfctx);
isc_event_free(&event);
}
resume_dslookup(isc_task_t *task, isc_event_t *event) {
dns_fetchevent_t *fevent = NULL;
dns_resolver_t *res = NULL;
- fetchctx_t *fctx = NULL;
+ fetchctx_t *fctx = NULL, *ds_fctx = NULL;
isc_result_t result;
dns_rdataset_t nameservers;
dns_fixedname_t fixed;
dns_name_t *domain = NULL;
- fetchctx_t *ev_fctx = NULL;
REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+
fevent = (dns_fetchevent_t *)event;
fctx = event->ev_arg;
+ ds_fctx = fctx;
REQUIRE(VALID_FCTX(fctx));
res = fctx->res;
* Note: fevent->rdataset must be disassociated and
* isc_event_free(&event) be called before resuming
* processing of the 'fctx' to prevent use-after-free.
- * 'fevent' is set to NULL so as to not have a dangling
- * pointer.
*/
if (fevent->result == ISC_R_CANCELED) {
if (dns_rdataset_isassociated(fevent->rdataset)) {
dns_rdataset_disassociate(fevent->rdataset);
}
- fevent = NULL;
- isc_event_free(&event);
dns_resolver_destroyfetch(&fctx->nsfetch);
goto cleanup;
}
UNLOCK(&res->buckets[fctx->bucketnum].lock);
-
- fctx_done(fctx, ISC_R_CANCELED, __LINE__);
+ fctx_done_detach(&fctx, ISC_R_CANCELED);
} else if (fevent->result == ISC_R_SUCCESS) {
FCTXTRACE("resuming DS lookup");
if (dns_rdataset_isassociated(fevent->rdataset)) {
dns_rdataset_disassociate(fevent->rdataset);
}
- fevent = NULL;
- isc_event_free(&event);
LOCK(&res->buckets[fctx->bucketnum].lock);
if (SHUTTINGDOWN(fctx)) {
fcount_decr(fctx);
dns_name_copy(fctx->nsname, fctx->domain);
result = fcount_incr(fctx, true);
- if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
- goto cleanup;
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Try again.
+ */
+ fctx_try(fctx, true, false);
+ } else {
+ fctx_done_detach(&fctx, DNS_R_SERVFAIL);
}
- /*
- * Try again.
- */
- fctx_try(fctx, true, false);
} else {
unsigned int n;
dns_rdataset_t *nsrdataset = NULL;
/*
- * Retrieve state from fctx->nsfetch before we destroy
- * it.
+ * Get domain and nameservers from fctx->nsfetch
+ * before we destroy it.
*/
domain = dns_fixedname_initname(&fixed);
dns_name_copy(fctx->nsfetch->private->domain, domain);
if (dns_rdataset_isassociated(fevent->rdataset)) {
dns_rdataset_disassociate(fevent->rdataset);
}
- fevent = NULL;
- isc_event_free(&event);
dns_resolver_destroyfetch(&fctx->nsfetch);
}
UNLOCK(&res->buckets[fctx->bucketnum].lock);
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done(&fctx, DNS_R_SERVFAIL);
goto cleanup;
}
if (dns_rdataset_isassociated(
if (dns_rdataset_isassociated(fevent->rdataset)) {
dns_rdataset_disassociate(fevent->rdataset);
}
- fevent = NULL;
- isc_event_free(&event);
LOCK(&res->buckets[fctx->bucketnum].lock);
if (SHUTTINGDOWN(fctx)) {
FCTXTRACE("continuing to look for parent's NS records");
- fctx_attach(fctx, &ev_fctx);
-
+ fctx_addref(fctx);
result = dns_resolver_createfetch(
res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset,
NULL, NULL, 0, fctx->options, 0, NULL, task,
- resume_dslookup, ev_fctx, &fctx->nsrrset, NULL,
+ resume_dslookup, fctx, &fctx->nsrrset, NULL,
&fctx->nsfetch);
/*
* fevent->rdataset (a.k.a. fctx->nsrrset) must not be
if (result == DNS_R_DUPLICATE) {
result = DNS_R_SERVFAIL;
}
- fctx_detach(&ev_fctx);
- fctx_done(fctx, result, __LINE__);
+ fctx_unref(fctx);
+ fctx_done_detach(&fctx, result);
}
}
cleanup:
- INSIST(event == NULL);
- INSIST(fevent == NULL);
if (dns_rdataset_isassociated(&nameservers)) {
dns_rdataset_disassociate(&nameservers);
}
- fctx_detach(&fctx);
+ isc_event_free(&event);
+ fctx_detach(&ds_fctx);
}
static void
dcname = dns_fixedname_initname(&founddc);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&rctx->fctx, DNS_R_SERVFAIL);
return;
}
if (dns_rdatatype_atparent(fctx->type)) {
findoptions, true, true, &fctx->nameservers, NULL);
if (result != ISC_R_SUCCESS) {
FCTXTRACE("couldn't find a zonecut");
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&rctx->fctx, DNS_R_SERVFAIL);
return;
}
if (!dns_name_issubdomain(fname, fctx->domain)) {
* QDOMAIN.
*/
FCTXTRACE("nameservers now above QDOMAIN");
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&rctx->fctx, DNS_R_SERVFAIL);
return;
}
result = fcount_incr(fctx, true);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&rctx->fctx, DNS_R_SERVFAIL);
return;
}
fctx->ns_ttl = fctx->nameservers.ttl;
*/
static void
rctx_resend(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo) {
- isc_result_t result;
fetchctx_t *fctx = rctx->fctx;
+ isc_result_t result;
FCTXTRACE("resend");
inc_stats(fctx->res, dns_resstatscounter_retry);
result = fctx_query(fctx, addrinfo, rctx->retryopts);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, result, __LINE__);
+ fctx_done_detach(&rctx->fctx, result);
}
}
rctx_chaseds(respctx_t *rctx, dns_message_t *message,
dns_adbaddrinfo_t *addrinfo, isc_result_t result) {
fetchctx_t *fctx = rctx->fctx;
- unsigned int n;
- fetchctx_t *ev_fctx = NULL;
isc_task_t *task = NULL;
+ unsigned int n;
add_bad(fctx, message, addrinfo, result, rctx->broken_type);
fctx_cancelqueries(fctx, true, false);
FCTXTRACE("suspending DS lookup to find parent's NS records");
- fctx_attach(fctx, &ev_fctx);
-
+ fctx_addref(fctx);
task = fctx->res->buckets[fctx->bucketnum].task;
result = dns_resolver_createfetch(
fctx->res, fctx->nsname, dns_rdatatype_ns, NULL, NULL, NULL,
- NULL, 0, fctx->options, 0, NULL, task, resume_dslookup, ev_fctx,
+ NULL, 0, fctx->options, 0, NULL, task, resume_dslookup, fctx,
&fctx->nsrrset, NULL, &fctx->nsfetch);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_DUPLICATE) {
result = DNS_R_SERVFAIL;
}
- fctx_detach(&ev_fctx);
- fctx_done(fctx, result, __LINE__);
+ fctx_detach(&fctx);
+ fctx_done_detach(&rctx->fctx, result);
}
}
{
fctx_cancelquery(&query, rctx->finish, rctx->no_response,
false);
- fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+ fctx_done_detach(&rctx->fctx, DNS_R_SERVFAIL);
goto detach;
}
#endif /* ifdef ENABLE_AFL */
/*
* We're done.
*/
- fctx_done(fctx, result, __LINE__);
+ fctx_done_detach(&rctx->fctx, result);
}
detach:
unsigned int spillat;
unsigned int spillatmin;
bool dodestroy = false;
- fetchctx_t *ev_fctx = NULL;
UNUSED(forwarders);
* Launch this fctx.
*/
event = &fctx->control_event;
- fctx_attach(fctx, &ev_fctx);
+ fctx_addref(fctx);
ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
- DNS_EVENT_FETCHCONTROL, fctx_start,
- ev_fctx, NULL, NULL, NULL);
+ DNS_EVENT_FETCHCONTROL, fctx_start, fctx,
+ NULL, NULL, NULL);
isc_task_send(res->buckets[bucketnum].task, &event);
} else {
dodestroy = true;
void
dns_resolver_cancelfetch(dns_fetch_t *fetch) {
- fetchctx_t *fctx;
- dns_resolver_t *res;
- dns_fetchevent_t *event, *next_event;
- isc_task_t *etask;
+ fetchctx_t *fctx = NULL;
+ dns_resolver_t *res = NULL;
+ dns_fetchevent_t *event = NULL;
REQUIRE(DNS_FETCH_VALID(fetch));
fctx = fetch->private;
* to those for other fetches that have joined the same
* fctx) and send it with result = ISC_R_CANCELED.
*/
- event = NULL;
if (fctx->state != fetchstate_done) {
+ dns_fetchevent_t *next_event = NULL;
for (event = ISC_LIST_HEAD(fctx->events); event != NULL;
event = next_event) {
next_event = ISC_LIST_NEXT(event, ev_link);
}
}
if (event != NULL) {
- etask = event->ev_sender;
+ isc_task_t *etask = event->ev_sender;
event->ev_sender = fctx;
event->result = ISC_R_CANCELED;
isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
void
dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
- dns_fetch_t *fetch;
- dns_resolver_t *res;
- dns_fetchevent_t *event, *next_event;
- fetchctx_t *fctx;
+ dns_fetch_t *fetch = NULL;
+ dns_resolver_t *res = NULL;
+ fetchctx_t *fctx = NULL;
unsigned int bucketnum;
REQUIRE(fetchp != NULL);
* trying to destroy the fetch.
*/
if (fctx->state != fetchstate_done) {
+ dns_fetchevent_t *event = NULL, *next_event = NULL;
for (event = ISC_LIST_HEAD(fctx->events); event != NULL;
event = next_event) {
next_event = ISC_LIST_NEXT(event, ev_link);