Eat incoming garbage on statefull transports

Can deal with timed out queries that are answered anyway.
+ reset the upstream on failure always
  (since requests are rescheduled for fallback by upstream_failed now anyway)
This commit is contained in:
Willem Toorop 2017-10-17 16:58:01 +02:00
parent fa597399e2
commit eedd1a1448
4 changed files with 49 additions and 43 deletions

View File

@ -800,6 +800,10 @@ _getdns_upstream_reset(getdns_upstream *upstream)
/* Now TLS stuff*/
upstream->tls_auth_state = GETDNS_AUTH_NONE;
if (upstream->event.ev && upstream->loop) {
upstream->loop->vmt->clear(
upstream->loop, &upstream->event);
}
if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj);
@ -2769,11 +2773,14 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
struct addrinfo hints;
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(upstream_list, GETDNS_RETURN_INVALID_PARAMETER);
r = getdns_list_get_length(upstream_list, &count);
if (count == 0 || r != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
if ( !upstream_list
|| (r = getdns_list_get_length(upstream_list, &count))
|| count == 0) {
_getdns_upstreams_dereference(context->upstreams);
context->upstreams = NULL;
dispatch_updated(context,
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */

View File

@ -551,10 +551,7 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner);
}
if (during_setup == 0)
return;
else if (during_setup > 0)
if (during_setup > 0)
_getdns_upstream_reset(upstream);
else
_getdns_upstream_shutdown(upstream);
@ -2118,7 +2115,13 @@ upstream_reschedule_events(getdns_upstream *upstream) {
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SCHEDULE,
__FUNC__, upstream->fd);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->event.ev)
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->fd == -1 || !( upstream->conn_state == GETDNS_CONN_SETUP
|| upstream->conn_state == GETDNS_CONN_OPEN ))
return;
if (!upstream->write_queue && upstream->event.write_cb) {
upstream->event.write_cb = NULL;
}
@ -2138,16 +2141,11 @@ upstream_reschedule_events(getdns_upstream *upstream) {
DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n",
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd,
(int)upstream->keepalive_timeout);
/* TODO: Schedule a read also anyway,
* to digest timed out answers.
* Dont forget to schedule with upstream->fd then!
*
* upstream->event.read_cb = upstream_read_cb;
*/
upstream->event.read_cb = upstream_read_cb;
upstream->event.timeout_cb = upstream_idle_timeout_cb;
GETDNS_SCHEDULE_EVENT(upstream->loop, -1,
( upstream->conn_state == GETDNS_CONN_OPEN
? upstream->keepalive_timeout : 0), &upstream->event);
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
upstream->keepalive_timeout, &upstream->event);
}
}

View File

@ -116,30 +116,24 @@ getdns_sync_data_cleanup(getdns_sync_data *data)
upstream = &ctxt->upstreams->upstreams[i];
if (upstream->loop != &data->context->sync_eventloop.loop)
continue;
if (upstream->event.read_cb || upstream->event.write_cb) {
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
} else if (upstream->event.timeout_cb) {
/* Timeout's at upstream are idle-timeouts only.
* They should be fired on completion of the
* synchronous request.
*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->conn_state != GETDNS_CONN_OPEN ||
upstream->keepalive_timeout == 0)
(*upstream->event.timeout_cb)(upstream->event.userarg);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->event.timeout_cb &&
( upstream->conn_state != GETDNS_CONN_OPEN
|| upstream->keepalive_timeout == 0)) {
(*upstream->event.timeout_cb)(upstream->event.userarg);
upstream->event.timeout_cb = NULL;
}
upstream->loop = data->context->extension;
upstream->is_sync_loop = 0;
if (upstream->event.read_cb || upstream->event.write_cb)
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
TIMEOUT_FOREVER, &upstream->event);
else if (upstream->event.timeout_cb &&
upstream->conn_state == GETDNS_CONN_OPEN &&
upstream->keepalive_timeout != 0) {
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
upstream->keepalive_timeout, &upstream->event);
if ( upstream->event.read_cb || upstream->event.write_cb
|| upstream->event.timeout_cb) {
GETDNS_SCHEDULE_EVENT(upstream->loop,
( upstream->event.read_cb
|| upstream->event.write_cb ? upstream->fd : -1),
( upstream->event.timeout_cb
? upstream->keepalive_timeout : TIMEOUT_FOREVER ),
&upstream->event);
}
}
}

View File

@ -1279,7 +1279,8 @@ void read_line_cb(void *userarg)
if (listen_count)
(void) getdns_context_set_listen_addresses(
context, NULL, NULL, NULL);
(void) getdns_context_set_idle_timeout(context, 0);
(void) getdns_context_set_upstream_recursive_servers(
context, NULL);
return;
}
if (query_file && verbosity)
@ -1678,16 +1679,22 @@ static void stubby_log(void *userarg, uint64_t system,
#ifdef GETDNS_ON_WINDOWS
time_t tsec;
if (!verbosity)
return;
gettimeofday(&tv, NULL);
tsec = (time_t) tv.tv_sec;
gmtime_s(&tm, (const time_t *) &tsec);
#else
if (!verbosity)
return;
gettimeofday(&tv, NULL);
gmtime_r(&tv.tv_sec, &tm);
#endif
strftime(buf, 10, "%H:%M:%S", &tm);
(void)userarg; (void)system; (void)level;
(void) fprintf(stderr, "[%s.%.6d] STUBBY: ", buf, (int)tv.tv_usec);
(void) fprintf(stderr, "[%s.%.6d] UPSTREAM ", buf, (int)tv.tv_usec);
(void) vfprintf(stderr, fmt, ap);
}
@ -1741,10 +1748,10 @@ main(int argc, char **argv)
(void) parse_config_file(home_stubby_conf_fn, 0);
}
clear_listen_list_on_arg = 1;
(void) getdns_context_set_logfunc(context, NULL,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
}
(void) getdns_context_set_logfunc(context, NULL,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
if ((r = parse_args(argc, argv)))
goto done_destroy_context;
clear_listen_list_on_arg = 0;