if(modstack_find(&worker->env.mesh->mods, "subnetcache") != -1
&& worker->env.unique_mesh) {
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
- PREFETCH_EXPIRY_ADD, rpz_passthru, repinfo, opt_list);
- PREFETCH_EXPIRY_ADD, rpz_passthru, &repinfo->addr, opt_list);
++ PREFETCH_EXPIRY_ADD, rpz_passthru,
++ &repinfo->client_addr, opt_list);
return;
}
#endif
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
struct ecs_data *edns = &sq->ecs_client_in;
size_t i;
- hashvalue_type h;
- struct lruhash_entry* lru_entry;
- int need_to_insert;
-
- /* qinfo_hash is not set if it is prefetch request */
- if (qstate->minfo[id] && ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash) {
- h = ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash;
- } else {
- h = query_info_hash(&qstate->qinfo, qstate->query_flags);
- }
-
+ int only_match_scope_zero;
+
+ /* We already calculated hash upon lookup (lookup_and_reply) if we were
+ * allowed to look in the ECS cache */
+ hashvalue_type h = qstate->minfo[id] &&
+ ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated?
+ ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
+ query_info_hash(&qstate->qinfo, qstate->query_flags);
/* Step 1, general qinfo lookup */
- struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
- lru_entry = slabhash_lookup(subnet_msg_cache, h,
++ struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h,
&qstate->qinfo, 1);
- need_to_insert = (lru_entry == NULL);
+ int need_to_insert = (lru_entry == NULL);
if (!lru_entry) {
void* data = calloc(1,
sizeof(struct subnet_msg_cache_data));
return;
}
- lock_rw_wrlock(&sne->biglock);
- if (qstate->mesh_info->reply_list && lookup_and_reply(qstate, id, sq, qstate->env->cfg->prefetch)) {
- sne->num_msg_cache++;
- lock_rw_unlock(&sne->biglock);
- verbose(VERB_QUERY, "subnetcache: answered from cache");
- qstate->ext_state[id] = module_finished;
+ if(!sq->started_no_cache_lookup && !qstate->blacklist) {
+ lock_rw_wrlock(&sne->biglock);
- if(lookup_and_reply(qstate, id, sq)) {
++ if(qstate->mesh_info->reply_list &&
++ lookup_and_reply(qstate, id, sq,
++ qstate->env->cfg->prefetch)) {
+ sne->num_msg_cache++;
+ lock_rw_unlock(&sne->biglock);
+ verbose(VERB_QUERY, "subnetcache: answered from cache");
+ qstate->ext_state[id] = module_finished;
- subnet_ecs_opt_list_append(&sq->ecs_client_out,
- &qstate->edns_opts_front_out, qstate);
- return;
+ subnet_ecs_opt_list_append(&sq->ecs_client_out,
+ &qstate->edns_opts_front_out, qstate,
+ qstate->region);
+ if(verbosity >= VERB_ALGO) {
+ subnet_log_print("reply has edns subnet",
+ edns_opt_list_find(
+ qstate->edns_opts_front_out,
+ qstate->env->cfg->
+ client_subnet_opcode));
+ }
+ return;
+ }
+ lock_rw_unlock(&sne->biglock);
}
- lock_rw_unlock(&sne->biglock);
sq->ecs_server_out.subnet_addr_fam =
sq->ecs_client_in.subnet_addr_fam;
return;
}
} else {
- /* Fake the ECS data from the client's IP */
- struct ecs_data ecs;
- memset(&ecs, 0, sizeof(ecs));
- subnet_option_from_ss(addr, &ecs, mesh->env->cfg);
- if(ecs.subnet_validdata == 0) {
- log_err("prefetch_subnet subnet_option_from_ss: invalid data");
- return;
- }
- subnet_ecs_opt_list_append(&ecs, &s->s.edns_opts_front_in, &s->s);
- if(!s->s.edns_opts_front_in) {
- log_err("prefetch_subnet subnet_ecs_opt_list_append: out of memory");
- return;
- }
+ /* Store the client's address. Later in the subnet module,
+ * it is decided whether to include an ECS option or not.
+ */
- s->s.client_addr = rep->client_addr;
++ s->s.client_addr = *addr;
}
#ifdef UNBOUND_DEBUG
n =
if(s == module_finished) {
if(mstate->s.curmod == 0) {
struct query_info* qinfo = NULL;
- struct edns_option* opt_list = NULL, *ecs;
++ struct edns_option* opt_list = NULL;
+ struct sockaddr_storage addr;
uint16_t qflags;
int rpz_p = 0;
- addr = mstate->reply_list->query_reply.addr;
+ #ifdef CLIENT_SUBNET
++ struct edns_option* ecs;
+ if(mstate->s.need_refetch && mstate->reply_list &&
+ modstack_find(&mesh->mods, "subnetcache") != -1 &&
+ mstate->s.env->unique_mesh) {
++ addr = mstate->reply_list->query_reply.client_addr;
+ } else
+ #endif
+ memset(&addr, 0, sizeof(addr));
+
mesh_query_done(mstate);
mesh_walk_supers(mesh, mstate);
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
-www.example.com. IN A
+www.example.com. IN A
SECTION ANSWER
- www.example.com. 1 IN A 10.20.30.40
+ www.example.com. 1 IN A 10.20.30.40
SECTION AUTHORITY
- example.com. 3591 IN NS ns.example.com.
+ example.com. 3591 IN NS ns.example.com.
SECTION ADDITIONAL
- ns.example.com. 3591 IN A 1.2.3.4
+ ns.example.com. 3591 IN A 1.2.3.4
ENTRY_END
- ; Allow time to pass so that the global cache record is expired
- STEP 13 TIME_PASSES ELAPSE 2
+ ; Allow for some time to pass to differentiate from a cached vs resolved answer
+ STEP 6 TIME_PASSES ELAPSE 1
- ; Query again to verify that the record was prefetched and stored in the ECS
- ; cache (because the server replied with ECS this time)
- STEP 14 QUERY
+ STEP 7 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION