From 14bb1f8aa0a088881340ab2fb1859d96fca077b0 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 10 Oct 2024 16:39:10 +1100 Subject: [PATCH] Use a binary search to find the NSEC3 closest encloser maxlabels is the suffix length that corresponds to the latest NXDOMAIN response. minlabels is the suffix length that corresponds to longest found existing name. (cherry picked from commit 67f31c504679dfcd9f1231037afa56da01e40d36) --- lib/ns/query.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/ns/query.c b/lib/ns/query.c index 17f2592c2e..05e6086ea2 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -11311,24 +11311,33 @@ again: * No NSEC proof available, return NSEC3 proofs instead. */ cname = dns_fixedname_initname(&cfixed); + /* - * Find the closest encloser. + * Find the closest encloser using a binary search. + * maxlabels: suffix length of NXDOMAIN result + * minlabels: suffix length of non NXDOMAIN result */ + unsigned int maxlabels = dns_name_countlabels(name); + unsigned int minlabels = dns_name_countlabels(fname); + bool search = result == DNS_R_NXDOMAIN; dns_name_copy(name, cname); - while (result == DNS_R_NXDOMAIN) { - labels = dns_name_countlabels(cname) - 1; - /* - * Sanity check. - */ - if (labels == 0U) { - goto cleanup; + while (search) { + labels = (maxlabels + minlabels) / 2; + dns_name_split(name, labels, NULL, cname); + if (labels == minlabels) { + break; } - 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); + if (result == DNS_R_NXDOMAIN) { + maxlabels = labels; + } else { + minlabels = labels; + } } + /* * Add closest (provable) encloser NSEC3. */