Commit graph

46050 commits

Author SHA1 Message Date
Evan Hunt
89e57b45e0 fix: usr: Check that an NSEC signer is at or above the name to be validated
Add a check that an NSEC record being used as a proof of nonexistence
for a given name is not signed by a name lower in the DNS hierarchy than
the one in question.

Closes #5876

Merge branch '5876-nsec-signer-above-name' into 'main'

See merge request isc-projects/bind9!12272
2026-06-24 21:04:20 +00:00
Alessio Podda
4fb662a171 Reproducer for #5876 child apex self-loop NSEC
Added to "nsec_synthesis" system test.

Co-Authored-By: Evan Hunt <each@isc.org>
2026-06-24 21:03:45 +00:00
Evan Hunt
c5f99f3508 Check that an NSEC signer is at or above the name to be validated
Add a check that an NSEC record being used as a proof of nonexistence
for a given name is not signed by a name lower in the DNS hierarchy than
the one in question.

Fixes: isc-projects/bind9#5876
2026-06-24 21:03:45 +00:00
Colin Vidal
6a41fa3e9c fix: test: Fix RRL test random failure
RRL test were randomly failing because `ns2` hint files uses

```
.	NS	ns1.
ns1.	A	10.53.0.1
```

Whereas `ns1` root zone didn't contains `ns1.` as NS (but only `ns.`).
This is a problem with the following scenario:

- A query starts before priming;
- It gets the root hints as zonecut (with `. NS ns1.`, and no glues, this
  is how parent-centric currently works);
- Priming starts and complete (so now rootdb contains the answer/glues
  from `ns1` root file);
- Then the query go to ADB to resolve `ns1.`.

Resolution of `ns1.` fails since it doesn't exists from the rootdb
anymore. This is a configuration issue (the resolver behavior is correct
and expected) whch is now fixed.

Closes #6032

Merge branch '6032-fix-rrl' into 'main'

See merge request isc-projects/bind9!12322
2026-06-24 22:31:27 +02:00
Colin Vidal
49cb99bb08 Fix RRL random failure
RRL test were randomly failing because `ns2` hint files uses

```
.	NS	ns1.
ns1.	A	10.53.0.1
```

Whereas `ns1` root zone didn't contains `ns1.` as NS (but only `ns.`).
This is a problem with the following scenario:

- A query starts before priming;
- It gets the root hints as zonecut (with `. NS ns1.`, and no glues, this
  is how parent-centric currently works);
- Priming starts and complete (so now rootdb contains the answer/glues
  from `ns1` root file);
- Then the query go to ADB to resolve `ns1.`.

Resolution of `ns1.` fails since it doesn't exists from the rootdb
anymore. This is a configuration issue (the resolver behavior is correct
and expected) whch is now fixed.
2026-06-24 21:56:16 +02:00
Michal Nowak
c20bab513b new: ci: Add Alpine Linux 3.24
Merge branch 'mnowak/alpine-3.24' into 'main'

See merge request isc-projects/bind9!12229
2026-06-24 17:45:14 +02:00
Michal Nowak
62670aa1b7 Fix a false positive compiler warning/error on Alpine 3.24
On Alpine Linux 3.24, GCC 15 with fortify-headers produces a compiler
warning when building bin/nsupdate/nsupdate.c:

    In function 'fgets',
        inlined from 'get_next_command' at ../bin/nsupdate/nsupdate.c:2414:13:
    /usr/include/fortify/stdio.h:48:16: error: 'cmdlinebuf' may be used uninitialized [-Werror=maybe-uninitialized]
       48 |         return __orig_fgets(__s, __n, __f);
          |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/include/fortify/stdio.h:42:1: note: in a call to '*fgets' declared with attribute 'access (read_write, 1, 2)' here
       42 | _FORTIFY_FN(fgets) char *fgets(char * _FORTIFY_POS0 __s, int __n, FILE *__f)
          | ^~~~~~~~~~~
    ../bin/nsupdate/nsupdate.c:2405:14: note: 'cmdlinebuf' declared here
     2405 |         char cmdlinebuf[MAXCMD];
          |              ^~~~~~~~~~

This is a false positive, because fgets() only writes into the buffer;
the fortify-headers wrapper annotates the buffer argument with
'access (read_write, ...)', which makes GCC treat passing an
uninitialized buffer as a read of uninitialized memory.

Initialize the 'cmdlinebuf' buffer anyway to avoid the build error.

Assisted-by: Claude:claude-fable-5
2026-06-24 17:44:42 +02:00
Michal Nowak
774a9661fc Add Alpine Linux 3.24 2026-06-24 17:44:42 +02:00
Michal Nowak
28cddaaba6 fix: test: Retry pipequeries on a transient EADDRINUSE in the pipelined test
On FreeBSD, the TCP connect() call can transiently fail with
EADDRINUSE under parallel CI load.  The netmgr already retries such
connects (see #3451), but it retries on the same socket, which is
already bound to the same ephemeral source port, so when the
four-tuple is genuinely busy (e.g. in TIME_WAIT) every retry fails
the same way.  pipequeries then exits with "request event result:
address in use", leaving raw.1 empty and failing the first check.

All eight requests share a single TCP dispatch, so the failed connect
means no query ever reached ns4 and its cache is still cold.  It is
therefore safe to run pipequeries again: a fresh process binds a new
ephemeral port, and the out-of-order check keeps its meaning.  Retry
for up to ten attempts, but only on this specific transient error.

Assisted-by: Claude Code:claude-fable-5

Merge branch 'mnowak/pipelined-retry-transient-eaddrinuse' into 'main'

See merge request isc-projects/bind9!12228
2026-06-24 17:16:14 +02:00
Michal Nowak
b9cf877277 Retry pipequeries on a transient EADDRINUSE in the pipelined test
On FreeBSD, the TCP connect() call can transiently fail with
EADDRINUSE under parallel CI load.  The netmgr already retries such
connects (see #3451), but it retries on the same socket, which is
already bound to the same ephemeral source port, so when the
four-tuple is genuinely busy (e.g. in TIME_WAIT) every retry fails
the same way.  pipequeries then exits with "request event result:
address in use", leaving raw.1 empty and failing the first check.

All eight requests share a single TCP dispatch, so the failed connect
means no query ever reached ns4 and its cache is still cold.  It is
therefore safe to run pipequeries again: a fresh process binds a new
ephemeral port, and the out-of-order check keeps its meaning.  Retry
for up to ten attempts, but only on this specific transient error.

Assisted-by: Claude:claude-fable-5
Assisted-by: Claude:claude-opus-4-8
2026-06-24 17:15:42 +02:00
Michal Nowak
74a3c561aa new: dev: Print OS platform in "named -V"
The "running on" line emitted by `named -V` (as well as the startup
log and `rndc status`, which share the same source) now appends the
PRETTY_NAME value from /etc/os-release in parentheses after the uname
output, e.g.:

    running on Linux x86_64 6.19.14-... (Fedora Linux 42 (Workstation Edition))

This helps disambiguate environments where the kernel string is not a
reliable indicator of the userspace, such as RHEL clones and
containers whose kernel does not match the host OS.

When /etc/os-release is absent, /usr/lib/os-release is tried as a
fallback per the systemd os-release(5) specification. When neither is
available or no PRETTY_NAME is found, the output is unchanged.

Assisted-by: Claude:claude-opus-4-7

Closes #5334

Merge branch '5334-add-os-platform-to-named-V' into 'main'

See merge request isc-projects/bind9!12055
2026-06-24 17:06:30 +02:00
Michal Nowak
b5ca9d3372 Print OS platform in "named -V"
The "running on" line emitted by `named -V` (as well as the startup
log and `rndc status`, which share the same source) now appends the
PRETTY_NAME value from /etc/os-release in parentheses after the uname
output, e.g.:

    running on Linux x86_64 6.19.14-... (Fedora Linux 42 (Workstation Edition))

This helps disambiguate environments where the kernel string is not a
reliable indicator of the userspace, such as RHEL clones and
containers whose kernel does not match the host OS.

When /etc/os-release is absent, /usr/lib/os-release is tried as a
fallback per the systemd os-release(5) specification. When neither is
available or no PRETTY_NAME is found, the output is unchanged.

Assisted-by: Claude:claude-opus-4-7
2026-06-24 17:05:35 +02:00
Ondřej Surý
ff3721d501 new: test: Add extra expired RRSIGs test to dnssec_py
Related #5760

Merge branch 'nicki/pytest-add-extra-expired-rrsigs-test' into 'main'

See merge request isc-projects/bind9!11808
2026-06-24 16:32:15 +02:00
Nicki Křížek
fe2fea73a4 Add extra expired RRSIGs test to dnssec_py
The test verifies that a validating resolver enforces the
max-validations-per-fetch limit when encountering a record with multiple
expired RRSIGs followed by a valid one. One of the records is signed
three times: twice with expired timestamps (to produce two expired
RRSIGs for a.rrsigs-extra-expired/A) and once with valid timestamps,
after which the expired RRSIGs are injected back into the signed zone
file. max-validations-per-fetch is set to 2 via the template variable so
that the third (valid) RRSIG is never reached, causing SERVFAIL.

Assisted-by: Claude:claude-opus-4-8
2026-06-24 15:09:38 +02:00
Michal Nowak
c2723d9162 fix: test: Report all unregistered unit test files at once
Collect every unregistered unit test file before exiting instead of
failing on the first one, so a single configure run lists them all.

Assisted-by: Claude:claude-opus-4-8

Merge branch 'mnowak/report-all-unregistered-unit-tests' into 'main'

See merge request isc-projects/bind9!12220
2026-06-24 13:57:42 +02:00
Michal Nowak
f4ccbe8159 Report all unregistered unit test files at once
Collect every unregistered unit test file before exiting instead of
failing on the first one, so a single configure run lists them all.

Assisted-by: Claude:claude-opus-4-8
2026-06-24 13:57:07 +02:00
Ondřej Surý
1541662c65 fix: usr: Stop reusing outgoing TCP connections the peer has already closed
``named`` could hand a new query an idle forwarder/upstream TCP or TLS
connection that the peer had already closed, causing the query to fail
(and CLOSE-WAIT sockets to pile up). Idle reused connections are now
watched, so a close is noticed and the connection is dropped instead of
reused. A new ``tcp-reuse-timeout`` option controls how long an idle
outgoing connection is kept open for reuse (default 5 seconds).

Closes #6171

Merge branch '6171-tcp-reuse-idle-read' into 'main'

See merge request isc-projects/bind9!12289
2026-06-24 13:52:58 +02:00
Ondřej Surý
477130cf8e Add the tcp-reuse-timeout option
The idle timeout that bounds how long a reused outgoing TCP/TLS
connection is held open for reuse was only tunable through the 'named -T
tcpidletimeout' developer hook added earlier on this branch. Make it a
proper configuration option, tcp-reuse-timeout (options block, in units
of 100 milliseconds like the other tcp-*-timeout options), and drop the
-T hook.
2026-06-24 13:52:46 +02:00
Ondřej Surý
febeac215d Keep idle reused outgoing TCP connections under read
A reused TCP/TLS dispatch with no outstanding responses was left in the
reuse pool with no read pending, so a peer closing the idle connection
went unnoticed: the socket lingered in CLOSE-WAIT and the dead dispatch
was later handed to a new query, which failed and the fetch timed out.
Keep a read pending on an idle connected dispatch, bounded by an idle
timeout, so the close is seen promptly and the connection is dropped
from the pool instead of reused.

The idle read may only be (re)armed while the dispatch is still
connected; arming it on a dispatch that is already shutting down
re-reads a dying handle and double-schedules a netmgr job.

On shutdown, close the connection as soon as the dispatch reaches its
terminal state instead of waiting for the last reference to drop, so an
unexpected read (or a peer-side close) cannot leave the socket in
CLOSE-WAIT while a reference still lingers.
2026-06-24 13:52:46 +02:00
Michał Kępień
a65ece3648 rem: ci: Drop Danger check related to pre-release testing
With the advent of the new development model involving security-*
branches and autorebasing, the value added by the pre-release testing
mechanism dropped drastically.  The only remaining benefit of
pre-release testing is flagging in-progress security fixes targeting
open source branches that conflict with the corresponding bind-9.x-sub
branches.  However, such conflicts are a rare occurrence and can be
handled after merging anyway.

Remove the Danger check related to pre-release testing.

Merge branch 'michal/drop-danger-check-related-to-pre-release-testing' into 'main'

See merge request isc-projects/bind9!12313
2026-06-24 13:33:57 +02:00
Michał Kępień
4c2046b59f
Drop Danger check related to pre-release testing
With the advent of the new development model involving security-*
branches and autorebasing, the value added by the pre-release testing
mechanism dropped drastically.  The only remaining benefit of
pre-release testing is flagging in-progress security fixes targeting
open source branches that conflict with the corresponding bind-9.x-sub
branches.  However, such conflicts are a rare occurrence and can be
handled after merging anyway.

Remove the Danger check related to pre-release testing.
2026-06-24 13:25:27 +02:00
Andoni Duarte
11b3b35054 fix: ci: Use resource-group for RPM-related CI jobs
RPM build jobs work by pushing a commits to main in a repository. Each
repository is identified by the `SERVICE variable and, since race
conditions may happen, the jobs are run serially via GitLab's
resource_group mechanism.

Merge branch 'andoni/use-resource-group-for-rpms-copr-ci-job' into 'main'

See merge request isc-projects/bind9!12295
2026-06-24 10:33:10 +00:00
Andoni Duarte Pintado
44431b1689 Use resource groups for RPM build CI jobs
RPM build jobs push commits to Git repositories.  If multiple such jobs
are triggered simultaneously, some of these pushes may fail due to the
same Git branch getting updated by one job while another one attempts to
do the same thing in parallel.  Use GitLab's resource group mechanism to
prevent such races: group jobs by the Git repository they push to, which
is indicated by the $SERVICE variable set for each job.
2026-06-24 10:30:28 +00:00
Ondřej Surý
19c202d470 fix: usr: Truncated reply to a TSIG query no longer stalls the resolver
When an upstream server returned a truncated reply to a query that BIND had
signed with TSIG, the resolver could keep waiting for a follow-up UDP packet
that never arrived, so the query stalled until it hit resolver-query-timeout
and the client received no answer. BIND now treats any reply it cannot
authenticate as an immediate failure and returns SERVFAIL right away as a
defense in depth.

Closes #6028

Merge branch '6028-tsig-truncated-tsig-response' into 'main'

See merge request isc-projects/bind9!12080
2026-06-24 12:18:30 +02:00
Ondřej Surý
2327277f90 Fail the fetch when a response fails the TSIG signature check
A response that failed the signature check with a missing or unexpected
TSIG used to set nextitem, so the resolver kept reading the dispatch for
another response.  When the response was truncated with the TSIG cut off
the end of the wire, no further response ever arrived and the fetch
stalled until resolver-query-timeout.

Treat an unauthenticated response like every other signature-check
failure and finish the fetch immediately.  A response carrying a missing
or bogus TSIG now yields SERVFAIL instead of being skipped in favour of
a later one; the cookie system test that fed a spoofed TSIG response is
updated to expect that.  The unauthenticated data is still never
returned.
2026-06-24 12:18:19 +02:00
Michal Nowak
7d20711c65 fix: dev: Avoid writing through a const pointer in render_xsl()
render_xsl() served the static XSL stylesheet by casting away the const
qualifier of xslmsg and handing the pointer to isc_buffer_reinit():

    p = UNCONST(xslmsg);
    isc_buffer_reinit(b, p, strlen(xslmsg));

isc_buffer_reinit() copies any pre-existing buffer content into the new
base with memmove(), so the call would write into xslmsg, which is a
'const char[]' living in read-only memory.  This is safe today only
because the supplied bodybuffer is always freshly initialized with
length 0, so the memmove() never runs -- a fragile, action-at-a-distance
invariant that GCC's -fanalyzer flags as a write to a const object
(-Wanalyzer-write-to-const).

Use isc_buffer_constinit(), the primitive intended for pointing a buffer
at constant data: it goes through isc_buffer_init() and never writes to
the base.  This drops the UNCONST cast, keeps xslmsg in read-only
memory, and silences the analyzer warning.

Assisted-by: Claude:claude-opus-4-8

Merge branch 'mnowak/render-xsl-const-buffer' into 'main'

See merge request isc-projects/bind9!12168
2026-06-24 11:30:59 +02:00
Michal Nowak
a8368cdf17 Avoid writing through a const pointer in render_xsl()
render_xsl() cast away the const of the static xslmsg stylesheet and
passed it to isc_buffer_reinit(), which memmove()s into the base when
the buffer is non-empty -- a write to read-only memory that -fanalyzer
flags (-Wanalyzer-write-to-const).  It only stayed safe because the
body buffer is always empty here.

Use isc_buffer_constinit(), which never writes to the base, and assert
the empty-buffer contract with REQUIRE(isc_buffer_length(b) == 0).

Assisted-by: Claude:claude-opus-4-8
2026-06-24 10:56:34 +02:00
Michał Kępień
79e58c7c23 chg: ci: Miscellaneous autorebasing tweaks
- Remove the "autorebase-merge-request" CI job
  - Fix formatting of autorebase failure notifications
  - Send Zulip notifications for autorebase failures

Merge branch 'michal/autorebase-ci-tweaks' into 'main'

See merge request isc-projects/bind9!12288
2026-06-24 10:07:41 +02:00
Michał Kępień
dca92d738a
Send Zulip notifications for autorebase failures
Use the GitLab-to-Zulip username map available in the BIND 9 QA
repository to determine the Zulip username of the developer who happened
to author a breaking base branch change, so that a Zulip notification
can be triggered for that developer.
2026-06-24 10:04:06 +02:00
Michał Kępień
5d6390b804
Fix formatting of autorebase failure notifications
Using a plain "echo" command does not turn "\n" into newline
characters, breaking the formatting of the Zulip notifications sent upon
autorebase failures.  Fix by using "echo -e" instead, which enables
interpreting backslash sequences in the provided input.
2026-06-24 10:04:06 +02:00
Michał Kępień
261208b987
Remove the "autorebase-merge-request" CI job
The "autorebase-merge-request" CI job is not useful in practice as the
Danger check whose complaints it was supposed to address does not look
for commit hashes in the original merge request's target branch, but
rather in the original merge request itself - and those commit hashes
remain stable over time.  Furthermore, after a backport gets merged, any
cherry-pick references its commits might contain will be maintained by
other autorebasing jobs.  Given the above, remove the
"autorebase-merge-request" CI job as it serves no useful purpose.
2026-06-24 10:04:06 +02:00
Ondřej Surý
ac6696cdb5 fix: dev: Don't serve a stale CNAME or record when fresh data of the other exists
When a cached name held both a CNAME and records of another type — one stale,
the other still fresh — named with serve-stale could return the expired set
instead of the fresh one, in either direction. It now prefers whichever is fresh.

Merge branch 'ondrej/fix-serve_stale-cname-and-type' into 'main'

See merge request isc-projects/bind9!12282
2026-06-24 06:53:34 +02:00
Ondřej Surý
b7144fb9cf
Don't stop qpcache_find on a stale header while fresh data remains
With serve-stale enabled, stale rdataset headers are kept at a node so
they can be served as a last resort. The find loop, however, accepted a
stale CNAME or stale record of the requested type as a final answer and
broke out of the iteration early, returning stale data even when a fresh
header for the same name appeared later in the scan. Treat STALE(found)
like a missing answer so the loop keeps looking and only falls back to
the stale header when no fresh answer is found.
2026-06-24 06:53:00 +02:00
Arаm Sаrgsyаn
fb47b6bf3e fix: usr: Fix a bug in DNS UPDATE processing with inline-signing enabled
In rare cases the :iscman:`named` process could terminate unexpectedly
when processing authorized DNS UPDATE messages in quick procession
which are updating a zone with inline-signing enabled. This has been
fixed.

Closes #5816

Merge branch '5816-inline-signing-concurrent-update-fix' into 'main'

See merge request isc-projects/bind9!11982
2026-06-22 20:56:07 +00:00
Aram Sargsyan
5e12906669 Fix memory leak bug during zone shutdown
The dns_update_signaturesinc() updates zone signatures in chunks,
keeping its current state in 'zone->rss_state'. When a zone shuts
down, the signature update process is canceled, and all the data
in the state is not freed.

Create a new dns_update_state_clear() function which can be called
from dns_zone_free() to free the memory.
2026-06-22 20:51:53 +00:00
Aram Sargsyan
b56e3cd2ee Handle zone shutting down case in receive_secure_serial()
When the zone is shutting down jump straight to cleanup, otherwise
an assertion failure is possible, e.g. because zone->loop can be
already NULL.
2026-06-22 20:51:53 +00:00
Aram Sargsyan
fad2c5b757 Remove the unused link from 'struct rss'
The link is declared but never used. Remove it.
2026-06-22 20:51:53 +00:00
Aram Sargsyan
5118f3bad6 Fix a bug in "receive secure serial" processing
When a DNS UPDATE messages is received, the zone_send_secureserial()
function can schedule a new receive_secure_serial() call with a new
'rss' object before a previous one had a chance to be fully processed.
This can cause an assertion failure in receive_secure_serial() with a
new 'rss' object (when the old one was rescheduled because it got
DNS_R_CONTINUE from dns_update_signaturesinc()). In other words:

1. receive_secure_serial() called with rss, sets zone->rss = rss,
   reschedules because of DNS_R_CONTINUE
2. receive_secure_serial() called with rss_new, INSIST fails because
   zone->rss != rss_new), i.e. this was called before the old 'rss'
   was fully processed

Change the code logic by introducing a new 'rss_next' field and making
sure the old 'rss' is complete before starting processing the new
one.
2026-06-22 20:51:53 +00:00
Aram Sargsyan
7d7130f51a Remove redundant INSIST
The check is already performed in the INSIST above.
2026-06-22 20:51:53 +00:00
Aram Sargsyan
37f265f59a Add a new check in "inline" system test
This new check floods the server with DNS UPDATE messages for an
'inline-signing yes; sig-signing-signatures 1;' zone to see if
it manages to process the updates correctly.
2026-06-22 20:51:53 +00:00
Matthijs Mekking
868bb66a9a chg: dev: Fix double initialization in copy_tuple()
Small cleanup. Found with ninja -C build-dir/ scan-build.

Patch submitted by Tim Rühsen.

Closes #6163

Merge branch '6163-double-initialization-copy-tuple' into 'main'

See merge request isc-projects/bind9!12292
2026-06-22 14:53:07 +00:00
Matthijs Mekking
e7b5be8f84 Fix double initialization in copy_tuple()
Small cleanup. Found with ninja -C build-dir/ scan-build.

Patch submitted by Tim Rühsen.
2026-06-22 14:18:59 +00:00
Ondřej Surý
42c741baa6 chg: dev: Reference count and flatten the cache slabheader storage
Internal refactoring of the cache database (qpcache) with no functional
change. The slab headers that hold cached rdatasets are now reference
counted and own their memory context and node reference directly, so a
header can outlive the cleaning of its node and be reclaimed
independently of it. Building on that, the per-type slabtop container is
folded into the slab header itself, removing a level of indirection and
one allocation per cached type.

Merge branch 'ondrej/slabheader-reference-counting' into 'main'

See merge request isc-projects/bind9!12285
2026-06-22 15:05:10 +02:00
Ondřej Surý
057042304d
Keep in-flight cache headers safe from LRU eviction during add
When the cache is over its size limit, qpcache_miss() runs LRU eviction
while add() is still in progress.  Eviction removes a header together
with its RRSIG/covered 'related' partner, so it could free a header the
add still needs -- the new header, the partner it was just paired with,
or the one about to be displaced for max-types-per-name.  With 'related'
now a counted reference, that became a use-after-free reachable under
sustained load.

Run the eviction last, after the new header is linked, bound and any
over-limit header removed, and skip the new header and its partner in
the eviction loop (the partner is marked visited so the SIEVE hand still
advances).  Per-header removal is factored into header_delete(),
expire_header() and flush_node().
2026-06-22 13:45:23 +02:00
Ondřej Surý
06abfa3264
Remove the ANCIENT slabheader attribute and statistics counter
Cache headers are now unlinked from their node as soon as they expire,
so a slabheader is never left in the "ancient, awaiting cleanup" state
that DNS_SLABHEADERATTR_ANCIENT tracked.  Drop the attribute, rename
mark_ancient() to header_delete() to reflect that it now removes the
header rather than flagging it (keying idempotency on list membership),
and remove the ancient RRset statistics counter that recorded the state,
which is now always zero; the rdataset statistics array shrinks to
match.

The rdataset-level 'ancient' flag and 'rndc dumpdb -expired' are
unaffected: expiry is derived from the entry's TTL when the rdataset is
bound, not from the slabheader attribute.
2026-06-22 13:45:18 +02:00
Ondřej Surý
5b50f4133a
Factor the header/RRSIG extraction out of the find paths
qpcache_find, qpcache_findrdataset, and find_headers each repeated the
same logic to pick a header and its RRSIG out of a slabheader and its
'related' link.  Pull it into store_headers(), and rename check_header()
to invalid_header() since it returns true when the header should be
skipped.
2026-06-22 13:45:15 +02:00
Ondřej Surý
5bd08f8942
Squash dns_slabtop into dns_slabheader
With headers removed eagerly in mark_ancient there is at most one header
per type at a node, so the separate per-type dns_slabtop container no
longer earns its keep.  Fold its fields onto the header -- the link into
the node's list, the RRSIG/covered related pairing, and the SIEVE-LRU
state -- and link headers directly into the node, dropping a level of
indirection and an allocation per cached type.
2026-06-22 13:45:13 +02:00
Ondřej Surý
76e21399dd
Remove cache headers and empty slabtops eagerly in mark_ancient
Now that a bound rdataset keeps references to both the slabheader and
the node, an ancient header (and the slabtop it leaves empty) can be
removed from the cache immediately in mark_ancient, instead of being
parked on a per-node dirty list and reclaimed only once the node becomes
unreferenced.  This drops the dirty list and the clean_cache_* machinery
entirely.

Because the cache structure can now change under a node that still has
external references, the all-rdatasets iterator no longer walks the live
slabtop list: allrdatasets() binds every matching rdataset up front and
the iterator works from that snapshot, cloning out each entry.
2026-06-22 13:45:08 +02:00
Ondřej Surý
202889b044
Free the slabheader proofs in its destructor
Now that the slabheader carries its own memory context, free its
noqname/closest proofs from slabheader_destroy rather than reaching
through the owning node's deletedata method.  That was the method's last
caller, so remove dns_db_deletedata entirely; the cache bookkeeping it
performed (rrset statistics and the dirty list) becomes a plain helper
called wherever a header leaves the cache.
2026-06-22 13:45:05 +02:00
Ondřej Surý
d9701e1fae
Store the bound node and slabheader reference on the rdataset
The bound rdataset now keeps its own node reference instead of reaching
it through the slabheader, and each slabheader carries its own memory
context so it can free itself once its reference count reaches zero.
The noqname/closest proof rdatasets are views into a slabheader's proof
slabs, so they now hold a reference to that slabheader too, keeping the
proof slab (and the cloned owner name): alive for as long as the proof
rdataset is.  Keeping the node on the rdataset means node access stays
valid for the life of the rdataset, independent of the slabheader's own
node pointer.
2026-06-22 13:44:58 +02:00