From b30bff7dee69f516e74ba54e8d1c7ba7958fe463 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/qpzone.c | 6 +++++- lib/dns/rbt-zonedb.c | 6 +++++- lib/ns/query.c | 20 ++++++++++++++++---- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index f2b7b76685..881548c80e 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 e38f4a3aca..cb689c4a01 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -258,6 +258,7 @@ enum { DNS_DBFIND_FORCENSEC3 = 1 << 5, DNS_DBFIND_ADDITIONALOK = 1 << 6, DNS_DBFIND_NOZONECUT = 1 << 7, + DNS_DBFIND_WANTPARTIAL = 1 << 8, }; /* diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 9ef4cf8ec8..efafd16c69 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -3414,7 +3414,11 @@ 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/dns/rbt-zonedb.c b/lib/dns/rbt-zonedb.c index d15abd2c84..de6be704c7 100644 --- a/lib/dns/rbt-zonedb.c +++ b/lib/dns/rbt-zonedb.c @@ -1095,7 +1095,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 75a87ca211..f656a21017 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -11216,6 +11216,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; /* @@ -11225,10 +11226,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.