]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
cycle detection
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 26 Jul 2007 09:29:21 +0000 (09:29 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 26 Jul 2007 09:29:21 +0000 (09:29 +0000)
git-svn-id: file:///svn/unbound/trunk@452 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c
services/mesh.c
services/mesh.h
util/module.h

index 4043c4ff8c8b7a4ee7573a7d0d4038e558f41ef4..994a7d0c227bd94d3c164a210d9f76fa8916e9f6 100644 (file)
@@ -712,6 +712,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
        worker->env.kill_sub = &mesh_state_delete;
        worker->env.query_done = &mesh_query_done;
        worker->env.walk_supers = &mesh_walk_supers;
+       worker->env.detect_cycle = &mesh_detect_cycle;
        if(!worker->env.mesh) {
                worker_delete(worker);
                return 0;
index f1713c8bb4e67c6da1c3b2f4026e338f893d9b4a..e4967167bd6c4d69e7ef64a2c5d373c80a5a6927 100644 (file)
@@ -1,3 +1,7 @@
+26 July 2007: Wouter
+       - cycle detection, for query state dependencies. Will attempt to
+         circumvent the cycle, but if no other targets available fails.
+
 25 July 2007: Wouter
        - testbound read ADDRESS and check it.
        - test for version.bind and friends.
index 656b58f5cebdade0f35df24dac4671bca9a65785..bedf78a40a0a1a0882bf10aa733c751d73ff5f4c 100644 (file)
@@ -354,3 +354,32 @@ iter_ns_probability(struct ub_randstate* rnd, int n, int m)
        sel = ub_random(rnd) % m; 
        return (sel < n);
 }
+
+/** detect dependency cycle for query and target */
+static int
+causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
+       uint16_t t, uint16_t c)
+{
+       struct query_info qinf;
+       qinf.qname = name;
+       qinf.qname_len = namelen;
+       qinf.qtype = t;
+       qinf.qclass = c;
+       return (*qstate->env->detect_cycle)(qstate, &qinf);
+}
+
+void 
+iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
+{
+       struct delegpt_ns* ns;
+       for(ns = dp->nslist; ns; ns = ns->next) {
+               if(ns->resolved)
+                       continue;
+               /* see if this ns as target causes dependency cycle */
+               if(causes_cycle(qstate, ns->name, ns->namelen, 
+                       LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass) ||
+                  causes_cycle(qstate, ns->name, ns->namelen, 
+                       LDNS_RR_TYPE_A, qstate->qinfo.qclass))
+                       ns->resolved = 1;
+       }
+}
index 2531ad37f4249c193a9c18843a8634a123e7b288..7e3a5ccabd086cfbfca6697d234e2d3381d6628c 100644 (file)
@@ -52,6 +52,7 @@ struct msg_parse;
 struct ub_randstate;
 struct query_info;
 struct reply_info;
+struct module_qstate;
 
 /**
  * Process config options and set iterator module state.
@@ -119,4 +120,12 @@ int iter_dns_store(struct module_env* env, struct query_info* qinf,
  */
 int iter_ns_probability(struct ub_randstate* rnd, int n, int m);
 
+/**
+ * Mark targets that result in a dependency cycle as done, so they
+ * will not get selected as targets.
+ * @param qstate: query state.
+ * @param dp: delegpt to mark ns in.
+ */
+void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
+
 #endif /* ITERATOR_ITER_UTILS_H */
index 0809535bc41f66841490519ac5e023f96d601718..f2cff2b47fff2796bae21d5e423bc677038e0ccc 100644 (file)
@@ -811,8 +811,11 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
 {
        int query_count = 0;
        struct delegpt_ns* ns = iq->dp->nslist;
-       int missing = (int)delegpt_count_missing_targets(iq->dp);
+       int missing;
        int toget = 0;
+
+       iter_mark_cycle_targets(qstate, iq->dp);
+       missing = (int)delegpt_count_missing_targets(iq->dp);
        log_assert(maxtargets != 0); /* that would not be useful */
 
        /* Generate target requests. Basically, any missing targets 
@@ -840,13 +843,6 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
                        missing --;
                        continue;
                }
-               if(iq->refetch_glue && dname_subdomain_c(ns->name, 
-                       iq->dp->name)) {
-                       log_nametypeclass(VERB_DETAIL, "skip double glue "
-                               "refetch", ns->name, LDNS_RR_TYPE_A, 
-                               iq->qchase.qclass);
-                       continue;
-               }
 
                if(ie->supports_ipv6) {
                        /* Send the AAAA request. */
index 0061c1e1da66a57b9d3fa49edd2947d910c5ce11..3d8c48ea955edbbdddcb61a3269b23115d44d22b 100644 (file)
@@ -588,3 +588,28 @@ mesh_get_mem(struct mesh_area* mesh)
        }
        return s;
 }
+
+/** helper recursive rbtree find routine */
+static int
+find_in_subsub(struct mesh_state* m, struct mesh_state* tofind)
+{
+       struct mesh_state_ref* r;
+       RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) {
+               if(r->s == tofind || find_in_subsub(r->s, tofind))
+                       return 1;
+       }
+       return 0;
+}
+
+int 
+mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo)
+{
+       struct mesh_area* mesh = qstate->env->mesh;
+       struct mesh_state* cyc_m = qstate->mesh_info;
+       struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, BIT_RD, 0);
+       if(!dep_m)
+               return 0;
+       if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m))
+               return 1;
+       return 0;
+}
index 75afdcb702bb48a712bf3a9a149407624b5e8f55..dc260a615303e6e3d23550787688c717c8436668 100644 (file)
@@ -357,4 +357,15 @@ void mesh_stats(struct mesh_area* mesh, const char* str);
  */
 size_t mesh_get_mem(struct mesh_area* mesh);
 
+/**
+ * Find cycle; see if the given mesh is in the targets sub, or sub-sub, ...
+ * trees.
+ * @param qstate: given mesh querystate.
+ * @param qinfo: query info for dependency.
+ * @return true if the name,type,class exists and the given qstate mesh exists
+ *     as a dependency of that name. Thus if qstate becomes dependent on
+ *     name,type,class then a cycle is created.
+ */
+int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo);
+
 #endif /* SERVICES_MESH_H */
index 5d2481b603c1ad8db1799b04808118d755d0fa31..687aea63e4c416fa4d8a1158d8072f8d18d04eec 100644 (file)
@@ -196,6 +196,20 @@ struct module_env {
        void (*walk_supers)(struct module_qstate* qstate, int id, 
                void (*cb)(struct module_qstate*, int, struct module_qstate*));
 
+       /**
+        * Detect if adding a dependency for qstate on name,type,class will
+        * create a dependency cycle.
+        * @param qstate: given mesh querystate.
+        * @param qinfo: query info for dependency. Assumed RDflag and not
+        *      priming.
+        * @return true if the name,type,class exists and the given 
+        *      qstate mesh exists as a dependency of that name. Thus 
+        *      if qstate becomes dependent on name,type,class then a 
+        *      cycle is created.
+        */
+       int (*detect_cycle)(struct module_qstate* qstate, 
+               struct query_info* qinfo);
+
        /** region for temporary usage. May be cleared after operate() call. */
        struct region* scratch;
        /** internal data for daemon - worker thread. */