]> git.ipfire.org Git - thirdparty/bind9.git/log
thirdparty/bind9.git
2 weeks agofix: dev: free per-command rndc state when response serialisation fails
Ondřej Surý [Thu, 30 Apr 2026 07:33:00 +0000 (09:33 +0200)] 
fix: dev: free per-command rndc state when response serialisation fails

When isccc_cc_towire failed while building an rndc reply,
control_respond returned without releasing the per-command request,
response, HMAC secret copy, and text buffer.  They were eventually
freed when the connection closed, but until then the HMAC key copy
stayed in named's memory.  The failure path now goes through the
same cleanup label as every other error.

Closes #5913

Merge branch '5913-controlconf-control-respond-cleanup-leak' into 'main'

See merge request isc-projects/bind9!11915

2 weeks agoRun conn_cleanup on isccc_cc_towire failure in control_respond
Ondřej Surý [Thu, 30 Apr 2026 04:29:21 +0000 (06:29 +0200)] 
Run conn_cleanup on isccc_cc_towire failure in control_respond

The bare return left conn->secret, conn->response, conn->request, and
conn->text pinned until the connection itself was torn down — every
other error in the function reaches conn_cleanup via goto, and the
success path falls into the same label, so the towire-failure return
was the lone outlier.  Send it through the existing cleanup path.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: dev: remove the rndc testgen command
Ondřej Surý [Thu, 30 Apr 2026 04:35:07 +0000 (06:35 +0200)] 
fix: dev: remove the rndc testgen command

testgen existed only to let the rndc system test generate large response payloads.
It accepted an unbounded count and was reachable from read-only control channels,
so any read-only rndc client could drive named into memory exhaustion. The command
and its supporting test helper are gone; remaining rndc commands already produce
non-trivial responses, so transport coverage is preserved.

Closes #5911

Merge branch '5911-rndc-testgen-32bit-truncation-memory-exhaustion' into 'main'

See merge request isc-projects/bind9!11912

2 weeks agoRemove the rndc testgen command
Ondřej Surý [Wed, 29 Apr 2026 18:41:20 +0000 (20:41 +0200)] 
Remove the rndc testgen command

testgen existed solely to let the rndc system test exercise large
response payloads — it has no operator value, accepts an unbounded
count, and could be invoked by any read-only rndc client to drive
named into memory exhaustion.  Drop the command, the gencheck helper
that validated its output, and the buffer-size loop in the rndc
system test; the remaining rndc subcommands already produce
non-trivial responses, so the framing path stays exercised.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: dev: Fix swapped arguments in redirect2() single-label branch
Ondřej Surý [Wed, 29 Apr 2026 19:46:32 +0000 (21:46 +0200)] 
fix: dev: Fix swapped arguments in redirect2() single-label branch

On a recursive resolver with nxdomain-redirect configured, an
NXDOMAIN result for a query whose qname is the root could corrupt
the view's nxdomain-redirect target, after which the redirect
feature stopped working for every subsequent query in that view
until named was restarted.

Closes #5908

Merge branch '5908-query-redirect2-name-copy-arg-swap' into 'main'

See merge request isc-projects/bind9!11908

2 weeks agoFix swapped arguments in redirect2() single-label branch
Ondřej Surý [Wed, 29 Apr 2026 17:23:19 +0000 (19:23 +0200)] 
Fix swapped arguments in redirect2() single-label branch

For a query whose qname is the root, the labels==1 branch in
redirect2() called dns_name_copy(redirectname, view->redirectzone)
with arguments reversed, overwriting the view-global
nxdomain-redirect target with the empty redirectname rather than
copying the configured target into the per-query lookup name.  After
the corruption, view->redirectzone names the root, so
dns_name_issubdomain() makes redirect2() short-circuit for every
subsequent query and the nxdomain-redirect feature stops working
until named is restarted.

Triggering this needs the resolver to receive an NXDOMAIN for the
root from upstream, which does not happen in normal DNS operation.

Swap the arguments to match the dns_name_copy(source, dest)
signature.  Add a system test that issues a root query through the
nxdomain-redirect resolver and verifies the redirect feature still
works for a normal NXDOMAIN-producing query afterwards.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: usr: Fix rndc-confgen aborting on HMAC-SHA-384/512 keys above 512 bits
Ondřej Surý [Wed, 29 Apr 2026 18:34:31 +0000 (20:34 +0200)] 
fix: usr: Fix rndc-confgen aborting on HMAC-SHA-384/512 keys above 512 bits

`rndc-confgen -A hmac-sha384` and `-A hmac-sha512` documented a `-b`
range of 1..1024, but any value above 512 aborted on hardened builds
instead of producing a key. The full advertised range now works.

Closes #5903

Merge branch '5903-hmac-generate-stack-overflow' into 'main'

See merge request isc-projects/bind9!11903

2 weeks agoSize HMAC key generation buffers to the maximum block size
Ondřej Surý [Wed, 29 Apr 2026 14:23:10 +0000 (16:23 +0200)] 
Size HMAC key generation buffers to the maximum block size

hmac_generate() declared its on-stack nonce buffer as
unsigned char data[ISC_MAX_MD_SIZE], i.e. 64 bytes. That is the maximum
digest size, but the buffer is filled up to the algorithm's HMAC block
size, which is 128 bytes for SHA-384 and SHA-512. Asking rndc-confgen
for an HMAC-SHA-384 or HMAC-SHA-512 key with -b > 512 (the documented
range allows up to 1024) wrote past the end of the stack buffer; on
hardened builds this aborted with a stack-smash detector firing
instead of producing a key.

Use the existing ISC_MAX_BLOCK_SIZE (128) for the buffer so the full
1..1024 range advertised by -A hmac-sha{384,512} works as documented.
The matching key_rawsecret[64] in confgen's generate_key() is enlarged
the same way so the generated key fits when dumped to the buffer.

Add a system test that exercises rndc-confgen across the previously
overflowing keysizes; with -Db_sanitize=address it caught the abort
before the fix.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: dev: Do not follow symlinks when chowning the NZD database
Ondřej Surý [Wed, 29 Apr 2026 17:18:55 +0000 (19:18 +0200)] 
fix: dev: Do not follow symlinks when chowning the NZD database

When `named` runs as root, the per-view NZD database file is chowned
to the user `named` drops to. The chown call followed symlinks, so a
symlink at the database path could redirect the ownership change to an
unrelated file. The chown now refuses non-regular files and never
follows symlinks.

Closes #5905

Merge branch '5905-nzd-env-close-symlink-chown' into 'main'

See merge request isc-projects/bind9!11907

2 weeks agoStop nzd_env_close from chowning through symlinks
Ondřej Surý [Wed, 29 Apr 2026 15:49:46 +0000 (17:49 +0200)] 
Stop nzd_env_close from chowning through symlinks

When named is running as root, nzd_env_close() chowns the per-view
NZD database file to the unprivileged user that named will drop to.
The call used chown(), which follows symlinks, so a symlink at the
NZD path would silently transfer ownership of whatever the link
pointed at instead of the database file itself.

Switch to lstat() + S_ISREG() + lchown() so the chown only fires when
the path is a regular file and never traverses a symlink even if one
is planted between the lstat and the lchown.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: usr: Validate key names in rndc-confgen, tsig-keygen, ddns-confgen
Ondřej Surý [Wed, 29 Apr 2026 16:12:52 +0000 (18:12 +0200)] 
fix: usr: Validate key names in rndc-confgen, tsig-keygen, ddns-confgen

The three tools embedded the key-name argument verbatim into the
generated `named.conf` block, so a name containing characters like
`"`, `{`, or `;` produced output that did not match the intended
`key` clause. Key names are now restricted to letters, digits, dots,
hyphens, and underscores.

Closes #5904

Merge branch '5904-confgen-keyname-config-injection' into 'main'

See merge request isc-projects/bind9!11904

2 weeks agoReject unsafe key names in rndc-confgen, tsig-keygen, ddns-confgen
Ondřej Surý [Wed, 29 Apr 2026 15:02:11 +0000 (17:02 +0200)] 
Reject unsafe key names in rndc-confgen, tsig-keygen, ddns-confgen

The three tools interpolated their key-name argument verbatim into the
generated 'key "..." { ... };' clause. A name containing '"', '{', '}',
or ';' could close the clause and append additional named.conf
statements — for example, a second key block with an attacker-chosen
secret. The injected output passes named-checkconf and is loaded by
named as a valid configuration. The risk shows up when an automation
wrapper feeds tenant or zone names from a less-trusted source through
-k / -y / -s / -z (or the tsig-keygen positional argument).

Validate the final key name (after the optional -s / -z suffix is
concatenated in tsig-keygen) against [A-Za-z0-9._-]+ and exit with an
error otherwise. The allowlist covers the documented usage; every
character used in the injection vectors is excluded.

Add a system test that runs the documented PoC payloads through each
tool and asserts a non-zero exit, plus sanity coverage for the default
key names and dotted DNS-style names.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: usr: Fix suppressed missing-glue check in named-checkzone
Ondřej Surý [Wed, 29 Apr 2026 15:31:30 +0000 (17:31 +0200)] 
fix: usr: Fix suppressed missing-glue check in named-checkzone

named-checkzone and named-checkconf -z silently skipped the
missing-glue check for any NS name that had already triggered an
extra-AAAA-glue warning, so zones missing required A glue could pass
validation and be deployed with broken delegations.

Merge branch 'ondrej/check-tool-err-glue-code-collision' into 'main'

See merge request isc-projects/bind9!11899

2 weeks agoResolve ERR_MISSING_GLUE / ERR_EXTRA_AAAA value collision
Ondřej Surý [Wed, 29 Apr 2026 12:03:38 +0000 (14:03 +0200)] 
Resolve ERR_MISSING_GLUE / ERR_EXTRA_AAAA value collision

Both constants were defined as 5. The symbol table used by checkns() to
deduplicate log messages keys on (name, error_code), so logging an
extra-AAAA error caused logged() to also return true for the
missing-glue check, silently skipping the entire missing-glue block for
the same name in named-checkzone and named-checkconf -z.

Convert the ERR_* defines to an auto-numbered enum so the compiler
guarantees the values stay pairwise distinct.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: dev: Validate -l and -L numeric arguments in named-checkzone
Ondřej Surý [Wed, 29 Apr 2026 15:25:53 +0000 (17:25 +0200)] 
fix: dev: Validate -l and -L numeric arguments in named-checkzone

named-checkzone and named-compilezone parsed the -l (max TTL) and -L
(source serial) arguments with strtol(), so a negative value such as
-1 silently became UINT32_MAX and out-of-range values were truncated
to 32 bits without warning; -l in particular appeared to cap TTLs but
no longer enforced anything. Both flags now go through isc_parse_uint32()
and reject any value that is not a valid 32-bit unsigned integer.

Merge branch 'ondrej/named-checkzone-strtol-truncation' into 'main'

See merge request isc-projects/bind9!11900

2 weeks agoValidate -l and -L arguments in named-checkzone
Ondřej Surý [Wed, 29 Apr 2026 12:52:21 +0000 (14:52 +0200)] 
Validate -l and -L arguments in named-checkzone

The -l (max TTL) and -L (source serial) flags parsed their arguments
with strtol() and assigned the result directly to uint32_t with no
range check. A negative value such as -1 became UINT32_MAX, which made
-l silently disable the TTL cap it claimed to enforce, and out-of-range
values truncated to 32 bits without warning.

Switch both flags to isc_parse_uint32(), which rejects leading non-
alphanumeric input (catching '-'), checks ERANGE, and validates the
32-bit range, so an invalid argument now exits with an error instead
of being silently coerced.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: usr: Stop rndc-confgen from following symlinks when writing the keyfile
Ondřej Surý [Wed, 29 Apr 2026 14:56:37 +0000 (16:56 +0200)] 
fix: usr: Stop rndc-confgen from following symlinks when writing the keyfile

When rndc-confgen -a (re)created the rndc control key, it followed a
symbolic link if one happened to exist at the keyfile path: the
existence check looked through the link, then the file was truncated,
its ownership changed, and the key contents written into whatever file
the link pointed at. rndc-confgen now refuses to follow symbolic links
at the keyfile path and fails with an error instead, so the wrong file
can no longer be overwritten by accident.

Merge branch '5901-rndc-confgen-symlink-attack' into 'main'

See merge request isc-projects/bind9!11902

2 weeks agoStop isc_file_safecreate from following symlinks
Ondřej Surý [Wed, 29 Apr 2026 13:30:05 +0000 (15:30 +0200)] 
Stop isc_file_safecreate from following symlinks

The function existence-checked the target with stat() and then opened
the same path without O_NOFOLLOW, so a symlink at the target path
passed the regular-file test against the link's destination and the
open() that followed truncated and wrote through the link.
rndc-confgen -a is typically run as root and writes the keyfile under
a directory that service accounts may have write access to, so a stray
symlink there would silently redirect the truncate, fchown, and
overwrite to whatever file the link pointed at.

Switch the existence check to lstat() and use S_ISREG() so a symlink's
S_IFLNK mode is detected directly (a plain bitmask of S_IFREG matches
both, since S_IFLNK shares its high bit). Add O_NOFOLLOW to both
open() flag sets to close the lstat/open TOCTOU window. Hardening
against unexpected symlinks on intermediate path components is out of
scope.

Assisted-by: Claude:claude-opus-4-7
2 weeks agochg: usr: Document that named-checkzone must not run on untrusted input
Ondřej Surý [Wed, 29 Apr 2026 14:39:45 +0000 (16:39 +0200)] 
chg: usr: Document that named-checkzone must not run on untrusted input

The zone-file parser implements $INCLUDE by opening whatever local
path the zone text names, and fragments of the included file leak
through parser error messages. There is no safe way to validate
untrusted zone text with named-checkzone or named-compilezone, so
the manual pages for both tools now warn against doing so.

Merge branch 'ondrej/named-checkzone-include-path-traversal' into 'main'

See merge request isc-projects/bind9!11901

2 weeks agoDrop unused DNS_MASTER_NOINCLUDE and warn about untrusted zone text
Ondřej Surý [Wed, 29 Apr 2026 13:08:20 +0000 (15:08 +0200)] 
Drop unused DNS_MASTER_NOINCLUDE and warn about untrusted zone text

DNS_MASTER_NOINCLUDE was defined to suppress $INCLUDE processing, but
no caller ever set it, so the guarded code path was dead and the flag
gave the false impression that named-checkzone could be hardened
against untrusted input. The zone-file parser cannot safely read text
from a less-trusted source than the user running the tool: $INCLUDE
opens any local file readable by that user, and fragments of its
contents leak through tokenizer error messages.

Rather than wire up an opt-in flag that suggests this is a supported
mode, remove the dead flag and the dead guard, and document in the
named-checkzone and named-compilezone manual pages that these tools
must not be run on zone text from an untrusted source.

Assisted-by: Claude:claude-opus-4-7
2 weeks agofix: usr: Glues from different parent are rejected
Colin Vidal [Wed, 29 Apr 2026 09:29:36 +0000 (11:29 +0200)] 
fix: usr: Glues from different parent are rejected

The changes making BIND 9 parent-centric !11621 introduced an issue where it could be possible, when processing a referral, to use the glue to a nameserver which has a different parent than the zonecut. For instance:

AUTHORITY
test.example. NS ns.test.example.
test.example. NS ns.foo.example.
test.example. NS ns.bar.

ADDITIONAL
ns.bar. A 1.2.3.4
ns.foo.example. A 5.6.7.8
ns.test.example. A 9.8.7.6

In such situation, only the glues for `ns.foo.example.` and `ns.test.example.` should be used, and the glue from `ns.bar.` must be ignored as this is not either a sub-domain or a sibling domain, the parent is different (`bar.` instead of `example.`). This is now fixed.

Sibling glue and cyclic sibling glues are defined in RFC 9471 section 2.2 and section 2.3.

Merge branch 'colin/cyclic-glues-test' into 'main'

See merge request isc-projects/bind9!11873

2 weeks agoDo not add glues from different parent in delegdb
Colin Vidal [Fri, 17 Apr 2026 11:09:56 +0000 (13:09 +0200)] 
Do not add glues from different parent in delegdb

When processing a referral, the `cache_delegns()` function was accepting
glues from a different parent. For instance:

```
AUTHORITY
test.example. NS ns.test.example.
test.example. NS ns.foo.example.
test.example. NS ns.bar.

ADDITIONAL
ns.bar. A 1.2.3.4
ns.foo.example. A 5.6.7.8
ns.test.example. A 9.8.7.6
```

In such situation, only the glues for `ns.foo.example.` and
`ns.test.example.` should be used, and the glue from `ns.bar.` should be
ignored as this is not either a sub-domain or a sibling domain, the
parent is different (`bar.` instead of `example.`). This is now fixed.

Sibling glue and cyclic sibling glues are defined in RFC 9471 section
2.2 and section 2.3.

2 weeks agoAdd cyclic_glue system test
Colin Vidal [Thu, 2 Apr 2026 15:52:23 +0000 (17:52 +0200)] 
Add cyclic_glue system test

The cyclic_glue system test ensures that:

- cyclic sibling glues are used;
- (by transitivity) sibling glues are used too;
- but glues from different parent are ignored.

2 weeks agofix: dev: Make BIND9 compatible with OpenSSL 4
Arаm Sаrgsyаn [Tue, 28 Apr 2026 14:46:43 +0000 (14:46 +0000)] 
fix: dev: Make BIND9 compatible with OpenSSL 4

OPENSSL_cleanup() in OpenSSL 4 doesn't free the memory, and that is
not compatible with BIND 9's memory leak detection code. Don't use
custom allocation/deallocation functions for OpenSSL's internal memory
management.

See https://github.com/openssl/openssl/pull/29721

Closes #5808

Merge branch '5808-openssl4-compat-fix' into 'main'

See merge request isc-projects/bind9!11865

2 weeks agoRemove OpenSSL memory tracking support from the ossl3.c module
Aram Sargsyan [Thu, 16 Apr 2026 17:31:04 +0000 (17:31 +0000)] 
Remove OpenSSL memory tracking support from the ossl3.c module

OPENSSL_cleanup() in OpenSSL 4 doesn't free the memory, and that is
not compatible with BIND 9's memory leak detection code. Don't use
custom allocation/deallocation functions for OpenSSL's internal memory
management in the ossl3.c module.

See https://github.com/openssl/openssl/pull/29721

2 weeks agochg: nil: Disable licensing check for root.hints
Colin Vidal [Tue, 28 Apr 2026 14:41:26 +0000 (16:41 +0200)] 
chg: nil: Disable licensing check for root.hints

Removing REUSE licensing header check for `root.hints` files.

Merge branch 'colin/disable-licensing-check-roothints' into 'main'

See merge request isc-projects/bind9!11893

2 weeks agoRemove licensing header check for `root.hint[s]`
Colin Vidal [Tue, 28 Apr 2026 13:46:57 +0000 (14:46 +0100)] 
Remove licensing header check for `root.hint[s]`

Removing REUSE licensing header check for `root.hint` and `root.hints`
files.

Assisted-by: Claude:claude-opus-4-7
2 weeks agochg: dev: don't set named curves explicitly in pre-3.0 libcrypto
Aydın Mercan [Tue, 28 Apr 2026 10:34:31 +0000 (13:34 +0300)] 
chg: dev: don't set named curves explicitly in pre-3.0 libcrypto

The function EC_KEY_set_asn1_flag is deprecated in AWS-LC. Fortunately
calling it to make sure we use named curve keys is entirely unnecessary.

More information for pre-3.0 libcrypto and significant forks are as
following:

OpenSSL: Named curves were the default between 1.1.0 and 3.6.1 [1],[2]

AWS-LC: Library only supports named curves in the first place [3]

BoringSSL: Likewise with AWS-LC [4]

LibreSSL: EC_GROUPs are named by default [5]

[1]: https://github.com/openssl/openssl/commit/86f300d38540ead85543aee0cb30c32145931744
[2]: https://github.com/openssl/openssl/commit/9db6af922c48c5cab5398ef9f37e425e382f9440
[3]: https://github.com/aws/aws-lc/blob/a605df416bc6ddd0a3b79d728770664ce2302e71/include/openssl/ec_key.h#L442-L445
[4]: https://github.com/google/boringssl/blob/514abb73bb80130000b46cf589190c967c6647cd/include/openssl/ec_key.h#L279-L280
[5]: https://github.com/libressl/openbsd/blob/c9338745181f31ae01336081edfdb738c0b76d5f/src/lib/libcrypto/ec/ec_lib.c#L94

Merge branch '5542-ec_key_set_asn1_flag-is-deprecated-with-aws-lc' into 'main'

See merge request isc-projects/bind9!11530

2 weeks agodon't set named curves explicitly in pre-3.0 libcrypto
Aydın Mercan [Fri, 6 Feb 2026 12:31:40 +0000 (15:31 +0300)] 
don't set named curves explicitly in pre-3.0 libcrypto

The function `EC_KEY_set_asn1_flag` is deprecated in AWS-LC. Fortunately
calling it to make sure we use named curve keys is entirely unnecessary.

More information for pre-3.0 libcrypto and significant forks are as
following:

OpenSSL: Named curves were the default between 1.1.0 and 3.6.1 [1],[2]
AWS-LC: Library only supports named curves in the first place [3]
BoringSSL: Likewise with AWS-LC [4]
LibreSSL: `EC_GROUP`s are named by default [5]

[1] https://github.com/openssl/openssl/commit/86f300d38540ead85543aee0cb30c32145931744
[2] https://github.com/openssl/openssl/commit/9db6af922c48c5cab5398ef9f37e425e382f9440
[3] https://github.com/aws/aws-lc/blob/a605df416bc6ddd0a3b79d728770664ce2302e71/include/openssl/ec_key.h#L442-L445
[4] https://github.com/google/boringssl/blob/514abb73bb80130000b46cf589190c967c6647cd/include/openssl/ec_key.h#L279-L280
[5] https://github.com/libressl/openbsd/blob/c9338745181f31ae01336081edfdb738c0b76d5f/src/lib/libcrypto/ec/ec_lib.c#L94

2 weeks agosec: usr: Fix race condition in getsigningtime()
Alessio Podda [Mon, 27 Apr 2026 17:15:00 +0000 (17:15 +0000)] 
sec: usr: Fix race condition in getsigningtime()

Compute qpzone_get_lock(elem->node) into a local variable while the
heap lock is still held, rather than dereferencing the stale elem
pointer after releasing the lock. A concurrent thread running
setsigningtime() (e.g. via IXFR apply on a worker thread) could free
the top-of-heap element between the heap lock release and the
dereference, causing a use-after-free.

Closes #5883

Merge branch '5883-getsigningtime-race-fix' into 'main'

See merge request isc-projects/bind9!11875

2 weeks agoFix race condition in getsigningtime()
Alessio Podda [Thu, 16 Apr 2026 11:20:50 +0000 (13:20 +0200)] 
Fix race condition in getsigningtime()

Compute qpzone_get_lock(elem->node) into a local variable while the
heap lock is still held, rather than dereferencing the stale elem
pointer after releasing the lock. A concurrent thread running
setsigningtime() (e.g. via IXFR apply on a worker thread) could free
the top-of-heap element between the heap lock release and the
dereference, causing a use-after-free.

2 weeks agonew: doc: Add AI coding assistants guidance to CONTRIBUTING.md
Ondřej Surý [Mon, 27 Apr 2026 08:12:05 +0000 (10:12 +0200)] 
new: doc: Add AI coding assistants guidance to CONTRIBUTING.md

Adapted from the Linux kernel's Documentation/process/coding-assistants.rst
to the BIND 9 context. Adds three subsections under the existing
"Guidelines for Tool-Generated Content" section:

- Licensing and legal requirements (MPL-2.0, SPDX identifiers).
- Signed-off-by and Developer Certificate of Origin: AI agents must
  not add Signed-off-by trailers; only the human submitter may
  certify the DCO.
- Attribution: the Assisted-by: AGENT_NAME:MODEL_VERSION trailer
  for recording AI involvement, with an explicit prohibition on
  AI-added Co-Authored-By trailers (Co-Authored-By designates a
  human co-author who shares responsibility).

Merge branch 'ondrej/coding-assistants-doc' into 'main'

See merge request isc-projects/bind9!11888

3 weeks agoAdd AI coding assistants guidance to CONTRIBUTING.md
Ondřej Surý [Wed, 22 Apr 2026 13:01:34 +0000 (15:01 +0200)] 
Add AI coding assistants guidance to CONTRIBUTING.md

Adapted from the Linux kernel's Documentation/process/coding-assistants.rst
to the BIND 9 context. Adds three subsections under the existing
"Guidelines for Tool-Generated Content" section:

- Licensing and legal requirements (MPL-2.0, SPDX identifiers).
- Signed-off-by and Developer Certificate of Origin: AI agents must
  not add Signed-off-by trailers; only the human submitter may
  certify the DCO.
- Attribution: the Assisted-by: AGENT_NAME:MODEL_VERSION trailer
  for recording AI involvement, with an explicit prohibition on
  AI-added Co-Authored-By trailers (Co-Authored-By designates a
  human co-author who shares responsibility).

3 weeks agofix: dev: Remove unneeded options in dns_zonefetch
Evan Hunt [Wed, 22 Apr 2026 11:00:24 +0000 (11:00 +0000)] 
fix: dev: Remove unneeded options in dns_zonefetch

In the `dns_zonefetch` mechanism, some option flags for
`dns_resolver_createfetch()` were used for all fetches, but
were actually only needed by the `DNSKEY` refresh fetches.

(Specifially, these options were `DNS_FETCHOPT_UNSHARED`
and `DNS_FETCHOPT_NOCACHED`, which were used along with
`DNS_FETCHOPT_NOVALIDATE` to ensure we get a new copy of
the DNSKEY as it is currently published by the authority,
without prior validation.  Those conditions are needed
for RFC 5011 trust anchor maintenace, but not when looking
up parent-`NS` or `DSYNC` RRsets.)

Merge branch 'each-zonefetch-cleanup' into 'main'

See merge request isc-projects/bind9!11866

3 weeks agoremove unneeded options in dns_zonefetch
Evan Hunt [Fri, 17 Apr 2026 02:40:40 +0000 (19:40 -0700)] 
remove unneeded options in dns_zonefetch

In the dns_zonefetch mechanism, some option flags for
dns_resolver_createfetch() were used for all fetches, but
were actually only needed by the DNSKEY refresh fetches.

(Specifially, these options were DNS_FETCHOPT_UNSHARED
and DNS_FETCHOPT_NOCACHED, which were used along with
DNS_FETCHOPT_NOVALIDATE to ensure we get a new copy of
the DNSKEY as it is currently published by the authority,
without prior validation.  Those conditions are needed
for RFC 5011 trust anchor maintenace, but not when looking
up parent-NS or DSYNC RRsets.)

3 weeks agonew: dev: Add DTRACE probes to the delegation cache
Ondřej Surý [Mon, 20 Apr 2026 13:11:21 +0000 (15:11 +0200)] 
new: dev: Add DTRACE probes to the delegation cache

The new delegation cache, which stores NS-based and DELEG-based delegations per view, is now instrumented
with static user-space tracing probes so that cache hit rate, insertion and lookup latency, eviction pressure
under memory limits, and removals triggered by rndc flush-delegation can be observed on a running named.

Merge branch 'ondrej/delegdb-dtrace-probes' into 'main'

See merge request isc-projects/bind9!11855

3 weeks agoAdd dtrace/ with example SystemTap trace scripts
Ondřej Surý [Wed, 15 Apr 2026 13:12:51 +0000 (15:12 +0200)] 
Add dtrace/ with example SystemTap trace scripts

Introduces a top-level dtrace/ directory for user-contributed trace
scripts that consume the USDT probes exported by libdns, libns, and
libisc.  Ships with delegdb-trace.stp, which streams every insertion,
eviction, and rndc flush-delegation removal in the delegation cache,
and a README pointing at the provider files and explaining how to list
and run the probes on Linux (SystemTap) and on FreeBSD/macOS (DTrace).

3 weeks agoAdd DTRACE probes to dns_delegdb
Ondřej Surý [Wed, 15 Apr 2026 12:53:37 +0000 (14:53 +0200)] 
Add DTRACE probes to dns_delegdb

Instrument the delegation cache (introduced to back both NS-based and
DELEG-based delegations) with 11 USDT probes in the libdns provider so
that hit rate, eviction pressure, and lookup latency can be measured
without recompiling or enabling logging.

The probes are:

- delegdb_lookup_start / delegdb_lookup_done wrap dns_delegdb_lookup()
  and pass the query name plus the result code.

- delegdb_insert_start / delegdb_insert_done wrap dns_delegset_insert().
  The early SHUTTINGDOWN return is funneled through the cleanup label
  so the done probe fires on every path.

- delegdb_cleanup_start / delegdb_cleanup_done bracket the SIEVE-based
  eviction triggered when the cache goes overmem, reporting the number
  of bytes requested and actually reclaimed.  An additional per-node
  delegdb_evict probe (guarded by _ENABLED() because it fires inside
  the loop) exposes which zones are being evicted.

- delegdb_create, delegdb_reuse, and delegdb_shutdown trace the per-view
  lifecycle across server reloads.

- delegdb_delete traces rndc flush-delegation paths, reporting whether
  a subtree or single name was removed.

Name arguments are stringified with dns_name_format() behind
LIBDNS_*_ENABLED() guards so that the hot lookup and insert paths remain
zero-cost when no consumer is attached.

3 weeks agofix: dev: Fix inverted gethostname() check in rndc status
Ondřej Surý [Fri, 17 Apr 2026 15:52:39 +0000 (17:52 +0200)] 
fix: dev: Fix inverted gethostname() check in rndc status

The replacement of named_os_gethostname() with raw gethostname()
inverted the success check: the "localhost" fallback runs on success,
and on failure the uninitialized hostname buffer is read by snprintf(),
leaking stack memory via the rndc status reply.

Closes #5889

Merge branch '5889-fix-gethostname-inverted-check' into 'main'

See merge request isc-projects/bind9!11879

3 weeks agoFix inverted gethostname() check in rndc status
Ondřej Surý [Fri, 17 Apr 2026 14:28:50 +0000 (16:28 +0200)] 
Fix inverted gethostname() check in rndc status

When named_os_gethostname() was replaced with raw gethostname(), the
success/failure polarity was flipped: the fallback to "localhost" now
runs on success and the hostname buffer is left uninitialized on
failure.  In the failure path, snprintf() then reads the uninitialized
stack buffer, disclosing stack contents via the rndc status reply.

4 weeks agochg: test: Reimplement xfer/ans5 using ControllableAsyncServer
Štěpán Balážik [Fri, 17 Apr 2026 14:26:18 +0000 (14:26 +0000)] 
chg: test: Reimplement xfer/ans5 using ControllableAsyncServer

Merge branch 'stepan/xfer-asyncserver' into 'main'

See merge request isc-projects/bind9!11626

4 weeks agoReimplement xfer/ans5 using ControllableAsyncServer
Štěpán Balážik [Fri, 23 Jan 2026 18:51:45 +0000 (19:51 +0100)] 
Reimplement xfer/ans5 using ControllableAsyncServer

Remove the last usage of the `ans.pl` server and the server itself.

4 weeks agoConvert responses to bytes before logging them in asyncserver
Štěpán Balážik [Wed, 21 Jan 2026 18:34:29 +0000 (19:34 +0100)] 
Convert responses to bytes before logging them in asyncserver

Ensure that the actual packet contents are logged including the TSIG
record which is calculated on `to_wire` call.

4 weeks agoImprove readability of endianness conversions
Štěpán Balážik [Fri, 10 Apr 2026 16:25:17 +0000 (18:25 +0200)] 
Improve readability of endianness conversions

Replace the less obvious and less explicit `struct.unpack()` and
`struct.pack()` calls with calls to `int.from_bytes()` and
`int.to_bytes()`, respectively.

4 weeks agoRefactor AxfrHandler and hoist it to isctest.asyncserver
Štěpán Balážik [Mon, 19 Jan 2026 21:04:32 +0000 (22:04 +0100)] 
Refactor AxfrHandler and hoist it to isctest.asyncserver

It will be useful in the xfer system test as well.

4 weeks agoFix FallbackTooManyRecordsAxfrHandler to follow convention
Štěpán Balážik [Mon, 19 Jan 2026 20:49:36 +0000 (21:49 +0100)] 
Fix FallbackTooManyRecordsAxfrHandler to follow convention

All the other subclasses AxfrHandler send three messages.
This oversight was inherited from the original Perl implementation of
the server and was not fixed in 46ecbbe where it was rewritten.

This allows refactoring and sharing of the superclass.

4 weeks agofix: usr: Fix named crash when processing SIG records in dynamic updates
Ondřej Surý [Fri, 17 Apr 2026 14:09:52 +0000 (16:09 +0200)] 
fix: usr: Fix named crash when processing SIG records in dynamic updates

Previously, :iscman:`named` could abort if a client sent a dynamic update containing a SIG record (the legacy signature type) to a zone configured with an update-policy. The function `dns_db_findrdataset` had an incorrect requirements prerequisite that prevented SIG records being looked up, which was triggered as part of processing an UPDATE request and could be triggered remotely by any client permitted to send updates. This has been fixed by ensuring that SIG records are handled consistently with RRSIG records during update processing.

Closes #5818

Merge branch '5818-fix-update-of-sig' into 'main'

See merge request isc-projects/bind9!11864

4 weeks agoAdd test for SIG in prequisites of dynamic update
Matthijs Mekking [Thu, 16 Apr 2026 14:17:34 +0000 (16:17 +0200)] 
Add test for SIG in prequisites of dynamic update

Make sure the nameserver correctly handles SIG records in the
prerequisites of the dynamic update. The first check is to ensure that
the prerequisites are not examined prior to checking the credentials.

The second test case checks that the SIG present prerequisite is
examined and therefore refuses the update. Also this should not trigger
an assertion failure in dns__db_findrdataset() (due to the REQUIRE()
only accepted dns_rdatatype_rrsig when the covers parameter was set).

4 weeks agoAdd AXFR regression test for SIG covers preservation
Ondřej Surý [Thu, 16 Apr 2026 11:25:03 +0000 (13:25 +0200)] 
Add AXFR regression test for SIG covers preservation

diff.c rdata_covers() runs on both dns_diff_apply (IXFR, ns/update.c
dynamic updates) and dns_diff_load (AXFR).  After the previous commit
refused SIG and NXT in dynamic updates, the AXFR path remains the
most natural way to drive legacy SIG records into a secondary's zone
DB and regression-gate the rdata_covers() fix.

The test adds ans11 as an AsyncDnsServer primary for a small zone
whose AXFR carries two SIG rdatas at the same owner with different
covered types (A, MX) and different TTLs (600, 1200), and declares
ns6 a secondary of that zone.  With the bug present, dns_diff_load
groups both tuples at typepair (SIG, 0) and the MX-covering record
inherits the first-seen TTL (600); the fix keeps them at (SIG, A)
and (SIG, MX) with their original TTLs.

rndc dumpdb -zones on the secondary is used to inspect stored state
directly, because the wire-level SIG query response merges
same-(owner,type,class) RRs and masks the per-rdataset TTLs.

4 weeks agoRefuse SIG and NXT records in dynamic updates
Ondřej Surý [Thu, 16 Apr 2026 10:23:34 +0000 (12:23 +0200)] 
Refuse SIG and NXT records in dynamic updates

SIG (24) and NXT (30) are obsolete DNSSEC record types, superseded by
RRSIG and NSEC in RFC 3755.  Allowing them through dynamic update
exposes two distinct bugs that the surrounding GL#5818 work already
fixes as defense-in-depth:

  - dns__db_findrdataset() used to REQUIRE that (covers == 0 ||
    type == RRSIG), which aborts named when a SIG update reaches the
    prescan foreach_rr() call.  Fixed to accept dns_rdatatype_issig().
  - diff.c rdata_covers() used to test only RRSIG, dropping the
    covered-type field for SIG rdatas; the zone DB then filed every
    SIG rdataset under typepair (SIG, 0) instead of
    (SIG, covered_type) and follow-up adds collided at that bucket.
    Fixed to use dns_rdatatype_issig().

Both underlying bugs are still reachable via inbound zone transfer
(diff.c rdata_covers() runs from both dns_diff_apply on the IXFR path
and dns_diff_load on the AXFR path), so the type-helper fixes above
remain necessary.  For the dynamic-update path, the simplest and
safest posture is to refuse SIG and NXT outright at the front door in
ns/update.c, alongside the existing NSEC/NSEC3/non-apex-RRSIG
refusals.  KEY remains permitted because it is still used to carry
public keys for SIG(0) transaction authentication.

The existing tcp-self SIG regression test is repointed to assert
REFUSED on the SIG add, a symmetric NXT test is added, and the
SIG-via-dyn-update covers-bucket test is removed because it is no
longer reachable through this entry point; AXFR-based coverage of
diff.c rdata_covers() follows in a separate commit.

4 weeks agoAdd regression test for SIG covers being dropped in dns_diff_apply
Ondřej Surý [Thu, 16 Apr 2026 09:16:40 +0000 (11:16 +0200)] 
Add regression test for SIG covers being dropped in dns_diff_apply

rdata_covers() in lib/dns/diff.c tests `type == dns_rdatatype_rrsig`
instead of dns_rdatatype_issig(), so for a legacy SIG (24) rdata it
returns 0 and the covered type is discarded on the dynamic-update /
IXFR path.  The zone DB then files every SIG rdataset under typepair
(SIG, 0) instead of (SIG, covered_type), and a follow-up add with a
different covers field but a different TTL collides at that bucket,
trips DNS_DBADD_EXACTTTL in qpzone, returns DNS_R_NOTEXACT, and comes
back to the client as SERVFAIL.

The new test adds a PTR to establish the node (tcp-self requires the
client IP's reverse form to equal the owner), then two SIG updates
with different covers and different TTLs; on a buggy build the second
update is SERVFAIL and named logs `dns_diff_apply: .../SIG/IN: add
not exact`.  The test is expected to pass once rdata_covers() is
switched to dns_rdatatype_issig(), matching the fix already adopted
for dns__db_findrdataset() on this branch and the helper pattern used
in master.c, xfrout.c, and qpcache.c.

4 weeks agoFix dropped covers field for SIG records in dns_diff_apply
Ondřej Surý [Thu, 16 Apr 2026 09:21:48 +0000 (11:21 +0200)] 
Fix dropped covers field for SIG records in dns_diff_apply

rdata_covers() in lib/dns/diff.c discriminated only on
dns_rdatatype_rrsig (46) and returned 0 for the legacy SIG (24), so
the covered-type field was silently discarded on the dynamic-update
and IXFR paths.  Every SIG rdataset was then filed in the zone DB
under typepair (SIG, 0) instead of (SIG, covered_type); a second SIG
add with a different covers but a different TTL collided at that
bucket, tripped DNS_DBADD_EXACTTTL in qpzone, returned
DNS_R_NOTEXACT, and came back to the client as SERVFAIL.

Use dns_rdatatype_issig() here so both SIG and RRSIG carry their
covers through the diff, matching the helper pattern already used in
lib/dns/master.c, lib/ns/xfrout.c, lib/dns/qpcache.c, and the
dns__db_findrdataset() REQUIRE that the surrounding merge request
just relaxed.

4 weeks agoAdd system test for SIG record handling in update-policy tcp-self
Ondřej Surý [Tue, 7 Apr 2026 14:40:36 +0000 (16:40 +0200)] 
Add system test for SIG record handling in update-policy tcp-self

Verify that a SIG record sent via TCP dynamic update is accepted
by the tcp-self update-policy and correctly stored in the zone.

4 weeks agoFix assertion failure in dns_db_findrdataset() for SIG records
Mark Andrews [Tue, 7 Apr 2026 14:39:57 +0000 (16:39 +0200)] 
Fix assertion failure in dns_db_findrdataset() for SIG records

dns__db_findrdataset() had a REQUIRE() that only accepted
dns_rdatatype_rrsig when the covers parameter was set.  A dynamic
update containing a SIG record (type 24) would trigger this
assertion, crashing named.  Use dns_rdatatype_issig() to accept
both SIG and RRSIG.

4 weeks agofix: dev: Fix strict weak ordering violation in resign_sooner()
Alessio Podda [Fri, 17 Apr 2026 14:07:16 +0000 (14:07 +0000)] 
fix: dev: Fix strict weak ordering violation in resign_sooner()

resign_sooner_values() only checked whether rhs was SOA-typed when
resign times were equal, but did not check lhs. When both entries were
SOA-typed with equal resign times, the comparison returned true in both
directions, violating irreflexivity and corrupting heap invariants.

Add lhs_typepair parameter and require lhs to be non-SOA for the
tie-breaking logic to apply.

Closes #5884

Merge branch '5884-heap-condition-fix' into 'main'

See merge request isc-projects/bind9!11874

4 weeks agoFix strict weak ordering violation in resign_sooner()
Alessio Podda [Thu, 16 Apr 2026 11:21:04 +0000 (13:21 +0200)] 
Fix strict weak ordering violation in resign_sooner()

resign_sooner_values() only checked whether rhs was SOA-typed when
resign times were equal, but did not check lhs. When both entries were
SOA-typed with equal resign times, the comparison returned true in both
directions, violating irreflexivity and corrupting heap invariants.

Add lhs_typepair parameter and require lhs to be non-SOA for the
tie-breaking logic to apply.

4 weeks agonew: ci: Add "assign-milestones" job to CI
Andoni Duarte [Fri, 17 Apr 2026 09:42:22 +0000 (09:42 +0000)] 
new: ci: Add "assign-milestones" job to CI

After a release is signed (the "sign" job), the "assign-milestones" job
will assign issues and merge requests to the corresponding version
milestones.

Merge branch 'andoni/add-assign-milestone-ci-job' into 'main'

See merge request isc-projects/bind9!11868

4 weeks agoAdd job to assign issues and merge requests to version milestones
Andoni Duarte Pintado [Thu, 26 Feb 2026 09:06:48 +0000 (10:06 +0100)] 
Add job to assign issues and merge requests to version milestones

After a release is signed (the "sign" job), the "assign-milestones" job
will assign issues and merge requests to the corresponding version
milestones.

4 weeks agonew: ci: Extend the prepare-release-announcement job to post release links
Andoni Duarte [Fri, 17 Apr 2026 08:51:35 +0000 (08:51 +0000)] 
new: ci: Extend the prepare-release-announcement job to post release links

The prepare-release-announcement job is now extended so that after
creating the announcement MR, it posts a message with links to the newly
released versions to Mattermost.

Merge branch 'andoni/extend-prepare-release-announcement-with-urls-message' into 'main'

See merge request isc-projects/bind9!11860

4 weeks agoExtend the prepare-release-announcement job post release links
Andoni Duarte Pintado [Thu, 16 Apr 2026 13:59:27 +0000 (15:59 +0200)] 
Extend the prepare-release-announcement job post release links

The prepare-release-announcement job is now extended so that after
creating the announcement MR, it posts a message with links to the newly
released versions to Mattermost.

4 weeks agonew: doc: Document opt-in 🤖 marker for agent-authored issues and MRs
Ondřej Surý [Thu, 16 Apr 2026 17:00:03 +0000 (19:00 +0200)] 
new: doc: Document opt-in 🤖 marker for agent-authored issues and MRs

Add short notes in CONTRIBUTING.md telling automated agents to append
🤖 to the title of issues and merge requests so they can be routed
through the streamlined agent triage/merge process.

Merge branch 'ondrej/agent-contributing' into 'main'

See merge request isc-projects/bind9!11861

4 weeks agoDocument opt-in 🤖 marker for agent-authored issues and MRs
Ondřej Surý [Thu, 16 Apr 2026 16:51:01 +0000 (18:51 +0200)] 
Document opt-in 🤖 marker for agent-authored issues and MRs

Add short notes in CONTRIBUTING.md telling automated agents to append
🤖 to the title of issues and merge requests so they can be routed
through the streamlined agent triage/merge process.

4 weeks agofix: dev: Add missing parenthesis to fxhash
Alessio Podda [Thu, 16 Apr 2026 14:48:19 +0000 (14:48 +0000)] 
fix: dev: Add missing parenthesis to fxhash

The fxhash implementation had a missing parenthesis that caused it to
diverge from Rust's reference implementation. This commit fixes this.

Closes #5882

Merge branch '5882-fxhash-fix' into 'main'

See merge request isc-projects/bind9!11857

4 weeks agoAdd missing parenthesis to fxhash
Alessio Podda [Thu, 16 Apr 2026 09:56:46 +0000 (11:56 +0200)] 
Add missing parenthesis to fxhash

The fxhash implementation had a missing parenthesis that caused it to
diverge from Rust's reference implementation. This commit fixes this.

4 weeks agofix: usr: Prevent excessive priming queries to the root servers
Ondřej Surý [Thu, 16 Apr 2026 12:33:44 +0000 (14:33 +0200)] 
fix: usr: Prevent excessive priming queries to the root servers

BIND was sending a priming query to the root servers on nearly every
recursive lookup instead of only when the cached root information
expired.  Priming now rearms only after the TTL of the fetched records
elapses, and the refreshed root NS set is used for query routing until
the next cycle.

Merge branch 'ondrej/fix-delegdb-priming' into 'main'

See merge request isc-projects/bind9!11847

4 weeks agoRename view->hints to view->rootdb and rearm priming
Ondřej Surý [Wed, 15 Apr 2026 06:11:17 +0000 (08:11 +0200)] 
Rename view->hints to view->rootdb and rearm priming

With the parent-centric resolver, dns_view_bestzonecut() consults the
delegation DB (view->deleg) rather than the main cache for the closest
zonecut.  Root is never the target of a referral, so it never lands in
delegdb; bestzonecut therefore falls through to the hints lookup on
every query whose closest ancestor is root.  prime_done() only called
dns_root_checkhints(), which logs discrepancies but does not update
any store bestzonecut looks at, so the fresh root NS records obtained
by priming were never used and priming kept re-firing.

Rename view->hints to view->rootdb and refresh it when a priming
fetch completes: the '.' NS rdataset is replaced with the fetched
one, and for each listed nameserver the matching A/AAAA glue is
copied from the response's ADDITIONAL section.  Only glue for names
that actually appear as NS targets is accepted, so a hostile response
cannot inject unrelated records.  Glue the response did not carry is
left untouched, so the hints-file records loaded at startup remain as
a fallback.

Each view gets its own rootdb: the previous shared
named_g_server->in_roothints is gone, and configure_view() calls
dns_rootns_create() per view when the class-IN defaults are needed.
That keeps the priming writer one-per-DB, so concurrent priming in
different views cannot race on the same zone-DB version.

The rootdb refresh runs synchronously from the resolver response path,
so records go straight from the wire into rootdb with no cache round
trip and no dependency on DNSSEC validation state.  A new
DNS_FETCHOPT_PRIMING option marks the priming fetch; prime_done()
itself is now pure cleanup.

Track the rootdb freshness window in view->rootdb_expires and trigger
re-priming lazily from dns_view_find() and bestzonecut_rootdb() only
when the window has elapsed.  Stale records are still served while the
fresh priming fetch is in flight.

Drop dns_root_checkhints() and its helpers; the rootdb is now the
authoritative source the resolver consults.

4 weeks agofix: usr: Fix zone filename token-parsing bug
Arаm Sаrgsyаn [Thu, 16 Apr 2026 11:37:17 +0000 (11:37 +0000)] 
fix: usr: Fix zone filename token-parsing bug

The :iscman:`named` process could terminate unexpectedly when
processing a catalog member zone containing special characters
like '%' or '$' which could be interpreted as zone filename tokens
and trigger a case-sensitivity bug in the token-parsing code. This
has been fixed.

Closes #5849

Merge branch '5849-catz-filename-and-token-parsing-fix' into 'main'

See merge request isc-projects/bind9!11839

4 weeks agoTreat '%' and '$' as special characters for catalog member zone names
Aram Sargsyan [Mon, 13 Apr 2026 12:02:31 +0000 (12:02 +0000)] 
Treat '%' and '$' as special characters for catalog member zone names

The filename of the catalog member zones are generated dynamically
based on the zone's name. If the zone's name is too long or if it
contains special characters the name's digest is used instead.

Since '%' and '$' are now treated as special characters in the zone
names (see !10779), add these characters to the list of the special
characters.

4 weeks agoA a test to check zone filename case-insensitivity
Aram Sargsyan [Mon, 13 Apr 2026 11:42:07 +0000 (11:42 +0000)] 
A a test to check zone filename case-insensitivity

The test adds a catalog member zone which has '%X' in its name and
it ends up in the zone filename parser's code because the filename
is currently generated (by the catalog zone code) based on the zone's
name.

Zones which have a name with the '%' special character should be
filtered and their name's digest should be used instead for filenane
generation (like it is implemented for other special characters), and
that fix is coming next.

4 weeks agoFix case-sensitivity bug in zone filename token-parsing
Aram Sargsyan [Mon, 13 Apr 2026 11:38:19 +0000 (11:38 +0000)] 
Fix case-sensitivity bug in zone filename token-parsing

The setfilename() function uses case-insensitive strcasestr() when
matching the possible tokens, but then one of the token parsers
uses case-sensitive INSIST checks which can assert when, for example,
matching '%X' and INSIST only accepts '%x'.

The case-insensitivity is documented, which means it's the parser
that needs to be fixed, not the matcher.

Convert the character to lowercase before checking the token's
validity.

4 weeks agofix: usr: Avoid extra round trips for DS lookups when the parent delegation is alread...
Ondřej Surý [Thu, 16 Apr 2026 11:16:34 +0000 (13:16 +0200)] 
fix: usr: Avoid extra round trips for DS lookups when the parent delegation is already cached

DS queries could take two unnecessary extra round trips when the resolver sent them to the child zone instead of the parent. The child responds with NODATA, forcing a recovery path to rediscover the parent delegation even though it was already cached.  The resolver now consults its delegation cache before starting DS fetches, sending queries directly to the correct parent nameservers and eliminating the extra latency.

Merge branch 'ondrej/fix-ds-chase' into 'main'

See merge request isc-projects/bind9!11835

4 weeks agoAdd system test for the chase DS fix
Colin Vidal [Wed, 15 Apr 2026 12:00:06 +0000 (14:00 +0200)] 
Add system test for the chase DS fix

Add a system test which ensures, whenever the DS record can't be found
in the local cache, that the resolver first tries to get the parent NS
from the delegation cache to ask them the DS record, directly, rather
than running the fallback flow where the resolver attempts to query the
DS record from NS of the validating name (which would fails, then the
resolver would remove one label and fetch again, fails, and so on until
it reach the closest zonecut).

The test relies on the fact that when the fallback flow is run, the
`rctx_chaseds()` function is run, adding the "chase DS servers ..." and
"suspending DS lookup to find parent's..." logs.

4 weeks agorename `DNS_DBFIND_NOEXACT` to `DNS_DBFIND_ABOVE`
Colin Vidal [Mon, 13 Apr 2026 08:31:44 +0000 (10:31 +0200)] 
rename `DNS_DBFIND_NOEXACT` to `DNS_DBFIND_ABOVE`

The `DNS_DBFIND_NOEXACT` flag name is ambiguous, as it does not clearly
indicate the lookup behavior (e.g., sibling, child, or parent).

Rename it to `DNS_DBFIND_ABOVE` to better reflect that the lookup
targets a closer ancestor name.

4 weeks agoReplace FIXME with rationale for not cleaning expired delegdb nodes
Ondřej Surý [Fri, 10 Apr 2026 11:19:55 +0000 (13:19 +0200)] 
Replace FIXME with rationale for not cleaning expired delegdb nodes

Expired delegation nodes are naturally replaced when the resolver
fetches fresh data, and any remaining stale nodes are reclaimed by
SIEVE eviction under memory pressure.

4 weeks agoRemove hiwater/lowater fields from delegdb
Colin Vidal [Fri, 10 Apr 2026 06:57:51 +0000 (08:57 +0200)] 
Remove hiwater/lowater fields from delegdb

The delegdb does not directly use the hiwater and lowater values during
the cleaning flow, so these fields are no longer necessary.

4 weeks agoReclaim only what the new delegation needs
Ondřej Surý [Thu, 9 Apr 2026 10:46:45 +0000 (12:46 +0200)] 
Reclaim only what the new delegation needs

delegdb_cleanup() was overwriting the caller-supplied 'requested'
value with (hiwater - lowater), so every overmem cleanup tried to
free the full watermark band regardless of how much memory the new
delegation actually needed.  Drop the override so the caller's size
is used: we now walk the SIEVE only until we have reclaimed enough
room for the new node, leaving unrelated entries in place.

4 weeks agoAccount transient delegsets against the caller's memory context
Ondřej Surý [Thu, 9 Apr 2026 10:45:30 +0000 (12:45 +0200)] 
Account transient delegsets against the caller's memory context

dns_delegset_fromnsrdataset() used isc_g_mctx for the transient
delegset it builds from a DNS NS rdataset.  That hides delegation
data in the global default context instead of accounting it against
the subsystem that owns it: a resolver fctx, a view, or a query
context.

Take an explicit mctx parameter so callers can direct the allocation
to the right place, and update the three call sites:
- lib/dns/view.c:1189 (dns_view_bestzonecut fallback) uses view->mctx
- lib/dns/resolver.c:7071 (resume_dslookup) uses fctx->mctx
- lib/ns/query.c:8672 (query_delegation_recurse) uses the client
  manager's mctx

Also tighten delegdb cleanup to run inside the same write transaction
as the insert: delegdb_node_prepare() now returns the size of the new
node, and delegdb_cleanup() takes the caller's open qp so that the
overmem reclamation and the insert share one commit instead of doing
two nested write transactions.

4 weeks agoFix delegation database NOEXACT lookup for top-level names
Ondřej Surý [Thu, 9 Apr 2026 10:06:31 +0000 (12:06 +0200)] 
Fix delegation database NOEXACT lookup for top-level names

dns__deleg_lookup() with DNS_DBFIND_NOEXACT is supposed to return
the deepest proper ancestor of the lookup name.  It called
getparentnode() to step up from an exact match, but getparentnode()
only iterated while the chain length was >= 2.  When the chain
contained a single entry (the exact match itself with no ancestor
stored in the trie), the loop did not execute and left the caller
looking at the exact match.  The subsequent isactive() check then
returned success and the function reported the exact match as the
"deepest ancestor", violating NOEXACT semantics.

This was observable as the resolver picking the child-side
delegation for an at-parent type (e.g. a DS query for a TLD), then
sending the query to the child's own nameservers and recovering via
the "chase DS servers" path.

Have getparentnode() set '*node' to NULL when it cannot find an
active proper ancestor, and make dns__deleg_lookup() NULL-check
before returning, matching the canonical NOEXACT implementation in
dns_zt_find().  Update the deleg unit test to expect NOTFOUND for
the top-level-no-parent case.

4 weeks agoUse the delegation database in get_dsset()
Ondřej Surý [Thu, 9 Apr 2026 07:44:29 +0000 (09:44 +0200)] 
Use the delegation database in get_dsset()

When the validator needs a DS RRset and the cache does not have it,
get_dsset() falls back to creating a fresh fetch.  Without a hint, the
resolver picks the closest known zone cut for the DS query, and in the
parent-centric resolver that can land on a delegation at the DS owner
name itself (the child side). This can happens when the parent
delegation is expired, or if the zonecut of the parent doesn't match the
labels in the name.

Querying the child for its own DS records yields NODATA from the apex of
the zone, which sends the resolver into the "chase DS servers" recovery
path and costs two extra round trips for a parent delegation we already
had cached in the delegation database.

Look up the parent zone in the delegation database before kicking
off the fetch, and pass any usable delegation to the resolver as a
hint.  When the hint is present, the resolver sends the DS query
straight to the parent's nameservers and the chase path is avoided
entirely.

To support this, create_fetch() now takes optional 'domain' and
'delegset' parameters that are forwarded to dns_resolver_createfetch().
All other call sites pass NULL.

4 weeks agorem: nil: Continue removal of license headers from test zones
Evan Hunt [Wed, 15 Apr 2026 19:26:35 +0000 (19:26 +0000)] 
rem: nil: Continue removal of license headers from test zones

Copyright license headers were removed from system test zone files in
commit f144db6b686, but this change only applied to files named '*.db',
'*.db.in', etc. There were some zone files called '*.zone' which were
left unchanged; these have been updated now as well.

Merge branch 'each-cleanup-zonefiles' into 'main'

See merge request isc-projects/bind9!11853

4 weeks agoContinue removal of license headers from test zones
Evan Hunt [Wed, 15 Apr 2026 04:20:39 +0000 (21:20 -0700)] 
Continue removal of license headers from test zones

Copyright license headers were removed from system test zone files in
commit f144db6b686, but this change only applied to files named '*.db',
'*.db.in', etc. There were some zone files called '*.zone' which were
left unchanged; these have been updated now as well.

4 weeks agofix: test: Use virtualenv's Python interpreter when running tests from a venv
Nicki Křížek [Wed, 15 Apr 2026 14:05:16 +0000 (16:05 +0200)] 
fix: test: Use virtualenv's Python interpreter when running tests from a venv

Merge branch 'nicki/pytest-venv-python' into 'main'

See merge request isc-projects/bind9!11854

4 weeks agoLog the Python interpreter used to run the system tests during setup
Štěpán Balážik [Wed, 15 Apr 2026 13:12:38 +0000 (15:12 +0200)] 
Log the Python interpreter used to run the system tests during setup

This is useful when running in an virtual environment or on a machine
where multiple Python versions are installed.

4 weeks agoUse virtualenv's Python interpreter when running tests from a venv
Nicki Křížek [Wed, 15 Apr 2026 08:08:01 +0000 (08:08 +0000)] 
Use virtualenv's Python interpreter when running tests from a venv

Meson bakes the absolute path of the detected Python binary (e.g.
/usr/bin/python3.12) into the PYTHON build variable. When tests are run
from a virtualenv, that stored path might point to the system Python
which lacks the virtualenv's installed packages, causing test failures.

Fix this by checking whether the current process is running inside a
virtualenv (sys.prefix != sys.base_prefix) and, if so, replacing the
stored PYTHON build var with sys.executable — the interpreter that is
already running pytest and has all required dependencies available.

The behaviour on EL8/EL9 (where meson prefers python3.12 over the older
platform default) and on FreeBSD (python3.11) is unchanged, since those
workflows run pytest without an active virtualenv in our CI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4 weeks agofix: dev: Fix a bug with template filename reuse
Evan Hunt [Wed, 15 Apr 2026 06:57:27 +0000 (06:57 +0000)] 
fix: dev: Fix a bug with template filename reuse

When a zone filename is defined in `named.conf` which will be
written to by the server - i.e., for secondary or dynamically updated
zones - there is a test at configuration time to ensure that the
filename is non-unique.

This test is run before the zone is actually created, so a zone
configured using a template may not have had its filename expanded
yet.  This can cause a configuration to fail because, for example,
multiple zones appear to using the filename `$name.db`.

This has been fixed by adding a new function `dns_zone_expandzonefile()`
and calling it during the uniqueness check.

Merge branch 'each-template-file' into 'main'

See merge request isc-projects/bind9!11769

4 weeks agoFix a bug with template filename reuse
Mark Andrews [Thu, 2 Apr 2026 04:25:09 +0000 (15:25 +1100)] 
Fix a bug with template filename reuse

When a zone filename is defined in named.conf which will be
written to by the server - i.e., secondary or dynamically updated
zones - there is a test at configuration time to ensure that the
filename is non-unique.

This test is run before the zone is actually created, so a zone
configured using a template may not have had its filename expanded
yet.  This can cause a configuration to fail because, for example,
multiple zones appear to using the filename "$name.db".

This has been fixed by calling dns_zone_expandzonefile() from
isccfg_check_zoneconf(), to expand the names when checking for
uniqueness.

4 weeks agoMake zone filename expansion accessible from outside dns_zone
Mark Andrews [Thu, 2 Apr 2026 04:25:09 +0000 (15:25 +1100)] 
Make zone filename expansion accessible from outside dns_zone

This adds a new API call dns_zone_expandzonefie(), which will enable
named-checkconf to expand filenames the same way the server does in
dns_zone_setfile().

4 weeks agofix: usr: Remove unnecessary dns_name_free call
Mark Andrews [Wed, 15 Apr 2026 01:36:50 +0000 (11:36 +1000)] 
fix: usr: Remove unnecessary dns_name_free call

When processing a catalog zone member's primaries definition and
there is a TXT record containing an invalid name TSIG key name,
dns_name_free was incorrectly called triggering an assertion.
This has been fixed.

Closes #5858

Merge branch '5858-remove-unnecessary-dns-name-free-call' into 'main'

See merge request isc-projects/bind9!11832

4 weeks agoRemove unnecessary dns_name_free call
Mark Andrews [Fri, 10 Apr 2026 03:07:26 +0000 (13:07 +1000)] 
Remove unnecessary dns_name_free call

When processing a catalog zone member's primaries definition and
there is a TXT record containing an invalid name TSIG key name,
dns_name_free was incorrectly called triggering an assertion.
This has been fixed.

4 weeks agoChecking invalid TSIG key name in a catalog zone
Mark Andrews [Fri, 10 Apr 2026 03:05:31 +0000 (13:05 +1000)] 
Checking invalid TSIG key name in a catalog zone

4 weeks agofix: usr: Implement seamless outgoing TCP connection reuse
Ondřej Surý [Tue, 14 Apr 2026 17:29:54 +0000 (19:29 +0200)] 
fix: usr: Implement seamless outgoing TCP connection reuse

The resolver can and will reuse outgoing TCP connections to the same host, as recommended by RFC 7766. This prevents a whole class of attacks that abuse the fact that establishing a TCP connection is expensive and it is fairly easy to deplete the outgoing TCP ports by putting them into TIME_WAIT state.

The number of pipelined queries per connection is capped at 256 to limit the impact of a connection drop.

Merge branch '3741-reuse-tcp-connections' into 'main'

See merge request isc-projects/bind9!11845

4 weeks agoInclude disptype and transport in dispatch hash key
Ondřej Surý [Thu, 9 Apr 2026 15:35:09 +0000 (17:35 +0200)] 
Include disptype and transport in dispatch hash key

Move disptype and transport into dispatch_hash() and dispatch_match()
so that the match function is the single source of truth for whether
two TCP dispatches are interchangeable.  This replaces the post-loop
disptype filter in dispatch_gettcp() and makes the disptype field in
struct dispatch_key actually used.

4 weeks agoDo not reuse shared TCP dispatches for zone transfers
Ondřej Surý [Thu, 19 Mar 2026 04:06:47 +0000 (05:06 +0100)] 
Do not reuse shared TCP dispatches for zone transfers

Zone transfers (XFRIN) need a dedicated TCP connection because they
are long-lived and stream the entire zone.

4 weeks agoUse sequential per-dispatch message IDs for TCP
Ondřej Surý [Sun, 15 Mar 2026 06:52:34 +0000 (07:52 +0100)] 
Use sequential per-dispatch message IDs for TCP

TCP dispentries no longer use the global QID hash table at all.
Responses are matched by scanning disp->active, and sequential
per-dispatch IDs (bounded by the pipelining limit) are unique
within a single dispatch by construction.  Since TCP delivers
only data we asked for on a specific connection, the per-peer
uniqueness that the global table enforced was never actually
needed for TCP.

DNS_DISPATCHOPT_FIXEDID is plumbed through dns_request_createraw
-> get_dispatch -> dns_dispatch_createtcp so FIXEDID TCP requests
always get a fresh isolated dispatch — the caller-supplied ID
then cannot collide with any other in-flight query either.

4 weeks agoLimit TCP pipelining per shared dispatch
Ondřej Surý [Sun, 15 Mar 2026 06:23:33 +0000 (07:23 +0100)] 
Limit TCP pipelining per shared dispatch

Cap the number of in-flight queries on a single shared TCP dispatch.
When the limit is reached, the dispatch is removed from the hash
table so subsequent queries get a fresh connection.  The existing
dispatch continues serving its queries until they complete.

This bounds the blast radius of a connection drop: at most N queries
fail simultaneously instead of all queries to that server.

The default limit is 256.  It can be overridden for testing via
'named -T tcppipelining=N'.

4 weeks agoDisable TCP pipelining in tcp and masterformat system test
Ondřej Surý [Sun, 15 Mar 2026 07:57:26 +0000 (08:57 +0100)] 
Disable TCP pipelining in tcp and masterformat system test

Set tcppipelining=1 on recursive servers in the system tests to
restore one-query-per-connection behavior.  The tests relies on
specific connection and query counting that breaks with TCP
connection sharing.

4 weeks agoImplement seamless TCP connection reuse in dns_dispatch
Ondřej Surý [Tue, 17 Feb 2026 10:05:33 +0000 (11:05 +0100)] 
Implement seamless TCP connection reuse in dns_dispatch

Previously, the user of dns_dispatch API had to first call
dns_dispatch_gettcp() and if that failed create a new TCP dispatch with
dns_dispatch_createtcp().  This has been changed and the TCP connection
reuse happens transparently inside dns_dispatch_createtcp().  There are
separate buckets for dns_resolver, dns_request and dns_xfrin units, so
these don't get mixed together.

4 weeks agofix: usr: Fix 'rndc modzone' issue with non-existing zones
Arаm Sаrgsyаn [Tue, 14 Apr 2026 09:36:17 +0000 (09:36 +0000)] 
fix: usr: Fix 'rndc modzone' issue with non-existing zones

The :iscman:`named` process could terminate unexpectedly or become
subject to undefined behavior when issued an :option:`rndc modzone`
operation for a non-existing zone. This has been fixed.

Closes #5848

Merge branch '5848-do_modzone-unlock-bug-fix' into 'main'

See merge request isc-projects/bind9!11844

4 weeks agoAdd a new check in "addzone" system test
Aram Sargsyan [Mon, 13 Apr 2026 17:00:49 +0000 (17:00 +0000)] 
Add a new check in "addzone" system test

Check that named handles requests to modify non-existing zones
without issues.

4 weeks agoFix a lock/unlock bug in server.c:do_modzone()
Aram Sargsyan [Mon, 13 Apr 2026 16:58:56 +0000 (16:58 +0000)] 
Fix a lock/unlock bug in server.c:do_modzone()

The cleanup path always unlocks the 'view->newzone.lock' lock, but
there are 'goto cleanup;' operations even before the lock is locked,
which causes an assertion failure.

Don't use the cleanup path before the lock is locked.