- Fix DNS64 to not store intermediate results in cache, this avoids
other threads from picking up the wrong data. The module restores
the previous no_cache_store setting when the the module is finished.
+ - Fix #4208: 'stub-no-cache' and 'forward-no-cache' not work.
26 November 2018: Wouter
- Fix to not set GLOB_NOSORT so the unbound.conf include: files are
#include "util/config_file.h"
#include "util/data/msgreply.h"
#include "sldns/sbuffer.h"
+#include "iterator/iter_utils.h"
/** externally called */
void
return 0;
qstate->minfo[id] = sq;
memset(sq, 0, sizeof(*sq));
+ sq->started_no_cache_store = qstate->no_cache_store;
return 1;
}
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
- qstate->no_cache_store = 0;
+ if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo)) {
+ qstate->no_cache_store = 0;
+ }
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
qstate->env->cfg->client_subnet_always_forward) ||
* is still usefull to put it in the edns subnet cache for
* when a client explicitly asks for subnet specific answer. */
verbose(VERB_QUERY, "subnet: Authority indicates no support");
- lock_rw_wrlock(&sne->biglock);
- update_cache(qstate, id);
- lock_rw_unlock(&sne->biglock);
+ if(!sq->started_no_cache_store) {
+ lock_rw_wrlock(&sne->biglock);
+ update_cache(qstate, id);
+ lock_rw_unlock(&sne->biglock);
+ }
if (sq->subnet_downstream)
cp_edns_bad_response(c_out, c_in);
return module_finished;
}
lock_rw_wrlock(&sne->biglock);
- update_cache(qstate, id);
+ if(!sq->started_no_cache_store) {
+ update_cache(qstate, id);
+ }
sne->num_msg_nocache++;
lock_rw_unlock(&sne->biglock);
ecs_opt_list_append(&sq->ecs_client_out,
&qstate->edns_opts_front_out, qstate);
}
+ qstate->no_cache_store = sq->started_no_cache_store;
return;
}
if(sq && outbound) {
struct ecs_data ecs_server_out;
int subnet_downstream;
int subnet_sent;
+ /** has the subnet module been started with no_cache_store? */
+ int started_no_cache_store;
};
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
return 0;
return 1;
}
+
+int
+iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf)
+{
+ struct iter_hints_stub *stub;
+ struct delegpt *dp;
+
+ /* Check for stub. */
+ stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
+ qinf->qclass, NULL);
+ dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->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(qinf->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(qinf->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;
+}
*/
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
+/**
+ * Lookup if no_cache is set in stub or fwd.
+ * @param qstate: query state with env with hints and fwds.
+ * @param qinf: query name to lookup for.
+ * @return true if no_cache is set in stub or fwd.
+ */
+int iter_stub_fwd_no_cache(struct module_qstate *qstate,
+ struct query_info *qinf);
+
#endif /* ITERATOR_ITER_UTILS_H */
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
/* 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;
--- /dev/null
+; This is a comment.
+; config options go here.
+forward-zone: name: "." forward-addr: 216.0.0.1
+ forward-no-cache: yes
+CONFIG_END
+
+SCENARIO_BEGIN Forward with no_cache set
+RANGE_BEGIN 0 10
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+www.example.com. IN A
+ SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ SECTION AUTHORITY
+www.example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ns.example.com. IN A 10.20.30.50
+ ENTRY_END
+RANGE_END
+RANGE_BEGIN 200 300
+RANGE_END
+
+RANGE_BEGIN 20 100
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+www.example.com. IN A
+ SECTION ANSWER
+www.example.com. IN A 10.20.30.44
+ SECTION AUTHORITY
+www.example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ns.example.com. IN A 10.20.30.50
+ ENTRY_END
+RANGE_END
+RANGE_BEGIN 200 300
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA
+MATCH opcode qname qtype all
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+; make some time pass but not enough to timeout a cached record
+STEP 10 TIME_PASSES ELAPSE 10
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+STEP 24 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA
+MATCH opcode qname qtype all
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.44
+ENTRY_END
+SCENARIO_END