Fix callbacks during scheduling in DNSSEC code too

This commit is contained in:
Willem Toorop 2016-04-22 14:09:18 +02:00
parent 15271d0438
commit d61e64c9c7
3 changed files with 35 additions and 11 deletions

View File

@ -736,6 +736,8 @@ typedef struct chain_node chain_node;
struct chain_head { struct chain_head {
struct mem_funcs my_mf; struct mem_funcs my_mf;
size_t lock;
chain_head *next; chain_head *next;
chain_node *parent; chain_node *parent;
size_t node_count; /* Number of nodes attached directly size_t node_count; /* Number of nodes attached directly
@ -857,6 +859,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
head = *chain_p = (chain_head *)region; head = *chain_p = (chain_head *)region;
head->my_mf = *mf; head->my_mf = *mf;
head->lock = 1;
head->next = NULL; head->next = NULL;
head->rrset.name = head->name_spc; head->rrset.name = head->name_spc;
memcpy(head->name_spc, rrset->name, dname_len); memcpy(head->name_spc, rrset->name, dname_len);
@ -1319,6 +1322,7 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq)
default : check_chain_complete(node->chains); default : check_chain_complete(node->chains);
return; return;
} }
node->lock++;
n_signers = 0; n_signers = 0;
for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len) for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len)
; i ; i
@ -1344,6 +1348,7 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq)
*/ */
val_chain_sched_soa_node(node->parent); val_chain_sched_soa_node(node->parent);
node->lock--;
check_chain_complete(node->chains); check_chain_complete(node->chains);
} }
@ -1363,17 +1368,21 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq)
! _dname_equal(node->ds.name, rrset->name)) ! _dname_equal(node->ds.name, rrset->name))
node = node->parent; node = node->parent;
if (node) if (node) {
node->lock++;
val_chain_sched_ds_node(node); val_chain_sched_ds_node(node);
else { } else {
/* SOA for a different name */ /* SOA for a different name */
node = (chain_node *)dnsreq->user_pointer; node = (chain_node *)dnsreq->user_pointer;
node->lock++;
val_chain_sched_soa_node(node->parent); val_chain_sched_soa_node(node->parent);
} }
} else if (node->parent) } else if (node->parent) {
node->lock++;
val_chain_sched_soa_node(node->parent); val_chain_sched_soa_node(node->parent);
}
node->lock--;
check_chain_complete(node->chains); check_chain_complete(node->chains);
} }
@ -3003,7 +3012,7 @@ static size_t count_outstanding_requests(chain_head *head)
if (!head) if (!head)
return 0; return 0;
for ( node = head->parent, count = 0 for ( node = head->parent, count = head->lock
; node ; node
; node = node->parent) { ; node = node->parent) {
@ -3245,6 +3254,7 @@ static void check_chain_complete(chain_head *chain)
} }
/* Final user callback */ /* Final user callback */
dnsreq->validating = 0;
_getdns_call_user_callback(dnsreq, response_dict); _getdns_call_user_callback(dnsreq, response_dict);
} }
@ -3252,7 +3262,11 @@ static void check_chain_complete(chain_head *chain)
void _getdns_get_validation_chain(getdns_dns_req *dnsreq) void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
{ {
getdns_network_req *netreq, **netreq_p; getdns_network_req *netreq, **netreq_p;
chain_head *chain = NULL; chain_head *chain = NULL, *chain_p;
if (dnsreq->validating)
return;
dnsreq->validating = 1;
for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) { for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
if (! netreq->response if (! netreq->response
@ -3277,12 +3291,16 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
, netreq , netreq
); );
} }
if (chain) if (chain) {
for (chain_p = chain; chain_p; chain_p = chain_p->next)
chain_p->lock--;
check_chain_complete(chain); check_chain_complete(chain);
else } else {
dnsreq->validating = 0;
_getdns_call_user_callback(dnsreq, _getdns_call_user_callback(dnsreq,
_getdns_create_getdns_response(dnsreq)); _getdns_create_getdns_response(dnsreq));
} }
}
/******************* getdns_validate_dnssec() Function ********************* /******************* getdns_validate_dnssec() Function *********************

View File

@ -903,6 +903,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->finished_next = NULL; result->finished_next = NULL;
result->freed = NULL; result->freed = NULL;
result->validating = 0;
network_req_init(result->netreqs[0], result, network_req_init(result->netreqs[0], result,
request_type, dnssec_extension_set, with_opt, request_type, dnssec_extension_set, with_opt,

View File

@ -304,10 +304,15 @@ typedef struct getdns_dns_req {
int dnssec_ok_checking_disabled; int dnssec_ok_checking_disabled;
int is_sync_request; int is_sync_request;
/* Integer pointed to by pointer will be set to 1 (if set), /* The validating and freed variables are used to make sure a single
* before the request is freed. * code path is followed while processing a DNS request, even when
* To be used by _getdns_submit_netreq only! * callbacks are already fired whilst the registering/scheduling call
* (i.e. ub_resolve_event) has not returned yet.
*
* validating is touched by _getdns_get_validation_chain only and
* freed is touched by _getdns_submit_netreq only
*/ */
int validating;
int *freed; int *freed;
/* internally scheduled request */ /* internally scheduled request */