From a1692359f36f1133c4a0916fdb8b70f04d870a64 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 3 Dec 2018 12:27:31 +0100 Subject: [PATCH] RFE #408: Retry fetching of TA after backoff time --- ChangeLog | 6 +++++- src/anchor.c | 12 +++++++++++- src/anchor.h | 3 ++- src/const-info.c | 2 ++ src/context.c | 30 ++++++++++++++++++++++++++++++ src/context.h | 4 +++- src/dnssec.c | 20 +++++++++++++++----- src/general.c | 9 +++++++-- src/getdns/getdns_extra.h.in | 33 ++++++++++++++++++++++++++++++++- src/libgetdns.symbols | 2 ++ 10 files changed, 109 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index f5626102..4047abbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,11 @@ * 2018-??-??: Version 1.4.3 + * RFE #408: Fetching of trust anchors will be retried + after failure, after a certain backoff time. The time + can be configured with + getdns_context_set_trust_anchors_backoff_time(). * RFE #408: A "dnssec" extension that requires DNSSEC verification. When this extension is set, Indeterminate - DNSSEC status will noging be returned. + DNSSEC status will not be returned. * Issue #410: Unspecified ownership of get_api_information() * Fix for DNSSEC bug in finding most specific key when trust anchor proves non-existance of one of the labels diff --git a/src/anchor.c b/src/anchor.c index 31e0e6f0..950176a7 100644 --- a/src/anchor.c +++ b/src/anchor.c @@ -923,6 +923,8 @@ static void tas_fail(getdns_context *context, tas_connection *a) DEBUG_ANCHOR("Fatal error fetching trust anchor: " "%s connection failed too\n", rt_str(rt)); context->trust_anchors_source = GETDNS_TASRC_FAILED; + context->trust_anchors_backoff_expiry = + _getdns_get_now_ms() + context->trust_anchors_backoff_time; _getdns_ta_notify_dnsreqs(context); } else DEBUG_ANCHOR("%s connection failed, waiting for %s\n" @@ -1510,7 +1512,8 @@ static void _tas_hostname_lookup_cb(getdns_dns_req *dnsreq) tas_fail(context, a); } -void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop) +void _getdns_start_fetching_ta( + getdns_context *context, getdns_eventloop *loop, uint64_t *now_ms) { getdns_return_t r; size_t scheduled; @@ -1587,6 +1590,13 @@ void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop) "schedule address requests for %s\n" , tas_hostname); context->trust_anchors_source = GETDNS_TASRC_FAILED; + if (now_ms) { + if (*now_ms == 0) *now_ms = _getdns_get_now_ms(); + context->trust_anchors_backoff_expiry = + *now_ms + context->trust_anchors_backoff_time; + } else + context->trust_anchors_backoff_expiry = + _getdns_get_now_ms() + context->trust_anchors_backoff_time; _getdns_ta_notify_dnsreqs(context); } else context->trust_anchors_source = GETDNS_TASRC_FETCHING; diff --git a/src/anchor.h b/src/anchor.h index 3c826384..f8bff042 100644 --- a/src/anchor.h +++ b/src/anchor.h @@ -41,7 +41,8 @@ void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms); -void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop); +void _getdns_start_fetching_ta( + getdns_context *context, getdns_eventloop *loop, uint64_t *now_ms); #define MAX_KSKS 16 #define RRSIG_RDATA_LEN 16 diff --git a/src/const-info.c b/src/const-info.c index 3b9918bc..f6f0d18b 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -96,6 +96,7 @@ static struct const_info consts_info[] = { { 635, "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT }, { 636, "GETDNS_CONTEXT_CODE_TLS_MIN_VERSION", GETDNS_CONTEXT_CODE_TLS_MIN_VERSION_TEXT }, { 637, "GETDNS_CONTEXT_CODE_TLS_MAX_VERSION", GETDNS_CONTEXT_CODE_TLS_MAX_VERSION_TEXT }, + { 638, "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME_TEXT }, { 699, "GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE", GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE_TEXT }, { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT }, { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT }, @@ -205,6 +206,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_CONTEXT_CODE_TLS_MAX_VERSION", 637 }, { "GETDNS_CONTEXT_CODE_TLS_MIN_VERSION", 636 }, { "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 }, + { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME", 638 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 }, { "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL", 627 }, diff --git a/src/context.c b/src/context.c index 51ef96c2..b1b36231 100644 --- a/src/context.c +++ b/src/context.c @@ -1593,6 +1593,7 @@ getdns_context_create_with_extended_memory_functions( result->trust_anchors_url = NULL; result->trust_anchors_verify_email = NULL; result->trust_anchors_verify_CA = NULL; + result->trust_anchors_backoff_time = 2500; result->appdata_dir = NULL; result->tls_ca_path = NULL; result->tls_ca_file = NULL; @@ -4026,6 +4027,8 @@ _get_context_settings(getdns_context* context) context->tls_query_padding_blocksize) || getdns_dict_set_int(result, "resolution_type", context->resolution_type) + || getdns_dict_set_int(result, "trust_anchors_backoff_time", + context->trust_anchors_backoff_time) ) goto error; @@ -4960,6 +4963,7 @@ _getdns_context_config_setting(getdns_context *context, CONTEXT_SETTING_STRING(trust_anchors_url) CONTEXT_SETTING_STRING(trust_anchors_verify_CA) CONTEXT_SETTING_STRING(trust_anchors_verify_email) + CONTEXT_SETTING_INT(trust_anchors_backoff_time) CONTEXT_SETTING_STRING(appdata_dir) #ifndef USE_WINSOCK CONTEXT_SETTING_STRING(resolvconf) @@ -5430,6 +5434,32 @@ getdns_context_get_trust_anchors_verify_email( return GETDNS_RETURN_GOOD; } +getdns_return_t +getdns_context_set_trust_anchors_backoff_time( + getdns_context *context, uint64_t backoff_time) +{ + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; + + context->trust_anchors_backoff_time = backoff_time; + if (context->trust_anchors_source == GETDNS_TASRC_FAILED) + context->trust_anchors_source = GETDNS_TASRC_NONE; + dispatch_updated( context + , GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME); + return GETDNS_RETURN_GOOD; +} + +getdns_return_t +getdns_context_get_trust_anchors_backoff_time( + getdns_context *context, uint64_t *backoff_time) +{ + if (!backoff_time) + return GETDNS_RETURN_INVALID_PARAMETER; + + *backoff_time = context->trust_anchors_backoff_time; + return GETDNS_RETURN_GOOD; +} + getdns_return_t getdns_context_set_appdata_dir( getdns_context *context, const char *appdata_dir) diff --git a/src/context.h b/src/context.h index c0080930..ef16855e 100644 --- a/src/context.h +++ b/src/context.h @@ -269,7 +269,7 @@ typedef struct getdns_upstreams { size_t count; size_t current_udp; size_t current_stateful; - uint16_t max_backoff_value; + uint16_t max_backoff_value; uint16_t tls_backoff_time; uint16_t tls_connection_retries; getdns_log_config log; @@ -347,6 +347,8 @@ struct getdns_context { char *trust_anchors_url; char *trust_anchors_verify_CA; char *trust_anchors_verify_email; + uint64_t trust_anchors_backoff_time; + uint64_t trust_anchors_backoff_expiry; _getdns_ksks root_ksk; diff --git a/src/dnssec.c b/src/dnssec.c index 4dca78bc..dc0da14a 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -3302,11 +3302,11 @@ static void check_chain_complete(chain_head *chain) DEBUG_ANCHOR("root DNSKEY set was bogus!\n"); if (!dnsreq->waiting_for_ta) { - uint64_t now = 0; + uint64_t now_ms = 0; dnsreq->waiting_for_ta = 1; _getdns_context_equip_with_anchor( - context, &now); + context, &now_ms); if (context->trust_anchors_source == GETDNS_TASRC_XML) { @@ -3314,9 +3314,19 @@ static void check_chain_complete(chain_head *chain) check_chain_complete(chain); return; } - _getdns_start_fetching_ta( - context, dnsreq->loop); - + if (context->trust_anchors_source == + GETDNS_TASRC_FAILED + && 0 == _getdns_ms_until_expiry2( + context->trust_anchors_backoff_expiry, + &now_ms)) { + context->trust_anchors_source = + GETDNS_TASRC_NONE; + } + if (context->trust_anchors_source + != GETDNS_TASRC_FAILED) { + _getdns_start_fetching_ta( + context, dnsreq->loop, &now_ms); + } if (dnsreq->waiting_for_ta && context->trust_anchors_source == GETDNS_TASRC_FETCHING) { diff --git a/src/general.c b/src/general.c index 2cfec678..f3170072 100644 --- a/src/general.c +++ b/src/general.c @@ -595,13 +595,18 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, _getdns_context_track_outbound_request(req); if (req->dnssec_extension_set) { + if (context->trust_anchors_source == GETDNS_TASRC_FAILED + && _getdns_ms_until_expiry2( + context->trust_anchors_backoff_expiry, &now_ms) == 0) { + context->trust_anchors_source = GETDNS_TASRC_NONE; + } if (context->trust_anchors_source == GETDNS_TASRC_XML_UPDATE) - _getdns_start_fetching_ta(context, loop); + _getdns_start_fetching_ta(context, loop, &now_ms); else if (context->trust_anchors_source == GETDNS_TASRC_NONE) { _getdns_context_equip_with_anchor(context, &now_ms); if (context->trust_anchors_source == GETDNS_TASRC_NONE) { - _getdns_start_fetching_ta(context, loop); + _getdns_start_fetching_ta(context, loop, &now_ms); } } } diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 135c29bb..f1b2af36 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -108,7 +108,8 @@ extern "C" { #define GETDNS_CONTEXT_CODE_TLS_MIN_VERSION_TEXT "Change related to getdns_context_set_tls_min_version" #define GETDNS_CONTEXT_CODE_TLS_MAX_VERSION 637 #define GETDNS_CONTEXT_CODE_TLS_MAX_VERSION_TEXT "Change related to getdns_context_set_tls_max_version" - +#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME 638 +#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_trust_anchors_backoff_time" /** @} @@ -702,6 +703,22 @@ getdns_return_t getdns_context_set_trust_anchors_verify_email( getdns_context *context, const char *verify_email); +/** + * Configure the amount of milliseconds the trust anchors should not be tried + * to be fetched after failure. Default is 2500 which is two and a half seconds. + * Setting the trust anchors backoff time will cause fetching to be retried + * immediatly. + * @see getdns_context_get_trust_anchors_backoff_time + * @param context The context to configure + * @param value Number of milliseconds before fetch trust anchors + * will be retried. + * @return GETDNS_RETURN_GOOD on success + * @return GETDNS_RETURN_INVALID_PARAMETER if context is null. + */ +getdns_return_t +getdns_context_set_trust_anchors_backoff_time( + getdns_context *context, uint64_t value); + /** * Initialized the context's upstream recursive servers and suffixes * with the values from the given resolv.conf file. @@ -1316,6 +1333,20 @@ getdns_return_t getdns_context_get_trust_anchors_verify_email( getdns_context *context, const char **verify_email); +/** + * Get the amount of milliseconds the trust anchors will not be tried to be + * fetched after failure. + * @see getdns_context_set_trust_anchors_backoff_time + * @param context The context to configure + * @param value Number of milliseconds before fetch trust anchors + * will be retried. + * @return GETDNS_RETURN_GOOD on success + * @return GETDNS_RETURN_INVALID_PARAMETER if context is null. + */ +getdns_return_t +getdns_context_get_trust_anchors_backoff_time( + getdns_context *context, uint64_t *value); + /** * Get the value with which the context's upstream recursive servers * and suffixes were initialized. diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index 5c3fb52d..f0169761 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -43,6 +43,7 @@ getdns_context_get_tls_curves_list getdns_context_get_tls_max_version getdns_context_get_tls_min_version getdns_context_get_tls_query_padding_blocksize +getdns_context_get_trust_anchors_backoff_time getdns_context_get_trust_anchors_url getdns_context_get_trust_anchors_verify_CA getdns_context_get_trust_anchors_verify_email @@ -90,6 +91,7 @@ getdns_context_set_tls_curves_list getdns_context_set_tls_max_version getdns_context_set_tls_min_version getdns_context_set_tls_query_padding_blocksize +getdns_context_set_trust_anchors_backoff_time getdns_context_set_trust_anchors_url getdns_context_set_trust_anchors_verify_CA getdns_context_set_trust_anchors_verify_email