From c0187a19ea0da5332b66cc4fba5e00d96ad96705 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Wed, 15 Jun 2016 17:05:58 +0100 Subject: [PATCH] Quick fix for TLS timeouts not re-using a connection. Better solution is needed. Also minor fixes in getdns_query: - spurious semicolon (caused build warning) - build warning for initialised variable - have getdns_query honour the CLASS in the incoming query --- src/stub.c | 25 ++++++++++++++----------- src/test/getdns_query.c | 13 +++++++++++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/stub.c b/src/stub.c index 61e18b57..2962b3fb 100644 --- a/src/stub.c +++ b/src/stub.c @@ -495,14 +495,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 +517,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)) { @@ -588,7 +593,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 +621,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 +1026,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 +1074,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 +1803,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 +1895,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 +1962,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/getdns_query.c b/src/test/getdns_query.c index 9fd025d6..640e0b59 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -2207,7 +2207,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); @@ -2332,12 +2332,13 @@ getdns_return_t schedule_request(dns_msg *msg) 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; + getdns_dict *qext = NULL; if (!query_extensions_spc && !(query_extensions_spc = getdns_dict_create())) @@ -2418,6 +2419,14 @@ getdns_return_t schedule_request(dns_msg *msg) 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",