more cycle checks.

fix for reentrant problem.


git-svn-id: file:///svn/unbound/trunk@1485 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2009-02-18 13:23:17 +00:00
parent c699ba2c40
commit cf068986ff
4 changed files with 25 additions and 17 deletions

View file

@ -1,3 +1,10 @@
18 February 2009: Wouter
- more cycle detection. Also for target queries.
- fixup bug where during deletion of the mesh queries the callbacks
that were reentrant caused assertion failures. Keep the mesh in
a reentrant safe state. Affects libunbound, reload of server,
on quit and flush_requestlist.
13 February 2009: Wouter
- forwarder information now per-thread duplicated.
This keeps it read only for speed, with no locking necessary.

View file

@ -459,15 +459,13 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
* @param subq_ret: if newly allocated, the subquerystate, or NULL if it does
* not need initialisation.
* @param v: if true, validation is done on the subquery.
* @param detcyc: if true, cycle detection is done on the subquery.
* @return false on error (malloc).
*/
static int
generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, struct module_qstate* qstate, int id,
struct iter_qstate* iq, enum iter_state initial_state,
enum iter_state final_state, struct module_qstate** subq_ret, int v,
int detcyc)
enum iter_state final_state, struct module_qstate** subq_ret, int v)
{
struct module_qstate* subq = NULL;
struct iter_qstate* subiq = NULL;
@ -490,13 +488,11 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
if(!v)
qflags |= BIT_CD;
if(detcyc) {
fptr_ok(fptr_whitelist_modenv_detect_cycle(
qstate->env->detect_cycle));
if((*qstate->env->detect_cycle)(qstate, &qinf, qflags, prime)){
log_query_info(VERB_DETAIL, "cycle detected", &qinf);
return 0;
}
fptr_ok(fptr_whitelist_modenv_detect_cycle(
qstate->env->detect_cycle));
if((*qstate->env->detect_cycle)(qstate, &qinf, qflags, prime)){
log_query_info(VERB_DETAIL, "cycle detected", &qinf);
return 0;
}
/* attach subquery, lookup existing or make a new one */
@ -565,7 +561,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq,
* the normal INIT state logic (which would cause an infloop). */
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
&subq, 0, 1)) {
&subq, 0)) {
verbose(VERB_ALGO, "could not prime root");
return 0;
}
@ -634,7 +630,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
* redundant INIT state processing. */
if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 1)) {
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) {
verbose(VERB_ALGO, "could not prime stub");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return 1; /* return 1 to make module stop, with error */
@ -712,7 +708,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq,
if(!generate_sub_request(s->rk.dname, s->rk.dname_len,
ntohs(s->rk.type), ntohs(s->rk.rrset_class),
qstate, id, iq,
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
verbose(VERB_ALGO, "could not generate addr check");
return;
}
@ -747,7 +743,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
if(!generate_sub_request(iq->dp->name, iq->dp->namelen,
LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
verbose(VERB_ALGO, "could not generate ns check");
return;
}
@ -1094,7 +1090,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,
{
struct module_qstate* subq;
if(!generate_sub_request(name, namelen, qtype, qclass, qstate,
id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0))
id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0))
return 0;
if(subq) {
struct iter_qstate* subiq =
@ -1729,7 +1725,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
if(!generate_sub_request(qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate, id, iq,
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
verbose(VERB_ALGO, "could not generate prime check");
}
generate_a_aaaa_check(qstate, iq, id);

View file

@ -191,7 +191,10 @@ static void
mesh_delete_helper(rbnode_t* n, void* ATTR_UNUSED(arg))
{
struct mesh_state* mstate = (struct mesh_state*)n->key;
mesh_state_cleanup(mstate);
/* perform a full delete, not only 'cleanup' routine,
* because other callbacks expect a clean state in the mesh.
* For 're-entrant' calls */
mesh_state_delete(&mstate->s);
}
void

View file

@ -1116,6 +1116,8 @@ serviced_delete(struct serviced_query* sq)
if(p->pc)
portcomm_loweruse(sq->outnet, p->pc);
pending_delete(sq->outnet, p);
/* this call can cause reentrant calls back into the
* mesh */
outnet_send_wait_udp(sq->outnet);
} else {
struct waiting_tcp* p = (struct waiting_tcp*)