]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Prime response state, both root priming and stub priming handling.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 4 Jun 2007 12:22:38 +0000 (12:22 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 4 Jun 2007 12:22:38 +0000 (12:22 +0000)
git-svn-id: file:///svn/unbound/trunk@364 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c

index ebb54cba0bd6ce78a5f4f7aef33edcfd15db4ad5..66d9be2b93626a5833859e53ad2096b9541ac350 100644 (file)
@@ -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
index 422e0ead75cfb9bb27097acc985be082879b8b2e..83eaa21860b625e9d6e740be2ced00240981e9e1 100644 (file)
@@ -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)
 {
index 5a7921bdada6acbcf313f3141ed8dc49f45ba60b..89f6f160830b55ae703288194ead9da88ab139c5 100644 (file)
@@ -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.
index 581716e458561427fbd5afff7c42fb43b06b5daf..3e289e88c69285f503d7bdfc23ce374891e1f32f 100644 (file)
@@ -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;