149 lines
4.8 KiB
Diff
149 lines
4.8 KiB
Diff
Index: contrib/unbound/iterator/iterator.c
|
|
===================================================================
|
|
--- contrib/unbound/iterator/iterator.c.orig
|
|
+++ contrib/unbound/iterator/iterator.c
|
|
@@ -117,6 +117,7 @@
|
|
iq->query_restart_count = 0;
|
|
iq->referral_count = 0;
|
|
iq->sent_count = 0;
|
|
+ iq->target_count = NULL;
|
|
iq->wait_priming_stub = 0;
|
|
iq->refetch_glue = 0;
|
|
iq->dnssec_expected = 0;
|
|
@@ -442,6 +443,26 @@
|
|
return 1;
|
|
}
|
|
|
|
+/** create target count structure for this query */
|
|
+static void
|
|
+target_count_create(struct iter_qstate* iq)
|
|
+{
|
|
+ if(!iq->target_count) {
|
|
+ iq->target_count = (int*)calloc(2, sizeof(int));
|
|
+ /* if calloc fails we simply do not track this number */
|
|
+ if(iq->target_count)
|
|
+ iq->target_count[0] = 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+target_count_increase(struct iter_qstate* iq, int num)
|
|
+{
|
|
+ target_count_create(iq);
|
|
+ if(iq->target_count)
|
|
+ iq->target_count[1] += num;
|
|
+}
|
|
+
|
|
/**
|
|
* Generate a subrequest.
|
|
* Generate a local request event. Local events are tied to this module, and
|
|
@@ -513,6 +534,10 @@
|
|
subiq = (struct iter_qstate*)subq->minfo[id];
|
|
memset(subiq, 0, sizeof(*subiq));
|
|
subiq->num_target_queries = 0;
|
|
+ target_count_create(iq);
|
|
+ subiq->target_count = iq->target_count;
|
|
+ if(iq->target_count)
|
|
+ iq->target_count[0] ++; /* extra reference */
|
|
subiq->num_current_queries = 0;
|
|
subiq->depth = iq->depth+1;
|
|
outbound_list_init(&subiq->outlist);
|
|
@@ -1339,6 +1364,12 @@
|
|
|
|
if(iq->depth == ie->max_dependency_depth)
|
|
return 0;
|
|
+ if(iq->depth > 0 && iq->target_count &&
|
|
+ iq->target_count[1] > MAX_TARGET_COUNT) {
|
|
+ verbose(VERB_QUERY, "request has exceeded the maximum "
|
|
+ "number of glue fetches %d", iq->target_count[1]);
|
|
+ return 0;
|
|
+ }
|
|
|
|
iter_mark_cycle_targets(qstate, iq->dp);
|
|
missing = (int)delegpt_count_missing_targets(iq->dp);
|
|
@@ -1487,6 +1518,7 @@
|
|
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
|
}
|
|
iq->num_target_queries += qs;
|
|
+ target_count_increase(iq, qs);
|
|
if(qs != 0) {
|
|
qstate->ext_state[id] = module_wait_subquery;
|
|
return 0; /* and wait for them */
|
|
@@ -1496,6 +1528,12 @@
|
|
verbose(VERB_QUERY, "maxdepth and need more nameservers, fail");
|
|
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
|
}
|
|
+ if(iq->depth > 0 && iq->target_count &&
|
|
+ iq->target_count[1] > MAX_TARGET_COUNT) {
|
|
+ verbose(VERB_QUERY, "request has exceeded the maximum "
|
|
+ "number of glue fetches %d", iq->target_count[1]);
|
|
+ return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
|
+ }
|
|
/* mark cycle targets for parent-side lookups */
|
|
iter_mark_pside_cycle_targets(qstate, iq->dp);
|
|
/* see if we can issue queries to get nameserver addresses */
|
|
@@ -1525,6 +1563,7 @@
|
|
if(query_count != 0) { /* suspend to await results */
|
|
verbose(VERB_ALGO, "try parent-side glue lookup");
|
|
iq->num_target_queries += query_count;
|
|
+ target_count_increase(iq, query_count);
|
|
qstate->ext_state[id] = module_wait_subquery;
|
|
return 0;
|
|
}
|
|
@@ -1680,6 +1719,7 @@
|
|
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
|
}
|
|
iq->num_target_queries += extra;
|
|
+ target_count_increase(iq, extra);
|
|
if(iq->num_target_queries > 0) {
|
|
/* wait to get all targets, we want to try em */
|
|
verbose(VERB_ALGO, "wait for all targets for fallback");
|
|
@@ -1720,6 +1760,7 @@
|
|
/* errors ignored, these targets are not strictly necessary for
|
|
* this result, we do not have to reply with SERVFAIL */
|
|
iq->num_target_queries += extra;
|
|
+ target_count_increase(iq, extra);
|
|
}
|
|
|
|
/* Add the current set of unused targets to our queue. */
|
|
@@ -1765,6 +1806,7 @@
|
|
return 1;
|
|
}
|
|
iq->num_target_queries += qs;
|
|
+ target_count_increase(iq, qs);
|
|
}
|
|
/* Since a target query might have been made, we
|
|
* need to check again. */
|
|
@@ -2847,6 +2889,8 @@
|
|
iq = (struct iter_qstate*)qstate->minfo[id];
|
|
if(iq) {
|
|
outbound_list_clear(&iq->outlist);
|
|
+ if(iq->target_count && --iq->target_count[0] == 0)
|
|
+ free(iq->target_count);
|
|
iq->num_current_queries = 0;
|
|
}
|
|
qstate->minfo[id] = NULL;
|
|
Index: contrib/unbound/iterator/iterator.h
|
|
===================================================================
|
|
--- contrib/unbound/iterator/iterator.h.orig
|
|
+++ contrib/unbound/iterator/iterator.h
|
|
@@ -52,6 +52,8 @@
|
|
struct iter_prep_list;
|
|
struct iter_priv;
|
|
|
|
+/** max number of targets spawned for a query and its subqueries */
|
|
+#define MAX_TARGET_COUNT 32
|
|
/** max number of query restarts. Determines max number of CNAME chain. */
|
|
#define MAX_RESTART_COUNT 8
|
|
/** max number of referrals. Makes sure resolver does not run away */
|
|
@@ -254,6 +256,10 @@
|
|
|
|
/** number of queries fired off */
|
|
int sent_count;
|
|
+
|
|
+ /** number of target queries spawned in [1], for this query and its
|
|
+ * subqueries, the malloced-array is shared, [0] refcount. */
|
|
+ int* target_count;
|
|
|
|
/**
|
|
* The query must store NS records from referrals as parentside RRs
|