Iterator does not alter qstate identity.

git-svn-id: file:///svn/unbound/trunk@420 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-06-22 13:24:26 +00:00
parent e939a7689f
commit 9a1813e0bf
3 changed files with 63 additions and 82 deletions

View file

@ -4,6 +4,9 @@
set, so that a priming(stub) subquery error can be handled.
- iterator stores if it is priming or not.
- log_query_info() neater logging.
- changed iterator so that it does not alter module_qstate.qinfo
but keeps a chase query info. Also query_flags are not altered,
the iterator uses chase_flags.
21 June 2007: Wouter
- Fixup secondary buffer in case of error callback.

View file

@ -110,9 +110,9 @@ iter_new(struct module_qstate* qstate, int id)
iq->referral_count = 0;
iq->priming = 0;
iq->priming_stub = 0;
iq->orig_qflags = qstate->query_flags;
/* remove all weird bits from the query flags */
qstate->query_flags &= BIT_RD;
iq->chase_flags = qstate->query_flags;
/* Start with the (current) qname. */
iq->qchase = qstate->qinfo;
outbound_list_init(&iq->outlist);
return 1;
}
@ -253,18 +253,9 @@ final_state(struct iter_qstate* iq)
static int
error_response(struct module_qstate* qstate, int id, int rcode)
{
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
verbose(VERB_DETAIL, "return error response %s",
ldns_lookup_by_id(ldns_rcodes, rcode)?
ldns_lookup_by_id(ldns_rcodes, rcode)->name:"??");
if(iq) {
if(iq->orig_qname) {
/* encode original query */
qstate->qinfo.qname = iq->orig_qname;
qstate->qinfo.qname_len = iq->orig_qnamelen;
}
qstate->query_flags = iq->orig_qflags;
}
qinfo_query_encode(qstate->buf, &qstate->qinfo);
LDNS_RCODE_SET(ldns_buffer_begin(qstate->buf), rcode);
LDNS_RA_SET(ldns_buffer_begin(qstate->buf));
@ -317,7 +308,7 @@ iter_prepend(struct iter_qstate* iq, struct dns_msg* msg,
* Encode response message for iterator responses. Into response buffer.
* On error an error message is encoded.
* @param qstate: query state. With qinfo information.
* @param iq: iterator query state. With qinfo original and prepend list.
* @param iq: iterator query state. With prepend list.
* @param msg: answer message.
* @param id: module id (used in error condition).
*/
@ -325,12 +316,7 @@ static void
iter_encode_respmsg(struct module_qstate* qstate, struct iter_qstate* iq,
struct dns_msg* msg, int id)
{
struct query_info qinf = qstate->qinfo;
struct edns_data edns;
if(iq->orig_qname) {
qinf.qname = iq->orig_qname;
qinf.qname_len = iq->orig_qnamelen;
}
if(iq->prepend_list) {
if(!iter_prepend(iq, msg, qstate->region)) {
log_err("prepend rrsets: out of memory");
@ -344,8 +330,9 @@ iter_encode_respmsg(struct module_qstate* qstate, struct iter_qstate* iq,
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.ext_rcode = 0;
edns.bits = qstate->edns.bits & EDNS_DO;
if(!reply_info_answer_encode(&qinf, msg->rep, 0, iq->orig_qflags,
qstate->buf, 0, 1, qstate->env->scratch, qstate->edns.udp_size,
if(!reply_info_answer_encode(&qstate->qinfo, msg->rep, 0,
qstate->query_flags, qstate->buf, 0, 1,
qstate->env->scratch, qstate->edns.udp_size,
&edns, (int)(qstate->edns.bits & EDNS_DO))) {
/* encode servfail */
error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@ -398,8 +385,8 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
{
size_t i;
/* Start with the (current) qname. */
*mname = qstate->qinfo.qname;
*mname_len = qstate->qinfo.qname_len;
*mname = iq->qchase.qname;
*mname_len = iq->qchase.qname_len;
/* Iterate over the ANSWER rrsets in order, looking for CNAMEs and
* DNAMES. */
@ -473,6 +460,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
subq->query_flags = 0; /* OPCODE QUERY, no flags */
subq->edns.udp_size = 65535;
subq->buf = qstate->buf;
subq->env = qstate->env;
subq->env->scratch = qstate->env->scratch;
subq->region = region_create(malloc, free);
if(!subq->region) {
@ -490,7 +478,6 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
free(subq);
return NULL;
}
subq->env = qstate->env;
subq->work_info = NULL;
subq->parent = qstate;
module_subreq_insert(&qstate->subquery_first, subq);
@ -503,6 +490,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
outbound_list_init(&subiq->outlist);
subiq->state = initial_state;
subiq->final_state = final_state;
subiq->qchase = subq->qinfo;
/* RD should be set only when sending the query back through the INIT
* state. */
@ -512,8 +500,10 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
* the resolution chain, which might have a validator. We are
* uninterested in validating things not on the direct resolution
* path. */
subq->query_flags |= BIT_CD;
subiq->orig_qflags = subq->query_flags;
/* Turned off! CD does not make a difference in query results.
qstate->query_flags |= BIT_CD;
*/
subiq->chase_flags = subq->query_flags;
return subq;
}
@ -671,13 +661,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
/* This either results in a query restart (CNAME cache response), a
* terminating response (ANSWER), or a cache miss (null). */
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate->region, qstate->env->scratch);
msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
iq->qchase.qname_len, iq->qchase.qtype,
iq->qchase.qclass, qstate->region, qstate->env->scratch);
if(msg) {
/* handle positive cache response */
enum response_type type = response_type_from_cache(msg,
&qstate->qinfo);
&iq->qchase);
log_dns_msg("msg from cache lookup", &msg->qinfo, msg->rep);
if(type == RESPONSE_TYPE_CNAME) {
@ -685,16 +675,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
size_t slen = 0;
verbose(VERB_ALGO, "returning CNAME response from "
"cache");
if(!iq->orig_qname) {
iq->orig_qname = qstate->qinfo.qname;
iq->orig_qnamelen = qstate->qinfo.qname_len;
}
if(!handle_cname_response(qstate, iq, msg,
&sname, &slen))
return error_response(qstate, id,
LDNS_RCODE_SERVFAIL);
qstate->qinfo.qname = sname;
qstate->qinfo.qname_len = slen;
iq->qchase.qname = sname;
iq->qchase.qname_len = slen;
/* This *is* a query restart, even if it is a cheap
* one. */
iq->query_restart_count++;
@ -742,9 +728,9 @@ return nextState(event, req, state, IterEventState.INIT_REQUEST_STATE);
/* first, adjust for DS queries. To avoid the grandparent problem,
* we just look for the closest set of server to the parent of qname.
*/
delname = qstate->qinfo.qname;
delnamelen = qstate->qinfo.qname_len;
if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS && delname[0] != 0) {
delname = iq->qchase.qname;
delnamelen = iq->qchase.qname_len;
if(iq->qchase.qtype == LDNS_RR_TYPE_DS && delname[0] != 0) {
/* do not adjust root label, remove first label from delname */
size_t lablen = delname[0] + 1;
delname += lablen;
@ -754,7 +740,7 @@ return nextState(event, req, state, IterEventState.INIT_REQUEST_STATE);
/* Lookup the delegation in the cache. If null, then the cache needs
* to be primed for the qclass. */
iq->dp = dns_cache_find_delegation(qstate->env, delname, delnamelen,
qstate->qinfo.qtype, qstate->qinfo.qclass, qstate->region,
iq->qchase.qtype, iq->qchase.qclass, qstate->region,
&iq->deleg_msg);
/* If the cache has returned nothing, then we have a root priming
@ -762,7 +748,7 @@ return nextState(event, req, state, IterEventState.INIT_REQUEST_STATE);
if(iq->dp == NULL) {
/* Note that the result of this will set a new
* DelegationPoint based on the result of priming. */
if(!prime_root(qstate, iq, ie, id, qstate->qinfo.qclass))
if(!prime_root(qstate, iq, ie, id, iq->qchase.qclass))
return error_response(qstate, id, LDNS_RCODE_REFUSED);
/* priming creates an sends a subordinate query, with
@ -774,9 +760,9 @@ return nextState(event, req, state, IterEventState.INIT_REQUEST_STATE);
/* Reset the RD flag. If this is a query restart, then the RD
* will have been turned off. */
if(iq->orig_qflags & BIT_RD)
qstate->query_flags |= BIT_RD;
else qstate->query_flags &= ~BIT_RD;
if(qstate->query_flags & BIT_RD)
iq->chase_flags |= BIT_RD;
else iq->chase_flags &= ~BIT_RD;
/* Otherwise, set the current delegation point and move on to the
* next state. */
@ -807,8 +793,8 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
&qstate->qinfo);
/* Check to see if we need to prime a stub zone. */
if(prime_stub(qstate, iq, ie, id, qstate->qinfo.qname,
qstate->qinfo.qclass)) {
if(prime_stub(qstate, iq, ie, id, iq->qchase.qname,
iq->qchase.qclass)) {
/* A priming sub request was made */
return 0;
}
@ -834,7 +820,7 @@ processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq)
&qstate->qinfo);
/* If the RD flag wasn't set, then we just finish with the
* cached referral as the response. */
if(!(qstate->query_flags & BIT_RD)) {
if(!(iq->chase_flags & BIT_RD)) {
iq->response = iq->deleg_msg;
if(verbosity >= VERB_ALGO)
log_dns_msg("no RD requested, using delegation msg",
@ -844,7 +830,7 @@ processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq)
/* After this point, unset the RD flag -- this query is going to
* be sent to an auth. server. */
qstate->query_flags &= ~BIT_RD;
iq->chase_flags &= ~BIT_RD;
/* Jump to the next state. */
return next_state(iq, QUERYTARGETS_STATE);
@ -927,7 +913,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
if(dname_subdomain_c(ns->name, iq->dp->name)) {
log_nametypeclass(VERB_DETAIL, "skipping target name "
"because it should have been glue", ns->name,
LDNS_RR_TYPE_NS, qstate->qinfo.qclass);
LDNS_RR_TYPE_NS, iq->qchase.qclass);
continue;
}
@ -935,14 +921,14 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
/* Send the AAAA request. */
if(!generate_target_query(qstate, iq, id,
ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass))
LDNS_RR_TYPE_AAAA, iq->qchase.qclass))
return 0;
query_count++;
}
/* Send the A request. */
if(!generate_target_query(qstate, iq, id,
ns->name, ns->namelen,
LDNS_RR_TYPE_A, qstate->qinfo.qclass))
LDNS_RR_TYPE_A, iq->qchase.qclass))
return 0;
query_count++;
@ -1096,14 +1082,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
/* We have a valid target. */
log_query_info(VERB_DETAIL, "sending query:", &qstate->qinfo);
log_query_info(VERB_DETAIL, "sending query:", &iq->qchase);
log_name_addr(VERB_DETAIL, "sending to target:", iq->dp->name,
&target->addr, target->addrlen);
outq = (*qstate->env->send_query)(
qstate->qinfo.qname, qstate->qinfo.qname_len,
qstate->qinfo.qtype, qstate->qinfo.qclass,
qstate->query_flags, 1, &target->addr, target->addrlen,
qstate);
iq->qchase.qname, iq->qchase.qname_len,
iq->qchase.qtype, iq->qchase.qclass,
iq->chase_flags, 1, &target->addr, target->addrlen, qstate);
if(!outq) {
log_err("error sending query to auth server; skip this address");
log_addr("error for address:", &target->addr, target->addrlen);
@ -1139,7 +1124,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_ALGO, "query response was timeout");
return next_state(iq, QUERYTARGETS_STATE);
}
type = response_type_from_server(iq->response, &qstate->qinfo, iq->dp);
type = response_type_from_server(iq->response, &iq->qchase, iq->dp);
if(type == RESPONSE_TYPE_ANSWER) {
/* ANSWER type responses terminate the query algorithm,
* so they sent on their */
@ -1196,10 +1181,6 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_DETAIL, "query response was CNAME");
log_dns_msg("cname msg", &iq->response->qinfo, iq->response->rep);
/* Process the CNAME response. */
if(!iq->orig_qname) {
iq->orig_qname = qstate->qinfo.qname;
iq->orig_qnamelen = qstate->qinfo.qname_len;
}
if(!handle_cname_response(qstate, iq, iq->response,
&sname, &snamelen))
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@ -1209,8 +1190,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if(!iter_dns_store(qstate->env, iq->response, 1))
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
/* set the current request's qname to the new value. */
qstate->qinfo.qname = sname;
qstate->qinfo.qname_len = snamelen;
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
/* Clear the query state, since this is a query restart. */
iq->deleg_msg = NULL;
iq->dp = NULL;
@ -1277,7 +1258,7 @@ processPrimeResponse(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_qstate* foriq;
struct delegpt* dp = NULL;
enum response_type type = response_type_from_server(iq->response,
&qstate->qinfo, iq->dp);
&iq->qchase, iq->dp);
/* This event is finished. */
qstate->ext_state[id] = module_finished;
@ -1298,7 +1279,7 @@ processPrimeResponse(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
log_query_info(VERB_DETAIL, "priming successful for", &qstate->qinfo);
log_query_info(VERB_DETAIL, "priming successful for", &iq->qchase);
delegpt_log(dp);
foriq = (struct iter_qstate*)forq->minfo[id];
foriq->dp = dp;
@ -1348,11 +1329,8 @@ processTargetResponse(struct module_qstate* qstate, struct iter_qstate* iq,
foriq = (struct iter_qstate*)forq->minfo[id];
/* check to see if parent event is still interested. */
if(iq->orig_qname)
dpns = delegpt_find_ns(foriq->dp, iq->orig_qname,
iq->orig_qnamelen);
else dpns = delegpt_find_ns(foriq->dp, qstate->qinfo.qname,
/* check to see if parent event is still interested (in orig name). */
dpns = delegpt_find_ns(foriq->dp, qstate->qinfo.qname,
qstate->qinfo.qname_len);
if(!dpns) {
/* FIXME: maybe store this nameserver address in the cache
@ -1371,7 +1349,7 @@ processTargetResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* the original event.
* NOTE: we could only look for the AnswerRRset if the
* response type was ANSWER. */
rrset = reply_find_answer_rrset(&qstate->qinfo, iq->response->rep);
rrset = reply_find_answer_rrset(&iq->qchase, iq->response->rep);
if(rrset) {
/* if CNAMEs have been followed - add new NS to delegpt. */
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
@ -1556,7 +1534,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
goto handle_it;
/* normalize and sanitize: easy to delete items from linked lists */
if(!scrub_message(pkt, prs, &qstate->qinfo, iq->dp->name,
if(!scrub_message(pkt, prs, &iq->qchase, iq->dp->name,
qstate->env->scratch))
goto handle_it;
@ -1630,6 +1608,10 @@ iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
if(iq) log_query_info(VERB_DETAIL, "iterator operate: query",
&qstate->qinfo);
if(iq && qstate->qinfo.qname != iq->qchase.qname)
log_query_info(VERB_DETAIL, "iterator operate: chased to",
&iq->qchase);
if(ie->fwd_addrlen != 0) {
perform_forward(qstate, event, id, outbound);
return;
@ -1680,11 +1662,6 @@ iter_clear(struct module_qstate* qstate, int id)
if(!qstate)
return;
iq = (struct iter_qstate*)qstate->minfo[id];
if(iq && iq->orig_qname) {
/* so the correct qname gets free'd */
qstate->qinfo.qname = iq->orig_qname;
qstate->qinfo.qname_len = iq->orig_qnamelen;
}
if(iq) {
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;

View file

@ -43,6 +43,7 @@
#ifndef ITERATOR_ITERATOR_H
#define ITERATOR_ITERATOR_H
#include "services/outbound_list.h"
#include "util/data/msgreply.h"
struct module_func_block;
struct delegpt;
struct iter_hints;
@ -183,12 +184,12 @@ struct iter_qstate {
/** Last element of the prepend list */
struct iter_prep_list* prepend_last;
/** original query name - if not NULL, malloced and before CNAME */
uint8_t* orig_qname;
/** original query name length */
size_t orig_qnamelen;
/** original query flags (i.e. RD flag) */
uint16_t orig_qflags;
/** query name used for chasing the results. Initially the same as
* the state qinfo, but after CNAMEs this will be different.
* The query info used to elicit the results needed. */
struct query_info qchase;
/** query flags to use when chasing the answer (i.e. RD flag) */
uint16_t chase_flags;
/**
* This is the current delegation point for an in-progress query. This