167 lines
5.0 KiB
Diff
167 lines
5.0 KiB
Diff
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
|
|
index 7e88b6b63c..768c4e56da 100644
|
|
--- a/bin/dig/dighost.c
|
|
+++ b/bin/dig/dighost.c
|
|
@@ -1577,6 +1577,31 @@ check_if_done(void) {
|
|
}
|
|
}
|
|
|
|
+
|
|
+/*%
|
|
+ * Check if we're done with all the queries in the lookup, except for
|
|
+ * the `except_q` query (can be NULL if no exception is required).
|
|
+ * Expects `l` to be a valid and locked lookup.
|
|
+ */
|
|
+static bool
|
|
+check_if_queries_done(dig_lookup_t *l, dig_query_t *except_q) {
|
|
+ dig_query_t *q = ISC_LIST_HEAD(l->q);
|
|
+
|
|
+ debug("check_if_queries_done(%p)", l);
|
|
+
|
|
+ while (q != NULL) {
|
|
+ if (!q->started || q->waiting_connect || q->waiting_senddone || q->pending_free) {
|
|
+ if (!q->canceled && q != except_q) {
|
|
+ debug("there is a pending query %p", q);
|
|
+ return (false);
|
|
+ }
|
|
+ }
|
|
+ q = ISC_LIST_NEXT(q, link);
|
|
+ }
|
|
+
|
|
+ return (true);
|
|
+}
|
|
+
|
|
/*%
|
|
* Clear out a query when we're done with it. WARNING: This routine
|
|
* WILL invalidate the query pointer.
|
|
@@ -2563,7 +2588,6 @@ setup_lookup(dig_lookup_t *lookup) {
|
|
query->waiting_senddone = false;
|
|
query->pending_free = false;
|
|
query->recv_made = false;
|
|
- query->first_pass = true;
|
|
query->first_soa_rcvd = false;
|
|
query->second_rr_rcvd = false;
|
|
query->first_repeat_rcvd = false;
|
|
@@ -2663,6 +2687,7 @@ cancel_lookup(dig_lookup_t *lookup) {
|
|
while (query != NULL) {
|
|
REQUIRE(DIG_VALID_QUERY(query));
|
|
next = ISC_LIST_NEXT(query, link);
|
|
+ query->canceled = true;
|
|
if (query->sock != NULL) {
|
|
isc_socket_cancel(query->sock, global_task,
|
|
ISC_SOCKCANCEL_ALL);
|
|
@@ -2905,6 +2930,12 @@ send_udp(dig_query_t *query) {
|
|
return;
|
|
}
|
|
|
|
+ query->started = true;
|
|
+ if (atomic_load(&cancel_now)) {
|
|
+ return;
|
|
+ }
|
|
+ INSIST(!free_now);
|
|
+
|
|
result = isc_socket_create(socketmgr,
|
|
isc_sockaddr_pf(&query->sockaddr),
|
|
isc_sockettype_udp, &query->sock);
|
|
@@ -3031,6 +3062,10 @@ connect_timeout(isc_task_t *task, isc_event_t *event) {
|
|
clear_query(query);
|
|
}
|
|
}
|
|
+ if (check_if_queries_done(l, query)) {
|
|
+ cancel_lookup(l);
|
|
+ check_next_lookup(l);
|
|
+ }
|
|
UNLOCK_LOOKUP;
|
|
return;
|
|
}
|
|
@@ -3286,6 +3321,14 @@ connect_done(isc_task_t *task, isc_event_t *event) {
|
|
query = sevent->ev_arg;
|
|
REQUIRE(DIG_VALID_QUERY(query));
|
|
|
|
+ query->started = true;
|
|
+
|
|
+ if (atomic_load(&cancel_now)) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ INSIST(!free_now);
|
|
+
|
|
INSIST(query->waiting_connect);
|
|
|
|
query->waiting_connect = false;
|
|
@@ -4002,6 +4045,9 @@ recv_done(isc_task_t *task, isc_event_t *event) {
|
|
: "recursion not available",
|
|
query->servname);
|
|
clear_query(query);
|
|
+ if (check_if_queries_done(l, query)) {
|
|
+ cancel_lookup(l);
|
|
+ }
|
|
check_next_lookup(l);
|
|
dns_message_detach(&msg);
|
|
isc_event_free(&event);
|
|
@@ -4126,7 +4172,12 @@ recv_done(isc_task_t *task, isc_event_t *event) {
|
|
l->trace_root = false;
|
|
usesearch = false;
|
|
} else {
|
|
+ /*
|
|
+ * This is a query in the followup lookup
|
|
+ */
|
|
dighost_printmessage(query, &b, msg, true);
|
|
+
|
|
+ docancel = check_if_queries_done(l, query);
|
|
}
|
|
}
|
|
}
|
|
@@ -4305,6 +4356,7 @@ cancel_all(void) {
|
|
nq = ISC_LIST_NEXT(q, link);
|
|
debug("canceling pending query %p, belonging to %p", q,
|
|
current_lookup);
|
|
+ q->canceled = true;
|
|
if (q->sock != NULL) {
|
|
isc_socket_cancel(q->sock, NULL,
|
|
ISC_SOCKCANCEL_ALL);
|
|
@@ -4317,6 +4369,7 @@ cancel_all(void) {
|
|
nq = ISC_LIST_NEXT(q, clink);
|
|
debug("canceling connecting query %p, belonging to %p",
|
|
q, current_lookup);
|
|
+ q->canceled = true;
|
|
if (q->sock != NULL) {
|
|
isc_socket_cancel(q->sock, NULL,
|
|
ISC_SOCKCANCEL_ALL);
|
|
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
|
|
index 9e6035255f..48c6262008 100644
|
|
--- a/bin/dig/include/dig/dig.h
|
|
+++ b/bin/dig/include/dig/dig.h
|
|
@@ -166,9 +166,9 @@ struct dig_lookup {
|
|
struct dig_query {
|
|
unsigned int magic;
|
|
dig_lookup_t *lookup;
|
|
- bool waiting_connect, pending_free, waiting_senddone, first_pass,
|
|
+ bool waiting_connect, pending_free, waiting_senddone, started,
|
|
first_soa_rcvd, second_rr_rcvd, first_repeat_rcvd, recv_made,
|
|
- warn_id, timedout;
|
|
+ warn_id, timedout, canceled;
|
|
uint32_t first_rr_serial;
|
|
uint32_t second_rr_serial;
|
|
uint32_t msg_count;
|
|
diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh
|
|
index 22933c7f9d..4b0ed7db10 100644
|
|
--- a/bin/tests/system/digdelv/tests.sh
|
|
+++ b/bin/tests/system/digdelv/tests.sh
|
|
@@ -1043,6 +1043,15 @@ if [ -x "$DIG" ] ; then
|
|
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
|
status=$((status+ret))
|
|
|
|
+ # See [GL #3248] for more information
|
|
+ n=$((n+1))
|
|
+ echo_i "check that dig correctly refuses to use a server with a IPv4 mapped IPv6 address after failing with a regular IP address ($n)"
|
|
+ ret=0
|
|
+ dig_with_opts +nomapped @10.53.0.8 @::ffff:10.53.0.8 a.example > dig.out.test$n 2>&1 || ret=1
|
|
+ grep -F ";; Skipping mapped address" dig.out.test$n > /dev/null || ret=1
|
|
+ grep -F ";; No acceptable nameservers" dig.out.test$n > /dev/null || ret=1
|
|
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
|
+ status=$((status+ret))
|
|
else
|
|
echo_i "$DIG is needed, so skipping these dig tests"
|
|
fi
|