+18 May 2026: Wouter
+ - Fix for mixed class referrals, the resolver uses the query
+ class. Thanks to Xin Wang and Jiajia Liu, Northwestern
+ Polytechnical University, for the report.
+
15 May 2026: Wouter
- Fix man page entry for so-sndbuf, it is for responses sent out.
- Fix val_find_DS for robustness, to check the result of
/** find NS rrset in given list */
static struct ub_packed_rrset_key*
-find_NS(struct reply_info* rep, size_t from, size_t to)
+find_NS(struct reply_info* rep, size_t from, size_t to, uint16_t qclass)
{
size_t i;
for(i=from; i<to; i++) {
- if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS &&
+ ntohs(rep->rrsets[i]->rk.rrset_class) == qclass)
return rep->rrsets[i];
}
return NULL;
size_t i;
/* look for NS records in the authority section... */
ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets,
- msg->rep->an_numrrsets+msg->rep->ns_numrrsets);
+ msg->rep->an_numrrsets+msg->rep->ns_numrrsets,
+ msg->qinfo.qclass);
/* In some cases (even legitimate, perfectly legal cases), the
* NS set for the "referral" might be in the answer section. */
if(!ns_rrset)
- ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets);
+ ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets,
+ msg->qinfo.qclass);
/* If there was no NS rrset in the authority section, then this
* wasn't a referral message. (It might not actually be a
i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
continue;
- if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
+ if(ntohs(s->rk.type) == LDNS_RR_TYPE_A &&
+ ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
return NULL;
- } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
+ } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA &&
+ ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
return NULL;
}
"RRset:", pkt, msg, prev, &rrset);
continue;
}
+ if(ntohs(rrset->rrset_class) != qinfo->qclass) {
+ remove_rrset("normalize: removing other class "
+ "RRset:", pkt, msg, prev, &rrset);
+ continue;
+ }
if(nsset == NULL) {
nsset = rrset;
} else {
--- /dev/null
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+ qname-minimisation: "no"
+ minimal-responses: no
+ iter-scrub-promiscuous: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test referral with mixed class items
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR 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 NOERROR
+SECTION QUESTION
+www.example.com. IN A
+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
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+; mixed class contents
+example.com. CH NS ch.example.com.
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ch.example.com. CH A 1.2.3.5
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+; ch.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ch.example.com.
+SECTION ADDITIONAL
+ch.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.42
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END