From 58885e04d72f9eb1054c3d93c9e5a896be4c70ed Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 31 Oct 2015 21:04:08 +0900 Subject: [PATCH 01/12] dnssec_roadblock_avoidance extension --- configure.ac | 9 ++++++++- src/dnssec.c | 19 +++++++++++++++++++ src/general.c | 21 ++++++++++++++++----- src/general.h | 2 ++ src/request-internal.c | 5 +++++ src/types-internal.h | 4 ++++ src/util-internal.c | 3 +++ 7 files changed, 57 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index b4409fa3..439bbc4d 100644 --- a/configure.ac +++ b/configure.ac @@ -392,7 +392,14 @@ case "$enable_ecdsa" in ;; esac - +AC_ARG_ENABLE(draft-dnssec-roadblock-avoidance, AC_HELP_STRING([--enable-draft-dnssec-roadblock-avoidance], [Enable experimental dnssec roadblock avoidance])) +case "$enable_draft_dnssec_roadblock_avoidance" in + yes) + AC_DEFINE_UNQUOTED([DNSSEC_ROADBLOCK_AVOIDANCE], [1], [Define this to enable the experimental draft dnssec roadblock avoidance.]) + ;; + no|*) + ;; +esac AC_ARG_ENABLE(draft-edns-cookies, AC_HELP_STRING([--enable-draft-edns-cookies], [Enable experimental edns cookies])) case "$enable_draft_edns_cookies" in diff --git a/src/dnssec.c b/src/dnssec.c index 780ac6de..1629764e 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -3088,6 +3088,25 @@ static void check_chain_complete(chain_head *chain) chain, rrset_iter_init( &tas_iter , context->trust_anchors , context->trust_anchors_len)); +#endif +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + if ( dnsreq->dnssec_roadblock_avoidance + && dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) { + + getdns_return_t r = GETDNS_RETURN_GOOD; + getdns_network_req **netreq_p, *netreq; + + dnsreq->avoid_dnssec_roadblocks = 1; + + for ( netreq_p = dnsreq->netreqs + ; !r && (netreq = *netreq_p) + ; netreq_p++) { + + netreq->state = NET_REQ_NOT_SENT; + (void) _getdns_submit_netreq(netreq); + } + return; + } #endif val_chain_list = dnsreq->dnssec_return_validation_chain ? getdns_list_create_with_context(context) : NULL; diff --git a/src/general.c b/src/general.c index 2cb9b0f0..37688a09 100644 --- a/src/general.c +++ b/src/general.c @@ -128,14 +128,20 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res) #endif -static getdns_return_t -submit_network_request(getdns_network_req *netreq) +getdns_return_t +_getdns_submit_netreq(getdns_network_req *netreq) { getdns_return_t r; getdns_dns_req *dns_req = netreq->owner; char name[1024]; - if (dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING + if ( +#ifdef STUB_NATIVE_DNSSEC +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + ( +#endif +#endif + dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING /* TODO: Until DNSSEC with the new async stub resolver is finished, * use unbound when we need DNSSEC. */ @@ -143,6 +149,11 @@ submit_network_request(getdns_network_req *netreq) || dns_req->dnssec_return_status || dns_req->dnssec_return_only_secure || dns_req->dnssec_return_validation_chain +#else +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + && !dns_req->dnssec_roadblock_avoidance + ) || dns_req->avoid_dnssec_roadblocks +#endif #endif ) { @@ -217,7 +228,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, for ( netreq_p = req->netreqs ; !r && (netreq = *netreq_p) ; netreq_p++) - r = submit_network_request(netreq); + r = _getdns_submit_netreq(netreq); else for (i = 0; i < context->namespace_count; i++) { if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) { @@ -239,7 +250,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, for ( netreq_p = req->netreqs ; !r && (netreq = *netreq_p) ; netreq_p++) - r = submit_network_request(netreq); + r = _getdns_submit_netreq(netreq); break; } else r = GETDNS_RETURN_BAD_CONTEXT; diff --git a/src/general.h b/src/general.h index 94c32219..58201056 100644 --- a/src/general.h +++ b/src/general.h @@ -44,6 +44,8 @@ void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *); void _getdns_check_dns_req_complete(getdns_dns_req *dns_req); +getdns_return_t _getdns_submit_netreq(getdns_network_req *netreq); + getdns_return_t _getdns_general_loop(getdns_context *context, getdns_eventloop *loop, diff --git a/src/request-internal.c b/src/request-internal.c index 30156724..a7e1b20c 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -372,6 +372,11 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_validation_chain = dnssec_return_validation_chain; result->edns_cookies = edns_cookies; +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + result->dnssec_roadblock_avoidance = is_extension_set( + extensions, "dnssec_roadblock_avoidance"); + result->avoid_dnssec_roadblocks = 0; +#endif /* will be set by caller */ result->user_pointer = NULL; diff --git a/src/types-internal.h b/src/types-internal.h index 93b97973..11629d84 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -261,6 +261,10 @@ typedef struct getdns_dns_req { int dnssec_return_status; int dnssec_return_only_secure; int dnssec_return_validation_chain; +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + int dnssec_roadblock_avoidance; + int avoid_dnssec_roadblocks; +#endif int edns_cookies; /* Internally used by return_validation_chain */ diff --git a/src/util-internal.c b/src/util-internal.c index d6e9299e..48eefa17 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -63,6 +63,9 @@ static getdns_extension_format extformats[] = { {"dnssec_return_only_secure", t_int}, {"dnssec_return_status", t_int}, {"dnssec_return_validation_chain", t_int}, +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + {"dnssec_roadblock_avoidance", t_int}, +#endif #ifdef EDNS_COOKIES {"edns_cookies", t_int}, #endif From a85b17c8856aabe118b8a43992d859bc3984bc85 Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 10:24:02 +0900 Subject: [PATCH 02/12] working prototype 1 --- src/Makefile.in | 2 +- src/request-internal.c | 10 +++++++- src/stub.c | 6 +++++ src/types-internal.h | 9 ++++++++ src/util-internal.c | 52 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index 381ab6bd..d6d90054 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -117,7 +117,7 @@ install: libgetdns.la $(INSTALL) -m 755 -d $(DESTDIR)$(includedir) $(INSTALL) -m 755 -d $(DESTDIR)$(includedir)/getdns $(INSTALL) -m 644 getdns/getdns.h $(DESTDIR)$(includedir)/getdns/getdns.h - $(INSTALL) -m 644 $(srcdir)/getdns/getdns_extra.h $(DESTDIR)$(includedir)/getdns/getdns_extra.h + $(INSTALL) -m 644 getdns/getdns_extra.h $(DESTDIR)$(includedir)/getdns/getdns_extra.h $(INSTALL) -m 755 -d $(DESTDIR)$(libdir) $(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir) if test $(have_libevent) = 1 ; then $(INSTALL) -m 644 $(srcdir)/getdns/getdns_ext_libevent.h $(DESTDIR)$(includedir)/getdns/ ; $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi diff --git a/src/request-internal.c b/src/request-internal.c index 30156724..3e87195d 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -114,6 +114,12 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->write_queue_tail = NULL; net_req->response_len = 0; + /* Some fields to record info for return_call_debugging */ + net_req->debug_start_time = 0; + net_req->debug_end_time = 0; + net_req->debug_tls_auth_status = 0; + net_req->debug_upstream = NULL; + net_req->wire_data_sz = wire_data_sz; if (max_query_sz) { /* first two bytes will contain query length (for tcp) */ @@ -372,7 +378,9 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_validation_chain = dnssec_return_validation_chain; result->edns_cookies = edns_cookies; - + result->return_call_debugging + = is_extension_set(extensions, "return_call_debugging"); + /* will be set by caller */ result->user_pointer = NULL; result->user_callback = NULL; diff --git a/src/stub.c b/src/stub.c index 7bc30c2d..cafd1f85 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1276,6 +1276,8 @@ stub_udp_write_cb(void *userarg) dnsreq->loop, netreq->fd, dnsreq->context->timeout, getdns_eventloop_event_init(&netreq->event, netreq, stub_udp_read_cb, NULL, stub_timeout_cb)); + + netreq->debug_upstream = netreq->upstream; } /**************************/ @@ -1343,6 +1345,7 @@ stub_tcp_write_cb(void *userarg) dnsreq->loop, netreq->fd, dnsreq->context->timeout, getdns_eventloop_event_init(&netreq->event, netreq, stub_tcp_read_cb, NULL, stub_timeout_cb)); + netreq->debug_upstream = netreq->upstream; return; } } @@ -1477,6 +1480,9 @@ upstream_write_cb(void *userarg) return; default: + netreq->debug_upstream = netreq->upstream; + /* Need this because auth status is reset on connection clode */ + netreq->debug_tls_auth_status = netreq->upstream->tls_auth_failed; upstream->writes_done++; netreq->query_id = (uint16_t) q; /* Unqueue the netreq from the write_queue */ diff --git a/src/types-internal.h b/src/types-internal.h index 93b97973..0dbe7028 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -226,6 +226,12 @@ typedef struct getdns_network_req /* Network requests scheduled to write after me */ struct getdns_network_req *write_queue_tail; + /* Some fields to record info for return_call_debugging */ + uint64_t debug_start_time; + uint64_t debug_end_time; + size_t debug_tls_auth_status; + struct getdns_upstream *debug_upstream; + /* When more space is needed for the wire_data response than is * available in wire_data[], it will be allocated seperately. * response will then not point to wire_data anymore. @@ -237,6 +243,8 @@ typedef struct getdns_network_req size_t wire_data_sz; uint8_t wire_data[]; + + } getdns_network_req; /** @@ -262,6 +270,7 @@ typedef struct getdns_dns_req { int dnssec_return_only_secure; int dnssec_return_validation_chain; int edns_cookies; + int return_call_debugging; /* Internally used by return_validation_chain */ int dnssec_ok_checking_disabled; diff --git a/src/util-internal.c b/src/util-internal.c index d6e9299e..67a8c982 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -671,6 +671,33 @@ success: return result; } +getdns_dict * +_getdns_create_call_debugging_dict(getdns_context *context, + getdns_network_req *netreq, + getdns_dict *reply) { + getdns_dict *netreq_debug = getdns_dict_create_with_context(context); + getdns_bindata *qname = NULL; + uint32_t qtype; + getdns_dict *question = NULL; + getdns_dict_get_dict(reply, "question", &question); + getdns_dict_get_bindata(question, "qname", &qname); + getdns_dict_set_bindata(netreq_debug, "qname", qname); + getdns_dict_get_int(question, "qtype", &qtype); + getdns_dict_set_int(netreq_debug, "qtype", qtype); + getdns_dict *address_debug = getdns_dict_create_with_context(context); + _getdns_sockaddr_to_dict(context, &netreq->upstream->addr, &address_debug); + getdns_dict_set_dict(netreq_debug, "upstream", address_debug); + getdns_dict_set_int(netreq_debug, "transport", netreq->upstream->transport); + /* Only include the auth status if TLS was used */ + if (netreq->upstream->transport == GETDNS_TRANSPORT_TLS) { + getdns_dict_util_set_string(netreq_debug, "tls_auth", + netreq->debug_tls_auth_status == 0 ? "OK" : "FAILED"); + } + return netreq_debug; + +} + + getdns_dict * _getdns_create_getdns_response(getdns_dns_req *completed_request) { @@ -678,6 +705,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_list *just_addrs = NULL; getdns_list *replies_full; getdns_list *replies_tree; + getdns_list *call_debugging; getdns_network_req *netreq, **netreq_p; int rrsigs_in_answer = 0; getdns_dict *reply; @@ -713,6 +741,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) if (!(replies_tree = getdns_list_create_with_context(context))) goto error_free_replies_full; + if (completed_request->return_call_debugging) { + if (!(call_debugging = getdns_list_create_with_context(context))) + goto error_free_result; + } + for ( netreq_p = completed_request->netreqs ; (netreq = *netreq_p) ; netreq_p++) { @@ -769,6 +802,17 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_dict_destroy(reply); goto error; } + + if (completed_request->return_call_debugging) { + getdns_dict *netreq_debug; + if (!(netreq_debug = _getdns_create_call_debugging_dict(context, + netreq, reply))) { + goto error; + } + _getdns_list_append_dict(call_debugging, netreq_debug); + getdns_dict_destroy(netreq_debug); + } + getdns_dict_destroy(reply); /* buffer */ @@ -785,6 +829,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error_free_replies_full; getdns_list_destroy(replies_full); + if (completed_request->return_call_debugging) { + if (getdns_dict_set_list(result, "return_call_debugging", call_debugging)) + goto error_free_call_debugging; + } + if (just_addrs && getdns_dict_set_list( result, GETDNS_STR_KEY_JUST_ADDRS, just_addrs)) goto error_free_result; @@ -806,6 +855,9 @@ error: getdns_list_destroy(replies_tree); error_free_replies_full: getdns_list_destroy(replies_full); +error_free_call_debugging: + if (completed_request->return_call_debugging) + getdns_list_destroy(call_debugging); error_free_result: getdns_list_destroy(just_addrs); getdns_dict_destroy(result); From 80864655d7e2865230489d897ca724231470709f Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 10:51:00 +0900 Subject: [PATCH 03/12] Working prototype 2 --- src/util-internal.c | 60 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/src/util-internal.c b/src/util-internal.c index 67a8c982..4b420ca7 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -675,24 +675,64 @@ getdns_dict * _getdns_create_call_debugging_dict(getdns_context *context, getdns_network_req *netreq, getdns_dict *reply) { - getdns_dict *netreq_debug = getdns_dict_create_with_context(context); + getdns_bindata *qname = NULL; uint32_t qtype; getdns_dict *question = NULL; - getdns_dict_get_dict(reply, "question", &question); - getdns_dict_get_bindata(question, "qname", &qname); - getdns_dict_set_bindata(netreq_debug, "qname", qname); - getdns_dict_get_int(question, "qtype", &qtype); - getdns_dict_set_int(netreq_debug, "qtype", qtype); + if (getdns_dict_get_dict(reply, "question", &question)) { + return NULL; + } + if (getdns_dict_get_bindata(question, "qname", &qname)) { + return NULL; + } + if (getdns_dict_get_int(question, "qtype", &qtype)) { + return NULL; + } + + /* It is the responsibility of the caller to free this */ + getdns_dict *netreq_debug = getdns_dict_create_with_context(context); + if (netreq_debug == NULL) { + return NULL; + } + getdns_dict *address_debug = getdns_dict_create_with_context(context); + if (address_debug == NULL){ + getdns_dict_destroy(netreq_debug); + return NULL; + } _getdns_sockaddr_to_dict(context, &netreq->upstream->addr, &address_debug); - getdns_dict_set_dict(netreq_debug, "upstream", address_debug); - getdns_dict_set_int(netreq_debug, "transport", netreq->upstream->transport); + + if (getdns_dict_set_bindata(netreq_debug, "qname", qname)) { + getdns_dict_destroy(netreq_debug); + getdns_dict_destroy(address_debug); + return NULL; + } + if (getdns_dict_set_int(netreq_debug, "qtype", qtype)) { + getdns_dict_destroy(netreq_debug); + getdns_dict_destroy(address_debug); + return NULL; + } + if (getdns_dict_set_dict(netreq_debug, "upstream", address_debug)) { + getdns_dict_destroy(netreq_debug); + getdns_dict_destroy(address_debug); + return NULL; + } + getdns_dict_destroy(address_debug); + + if (getdns_dict_set_int(netreq_debug, "transport", + netreq->upstream->transport)) { + getdns_dict_destroy(netreq_debug); + return NULL; + } /* Only include the auth status if TLS was used */ if (netreq->upstream->transport == GETDNS_TRANSPORT_TLS) { - getdns_dict_util_set_string(netreq_debug, "tls_auth", - netreq->debug_tls_auth_status == 0 ? "OK" : "FAILED"); + if (getdns_dict_util_set_string(netreq_debug, "tls_auth", + netreq->debug_tls_auth_status == 0 ? "OK" : "FAILED")) { + getdns_dict_destroy(netreq_debug); + return NULL; + } } + return netreq_debug; } From 25f7f2182be70527d452c5d06c2b6373104fc0d4 Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 11:04:03 +0900 Subject: [PATCH 04/12] working prototype 3 --- src/dict.c | 1 + src/util-internal.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/dict.c b/src/dict.c index 16e0b3fb..19e55e0a 100644 --- a/src/dict.c +++ b/src/dict.c @@ -994,6 +994,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, "resolution_type") == 0) && (strval = _getdns_get_const_info(item->i.data.n)->name)) { diff --git a/src/util-internal.c b/src/util-internal.c index 4b420ca7..fb1d664d 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -727,9 +727,11 @@ _getdns_create_call_debugging_dict(getdns_context *context, /* Only include the auth status if TLS was used */ if (netreq->upstream->transport == GETDNS_TRANSPORT_TLS) { if (getdns_dict_util_set_string(netreq_debug, "tls_auth", - netreq->debug_tls_auth_status == 0 ? "OK" : "FAILED")) { - getdns_dict_destroy(netreq_debug); - return NULL; + netreq->debug_tls_auth_status == 0 ? + "OK: Hostname matched valid cert." : + "FAILED: Server not validated.")) { + getdns_dict_destroy(netreq_debug); + return NULL; } } From 2d20e18b8ab758d2231c1d470c8efcbb101d26d2 Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 11:14:45 +0900 Subject: [PATCH 05/12] working prototype 4 --- src/request-internal.c | 1 - src/stub.c | 4 ---- src/types-internal.h | 1 - 3 files changed, 6 deletions(-) diff --git a/src/request-internal.c b/src/request-internal.c index 3e87195d..2bef85ae 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -118,7 +118,6 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->debug_start_time = 0; net_req->debug_end_time = 0; net_req->debug_tls_auth_status = 0; - net_req->debug_upstream = NULL; net_req->wire_data_sz = wire_data_sz; if (max_query_sz) { diff --git a/src/stub.c b/src/stub.c index cafd1f85..e6974378 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1276,8 +1276,6 @@ stub_udp_write_cb(void *userarg) dnsreq->loop, netreq->fd, dnsreq->context->timeout, getdns_eventloop_event_init(&netreq->event, netreq, stub_udp_read_cb, NULL, stub_timeout_cb)); - - netreq->debug_upstream = netreq->upstream; } /**************************/ @@ -1345,7 +1343,6 @@ stub_tcp_write_cb(void *userarg) dnsreq->loop, netreq->fd, dnsreq->context->timeout, getdns_eventloop_event_init(&netreq->event, netreq, stub_tcp_read_cb, NULL, stub_timeout_cb)); - netreq->debug_upstream = netreq->upstream; return; } } @@ -1480,7 +1477,6 @@ upstream_write_cb(void *userarg) return; default: - netreq->debug_upstream = netreq->upstream; /* Need this because auth status is reset on connection clode */ netreq->debug_tls_auth_status = netreq->upstream->tls_auth_failed; upstream->writes_done++; diff --git a/src/types-internal.h b/src/types-internal.h index 0dbe7028..c6376de6 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -230,7 +230,6 @@ typedef struct getdns_network_req uint64_t debug_start_time; uint64_t debug_end_time; size_t debug_tls_auth_status; - struct getdns_upstream *debug_upstream; /* When more space is needed for the wire_data response than is * available in wire_data[], it will be allocated seperately. From f5662bbf32b3dbf1abff412cc04dd0e5b20b49ab Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 11:43:12 +0900 Subject: [PATCH 06/12] working prototype 5 --- src/util-internal.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/util-internal.c b/src/util-internal.c index fb1d664d..27932bbc 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -702,17 +702,17 @@ _getdns_create_call_debugging_dict(getdns_context *context, } _getdns_sockaddr_to_dict(context, &netreq->upstream->addr, &address_debug); - if (getdns_dict_set_bindata(netreq_debug, "qname", qname)) { + if (getdns_dict_set_bindata(netreq_debug, "query_name", qname)) { getdns_dict_destroy(netreq_debug); getdns_dict_destroy(address_debug); return NULL; } - if (getdns_dict_set_int(netreq_debug, "qtype", qtype)) { + if (getdns_dict_set_int(netreq_debug, "query_type", qtype)) { getdns_dict_destroy(netreq_debug); getdns_dict_destroy(address_debug); return NULL; } - if (getdns_dict_set_dict(netreq_debug, "upstream", address_debug)) { + if (getdns_dict_set_dict(netreq_debug, "query_to", address_debug)) { getdns_dict_destroy(netreq_debug); getdns_dict_destroy(address_debug); return NULL; @@ -724,9 +724,19 @@ _getdns_create_call_debugging_dict(getdns_context *context, getdns_dict_destroy(netreq_debug); return NULL; } + if (getdns_dict_set_int(netreq_debug, "start_time", + netreq->debug_start_time)) { + getdns_dict_destroy(netreq_debug); + return NULL; + } + if (getdns_dict_set_int(netreq_debug, "end_time", + netreq->debug_end_time)) { + getdns_dict_destroy(netreq_debug); + return NULL; + } /* Only include the auth status if TLS was used */ if (netreq->upstream->transport == GETDNS_TRANSPORT_TLS) { - if (getdns_dict_util_set_string(netreq_debug, "tls_auth", + if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status", netreq->debug_tls_auth_status == 0 ? "OK: Hostname matched valid cert." : "FAILED: Server not validated.")) { From ae2cc39a3695b24d2dd65bf562d0144ee5dc3911 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 1 Nov 2015 12:28:43 +0900 Subject: [PATCH 07/12] Full roadblock avoidance functionality --- src/context.c | 51 ++++++++++++++++++++++++++---------------- src/general.c | 38 +++++++++++++++---------------- src/request-internal.c | 19 +++++++++++++--- src/util-internal.c | 7 +++++- 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/src/context.c b/src/context.c index 8a71e727..2408abb4 100644 --- a/src/context.c +++ b/src/context.c @@ -2143,13 +2143,37 @@ ub_setup_stub(struct ub_ctx *ctx, getdns_context *context) } #endif + +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE static getdns_return_t -_getdns_ns_dns_setup(struct getdns_context *context) +ub_setup_recursing(struct ub_ctx *ctx, getdns_context *context) { #ifdef HAVE_LIBUNBOUND _getdns_rr_iter rr_spc, *rr; char ta_str[8192]; #endif + + /* TODO: use the root servers via root hints file */ + (void) ub_ctx_set_fwd(ctx, NULL); + if (!context->unbound_ta_set && context->trust_anchors) { + for ( rr = _getdns_rr_iter_init( &rr_spc + , context->trust_anchors + , context->trust_anchors_len) + ; rr ; rr = _getdns_rr_iter_next(rr) ) { + + (void) gldns_wire2str_rr_buf(rr->pos, + rr->nxt - rr->pos, ta_str, sizeof(ta_str)); + (void) ub_ctx_add_ta(ctx, ta_str); + } + context->unbound_ta_set = 1; + } + return GETDNS_RETURN_GOOD; +} +#endif + +static getdns_return_t +_getdns_ns_dns_setup(struct getdns_context *context) +{ assert(context); switch (context->resolution_type) { @@ -2157,31 +2181,20 @@ _getdns_ns_dns_setup(struct getdns_context *context) if (!context->upstreams || !context->upstreams->count) return GETDNS_RETURN_GENERIC_ERROR; #ifdef STUB_NATIVE_DNSSEC +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + return ub_setup_recursing(context->unbound_ctx, context); +#else return GETDNS_RETURN_GOOD; +#endif #else return ub_setup_stub(context->unbound_ctx, context); #endif case GETDNS_RESOLUTION_RECURSING: #ifdef HAVE_LIBUNBOUND - /* TODO: use the root servers via root hints file */ - (void) ub_ctx_set_fwd(context->unbound_ctx, NULL); - if (!context->unbound_ta_set && context->trust_anchors) { - for ( rr = _getdns_rr_iter_init( &rr_spc - , context->trust_anchors - , context->trust_anchors_len) - ; rr ; rr = _getdns_rr_iter_next(rr) ) { - - (void) gldns_wire2str_rr_buf(rr->pos, - rr->nxt - rr->pos, ta_str, sizeof(ta_str)); - (void) ub_ctx_add_ta( - context->unbound_ctx, ta_str); - } - context->unbound_ta_set = 1; - } - return GETDNS_RETURN_GOOD; + return ub_setup_recursing(context->unbound_ctx, context); #else - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_NOT_IMPLEMENTED; #endif } return GETDNS_RETURN_BAD_CONTEXT; @@ -2201,7 +2214,7 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, /* Transport can in theory be set per query in stub mode */ if (context->resolution_type == GETDNS_RESOLUTION_STUB && - tls_is_in_transports_list(context) == 1) { + tls_is_in_transports_list(context) == 1) { if (context->tls_ctx == NULL) { #ifdef HAVE_TLS_v1_2 /* Create client context, use TLS v1.2 only for now */ diff --git a/src/general.c b/src/general.c index 37688a09..c73a2e9e 100644 --- a/src/general.c +++ b/src/general.c @@ -90,10 +90,16 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) else if (! results_found) _getdns_call_user_callback(dns_req, NULL); else if (dns_req->dnssec_return_validation_chain +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + || ( dns_req->dnssec_roadblock_avoidance + && !dns_req->avoid_dnssec_roadblocks) +#endif + #ifdef STUB_NATIVE_DNSSEC || (dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB && (dns_req->dnssec_return_status || - dns_req->dnssec_return_only_secure)) + dns_req->dnssec_return_only_secure + )) #endif ) _getdns_get_validation_chain(dns_req); @@ -135,28 +141,22 @@ _getdns_submit_netreq(getdns_network_req *netreq) getdns_dns_req *dns_req = netreq->owner; char name[1024]; - if ( + #ifdef STUB_NATIVE_DNSSEC -#ifdef DNSSEC_ROADBLOCK_AVOIDANCE - ( -#endif -#endif - dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING - /* TODO: Until DNSSEC with the new async stub resolver is finished, - * use unbound when we need DNSSEC. - */ -#ifndef STUB_NATIVE_DNSSEC +# ifdef DNSSEC_ROADBLOCK_AVOIDANCE + + if ((dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING + && !dns_req->dnssec_roadblock_avoidance) + || dns_req->avoid_dnssec_roadblocks) { +# else + if ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING) { +# endif +#else + if ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING || dns_req->dnssec_return_status || dns_req->dnssec_return_only_secure - || dns_req->dnssec_return_validation_chain -#else -#ifdef DNSSEC_ROADBLOCK_AVOIDANCE - && !dns_req->dnssec_roadblock_avoidance - ) || dns_req->avoid_dnssec_roadblocks + || dns_req->dnssec_return_validation_chain) { #endif -#endif - ) { - /* schedule the timeout */ if (! dns_req->timeout.timeout_cb) { dns_req->timeout.userarg = dns_req; diff --git a/src/request-internal.c b/src/request-internal.c index a7e1b20c..90ed195a 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -221,10 +221,19 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, = is_extension_set(extensions, "dnssec_return_validation_chain"); int edns_cookies = is_extension_set(extensions, "edns_cookies"); +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + int dnssec_roadblock_avoidance + = is_extension_set(extensions, "dnssec_roadblock_avoidance") + || (extensions == dnssec_ok_checking_disabled); +#endif int dnssec_extension_set = dnssec_return_status || dnssec_return_only_secure || dnssec_return_validation_chain - || (extensions == dnssec_ok_checking_disabled); + || (extensions == dnssec_ok_checking_disabled) +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + || dnssec_roadblock_avoidance +#endif + ; uint32_t edns_do_bit; int edns_maximum_udp_payload_size; @@ -305,7 +314,12 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, ? edns_maximum_udp_payload_size : 512; /* (x + 7) / 8 * 8 to align on 8 byte boundries */ +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + if (context->resolution_type == GETDNS_RESOLUTION_RECURSING + && !dnssec_roadblock_avoidance) +#else if (context->resolution_type == GETDNS_RESOLUTION_RECURSING) +#endif max_query_sz = 0; else { for (i = 0; i < noptions; i++) { @@ -373,8 +387,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->dnssec_return_validation_chain = dnssec_return_validation_chain; result->edns_cookies = edns_cookies; #ifdef DNSSEC_ROADBLOCK_AVOIDANCE - result->dnssec_roadblock_avoidance = is_extension_set( - extensions, "dnssec_roadblock_avoidance"); + result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance; result->avoid_dnssec_roadblocks = 0; #endif diff --git a/src/util-internal.c b/src/util-internal.c index 48eefa17..cc82dab1 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -38,6 +38,7 @@ #include #include #include +#include "config.h" #include "getdns/getdns.h" #include "dict.h" #include "list.h" @@ -699,7 +700,11 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) return NULL; dnssec_return_status = completed_request->dnssec_return_status || - completed_request->dnssec_return_only_secure; + completed_request->dnssec_return_only_secure +#ifdef DNSSEC_ROADBLOCK_AVOIDANCE + || completed_request->dnssec_roadblock_avoidance +#endif + ; if (completed_request->netreqs[0]->request_type == GETDNS_RRTYPE_A || completed_request->netreqs[0]->request_type == GETDNS_RRTYPE_AAAA) From 51eb2fdf5590efda9a4dafef5971e5bef26245b9 Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 12:47:49 +0900 Subject: [PATCH 08/12] working prototype 6 --- src/dict.c | 1 + src/stub.c | 26 ++++++++++++++++++++++---- src/util-internal.c | 11 ++++------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/dict.c b/src/dict.c index 19e55e0a..dd59d346 100644 --- a/src/dict.c +++ b/src/dict.c @@ -981,6 +981,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, if (!json && (strcmp(item->node.key, "type") == 0 || strcmp(item->node.key, "type_covered") == 0 || + strcmp(item->node.key, "query_type") == 0 || strcmp(item->node.key, "qtype") == 0) && (strval = _getdns_rr_type_name(item->i.data.n))) { if (gldns_buffer_printf( diff --git a/src/stub.c b/src/stub.c index e6974378..b6c6d11d 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1176,6 +1176,19 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp, return STUB_TCP_ERROR; } +static uint64_t +_getdns_get_time_as_uintt64() { + + struct timeval tv; + uint64_t now; + + if (gettimeofday(&tv, NULL)) { + return 0; + } + now = tv.tv_sec * 1000000 + tv.tv_usec; + return now; +} + /**************************/ /* UDP callback functions */ /**************************/ @@ -1237,6 +1250,7 @@ stub_udp_read_cb(void *userarg) netreq->response_len = read; dnsreq->upstreams->current = 0; done: + netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->state = NET_REQ_FINISHED; _getdns_check_dns_req_complete(dnsreq); } @@ -1251,6 +1265,7 @@ stub_udp_write_cb(void *userarg) GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); + netreq->debug_start_time = _getdns_get_time_as_uintt64(); netreq->query_id = arc4random(); GLDNS_ID_SET(netreq->query, netreq->query_id); if (netreq->opt) { @@ -1314,7 +1329,7 @@ stub_tcp_read_cb(void *userarg) netreq->tcp.read_pos - netreq->tcp.read_buf; netreq->tcp.read_buf = NULL; dnsreq->upstreams->current = 0; - + netreq->debug_end_time = _getdns_get_time_as_uintt64(); stub_cleanup(netreq); close(netreq->fd); _getdns_check_dns_req_complete(dnsreq); @@ -1327,7 +1342,7 @@ stub_tcp_write_cb(void *userarg) getdns_network_req *netreq = (getdns_network_req *)userarg; getdns_dns_req *dnsreq = netreq->owner; int q; - + netreq->debug_start_time = _getdns_get_time_as_uintt64(); switch ((q = stub_tcp_write(netreq->fd, &netreq->tcp, netreq))) { case STUB_TCP_AGAIN: return; @@ -1420,7 +1435,7 @@ upstream_read_cb(void *userarg) getdns_eventloop_event_init(&upstream->event, upstream, NULL, upstream_write_cb, NULL)); } - + netreq->debug_end_time = _getdns_get_time_as_uintt64(); /* This also reschedules events for the upstream*/ stub_cleanup(netreq); @@ -1447,7 +1462,10 @@ upstream_write_cb(void *userarg) getdns_network_req *netreq = upstream->write_queue; getdns_dns_req *dnsreq = netreq->owner; int q; - + + /* TODO: think about TCP AGAIN */ + netreq->debug_start_time = _getdns_get_time_as_uintt64(); + DEBUG_STUB("--- WRITE: %s: %p TYPE: %d\n", __FUNCTION__, netreq, netreq->request_type); if (tls_requested(netreq) && tls_should_write(upstream)) diff --git a/src/util-internal.c b/src/util-internal.c index 27932bbc..377395a3 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -724,13 +724,10 @@ _getdns_create_call_debugging_dict(getdns_context *context, getdns_dict_destroy(netreq_debug); return NULL; } - if (getdns_dict_set_int(netreq_debug, "start_time", - netreq->debug_start_time)) { - getdns_dict_destroy(netreq_debug); - return NULL; - } - if (getdns_dict_set_int(netreq_debug, "end_time", - netreq->debug_end_time)) { + + /* TODO: This is not safe */ + uint32_t run_time = (uint32_t)(netreq->debug_end_time - netreq->debug_start_time); + if (getdns_dict_set_int(netreq_debug, "run_time/ms", run_time/1000)) { getdns_dict_destroy(netreq_debug); return NULL; } From 30043d2ba5db279797f123f635f23c86840965ae Mon Sep 17 00:00:00 2001 From: jad Date: Sun, 1 Nov 2015 13:09:18 +0900 Subject: [PATCH 09/12] corrected name --- src/util-internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util-internal.c b/src/util-internal.c index 377395a3..6ff02bb2 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -879,7 +879,7 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_list_destroy(replies_full); if (completed_request->return_call_debugging) { - if (getdns_dict_set_list(result, "return_call_debugging", call_debugging)) + if (getdns_dict_set_list(result, "call_debugging", call_debugging)) goto error_free_call_debugging; } From b062974fb17e968f256406128133a76d5b53cd52 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 1 Nov 2015 15:48:31 +0900 Subject: [PATCH 10/12] ub_setup_recursion also for non roadblock avoidance --- src/context.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/context.c b/src/context.c index ee96dbe5..179a8a88 100644 --- a/src/context.c +++ b/src/context.c @@ -2135,7 +2135,6 @@ ub_setup_stub(struct ub_ctx *ctx, getdns_context *context) #endif -#ifdef DNSSEC_ROADBLOCK_AVOIDANCE static getdns_return_t ub_setup_recursing(struct ub_ctx *ctx, getdns_context *context) { @@ -2160,7 +2159,6 @@ ub_setup_recursing(struct ub_ctx *ctx, getdns_context *context) } return GETDNS_RETURN_GOOD; } -#endif static getdns_return_t _getdns_ns_dns_setup(struct getdns_context *context) From 3a1905041315cf15f1a4441053de8ecf314de932 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 4 Nov 2015 16:17:53 +0900 Subject: [PATCH 11/12] Code review changes Commented inline on github --- src/util-internal.c | 137 ++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 74 deletions(-) diff --git a/src/util-internal.c b/src/util-internal.c index 6ff02bb2..ece41d3c 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -672,81 +672,68 @@ success: } getdns_dict * -_getdns_create_call_debugging_dict(getdns_context *context, - getdns_network_req *netreq, - getdns_dict *reply) { +_getdns_create_call_debugging_dict( + getdns_context *context, getdns_network_req *netreq) +{ + getdns_bindata qname; + getdns_dict *netreq_debug; + getdns_dict *address_debug = NULL; - getdns_bindata *qname = NULL; - uint32_t qtype; - getdns_dict *question = NULL; - if (getdns_dict_get_dict(reply, "question", &question)) { - return NULL; - } - if (getdns_dict_get_bindata(question, "qname", &qname)) { - return NULL; - } - if (getdns_dict_get_int(question, "qtype", &qtype)) { - return NULL; - } + assert(netreq); /* It is the responsibility of the caller to free this */ - getdns_dict *netreq_debug = getdns_dict_create_with_context(context); - if (netreq_debug == NULL) { + if (!(netreq_debug = getdns_dict_create_with_context(context))) return NULL; - } - getdns_dict *address_debug = getdns_dict_create_with_context(context); - if (address_debug == NULL){ - getdns_dict_destroy(netreq_debug); - return NULL; - } - _getdns_sockaddr_to_dict(context, &netreq->upstream->addr, &address_debug); + qname.data = netreq->owner->name; + qname.size = netreq->owner->name_len; + + if (getdns_dict_set_bindata(netreq_debug, "query_name", &qname) || + getdns_dict_set_int( netreq_debug, "query_type" + , netreq->request_type ) || + + /* Safe, because uint32_t facilitates RRT's of almost 50 days*/ + getdns_dict_set_int(netreq_debug, "run_time/ms", + (uint32_t)(( netreq->debug_end_time + - netreq->debug_start_time)/1000))) { - if (getdns_dict_set_bindata(netreq_debug, "query_name", qname)) { getdns_dict_destroy(netreq_debug); - getdns_dict_destroy(address_debug); return NULL; - } - if (getdns_dict_set_int(netreq_debug, "query_type", qtype)) { - getdns_dict_destroy(netreq_debug); + + } else if (!netreq->upstream) + + /* Nothing more for full recursion */ + return netreq_debug; + + + /* Stub resolver debug data */ + _getdns_sockaddr_to_dict( + context, &netreq->upstream->addr, &address_debug); + + if (getdns_dict_set_dict(netreq_debug, "query_to", address_debug) || + getdns_dict_set_int( netreq_debug, "transport" + , netreq->upstream->transport)) { + getdns_dict_destroy(address_debug); - return NULL; - } - if (getdns_dict_set_dict(netreq_debug, "query_to", address_debug)) { getdns_dict_destroy(netreq_debug); - getdns_dict_destroy(address_debug); return NULL; } getdns_dict_destroy(address_debug); + + if (netreq->upstream->transport != GETDNS_TRANSPORT_TLS) + return netreq_debug; - if (getdns_dict_set_int(netreq_debug, "transport", - netreq->upstream->transport)) { - getdns_dict_destroy(netreq_debug); - return NULL; - } - - /* TODO: This is not safe */ - uint32_t run_time = (uint32_t)(netreq->debug_end_time - netreq->debug_start_time); - if (getdns_dict_set_int(netreq_debug, "run_time/ms", run_time/1000)) { - getdns_dict_destroy(netreq_debug); - return NULL; - } /* Only include the auth status if TLS was used */ - if (netreq->upstream->transport == GETDNS_TRANSPORT_TLS) { - if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status", - netreq->debug_tls_auth_status == 0 ? - "OK: Hostname matched valid cert." : - "FAILED: Server not validated.")) { - getdns_dict_destroy(netreq_debug); - return NULL; - } + if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status", + netreq->debug_tls_auth_status == 0 ? + "OK: Hostname matched valid cert":"FAILED: Server not validated")){ + + getdns_dict_destroy(netreq_debug); + return NULL; } - return netreq_debug; - } - getdns_dict * _getdns_create_getdns_response(getdns_dns_req *completed_request) { @@ -754,13 +741,14 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) getdns_list *just_addrs = NULL; getdns_list *replies_full; getdns_list *replies_tree; - getdns_list *call_debugging; + getdns_list *call_debugging = NULL; getdns_network_req *netreq, **netreq_p; int rrsigs_in_answer = 0; getdns_dict *reply; getdns_bindata *canonical_name = NULL; int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0; getdns_bindata full_data; + getdns_dict *netreq_debug; /* info (bools) about dns_req */ int dnssec_return_status; @@ -790,10 +778,9 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) if (!(replies_tree = getdns_list_create_with_context(context))) goto error_free_replies_full; - if (completed_request->return_call_debugging) { - if (!(call_debugging = getdns_list_create_with_context(context))) - goto error_free_result; - } + if (completed_request->return_call_debugging && + !(call_debugging = getdns_list_create_with_context(context))) + goto error_free_replies_full; for ( netreq_p = completed_request->netreqs ; (netreq = *netreq_p) ; netreq_p++) { @@ -852,13 +839,17 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error; } - if (completed_request->return_call_debugging) { - getdns_dict *netreq_debug; - if (!(netreq_debug = _getdns_create_call_debugging_dict(context, - netreq, reply))) { + if (call_debugging) { + if (!(netreq_debug = + _getdns_create_call_debugging_dict(context,netreq))) + goto error; + + if (_getdns_list_append_dict( + call_debugging, netreq_debug)) { + + getdns_dict_destroy(netreq_debug); goto error; } - _getdns_list_append_dict(call_debugging, netreq_debug); getdns_dict_destroy(netreq_debug); } @@ -874,15 +865,14 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) goto error; getdns_list_destroy(replies_tree); + if (call_debugging && + getdns_dict_set_list(result, "call_debugging", call_debugging)) + goto error_free_call_debugging; + if (getdns_dict_set_list(result, "replies_full", replies_full)) goto error_free_replies_full; getdns_list_destroy(replies_full); - if (completed_request->return_call_debugging) { - if (getdns_dict_set_list(result, "call_debugging", call_debugging)) - goto error_free_call_debugging; - } - if (just_addrs && getdns_dict_set_list( result, GETDNS_STR_KEY_JUST_ADDRS, just_addrs)) goto error_free_result; @@ -902,11 +892,10 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) error: /* cleanup */ getdns_list_destroy(replies_tree); +error_free_call_debugging: + getdns_list_destroy(call_debugging); error_free_replies_full: getdns_list_destroy(replies_full); -error_free_call_debugging: - if (completed_request->return_call_debugging) - getdns_list_destroy(call_debugging); error_free_result: getdns_list_destroy(just_addrs); getdns_dict_destroy(result); From eb4ba438f72fb577fb86344913c5146365b29f44 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 5 Nov 2015 07:11:51 +0900 Subject: [PATCH 12/12] return_validation_chain + roadblock_avoidance bug --- src/dnssec.c | 20 ++++++++++++++++---- src/request-internal.c | 34 +++++++++++++++++++++++++++++----- src/types-internal.h | 2 ++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/dnssec.c b/src/dnssec.c index 1629764e..db0b7caa 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -1108,6 +1108,15 @@ static void add_question2val_chain(struct mem_funcs *mf, /************* Schedule Queries to Provision Validation Chain *************** *****************************************************************************/ +static getdns_dict *CD_extension(getdns_dns_req *dnsreq) +{ + return !dnsreq->dnssec_roadblock_avoidance + ? dnssec_ok_checking_disabled + : !dnsreq->avoid_dnssec_roadblocks + ? dnssec_ok_checking_disabled_roadblock_avoidance + : dnssec_ok_checking_disabled_avoid_roadblocks; +} + static void check_chain_complete(chain_head *chain); static void val_chain_node_soa_cb(getdns_dns_req *dnsreq); static void val_chain_sched_soa_node(chain_node *node) @@ -1127,7 +1136,7 @@ static void val_chain_sched_soa_node(chain_node *node) if (! node->soa_req && ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA, - dnssec_ok_checking_disabled, node, &dnsreq, NULL, + CD_extension(node->chains->netreq->owner), node, &dnsreq, NULL, val_chain_node_soa_cb)) node->soa_req = dnsreq->netreqs[0]; @@ -1174,13 +1183,15 @@ static void val_chain_sched_node(chain_node *node) if (! node->dnskey_req /* not scheduled */ && ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY, - dnssec_ok_checking_disabled, node, &dnsreq, NULL, val_chain_node_cb)) + CD_extension(node->chains->netreq->owner), + node, &dnsreq, NULL, val_chain_node_cb)) node->dnskey_req = dnsreq->netreqs[0]; if (! node->ds_req && node->parent /* not root */ && ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, - dnssec_ok_checking_disabled, node, &dnsreq, NULL, val_chain_node_cb)) + CD_extension(node->chains->netreq->owner), + node, &dnsreq, NULL, val_chain_node_cb)) node->ds_req = dnsreq->netreqs[0]; } @@ -1216,7 +1227,8 @@ static void val_chain_sched_ds_node(chain_node *node) if (! node->ds_req && node->parent /* not root */ && ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, - dnssec_ok_checking_disabled, node, &ds_req, NULL, val_chain_node_cb)) + CD_extension(node->chains->netreq->owner), + node, &ds_req, NULL, val_chain_node_cb)) node->ds_req = ds_req->netreqs[0]; } diff --git a/src/request-internal.c b/src/request-internal.c index e18d384d..5c8de2bc 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -48,6 +48,21 @@ getdns_dict dnssec_ok_checking_disabled_spc = { }; getdns_dict *dnssec_ok_checking_disabled = &dnssec_ok_checking_disabled_spc; +getdns_dict dnssec_ok_checking_disabled_roadblock_avoidance_spc = { + { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp }, + { 0 } +}; +getdns_dict *dnssec_ok_checking_disabled_roadblock_avoidance + = &dnssec_ok_checking_disabled_roadblock_avoidance_spc; + +getdns_dict dnssec_ok_checking_disabled_avoid_roadblocks_spc = { + { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp }, + { 0 } +}; +getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks + = &dnssec_ok_checking_disabled_avoid_roadblocks_spc; + + static int is_extension_set(getdns_dict *extensions, const char *extension) { @@ -56,7 +71,9 @@ is_extension_set(getdns_dict *extensions, const char *extension) if (! extensions) return 0; - else if (extensions == dnssec_ok_checking_disabled) + else if (extensions == dnssec_ok_checking_disabled + || extensions == dnssec_ok_checking_disabled_roadblock_avoidance + || extensions == dnssec_ok_checking_disabled_avoid_roadblocks) return 0; r = getdns_dict_get_int(extensions, extension, &value); @@ -297,14 +314,19 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, int edns_cookies = is_extension_set(extensions, "edns_cookies"); #ifdef DNSSEC_ROADBLOCK_AVOIDANCE + int avoid_dnssec_roadblocks + = (extensions == dnssec_ok_checking_disabled_avoid_roadblocks); int dnssec_roadblock_avoidance = is_extension_set(extensions, "dnssec_roadblock_avoidance") - || (extensions == dnssec_ok_checking_disabled); + || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance) + || avoid_dnssec_roadblocks; #endif int dnssec_extension_set = dnssec_return_status || dnssec_return_only_secure || dnssec_return_validation_chain || (extensions == dnssec_ok_checking_disabled) + || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance) + || (extensions == dnssec_ok_checking_disabled_avoid_roadblocks) #ifdef DNSSEC_ROADBLOCK_AVOIDANCE || dnssec_roadblock_avoidance #endif @@ -343,7 +365,9 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz; uint8_t *region; - if (extensions == dnssec_ok_checking_disabled) + if (extensions == dnssec_ok_checking_disabled || + extensions == dnssec_ok_checking_disabled_roadblock_avoidance || + extensions == dnssec_ok_checking_disabled_avoid_roadblocks) extensions = NULL; have_add_opt_parameters = getdns_dict_get_dict(extensions, @@ -392,7 +416,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, /* (x + 7) / 8 * 8 to align on 8 byte boundries */ #ifdef DNSSEC_ROADBLOCK_AVOIDANCE if (context->resolution_type == GETDNS_RESOLUTION_RECURSING - && !dnssec_roadblock_avoidance) + && (!dnssec_roadblock_avoidance || avoid_dnssec_roadblocks)) #else if (context->resolution_type == GETDNS_RESOLUTION_RECURSING) #endif @@ -459,7 +483,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->edns_cookies = edns_cookies; #ifdef DNSSEC_ROADBLOCK_AVOIDANCE result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance; - result->avoid_dnssec_roadblocks = 0; + result->avoid_dnssec_roadblocks = avoid_dnssec_roadblocks; #endif result->edns_client_subnet_private = context->edns_client_subnet_private; result->tls_query_padding_blocksize = context->tls_query_padding_blocksize; diff --git a/src/types-internal.h b/src/types-internal.h index 7fdd6f71..c1ca1e3e 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -364,6 +364,8 @@ typedef struct getdns_dns_req { /* utility methods */ extern getdns_dict *dnssec_ok_checking_disabled; +extern getdns_dict *dnssec_ok_checking_disabled_roadblock_avoidance; +extern getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks; /* dns request utils */ getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,