diff --git a/configure.ac b/configure.ac index 0807f012..82a27f14 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -AC_PREREQ([2.56]) +AC_PREREQ([2.68]) AC_CONFIG_MACRO_DIRS([m4]) sinclude(./m4/acx_openssl.m4) sinclude(./m4/acx_getaddrinfo.m4) diff --git a/src/dict.c b/src/dict.c index 8e7eec8f..e7294e62 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1053,7 +1053,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, strcmp(item->node.key, "status") == 0 || strcmp(item->node.key, "append_name") == 0 || strcmp(item->node.key, "follow_redirects") == 0 || - strcmp(item->node.key, "transport") == 0 || + strcmp(item->node.key, "transport") == 0 || strcmp(item->node.key, "resolution_type") == 0 || strcmp(item->node.key, "tls_authentication") == 0 ) && (strval = diff --git a/src/dnssec.c b/src/dnssec.c index 95c8cbbf..2e6425fb 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -2776,19 +2776,13 @@ static size_t count_outstanding_requests(chain_head *head) count += node->lock; - if (node->dnskey_req && - node->dnskey_req->state != NET_REQ_FINISHED && - node->dnskey_req->state != NET_REQ_CANCELED) + if (!_getdns_netreq_finished(node->dnskey_req)) count++; - if (node->ds_req && - node->ds_req->state != NET_REQ_FINISHED && - node->ds_req->state != NET_REQ_CANCELED) + if (!_getdns_netreq_finished(node->ds_req)) count++; - if (node->soa_req && - node->soa_req->state != NET_REQ_FINISHED && - node->soa_req->state != NET_REQ_CANCELED) + if (!_getdns_netreq_finished(node->soa_req)) count++; } return count + count_outstanding_requests(head->next); diff --git a/src/general.c b/src/general.c index 4b80dbdd..9de39116 100644 --- a/src/general.c +++ b/src/general.c @@ -104,8 +104,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) int results_found = 0, r; for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) - if (netreq->state != NET_REQ_FINISHED && - netreq->state != NET_REQ_CANCELED) + if (!_getdns_netreq_finished(netreq)) return; else if (netreq->response_len > 0) results_found = 1; diff --git a/src/stub.c b/src/stub.c index 61e18b57..4aa14dae 100644 --- a/src/stub.c +++ b/src/stub.c @@ -91,6 +91,7 @@ static int upstream_connect(getdns_upstream *upstream, static int fallback_on_write(getdns_network_req *netreq); static void stub_timeout_cb(void *userarg); +static uint64_t _getdns_get_time_as_uintt64(); /*****************************/ /* General utility functions */ /*****************************/ @@ -495,14 +496,17 @@ stub_cleanup(getdns_network_req *netreq) } static int -tls_cleanup(getdns_upstream *upstream) +tls_cleanup(getdns_upstream *upstream, int handshake_fail) { DEBUG_STUB("%s %-35s: FD: %d\n", STUB_DEBUG_CLEANUP, __FUNCTION__, upstream->fd); if (upstream->tls_obj != NULL) SSL_free(upstream->tls_obj); upstream->tls_obj = NULL; - upstream->tls_hs_state = GETDNS_HS_FAILED; + /* This will prevent the connection from being tried again for the cases + where we know it didn't work. Otherwise leave it to try again.*/ + if (handshake_fail) + upstream->tls_hs_state = GETDNS_HS_FAILED; /* Reset timeout on failure*/ GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER, @@ -514,6 +518,8 @@ tls_cleanup(getdns_upstream *upstream) static void upstream_erred(getdns_upstream *upstream) { + DEBUG_STUB("%s %-35s: FD: %d\n", + STUB_DEBUG_CLEANUP, __FUNCTION__, upstream->fd); getdns_network_req *netreq; while ((netreq = upstream->write_queue)) { @@ -559,12 +565,12 @@ stub_timeout_cb(void *userarg) stub_next_upstream(netreq); stub_cleanup(netreq); if (netreq->fd >= 0) close(netreq->fd); - if (netreq->owner->user_callback) + netreq->state = NET_REQ_TIMED_OUT; + if (netreq->owner->user_callback) { + netreq->debug_end_time = _getdns_get_time_as_uintt64(); (void) _getdns_context_request_timed_out(netreq->owner); - else { - netreq->state = NET_REQ_FINISHED; + } else _getdns_check_dns_req_complete(netreq->owner); - } } @@ -588,7 +594,7 @@ upstream_tls_timeout_cb(void *userarg) DEBUG_STUB("%s %-35s: FD: %d\n", STUB_DEBUG_CLEANUP, __FUNCTION__, upstream->fd); /* Clean up and trigger a write to let the fallback code to its job */ - tls_cleanup(upstream); + tls_cleanup(upstream, 1); /* Need to handle the case where the far end doesn't respond to a * TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853). @@ -616,7 +622,7 @@ stub_tls_timeout_cb(void *userarg) DEBUG_STUB("%s %-35s: MSG: %p\n", STUB_DEBUG_CLEANUP, __FUNCTION__, netreq); /* Clean up and trigger a write to let the fallback code to its job */ - tls_cleanup(upstream); + tls_cleanup(upstream, 0); /* Need to handle the case where the far end doesn't respond to a * TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853). @@ -1021,7 +1027,7 @@ tls_do_handshake(getdns_upstream *upstream) DEBUG_STUB("%s %-35s: FD: %d Handshake failed %d\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__, upstream->fd, want); - return tls_cleanup(upstream); + return tls_cleanup(upstream, 1); } } upstream->tls_hs_state = GETDNS_HS_DONE; @@ -1069,7 +1075,7 @@ tls_connected(getdns_upstream* upstream) int q = tcp_connected(upstream); if (q != 0) { if (q == STUB_TCP_ERROR) - tls_cleanup(upstream); + tls_cleanup(upstream, 0); return q; } @@ -1798,8 +1804,8 @@ upstream_reschedule_events(getdns_upstream *upstream, size_t idle_timeout) { GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER, &upstream->event); else { - DEBUG_STUB("%s %-35s: FD: %d Connection idle \n", - STUB_DEBUG_SCHEDULE, __FUNCTION__, upstream->fd); + DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n", + STUB_DEBUG_SCHEDULE, __FUNCTION__, upstream->fd, (int)idle_timeout); upstream->event.timeout_cb = upstream_idle_timeout_cb; if (upstream->tcp.write_error != 0) idle_timeout = 0; @@ -1890,7 +1896,6 @@ _getdns_submit_stub_request(getdns_network_req *netreq) case GETDNS_TRANSPORT_TLS: case GETDNS_TRANSPORT_TCP: upstream_schedule_netreq(netreq->upstream, netreq); - /* TODO[TLS]: Change scheduling for sync calls. */ /* For TLS, set a short timeout to catch setup problems. This is reset when the connection is successful.*/ GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -1958,8 +1963,7 @@ _getdns_submit_stub_request(getdns_network_req *netreq) GETDNS_SCHEDULE_EVENT( dnsreq->loop, -1, - ( transport == GETDNS_TRANSPORT_TLS - ? dnsreq->context->timeout /2 : dnsreq->context->timeout), + dnsreq->context->timeout, getdns_eventloop_event_init( &netreq->event, netreq, NULL, NULL, diff --git a/src/test/check_getdns_context_set_dns_transport.h b/src/test/check_getdns_context_set_dns_transport.h index c1135045..1985eac6 100644 --- a/src/test/check_getdns_context_set_dns_transport.h +++ b/src/test/check_getdns_context_set_dns_transport.h @@ -131,6 +131,7 @@ struct getdns_dict *extensions = getdns_dict_create(); uint32_t tc; uint32_t transport; + uint32_t mode; /* Note that stricly this test just establishes that the requested transport and the reported transport are consistent, it does not guarentee which @@ -157,6 +158,9 @@ ASSERT_RC(getdns_dict_get_int(response, "/call_reporting/0/transport", &transport), GETDNS_RETURN_GOOD, "Failed to extract \"transport\""); ASSERT_RC(transport, GETDNS_TRANSPORT_UDP, "Query did not go over UDP"); + ASSERT_RC(getdns_dict_get_int(response, "/call_reporting/0/resolution_type", &mode), + GETDNS_RETURN_GOOD, "Failed to extract \"resolution_type\""); + ASSERT_RC(mode, GETDNS_RESOLUTION_STUB, "Query did not use stub mode"); ASSERT_RC(getdns_dict_get_int(response, "/replies_tree/0/header/tc", &tc), GETDNS_RETURN_GOOD, "Failed to extract \"tc\""); ASSERT_RC(tc, 1, "Packet not trucated as expected"); @@ -208,6 +212,7 @@ struct getdns_dict *response = NULL; struct getdns_dict *extensions = getdns_dict_create(); uint32_t status; + uint32_t mode; uint32_t tc; /* Recursive mode does not report the transport used and does not answer @@ -239,13 +244,18 @@ CONTEXT_CREATE(TRUE); /* Re-do over TCP */ + ASSERT_RC(getdns_dict_set_int(extensions,"return_call_reporting", GETDNS_EXTENSION_TRUE), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); ASSERT_RC(getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY), GETDNS_RETURN_GOOD, "Return code from getdns_context_set_dns_transport()"); ASSERT_RC(getdns_context_set_edns_maximum_udp_payload_size(context, 512), GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_maximum_udp_payload_size()"); ASSERT_RC(getdns_general_sync(context, "getdnsapi.net", 48, extensions, &response), GETDNS_RETURN_GOOD, "Return code from getdns_general_sync()"); - + + ASSERT_RC(getdns_dict_get_int(response, "/call_reporting/0/resolution_type", &mode), + GETDNS_RETURN_GOOD, "Failed to extract \"resolution_type\""); + ASSERT_RC(mode, GETDNS_RESOLUTION_RECURSING, "Query did not use Recursive mode"); ASSERT_RC(getdns_dict_get_int(response, "/replies_tree/0/header/tc", &tc), GETDNS_RETURN_GOOD, "Failed to extract \"tc\""); ASSERT_RC(tc, 0, "Packet trucated - not as expected"); diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 962f496f..a1feab82 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -1130,7 +1130,7 @@ void servfail(dns_msg *msg, getdns_dict **resp_p) return; if (!getdns_dict_get_dict(msg->query, "header", &dict)) getdns_dict_set_dict(*resp_p, "header", dict); - if (!getdns_dict_get_dict(msg->query, "question", &dict)); + if (!getdns_dict_get_dict(msg->query, "question", &dict)) getdns_dict_set_dict(*resp_p, "question", dict); (void) getdns_dict_set_int( *resp_p, "/header/rcode", GETDNS_RCODE_SERVFAIL); @@ -1219,26 +1219,13 @@ void incoming_request_handler(getdns_context *context, getdns_bindata *qname; char *qname_str = NULL; uint32_t qtype; + uint32_t qclass; getdns_return_t r; getdns_dict *header; uint32_t n; getdns_list *list; getdns_transaction_t transaction_id; - getdns_dict *qext; - dns_msg *msg; - getdns_dict *response = NULL; - - assert(context); - assert(request); - - if (!(msg = malloc(sizeof(dns_msg)))) { - fprintf(stderr, "Could not handle incoming query due to " - "memory error\n"); - getdns_dict_destroy(request); - return; - } - msg->query = request; - msg->request_id = request_id; + getdns_dict *qext = NULL; if (!query_extensions_spc && !(query_extensions_spc = getdns_dict_create())) @@ -1319,6 +1306,14 @@ void incoming_request_handler(getdns_context *context, fprintf(stderr, "Could get qtype from query: %s\n", getdns_get_errorstr_by_id(r)); + else if ((r=getdns_dict_get_int(msg->query,"/question/qclass",&qclass))) + fprintf(stderr, "Could get qclass from query: %s\n", + getdns_get_errorstr_by_id(r)); + + else if ((r = getdns_dict_set_int(qext, "specify_class", qclass))) + fprintf(stderr, "Could set class from query: %s\n", + getdns_get_errorstr_by_id(r)); + else if ((r = getdns_general(context, qname_str, qtype, qext, msg, &transaction_id, request_cb))) fprintf(stderr, "Could not schedule query: %s\n", diff --git a/src/test/tests_transports.sh b/src/test/tests_transports.sh index 68b80568..13e5b6b6 100755 --- a/src/test/tests_transports.sh +++ b/src/test/tests_transports.sh @@ -2,7 +2,9 @@ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) SERVER_IP="8.8.8.8" +SERVER_IPv6="2001:4860:4860::8888" TLS_SERVER_IP="185.49.141.38~getdnsapi.net" +TLS_SERVER_IPv6="2a04:b900:0:100::38~getdnsapi.net" TLS_SERVER_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S=" TLS_SERVER_WRONG_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc1S=" GOOD_RESULT_SYNC="Status was: At least one response was returned" @@ -62,21 +64,22 @@ usage () { echo " -t server configured for TLS, TCP and UDP" echo " (This must include the hostname e.g. 185.49.141.38~getdnsapi.net)" echo " -k SPKI pin for server configured for TLS, TCP and UDP" + echo " -i Use IPv6 addresses (when using default servers)" } -while getopts ":p:s:t:k:dh" opt; do +while getopts ":p:s:t:k:idh" opt; do case $opt in - d ) set -x ;; + d ) set -x ; echo "DEBUG mode set" ;; p ) DIR=$OPTARG ;; s ) SERVER_IP=$OPTARG ; echo "Setting server to $OPTARG" ;; t ) TLS_SERVER_IP=$OPTARG ; echo "Setting TLS server to $OPTARG" ;; k ) TLS_SERVER_KEY=$OPTARG ; echo "Setting TLS server key to $OPTARG" ;; + i ) SERVER_IP=$SERVER_IPv6; TLS_SERVER_IP=$TLS_SERVER_IPv6 ; echo "Using IPv6" ;; h ) usage ; exit ;; esac done TLS_SERVER_IP_NO_NAME=`echo ${TLS_SERVER_IP%~*}` -echo $TLS_SERVER_IP_NO_NAME TLS_SERVER_IP_WRONG_NAME=`echo ${TLS_SERVER_IP::${#TLS_SERVER_IP}-1}` GOOD_QUERIES=( @@ -100,7 +103,7 @@ NOT_AVAILABLE_QUERIES=( "-s -A -q getdnsapi.net -l L @${SERVER_IP}" "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME}" "-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME}" -"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} ${TLS_SERVER_WRONG_KEY}") +"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_WRONG_KEY}\"") echo "Starting transport test" diff --git a/src/types-internal.h b/src/types-internal.h index f63fde13..6f7d99ea 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -154,10 +154,12 @@ priv_getdns_context_mf(getdns_context *context); typedef enum network_req_state_enum { - NET_REQ_NOT_SENT, - NET_REQ_IN_FLIGHT, - NET_REQ_FINISHED, - NET_REQ_CANCELED + NET_REQ_NOT_SENT = 0, + NET_REQ_IN_FLIGHT = 1, + NET_REQ_FINISHED = 2, /* Finish type in bits 2 and 3 */ + NET_REQ_CANCELED = 6, /* 2 + (1 << 2) */ + NET_REQ_TIMED_OUT = 10, /* 2 + (2 << 2) */ + NET_REQ_ERRORED = 14 /* 2 + (3 << 2) */ } network_req_state; @@ -255,11 +257,12 @@ typedef struct getdns_network_req uint8_t *response; size_t wire_data_sz; uint8_t wire_data[]; - - } getdns_network_req; +static inline int _getdns_netreq_finished(getdns_network_req *req) +{ return !req || (req->state & NET_REQ_FINISHED); } + /** * dns request - manages a number of network requests and * the initial data passed to getdns_general diff --git a/src/util-internal.c b/src/util-internal.c index aa255e0e..3a70f81c 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -812,12 +812,19 @@ _getdns_create_call_reporting_dict( getdns_dict_destroy(netreq_debug); return NULL; - } else if (!netreq->upstream) - + } else if (!netreq->upstream) { + if (getdns_dict_set_int( netreq_debug, "resolution_type", GETDNS_RESOLUTION_RECURSING)) { + getdns_dict_destroy(netreq_debug); + return NULL; + } /* Nothing more for full recursion */ return netreq_debug; + } - + if (getdns_dict_set_int( netreq_debug, "resolution_type", GETDNS_RESOLUTION_STUB)) { + getdns_dict_destroy(netreq_debug); + return NULL; + } /* Stub resolver debug data */ _getdns_sockaddr_to_dict( context, &netreq->upstream->addr, &address_debug); @@ -1102,6 +1109,18 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) for ( netreq_p = completed_request->netreqs ; (netreq = *netreq_p) ; netreq_p++) { + if (call_reporting && ( netreq->response_len + || netreq->state == NET_REQ_TIMED_OUT)) { + if (!(netreq_debug = + _getdns_create_call_reporting_dict(context,netreq))) + goto error; + + if (_getdns_list_append_this_dict( + call_reporting, netreq_debug)) + goto error; + + netreq_debug = NULL; + } if (! netreq->response_len) continue; @@ -1164,20 +1183,6 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_dict_destroy(reply); goto error; } - - if (call_reporting) { - if (!(netreq_debug = - _getdns_create_call_reporting_dict(context,netreq))) - goto error; - - if (_getdns_list_append_this_dict( - call_reporting, netreq_debug)) { - - getdns_dict_destroy(netreq_debug); - goto error; - } - } - if (_getdns_list_append_const_bindata(replies_full, netreq->response_len, netreq->response)) goto error;