From: W.C.A. Wijngaards Date: Wed, 27 May 2026 11:31:11 +0000 (+0200) Subject: - Fix that dns64 with subnetcache does not write ECS scoped X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=b53504049c13ba2d75e02e4bb5e2b3efa0ca17c7;p=thirdparty%2Funbound.git - Fix that dns64 with subnetcache does not write ECS scoped answers to global cache. Thanks to Qifan Zhang, Palo Alto Networks, for the report. --- diff --git a/dns64/dns64.c b/dns64/dns64.c index a0c911f02..fdcc1b41d 100644 --- a/dns64/dns64.c +++ b/dns64/dns64.c @@ -660,6 +660,7 @@ handle_event_moddone(struct module_qstate* qstate, int id) /* Store the response in cache. */ if( (!iq || !iq->started_no_cache_store) && + !qstate->is_subnet_answer && qstate->return_msg && qstate->return_msg->rep && !dns_cache_store( @@ -1015,6 +1016,7 @@ dns64_inform_super(struct module_qstate* qstate, int id, /* Store the generated response in cache. */ if ( (!super_dq || !super_dq->started_no_cache_store) && + !super->is_subnet_answer && !dns_cache_store(super->env, &super->qinfo, super->return_msg->rep, 0, super->prefetch_leeway, 0, NULL, super->query_flags, qstate->qstarttime, qstate->is_valrec)) diff --git a/doc/Changelog b/doc/Changelog index 0ec47e63d..bb9452922 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -21,6 +21,9 @@ to Qifan Zhang, Palo Alto Networks, for the report. - Fix, in depth, for respip rewrite of dns64 responses. Thanks to Qifan Zhang, Palo Alto Networks, for the report. + - Fix that dns64 with subnetcache does not write ECS scoped + answers to global cache. Thanks to Qifan Zhang, Palo Alto + Networks, for the report. 26 May 2026: Wouter - Fix for mesh new client and mesh new callback to rollback the diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index 587839faa..be09742f8 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -1015,6 +1015,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, subnet_ecs_opt_list_append(&sq->ecs_client_out, &qstate->edns_opts_front_out, qstate, qstate->region); + qstate->is_subnet_answer = 1; } sq->wait_subquery_done = 0; qstate->ext_state[id] = module_finished; @@ -1094,6 +1095,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, qstate->env->cfg->prefetch)) { sne->num_msg_cache++; lock_rw_unlock(&sne->biglock); + qstate->is_subnet_answer = 1; verbose(VERB_QUERY, "subnetcache: answered from cache"); qstate->ext_state[id] = module_finished; @@ -1165,6 +1167,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event, subnet_ecs_opt_list_append(&sq->ecs_client_out, &qstate->edns_opts_front_out, qstate, qstate->region); + qstate->is_subnet_answer = 1; if(verbosity >= VERB_ALGO) { subnet_log_print("reply has edns subnet", edns_opt_list_find( diff --git a/testdata/subnet_dns64_lookup.crpl b/testdata/subnet_dns64_lookup.crpl new file mode 100644 index 000000000..ec30d5415 --- /dev/null +++ b/testdata/subnet_dns64_lookup.crpl @@ -0,0 +1,224 @@ +server: + target-fetch-policy: "0 0 0 0 0" + access-control: 0.0.0.0/0 allow + send-client-subnet: 5.0.15.10 + max-client-subnet-ipv4: 24 + verbosity: 3 + module-config: "dns64 subnetcache iterator" + qname-minimisation: no + minimal-responses: yes + dns64-prefix: 64:ff9b::0/96 + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Subnet with DNS64 lookup + +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION AUTHORITY +net. IN SOA ns.example.com. root.example.com. 4 14400 3600 604800 3600 +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 5.0.15.10 +ENTRY_END +RANGE_END + +RANGE_BEGIN 0 100 + ADDRESS 5.0.15.10 +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ;; we expect to receive empty +HEX_EDNSDATA_END +ns.example.com. IN A 5.0.15.10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. root.example.com. 4 14400 3600 604800 3600 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ;; we expect to receive empty +HEX_EDNSDATA_END +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id copy_query copy_ednsdata_assume_clientsubnet +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 4.3.0.3 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 10.0.3.0 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 0a 00 03 ; address +HEX_EDNSDATA_END +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id copy_query copy_ednsdata_assume_clientsubnet +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 4.3.0.4 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 10.0.4.0 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 0a 00 04 ; address +HEX_EDNSDATA_END +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id copy_query copy_ednsdata_assume_clientsubnet +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN AAAA 2001:db8::3 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 10.0.3.0 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 0a 00 03 ; address +HEX_EDNSDATA_END +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname ednsdata +ADJUST copy_id copy_query copy_ednsdata_assume_clientsubnet +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN AAAA 2001:db8::4 +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + ; client is 10.0.4.0 + 00 08 ; OPC + 00 07 ; option length + 00 01 ; Family + 18 00 ; source mask, scopemask + 0a 00 04 ; address +HEX_EDNSDATA_END +ENTRY_END + +RANGE_END + +STEP 1 QUERY ADDRESS 10.0.3.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END + +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +;www.example.com. IN A 4.3.0.3 +www.example.com. IN AAAA 2001:db8::3 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 10 QUERY ADDRESS 10.0.4.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +;www.example.com. IN A 4.3.0.4 +www.example.com. IN AAAA 2001:db8::4 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/util/module.h b/util/module.h index 631eb530b..d093c2aec 100644 --- a/util/module.h +++ b/util/module.h @@ -701,6 +701,8 @@ struct module_qstate { time_t qstarttime; /** whether a message from cachedb will be used for the reply */ int is_cachedb_answer; + /** whether the reply is subnet specific */ + int is_subnet_answer; /** if the response as error is from error_response_cache, and is * suitable for caching (briefly) the error response. Set by the * iterator when no_cache_store is enabled, and there is an error. */