]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add dns_adb_createaddrinfosfind() for address-based lookups
authorColin Vidal <colin@isc.org>
Sat, 28 Mar 2026 09:02:22 +0000 (10:02 +0100)
committerColin Vidal <colin@isc.org>
Mon, 30 Mar 2026 18:41:13 +0000 (20:41 +0200)
Add a new ADB API function that creates a find from a list of addresses
rather than by looking up nameserver names.  This enables the resolver
to handle address-based delegations (NS-based with glues or DELEG with
addresses) and name-based delegations uniformly (i.e. the list of finds
from ADB is handled the same way no matter the type of the delegation).

lib/dns/adb.c
lib/dns/include/dns/adb.h

index db984019e8ea6df171ebaf0a13c0be5967aeb934..6c02ed86a46e194891346d0aea79eae724fedcc7 100644 (file)
@@ -1714,6 +1714,86 @@ dns_adb_shutdown(dns_adb_t *adb) {
        isc_async_run(isc_loop_main(), dns_adb_shutdown_async, adb);
 }
 
+static void
+findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *addr,
+            dns_adbaddrinfo_t **adbaddrp, isc_stdtime_t now) {
+       dns_adbentry_t *adbentry = get_attached_and_locked_entry(adb, now,
+                                                                addr);
+
+       in_port_t port = isc_sockaddr_getport(addr);
+       *adbaddrp = new_adbaddrinfo(adb, adbentry, port);
+
+       UNLOCK(&adbentry->lock);
+       dns_adbentry_detach(&adbentry);
+}
+
+isc_result_t
+dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
+                           in_port_t port, unsigned int options,
+                           isc_stdtime_t now, size_t maxaddrs,
+                           dns_adbfind_t **findp, size_t *findlen) {
+       isc_result_t result = ISC_R_SUCCESS;
+       dns_adbfind_t *find = NULL;
+       isc_sockaddr_t sockaddr = {};
+
+       REQUIRE(DNS_ADB_VALID(adb));
+       REQUIRE(addrs != NULL);
+       REQUIRE(findp != NULL && *findp == NULL);
+
+       rcu_read_lock();
+
+       if (atomic_load(&adb->shuttingdown)) {
+               CLEANUP(ISC_R_SHUTTINGDOWN);
+       }
+
+       if (now == 0) {
+               now = isc_stdtime_now();
+       }
+
+       find = new_adbfind(adb, port);
+       ISC_LIST_FOREACH(*addrs, addrlink, link) {
+               dns_adbaddrinfo_t *addrinfo = NULL;
+
+               sockaddr.type.sa.sa_family = addrlink->addr.family;
+               switch (addrlink->addr.family) {
+               case AF_INET:
+                       if ((options & DNS_ADBFIND_INET) == 0) {
+                               continue;
+                       }
+                       sockaddr.type.sin.sin_addr = addrlink->addr.type.in;
+                       sockaddr.type.sin.sin_port = htons(port);
+                       break;
+               case AF_INET6:
+                       if ((options & DNS_ADBFIND_INET6) == 0) {
+                               continue;
+                       }
+                       /*
+                        * TODO: findaddrinfo() compares the scope, this might
+                        * be a problem...
+                        */
+                       sockaddr.type.sin6.sin6_addr = addrlink->addr.type.in6;
+                       sockaddr.type.sin6.sin6_port = htons(port);
+
+                       break;
+               default:
+                       UNREACHABLE();
+               }
+
+               findaddrinfo(adb, &sockaddr, &addrinfo, now);
+               ISC_LIST_APPEND(find->list, addrinfo, publink);
+               (*findlen)++;
+
+               if (maxaddrs - *findlen == 0) {
+                       break;
+               }
+       }
+
+       *findp = find;
+cleanup:
+       rcu_read_unlock();
+       return result;
+}
+
 /*
  * Look up the name in our internal database.
  *
@@ -3137,14 +3217,7 @@ dns_adb_findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *addr,
                return ISC_R_SHUTTINGDOWN;
        }
 
-       dns_adbentry_t *adbentry = get_attached_and_locked_entry(adb, now,
-                                                                addr);
-
-       in_port_t port = isc_sockaddr_getport(addr);
-       *adbaddrp = new_adbaddrinfo(adb, adbentry, port);
-
-       UNLOCK(&adbentry->lock);
-       dns_adbentry_detach(&adbentry);
+       findaddrinfo(adb, addr, adbaddrp, now);
 
        rcu_read_unlock();
 
index 399e665ee8bb534c375947397b8aee2304d53ee8..157f8da0b2bfd50dc082f9a8bb15a8440e63b1a7 100644 (file)
@@ -346,6 +346,18 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
  *     returns.
  */
 
+isc_result_t
+dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
+                           in_port_t port, unsigned int options,
+                           isc_stdtime_t now, size_t maxaddrs,
+                           dns_adbfind_t **findp, size_t *findlen);
+/*%<
+ * Variant of `dns_adb_createfind()` which actually internally looks up
+ * addresses only using `dns_adb_findaddrinfo()`. This enables the caller to
+ * abstract the origin of the find (i.e. it needs to be names to be looked up
+ * into `dns_adbaddrinfo_t`, or from net addrs) and handle it the same way.
+ */
+
 void
 dns_adb_cancelfind(dns_adbfind_t *find);
 /*%<