summaryrefslogtreecommitdiff
path: root/iterator/iterator.c
diff options
context:
space:
mode:
Diffstat (limited to 'iterator/iterator.c')
-rw-r--r--iterator/iterator.c80
1 files changed, 29 insertions, 51 deletions
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 2f26bd3349de..8312dfd53313 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -69,6 +69,9 @@
#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
+/* in msec */
+int UNKNOWN_SERVER_NICENESS = 376;
+
int
iter_init(struct module_env* env, int id)
{
@@ -324,6 +327,29 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
/* serving expired contents, but nothing is cached
* at all, so the servfail cache entry is useful
* (stops waste of time on this servfail NORR_TTL) */
+ } else {
+ /* don't overwrite existing (non-expired) data in
+ * cache with a servfail */
+ struct msgreply_entry* msg;
+ if((msg=msg_cache_lookup(qstate->env,
+ qstate->qinfo.qname, qstate->qinfo.qname_len,
+ qstate->qinfo.qtype, qstate->qinfo.qclass,
+ qstate->query_flags, *qstate->env->now, 0))
+ != NULL) {
+ struct reply_info* rep = (struct reply_info*)
+ msg->entry.data;
+ if(FLAGS_GET_RCODE(rep->flags) ==
+ LDNS_RCODE_NOERROR ||
+ FLAGS_GET_RCODE(rep->flags) ==
+ LDNS_RCODE_NXDOMAIN) {
+ /* we have a good entry,
+ * don't overwrite */
+ lock_rw_unlock(&msg->entry.lock);
+ return error_response(qstate, id, rcode);
+ }
+ lock_rw_unlock(&msg->entry.lock);
+ }
+
}
memset(&err, 0, sizeof(err));
err.flags = (uint16_t)(BIT_QR | BIT_RA);
@@ -1144,53 +1170,6 @@ forward_request(struct module_qstate* qstate, struct iter_qstate* iq)
return 1;
}
-static int
-iter_stub_fwd_no_cache(struct module_qstate *qstate, struct iter_qstate *iq)
-{
- struct iter_hints_stub *stub;
- struct delegpt *dp;
-
- /* Check for stub. */
- stub = hints_lookup_stub(qstate->env->hints, iq->qchase.qname,
- iq->qchase.qclass, iq->dp);
- dp = forwards_lookup(qstate->env->fwds, iq->qchase.qname, iq->qchase.qclass);
-
- /* see if forward or stub is more pertinent */
- if(stub && stub->dp && dp) {
- if(dname_strict_subdomain(dp->name, dp->namelabs,
- stub->dp->name, stub->dp->namelabs)) {
- stub = NULL; /* ignore stub, forward is lower */
- } else {
- dp = NULL; /* ignore forward, stub is lower */
- }
- }
-
- /* check stub */
- if (stub != NULL && stub->dp != NULL) {
- if(stub->dp->no_cache) {
- char qname[255+1];
- char dpname[255+1];
- dname_str(iq->qchase.qname, qname);
- dname_str(stub->dp->name, dpname);
- verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
- }
- return (stub->dp->no_cache);
- }
-
- /* Check for forward. */
- if (dp) {
- if(dp->no_cache) {
- char qname[255+1];
- char dpname[255+1];
- dname_str(iq->qchase.qname, qname);
- dname_str(dp->name, dpname);
- verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
- }
- return (dp->no_cache);
- }
- return 0;
-}
-
/**
* Process the initial part of the request handling. This state roughly
* corresponds to resolver algorithms steps 1 (find answer in cache) and 2
@@ -1268,7 +1247,7 @@ 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). */
- if (iter_stub_fwd_no_cache(qstate, iq)) {
+ if (iter_stub_fwd_no_cache(qstate, &iq->qchase)) {
/* Asked to not query cache. */
verbose(VERB_ALGO, "no-cache set, going to the network");
qstate->no_cache_lookup = 1;
@@ -1903,7 +1882,6 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
struct delegpt* p = hints_lookup_root(qstate->env->hints,
iq->qchase.qclass);
if(p) {
- struct delegpt_ns* ns;
struct delegpt_addr* a;
iq->chase_flags &= ~BIT_RD; /* go to authorities */
for(ns = p->nslist; ns; ns=ns->next) {
@@ -2320,7 +2298,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
errinf(qstate, "auth zone lookup failed, fallback is off");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
- if(iq->dp && iq->dp->auth_dp) {
+ if(iq->dp->auth_dp) {
/* we wanted to fallback, but had no delegpt, only the
* auth zone generated delegpt, create an actual one */
iq->auth_zone_avoid = 1;
@@ -3592,7 +3570,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
if(event == module_event_noreply || event == module_event_error) {
if(event == module_event_noreply && iq->sent_count >= 3 &&
qstate->env->cfg->use_caps_bits_for_id &&
- !iq->caps_fallback) {
+ !iq->caps_fallback && !is_caps_whitelisted(ie, iq)) {
/* start fallback */
iq->caps_fallback = 1;
iq->caps_server = 0;