diff --git a/src/request-internal.c b/src/request-internal.c index 69a6718c..70029b09 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -167,6 +167,8 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->transport_count * sizeof(getdns_transport_list_t)); net_req->tls_auth_min = owner->context->tls_auth_min; + net_req->follow_redirects = owner->context->follow_redirects; + /* state variables from the resolver, don't touch */ net_req->upstream = NULL; diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 2e70bab2..44ee0773 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -517,6 +517,8 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n"); fprintf(out, "\t-S\tservice lookup ( is ignored)\n"); fprintf(out, "\t-t \tSet timeout in miliseconds\n"); + fprintf(out, "\t-x\tDo not follow redirects\n"); + fprintf(out, "\t-X\tFollow redirects (default)\n"); fprintf(out, "\t-W\tAppend suffix always (default)\n"); fprintf(out, "\t-1\tAppend suffix only to single label after failure\n"); @@ -1009,6 +1011,14 @@ getdns_return_t parse_args(int argc, char **argv) getdns_context_set_timeout( context, timeout); goto next; + case 'x': + getdns_context_set_follow_redirects( + context, GETDNS_REDIRECTS_DO_NOT_FOLLOW); + break; + case 'X': + getdns_context_set_follow_redirects( + context, GETDNS_REDIRECTS_FOLLOW); + break; case 'e': if (c[1] != 0 || ++i >= argc || !*argv[i]) { fprintf(stderr, "idle timeout expected " diff --git a/src/test/tpkg/125-valgrind-checks.tpkg/125-valgrind-checks.test b/src/test/tpkg/125-valgrind-checks.tpkg/125-valgrind-checks.test index 49f2cb75..60f216c7 100644 --- a/src/test/tpkg/125-valgrind-checks.tpkg/125-valgrind-checks.test +++ b/src/test/tpkg/125-valgrind-checks.tpkg/125-valgrind-checks.test @@ -11,6 +11,10 @@ qwerlkjhasdfpuiqwyerm.1234kjhrqwersv.com -G TXT bogus.nlnetlabs.nl -H 8.8.8.8 -H 2a04:b900:0:100::37 +-a -A -x www.microsoft.com +-s +-S +-X EOT ( if ! "${BUILDDIR}/build/libtool" exec valgrind -v --log-file=valgrind.log --leak-check=full --error-exitcode=1 --track-origins=yes "${GETDNS_QUERY}" -F queries -f "${TPKG_NAME}.ds" +dnssec_return_validation_chain diff --git a/src/types-internal.h b/src/types-internal.h index eb7bec31..acd4c7a3 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -205,6 +205,8 @@ typedef struct getdns_network_req */ int tsig_status; + getdns_redirects_t follow_redirects; + /* For stub resolving */ struct getdns_upstream *upstream; int fd; diff --git a/src/util-internal.c b/src/util-internal.c index f55a8752..14912982 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -491,10 +491,13 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, size_t bin_size; const uint8_t *bin_data; gldns_pkt_section section; - uint8_t canonical_name_space[256], owner_name_space[256]; - const uint8_t *canonical_name = canonical_name_space, *owner_name; + uint8_t canonical_name_space[256], owner_name_space[256], + query_name_space[256]; + const uint8_t *canonical_name = canonical_name_space, *owner_name, + *query_name; size_t canonical_name_len = sizeof(canonical_name_space), - owner_name_len = sizeof(owner_name_space); + owner_name_len = sizeof(owner_name_space), + query_name_len = sizeof(query_name_space); int new_canonical = 0, cnames_followed, request_answered, all_numeric_label; uint16_t rr_type; @@ -532,6 +535,15 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, canonical_name = req->owner->name; canonical_name_len = req->owner->name_len; + if (req->query && + (rr_iter = _getdns_rr_iter_init(&rr_iter_storage, req->query + , req->response - req->query))) + + query_name = _getdns_owner_if_or_as_decompressed( + rr_iter, query_name_space, &query_name_len); + else + query_name = NULL; + for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage , req->response , req->response_len) @@ -544,26 +556,44 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, section = _getdns_rr_iter_section(rr_iter); if (section == GLDNS_SECTION_QUESTION) { + if (!query_name) + query_name + = _getdns_owner_if_or_as_decompressed( + rr_iter, query_name_space, &query_name_len); if (_getdns_dict_set_this_dict(result, "question", rr_dict)) goto error; else rr_dict = NULL; continue; } - if (_getdns_list_append_this_dict(sections[section], rr_dict)) - goto error; - else rr_dict = NULL; - rr_type = gldns_read_uint16(rr_iter->rr_type); if (section > GLDNS_SECTION_QUESTION && rr_type == GETDNS_RRTYPE_RRSIG && rrsigs_in_answer) *rrsigs_in_answer = 1; - if (section != GLDNS_SECTION_ANSWER) + if (section != GLDNS_SECTION_ANSWER) { + if (_getdns_list_append_this_dict( + sections[section], rr_dict)) + goto error; + else rr_dict = NULL; continue; + } + if (req->follow_redirects == GETDNS_REDIRECTS_DO_NOT_FOLLOW) { + owner_name_len = sizeof(owner_name_space); + owner_name = _getdns_owner_if_or_as_decompressed( + rr_iter, owner_name_space, &owner_name_len); + + if (!_getdns_dname_equal(query_name, owner_name)) + continue; + } + if (_getdns_list_append_this_dict( + sections[GLDNS_SECTION_ANSWER], rr_dict)) + goto error; + else rr_dict = NULL; if (rr_type == GETDNS_RRTYPE_CNAME) { + owner_name_len = sizeof(owner_name_space); owner_name = _getdns_owner_if_or_as_decompressed( rr_iter, owner_name_space, &owner_name_len); if (!_getdns_dname_equal(canonical_name, owner_name))