summaryrefslogtreecommitdiff
path: root/edns-subnet/subnetmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'edns-subnet/subnetmod.c')
-rw-r--r--edns-subnet/subnetmod.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c
index 37dc550cd69c3..f1b401b9080ce 100644
--- a/edns-subnet/subnetmod.c
+++ b/edns-subnet/subnetmod.c
@@ -386,8 +386,7 @@ update_cache(struct module_qstate *qstate, int id)
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
- edns->subnet_source_mask,
- sq->ecs_server_in.subnet_scope_mask, rep,
+ edns->subnet_source_mask, sq->max_scope, rep,
rep->ttl, *qstate->env->now);
lock_rw_unlock(&lru_entry->lock);
@@ -543,7 +542,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
c_out->subnet_addr_fam = c_in->subnet_addr_fam;
c_out->subnet_source_mask = c_in->subnet_source_mask;
memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
- c_out->subnet_scope_mask = s_in->subnet_scope_mask;
+ c_out->subnet_scope_mask = sq->max_scope;
/* Limit scope returned to client to scope used for caching. */
if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
if(c_out->subnet_scope_mask >
@@ -648,6 +647,19 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
qstate->env->cfg->client_subnet_opcode);
sq->subnet_sent = 0;
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
+ } else if (!sq->track_max_scope &&
+ FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
+ response->rep->an_numrrsets > 0
+ ) {
+ struct ub_packed_rrset_key* s = response->rep->rrsets[0];
+ if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
+ query_dname_compare(qstate->qinfo.qname,
+ s->rk.dname) == 0) {
+ /* CNAME response for QNAME. From now on keep track of
+ * longest received ECS prefix for all queries on this
+ * qstate. */
+ sq->track_max_scope = 1;
+ }
}
return 1;
}
@@ -663,16 +675,19 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
return 1;
if((ecs_opt = edns_opt_list_find(
qstate->edns_opts_back_in,
- qstate->env->cfg->client_subnet_opcode))) {
- if(parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
- sq->subnet_sent &&
- sq->ecs_server_in.subnet_validdata)
+ qstate->env->cfg->client_subnet_opcode)) &&
+ parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
+ sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
/* Only skip global cache store if we sent an ECS option
* and received one back. Answers from non-whitelisted
* servers will end up in global cache. Answers for
* queries with 0 source will not (unless nameserver
* does not support ECS). */
qstate->no_cache_store = 1;
+ if(!sq->track_max_scope || (sq->track_max_scope &&
+ sq->ecs_server_in.subnet_scope_mask >
+ sq->max_scope))
+ sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
}
return 1;