]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix make_new_space function so that the incoming query is not
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 24 Oct 2011 13:49:59 +0000 (13:49 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 24 Oct 2011 13:49:59 +0000 (13:49 +0000)
  overwritten if a jostled out query causes a waiting query to be
  resumed that then fails and sends an error message.  (Thanks to
  Matthew Lee).

git-svn-id: file:///svn/unbound/trunk@2523 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/mesh.c
services/mesh.h

index 28a3016801dac3cc3fc31c2d82550087e1440e0d..8602b98a9645bd69a4050032ef576bbe2ec04fd2 100644 (file)
@@ -2,6 +2,10 @@
        - Fix resolve of partners.extranet.microsoft.com with a fix for the
          server selection for choosing out of a (particular) list of bad
          choices.
+       - Fix make_new_space function so that the incoming query is not
+         overwritten if a jostled out query causes a waiting query to be
+         resumed that then fails and sends an error message.  (Thanks to
+         Matthew Lee).
 
 21 October 2011: Wouter
        - fix --enable-allsymbols, fptr wlist is disabled on windows with this 
index aee0aa5e6766e181339160b92516201190988ce9..d9222d69c9172169496169cb6bad4444b5ac0a70 100644 (file)
@@ -162,7 +162,8 @@ mesh_create(struct module_stack* stack, struct module_env* env)
                return NULL;
        }
        mesh->histogram = timehist_setup();
-       if(!mesh->histogram) {
+       mesh->qbuf_bak = ldns_buffer_new(env->cfg->msg_buffer_size);
+       if(!mesh->histogram || !mesh->qbuf_bak) {
                free(mesh);
                log_err("mesh area alloc: out of memory");
                return NULL;
@@ -209,6 +210,7 @@ mesh_delete(struct mesh_area* mesh)
        while(mesh->all.count)
                mesh_delete_helper(mesh->all.root);
        timehist_delete(mesh->histogram);
+       ldns_buffer_free(mesh->qbuf_bak);
        free(mesh);
 }
 
@@ -232,7 +234,7 @@ mesh_delete_all(struct mesh_area* mesh)
        mesh->jostle_last = NULL;
 }
 
-int mesh_make_new_space(struct mesh_area* mesh)
+int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf)
 {
        struct mesh_state* m = mesh->jostle_first;
        /* free space is available */
@@ -250,6 +252,8 @@ int mesh_make_new_space(struct mesh_area* mesh)
                                "make space for a new one",
                                m->s.qinfo.qname, m->s.qinfo.qtype,
                                m->s.qinfo.qclass);
+                       /* backup the query */
+                       if(qbuf) ldns_buffer_copy(mesh->qbuf_bak, qbuf);
                        /* notify supers */
                        if(m->super_set.count > 0) {
                                verbose(VERB_ALGO, "notify supers of failure");
@@ -259,6 +263,9 @@ int mesh_make_new_space(struct mesh_area* mesh)
                        }
                        mesh->stats_jostled ++;
                        mesh_state_delete(&m->s);
+                       /* restore the query - note that the qinfo ptr to
+                        * the querybuffer is then correct again. */
+                       if(qbuf) ldns_buffer_copy(qbuf, mesh->qbuf_bak);
                        return 1;
                }
        }
@@ -280,7 +287,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
        int added = 0;
        /* does this create a new reply state? */
        if(!s || s->list_select == mesh_no_list) {
-               if(!mesh_make_new_space(mesh)) {
+               if(!mesh_make_new_space(mesh, rep->c->buffer)) {
                        verbose(VERB_ALGO, "Too many queries. dropping "
                                "incoming query.");
                        comm_point_drop_reply(rep);
@@ -431,7 +438,7 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
                        s->s.prefetch_leeway = leeway;
                return;
        }
-       if(!mesh_make_new_space(mesh)) {
+       if(!mesh_make_new_space(mesh, NULL)) {
                verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
                mesh->stats_dropped ++;
                return;
@@ -1137,7 +1144,8 @@ mesh_get_mem(struct mesh_area* mesh)
 {
        struct mesh_state* m;
        size_t s = sizeof(*mesh) + sizeof(struct timehist) +
-               sizeof(struct th_buck)*mesh->histogram->num;
+               sizeof(struct th_buck)*mesh->histogram->num +
+               sizeof(ldns_buffer) + ldns_buffer_capacity(mesh->qbuf_bak);
        RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
                /* all, including m itself allocated in qstate region */
                s += regional_get_mem(m->s.region);
index a6f3b58a9cda6e192f4c2789f8ba5412bfe73120..5f109779a4d2371ab8e65eec77c2c1823cdd069a 100644 (file)
@@ -123,6 +123,10 @@ struct mesh_area {
        /** (extended stats) rcode nodata in replies */
        size_t ans_nodata;
 
+       /** backup of query if other operations recurse and need the
+        * network buffers */
+       ldns_buffer* qbuf_bak;
+
        /** double linked list of the run-to-completion query states.
         * These are query states with a reply */
        struct mesh_state* forever_first;
@@ -535,9 +539,16 @@ int mesh_state_ref_compare(const void* ap, const void* bp);
 /**
  * Make space for another recursion state for a reply in the mesh
  * @param mesh: mesh area
+ * @param qbuf: query buffer to save if recursion is invoked to make space.
+ *    This buffer is necessary, because the following sequence in calls
+ *    can result in an overwrite of the incoming query:
+ *    delete_other_mesh_query - iter_clean - serviced_delete - waiting
+ *    udp query is sent - on error callback - callback sends SERVFAIL reply
+ *    over the same network channel, and shared UDP buffer is overwritten.
+ *    You can pass NULL if there is no buffer that must be backed up.
  * @return false if no space is available.
  */
-int mesh_make_new_space(struct mesh_area* mesh);
+int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf);
 
 /**
  * Insert mesh state into a double linked list.  Inserted at end.