mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
fix: usr: Fix a bug in the static-stub implementation
Static-stub addresses and addresses from other sources were 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 correct server addresses. Closes #4850 Merge branch '4850-add-an-additional-class-of-names-to-adb' into 'main' See merge request isc-projects/bind9!9314
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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:
|
||||
|
@@ -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;
|
||||
|
@@ -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.
|
||||
|
Reference in New Issue
Block a user