From: Wouter Wijngaards Date: Mon, 4 Jun 2007 12:22:38 +0000 (+0000) Subject: Prime response state, both root priming and stub priming handling. X-Git-Tag: release-0.4~102 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=81ae42fde046214297077cab69ad305a47109ab5;p=thirdparty%2Funbound.git Prime response state, both root priming and stub priming handling. git-svn-id: file:///svn/unbound/trunk@364 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index ebb54cba0..66d9be2b9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,7 @@ - cache lameness in response handling. - do not touch qstate after worker_process_query because it may have been deleted by that routine. + - Prime response state. 1 June 2007: Wouter - normalize incoming messages. Like unbound-java, with CNAME chain diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 422e0ead7..83eaa2186 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -218,6 +218,22 @@ dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, struct region* region) return m; } +struct dns_msg* +dns_copy_msg(struct dns_msg* from, struct region* region) +{ + struct dns_msg* m = (struct dns_msg*)region_alloc(region, + sizeof(struct dns_msg)); + if(!m) + return NULL; + m->qinfo = from->qinfo; + if(!(m->qinfo.qname = region_alloc_init(region, from->qinfo.qname, + from->qinfo.qname_len))) + return NULL; + if(!(m->rep = reply_info_copy(from->rep, NULL, region))) + return NULL; + return m; +} + int iter_dns_store(struct module_env* env, struct dns_msg* msg, int is_referral) { diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 5a7921bda..89f6f1608 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -86,6 +86,14 @@ struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, struct dns_msg* dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, struct region* region); +/** + * Copy a dns_msg to this region. + * @param from: dns message, also in region. + * @param region: region to use for allocation. + * @return newly allocated dns_msg, or NULL on memory error. + */ +struct dns_msg* dns_copy_msg(struct dns_msg* from, struct region* region); + /** * Allocate a dns_msg with malloc/alloc structure and store in dns cache. * @param env: environment, with alloc structure and dns cache. diff --git a/iterator/iterator.c b/iterator/iterator.c index 581716e45..3e289e88c 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1197,15 +1197,67 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, return next_state(qstate, iq, QUERYTARGETS_STATE); } -#if 0 -/** TODO */ +/** + * This handles the response to a priming query. This is used to handle both + * root and stub priming responses. This is basically the equivalent of the + * QUERY_RESP_STATE, but will not handle CNAME responses and will treat + * REFERRALs as ANSWERS. It will also update and reactivate the originating + * event. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @return true if the event needs more immediate processing, false if not. + * This state always returns false. + */ static int processPrimeResponse(struct module_qstate* qstate, struct iter_qstate* iq, - struct iter_env* ie, int id) + int id) { + struct module_qstate* forq = qstate->parent; + struct iter_qstate* foriq; + struct delegpt* dp = NULL; + enum response_type type = response_type_from_server(iq->response, + &qstate->qinfo, iq->dp); + log_assert(qstate->parent); /* this is a subrequest of another */ + if(type == RESPONSE_TYPE_ANSWER) { + /* Convert our response to a delegation point */ + dp = delegpt_from_message(iq->response, forq->region); + } + if(!dp) { + /* if there is no convertable delegation point, then + * the ANSWER type was (presumably) a negative answer. */ + verbose(VERB_ALGO, "prime response was not a positive " + "ANSWER; failing"); + /* note that this will call the forevent with event error. */ + qstate->ext_state[id] = module_error; + return 0; + } + + log_nametypeclass("priming successful for", qstate->qinfo.qname, + qstate->qinfo.qtype, qstate->qinfo.qclass); + /* This event is finished. */ + qstate->ext_state[id] = module_finished; + foriq = (struct iter_qstate*)forq->minfo[id]; + foriq->dp = dp; + foriq->response = dns_copy_msg(iq->response, forq->region); + if(!foriq->response) { + log_err("copy prime response: out of memory"); + /* note that this will call the forevent with event error. */ + qstate->ext_state[id] = module_error; + return 0; + } + + /* root priming responses go to init stage 2, priming stub + * responses to to stage 3. */ + if(iq->priming_stub) + foriq->state = INIT_REQUEST_3_STATE; + else foriq->state = INIT_REQUEST_2_STATE; + /* because we are finished, the parent will be reactivated */ return 0; } +#if 0 /** TODO */ static int processTargetResponse(struct module_qstate* qstate, struct iter_qstate* iq, @@ -1259,10 +1311,10 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq, case QUERY_RESP_STATE: cont = processQueryResponse(qstate, iq, id); break; -#if 0 case PRIME_RESP_STATE: - cont = processPrimeResponse(qstate, iq, ie, id); + cont = processPrimeResponse(qstate, iq, id); break; +#if 0 case TARGET_RESP_STATE: cont = processTargetResponse(qstate, iq, ie, id); break; @@ -1387,6 +1439,11 @@ iter_operate(struct module_qstate* qstate, enum module_ev event, int id, process_response(qstate, iq, ie, id, outbound, event); return; } + if(event == module_event_error) { + verbose(VERB_ALGO, "got called with event error, giving up"); + qstate->ext_state[id] = module_error; + return; + } log_err("bad event for iterator"); qstate->ext_state[id] = module_error;