Previously, BIND 9 would drop the ZEROTTL attribute when updating
previously cached NS entry with ZEROTTL attribute set.
Co-authored-by: Jinmei Tatuya <jtatuya@infoblox.com>
Use C23 stdckdint.h when available and define ckd_{mul,add,sub} shims to
__builtin_{mul,add,sub}_overflow(). Require the __builtin functions
unconditionally.
Currently following __builtin functions are used:
__builtin_add_overflow
__builtin_mul_overflow
__builtin_prefetch
__builtin_sub_overflow
__builtin_unreachable
These are generally available on our supported platform, and also we use
some of these unconditionally anyway in qp.c. Thus make the support for
these functions mandatory so we fail early in the 'setup' step.
The fxhash implementation was missing a constant for 32-bit platforms.
This has been fixed. Constant for 64-bit platform was update to match
the current Rust constants.
The previous refactoring added an assertion failure when negative RRSIG
would be added to the cache database. As result, any query for RRSIG in
any unsigned zone would trigger that assertion failure.
Allow the negative RRSIG entries to be stored in the cache database
again as not caching these would trigger new remote fetch every time
such query would be received from a client.
The following check:
__builtin_types_compatible_p(size_t, uint64_t)
doesn't work with default compiler on macOS. Workaround the issue
by typing the size_t to matching unsigned int type.
Using `static inline` functions in the headers break gcov as it cannot
properly track the hits. To fix the issue, convert the expressions to
statement macros. The added static assertions will ensure integer
promotion cannot occur unlike its previous function counterpart.
By default, when named is started it may start answering to
queries before the response policy zones are completely loaded
and processed. This new feature gives an option to the users to
tell named that incoming requests should result in SERVFAIL anwser
until all the response policy zones are procesed and ready.
During the initial configuration of named after startup, 'first_time'
is true. This is needed for implementing the new 'servfail-until-ready'
configuration option, which should take into effect only during the
initial configuration.
If so we also want to tickle the apex because DNSKEY/CDNSKEY/CDS
RRsets may need to be re-signed.
Note that this may be overzealous, because if state transitions
happen just because of timing events (RUMOURED -> OMNIPRESENT,
UNRETENTIVE -> HIDDEN) this would have to cause changes in the
zone DNSSEC records.
When a key retire, key generation/introduction, or a state transition
to RUMOURED/UNRETENTIVE should happen, instead they are logged.
When those logs look good, you can run 'rndc dnssec -step' to run the
keymgr and apply those steps.
Add a new option 'manual-mode' to 'dnssec-policy'. The intended
use is that if it is enabled, it will not automatically move to the
next state transition (RUMOURED, UNRETENTIVE), only after manual
confirmation. The intended state transition should be logged.
Currently, when releasing a qpznode after a read operation, we will
check if the node is dirty due to a previous write, upgrade the lock to
a write lock and perform a cleanup.
An unintended side effect of this is that protecting a node by
increasing the reference count must also protect its parent database.
For the very common case where only one zone is configured, this is a
non-trivial source of contention, as the same refcount will be hit by
all threads.
This commit removes the opportunistic cleaning and the database
refcount, reducing contention. Cleaning will be done only on
closeversion.
Per @each, skipping cleanup of (|nsec_|nsec3_)origin nodes in
qpznode_release in qpzone.c is a residual from RBTDB, but it is
unnecessary or at most a performance optimization with QP.
Remove it to make it further changes easier to qpznode_release easier.
The `<isc/bit.h>` header is a GNU C11 compatible version of C23's
`<stdbit.h>`.
It currently uses either `<stdbit.h>` or the equivilent compiler
builtins. However, the generic `__builtin_ctzg` and `__builtin_ctlz`
builtins are not available in every compiler version and thus falls
back to manually selecting from type.
Furthermore, the ctz fallback has been removed since `__builtin_ctzll`
has been used for a while directly without any compilation issues from
users. Thus, we can also require `__builtin_ctz`.
Unlike the rest of C23's bit utilities, we avoid the stdc_rotate_*
functions since we don't need the rotation modulus precision. This adds
a couple (admittedly cheap) unwanted instructions on some architectures.
> Put a space before opening parentheses only after control statement
> keywords (for/if/while...) except this option doesn’t apply to ForEach
> and If macros. This is useful in projects where ForEach/If macros are
> treated as function calls instead of control statements.
> Insert braces after control statements (if, else, for, do, and while)
> in C++ unless the control statements are inside macro definitions or
> the braces would enclose preprocessor directives.
When first dns_db_addrdataset() succeeds in cache_rrset(), but the
second one fails with error, the added rdataset was kept associated.
This caused assertion failure down the pipe in fctx_sendevents().
The compile-time DNS__TYPEPAIR_CHECK macro (wrapping an INSIST) is a
no-op if DNS_TYPEPAIR_CHECK is off, making at least one unused variable
in DNS_TYPEPAIR_TYPE and DNS_TYPEPAIR_COVERS scopes (as in such case,
only one member of the pair is effectively needed).
In such case, having an unused variable (the other member of the pair)
is expected, this silence the warning by adding a (void) cast on the
no-op version of DNS__TYPEPAIR_CHECK.
the if statements calling iterator_active() checked the EXISTS
flag on the header and then iterator_active() checked it again.
simplify so only the caller checks it.
As the qpcache has only one active header at the time, we can move the
SIEVE-LRU members from dns_slabheader_t to dns_slabtop_t structure thus
saving a little bit of memory in each slabheader and using it only once
per type.
The code that combines the top-level hierarchy (per-typepair) and
individual slab headers (per-version) saves a little bit of memory, but
makes the code convoluted, hard to read and hard to modify. Change the
top level hierarchy to be of different type with individual slabheaders
"hanging" from the per-typepair dns_slabtop_t structure.
This change makes the future enhancements (changing the top level data
structure for faster lookups; coupling type + sig(type) into single
slabtop) much easier.
The slabheader doesn't directly attach or link to 'db' anymore. Pass
only the memory context needed to create the slab header to make the
lack of relation ship more prominent.
Also don't call dns_slabheader_reset() from dns_slabheader_new(), it has
no added value.
Previously, when the new header was NOT added into the cache, we would
increment and then decrement stat counters immediately.
Delay incrementing the stat counters until after the newheader has
been actually added into the database.
A little cleanup to accomodate the fact that qpdb->rrsetstats is always
available was also done here.
Change the add() function in the dns_qpcache to properly return
DNS_R_UNCHANGED if the newheader was not actually consumed, and move
the dns_slabheader_destroy() call outside of the add() function.
Under normal circumstances, the case bitfield in the slabheader should
be set only once. By actually (soft-)enforcing this, the read locking
can be completely removed from the rdataslab_getownercase() as we can
check whether the case has been already set or not and making everything
immutable once the case has been set.
The slabheader.c, qpzone.c and qpcache.c had couple of shared macros
that were copied and paste between the units. Move these common
attributes access macros into private header, so these can be shared
among the three compilation units.
In the dns_qpcache unit, we use EXISTS() macro, but in the dns_qpzone
there's a NONEXISTENT() macro for the same slabheader attribute. Unify
the macro to be also EXISTS() in dns_qpzone.
Previously, when a negative header was stored in the cache, it would be
stored in the dns_typepair_t as .type = 0, .covers = <negative type>.
When searching the cache internally, we would have to look for both
positive and negative typepair and the slabheader .down list could be a
mix of positive and negative types.
Remove the extra representation of the negative type and simply use the
negative attribute on the slabheader. Other units (namely dns_ncache)
can still insert the (0, type) negative rdatasets into the cache, but
internally, those will be converted into (type, 0) slabheaders, and vice
versa - when binding the rdatasets, the negative (type, 0) slabheader
will be converted to (0, type) rdataset. Simple DNS_TYPEPAIR() helper
macro was added to simplify converting single rdatatype to typepair
value.
As a side-effect, the search logic in all places can exit early if
there's a negative header for the type we are looking for, f.e. when
searching for the zone cut, we don't have to walk through all the
slabheaders, if there's a stored negative slabheader.
Use dns_rdatatype_none instead of plain '0' for dns_rdatatype_t and
dns_typepair_t manipulation. While plain '0' is technically ok, it
doesn't carry the required semantic meaning, and using the named
dns_rdatatype_none constant makes the code more readable.
When in developer's mode, make the DNS_TYPEPAIR_* macros be more
strict on the contents of the 'base' and 'covers', so we can catch
invalid use of the API.
The RR type 0 is a reserved type for SIG[1] resource record. It should
not be ever inserted into the database nor queried. Add a special
handling to bail out quickly with DNS_R_DISALLOWED when inserting and
ISC_R_NOTFOUND when looking up TYPE0. This is also prerequisite for
stricter checks in the follow-up commit.
1. https://www.rfc-editor.org/rfc/rfc2535#section-4.1.8.1
The dns_typepair_t and dns_rdatatype_t variables were both named 'type'
in multiple places. Rename all dns_typepair_t variables to include word
'pair' in the variable name to make sure that the distinction between
the two types is more clear.
Instead of catching the DNS_R_UNCHANGED from dns_db_addrdataset() (via
cache_rrset() and dns_ncache_add()) individually, mask it properly as
soon as possible, by moving the sigrdataset caching logic inside
cache_rrset() and returning ISC_R_SUCCESS from cache_rrset() and
dns_ncache_add() when the database was unchanged.
The logic to delete records from the cache was relying on the contents
of the validation answer. Change the logic to always delete the
contents of the cache on the broken chain result.
during a recent refactoring of validated(), a line was
removed, causing 'result' to be left unchanged. this
wasted time continuing to try to validate when a
non-recoverable error had occured, and caused the wrong
reason to be logged in add_bad().
Initialization of the common members of rdata type structures varies
across branches. Standardize it by using the DNS_RDATACOMMON_INIT
macro for all types, so that new types are more likely to use it,
and hence backport more cleanly.
All databases in the codebase follow the same structure: a database is
an associative container from DNS names to nodes, and each node is an
associative container from RR types to RR data.
Each database implementation (qpzone, qpcache, sdlz, builtin, dyndb) has
its own corresponding node type (qpznode, qpcnode, etc). However, some
code needs to work with nodes generically regardless of their specific
type - for example, to acquire locks, manage references, or
register/unregister slabs from the heap.
Currently, these generic node operations are implemented as methods in
the database vtable, which creates problematic coupling between database
and node lifetimes. If a node outlives its parent database, the node
destructor will destroy all RR data, and each RR data destructor will
try to unregister from heaps by calling a virtual function from the
database vtable. Since the database was already freed, this causes a
crash.
This commit breaks the coupling by standardizing the layout of all
database nodes, adding a dedicated vtable for node operations, and
moving node-specific methods from the database vtable to the node
vtable.
Right now dns_sdlzlookup has a slight difference from other dbnode
implementations in that it stores a pointer to a dns name instead of
the dns name itself.
This commit harmonizes dns_sdlzlookup with other dbnode
implementations, facilitating further refactoring.
- there was special-case code in validated() to handle the results
of a validator started by a CD=1 query. since that never happens,
the code has been removed.
- the section of code that handles opportunistic caching of
validated SOA, NS and NSEC data has been split out to a separate
function.
- the number of goto statements has been reduced considerably.