From: Wouter Wijngaards Date: Wed, 18 Feb 2009 13:23:17 +0000 (+0000) Subject: more cycle checks. X-Git-Tag: release-1.3.0~138 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf068986ff4e41c644d523883473892ed0100438;p=thirdparty%2Funbound.git more cycle checks. fix for reentrant problem. git-svn-id: file:///svn/unbound/trunk@1485 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index fa41dc759..ed54afe42 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/iterator/iterator.c b/iterator/iterator.c index 878c5c92e..88873c15c 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -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); diff --git a/services/mesh.c b/services/mesh.c index c7a0f837d..10619e555 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -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 diff --git a/services/outside_network.c b/services/outside_network.c index 4d6279145..a5d2374b8 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -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*)