version 1.3, 2019/01/09 16:54:59 |
version 1.4, 2019/02/24 20:01:27 |
Line 2732 send_tcp_connect(dig_query_t *query) { |
|
Line 2732 send_tcp_connect(dig_query_t *query) { |
|
return; |
return; |
} |
} |
|
|
if (specified_source && |
|
(isc_sockaddr_pf(&query->sockaddr) != |
|
isc_sockaddr_pf(&bind_address))) { |
|
printf(";; Skipping server %s, incompatible " |
|
"address family\n", query->servname); |
|
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); |
|
if (next == NULL) { |
|
printf(";; No acceptable nameservers\n"); |
|
check_next_lookup(l); |
|
return; |
|
} |
|
send_tcp_connect(next); |
|
return; |
|
} |
|
|
|
INSIST(query->sock == NULL); |
INSIST(query->sock == NULL); |
|
|
if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) { |
if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) { |
Line 2904 send_udp(dig_query_t *query) { |
|
Line 2883 send_udp(dig_query_t *query) { |
|
} |
} |
|
|
/*% |
/*% |
|
* If there are more servers available for querying within 'lookup', initiate a |
|
* TCP or UDP query to the next available server and return true; otherwise, |
|
* return false. |
|
*/ |
|
static bool |
|
try_next_server(dig_lookup_t *lookup) { |
|
dig_query_t *current_query, *next_query; |
|
|
|
current_query = lookup->current_query; |
|
if (current_query == NULL || !ISC_LINK_LINKED(current_query, link)) { |
|
return (false); |
|
} |
|
|
|
next_query = ISC_LIST_NEXT(current_query, link); |
|
if (next_query == NULL) { |
|
return (false); |
|
} |
|
|
|
debug("trying next server..."); |
|
|
|
if (lookup->tcp_mode) { |
|
send_tcp_connect(next_query); |
|
} else { |
|
send_udp(next_query); |
|
} |
|
|
|
return (true); |
|
} |
|
|
|
/*% |
* IO timeout handler, used for both connect and recv timeouts. If |
* IO timeout handler, used for both connect and recv timeouts. If |
* retries are still allowed, either resend the UDP packet or queue a |
* retries are still allowed, either resend the UDP packet or queue a |
* new TCP lookup. Otherwise, cancel the lookup. |
* new TCP lookup. Otherwise, cancel the lookup. |
Line 2911 send_udp(dig_query_t *query) { |
|
Line 2920 send_udp(dig_query_t *query) { |
|
static void |
static void |
connect_timeout(isc_task_t *task, isc_event_t *event) { |
connect_timeout(isc_task_t *task, isc_event_t *event) { |
dig_lookup_t *l = NULL; |
dig_lookup_t *l = NULL; |
dig_query_t *query = NULL, *cq; |
dig_query_t *query = NULL; |
|
|
UNUSED(task); |
UNUSED(task); |
REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE); |
REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE); |
Line 2931 connect_timeout(isc_task_t *task, isc_ev |
|
Line 2940 connect_timeout(isc_task_t *task, isc_ev |
|
return; |
return; |
} |
} |
|
|
if ((query != NULL) && (query->lookup->current_query != NULL) && |
if (try_next_server(l)) { |
ISC_LINK_LINKED(query->lookup->current_query, link) && |
if (l->tcp_mode) { |
(ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) { |
if (query->sock != NULL) { |
debug("trying next server..."); |
|
cq = query->lookup->current_query; |
|
if (!l->tcp_mode) |
|
send_udp(ISC_LIST_NEXT(cq, link)); |
|
else { |
|
if (query->sock != NULL) |
|
isc_socket_cancel(query->sock, NULL, |
isc_socket_cancel(query->sock, NULL, |
ISC_SOCKCANCEL_ALL); |
ISC_SOCKCANCEL_ALL); |
send_tcp_connect(ISC_LIST_NEXT(cq, link)); |
} else { |
|
clear_query(query); |
|
} |
} |
} |
UNLOCK_LOOKUP; |
UNLOCK_LOOKUP; |
return; |
return; |
Line 2989 connect_timeout(isc_task_t *task, isc_ev |
|
Line 2994 connect_timeout(isc_task_t *task, isc_ev |
|
} |
} |
|
|
/*% |
/*% |
|
* Called when a peer closes a TCP socket prematurely. |
|
*/ |
|
static void |
|
requeue_or_update_exitcode(dig_lookup_t *lookup) { |
|
if (lookup->eoferr == 0U) { |
|
/* |
|
* Peer closed the connection prematurely for the first time |
|
* for this lookup. Try again, keeping track of this failure. |
|
*/ |
|
dig_lookup_t *requeued_lookup = requeue_lookup(lookup, true); |
|
requeued_lookup->eoferr++; |
|
} else { |
|
/* |
|
* Peer closed the connection prematurely and it happened |
|
* previously for this lookup. Indicate an error. |
|
*/ |
|
exitcode = 9; |
|
} |
|
} |
|
|
|
/*% |
* Event handler for the TCP recv which gets the length header of TCP |
* Event handler for the TCP recv which gets the length header of TCP |
* packets. Start the next recv of length bytes. |
* packets. Start the next recv of length bytes. |
*/ |
*/ |
Line 2999 tcp_length_done(isc_task_t *task, isc_ev |
|
Line 3025 tcp_length_done(isc_task_t *task, isc_ev |
|
isc_region_t r; |
isc_region_t r; |
isc_result_t result; |
isc_result_t result; |
dig_query_t *query = NULL; |
dig_query_t *query = NULL; |
dig_lookup_t *l, *n; |
dig_lookup_t *l; |
uint16_t length; |
uint16_t length; |
|
|
REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); |
REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); |
Line 3038 tcp_length_done(isc_task_t *task, isc_ev |
|
Line 3064 tcp_length_done(isc_task_t *task, isc_ev |
|
sockcount--; |
sockcount--; |
debug("sockcount=%d", sockcount); |
debug("sockcount=%d", sockcount); |
INSIST(sockcount >= 0); |
INSIST(sockcount >= 0); |
if (sevent->result == ISC_R_EOF && l->eoferr == 0U) { |
if (sevent->result == ISC_R_EOF) { |
n = requeue_lookup(l, true); |
requeue_or_update_exitcode(l); |
n->eoferr++; |
|
} |
} |
isc_event_free(&event); |
isc_event_free(&event); |
clear_query(query); |
clear_query(query); |
Line 3399 process_cookie(dig_lookup_t *l, dns_mess |
|
Line 3424 process_cookie(dig_lookup_t *l, dns_mess |
|
} |
} |
|
|
INSIST(msg->cc_ok == 0 && msg->cc_bad == 0); |
INSIST(msg->cc_ok == 0 && msg->cc_bad == 0); |
if (optlen >= len && optlen >= 8U) { |
if (len >= 8 && optlen >= 8U) { |
if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) { |
if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) { |
msg->cc_ok = 1; |
msg->cc_ok = 1; |
} else { |
} else { |
Line 3486 recv_done(isc_task_t *task, isc_event_t |
|
Line 3511 recv_done(isc_task_t *task, isc_event_t |
|
dig_lookup_t *n, *l; |
dig_lookup_t *n, *l; |
bool docancel = false; |
bool docancel = false; |
bool match = true; |
bool match = true; |
|
bool done_process_opt = false; |
unsigned int parseflags; |
unsigned int parseflags; |
dns_messageid_t id; |
dns_messageid_t id; |
unsigned int msgflags; |
unsigned int msgflags; |
Line 3541 recv_done(isc_task_t *task, isc_event_t |
|
Line 3567 recv_done(isc_task_t *task, isc_event_t |
|
debug("sockcount=%d", sockcount); |
debug("sockcount=%d", sockcount); |
INSIST(sockcount >= 0); |
INSIST(sockcount >= 0); |
} |
} |
if (sevent->result == ISC_R_EOF && l->eoferr == 0U) { |
if (sevent->result == ISC_R_EOF) { |
n = requeue_lookup(l, true); |
requeue_or_update_exitcode(l); |
n->eoferr++; |
|
} |
} |
isc_event_free(&event); |
isc_event_free(&event); |
clear_query(query); |
clear_query(query); |
Line 3780 recv_done(isc_task_t *task, isc_event_t |
|
Line 3805 recv_done(isc_task_t *task, isc_event_t |
|
UNLOCK_LOOKUP; |
UNLOCK_LOOKUP; |
return; |
return; |
} |
} |
|
done_process_opt = true; |
} |
} |
if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || |
if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || |
(check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) |
(check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) |
Line 3869 recv_done(isc_task_t *task, isc_event_t |
|
Line 3895 recv_done(isc_task_t *task, isc_event_t |
|
} |
} |
} |
} |
|
|
if (l->cookie != NULL) { |
if (!done_process_opt) { |
if (msg->opt == NULL) |
if (l->cookie != NULL) { |
printf(";; expected opt record in response\n"); |
if (msg->opt == NULL) { |
else |
printf(";; expected opt record in response\n"); |
|
} else { |
|
process_opt(l, msg); |
|
} |
|
} else if (l->sendcookie && msg->opt != NULL) { |
process_opt(l, msg); |
process_opt(l, msg); |
} else if (l->sendcookie && msg->opt != NULL) |
} |
process_opt(l, msg); |
} |
if (!l->doing_xfr || l->xfr_q == query) { |
if (!l->doing_xfr || l->xfr_q == query) { |
if (msg->rcode == dns_rcode_nxdomain && |
if (msg->rcode == dns_rcode_nxdomain && |
(l->origin != NULL || l->need_search)) { |
(l->origin != NULL || l->need_search)) { |