mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'devel/scheduling_bug_detection' into features/canonical_dnssec_chain
This commit is contained in:
commit
af8e27f059
36
src/dnssec.c
36
src/dnssec.c
|
@ -719,6 +719,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
|
||||||
|
@ -840,6 +842,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);
|
||||||
|
@ -1302,6 +1305,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
|
||||||
|
@ -1327,6 +1331,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1346,17 +1351,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2972,7 +2981,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) {
|
||||||
|
|
||||||
|
@ -3221,7 +3230,7 @@ static void check_chain_complete(chain_head *chain)
|
||||||
&& !dnsreq->avoid_dnssec_roadblocks
|
&& !dnsreq->avoid_dnssec_roadblocks
|
||||||
&& dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) {
|
&& dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) {
|
||||||
|
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
int r = GETDNS_RETURN_GOOD;
|
||||||
getdns_network_req **netreq_p, *netreq;
|
getdns_network_req **netreq_p, *netreq;
|
||||||
|
|
||||||
dnsreq->avoid_dnssec_roadblocks = 1;
|
dnsreq->avoid_dnssec_roadblocks = 1;
|
||||||
|
@ -3302,6 +3311,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3309,7 +3319,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
|
||||||
|
@ -3334,11 +3348,15 @@ 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,7 @@ void
|
||||||
_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
||||||
{
|
{
|
||||||
getdns_network_req **netreq_p, *netreq;
|
getdns_network_req **netreq_p, *netreq;
|
||||||
int results_found = 0;
|
int results_found = 0, r;
|
||||||
|
|
||||||
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++)
|
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++)
|
||||||
if (netreq->state != NET_REQ_FINISHED &&
|
if (netreq->state != NET_REQ_FINISHED &&
|
||||||
|
@ -198,8 +198,11 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
||||||
; (netreq = *netreq_p)
|
; (netreq = *netreq_p)
|
||||||
; netreq_p++ ) {
|
; netreq_p++ ) {
|
||||||
_getdns_netreq_reinit(netreq);
|
_getdns_netreq_reinit(netreq);
|
||||||
if (_getdns_submit_netreq(netreq))
|
if ((r = _getdns_submit_netreq(netreq))) {
|
||||||
|
if (r == DNS_REQ_FINISHED)
|
||||||
|
return;
|
||||||
netreq->state = NET_REQ_FINISHED;
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_getdns_check_dns_req_complete(dns_req);
|
_getdns_check_dns_req_complete(dns_req);
|
||||||
return;
|
return;
|
||||||
|
@ -233,8 +236,11 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
||||||
; (netreq = *netreq_p)
|
; (netreq = *netreq_p)
|
||||||
; netreq_p++ ) {
|
; netreq_p++ ) {
|
||||||
_getdns_netreq_reinit(netreq);
|
_getdns_netreq_reinit(netreq);
|
||||||
if (_getdns_submit_netreq(netreq))
|
if ((r = _getdns_submit_netreq(netreq))) {
|
||||||
|
if (r == DNS_REQ_FINISHED)
|
||||||
|
return;
|
||||||
netreq->state = NET_REQ_FINISHED;
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_getdns_check_dns_req_complete(dns_req);
|
_getdns_check_dns_req_complete(dns_req);
|
||||||
return;
|
return;
|
||||||
|
@ -312,13 +318,16 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
getdns_return_t
|
int
|
||||||
_getdns_submit_netreq(getdns_network_req *netreq)
|
_getdns_submit_netreq(getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
getdns_return_t r;
|
getdns_return_t r;
|
||||||
getdns_dns_req *dns_req = netreq->owner;
|
getdns_dns_req *dns_req = netreq->owner;
|
||||||
char name[1024];
|
char name[1024];
|
||||||
|
int dnsreq_freed = 0;
|
||||||
|
#ifdef HAVE_LIBUNBOUND
|
||||||
|
int ub_resolve_r;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef STUB_NATIVE_DNSSEC
|
#ifdef STUB_NATIVE_DNSSEC
|
||||||
# ifdef DNSSEC_ROADBLOCK_AVOIDANCE
|
# ifdef DNSSEC_ROADBLOCK_AVOIDANCE
|
||||||
|
@ -351,24 +360,34 @@ _getdns_submit_netreq(getdns_network_req *netreq)
|
||||||
dns_req->name_len, name, sizeof(name));
|
dns_req->name_len, name, sizeof(name));
|
||||||
|
|
||||||
#ifdef HAVE_LIBUNBOUND
|
#ifdef HAVE_LIBUNBOUND
|
||||||
|
dns_req->freed = &dnsreq_freed;
|
||||||
#ifdef HAVE_UNBOUND_EVENT_API
|
#ifdef HAVE_UNBOUND_EVENT_API
|
||||||
if (_getdns_ub_loop_enabled(&dns_req->context->ub_loop))
|
if (_getdns_ub_loop_enabled(&dns_req->context->ub_loop))
|
||||||
return ub_resolve_event(dns_req->context->unbound_ctx,
|
ub_resolve_r = ub_resolve_event(dns_req->context->unbound_ctx,
|
||||||
name, netreq->request_type, netreq->owner->request_class,
|
name, netreq->request_type, netreq->owner->request_class,
|
||||||
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ?
|
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ?
|
||||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
return ub_resolve_async(dns_req->context->unbound_ctx,
|
ub_resolve_r = ub_resolve_async(dns_req->context->unbound_ctx,
|
||||||
name, netreq->request_type, netreq->owner->request_class,
|
name, netreq->request_type, netreq->owner->request_class,
|
||||||
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
||||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||||
|
if (dnsreq_freed)
|
||||||
|
return DNS_REQ_FINISHED;
|
||||||
|
dns_req->freed = NULL;
|
||||||
|
return ub_resolve_r ? GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||||
#else
|
#else
|
||||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* Submit with stub resolver */
|
/* Submit with stub resolver */
|
||||||
return _getdns_submit_stub_request(netreq);
|
dns_req->freed = &dnsreq_freed;
|
||||||
|
r = _getdns_submit_stub_request(netreq);
|
||||||
|
if (dnsreq_freed)
|
||||||
|
return DNS_REQ_FINISHED;
|
||||||
|
dns_req->freed = NULL;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -457,7 +476,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
||||||
void *userarg, getdns_network_req **return_netreq_p,
|
void *userarg, getdns_network_req **return_netreq_p,
|
||||||
getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces)
|
getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces)
|
||||||
{
|
{
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
int r = GETDNS_RETURN_GOOD;
|
||||||
getdns_network_req *netreq, **netreq_p;
|
getdns_network_req *netreq, **netreq_p;
|
||||||
getdns_dns_req *req;
|
getdns_dns_req *req;
|
||||||
getdns_dict *localnames_response;
|
getdns_dict *localnames_response;
|
||||||
|
@ -496,8 +515,16 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
||||||
/* issue all network requests */
|
/* issue all network requests */
|
||||||
for ( netreq_p = req->netreqs
|
for ( netreq_p = req->netreqs
|
||||||
; !r && (netreq = *netreq_p)
|
; !r && (netreq = *netreq_p)
|
||||||
; netreq_p++)
|
; netreq_p++) {
|
||||||
r = _getdns_submit_netreq(netreq);
|
if ((r = _getdns_submit_netreq(netreq))) {
|
||||||
|
if (r == DNS_REQ_FINISHED) {
|
||||||
|
if (return_netreq_p)
|
||||||
|
*return_netreq_p = NULL;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else for (i = 0; i < context->namespace_count; i++) {
|
else for (i = 0; i < context->namespace_count; i++) {
|
||||||
if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) {
|
if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) {
|
||||||
|
@ -518,14 +545,21 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
|
||||||
r = GETDNS_RETURN_GOOD;
|
r = GETDNS_RETURN_GOOD;
|
||||||
for ( netreq_p = req->netreqs
|
for ( netreq_p = req->netreqs
|
||||||
; !r && (netreq = *netreq_p)
|
; !r && (netreq = *netreq_p)
|
||||||
; netreq_p++)
|
; netreq_p++) {
|
||||||
r = _getdns_submit_netreq(netreq);
|
if ((r = _getdns_submit_netreq(netreq))) {
|
||||||
|
if (r == DNS_REQ_FINISHED) {
|
||||||
|
if (return_netreq_p)
|
||||||
|
*return_netreq_p = NULL;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
r = GETDNS_RETURN_BAD_CONTEXT;
|
r = GETDNS_RETURN_BAD_CONTEXT;
|
||||||
}
|
}
|
||||||
|
if (r > 0) { /* i.e. r != GETDNS_RETURN_GOOD && r != DNS_REQ_FINISHED */
|
||||||
if (r != 0) {
|
|
||||||
/* clean up the request */
|
/* clean up the request */
|
||||||
_getdns_context_clear_outbound_request(req);
|
_getdns_context_clear_outbound_request(req);
|
||||||
_getdns_dns_req_free(req);
|
_getdns_dns_req_free(req);
|
||||||
|
|
|
@ -42,9 +42,11 @@
|
||||||
|
|
||||||
/* private inner helper used by sync and async */
|
/* private inner helper used by sync and async */
|
||||||
|
|
||||||
|
#define DNS_REQ_FINISHED -1
|
||||||
|
|
||||||
void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *);
|
void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *);
|
||||||
void _getdns_check_dns_req_complete(getdns_dns_req *dns_req);
|
void _getdns_check_dns_req_complete(getdns_dns_req *dns_req);
|
||||||
getdns_return_t _getdns_submit_netreq(getdns_network_req *netreq);
|
int _getdns_submit_netreq(getdns_network_req *netreq);
|
||||||
|
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
|
|
|
@ -640,7 +640,8 @@ _getdns_dns_req_free(getdns_dns_req * req)
|
||||||
req->loop->vmt->clear(req->loop, &req->timeout);
|
req->loop->vmt->clear(req->loop, &req->timeout);
|
||||||
req->timeout.timeout_cb = NULL;
|
req->timeout.timeout_cb = NULL;
|
||||||
}
|
}
|
||||||
|
if (req->freed)
|
||||||
|
*req->freed = 1;
|
||||||
GETDNS_FREE(req->my_mf, req);
|
GETDNS_FREE(req->my_mf, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,6 +908,8 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
result->upstreams->referenced++;
|
result->upstreams->referenced++;
|
||||||
|
|
||||||
result->finished_next = NULL;
|
result->finished_next = 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,
|
||||||
|
|
|
@ -6,8 +6,12 @@
|
||||||
|
|
||||||
cat >queries <<EOT
|
cat >queries <<EOT
|
||||||
NS .
|
NS .
|
||||||
|
localhost
|
||||||
|
localhost.
|
||||||
|
A localhost.
|
||||||
-A getdnsapi.net
|
-A getdnsapi.net
|
||||||
qwerlkjhasdfpuiqwyerm.1234kjhrqwersv.com
|
qwerlkjhasdfpuiqwyerm.1234kjhrqwersv.com
|
||||||
|
localhost.
|
||||||
-G TXT bogus.nlnetlabs.nl
|
-G TXT bogus.nlnetlabs.nl
|
||||||
-H 8.8.8.8
|
-H 8.8.8.8
|
||||||
-H 2a04:b900:0:100::37
|
-H 2a04:b900:0:100::37
|
||||||
|
|
|
@ -5,4 +5,10 @@
|
||||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||||
|
|
||||||
cd "${BUILDDIR}/build-event-loops"
|
cd "${BUILDDIR}/build-event-loops"
|
||||||
make test
|
if make test
|
||||||
|
then
|
||||||
|
if grep ERROR "${BUILDDIR}/build-event-loops/src/test/*.log"
|
||||||
|
then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
|
@ -306,6 +306,17 @@ typedef struct getdns_dns_req {
|
||||||
|
|
||||||
uint16_t tls_query_padding_blocksize;
|
uint16_t tls_query_padding_blocksize;
|
||||||
|
|
||||||
|
/* The validating and freed variables are used to make sure a single
|
||||||
|
* code path is followed while processing a DNS request, even when
|
||||||
|
* 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;
|
||||||
|
|
||||||
/* internally scheduled request */
|
/* internally scheduled request */
|
||||||
internal_cb_t internal_cb;
|
internal_cb_t internal_cb;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue