]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Return wildcard names instead of synthetized names in dns_db_find()
authorAlessio Podda <alessio@isc.org>
Wed, 22 Jul 2026 13:43:18 +0000 (15:43 +0200)
committerAlessio Podda <alessio@isc.org>
Wed, 12 Aug 2026 19:57:34 +0000 (19:57 +0000)
Previously dns_db_find() would return the synthetized name on a
wildcard match. This is insufficient, as sometimes query processing
requires the wildcard name instead of the synthetized name.

This commit modifies the dns_db_find() API to return the wildcard
name instead of the synthetized name, and adds helper functions to
query.c to derive the synthetized name if needed.

lib/dns/qpzone.c
lib/dns/sdlz.c
lib/ns/query.c
tests/dns/qpzone_test.c

index 23749db8b3fd9aae431d719396723c37e685bb12..9f55e51c4803e9984992b691755cb55f1038bcf9 100644 (file)
@@ -3560,7 +3560,7 @@ qpzone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
                         */
                        result = find_wildcard(&search, &node, name, nspace);
                        if (result == ISC_R_SUCCESS) {
-                               dns_name_copy(name, foundname);
+                               dns_name_copy(&node->name, foundname);
                                wild = true;
                                goto found;
                        } else if (result != ISC_R_NOTFOUND) {
@@ -3827,6 +3827,9 @@ found:
                         *
                         * Return the delegation.
                         */
+                       if (wild) {
+                               foundname->attributes.wildcard = true;
+                       }
                        NODE_UNLOCK(nlock, &nlocktype);
                        result = qpzone_setup_delegation(
                                &search, nodep, foundname, rdataset,
index 49290aedff54106fe968eb8f8e726e5a5b3c85b8..198967f738b321ecfeb6c3dd94cab19aec4bbc3a 100644 (file)
@@ -479,6 +479,9 @@ getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
        char zonestr[DNS_NAME_MAXTEXT + 1];
        bool isorigin;
        dns_sdlzauthorityfunc_t authority;
+       dns_fixedname_t wildfixed;
+       dns_name_t *wildname = dns_fixedname_initname(&wildfixed);
+       const dns_name_t *nodename = name;
 
        REQUIRE(VALID_SDLZDB(sdlz));
        REQUIRE(nodep != NULL && *nodep == NULL);
@@ -572,6 +575,12 @@ getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
                                zonestr, wildstr, sdlz->dlzimp->driverarg,
                                sdlz->dbdata, node, methods, clientinfo);
                        if (result == ISC_R_SUCCESS) {
+                               result = dns_name_concatenate(
+                                       wild, &sdlz->common.origin, wildname);
+                               if (result != ISC_R_SUCCESS) {
+                                       break;
+                               }
+                               nodename = wildname;
                                break;
                        }
                }
@@ -603,7 +612,7 @@ getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
        }
 
        if (!dns_name_dynamic(&node->name)) {
-               dns_name_dup(name, sdlz->common.mctx, &node->name);
+               dns_name_dup(nodename, sdlz->common.mctx, &node->name);
        }
 
        *nodep = (dns_dbnode_t *)node;
@@ -902,7 +911,19 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
        }
 
        if (foundname != NULL) {
-               dns_name_copy(xname, foundname);
+               if (node != NULL) {
+                       dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
+
+                       dns_name_copy(&sdlznode->name, foundname);
+                       if (dns_name_iswildcard(&sdlznode->name) &&
+                           !dns_name_equal(name, &sdlznode->name) &&
+                           dns_name_matcheswildcard(name, &sdlznode->name))
+                       {
+                               foundname->attributes.wildcard = true;
+                       }
+               } else {
+                       dns_name_copy(xname, foundname);
+               }
        }
 
        if (nodep != NULL) {
index 950b6c7cfbc55994714d97d3334f6f263baa91c1..9f44f75765bfe2d75e9dec3bc6bda72fca7c9a4b 100644 (file)
@@ -1555,6 +1555,16 @@ query_isduplicate(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
        return false;
 }
 
+static void
+query_fix_wildcardname(const dns_name_t *qname, dns_name_t *fname) {
+       if (fname->attributes.wildcard) {
+               dns_name_copy(qname, fname);
+               fname->attributes.wildcard = true;
+       } else {
+               fname->attributes.wildcard = false;
+       }
+}
+
 /*
  * Look up data for given 'name' and 'type' in given 'version' of 'db' for
  * 'client'. Called from query_additionalauth().
@@ -1872,6 +1882,7 @@ found:
         * We have found a potential additional data rdataset, or
         * at least a node to iterate over.
         */
+       query_fix_wildcardname(name, fname);
        ns_client_keepname(client, fname, dbuf);
 
        /*
@@ -4417,6 +4428,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        result = dns_db_findext(db, client->query.qname, dbversion->version,
                                qtype, DNS_DBFIND_NOZONECUT, client->inner.now,
                                &node, found, &cm, &ci, &trdataset, NULL);
+       query_fix_wildcardname(client->query.qname, found);
        if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
                dns_rdataset_cleanup(rdataset);
                dns_rdataset_cleanup(&trdataset);
@@ -4555,6 +4567,7 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        result = dns_db_findext(db, redirectname, version, qtype, 0,
                                client->inner.now, &node, found, &cm, &ci,
                                &trdataset, NULL);
+       query_fix_wildcardname(redirectname, found);
        if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
                dns_rdataset_cleanup(rdataset);
                dns_rdataset_cleanup(&trdataset);
@@ -5496,7 +5509,10 @@ query_lookup(query_ctx_t *qctx) {
         */
        if (qctx->dns64 && qctx->rpz) {
                dns_name_copy(qctx->client->query.qname, qctx->fname);
+               qctx->fname->attributes.wildcard = false;
                dns_rdataset_cleanup(qctx->sigrdataset);
+       } else {
+               query_fix_wildcardname(rpzqname, qctx->fname);
        }
 
        if (!qctx->is_zone) {
index 066f5921a5372ee82910fad79c9eefc652464038..e4a0306a168311810c4191bd5eca6ae167d99978 100644 (file)
@@ -453,6 +453,49 @@ ISC_RUN_TEST_IMPL(diffop_add_sub) {
        assert_null(db);
 }
 
+ISC_RUN_TEST_IMPL(wildcard_foundname) {
+       static const unsigned char address[] = { 192, 0, 2, 1 };
+       isc_result_t result;
+       dns_db_t *db = NULL;
+       dns_dbversion_t *version = NULL;
+       dns_dbnode_t *node = NULL;
+       dns_fixedname_t fqname, fwild, ffound;
+       dns_name_t *qname = NULL, *wild = NULL, *found = NULL;
+       dns_rdataset_t rdataset;
+
+       result = dns__qpzone_create(isc_g_mctx, &example_org_name,
+                                   dns_dbtype_zone, dns_rdataclass_in, 0, NULL,
+                                   NULL, &db);
+       assert_int_equal(result, ISC_R_SUCCESS);
+       assert_non_null(db);
+
+       dns_test_namefromstring("host.example.org.", &fqname);
+       dns_test_namefromstring("*.example.org.", &fwild);
+       qname = dns_fixedname_name(&fqname);
+       wild = dns_fixedname_name(&fwild);
+       found = dns_fixedname_initname(&ffound);
+
+       WITH_NEWVERSION(db, newversion, true) {
+               apply_dns_update(db, newversion, wild, dns_rdatatype_a,
+                                dns_rdataclass_in, 300, address,
+                                sizeof(address), DNS_DIFFOP_ADD);
+       }
+
+       dns_rdataset_init(&rdataset);
+       dns_db_currentversion(db, &version);
+       result = dns_db_find(db, qname, version, dns_rdatatype_a, 0, 0, &node,
+                            found, &rdataset, NULL);
+       assert_int_equal(result, ISC_R_SUCCESS);
+       assert_true(dns_name_equal(found, wild));
+       assert_true(found->attributes.wildcard);
+
+       dns_rdataset_disassociate(&rdataset);
+       dns_db_detachnode(&node);
+       dns_db_closeversion(db, &version, false);
+       dns_db_detach(&db);
+       assert_null(db);
+}
+
 ISC_RUN_TEST_IMPL(diffop_addresign) {
        isc_result_t result;
        dns_db_t *db = NULL;
@@ -521,6 +564,7 @@ ISC_TEST_ENTRY(ownercase)
 ISC_TEST_ENTRY(setownercase)
 ISC_TEST_ENTRY(resign_sooner_values)
 ISC_TEST_ENTRY(diffop_add_sub)
+ISC_TEST_ENTRY(wildcard_foundname)
 ISC_TEST_ENTRY(diffop_addresign)
 ISC_TEST_LIST_END