diff --git a/src/dnssec.c b/src/dnssec.c index fda34d10..6c7547c3 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -49,6 +49,7 @@ #include "rr-dict.h" #include "gldns/str2wire.h" #include "gldns/wire2str.h" +#include "general.h" void priv_getdns_call_user_callback(getdns_dns_req *, struct getdns_dict *); @@ -66,7 +67,7 @@ struct chain_response { int sec; char *bogus; struct validation_chain *chain; - int unbound_id; + getdns_transaction_t transaction_id; }; struct chain_link { @@ -181,10 +182,12 @@ static void callback_on_complete_chain(struct validation_chain *chain) static void -ub_chain_response_callback(void *arg, int err, struct ub_result* ub_res) +chain_response_callback(struct getdns_dns_req *dns_req) { - struct chain_response *response = (struct chain_response *) arg; - getdns_context *context = response->chain->dns_req->context; + struct chain_response *response = + (struct chain_response *) dns_req->user_pointer; + getdns_context *context = dns_req->context; + getdns_network_req **netreq_p, *netreq; priv_getdns_rr_iter rr_iter_storage, *rr_iter; priv_getdns_rdf_iter rdf_storage, *rdf; gldns_pkt_section section; @@ -193,52 +196,54 @@ ub_chain_response_callback(void *arg, int err, struct ub_result* ub_res) getdns_list *keys; size_t nkeys; - response->err = err; - response->sec = ub_res ? ub_res->secure : 0; - response->bogus = ub_res ? ub_res->why_bogus : NULL; - - if (ub_res == NULL || ub_res->answer_packet == NULL || + if (dns_req == NULL || !(keys = getdns_list_create_with_context(context))) goto done; - for ( rr_iter = priv_getdns_rr_iter_init(&rr_iter_storage - , ub_res->answer_packet - , ub_res->answer_len) - ; rr_iter - ; rr_iter = priv_getdns_rr_iter_next(rr_iter) - ) { - section = priv_getdns_rr_iter_section(rr_iter); - if (section != GLDNS_SECTION_ANSWER) - continue; + for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) { + for ( rr_iter = priv_getdns_rr_iter_init(&rr_iter_storage + , netreq->response + , netreq->response_len) + ; rr_iter + ; rr_iter = priv_getdns_rr_iter_next(rr_iter) + ) { + section = priv_getdns_rr_iter_section(rr_iter); + if (section != GLDNS_SECTION_ANSWER) + continue; - rr_type = gldns_read_uint16(rr_iter->rr_type); + rr_type = gldns_read_uint16(rr_iter->rr_type); - if (rr_type == GETDNS_RRTYPE_DS || - rr_type == GETDNS_RRTYPE_DNSKEY) { - if (!(rr_dict = priv_getdns_rr_iter2rr_dict(context, rr_iter))) + if (rr_type == GETDNS_RRTYPE_DS || + rr_type == GETDNS_RRTYPE_DNSKEY) { + if (!(rr_dict = priv_getdns_rr_iter2rr_dict( + context, rr_iter))) + continue; + if (getdns_list_append_dict(keys, rr_dict)) + break; + } + if (rr_type != GETDNS_RRTYPE_RRSIG) + continue; + + if (!(rdf = priv_getdns_rdf_iter_init( + &rdf_storage, rr_iter))) + continue; + + type_covered = gldns_read_uint16(rdf->pos); + if (type_covered == GETDNS_RRTYPE_DS) { + if ((rdf = priv_getdns_rdf_iter_init_at( + &rdf_storage, rr_iter, 7))) + launch_chain_link_lookup( + response->chain, rdf); + + } else if (type_covered != GETDNS_RRTYPE_DNSKEY) + continue; + + if (!(rr_dict = priv_getdns_rr_iter2rr_dict( + context, rr_iter))) continue; if (getdns_list_append_dict(keys, rr_dict)) break; } - if (rr_type != GETDNS_RRTYPE_RRSIG) - continue; - - if (!(rdf = priv_getdns_rdf_iter_init(&rdf_storage, rr_iter))) - continue; - - type_covered = gldns_read_uint16(rdf->pos); - if (type_covered == GETDNS_RRTYPE_DS) { - if ((rdf = priv_getdns_rdf_iter_init_at( - &rdf_storage, rr_iter, 7))) - launch_chain_link_lookup(response->chain, rdf); - - } else if (type_covered != GETDNS_RRTYPE_DNSKEY) - continue; - - if (!(rr_dict = priv_getdns_rr_iter2rr_dict(context, rr_iter))) - continue; - if (getdns_list_append_dict(keys, rr_dict)) - break; } if (getdns_list_get_length(keys, &nkeys)) getdns_list_destroy(keys); @@ -248,32 +253,47 @@ ub_chain_response_callback(void *arg, int err, struct ub_result* ub_res) else response->result = keys; - ub_resolve_free(ub_res); done: if (response->err == 0 && response->result == NULL) response->err = -1; - + if (dns_req) { + getdns_context_clear_outbound_request(dns_req); + dns_req_free(dns_req); + } callback_on_complete_chain(response->chain); } static void chain_response_init( struct validation_chain *chain, struct chain_response *response) { - response->err = 0; - response->result = NULL; - response->sec = 0; - response->bogus = NULL; - response->chain = chain; - response->unbound_id = -1; + response->err = 0; + response->result = NULL; + response->sec = 0; + response->bogus = NULL; + response->chain = chain; + response->transaction_id = -1; } static int resolve(char* name, int rrtype, struct chain_response *response) { - return ub_resolve_async( - response->chain->dns_req->context->unbound_ctx, - name, rrtype, GETDNS_RRCLASS_IN, response, - ub_chain_response_callback, &response->unbound_id); + getdns_return_t r; + getdns_dict *extensions; + + if (!(extensions = getdns_dict_create_with_context( + response->chain->dns_req->context))) + return GETDNS_RETURN_MEMORY_ERROR; + + if (!(r = getdns_dict_set_int(extensions, + "dnssec_ok_checking_disabled", GETDNS_EXTENSION_TRUE))) + + r = priv_getdns_general_loop(response->chain->dns_req->context, + response->chain->dns_req->loop, name, rrtype, extensions, + response, &response->transaction_id, NULL, + chain_response_callback); + + getdns_dict_destroy(extensions); + return r; } static void diff --git a/src/general.c b/src/general.c index 12616068..747ed0bb 100644 --- a/src/general.c +++ b/src/general.c @@ -91,7 +91,9 @@ priv_getdns_check_dns_req_complete(getdns_dns_req *dns_req) else if (netreq->response_len > 0) results_found = 1; - if (! results_found) + if (dns_req->internal_cb) + dns_req->internal_cb(dns_req); + else if (! results_found) priv_getdns_call_user_callback(dns_req, NULL); else if (dns_req->dnssec_return_validation_chain #ifdef STUB_NATIVE_DNSSEC @@ -172,7 +174,7 @@ static getdns_return_t getdns_general_ns(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions, void *userarg, getdns_transaction_t *transaction_id, - getdns_callback_t callbackfn, int usenamespaces) + getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces) { getdns_return_t r = GETDNS_RETURN_GOOD; getdns_network_req *netreq, **netreq_p; @@ -180,7 +182,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, getdns_dict *localnames_response; size_t i; - if (!context || !name || !callbackfn) + if (!context || !name || (!callbackfn && !internal_cb)) return GETDNS_RETURN_INVALID_PARAMETER; if ((r = validate_dname(name))) @@ -200,6 +202,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, req->user_pointer = userarg; req->user_callback = callbackfn; + req->internal_cb = internal_cb; if (transaction_id) *transaction_id = req->trans_id; @@ -252,11 +255,11 @@ getdns_return_t priv_getdns_general_loop(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions, void *userarg, getdns_transaction_t *transaction_id, - getdns_callback_t callback) + getdns_callback_t callback, internal_cb_t internal_cb) { return getdns_general_ns(context, loop, name, request_type, extensions, - userarg, transaction_id, callback, 0); + userarg, transaction_id, callback, internal_cb, 0); } /* getdns_general_loop */ @@ -279,7 +282,7 @@ priv_getdns_address_loop(getdns_context *context, getdns_eventloop *loop, r = getdns_general_ns(context, loop, name, GETDNS_RRTYPE_A, extensions, - userarg, transaction_id, callback, 1); + userarg, transaction_id, callback, NULL, 1); if (cleanup_extensions) getdns_dict_destroy(extensions); @@ -370,7 +373,7 @@ priv_getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop, return GETDNS_RETURN_INVALID_PARAMETER; } retval = priv_getdns_general_loop(context, loop, name, req_type, - extensions, userarg, transaction_id, callback); + extensions, userarg, transaction_id, callback, NULL); return retval; } /* getdns_hostname_loop */ @@ -380,7 +383,7 @@ priv_getdns_service_loop(getdns_context *context, getdns_eventloop *loop, getdns_transaction_t * transaction_id, getdns_callback_t callback) { return getdns_general_ns(context, loop, name, GETDNS_RRTYPE_SRV, - extensions, userarg, transaction_id, callback, 1); + extensions, userarg, transaction_id, callback, NULL, 1); } /* getdns_service_loop */ /** @@ -395,7 +398,7 @@ getdns_general(getdns_context *context, if (!context) return GETDNS_RETURN_INVALID_PARAMETER; return priv_getdns_general_loop(context, context->extension, name, request_type, extensions, - userarg, transaction_id, callback); + userarg, transaction_id, callback, NULL); } /* getdns_general */ diff --git a/src/general.h b/src/general.h index d70cd454..055f2f7e 100644 --- a/src/general.h +++ b/src/general.h @@ -49,7 +49,7 @@ getdns_return_t priv_getdns_general_loop(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions, void *userarg, getdns_transaction_t *transaction_id, - getdns_callback_t callbackfn); + getdns_callback_t callbackfn, internal_cb_t internal_cb); getdns_return_t priv_getdns_address_loop(getdns_context *context, getdns_eventloop *loop, diff --git a/src/request-internal.c b/src/request-internal.c index 3afe4d24..58fac938 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -207,8 +207,12 @@ dns_req_new(getdns_context *context, getdns_eventloop *loop, = is_extension_set(extensions, "dnssec_return_only_secure"); int dnssec_return_validation_chain = is_extension_set(extensions, "dnssec_return_validation_chain"); + int dnssec_ok_checking_disabled + = is_extension_set(extensions, "dnssec_ok_checking_disabled"); + int dnssec_extension_set = dnssec_return_status - || dnssec_return_only_secure || dnssec_return_validation_chain; + || dnssec_return_only_secure || dnssec_return_validation_chain + || dnssec_ok_checking_disabled;; uint32_t edns_do_bit; int edns_maximum_udp_payload_size; diff --git a/src/rr-iter.c b/src/rr-iter.c index 0843deeb..f6188307 100644 --- a/src/rr-iter.c +++ b/src/rr-iter.c @@ -86,7 +86,7 @@ priv_getdns_rr_iter_init(priv_getdns_rr_iter *i, uint8_t *pkt, size_t pkt_len) { assert(i); - if (pkt_len < GLDNS_HEADER_SIZE + 5) { + if (!pkt || pkt_len < GLDNS_HEADER_SIZE + 5) { i->pos = NULL; return NULL; } diff --git a/src/sync.c b/src/sync.c index ea44f7d9..66e53a97 100644 --- a/src/sync.c +++ b/src/sync.c @@ -123,7 +123,7 @@ getdns_general_sync(getdns_context *context, const char *name, return r; if ((r = priv_getdns_general_loop(context, &loop.loop.loop, name, - request_type, extensions, &loop, NULL, getdns_sync_cb))) { + request_type, extensions, &loop, NULL, getdns_sync_cb, NULL))) { getdns_sync_loop_cleanup(&loop); return r; diff --git a/src/types-internal.h b/src/types-internal.h index b3b1f981..5c775fd7 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -108,6 +108,7 @@ struct getdns_upstream; struct getdns_dns_req; struct getdns_network_req; +typedef void (*internal_cb_t)(struct getdns_dns_req *dns_req); #define MF_PLAIN ((void *)&plain_mem_funcs_user_arg) extern void *plain_mem_funcs_user_arg; @@ -238,6 +239,12 @@ typedef struct getdns_dns_req { int dnssec_return_only_secure; int dnssec_return_validation_chain; + /* Internally used by return_validation_chain */ + int dnssec_ok_checking_disabled; + + /* internally scheduled request */ + internal_cb_t internal_cb; + /* event loop */ getdns_eventloop *loop; diff --git a/src/util-internal.c b/src/util-internal.c index 4038de2a..4ceef653 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -60,6 +60,7 @@ static getdns_extension_format extformats[] = { {"add_opt_parameters", t_dict}, {"add_warning_for_bad_dns", t_int}, + {"dnssec_ok_checking_disabled", t_int}, {"dnssec_return_only_secure", t_int}, {"dnssec_return_status", t_int}, {"dnssec_return_validation_chain", t_int},