Commit graph

16152 commits

Author SHA1 Message Date
Ondřej Surý
3e05958a42
Refactor find headers to make use of related
Change the code of finding headers to make use of the related circular
reference.

Co-authored-by: Matthijs Mekking <matthijs@isc.org>
2025-09-24 00:07:08 +02:00
Ondřej Surý
0f13d7f2fa
Expire related headers at the same time
Previously, the slabtops for "type" and its signature was only loosely
coupled and the headers could expire at different time (both TTL and LRU
based expiry).  This commit expires the headers in both related
headers.

Co-authored-by: Matthijs Mekking <matthijs@isc.org>
2025-09-24 00:07:07 +02:00
Ondřej Surý
0b317abe4e
Add a circular reference between slabtops for type and RRSIG(type)
Previously, the slabtops for "type" and its signature was only loosely
coupled.  Add a .related member to the slabtop that allows us to
optimize the lookups because now both slabtops are looked up at the
same time.

Co-authored-by: Matthijs Mekking <matthijs@isc.org>
2025-09-24 00:07:07 +02:00
Ondřej Surý
270f78194e
Refactor find headers
Another recurring code pattern that can be moved into a separate
function.

Co-authored-by: Matthijs Mekking <matthijs@isc.org>
2025-09-24 00:07:07 +02:00
Ondřej Surý
6b0e6cb058
Refactor check header
There was a pattern where first the header was checked for NULL
and then for being stale. In both cases the code path is the same
so it makes sense to put them in a separate function.

Co-authored-by: Matthijs Mekking <matthijs@isc.org>
2025-09-24 00:07:07 +02:00
Ondřej Surý
133d76c05e
Move the size of the expired data into expireheader
Co-authored-by: Matthijs Mekking <matthijs@isc.org>
2025-09-24 00:07:07 +02:00
Ondřej Surý
28fff0045d
Convert slabheader to use the cds_list
This is the second commit in series that aims to reduce the node locking
by replacing the single-linked list of slabheader(s) with CDS linked list.
This commit doesn't do anything else beyond replacing .next link with
the cds_list_head.  RCU semantics is going to be added in the subsequent
commits.
2025-09-23 23:18:44 +02:00
Ondřej Surý
63389b8ce6
Convert slabtop to use the cds_list
This is the first commit in series that aims to reduce the node locking
by replacing the single-linked list of slabtop(s) with CDS linked list.
This commit doesn't do anything else beyond replacing .next link with
the cds_list_head.  RCU semantics is going to be added in the subsequent
commits.
2025-09-23 11:21:47 +02:00
Ondřej Surý
09762bdc44
Fix datarace between unlocking fctx lock and shuttingdown fctx
There was a data race where new fetch response could be added to the
fetch context after we unlock the fetch context and before we shut it
down.  This could cause assertion failure when fctx__done() was called
with ISC_R_SUCCESS because there was originally no fetch response, but
new fetch response without associated dataset was added before we had a
chance to shutdown the fetch context.  This manifested in the
validated() callback, where cache_rrset() now returns ISC_R_SUCCESS
instead of DNS_R_UNCHANGED when cache was not changed.  However the data
race was wrong on a general level.

When the fctx__done() is called with ISC_R_SUCCESS as result is expects
the fctx->lock to be already acquired to prevent these data races.
2025-09-23 10:29:27 +02:00
Ondřej Surý
1aa9cd3484
Split the fctx_done() into success and failure variants
The split will allow us to call fctx__done() with fctx->lock acquired
when it is called with ISC_R_SUCESS to prevent data races when finishing
the fetch context.
2025-09-19 10:53:29 +02:00
Ondřej Surý
cdc6950d04
Add more unit tests for dns_qp unit
Add basic unit tests and add missing DbC checks for mandatory
dns_qp_create() arguments.
2025-09-17 15:58:44 +02:00
Ondřej Surý
9e2d5d94bd
Remove dns_dbtree_t and its usage
As we removed the ability to count nodes in the auxiliary trees (because
there are no auxiliary trees), we can also cleanup the API and
associated enum type (dns_dbtree_t).
2025-09-17 15:58:44 +02:00
Ondřej Surý
a3e96f2d49
Squash the qpcache tree and nsec trees
The dns_qpcache already had all the namespace changes needed to put the
normal data and auxiliary NSEC data into a single tree.  Remove the
extra nsec QP trie and use the single QP trie for all the cache data.
2025-09-17 15:58:44 +02:00
Ondřej Surý
ec0a5f3a9d
Remove the dbiterator_{last,prev} from the qpcache
The dbiterator_{last,prev} functions are not used in the cache, and the
implementation would get quite complicated when we squash the main and
nsec trees together.  It's easier to just not implement these.
2025-09-17 15:58:44 +02:00
Ondřej Surý
70c8054b84
Remove CacheNSECNodes statistics counter
There is no auxiliary NSEC tree, so we can't count the NSEC nodes
separately.  Remove the CacheNSECNodes statistics counter as it would be
always zero.
2025-09-17 15:58:44 +02:00
Ondřej Surý
136fddf538
Use result of first_*_header() calls instead of direct value
Fix places where we got the header by calling first_*_header() function,
but then worked with top->header instead of the result.
2025-09-16 18:47:53 +02:00
Ondřej Surý
fa12ba28ce
Fix up the descriptions in rdataslab.h
There were a lot of outdated comments. They've been updated or removed.
2025-09-16 18:47:53 +02:00
Ondřej Surý
b2f653b332
Fix dns_qpmulti_memusage() on empty dns_qpmulti_t instance
The dns_qpmulti_memusage() causes assertion failure when called on
freshly created qpmulti instance because the qp->usage hasn't been
allocated yet.
2025-09-16 16:30:15 +02:00
Colin Vidal
2cbe958df6 simplify nchildren count in isc_nm_listenudp
Slight simplification of the logic to define .nchildren listening UDP
socket.
2025-09-16 14:22:15 +02:00
Colin Vidal
c16e944b3c remove orphan dns_loadmgr_t type
dns_loadmgr_t typedef is declared but never defines as well as a pointer
of this type in named_server_t. Removing it.
2025-09-15 22:03:11 +02:00
Evan Hunt
4122143c4d remove dns_db_{un,}locknode
remove the dns_db_locknode() and _unlocknode() calls, so that callers no
longer have the ability to directly manipulate the internal locking of
cache and zone databases.
2025-09-15 16:11:50 +00:00
Evan Hunt
17101fa491 make getoriginnode implementation optional
if the dns_db_getoriginnode() call is not implemented, we can
fall back to running dns_db_findnode() on the database origin.
we now only implement getoriginnode directly in databases where
it's clearly faster than the fallback implementation would be.
2025-09-15 16:11:50 +00:00
Evan Hunt
7a5344d591 minor cleanup in sdlz.c
dns_db_issecure() and dns_db_nodecount() return false and 0,
respectively, if they are not implemented, so there's no need to
have implementation functions that only return false and 0.
2025-09-15 16:11:50 +00:00
Evan Hunt
b2009e1ebc remove unnecessary dns_db_nodefullname()
now that node->name is accessible as a common dbnode member,
it's no longer necessary to provide an API call for that.
2025-09-15 16:11:50 +00:00
Evan Hunt
18db48eb2c remove node lock for settrust and clearprefetch
dns_rdataset_clearprefetch() performs an atomic operation,
so it didn't actually need to lock the database node.

dns_rdataset_settrust() updates header->trust; this is also
now atomic, so it doesn't need to lock the node now either.
2025-09-15 16:11:50 +00:00
Evan Hunt
4de396f955 merge dns_db_find/findext and dns_db_findnode/findnodeext
the dns_db_findext and _findnodeext calls are extended versions
of dns_db_find and _findnode, which take additional arguments for
client information in order to support ECS. previously, database
implementations could support either API call, with cross-compatibility
so that, for example, dns_db_findext() could call a find implementation
if findext was not implemented, and dns_db_find() could call findext
if find was not implemented.

this has now been simplified. the find and findnodeext implementations
now support client info.  all database implementations will now provide
these calls.  implementations which do not support ECS will simply
ignore the clientinfo and clientinfomethods parameters.

this only affects the underlying implementation; callers will still
use the same interface. dns_db_find() and dns_db_findnode() are now
macros which pass NULL to the clientinfo parameters, so that callers
don't have to do so explicitly. dns_db_findext() and dns_db_findnodeext()
are still available for callers that do wish to pass clientinfo pointers.
2025-09-15 16:11:50 +00:00
Evan Hunt
9e14fcd259 remove obsolete dns_db_hashsize()
this function's purpose was to populate the "CacheBuckets" statistic,
but there are no databases left that implemented it, so the return
value was always 0. "CacheBuckets" has now been removed from the
statistics, and the dns_db_hashsize() API call has been removed.
2025-09-15 16:11:50 +00:00
Evan Hunt
0222c385aa dns_rdatalist functions are not for general use
the rdataset method implementation functions in dns/rdatalist.c (i.e.,
dns_rdatalist_first, _next, etc) are not meant to be called directly;
they're called via dns_rdataset_first(), dns_rdataset_next(), etc.

in dnssec-ksr.c, a list-based rdataset was iterated using these
functions. this has been fixed, and the functions have been renamed
to use the `dns__` prefix as a signal that they aren't meant to be
used outside the rdataset implementation.
2025-09-15 16:11:50 +00:00
Evan Hunt
7e7d8bece7 remove obsolete dns_db_setloop()
no database implementation has needed an event loop
since the RBT cache was removed, so the setloop API call
is no longer needed.
2025-09-15 16:11:50 +00:00
Ondřej Surý
1e9430ffad
Fix detection whether node is active in find_wildcard()
The current code would fail during the write transaction.  The first
header would not match the search->serial and the node might be
incorrectly detected as inactive.
2025-09-15 17:44:57 +02:00
Ondřej Surý
a8c3661e2b
Make the database ownercase modifiable only via addrdataset()
Simplify the implementation around the database ownercase.  Remove the
dns_rdataset_setownercase() implementation for the slabheaders and only
allow setting ownercase on rdatalists and rdatasets.  The ownercase in
the database can now be set only with dns_db_addrdataset() by passing
rdataset with correctly set ownercase.
2025-09-13 06:56:58 +02:00
Colin Vidal
d42d8891ac do not inline dns_zone_gethooktable
Since !10959 `dns_zone_gethooktable()` is only called once per query,
and the suspicion (from perflab analysis) that this (simple, as just
returning a pointer) call was slowing things down (perhaps because of
code locality reasons?) doesn't matter anymore. So even if !10959
inlined it, it shouldn't matter anymore.
2025-09-11 14:21:10 +02:00
Evan Hunt
0cdcc8a8f4 rename NS_QUERY_RESET to NS_QUERY_CLEANUP
query_reset() is called during query initialization, but the only
time the NS_QUERY_SETUP hook runs is when it's called from
query_cleanup().  it makes more sense to move the hook point to
there and rename it to NS_QUERY_CLEANUP.

this change caused a crash in the unit tests due to the view being
unnecessarily detached before ns__client_reset_cb() was called.
this has also been fixed.
2025-09-10 17:46:53 -07:00
Colin Vidal
b6a292b03f don't call hooks when a query hasn't started
guard the call to the NS_QUERY_RESET hook so it's called only if
the view has been set. If the view is NULL, it means the client has
been reset _before_ the query even started, and no other hook could
have been called, so it doesn't make sense to call this one.

this also enables us to avoid a NULL-check on the qctx->view in the
CALL_HOOK macros.
2025-09-10 14:14:36 -07:00
Evan Hunt
637e8d01d2 minimize calls to dns_zone_gethooktable per qctx
add a 'zhooks' member to the query_ctx structure, so that we only
need to look up the hook table for the zone once when iniitalizing
a qctx, and not once for every hook point.
2025-09-10 14:05:42 -07:00
Evan Hunt
0194a265fe check target pointer validity in qctx_save
Make sure the target pointer address (getting the allocated instance of
qctx) is valid and the pointer is NULL.
2025-09-10 12:43:05 +02:00
Ondřej Surý
4dc711ef86
Reduce the code duplication around getting slabheaders from slabtop
There was a lot of duplicated code around getting the first header that
exists, is active, and matches the version header from the qpzonedb.
Move the duplicate code into a helper function and unify the same
approach for the qpcache too even though the code is much simpler there.
It should come handy when top->header is something more complicated than
a pointer to first slabheader.
2025-09-10 10:18:48 +02:00
Mark Andrews
7d765a3514 Remove dns_rdataset_equals as unneeded 2025-09-10 14:20:22 +10:00
Mark Andrews
b954a1df43 Fix missing RRSIGs for "glue" lookups with CD=1
The code to test whether to store the RRSIGs on DNS_R_UNCHANGED
with CD=1 was failing because the comparison methods of the two
rdatatset instances were not compatible.  Move the testing into
dns_db_addrdataset(), and request it by setting the DNS_ADD_EQUALOK
option.  If the option is set and the old and new rrsets compare
as equal, dns_db_addrdataset() returns ISC_R_SUCCESS instead of
DNS_R_UNCHANGED.
2025-09-10 14:20:22 +10:00
Mark Andrews
e968d0fb8e The last argument to cache_rrset is wrong
The last argument to cache_rrset should be a bool (false)
not a pointer (NULL).
2025-09-10 10:51:21 +10:00
Colin Vidal
d676ce8085 remove query_ctx_t detach_client property
Since the removal of NS_QUERY_QCTX_DESTROYED hook, there is no need for
the `qctx->detach_client` object anymore, as this was designed to tell
the plugin whether the client object is about to be, or is already,
freed from memory.  This is not needed anymore, as NS_QUERY_RESET is
called _always_ when the client object is about to be freed from memory.

Remove `detach_client` and tidy up the code a bit by including the
freeing of the qctx object (when allocated) inside the qctx_destroy
function instead of requiring extra calls.
2025-09-09 10:02:32 +02:00
Colin Vidal
95c71c2739 replace QCTX_INIT/_DESTROY hooks with QUERY_SETUP/_RESET
The hook NS_QUERY_QCTX_DESTROY is problematic with zone plugins because
it can be called in some contexts where `qctx->client` is invalid (the
pointer is dangling); which would lead to a use-after-free (spotted by
TSAN build) as `qctx->client` is used to get the zone hooktable, to find
out whether there is an authoritive zone which would have
NS_QUERY_QCTX_DESTROY registered.

This can't easily be fixed, because there is no easy way to know from
query.c code if `client` is still a valid object: `client->reqhandle`,
representing the request from a client, is refcounted, and the `client`
object is freed from memory once its refcounter gets to 0. While
`reqhandle` is attached from query.c code, it can be attached more than
once from asynchronous code and there is no clear path where detaching
it would lead to a client free. Hence, there is no way to know for sure
when to set `qctx->client = NULL` (this is why the pointer remains
dangling).

Back to the original problem; this is why the NS_QUERY_QCTX_DESTROY hook
is incompatible with zone plugins. `qctx->detach_client`, which is used
to tell a plugin that the `client` object is either free or about to be
free can't be use either, because in some cases the client is still
there, and should be used.

Code issue aside, the `qctx` object is really just an aggregate of
various data to pass easily in the various functions and callbacks,
initially stored on the stack, but allocated in some cases (for some
asynchronous flow, when recursion is needed), so the point it gets
created/"destroyed" is really just an implementation "detail", and
providing a higher level hook for the plugin would be beneficial. Hence,
NS_QUERY_RESET and NS_QUERY_INIT are removed, and instead, the existing
NS_QUERY_SETUP can be used as well as the newly introduced
NS_QUERY_RESET (which replaces NS_QUERY_QCTX_DESTROY). The advanage is
that NS_QUERY_RESET is called _only_ when the client object is _always_
about to be freed, which avoids usage of the extra `qctx->detach_client`
usage from the plugin.

The way NS_QUERY_RESET works is that when the `client` is freed, a
callback (from `query.c`) is called. This callback creates a transient
qctx object on the stack with a pointer to the view, and uses that
to call the hook.
2025-09-09 09:42:34 +02:00
Colin Vidal
260bbc24c9 add plugin_register param telling the source
The plugin `plugin_register` API has a new parameter `source` indicating
whether the plugin is loaded from a view or a zone.

This extra parameter enables the plugin to fail early during
initialization if a plugin written to be used in a zone exclusively
is loaded at a view level, or vice versa.
2025-09-09 09:42:34 +02:00
Colin Vidal
1566634fae add NS_QUERY_AUTHZONE_ATTACHED hook
Add a new query hook called `NS_QUERY_AUTHZONE_ATTACHED`. This hook is
called whenever an authoritative zone is found and attached during a
query answer.

From code level, this hook is called when `qctx->client->query->authzone`
is attached during a query.  This enables zone-specific plugins to
initialize specific states whenever a local zone is found that can
answer a query.
2025-09-09 09:42:34 +02:00
Colin Vidal
91cd7b865c update hook developer documentation
Attempt to add zone plugin specificities into the hook developer
documentation. In particular about the hook call order and hookpoint
which can't be called on a zone plugin.
2025-09-09 09:42:34 +02:00
Colin Vidal
5893770cd9 add zone-specific plugin instance
The zone object now has its own hooktable and plugins, which are
initialized during zone initialization.
2025-09-09 09:42:34 +02:00
Colin Vidal
7ea70b4e19 add namedconf support for plugin inside a zone
The named.conf parser now accepts the plugin clause inside a zone
definition.  This enables us to add (in later commits) support for
zone plugins.
2025-09-09 09:42:34 +02:00
Ondřej Surý
2963d1aaf1
Refactor the cyclic ordering to use query ID as offset
Mimic the Unbound behaviour where the cyclic offset is taken from query
ID, and remove recording of the current state.  As the incoming query ID
should have random distribution, the cyclic ordering should also have
uniform distribution of the starting record.
2025-09-08 14:04:13 +02:00
Ondřej Surý
b3f5c3b0fc
Refactor the cyclic ordering to be more efficient
With random ordering removed, the cyclic ordering can be rewritten in a
that it uses thread_local static array to keep the cyclic order.

This could be further improved by keeping the current position inside
the slabheader and adding a function to start directly there instead at
dns_rdataset_first().
2025-09-08 14:04:13 +02:00
Ondřej Surý
7dc6048f93
Remove the random ordering of resource records in RRset
The rrset-order random doesn't offer uniform distribution of all
permutations and it isn't superior to cyclic order in any way.  Make the
random ordering an alias to the cyclic ordering.
2025-09-08 14:04:13 +02:00