From 5d81a258e3c7988c9505bba9071e6db9ff327399 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 4 Dec 2023 17:15:41 +1100 Subject: [PATCH] Return partial match when requested Return partial match from dns_db_find/dns_db_find when requested to short circuit the closest encloser discover process. Most of the time this will be the actual closest encloser but may not be when there yet to be committed / cleaned up versions of the zone with names below the actual closest encloser. (cherry picked from commit d42ea08f16bc6fc4b401f6b6f45a387cfb7f5d73) --- bin/tests/system/dnssec/tests.sh | 4 ++-- lib/dns/include/dns/db.h | 1 + lib/dns/rbtdb.c | 6 +++++- lib/ns/query.c | 20 ++++++++++++++++---- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index c7b1c3aab8..6ef6b1d84e 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -386,9 +386,9 @@ status=$((status + ret)) echo_i "checking negative validation NXDOMAIN NSEC3 ($n)" ret=0 -dig_with_opts +noauth q.nsec3.example. \ +dig_with_opts +noauth a.b.c.d.e.f.g.h.i.j.nsec3.example. \ @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth q.nsec3.example. \ +dig_with_opts +noauth a.b.c.d.e.f.g.h.i.j.nsec3.example. \ @10.53.0.4 a >dig.out.ns4.test$n || ret=1 digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 07ff9a43d5..5cc563884d 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -244,6 +244,7 @@ struct dns_dbonupdatelistener { #define DNS_DBFIND_FORCENSEC3 0x0080 #define DNS_DBFIND_ADDITIONALOK 0x0100 #define DNS_DBFIND_NOZONECUT 0x0200 +#define DNS_DBFIND_WANTPARTIAL 0x0400 /* * DNS_DBFIND_STALEOK: This flag is set when BIND fails to refresh a RRset due diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 5c2f0b252d..bb184f7ed8 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -4134,7 +4134,11 @@ zone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, : DNS_R_NXDOMAIN; } } else { - result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN; + bool wantpartial = (options & DNS_DBFIND_WANTPARTIAL) != + 0; + result = active ? DNS_R_EMPTYNAME + : wantpartial ? DNS_R_PARTIALMATCH + : DNS_R_NXDOMAIN; } goto tree_exit; } else if (result != ISC_R_SUCCESS) { diff --git a/lib/ns/query.c b/lib/ns/query.c index 58a9d436fc..0d5274226c 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -11569,6 +11569,7 @@ again: * Find the closest encloser. */ dns_name_copy(name, cname); + bool once = true; while (result == DNS_R_NXDOMAIN) { labels = dns_name_countlabels(cname) - 1; /* @@ -11578,10 +11579,21 @@ again: goto cleanup; } dns_name_split(cname, labels, NULL, cname); - result = dns_db_findext(qctx->db, cname, qctx->version, - dns_rdatatype_nsec, options, 0, - NULL, fname, &cm, &ci, NULL, - NULL); + result = dns_db_findext( + qctx->db, cname, qctx->version, + dns_rdatatype_nsec, + options | (once ? DNS_DBFIND_WANTPARTIAL : 0), + 0, NULL, fname, &cm, &ci, NULL, NULL); + if (result == DNS_R_PARTIALMATCH && once) { + unsigned int flabels = + dns_name_countlabels(fname); + if (labels > flabels + 1) { + dns_name_split(cname, flabels + 1, NULL, + cname); + } + result = DNS_R_NXDOMAIN; + } + once = false; } /* * Add closest (provable) encloser NSEC3.