Merge pull request #265 from saradickinson/feature/new_settings

Feature/new settings
This commit is contained in:
wtoorop 2017-03-20 22:25:52 +01:00 committed by GitHub
commit 52e3d2e1b0
9 changed files with 253 additions and 43 deletions

View File

@ -73,6 +73,9 @@ static struct const_info consts_info[] = {
{ 619, "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT },
{ 620, "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT },
{ 621, "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT },
{ 622, "GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS", GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT },
{ 623, "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT },
{ 624, "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT },
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
@ -157,9 +160,12 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
{ "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 },
{ "GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS", 622 },
{ "GETDNS_CONTEXT_CODE_SUFFIX", 608 },
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
{ "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 },
{ "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 },
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
{ "GETDNS_DNSSEC_BOGUS", 401 },

View File

@ -89,9 +89,6 @@ typedef unsigned short in_port_t;
#define GETDNS_STR_PORT_ZERO "0"
#define GETDNS_STR_PORT_DNS "53"
#define GETDNS_STR_PORT_DNS_OVER_TLS "853"
/* How long to wait in seconds before re-trying a connection based backed-off
upstream. Using 1 hour for all transports - based on RFC7858 value for for TLS.*/
#define BACKOFF_RETRY 3600
#ifdef HAVE_PTHREAD
static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER;
@ -657,6 +654,9 @@ upstreams_create(getdns_context *context, size_t size)
r->referenced = 1;
r->count = 0;
r->current_udp = 0;
r->current_stateful = 0;
r->tls_backoff_time = context->tls_backoff_time;
r->tls_connection_retries = context->tls_connection_retries;
return r;
}
@ -731,17 +731,17 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
if (upstream->tls_auth_state > upstream->best_tls_auth_state)
upstream->best_tls_auth_state = upstream->tls_auth_state;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->responses_received, (int)upstream->responses_timeouts,
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->total_responses, (int)upstream->total_timeouts,
_getdns_auth_str(upstream->best_tls_auth_state));
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->conn_completed, (int)upstream->conn_setup_failed,
@ -753,16 +753,16 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
Leave choice between working upstreams to the stub.
This back-off should be time based for TLS according to RFC7858. For now,
use the same basis if we simply can't get TCP service either.*/
uint16_t conn_retries = upstream->upstreams->tls_connection_retries;
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
if (upstream->conn_setup_failed >= GETDNS_CONN_ATTEMPTS ||
(upstream->conn_shutdowns >= GETDNS_CONN_ATTEMPTS*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0) ||
(upstream->conn_completed >= GETDNS_CONN_ATTEMPTS &&
if (upstream->conn_setup_failed >= conn_retries
|| (upstream->conn_shutdowns >= conn_retries*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0)
|| (upstream->conn_completed >= conn_retries &&
upstream->total_responses == 0 &&
upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) {
upstream->conn_state = GETDNS_CONN_BACKOFF;
upstream->conn_retry_time = time(NULL) + BACKOFF_RETRY;
upstream->conn_retry_time = time(NULL) + upstream->upstreams->tls_backoff_time;
upstream->total_responses = 0;
upstream->total_timeouts = 0;
upstream->conn_completed = 0;
@ -770,7 +770,7 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
upstream->conn_shutdowns = 0;
upstream->conn_backoffs++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : !Backing off this upstream - Will retry as new upstream at %s",
DEBUG_DAEMON("%s %-40s : !Backing off this upstream - Will retry as new upstream at %s",
STUB_DEBUG_DAEMON, upstream->addr_str,
asctime(gmtime(&upstream->conn_retry_time)));
#endif
@ -1480,6 +1480,9 @@ getdns_context_create_with_extended_memory_functions(
goto error;
result->tls_auth = GETDNS_AUTHENTICATION_NONE;
result->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
result->round_robin_upstreams = 0;
result->tls_backoff_time = 3600;
result->tls_connection_retries = 2;
result->limit_outstanding_queries = 0;
/* unbound context is initialized here */
@ -2096,6 +2099,62 @@ getdns_context_set_tls_authentication(getdns_context *context,
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_authentication_list */
/*
* getdns_context_set_round_robin_upstreams
*
*/
getdns_return_t
getdns_context_set_round_robin_upstreams(getdns_context *context, uint8_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* only allow 0 or 1 */
if (value != 0 && value != 1) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
context->round_robin_upstreams = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_round_robin_upstreams */
/*
* getdns_context_set_tls_backoff_time
*
*/
getdns_return_t
getdns_context_set_tls_backoff_time(getdns_context *context, uint16_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* Value is in seconds. Should we have a lower limit? 1 second?*/
context->tls_backoff_time = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_backoff_time */
/*
* getdns_context_set_tls_connection_retries
*
*/
getdns_return_t
getdns_context_set_tls_connection_retries(getdns_context *context, uint16_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* Should we put a sensible upper limit on this? 10?*/
// if (value > 10) {
// return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
// }
context->tls_connection_retries = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_connection retries */
#ifdef HAVE_LIBUNBOUND
static void
set_ub_limit_outstanding_queries(getdns_context* context, uint16_t value) {
@ -3532,7 +3591,13 @@ _get_context_settings(getdns_context* context)
|| getdns_dict_set_int(result, "append_name",
context->append_name)
|| getdns_dict_set_int(result, "tls_authentication",
context->tls_auth))
context->tls_auth)
|| getdns_dict_set_int(result, "round_robin_upstreams",
context->round_robin_upstreams)
|| getdns_dict_set_int(result, "tls_backoff_time",
context->tls_backoff_time)
|| getdns_dict_set_int(result, "tls_connection_retries",
context->tls_connection_retries))
goto error;
/* list fields */
@ -3828,6 +3893,33 @@ getdns_context_get_tls_authentication(getdns_context *context,
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_round_robin_upstreams(getdns_context *context,
uint8_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->round_robin_upstreams;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_tls_backoff_time(getdns_context *context,
uint16_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->tls_backoff_time;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_tls_connection_retries(getdns_context *context,
uint16_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->tls_connection_retries;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_limit_outstanding_queries(getdns_context *context,
uint16_t* value) {
@ -4223,6 +4315,9 @@ _getdns_context_config_setting(getdns_context *context,
CONTEXT_SETTING_INT(edns_client_subnet_private)
CONTEXT_SETTING_INT(tls_authentication)
CONTEXT_SETTING_INT(round_robin_upstreams)
CONTEXT_SETTING_INT(tls_backoff_time)
CONTEXT_SETTING_INT(tls_connection_retries)
CONTEXT_SETTING_INT(tls_query_padding_blocksize)
/**************************************/

View File

@ -220,6 +220,9 @@ typedef struct getdns_upstreams {
size_t referenced;
size_t count;
size_t current_udp;
size_t current_stateful;
uint16_t tls_backoff_time;
uint16_t tls_connection_retries;
getdns_upstream upstreams[];
} getdns_upstreams;
@ -251,6 +254,9 @@ struct getdns_context {
uint32_t dnssec_allowed_skew;
getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/
getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/
uint8_t round_robin_upstreams;
uint16_t tls_backoff_time;
uint16_t tls_connection_retries;
getdns_transport_list_t *dns_transports;
size_t dns_transport_count;

View File

@ -76,6 +76,12 @@ extern "C" {
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS 622
#define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME 623
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES 624
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT "Change related to getdns_context_set_pubkey_pinset"
/** @}
*/
@ -265,6 +271,15 @@ getdns_return_t
getdns_context_set_tls_authentication(
getdns_context *context, getdns_tls_authentication_t value);
getdns_return_t
getdns_context_set_round_robin_upstreams(getdns_context *context, uint8_t value);
getdns_return_t
getdns_context_set_tls_backoff_time(getdns_context *context, uint16_t value);
getdns_return_t
getdns_context_set_tls_connection_retries(getdns_context *context, uint16_t value);
getdns_return_t
getdns_context_set_edns_client_subnet_private(getdns_context *context, uint8_t value);
@ -356,6 +371,18 @@ getdns_return_t
getdns_context_get_tls_authentication(getdns_context *context,
getdns_tls_authentication_t* value);
getdns_return_t
getdns_context_get_round_robin_upstreams(getdns_context *context,
uint8_t* value);
getdns_return_t
getdns_context_get_tls_backoff_time(getdns_context *context,
uint16_t* value);
getdns_return_t
getdns_context_get_tls_connection_retries(getdns_context *context,
uint16_t* value);
/**
* Get the currently registered callback function and user defined argument
* for context changes.

View File

@ -26,9 +26,12 @@ getdns_context_get_limit_outstanding_queries
getdns_context_get_namespaces
getdns_context_get_num_pending_requests
getdns_context_get_resolution_type
getdns_context_get_round_robin_upstreams
getdns_context_get_suffix
getdns_context_get_timeout
getdns_context_get_tls_authentication
getdns_context_get_tls_backoff_time
getdns_context_get_tls_connection_retries
getdns_context_get_tls_query_padding_blocksize
getdns_context_get_update_callback
getdns_context_get_upstream_recursive_servers
@ -56,9 +59,12 @@ getdns_context_set_memory_functions
getdns_context_set_namespaces
getdns_context_set_resolution_type
getdns_context_set_return_dnssec_status
getdns_context_set_round_robin_upstreams
getdns_context_set_suffix
getdns_context_set_timeout
getdns_context_set_tls_authentication
getdns_context_set_tls_backoff_time
getdns_context_set_tls_connection_retries
getdns_context_set_tls_query_padding_blocksize
getdns_context_set_update_callback
getdns_context_set_upstream_recursive_servers

View File

@ -594,7 +594,7 @@ stub_timeout_cb(void *userarg)
netreq->upstream->udp_timeouts++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (netreq->upstream->udp_timeouts % 100 == 0)
DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
STUB_DEBUG_DAEMON, netreq->upstream->addr_str,
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
#endif
@ -873,7 +873,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
#endif
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (!preverify_ok && !upstream->tls_fallback_ok)
DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - (%d) \"%s\"\n",
DEBUG_DAEMON("%s %-40s : Verify failed : Transport=TLS - *Failure* - (%d) \"%s\"\n",
STUB_DEBUG_DAEMON, upstream->addr_str, err,
X509_verify_cert_error_string(err));
#endif
@ -910,7 +910,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
else
DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
DEBUG_DAEMON("%s %-40s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
STUB_DEBUG_DAEMON, upstream->addr_str);
#endif
} else {
@ -923,6 +923,10 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
preverify_ok = 1;
DEBUG_STUB("%s %-35s: FD: %d, Allowing self-signed (%d) cert since pins match\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %-40s : Verify passed : Transport=TLS - Allowing self-signed cert since pins match\n",
STUB_DEBUG_DAEMON, upstream->addr_str);
#endif
}
}
@ -1369,14 +1373,20 @@ stub_udp_read_cb(void *userarg)
return;
}
netreq->response_len = read;
dnsreq->upstreams->current_udp = 0;
if (!dnsreq->context->round_robin_upstreams)
dnsreq->upstreams->current_udp = 0;
else {
dnsreq->upstreams->current_udp+=GETDNS_UPSTREAM_TRANSPORTS;
if (dnsreq->upstreams->current_udp >= dnsreq->upstreams->count)
dnsreq->upstreams->current_udp = 0;
}
netreq->debug_end_time = _getdns_get_time_as_uintt64();
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
upstream->udp_responses++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (upstream->udp_responses == 1 ||
upstream->udp_responses % 100 == 0)
DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(int)upstream->udp_responses, (int)upstream->udp_timeouts);
#endif
@ -1611,7 +1621,7 @@ upstream_write_cb(void *userarg)
/* Cleaning up after connection or auth check failure. Need to fallback. */
stub_cleanup(netreq);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - *Failure*\n",
DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - *Failure*\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"));
#endif
@ -1662,7 +1672,8 @@ upstream_working_ok(getdns_upstream *upstream)
{
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
return (upstream->responses_timeouts >
upstream->responses_received*GETDNS_CONN_ATTEMPTS ? 0 : 1);
upstream->responses_received*
upstream->upstreams->tls_connection_retries ? 0 : 1);
}
static int
@ -1675,6 +1686,17 @@ upstream_active(getdns_upstream *upstream)
return 0;
}
static int
upstream_usable(getdns_upstream *upstream)
{
if ((upstream->conn_state == GETDNS_CONN_CLOSED ||
upstream->conn_state == GETDNS_CONN_SETUP ||
upstream->conn_state == GETDNS_CONN_OPEN) &&
upstream->keepalive_shutdown == 0)
return 1;
return 0;
}
static int
upstream_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) {
if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
@ -1695,10 +1717,16 @@ upstream_valid(getdns_upstream *upstream,
getdns_transport_list_t transport,
getdns_network_req *netreq)
{
if (upstream->transport != transport || upstream->conn_state != GETDNS_CONN_CLOSED)
if (!(upstream->transport == transport && upstream_usable(upstream)))
return 0;
if (transport == GETDNS_TRANSPORT_TCP)
return 1;
if (upstream->conn_state == GETDNS_CONN_OPEN) {
if (!upstream_auth_status_ok(upstream, netreq))
return 0;
else
return 1;
}
/* We need to check past authentication history to see if this is usable for TLS.*/
if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
return 1;
@ -1731,7 +1759,7 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
getdns_upstreams *upstreams = netreq->owner->upstreams;
size_t i;
time_t now = time(NULL);
if (!upstreams->count)
return NULL;
@ -1741,37 +1769,55 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
upstreams->upstreams[i].conn_retry_time < now) {
upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Re-instating upstream\n",
DEBUG_DAEMON("%s %-40s : Re-instating upstream\n",
STUB_DEBUG_DAEMON, upstreams->upstreams[i].addr_str);
#endif
}
}
/* First find if an open upstream has the correct properties and use that*/
for (i = 0; i < upstreams->count; i++) {
if (upstream_valid_and_open(&upstreams->upstreams[i], transport, netreq))
return &upstreams->upstreams[i];
if (netreq->owner->context->round_robin_upstreams == 0) {
/* First find if an open upstream has the correct properties and use that*/
for (i = 0; i < upstreams->count; i++) {
if (upstream_valid_and_open(&upstreams->upstreams[i], transport, netreq))
return &upstreams->upstreams[i];
}
}
/* OK - we will have to open one. Choose the first one that has the best stats
and the right properties, but because we completely back off failed
/* OK - Find the next one to use. First check we have at least one valid
upstream because we completely back off failed
upstreams we may have no valid upstream at all (in contrast to UDP). This
will be better communicated to the user when we have better error codes*/
for (i = 0; i < upstreams->count; i++) {
i = upstreams->current_stateful;
do {
DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP,
__FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state);
if (upstream_valid(&upstreams->upstreams[i], transport, netreq)) {
upstream = &upstreams->upstreams[i];
break;
}
}
i++;
if (i >= upstreams->count)
i = 0;
} while (i != upstreams->current_stateful);
if (!upstream)
return NULL;
for (i++; i < upstreams->count; i++) {
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) &&
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
upstream = &upstreams->upstreams[i];
/* Now select the specific upstream */
if (netreq->owner->context->round_robin_upstreams == 0) {
/* Base the decision on the stats, noting we will have started from 0*/
for (i++; i < upstreams->count; i++) {
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) &&
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
upstream = &upstreams->upstreams[i];
}
} else {
/* Simplistic, but always just pick the first one, incrementing the current.
Note we are not distinguishing TCP/TLS here....*/
upstreams->current_stateful+=GETDNS_UPSTREAM_TRANSPORTS;
if (upstreams->current_stateful >= upstreams->count)
upstreams->current_stateful = 0;
}
return upstream;
}
@ -1856,7 +1902,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
}
upstream->conn_state = GETDNS_CONN_SETUP;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON,
DEBUG_DAEMON("%s %-40s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON,
upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP",
dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict");
#endif

View File

@ -434,6 +434,29 @@
}
END_TEST
START_TEST (getdns_context_set_context_update_callback_23)
{
/*
* value is NULL
* expect: GETDNS_RETURN_INVALID_PARAMETER
*/
struct getdns_context *context = NULL;
CONTEXT_CREATE(TRUE);
ASSERT_RC(getdns_context_set_context_update_callback(context, update_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_context_update_callback()");
expected_changed_item = GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS;
ASSERT_RC(getdns_context_set_round_robin_upstreams(context, 1),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_timeout()");
CONTEXT_DESTROY;
}
END_TEST
Suite *
getdns_context_set_context_update_callback_suite (void)
@ -462,6 +485,7 @@
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_20);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_21);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_22);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_23);
suite_add_tcase(s, tc_pos);
return s;

View File

@ -1,5 +1,11 @@
{ resolution_type: GETDNS_RESOLUTION_STUB
, dns_transport_list: [ GETDNS_TRANSPORT_TLS ]
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
, tls_query_padding_blocksize: 256
, edns_client_subnet_private : 1
, listen_addresses: [ 127.0.0.1, 0::1 ]
, idle_timeout: 10000
, round_robin_upstreams: 1
, upstream_recursive_servers:
[ { address_data: 145.100.185.15
, tls_auth_name: "dnsovertls.sinodun.com"
@ -56,9 +62,4 @@
} ]
}
]
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
, tls_query_padding_blocksize: 256
, edns_client_subnet_private : 1
, listen_addresses: [ 127.0.0.1, 0::1 ]
, idle_timeout: 10000
}

View File

@ -124,7 +124,6 @@ struct getdns_upstream;
#define GETDNS_TRANSPORTS_MAX 3
#define GETDNS_UPSTREAM_TRANSPORTS 2
#define GETDNS_CONN_ATTEMPTS 2
#define GETDNS_TRANSPORT_FAIL_MULT 5