]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix that dns64 with subnetcache does not write ECS scoped
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 27 May 2026 11:31:11 +0000 (13:31 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 27 May 2026 11:31:11 +0000 (13:31 +0200)
  answers to global cache. Thanks to Qifan Zhang, Palo Alto
  Networks, for the report.

dns64/dns64.c
doc/Changelog
edns-subnet/subnetmod.c
testdata/subnet_dns64_lookup.crpl [new file with mode: 0644]
util/module.h

index a0c911f02f22fb6db7d5c741a1315e6ae751f120..fdcc1b41d0aba09f54c205566228cd2621ed6b26 100644 (file)
@@ -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))
index 0ec47e63d822b0361141f9f389ee15b306cb7b17..bb9452922e1c07e5d492273ab7babef6c73d5b24 100644 (file)
@@ -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
index 587839faa6dfb4577f173feca90141b18462b126..be09742f89e65b295e0f8433c6f21629d9b52de0 100644 (file)
@@ -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 (file)
index 0000000..ec30d54
--- /dev/null
@@ -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
index 631eb530bbf03025534626140576bd384efedca6..d093c2aeca0bf58cf652c1b571c4ef522a0fdff7 100644 (file)
@@ -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. */