return 1;
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
+ if(sq->is_subquery_nonsubnet) {
+ if(sq->is_subquery_scopezero) {
+ /* Check if the result can be stored in the global cache,
+ * this is okay if the address and name are not configured
+ * as subnet address and subnet zone. */
+ if(!ecs_is_whitelisted(sn_env->whitelist,
+ addr, addrlen, qinfo->qname, qinfo->qname_len,
+ qinfo->qclass)) {
+ verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.");
+ qstate->no_cache_store = 0;
+ }
+ }
+ return 1;
+ }
+
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)
/**
* Create sub request that looks up the query.
* @param qstate: query state
+ * @param id: module id.
* @param sq: subnet qstate
* @return false on failure.
*/
static int
-generate_sub_request(struct module_qstate *qstate, struct subnet_qstate* sq)
+generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* sq)
{
struct module_qstate* subq = NULL;
uint16_t qflags = 0; /* OPCODE QUERY, no flags */
}
if(subq) {
/* It is possible to access the subquery module state. */
+ struct subnet_qstate* subsq;
+ if(!subnet_new_qstate(subq, id)) {
+ verbose(VERB_ALGO, "Could not allocate new subnet qstate");
+ return 0;
+ }
+ subsq = (struct subnet_qstate*)subq->minfo[id];
+ subsq->is_subquery_nonsubnet = 1;
+
+ /* When the client asks 0.0.0.0/0 and the name is not treated
+ * as subnet, it is to be stored in the global cache.
+ * Store that the client asked for that, if so. */
if(sq->ecs_client_in.subnet_source_mask == 0 &&
edns_opt_list_find(qstate->edns_opts_front_in,
qstate->env->cfg->client_subnet_opcode)) {
subq->no_cache_store = 1;
+ subsq->is_subquery_scopezero = 1;
}
}
return 1;
/**
* Perform the query without subnet
* @param qstate: query state
+ * @param id: module id.
* @param sq: subnet qstate
* @return module state
*/
static enum module_ext_state
-generate_lookup_without_subnet(struct module_qstate *qstate,
+generate_lookup_without_subnet(struct module_qstate *qstate, int id,
struct subnet_qstate* sq)
{
verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet");
- if(!generate_sub_request(qstate, sq)) {
+ if(!generate_sub_request(qstate, id, sq)) {
verbose(VERB_ALGO, "Could not generate sub query");
qstate->return_rcode = LDNS_RCODE_FORMERR;
qstate->return_msg = NULL;
* is still useful to put it in the edns subnet cache for
* when a client explicitly asks for subnet specific answer. */
verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
- return generate_lookup_without_subnet(qstate, sq);
+ return generate_lookup_without_subnet(qstate, id, sq);
}
/* Purposefully there was no sent subnet, and there is consequently
qstate->env->cfg->client_subnet_opcode);
sq->subnet_sent = 0;
sq->subnet_sent_no_subnet = 0;
- return generate_lookup_without_subnet(qstate, sq);
+ return generate_lookup_without_subnet(qstate, id, sq);
}
lock_rw_wrlock(&sne->biglock);
/* aggregated this deaggregated state */
qstate->ext_state[id] =
generate_lookup_without_subnet(
- qstate, sq);
+ qstate, id, sq);
return;
}
verbose(VERB_ALGO, "subnetcache: pass to next module");
qstate->env->cfg->client_subnet_opcode)) {
/* client asked for resolution without edns subnet */
qstate->ext_state[id] = generate_lookup_without_subnet(
- qstate, sq);
+ qstate, id, sq);
return;
}