]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Store static-stub addresses seperately in the adb
authorMark Andrews <marka@isc.org>
Wed, 14 Aug 2024 13:46:44 +0000 (23:46 +1000)
committerMark Andrews <marka@isc.org>
Tue, 1 Oct 2024 00:19:13 +0000 (00:19 +0000)
Static-stub address and addresses from other sources where being
mixed together resulting in static-stub queries going to addresses
not specified in the configuration or alternatively static-stub
addresses being used instead of the real addresses.

lib/dns/adb.c
lib/dns/include/dns/adb.h
lib/dns/include/dns/rdataset.h
lib/dns/resolver.c
lib/dns/view.c

index ef92322afa88c3fac98dbb7c8e8e9b6bc7e12258..d934e232d093609a9c271aa314da24657e51fa5a 100644 (file)
@@ -265,7 +265,7 @@ ISC_REFCOUNT_DECL(dns_adbentry);
  * Internal functions (and prototypes).
  */
 static dns_adbname_t *
-new_adbname(dns_adb_t *adb, const dns_name_t *, bool start_at_zone);
+new_adbname(dns_adb_t *adb, const dns_name_t *, unsigned int flags);
 static void
 destroy_adbname(dns_adbname_t *);
 static bool
@@ -296,7 +296,7 @@ static void
 purge_stale_names(dns_adb_t *adb, isc_stdtime_t now);
 static dns_adbname_t *
 get_attached_and_locked_name(dns_adb_t *, const dns_name_t *,
-                            bool start_at_zone, isc_stdtime_t now);
+                            unsigned int flags, isc_stdtime_t now);
 static void
 purge_stale_entries(dns_adb_t *adb, isc_stdtime_t now);
 static dns_adbentry_t *
@@ -409,9 +409,12 @@ enum {
 #define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
 #define FIND_AVOIDFETCHES(fn)  (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) != 0)
 #define FIND_STARTATZONE(fn)   (((fn)->options & DNS_ADBFIND_STARTATZONE) != 0)
+#define FIND_STATICSTUB(fn)    (((fn)->options & DNS_ADBFIND_STATICSTUB) != 0)
 #define FIND_HAS_ADDRS(fn)     (!ISC_LIST_EMPTY((fn)->list))
 #define FIND_NOFETCH(fn)       (((fn)->options & DNS_ADBFIND_NOFETCH) != 0)
 
+#define ADBNAME_FLAGS_MASK (DNS_ADBFIND_STARTATZONE | DNS_ADBFIND_STATICSTUB)
+
 /*
  * These are currently used on simple unsigned ints, so they are
  * not really associated with any particular type.
@@ -951,7 +954,7 @@ clean_finds_at_name(dns_adbname_t *name, dns_adbstatus_t astat,
 }
 
 static dns_adbname_t *
-new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
+new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, unsigned int flags) {
        dns_adbname_t *name = NULL;
 
        name = isc_mem_get(adb->mctx, sizeof(*name));
@@ -966,6 +969,7 @@ new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
                .v6 = ISC_LIST_INITIALIZER,
                .finds = ISC_LIST_INITIALIZER,
                .link = ISC_LINK_INITIALIZER,
+               .flags = flags & ADBNAME_FLAGS_MASK,
                .magic = DNS_ADBNAME_MAGIC,
        };
 
@@ -981,10 +985,6 @@ new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
        dns_name_copy(dnsname, name->name);
        dns_name_init(&name->target, NULL);
 
-       if (start_at_zone) {
-               name->flags |= DNS_ADBFIND_STARTATZONE;
-       }
-
        inc_adbstats(adb, dns_adbstats_namescnt);
        return (name);
 }
@@ -1235,8 +1235,8 @@ match_adbname(void *node, const void *key) {
        const dns_adbname_t *adbname0 = node;
        const dns_adbname_t *adbname1 = key;
 
-       if ((adbname0->flags & DNS_ADBFIND_STARTATZONE) !=
-           (adbname1->flags & DNS_ADBFIND_STARTATZONE))
+       if ((adbname0->flags & ADBNAME_FLAGS_MASK) !=
+           (adbname1->flags & ADBNAME_FLAGS_MASK))
        {
                return (false);
        }
@@ -1247,12 +1247,12 @@ match_adbname(void *node, const void *key) {
 static uint32_t
 hash_adbname(const dns_adbname_t *adbname) {
        isc_hash32_t hash;
-       bool start_at_zone = adbname->flags & DNS_ADBFIND_STARTATZONE;
+       unsigned int flags = adbname->flags & ADBNAME_FLAGS_MASK;
 
        isc_hash32_init(&hash);
        isc_hash32_hash(&hash, adbname->name->ndata, adbname->name->length,
                        false);
-       isc_hash32_hash(&hash, &start_at_zone, sizeof(start_at_zone), true);
+       isc_hash32_hash(&hash, &flags, sizeof(flags), true);
        return (isc_hash32_finalize(&hash));
 }
 
@@ -1261,14 +1261,14 @@ hash_adbname(const dns_adbname_t *adbname) {
  */
 static dns_adbname_t *
 get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
-                            bool start_at_zone, isc_stdtime_t now) {
+                            unsigned int flags, isc_stdtime_t now) {
        isc_result_t result;
        dns_adbname_t *adbname = NULL;
        isc_time_t timenow;
        isc_stdtime_t last_update;
        dns_adbname_t key = {
                .name = UNCONST(name),
-               .flags = (start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0,
+               .flags = flags & ADBNAME_FLAGS_MASK,
        };
        uint32_t hashval = hash_adbname(&key);
        isc_rwlocktype_t locktype = isc_rwlocktype_read;
@@ -1294,7 +1294,7 @@ get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
                UPGRADELOCK(&adb->names_lock, locktype);
 
                /* Allocate a new name and add it to the hash table. */
-               adbname = new_adbname(adb, name, start_at_zone);
+               adbname = new_adbname(adb, name, key.flags);
 
                void *found = NULL;
                result = isc_hashmap_add(adb->names, hashval, match_adbname,
@@ -1959,6 +1959,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
                now = isc_stdtime_now();
        }
 
+       /*
+        * If STATICSTUB is set we always want to have STARTATZONE set.
+        */
+       if (options & DNS_ADBFIND_STATICSTUB) {
+               options |= DNS_ADBFIND_STARTATZONE;
+       }
+
        /*
         * Remember what types of addresses we are interested in.
         */
@@ -1975,8 +1982,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
 
 again:
        /* Try to see if we know anything about this name at all. */
-       adbname = get_attached_and_locked_name(adb, name,
-                                              FIND_STARTATZONE(find), now);
+       adbname = get_attached_and_locked_name(adb, name, find->options, now);
 
        if (NAME_DEAD(adbname)) {
                UNLOCK(&adbname->lock);
@@ -2050,7 +2056,7 @@ again:
                         * Any other result, start a fetch for A, then fall
                         * through to AAAA.
                         */
-                       if (!NAME_FETCH_A(adbname)) {
+                       if (!NAME_FETCH_A(adbname) && !FIND_STATICSTUB(find)) {
                                wanted_fetches |= DNS_ADBFIND_INET;
                        }
                        break;
@@ -2093,7 +2099,8 @@ again:
                        /*
                         * Any other result, start a fetch for AAAA.
                         */
-                       if (!NAME_FETCH_AAAA(adbname)) {
+                       if (!NAME_FETCH_AAAA(adbname) && !FIND_STATICSTUB(find))
+                       {
                                wanted_fetches |= DNS_ADBFIND_INET6;
                        }
                        break;
@@ -3391,6 +3398,7 @@ dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
        dns_adbname_t *adbname = NULL;
        isc_result_t result;
        bool start_at_zone = false;
+       bool static_stub = false;
        dns_adbname_t key = { .name = UNCONST(name) };
 
        REQUIRE(DNS_ADB_VALID(adb));
@@ -3403,9 +3411,11 @@ dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
        RWLOCK(&adb->names_lock, isc_rwlocktype_write);
 again:
        /*
-        * Delete both entries - without and with DNS_ADBFIND_STARTATZONE set.
+        * Delete all entries - with and without DNS_ADBFIND_STARTATZONE set
+        * and with and without DNS_ADBFIND_STATICSTUB set.
         */
-       key.flags = (start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0;
+       key.flags = ((static_stub) ? DNS_ADBFIND_STATICSTUB : 0) |
+                   ((start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0);
 
        result = isc_hashmap_find(adb->names, hash_adbname(&key), match_adbname,
                                  (void *)&key, (void **)&adbname);
@@ -3422,6 +3432,10 @@ again:
                start_at_zone = true;
                goto again;
        }
+       if (!static_stub) {
+               static_stub = true;
+               goto again;
+       }
        RWUNLOCK(&adb->names_lock, isc_rwlocktype_write);
 }
 
index 91f7039b73e822928776d88fddeab957a5656fad..7288cdd527940dd72502b64ba444c3f9373f84f4 100644 (file)
@@ -192,6 +192,10 @@ struct dns_adbfind {
  *     Don't perform a fetch even if there are no address records available.
  */
 #define DNS_ADBFIND_NOFETCH 0x00000800
+/*%
+ *     Only look for glue record for static stub.
+ */
+#define DNS_ADBFIND_STATICSTUB 0x00001000
 
 /*%
  * The answers to queries come back as a list of these.
index 9d8788676ae630caca25c4ccc532ec9bfd47a844..cb0a8d327b81feb266551f5f056ac99409e9b3ca 100644 (file)
@@ -265,6 +265,7 @@ struct dns_rdataset {
 #define DNS_RDATASETATTR_STALE_WINDOW 0x04000000
 #define DNS_RDATASETATTR_STALE_ADDED  0x08000000
 #define DNS_RDATASETATTR_KEEPCASE     0x10000000
+#define DNS_RDATASETATTR_STATICSTUB   0x20000000
 
 /*%
  * _OMITDNSSEC:
index e64d6693af34f4ae52b6bfb45ce02dbdc1e25365..a78fb1503359843a64d633f70a272ceb1318c019 100644 (file)
@@ -627,8 +627,9 @@ enum {
 #define BADCOOKIE(a)   (((a)->flags & FCTX_ADDRINFO_BADCOOKIE) != 0)
 #define ISDUALSTACK(a) (((a)->flags & FCTX_ADDRINFO_DUALSTACK) != 0)
 
-#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
-#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
+#define NXDOMAIN(r)   (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+#define NEGATIVE(r)   (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
+#define STATICSTUB(r) (((r)->attributes & DNS_RDATASETATTR_STATICSTUB) != 0)
 
 #ifdef ENABLE_AFL
 bool dns_fuzzing_resolver = false;
@@ -3596,6 +3597,7 @@ normal_nses:
             result = dns_rdataset_next(&fctx->nameservers))
        {
                bool overquota = false;
+               unsigned int static_stub = 0;
 
                dns_rdataset_current(&fctx->nameservers, &rdata);
                /*
@@ -3606,13 +3608,19 @@ normal_nses:
                        continue;
                }
 
+               if (STATICSTUB(&fctx->nameservers) &&
+                   dns_name_equal(&ns.name, fctx->domain))
+               {
+                       static_stub = DNS_ADBFIND_STATICSTUB;
+               }
+
                if (no_addresses > NS_FAIL_LIMIT &&
                    dns_rdataset_count(&fctx->nameservers) > NS_RR_LIMIT)
                {
                        stdoptions |= DNS_ADBFIND_NOFETCH;
                }
-               findname(fctx, &ns.name, 0, stdoptions, 0, now, &overquota,
-                        &need_alternate, &no_addresses);
+               findname(fctx, &ns.name, 0, stdoptions | static_stub, 0, now,
+                        &overquota, &need_alternate, &no_addresses);
 
                if (!overquota) {
                        all_spilled = false;
index 7e9e5bb0e30e598f93dee2db343994d44e7e8ecc..2be324156c2c0106af0dfd7953e4d51c7dc67a85 100644 (file)
@@ -930,7 +930,9 @@ db_find:
                result = ISC_R_SUCCESS;
        }
 
-       if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
+       if (result == ISC_R_NOTFOUND && !is_staticstub_zone && use_hints &&
+           view->hints != NULL)
+       {
                if (dns_rdataset_isassociated(rdataset)) {
                        dns_rdataset_disassociate(rdataset);
                }
@@ -1145,6 +1147,14 @@ db_find:
                        goto cleanup;
                }
 
+               /*
+                * Tag static stub NS RRset so that when we look for
+                * addresses we use the configured server addresses.
+                */
+               if (dns_zone_gettype(zone) == dns_zone_staticstub) {
+                       rdataset->attributes |= DNS_RDATASETATTR_STATICSTUB;
+               }
+
                if (use_cache && view->cachedb != NULL && db != view->hints) {
                        /*
                         * We found an answer, but the cache may be better.