mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 10:10:06 +00:00
When adding glue to the header, we add header to the wait-free stack to be cleaned up later which sets wfc_node->next to non-NULL value. When the actual cleaning happens we would only cleanup the .glue_list, but since the database isn't locked for the time being, the headers could be reused while cleaning the existing glue entries, which creates a data race between database versions. Revert the code back to use per-database-version hashtable where keys are the node pointers. This allows each database version to have independent glue cache table that doesn't affect nodes or headers that could already "belong" to the future database version.
191 lines
6.6 KiB
C
191 lines
6.6 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <isc/heap.h>
|
|
#include <isc/lang.h>
|
|
#include <isc/urcu.h>
|
|
|
|
#include <dns/nsec3.h>
|
|
#include <dns/rbt.h>
|
|
#include <dns/types.h>
|
|
|
|
#define GLUETABLE_INIT_SIZE 1 << 2
|
|
#define GLUETABLE_MIN_SIZE 1 << 8
|
|
|
|
#define RDATATYPE_NCACHEANY DNS_TYPEPAIR_VALUE(0, dns_rdatatype_any)
|
|
|
|
#ifdef STRONG_RWLOCK_CHECK
|
|
#define STRONG_RWLOCK_CHECK(cond) REQUIRE(cond)
|
|
#else
|
|
#define STRONG_RWLOCK_CHECK(cond)
|
|
#endif
|
|
|
|
#define NODE_INITLOCK(l) isc_rwlock_init((l))
|
|
#define NODE_DESTROYLOCK(l) isc_rwlock_destroy(l)
|
|
#define NODE_LOCK(l, t, tp) \
|
|
{ \
|
|
STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
|
|
RWLOCK((l), (t)); \
|
|
*tp = t; \
|
|
}
|
|
#define NODE_UNLOCK(l, tp) \
|
|
{ \
|
|
STRONG_RWLOCK_CHECK(*tp != isc_rwlocktype_none); \
|
|
RWUNLOCK(l, *tp); \
|
|
*tp = isc_rwlocktype_none; \
|
|
}
|
|
#define NODE_RDLOCK(l, tp) NODE_LOCK(l, isc_rwlocktype_read, tp);
|
|
#define NODE_WRLOCK(l, tp) NODE_LOCK(l, isc_rwlocktype_write, tp);
|
|
#define NODE_TRYLOCK(l, t, tp) \
|
|
({ \
|
|
STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
|
|
isc_result_t _result = isc_rwlock_trylock(l, t); \
|
|
if (_result == ISC_R_SUCCESS) { \
|
|
*tp = t; \
|
|
}; \
|
|
_result; \
|
|
})
|
|
#define NODE_TRYRDLOCK(l, tp) NODE_TRYLOCK(l, isc_rwlocktype_read, tp)
|
|
#define NODE_TRYWRLOCK(l, tp) NODE_TRYLOCK(l, isc_rwlocktype_write, tp)
|
|
#define NODE_TRYUPGRADE(l, tp) \
|
|
({ \
|
|
STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_read); \
|
|
isc_result_t _result = isc_rwlock_tryupgrade(l); \
|
|
if (_result == ISC_R_SUCCESS) { \
|
|
*tp = isc_rwlocktype_write; \
|
|
}; \
|
|
_result; \
|
|
})
|
|
#define NODE_FORCEUPGRADE(l, tp) \
|
|
if (NODE_TRYUPGRADE(l, tp) != ISC_R_SUCCESS) { \
|
|
NODE_UNLOCK(l, tp); \
|
|
NODE_WRLOCK(l, tp); \
|
|
}
|
|
|
|
#define TREE_INITLOCK(l) isc_rwlock_init(l)
|
|
#define TREE_DESTROYLOCK(l) isc_rwlock_destroy(l)
|
|
#define TREE_LOCK(l, t, tp) \
|
|
{ \
|
|
STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
|
|
RWLOCK(l, t); \
|
|
*tp = t; \
|
|
}
|
|
#define TREE_UNLOCK(l, tp) \
|
|
{ \
|
|
STRONG_RWLOCK_CHECK(*tp != isc_rwlocktype_none); \
|
|
RWUNLOCK(l, *tp); \
|
|
*tp = isc_rwlocktype_none; \
|
|
}
|
|
#define TREE_RDLOCK(l, tp) TREE_LOCK(l, isc_rwlocktype_read, tp);
|
|
#define TREE_WRLOCK(l, tp) TREE_LOCK(l, isc_rwlocktype_write, tp);
|
|
#define TREE_TRYLOCK(l, t, tp) \
|
|
({ \
|
|
STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_none); \
|
|
isc_result_t _result = isc_rwlock_trylock(l, t); \
|
|
if (_result == ISC_R_SUCCESS) { \
|
|
*tp = t; \
|
|
}; \
|
|
_result; \
|
|
})
|
|
#define TREE_TRYRDLOCK(l, tp) TREE_TRYLOCK(l, isc_rwlocktype_read, tp)
|
|
#define TREE_TRYWRLOCK(l, tp) TREE_TRYLOCK(l, isc_rwlocktype_write, tp)
|
|
#define TREE_TRYUPGRADE(l, tp) \
|
|
({ \
|
|
STRONG_RWLOCK_CHECK(*tp == isc_rwlocktype_read); \
|
|
isc_result_t _result = isc_rwlock_tryupgrade(l); \
|
|
if (_result == ISC_R_SUCCESS) { \
|
|
*tp = isc_rwlocktype_write; \
|
|
}; \
|
|
_result; \
|
|
})
|
|
#define TREE_FORCEUPGRADE(l, tp) \
|
|
if (TREE_TRYUPGRADE(l, tp) != ISC_R_SUCCESS) { \
|
|
TREE_UNLOCK(l, tp); \
|
|
TREE_WRLOCK(l, tp); \
|
|
}
|
|
|
|
#define IS_STUB(db) (((db)->common.attributes & DNS_DBATTR_STUB) != 0)
|
|
#define IS_CACHE(db) (((db)->common.attributes & DNS_DBATTR_CACHE) != 0)
|
|
|
|
ISC_LANG_BEGINDECLS
|
|
|
|
struct dns_glue {
|
|
struct dns_glue *next;
|
|
dns_fixedname_t fixedname;
|
|
dns_rdataset_t rdataset_a;
|
|
dns_rdataset_t sigrdataset_a;
|
|
dns_rdataset_t rdataset_aaaa;
|
|
dns_rdataset_t sigrdataset_aaaa;
|
|
};
|
|
|
|
typedef struct {
|
|
dns_glue_t *glue_list;
|
|
dns_db_t *db;
|
|
dns_dbversion_t *version;
|
|
dns_name_t *nodename;
|
|
} dns_glue_additionaldata_ctx_t;
|
|
|
|
typedef struct {
|
|
isc_rwlock_t lock;
|
|
/* Protected in the refcount routines. */
|
|
isc_refcount_t references;
|
|
/* Locked by lock. */
|
|
bool exiting;
|
|
} db_nodelock_t;
|
|
|
|
static inline bool
|
|
prio_type(dns_typepair_t type) {
|
|
switch (type) {
|
|
case dns_rdatatype_soa:
|
|
case DNS_SIGTYPE(dns_rdatatype_soa):
|
|
case dns_rdatatype_a:
|
|
case DNS_SIGTYPE(dns_rdatatype_a):
|
|
case dns_rdatatype_mx:
|
|
case DNS_SIGTYPE(dns_rdatatype_mx):
|
|
case dns_rdatatype_aaaa:
|
|
case DNS_SIGTYPE(dns_rdatatype_aaaa):
|
|
case dns_rdatatype_nsec:
|
|
case DNS_SIGTYPE(dns_rdatatype_nsec):
|
|
case dns_rdatatype_nsec3:
|
|
case DNS_SIGTYPE(dns_rdatatype_nsec3):
|
|
case dns_rdatatype_ns:
|
|
case DNS_SIGTYPE(dns_rdatatype_ns):
|
|
case dns_rdatatype_ds:
|
|
case DNS_SIGTYPE(dns_rdatatype_ds):
|
|
case dns_rdatatype_cname:
|
|
case DNS_SIGTYPE(dns_rdatatype_cname):
|
|
case dns_rdatatype_dname:
|
|
case DNS_SIGTYPE(dns_rdatatype_dname):
|
|
case dns_rdatatype_svcb:
|
|
case DNS_SIGTYPE(dns_rdatatype_svcb):
|
|
case dns_rdatatype_https:
|
|
case DNS_SIGTYPE(dns_rdatatype_https):
|
|
case dns_rdatatype_dnskey:
|
|
case DNS_SIGTYPE(dns_rdatatype_dnskey):
|
|
case dns_rdatatype_srv:
|
|
case DNS_SIGTYPE(dns_rdatatype_srv):
|
|
case dns_rdatatype_txt:
|
|
case DNS_SIGTYPE(dns_rdatatype_txt):
|
|
case dns_rdatatype_ptr:
|
|
case DNS_SIGTYPE(dns_rdatatype_ptr):
|
|
case dns_rdatatype_naptr:
|
|
case DNS_SIGTYPE(dns_rdatatype_naptr):
|
|
return (true);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
ISC_LANG_ENDDECLS
|