Matthijs Mekking [Tue, 25 Nov 2025 07:56:32 +0000 (08:56 +0100)]
Test sending NOTIFY(CDS) messages
When starting up the services, send notifies for the existing CDS RRset.
This requires setting up a chain of trust for the test, so the DSYNC
records can be retrieved and validated.
This feature requires enabling 'notify-cds' and 'dnssec-validation'.
In this test, the scanner is pointed to ns2. Since there is no code
for receiving NOTIFY(CDS) messages for delegations, this is treated
as "not authoritative". Checking for this log message ensures us that
the NOTIFY(CDS) message was actually sent.
Matthijs Mekking [Thu, 30 Oct 2025 08:48:35 +0000 (09:48 +0100)]
Implement NOTIFY(CDS) logic
When the CDS/CDNSKEY RRset gets updated, schedule a NOTIFY(CDS) to be
sent to the parental agent. The parental agent is published in the
parent zone as a DSYNC RRset, so first we need to figure out the
parent owner name. This is done by finding the zonecut (querying for
NS RRset until we find a postive answer).
In nsfetch_dsync, we then schedule a zone fetch for the DSYNC record
at <child-labels>._dsync.<parent-labels>. Then we queue the notify
for each target in the DSYNC records that matches the NOTIFY scheme
and CDS RRtype.
Now that we log the type of the notify, some expected log messages
in the system tests need to be adjusted accordingly.
The bin/tests/system/nsec3/tests_nsec3_retransfer.py log is changed
to zone_needdump because it is more reliable. Other tests were
adjusted similar in MR !11265, but !11226 introduced a new
"sending notify" log line.
Matthijs Mekking [Tue, 18 Nov 2025 08:56:34 +0000 (09:56 +0100)]
Add type parameter to dns_notify_create()
With Generalized DNS Notifications, a zone may need to send different
type of NOTIFY messages for different reasons. When creating a new
notify, allow for specifying the type.
Matthijs Mekking [Tue, 28 Oct 2025 14:25:29 +0000 (15:25 +0100)]
Add port parameter to dns_notify_create()
The DSYNC record has a Port rdata field, so NOTIFY(CDS) messages may be
configured at different ports. When creating a new notify, allow for
specifying the port.
Matthijs Mekking [Tue, 28 Oct 2025 07:30:05 +0000 (08:30 +0100)]
Maintain separate notify contexts for SOA and CDS
With Generalized DNS Notifications, a zone may need to send different
NOTIFY messages for different reasons. Introduce a method to
initialize a notify context and maintain a notify contexts per RRtype.
Matthijs Mekking [Fri, 28 Nov 2025 12:42:28 +0000 (13:42 +0100)]
rollover-zsk-prepub: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/kasp.conf.j2 to
ecdsa256 and rename to ns3/kasp.conf.
Matthijs Mekking [Fri, 28 Nov 2025 10:38:06 +0000 (11:38 +0100)]
rollover-ksk-doubleksk: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/kasp.conf.j2 to
ecdsa256 and rename to ns3/kasp.conf.
Matthijs Mekking [Fri, 28 Nov 2025 09:43:42 +0000 (10:43 +0100)]
rollover-going-insecure: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/kasp.conf.j2 to
ecdsa256 and rename to ns3/kasp.conf.
Now we have to fake different lifetimes, so adjust fake_lifetime
to update a single key.
Note that we have changed the setup slightly: We also sign the
step2 zones, but with post validation disabled. This is more
accurate because we need to test that the public keys and signatures
are being removed from the zone.
Matthijs Mekking [Fri, 28 Nov 2025 08:59:51 +0000 (09:59 +0100)]
rollover-enable-dnssec: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM_NUMBER@ in ns3/kasp.conf.j2 to
13 and rename to ns3/kasp.conf.
This test introduces an unsigned delegation, adjust render_and_sign_zone
and configure_tld accordingly.
Matthijs Mekking [Thu, 27 Nov 2025 13:01:28 +0000 (14:01 +0100)]
rollover-csk-roll1: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/kasp.conf.j2 to
ecdsa256 and rename to ns3/kasp.conf.
Write a python method to set the key predecessor/successor relationship
into the key state files.
Matthijs Mekking [Thu, 27 Nov 2025 11:11:35 +0000 (12:11 +0100)]
rollover-algo-ksk-zsk: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
The RSASHA256 keys are generated with dnssec-keygen, without a policy
provided. Thus we have to fake the lifetime for these keys.
Signing has to be done without the -z option, because the KSK should
not sign all records in case of a KSK/ZSK split. Update the signing
code to allow for extra options when signing with CSK only.
Matthijs Mekking [Thu, 27 Nov 2025 09:37:22 +0000 (10:37 +0100)]
rollover-algo-csk: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.
Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/csk2.conf.j2 to
ecdsa256 and rename to ns3/csk2.conf.
Matthijs Mekking [Tue, 25 Nov 2025 10:17:40 +0000 (11:17 +0100)]
rollover: From setup.sh to pytest bootstrap
Introduce rollover/setup.py for all setup related test code.
Introduce rollover/ns1 and rollover/ns2 to create a chain of trust to
all rollover related test zones. The tld zones in rollover/ns2 contain
a DSYNC record that at a later time will be used for testing Generalized
DNS Notifications.
Write a python version of private_type_record so we can put such
records in the zone via jinja2 templating.
Matthijs Mekking [Tue, 25 Nov 2025 09:54:57 +0000 (10:54 +0100)]
Move ns6 to ns3 in rollover tests
There is no difference, so we are going to make it consistent. This will
make it easier to add a chain of trust for these zones (to be done in
a future commit).
Štěpán Balážik [Wed, 12 Nov 2025 15:19:25 +0000 (16:19 +0100)]
Allow ResponseHandlers to roll back changes made to a response
Previously, this was only possible by making a new response by calling
make_response on qctx.query. This however ignored the `default_aa` and
`default_rcode` parameters of AsyncDnsServer.
Add prepare_new_response and save_initialized_response methods to
QueryContext.
Štěpán Balážik [Wed, 12 Nov 2025 15:02:48 +0000 (16:02 +0100)]
Add TSIG keyring support to AsyncDnsServer
Previously, ResponseHandlers had to reparse the queries themselves if
they wanted to use TSIG. This led to `default_aa` and `default_rcode`
information being lost from the newly created messages.
Add support for TSIG keyrings to the AsyncDnsServer class directly.
Štěpán Balážik [Wed, 29 Oct 2025 17:59:31 +0000 (18:59 +0100)]
Allow users of AsyncDnsServer to set AA bit for all responses
Previously, all responses had to be set as authoritative explicitly
using DnsResponseSend(..., authoritative=True). After using this,
it became obvious that this is obnoxious.
Add an optional keyword-only parameter to AsyncDnsServer that sets the
default value of the AA bit on outgoing responses.
Make all the other parameters keyword-only as well.
Štěpán Balážik [Thu, 30 Oct 2025 12:41:23 +0000 (13:41 +0100)]
Refactor ControllableAsyncDnsServer setup
When this class was introduced, the constructor of its base class had no
parameters. This was changed in the meantime and these parameters were
not accessible by users of the subclass.
Don't override the constructor.
Move command setup to methods.
Move subclass-specific storage to cached properties.
Take instances of Command instead of the classes themselves for
symmetry with install_response_handler.
Arаm Sаrgsyаn [Wed, 17 Dec 2025 14:55:43 +0000 (14:55 +0000)]
fix: usr: Fix a possible catalog zone issue during reconfiguration
The :iscman:`named` process could terminate unexpectedly during
reconfiguration when a catalog zone update was taking place at
the same time. This has been fixed.
Merge branch 'aram/catz-reconfig-crash-fix' into 'main'
Aram Sargsyan [Fri, 5 Dec 2025 10:06:28 +0000 (10:06 +0000)]
Lock the catalog zone when reconfiguring it
A catalog zone is updated in an offloaded thread, which is not
stopped during a reconfiguration in an exclusive mode, and so
can cause a race condition with it.
Waiting for the offloaded threads to complete their work before
entering into the exclusive mode can potentially cause unwanted
delays, because offloaded threads are generally "allowed" to take
a longer amount of time before they complete.
Add a dns_catz_zone_prereconfig()/dns_catz_zone_postreconfig() pair
of functions which currently just lock the catalog zone when
reconfiguring it. The change should eliminate the race.
As a side note, there was already a similar pair of functions,
dns_catz_prereconfig() and dns_catz_postreconfig() which are called
before and after reconfiguring a 'dns_catz_zones_t' object.
Below are the stack traces of the reconfiguration thread which has
asserted, and a catalog zone update thread which was caught in the
middle of its work despite the fact that the exclusive mode is
turned on.
Ondřej Surý [Wed, 17 Dec 2025 07:38:34 +0000 (08:38 +0100)]
Cleanup the extra dns_rdataset_disassociate() code
Manually go through the code using dns_rdataset_isassociated() and
use dns_rdataset_cleanup() where appropriate in places that a simple
semantic patch is not able to find automatically.
Add a tag pipeline CI job to update the stable tag after a release
Introduce a CI job to update the "stable" tag with the latest released
stable version tag. This is a manual job that only runs in tag
pipelines in the context of a release.
Colin Vidal [Wed, 17 Dec 2025 09:18:53 +0000 (10:18 +0100)]
new: usr: Add support for Extended DNS Error 9 (Missing DNSKEY)
Extended DNS Error 9 (Missing DNSKEY) is now sent when a validating resolver attempts to validate a response but can't get the DNSKEY from the authoritative server of the zone, while the DS record is present in the parent zone.
Colin Vidal [Tue, 16 Dec 2025 18:33:50 +0000 (19:33 +0100)]
update SERVFAIL cache test
An existing SERVFAIL cache test is updated as it initially checks there
are no EDE (the first SERVFAIL) then immediately re-does the same query,
(still SERVFAIL), and expect the CACHED_ERROR EDE.
However, the configuration used for this test to generate a SERVFAIL is
a broken DNSSEC configuration, where the DNSKEY is not the expected one
(it's a ZSK instead of a KZK). As a result, the first attempt also now
raise an EDE (MISSING_DNSKEY).
Colin Vidal [Wed, 3 Dec 2025 13:22:43 +0000 (14:22 +0100)]
add system tests covering EDE 9
The authoritative server on "missing-dnskey." zone is ns2, the zone is
initially signed normally, but then the DNSKEY are pulled out from the
signed generated zone file. As a consequence, a quering the resolver ns4
returns a SERVFAIL with EDE9 as the chain of trust is broken: the DS is
prsent in the parent zone (the root zone in ns1), but the DNSKEY is
missing from the zone.
A similar is "wrong-dnskey.", but here the zone is signed correctly,
but the DS points to a different DNSKEY. Hence no supported matching
DNSKEY record could be found for the child.
Colin Vidal [Wed, 3 Dec 2025 13:20:20 +0000 (14:20 +0100)]
add support for EDE 9
Extended DNS Error 9 (Missing DNSKEY) is now sent when a validating resolver
attempts to validate a response but can't get the DNSKEY from the authoritative
server of the zone, while the DS record is present in the parent zone.
Note the EDE 9 is send as part of the proveunsecure flow, after the
validator successfully fetched the DS of the zone from the parent. So if
the DS is also missing, the EDE 9 won't be sent.
Michal Nowak [Tue, 16 Dec 2025 20:25:37 +0000 (21:25 +0100)]
chg: test: Temporarily change pytest.PytestRemovedIn9Warning error to warning
We need this to be able to use pytest 9.0 from Debian "sid".
Additionally, this error needs to be addressed before pytest 9.1 is
released, as the filter will no longer work. Also, all pytests in CI
images need to be upgraded to version 7, where the new API is supported.
Related #5690
Merge branch 'mnowak/ignore-pytest-PytestRemovedIn9Warning' into 'main'
Michal Nowak [Tue, 16 Dec 2025 18:03:38 +0000 (19:03 +0100)]
Temporarily change pytest.PytestRemovedIn9Warning error to warning
We need this to be able to use pytest 9.0 from Debian "sid".
Additionally, this error needs to be addressed before pytest 9.1 is
released, as the filter will no longer work. Also, all pytests in CI
images need to be upgraded to version 7, where the new API is supported.
We can't have the "filterwarnings" section in pytest.ini directly as
only pytest 8.0 knows about it.
Ondřej Surý [Tue, 16 Dec 2025 10:11:05 +0000 (11:11 +0100)]
Copy only the raw data when we are copying dns_slab{header,vec}
The makeslab function in rdataslab.c contains an optimization for cases
where the source is already an rdataslab. In these cases, it copies the
entire slab using memmove. However, this creates a race condition: while
the target slab is protected by a node lock, the source slab is not
protected. This becomes problematic because the TTL heap needs to
modify the heap index stored in the slab header, potentially while the
memmove operation is reading from it.
A closer look at makeslab shows that copying the header part of the slab
is unnecessary, the header can be default-initialized instead. This MR
modifies makeslab to copy only the raw part of the slab, while
default-initializing the header, eliminating the race condition. For
consistency, it also applies the same change to vecheader/makevec.
Alessio Podda [Tue, 16 Dec 2025 17:06:12 +0000 (17:06 +0000)]
fix: dev: Unpack struct vecheader
The bitset packing of the resign_lsb and heap_index in struct vecheader was causing a race condition, since both bindrdataset and heap operations tried to access the same byte (even though they are accessing different fields).
While heap operations are protected by the node lock of the header being inserted, they aren't protected by the node locks of the headers being displaced, leading to the race condition.
This MR fixes the issue by reverting the struct packing optimization.
Closes #5688
Merge branch '5688-no-heap-index-bitset' into 'main'
Alessio Podda [Tue, 16 Dec 2025 14:39:45 +0000 (15:39 +0100)]
Unpack struct vecheader
The bitset packing of the resign_lsb and heap_index in struct vecheader
was causing a race condition, since both bindrdataset and heap
operations tried to access the same byte (even though they are accessing
different fields).
While heap operations are protected by the node lock of the header being
inserted, they aren't protected by the node locks of the headers being
displaced, leading to the race condition.
This commit fixes the issue by reverting the struct packing
optimization.
Arаm Sаrgsyаn [Wed, 10 Dec 2025 17:30:50 +0000 (17:30 +0000)]
fix: usr: Fix the charts in the statistics channel
The charts in the statistics channel could sometimes fail
to render in the browser, and were completely disabled for
Mozilla-based browsers for historical reasons. This has
been fixed.
Merge branch 'aram/stats-channel-charts-fix' into 'main'
The statistics channel's HTML presentation has charts, but it has
a couple of problems.
1. Because of an inconsistent condition, a chart's JS code might have
been executed, while the HTML markup wasn't present, and this is
causing a JS error.
2. The feature is turned off on Mozilla-based browsers.
Fix the inconsistency in conditions, remove the conditional rendering
which disabled the feature for Mozilla-based browsers by looking at
the XSLT processor's name, and fix indentation inconsistencies.
This is a new seek function for dbiterator that is meant to find an
NSEC3 node in a zone database. The difference with dns_dbiterator_seek
is that if the node does not exist, this seek function will point the
iterator to the next NSEC3 name.
This test signs a large delegation with mostly insecure delegations
with NSEC3 optout. Once the NSEC3PARAM record is published, run
dnssec-verify to ensure the zone is correctly signed.
Alessio Podda [Tue, 9 Dec 2025 20:05:27 +0000 (21:05 +0100)]
Add DNS_VECHEADER_FOREACH
Add a FOREACH macro modelled around the DNS_RDATASET_FOREACH one, that
uses vecheader directly. Useful when you want to manipulate a vecheader
without binding it to avoid having to take the node lock inside qpzone.c.
Alessio Podda [Mon, 24 Nov 2025 08:16:18 +0000 (09:16 +0100)]
Add rdatavec
Add an implementation of rdataset specialized for authoritative
workloads. For now, it is a copy of rdataslab, with redundant fields
from the header removed.
Alessio Podda [Wed, 10 Dec 2025 11:15:24 +0000 (11:15 +0000)]
chg: dev: Remove unused foundname parameter
The `foundname` parameter in `qp.c:dns_qp_lookup` was effectively used only in unit tests, as in every case the name is needed, it can be retrieved directly from the node pointer. It also required an inefficient implementation that extracted the name by converting it into a key and then immediately converting it back.
This MR refactors `qp.c:dns_qp_lookup` not to have a foundname parameter, resulting in a 5% speedup in the handling of NXDOMAIN responses in perflab.
Merge branch 'alessio/qp-no-foundname' into 'main'
Alessio Podda [Tue, 9 Dec 2025 16:41:33 +0000 (17:41 +0100)]
Fix formatting after refactor
The removal of the foundname and name parameters from various qp.c
functions led to formatting issues. Restore the correct formatting via
clang-format.
Alessio Podda [Mon, 1 Dec 2025 14:12:01 +0000 (15:12 +0100)]
Remove maybe_set_name
Outside of unit tests, the name parameter in dns_qpiter_<...> and
dns_qpchain_<...> is only used in context where the name can be
extracted directly from the underlying node.
This commits modifies the signatures of dns_qpiter_<...> and
dns_qpchain_<...> not to have a name parameter. Where the name parameter
was needed, we now query the node and copy the name directly from it.
This allows us to remove maybe_set_name from qp.c. Besides simplifying
the API, this leads to a performance speedup for NXDOMAIN handling,
as we avoid calling maybe_set_name inside step, and maybe_set_name is
very inefficient.
A copy of the implementation maybe_set_name is retained for the unit
tests.
Alessio Podda [Sun, 23 Nov 2025 13:59:30 +0000 (14:59 +0100)]
Remove unused foundname parameter
The `foundname` parameter in dns_qp_lookup is used only in the unit
tests. This commit simplifies the API by removing it, and modifying the
unit tests to extract the name from pval.
Evan Hunt [Tue, 9 Dec 2025 21:20:06 +0000 (21:20 +0000)]
fix: dev: dns_name_totext() can now resize dynamic buffers
When `dns_name_totext()` is called with a dynamically allocated
target buffer which is too small for the name, it will now resize
the buffer instead of returning `ISC_R_NOSPACE`.
Merge branch 'each-name-totext-resize' into 'main'
Evan Hunt [Wed, 26 Nov 2025 03:48:02 +0000 (19:48 -0800)]
dns_name_totext() can now resize dynamic buffers
When dns_name_totext() is called with a dynamically allocated
target buffer which is too small for the name, it will resize
the buffer instead of returning ISC_R_NOSPACE.
Ondřej Surý [Fri, 28 Nov 2025 14:13:58 +0000 (15:13 +0100)]
Add more information to the rndc recursing output about fetches
It is possible to have a fetch that is active, but it has been cloned,
so it won't be used when found in the hash table. The fetch options
also prevent matching in the hash table, so add a hexadecimal dump of
the fctx->options to the output.