diff --git a/src/context.c b/src/context.c index b5eaf231..830c4c53 100644 --- a/src/context.c +++ b/src/context.c @@ -2915,6 +2915,9 @@ _getdns_context_cancel_request(getdns_context *context, &context->outbound_requests, &transaction_id))) return GETDNS_RETURN_UNKNOWN_TRANSACTION; + if (dnsreq->chain) + _getdns_cancel_validation_chain(dnsreq); + /* do the cancel */ cancel_dns_req(dnsreq); diff --git a/src/dnssec.c b/src/dnssec.c index 0269fe3d..905f778d 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -3115,6 +3115,38 @@ static void check_chain_complete(chain_head *chain) _getdns_call_user_callback(dnsreq, response_dict); } +void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) +{ + chain_head *head, *next; + chain_node *node; + size_t node_count; + + for ( head = dnsreq->chain; head ; head = next ) { + next = head->next; + + for ( node_count = head->node_count, node = head->parent + ; node_count + ; node_count--, node = node->parent ) { + + if (node->dnskey_req) + _getdns_context_cancel_request( + node->dnskey_req->owner->context, + node->dnskey_req->owner->trans_id, 0); + + if (node->ds_req) + _getdns_context_cancel_request( + node->ds_req->owner->context, + node->ds_req->owner->trans_id, 0); + + if (node->soa_req) + _getdns_context_cancel_request( + node->soa_req->owner->context, + node->soa_req->owner->trans_id, 0); + } + GETDNS_FREE(head->my_mf, head); + } + dnsreq->chain = NULL; +} void _getdns_get_validation_chain(getdns_dns_req *dnsreq) { @@ -3152,6 +3184,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq) for (chain_p = chain; chain_p; chain_p = chain_p->next) { if (chain_p->lock) chain_p->lock--; } + dnsreq->chain = chain; check_chain_complete(chain); } else { dnsreq->validating = 0; diff --git a/src/dnssec.h b/src/dnssec.h index 4237f933..b7becfe9 100644 --- a/src/dnssec.h +++ b/src/dnssec.h @@ -46,6 +46,7 @@ /* Do some additional requests to fetch the complete validation chain */ void _getdns_get_validation_chain(getdns_dns_req *dns_req); +void _getdns_cancel_validation_chain(getdns_dns_req *dns_req); uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf); diff --git a/src/request-internal.c b/src/request-internal.c index 8193acb7..3f180d56 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -934,6 +934,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->finished_next = NULL; result->freed = NULL; result->validating = 0; + result->chain = NULL; network_req_init(result->netreqs[0], result, request_type, dnssec_extension_set, with_opt, diff --git a/src/types-internal.h b/src/types-internal.h index 2ac85581..137892f1 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -267,6 +267,7 @@ typedef struct getdns_network_req static inline int _getdns_netreq_finished(getdns_network_req *req) { return !req || (req->state & NET_REQ_FINISHED); } +struct chain_head; /** * dns request - manages a number of network requests and * the initial data passed to getdns_general @@ -322,6 +323,9 @@ typedef struct getdns_dns_req { unsigned validating : 1; int *freed; + /* Validation chain to be canceled when this request is canceled */ + struct chain_head *chain; + uint16_t tls_query_padding_blocksize; /* internally scheduled request */