REQUIRE(query != NULL);
- debug("clear_query(%p)", query);
+ debug("debug_query(%p)", query);
- if (query->readhandle != NULL) {
- isc_nmhandle_detach(&query->readhandle);
- }
+ INSIST(query->recvspace != NULL);
- if (query->sendhandle != NULL) {
- isc_nmhandle_detach(&query->sendhandle);
- }
+ isc_mempool_put(commctx, query->recvspace);
+ isc_mempool_put(commctx, query->tmpsendspace);
+}
- lookup = query->lookup;
+static void
+destroy_query(dig_query_t *query) {
+ clear_query(query);
- if (lookup->current_query == query) {
- lookup->current_query = NULL;
- }
+ query->magic = 0;
+ isc_mem_free(mctx, query);
+}
- if (ISC_LINK_LINKED(query, link)) {
- ISC_LIST_UNLINK(lookup->q, query, link);
- }
- if (ISC_LINK_LINKED(query, clink)) {
- ISC_LIST_UNLINK(lookup->connecting, query, clink);
- }
- INSIST(query->recvspace != NULL);
+static void
+query_attach(dig_query_t *source, dig_query_t **targetp) {
+ REQUIRE(DIG_VALID_QUERY(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
- isc_mempool_put(commctx, query->recvspace);
- isc_mempool_put(commctx, query->tmpsendspace);
+ (void)isc_refcount_increment(&source->references);
- if (query->waiting_senddone) {
- debug("clear_query(): pending free");
- query->pending_free = true;
- } else {
- query->magic = 0;
- debug("clear_query(): free query");
- isc_mem_free(mctx, query);
+ *targetp = source;
+}
+
+static void
+query_detach(dig_query_t **queryp) {
+ dig_query_t *query = NULL;
+ dig_lookup_t *lookup = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(*queryp));
+
+ query = *queryp;
+ *queryp = NULL;
+
+ REQUIRE(DIG_VALID_QUERY(*queryp));
+
+ if (isc_refcount_decrement(&query->references) == 1) {
+ destroy_query(query);
}
}
dig_server_t *s;
void *ptr;
- debug("destroy");
+ debug("destroy_lookup");
s = ISC_LIST_HEAD(lookup->my_server_list);
while (s != NULL) {
debug("freeing server %p belonging to %p", s, lookup);
.warn_id = true,
.recvspace = isc_mempool_get(commctx),
.tmpsendspace = isc_mempool_get(commctx) };
+
if (query->recvspace == NULL) {
fatal("memory allocation failure");
}
dig_lookup_t *l = NULL;
REQUIRE(DIG_VALID_QUERY(query));
+ INSIST(query->sendhandle != NULL);
+ INSIST(handle == query->sendhandle);
debug("send_done()");
isc_refcount_decrement0(&sendcount);
debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount));
- /* Could occur on timeout or interrupt */
- if (query->sendhandle == NULL) {
- return;
- }
-
- INSIST(handle == query->sendhandle);
INSIST(!free_now);
if (eresult == ISC_R_CANCELED) {
- isc_nmhandle_detach(&query->sendhandle);
- return;
+ goto done;
} else if (eresult != ISC_R_SUCCESS) {
if (eresult != ISC_R_CANCELED) {
debug("send failed: %s", isc_result_totext(eresult));
}
- isc_nmhandle_detach(&query->sendhandle);
- return;
+ goto done;
}
LOCK_LOOKUP;
- query->waiting_senddone = false;
l = query->lookup;
- if (!query->pending_free && l->ns_search_only && !l->trace_root &&
- !l->tcp_mode) {
+ if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
debug("sending next, since searching");
next = ISC_LIST_NEXT(query, link);
if (next != NULL) {
start_udp(next);
- } else {
- isc_nmhandle_detach(&query->sendhandle);
}
- } else {
- isc_nmhandle_detach(&query->sendhandle);
}
- if (query->pending_free) {
- query->magic = 0;
- debug("senddone: free query");
- isc_mem_free(mctx, query);
- }
+ UNLOCK_LOOKUP;
+
+done:
+ isc_nmhandle_detach(&query->sendhandle);
+ query_detach(&query);
+ LOCK_LOOKUP;
+ check_if_done();
UNLOCK_LOOKUP;
}
while (query != NULL) {
REQUIRE(DIG_VALID_QUERY(query));
next = ISC_LIST_NEXT(query, link);
- if (query->readhandle != NULL) {
- check_if_done();
- } else {
- clear_query(query);
- }
+ ISC_LIST_DEQUEUE(lookup->q, query, link);
+ query_detach(&query);
query = next;
}
lookup->pending = false;
lookup->retries = 0;
+ check_if_done();
}
static void
debug("start_tcp(%p)", query);
l = query->lookup;
- query->waiting_connect = true;
query->lookup->current_query = query;
result = get_address(query->servname, port, &query->sockaddr);
if (result != ISC_R_SUCCESS) {
isc_netaddr_format(&netaddr, buf, sizeof(buf));
dighost_warning("Skipping mapped address '%s'", buf);
- query->waiting_connect = false;
if (ISC_LINK_LINKED(query, link)) {
next = ISC_LIST_NEXT(query, link);
} else {
next = NULL;
}
l = query->lookup;
- clear_query(query);
+ query_detach(&query);
if (next == NULL) {
dighost_warning("No acceptable nameservers");
check_next_lookup(l);
if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
query->handle = keep;
- query->waiting_connect = false;
launch_next_query(query);
+ query_detach(&query);
+ return;
} else {
int local_timeout = timeout * 1000;
if (local_timeout == 0) {
}
}
+ REQUIRE(query != NULL);
+
result = isc_nm_tcpdnsconnect(
netmgr, (isc_nmiface_t *)&localaddr,
(isc_nmiface_t *)&query->sockaddr, tcp_connected, query,
static void
send_udp(dig_query_t *query) {
+ dig_query_t *sendquery = NULL;
isc_region_t r;
+ query_attach(query, &sendquery);
+
isc_buffer_usedregion(&query->sendbuf, &r);
debug("sending a request");
TIME_NOW(&query->time_sent);
- query->waiting_senddone = true;
- if (query->sendhandle == NULL) {
- isc_nmhandle_attach(query->handle, &query->sendhandle);
- }
+ isc_nmhandle_attach(query->handle, &query->sendhandle);
- isc_nm_send(query->handle, &r, send_done, query);
+ isc_nm_send(query->handle, &r, send_done, sendquery);
isc_refcount_increment0(&sendcount);
/* XXX qrflag, print_query, etc... */
static void
udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
dig_query_t *query = (dig_query_t *)arg;
+ dig_query_t *readquery = NULL;
int local_timeout = timeout * 1000;
if (eresult == ISC_R_CANCELED) {
+ query_detach(&query);
return;
} else if (eresult != ISC_R_SUCCESS) {
if (eresult != ISC_R_CANCELED) {
debug("udp setup failed: %s",
isc_result_totext(eresult));
}
+ query_detach(&query);
return;
}
+ query_attach(query, &readquery);
+
debug("recving with lookup=%p, query=%p, handle=%p", query->lookup,
query, query->handle);
debug("have local timeout of %d", local_timeout);
isc_nmhandle_settimeout(handle, local_timeout);
- isc_nm_read(handle, recv_done, query);
- send_udp(query);
+ isc_nm_read(handle, recv_done, readquery);
+ send_udp(readquery);
+
+ query_detach(&query);
}
/*%
return;
}
- query->waiting_connect = false;
result = get_address(query->servname, port, &query->sockaddr);
if (result != ISC_R_SUCCESS) {
/* This servname doesn't have an address. */
dighost_warning("Skipping mapped address '%s'", buf);
next = ISC_LIST_NEXT(query, link);
l = query->lookup;
- clear_query(query);
+ query_detach(&query);
if (next == NULL) {
dighost_warning("No acceptable nameservers");
check_next_lookup(l);
debug("making new TCP request, %d tries left", l->retries);
requeue_lookup(l, true);
isc_refcount_decrement0(&recvcount);
- clear_query(query);
+ query_detach(&query);
check_next_lookup(l);
UNLOCK_LOOKUP;
return;
exitcode = 9;
}
- query->waiting_senddone = false;
- clear_query(query);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
*/
static void
launch_next_query(dig_query_t *query) {
+ dig_query_t *readquery = NULL;
int local_timeout = timeout * 1000;
dig_lookup_t *l = NULL;
isc_region_t r;
if (!query->lookup->pending) {
debug("ignoring launch_next_query because !pending");
- query->waiting_connect = false;
l = query->lookup;
- clear_query(query);
+ query_detach(&query);
check_next_lookup(l);
return;
}
- if (query->readhandle == NULL) {
- isc_nmhandle_attach(query->handle, &query->readhandle);
- }
+ isc_nmhandle_attach(query->handle, &query->readhandle);
isc_refcount_increment0(&recvcount);
debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
debug("have local timeout of %d", local_timeout);
isc_nmhandle_settimeout(query->handle, local_timeout);
- isc_nm_read(query->handle, recv_done, query);
+ query_attach(query, &readquery);
+ isc_nm_read(query->handle, recv_done, readquery);
if (!query->first_soa_rcvd) {
+ dig_query_t *sendquery = NULL;
debug("sending a request in launch_next_query");
TIME_NOW(&query->time_sent);
- query->waiting_senddone = true;
+ query_attach(query, &sendquery);
isc_buffer_usedregion(&query->sendbuf, &r);
if (keep != NULL) {
query->handle = keep;
}
isc_nmhandle_attach(query->handle, &query->sendhandle);
- isc_nm_send(query->handle, &r, send_done, query);
+ isc_nm_send(query->handle, &r, send_done, sendquery);
isc_refcount_increment0(&sendcount);
debug("sendcount=%" PRIuFAST32,
isc_refcount_current(&sendcount));
}
}
}
- query->waiting_connect = false;
return;
}
LOCK_LOOKUP;
- INSIST(query->waiting_connect);
-
if (eresult == ISC_R_CANCELED) {
debug("in cancel handler");
isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
l = query->lookup;
- clear_query(query);
+ query_detach(&query);
check_next_lookup(l);
UNLOCK_LOOKUP;
return;
next = NULL;
}
- clear_query(query);
+ query_detach(&query);
if (next != NULL) {
start_tcp(next);
check_next_lookup(l);
}
+ check_if_done();
+
UNLOCK_LOOKUP;
return;
}
- query->waiting_connect = false;
-
exitcode = 0;
query->handle = handle;
}
launch_next_query(query);
+ query_detach(&query);
isc_nmhandle_detach(&handle);
UNLOCK_LOOKUP;
}
result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
} while (result == ISC_R_SUCCESS);
launch_next_query(query);
+ query_detach(&query);
return (false);
doexit:
dighost_received(len, peer, query);
isc_sockaddr_t peer;
REQUIRE(DIG_VALID_QUERY(query));
+ INSIST(query->readhandle != NULL);
+ INSIST(handle == query->readhandle);
INSIST(!free_now);
debug("recv_done()");
if (eresult == ISC_R_CANCELED) {
debug("recv_done: cancel");
- clear_query(query);
+ query_detach(&query);
return;
}
isc_refcount_decrement0(&recvcount);
debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount));
- /* Could occur on timeout or interrupt */
- if (query->readhandle == NULL) {
- UNLOCK_LOOKUP;
- return;
- }
-
- INSIST(handle == query->readhandle);
-
TIME_NOW(&query->time_recv);
l = query->lookup;
newq = new_query(query->lookup, query->servname,
query->userarg);
- ISC_LIST_DEQUEUE(l->q, query, link);
ISC_LIST_PREPEND(l->q, newq, link);
- query->waiting_senddone = false;
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
- clear_query(query);
UNLOCK_LOOKUP;
start_udp(ISC_LIST_HEAD(l->q));
if ((!l->pending && !l->ns_search_only) || cancel_now) {
debug("no longer pending. Got %s", isc_result_totext(eresult));
- query->waiting_connect = false;
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
check_next_lookup(l);
UNLOCK_LOOKUP;
return;
requeue_or_update_exitcode(l);
}
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
"message");
}
if (fail) {
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
}
if (!match) {
+ /*
+ * We are still attached to query and the query->readhandle is
+ * also attached
+ */
isc_refcount_increment0(&recvcount);
isc_nm_read(handle, recv_done, query);
UNLOCK_LOOKUP;
isc_result_totext(result));
hex_dump(&b);
}
- query->waiting_connect = false;
dns_message_detach(&msg);
- clear_query(query);
+
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
expect, got);
dns_message_detach(&msg);
if (l->tcp_mode) {
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
} else {
if (!match) {
dns_message_detach(&msg);
if (l->tcp_mode) {
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
} else {
n->rdtype = l->qrdtype;
}
dns_message_detach(&msg);
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
n->rdtype = l->qrdtype;
}
dns_message_detach(&msg);
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
n->rdtype = l->qrdtype;
}
dns_message_detach(&msg);
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
UNLOCK_LOOKUP;
? "SERVFAIL reply"
: "recursion not available",
query->servname);
- clear_query(query);
+ isc_nmhandle_detach(&query->readhandle);
+ query_detach(&query);
check_next_lookup(l);
dns_message_detach(&msg);
isc_nmhandle_detach(&query->readhandle);
debug("still pending.");
}
+ isc_nmhandle_detach(&query->readhandle);
+
if (l->doing_xfr) {
if (query != l->xfr_q) {
dns_message_detach(&msg);
- isc_nmhandle_detach(&query->readhandle);
- query->waiting_connect = false;
+ query_detach(&query);
UNLOCK_LOOKUP;
return;
}
}
if (docancel) {
dns_message_detach(&msg);
- clear_query(query);
+ query_detach(&query);
cancel_lookup(l);
check_next_lookup(l);
}
dns_message_detach(&msg);
cancel_lookup(l);
}
- clear_query(query);
+ query_detach(&query);
check_next_lookup(l);
}
if (msg != NULL) {
if (current_lookup != NULL) {
for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) {
nq = ISC_LIST_NEXT(q, link);
- if (q->waiting_connect) {
- continue;
- }
debug("canceling pending query %p, belonging to %p", q,
current_lookup);
if (q->readhandle != NULL) {
debug("recvcount=%" PRIuFAST32,
isc_refcount_current(&recvcount));
}
- clear_query(q);
+ query_detach(&q);
}
for (q = ISC_LIST_HEAD(current_lookup->connecting); q != NULL;
q = nq) {
nq = ISC_LIST_NEXT(q, clink);
debug("canceling connecting query %p, belonging to %p",
q, current_lookup);
- clear_query(q);
+ query_detach(&q);
}
try_clear_lookup(current_lookup);
current_lookup = NULL;