# Release Notes

## Introduction

BIND 9.20 (Extended Support Version) is a stable branch, suitable for production use. This document summarizes significant changes since the last production release on the 9.18 branch. Please see the Changelog file for a more detailed list of changes and bug fixes.

## Supported Platforms

See the Supported Platforms section in the Resource Requirements chapter.

## Download

The latest versions of BIND 9 software can always be found at https://www.isc.org/download/. There you will find additional information about each release, and source code.

## Known Issues

The list of known issues affecting the latest version in the 9.20 branch can be found at https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.20

## Notes for BIND 9.20.11

### Security Fixes

- Fix a possible assertion failure when `stale-answer-client-timeout` is set to `0`.

  In specific circumstances the `named` resolver process could exit with an assertion failure when stale answers were enabled and the `stale-answer-client-timeout` configuration option was set to `0`. This has been fixed. (CVE-2025-40777) [GL #5372]

### New Features

- Add support for the CO flag to `dig`.

  Add support for Compact Denial of Existence to `dig`. This includes showing the CO (Compact Answers OK) flag when displaying messages and adding an option to set the CO flag when making queries (`dig +coflag`). [GL #5319]

### Bug Fixes

- Correct the default `interface-interval` from 60s to 60m.

  When the `interface-interval` parser was changed from a `uint32` parser to a duration parser, the default value stayed at plain number `60` which now means 60 seconds instead of 60 minutes. The documentation also incorrectly states that the value is in minutes. That has been fixed. [GL #5246]

- Fix a `purge-keys` bug when using multiple views of a zone.

  Previously, when a DNSSEC key was purged by one zone view, other zone views would return an error about missing key files. This has been fixed. [GL #5315]

- Use IPv6 queries in `delv +ns`.

  `delv +ns` invokes the same code to perform name resolution as `named`, but it neglected to set up an IPv6 dispatch object first. Consequently, it was behaving more like `named -4`. It now sets up dispatch objects for both address families, and performs resolver queries to both IPv4 and IPv6 addresses, except when one of the address families has been suppressed by using `delv -4` or `delv -6`. [GL #5352]

## Notes for BIND 9.20.10

### New Features

- Implement a new `notify-defer` configuration option.

  This new option sets a delay (in seconds) to wait before sending a set of `NOTIFY` messages for a zone. Whenever a `NOTIFY` message is ready to be sent, sending is deferred for this duration. This option should not be confused with the `notify-delay` option. The default is 0 seconds. [GL #5259]

### Removed Features

- Implement the systemd notification protocol manually to remove dependency on libsystemd.

### Bug Fixes

- Fix zone deletion issue.

  A secondary zone could initiate a new zone transfer from the primary server after it had been already deleted from the secondary server, and before the internal garbage collection was activated to clean it up completely. This has been fixed. [GL #5291]

- Fix a zone refresh bug.

  A secondary zone could fail to further refresh with new versions of the zone from a primary server if `named` was reconfigured during the SOA request step of an ongoing zone transfer. This has been fixed. [GL #5307]

## Notes for BIND 9.20.9

### Security Fixes

- Prevent an assertion failure when processing TSIG algorithm.

  DNS messages that included a Transaction Signature (TSIG) containing an invalid value in the algorithm field caused `named` to crash with an assertion failure. This has been fixed. (CVE-2025-40775) [GL #5300]

### Feature Changes

- Return DNS COOKIE and NSID with BADVERS.

  This change allows the client to identify a server that returns a BADVERS response and to provide a DNS SERVER COOKIE to be included in the resent request. [GL #5235]

- Disable separate memory context for libxml2 memory allocations on macOS.

  As of macOS Sequoia 15.4, custom memory allocation functions are no longer supported by the system-wide version of libxml2. This prevents tracking libxml2 memory allocations in a separate `named` memory context, so the latter has been disabled on macOS; the system allocator is now directly used for libxml2 memory allocations on that operating system. [GL #5268]

- Use Jinja2 templates in system tests.

  python-jinja2 is now required to run system tests. [GL #4938]

### Bug Fixes

- Revert NSEC3 closest encloser lookup improvements.

  The performance improvements for NSEC3 closest encloser lookups that were restored in BIND 9.20.8 turned out to cause incorrect NSEC3 records to be returned in nonexistence proofs and were therefore reverted again. [GL #5292]

- Fix EDNS YAML output in `dig`.

  `dig` was producing invalid YAML when displaying some EDNS options. This has been corrected.

  Several other improvements have been made to the display of EDNS option data:

  > - The correct name is now used for the UPDATE-LEASE option, which was previously displayed as `UL`, and it is split into separate `LEASE` and `LEASE-KEY` components in YAML mode.

  > - Human-readable durations are now displayed as comments in YAML mode so as not to interfere with machine parsing.

  > - KEY-TAG options are now displayed as an array of integers in YAML mode.

  > - EDNS COOKIE options are displayed as separate `CLIENT` and `SERVER` components, and cookie STATUS is a retrievable variable in YAML mode.

  [GL #5014]

- Fix RDATA checks for PRIVATEOID keys.

  In PRIVATEOID keys, the key data begins with a length byte followed by an ASN.1 object identifier that indicates the cryptographic algorithm to use. Previously, the length byte was not accounted for when checking the contents of keys and signatures, which could have led to interoperability problems with any zones signed using PRIVATEOID. This has been fixed. [GL #5270]

- Fix a serve-stale issue with a delegated zone.

  Even with `stale-answer-client-timeout` set to `0`, stale responses were not returned immediately for names in domains delegated from authoritative zones configured on the resolver. This has been fixed. [GL #5275]

## Notes for BIND 9.20.8

### New Features

- Add support for EDE 20 (Not Authoritative)

  Support was added for EDE codes 20 (Not Authoritative) when the client requests recursion (RD) but the server has recursion disabled.

  RFC 8914 indicates that EDE 20 should also be returned if the client does not have the RD bit set (and recursion is needed), but it does not apply for BIND; BIND would try to resolve from the “deepest” referral in the AUTHORITY section. For example, if the client asks for `www.isc.org/A` but the server only knows the root domain, it will return NOERROR but no answer for `www.isc.org/A`, just the list of other servers to ask. [GL #1836]

- Add support for EDE 7 and EDE 8.

  Support was added for EDE codes 7 (Signature Expired) and 8 (Signature Not Yet Valid), which might occur during DNSSEC validation. [GL #2715]

- `dig` can now display the received BADVERS message during negotiation.

  `dig +showbadvers` now displays the received BADVERS message and continues the EDNS version negotiation. Previously, to see the BADVERS message `dig +noednsnegotiation` had to be specified, which terminated the EDNS negotiation. Additionally, the specified EDNS value (`+edns=value`) is now used when making all the initial queries with `dig +trace`, i.e. EDNS version negotiation is performed with each server when performing the trace. [GL #5234]

- Add an `rndc` command to reset some statistics counters.

  The new `rndc reset-stats` command allows some statistics counters to be reset during runtime. At the moment only two “high-water” counters are supported, so the ability to reset them after the initial peaks during the server’s “warm-up” phase may be useful for some operators. [GL #5251]

### Bug Fixes

- Restore NSEC3 closest-encloser lookup improvements.

  A performance improvement for finding the closest encloser when generating authoritative responses from NSEC3 zones was previously reverted after a bug was found that could trigger an assertion failure. ([GL #4460], [GL #4950], and [GL #5108]) The bug has now been fixed, and the performance improvement has been restored. [GL #5204]

- Stop caching lack of EDNS support.

  `named` could falsely learn that a server did not support EDNS when a spoofed response was received; that subsequently prevented DNSSEC lookups from being made. This has been fixed. [GL #3949] [GL #5066]

- Fix resolver statistics counters for timed-out responses.

  When query responses timed out, the resolver could incorrectly increase the regular response counters, even if no response was received. This has been fixed. [GL #5193]

- Nested DNS validation could cause an assertion failure.

  When multiple nested DNS validations were destroyed out of order, the EDE context could be freed before all EDE codes were copied, which could cause an assertion failure. This has been fixed. [GL #5213]

- Wait for memory reclamation to finish in `named-checkconf`.

  Previously, when `named-checkzone` loaded the zone to the QP database, the delayed memory reclamation could cause an assertion check on exit. This has been fixed. [GL #5220]

- Ensure `max-clients-per-query` is at least `clients-per-query`.

  If the `max-clients-per-query` option is set to a lower value than `clients-per-query`, the value is adjusted to match `clients-per-query`. [GL #5224]

- Fix write after free in validator code.

  Raw integer pointers were being used for the validator’s nvalidations and nfails values, but the memory holding them could be freed while they were still being used. Reference counted counters are now used instead. [GL #5239]

- Don’t enforce NOAUTH/NOCONF flags in DNSKEYs.

  All DNSKEY keys are able to authenticate. The `DNS_KEYTYPE_NOAUTH` (and `DNS_KEYTYPE_NOCONF`) flags were defined for the KEY rdata type, and are not applicable to DNSKEY. Previously, however, because the DNSKEY implementation was built on top of KEY, the `_NOAUTH` flag prevented authentication in DNSKEYs as well. This has been corrected. [GL #5240]

- Fix several small DNSSEC timing issues.

  The following small issues related to `dnssec-policy` have been fixed:

  - In some cases the key manager inside BIND 9 would run every hour, while in other cases it would run less often.

  - While `CDS` and `CDNSKEY` records will be removed correctly from the zone when the corresponding `DS` record needs to be updated, the expected timing metadata for when this should happen was never set.

  - There were a couple of cases where the safety intervals were added inappropriately, delaying key rollovers longer than necessary.

  - Identical keys in a `dnssec-policy` may have been retired inappropriately. Note that having keys with identical properties is discouraged in all cases.

  [GL #5242]

- Fix inconsistency in CNAME/DNAME handling during resolution.

  Previously, in some cases, the resolver could return rdatasets of type CNAME or DNAME without the result code being set to `DNS_R_CNAME` or `DNS_R_DNAME`. This could trigger an assertion failure. This has been fixed. [GL #5201]

## Notes for BIND 9.20.7

### New Features

- Implement the `min-transfer-rate-in` configuration option.

  A new option `min-transfer-rate-in` has been added to the view and zone configurations. It can abort incoming zone transfers that run very slowly due to network-related issues, for example. The default value is 10240 bytes in five minutes. [GL #3914]

- Add HTTPS record query to `host` command line tool.

  The `host` command was extended to also query for the HTTPS RR type by default.

- Implement `sig0key-checks-limit` and `sig0message-checks-limit`.

  Previously, a hard-coded limitation of a maximum of two key or message verification checks was introduced when checking a message’s `SIG(0)` signature, to protect against possible DoS attacks. Two as a maximum was chosen so that more than a single key should only be required during key rotations, and in that case two keys are enough. It later became apparent that there are other use cases where even more keys are required; see the related GitLab issue for examples.

  This change introduces two new configuration options for the views: `sig0key-checks-limit` and `sig0message-checks-limit`. They define how many keys can be checked to find a matching key, and how many message verifications are allowed to take place once a matching key has been found. The former provides slightly less “expensive” key parsing operations and defaults to 16. The latter protects against expensive cryptographic operations when there are keys with colliding tags and algorithm numbers; the default is 2. [GL #5050]

### Bug Fixes

- Fix `dual-stack-servers` configuration option.

  The `dual-stack-servers` configuration option was not working as expected; the specified servers were not being used when they should have been, leading to resolution failures. This has been fixed. [GL #5019]

- Fix a data race causing a permanent active client increase.

  Previously, a data race could cause a newly created fetch context for a new client to be used before it had been fully initialized, which would cause the query to become stuck; queries for the same data would be either paused indefinitely or dropped because of the `clients-per-query` limit. This has been fixed. [GL #5053]

- Fix deferred validation of unsigned DS and DNSKEY records.

  When processing a query with the “checking disabled” bit set (CD=1), `named` stores the invalidated result in the cache, marked “pending”. When the same query is sent with CD=0, the cached data is validated and either accepted as an answer, or ejected from the cache as invalid. This deferred validation was not attempted for DS and DNSKEY records if they had no cached signatures, causing spurious validation failures. The deferred validation is now completed in this scenario.

  Also, if deferred validation fails, the data is now re-queried to find out whether the zone has been corrected since the invalid data was cached. [GL #5066]

- Fix RPZ race condition during a reconfiguration.

  With RPZ in use, `named` could terminate unexpectedly because of a race condition when a reconfiguration command was received using `rndc`. This has been fixed. [GL #5146]

- “CNAME and other data check” not applied to all types.

  An incorrect optimization caused “CNAME and other data” errors not to be detected if certain types were at the same node as a CNAME. This has been fixed. [GL #5150]

- Relax private DNSKEY and RRSIG constraints.

  DNSKEY, KEY, RRSIG, and SIG constraints have been relaxed to allow empty key and signature material after the algorithm identifier for PRIVATEOID and PRIVATEDNS. It is arguable whether this falls within the expected use of these types, as no key material is shared and the signatures are ineffective, but these are private algorithms and they can be totally insecure. [GL #5167]

- Remove NSEC/DS/NSEC3 RRSIG check from `dns_message_parse()`.

  Previously, when parsing responses, `named` incorrectly rejected responses without matching RRSIG records for NSEC/DS/NSEC3 records in the authority section. This rejection, if appropriate, should have been left for the validator to determine and has been fixed. [GL #5185]

- Fix TTL issue with ANY queries processed through RPZ “passthru”.

  Answers to an “ANY” query which were processed by the RPZ “passthru” policy had the response-policy’s `max-policy-ttl` value unexpectedly applied. This has been fixed. [GL #5187]

- `dnssec-signzone` needs to check for a NULL key when setting offline.

  `dnssec-signzone` could dereference a NULL key pointer when resigning a zone. This has been fixed. [GL #5192]

- Fix a bug in the statistics channel when querying zone transfer information.

  When querying zone transfer information from the statistics channel, there was a rare possibility that `named` could terminate unexpectedly if a zone transfer was in a state when transferring from all the available primary servers had failed earlier. This has been fixed. [GL #5198]

- Fix assertion failure when dumping recursing clients.

  Previously, if a new counter was added to the hash table while dumping recursing clients via the `rndc recursing` command, and `fetches-per-zone` was enabled, an assertion failure could occur. This has been fixed. [GL #5200]

- Dump the active resolver fetches from `dns_resolver_dumpfetches()`

  Previously, active resolver fetches were only dumped when the `fetches-per-zone` configuration option was enabled. Now, active resolver fetches are dumped along with the number of `clients-per-query` counters per resolver fetch.

## Notes for BIND 9.20.6

### New Features

- Adds support for EDE code 1 and 2.

  Support was added for EDE codes 1 and 2, which might occur during DNSSEC validation in the case of an unsupported RRSIG algorithm or DNSKEY digest. [GL #2715]

- Add an `rndc` command to toggle jemalloc profiling.

  The new command is `rndc memprof`; the memory profiling status is also reported inside `rndc status`. The status shows whether `named` can toggle memory profiling, and whether the server is built with jemalloc. [GL #4759]

- Add support for multiple extended DNS errors.

  The Extended DNS Error (EDE) mechanism may raise errors during a DNS resolution. `named` is now able to add up to three EDE codes in a DNS response. If there are duplicate error codes, only the first one is part of the DNS response. [GL #5085]

- Print the expiration time of stale records.

  BIND now prints the expiration time of any stale RRsets in the cache dump.

### Bug Fixes

- Recently expired records could be returned with a timestamp in future.

  Under rare circumstances, an RRSet that expired at the time of the query could be returned with a TTL in the future. This has been fixed.

  As a side effect, the expiration time of expired RRSets is no longer returned in a cache dump. [GL #5094]

- YAML string not terminated in negative response in delv.

  [GL #5098]

- Fix a bug in `dnssec-signzone` related to keys being offline.

  When `dnssec-signzone` was called on an already-signed zone and the private key file was unavailable, a signature that needed to be refreshed was dropped without being able to generate a replacement. This has been fixed. [GL #5126]

- Apply the memory limit only to ADB database items.

  Under heavy load, a resolver could exhaust the memory available for storing the information in the Address Database (ADB), effectively discarding previously stored information in the ADB. The memory used to retrieve and provide information from the ADB is no longer subject to the same memory limits that are applied to the Address Database. [GL #5127]

- Avoid unnecessary locking in the zone/cache database.

  Lock contention among many worker threads referring to the same database node at the same time is now prevented. This improves zone and cache database performance for any heavily contended database nodes. [GL #5130]

- Fix reporting of Extended DNS Error 22 (No Reachable Authority).

  This error code was previously not reported in some applicable situations. This has been fixed. [GL #5137]

## Notes for BIND 9.20.5

### Security Fixes

- DNS-over-HTTPS flooding fixes. (CVE-2024-12705)

  Fix DNS-over-HTTPS implementation issues that arise under heavy query load. Optimize resource usage for `named` instances that accept queries over DNS-over-HTTPS.

  Previously, `named` processed all incoming HTTP/2 data at once, which could overwhelm the server, especially when dealing with clients that sent requests but did not wait for responses. That has been fixed. Now, `named` handles HTTP/2 data in smaller chunks and throttles reading until the remote side reads the response data. It also throttles clients that send too many requests at once.

  In addition, `named` now evaluates excessive streams opened by clients that include no DNS data, which is considered “flooding.” It logs these clients and drops connections from them. [GL #4795]

  In some cases, `named` could leave DNS-over-HTTPS connections in the CLOSE_WAIT state indefinitely. That has also been fixed. [GL #5083]

  ISC would like to thank Jean-François Billaud for his assistance with investigating this issue.

- Limit additional section processing for large RDATA sets. (CVE-2024-11187)

  When answering queries, don’t add data to the additional section if the answer has more than 13 names in the RDATA. This limits the number of lookups into the database(s) during a single client query, reducing the query-processing load. [GL #5034]

  ISC would like to thank Toshifumi Sakaguchi for bringing this vulnerability to our attention.

### New Features

- Add Extended DNS Error Code 22 - No Reachable Authority.

  When the resolver is trying to query an authoritative server and eventually times out, a SERVFAIL answer is given to the client. Add the Extended DNS Error Code 22 - No Reachable Authority to the response. [GL #2268]

- Add a new option to configure the maximum number of outgoing queries per client request.

  The configuration option `max-query-count` sets how many outgoing queries per client request are allowed. The existing `max-recursion-queries` value is the number of permissible queries for a single name and is reset on every CNAME redirection. This new option is a global limit on the client request. The default is 200.

  The default for `max-recursion-queries` is changed from 32 to 50. This allows `named` to send a few more queries while looking up a single name. [GL #4980] [GL #4921]

- Use the Server Name Indication (SNI) extension for all outgoing TLS connections.

  This improves compatibility with other DNS server software. [GL #5099]

### Feature Changes

- Performance optimization for NSEC3 lookups introduced in BIND 9.20.2 was reverted to avoid risks associated with a complex code change. [GL #5108]

- The configuration clauses `parental-agents` and `primaries` are renamed to `remote-servers`.

  The top blocks `primaries` and `parental-agents` are no longer preferred and should be renamed to `remote-servers`. The zone statements `parental-agents` and `primaries` are still used, and may refer to any `remote-servers` top block. [GL #4544]

- Add none parameter to `query-source` and `query-source-v6` to disable IPv4 or IPv6 upstream queries but allow listening to queries from clients on IPv4 or IPv6. [GL #4981]

### Bug Fixes

- Fix `nsupdate` hang when processing a large update.

  To mitigate DNS flood attacks over a single TCP connection, throttle the connection when the other side does not read the data. Throttling should only occur on server-side sockets, but erroneously also happened for `nsupdate`, which acts as a client. When `nsupdate` started throttling the connection, it never attempted to read again. This has been fixed. [GL #4910]

- Fix possible assertion failure when reloading server while processing update policy rules. [GL #5006]

- Preserve cache across reconfig when using `attach-cache`.

  When the `attach-cache` option is used in the `options` block with an arbitrary name, it causes all views to use the same cache. Previously, this configuration caused the cache to be deleted and a new cache to be created every time the server was reconfigured. This has been fixed. [GL #5061]

- Resolve the spurious drops in performance due to glue cache.

  For performance reasons, the returned glue records are cached on the first use. The current implementation could randomly cause a performance drop and increased memory use. This has been fixed. [GL #5064]

- Fix `dnssec-signzone` signing non-DNSKEY RRsets with revoked keys.

  `dnssec-signzone` was using revoked keys for signing RRsets other than DNSKEY. This has been corrected. [GL #5070]

- Fix improper handling of unknown directives in `resolv.conf`.

  The line after an unknown directive in `resolv.conf` could accidentally be skipped, potentially affecting `dig`, `host`, `nslookup`, `nsupdate`, or `delv`. This has been fixed. [GL #5084]

- Fix response policy zones and catalog zones with an `$INCLUDE` statement defined.

  Response policy zones (RPZ) and catalog zones were not working correctly if they had an `$INCLUDE` statement defined. This has been fixed. [GL #5111]

## Notes for BIND 9.20.4

### New Features

- Update built-in `bind.keys` file with the new 2025 IANA root key.

  Add an initial-ds entry to `bind.keys` for the new root key, ID 38696, which is scheduled for publication in January 2025. [GL #4896]

### Removed Features

- Move contributed DLZ modules into a separate repository. DLZ modules should not be used except in testing.

  The DLZ modules were not maintained, the DLZ interface itself is going to be scheduled for removal, and the DLZ interface is blocking. Any module that blocks the query to the `database` blocks the whole server.

  The DLZ modules now live in https://gitlab.isc.org/isc-projects/dlz-modules repository. [GL #4865]

### Feature Changes

- `dnssec-ksr` now supports KSK rollovers.

  The tool now allows for KSK generation, as well as planned KSK rollovers. When signing a bundle from a Key Signing Request (KSR), only the key that is active in that time frame is used for signing. Also, the CDS and CDNSKEY records are now added and removed at the correct time. [GL #4697] [GL #4705]

- Print RFC 7314: EXPIRE option in transfer summary. [GL #5013]

- Emit more helpful log messages for exceeding `max-records-per-type`.

  The new log message is emitted when adding or updating an RRset fails due to exceeding the `max-records-per-type` limit. The log includes the owner name and type, corresponding zone name, and the limit value. It will be emitted on loading a zone file, inbound zone transfer (both AXFR and IXFR), handling a DDNS update, or updating a cache DB. It’s especially helpful in the case of zone transfer, since the secondary side doesn’t have direct access to the offending zone data.

  It could also be used for `max-types-per-name`, but this change doesn’t implement it yet as it’s much less likely to happen in practice.

- Harden key management when key files have become unavailable.

  Prior to doing key management, BIND 9 will check if the key files on disk match the expected keys. If key files for previously observed keys have become unavailable, this will prevent the internal key manager from running.

### Bug Fixes

- Use TLS for notifies if configured to do so.

  Notifies configured to use TLS will now be sent over TLS, instead of plain text UDP or TCP. Also, failing to load the TLS configuration for `notify` now results in an error. [GL #4821]

- {&dns} is as valid as {?dns} in a SVCB’s dohpath.

  `dig` failed to parse a valid SVCB record with a dohpath URI template containing a {&dns}, like dohpath=/some/path?key=value{&dns}”. [GL #4922]

- Fix NSEC3 closest encloser lookup for names with empty non-terminals.

  A previous performance optimization for finding the NSEC3 closest encloser when generating authoritative responses could cause servers to return incorrect NSEC3 records in some cases. This has been fixed. [GL #4950]

- `recursive-clients` statement with value 0 triggered an assertion failure.

  BIND 9.20.0 broke recursive-clients 0;. This has now been fixed. [GL #4987]

- Parsing of hostnames in `rndc.conf` was broken.

  When DSCP support was removed, parsing of hostnames in `rndc.conf` was accidentally broken, resulting in an assertion failure. This has been fixed. [GL #4991]

- `dig` options of the form [+-]option=<value> failed to display the value on the printed command line. This has been fixed. [GL #4993]

- Provide more visibility into TLS configuration errors by logging SSL_CTX_use_certificate_chain_file() and SSL_CTX_use_PrivateKey_file() errors individually. [GL #5008]

- Fix a race condition when canceling ADB find which could cause an assertion failure. [GL #5024]

- SERVFAIL cache memory cleaning is now more aggressive; it no longer consumes a lot of memory if the server encounters many SERVFAILs at once. [GL #5025]

- Fix trying the next primary XoT server when the previous one was marked as unreachable.

  In some cases `named` failed to try the next primary server in the `primaries` list when the previous one was marked as unreachable. This has been fixed. [GL #5038]

## Notes for BIND 9.20.3

### New Features

- Log query response status to the query log.

  Log a query response summary using the new `responses` category. Logging can be controlled via the `responselog` option and via `rndc responselog`. [GL #459]

- Added WALLET type.

  Add the new record type WALLET (262). This provides a mapping from a domain name to a cryptographic currency wallet. Multiple mappings can exist if multiple records exist. [GL #4947]

### Feature Changes

- Set logging category for `notify`/`xfer-in`-related messages.

  Some `notify` and `xfer-in`-related log messages were logged at the “general” category level instead of their own category. This has been fixed. [GL #2730]

- Allow IXFR-to-AXFR fallback on `DNS_R_TOOMANYRECORDS`.

  This change allows fallback from an IXFR failure to AXFR when the reason is `DNS_R_TOOMANYRECORDS`. [GL #4928]

### Bug Fixes

- Fix a statistics channel counter bug when “forward only” zones are used.

  When resolving a zone with a “forward only” policy, and finding out that all the forwarders were marked as “bad”, the “ServerQuota” counter of the statistics channel was incorrectly increased. This has been fixed. [GL #1793]

- Fix a bug in the static-stub implementation.

  Static-stub addresses and addresses from other sources were being mixed together, resulting in static-stub queries going to addresses not specified in the configuration, or alternatively, static-stub addresses being used instead of the correct server addresses. [GL #4850]

- Don’t allow `statistics-channels` if libxml2 and libjson-c are not configured.

  When BIND 9 is not configured with the libxml2 and libjson-c libraries, the use of the `statistics-channels` option is a fatal error. [GL #4895]

- Separate DNSSEC validation from long-running tasks.

  Split CPU-intensive and long-running tasks into separate threadpools in a way that the long-running tasks - like RPZ, catalog zone processing, or zone file operations - don’t block CPU-intensive operations like DNSSEC validations. [GL #4898]

- Fix an assertion failure when processing access control lists.

  The `named` process could terminate unexpectedly when processing ACLs. This has been fixed. [GL #4908]

- Fix a bug in Offline KSK using a ZSK with an unlimited lifetime.

  If the ZSK had an unlimited lifetime, the timing metadata `Inactive` and `Delete` could not be found and were treated as an error, preventing the zone from being signed. This has been fixed. [GL #4914]

- Limit the outgoing UDP send queue size.

  If the operating system UDP queue got full and the outgoing UDP sending started to be delayed, BIND 9 could exhibit memory spikes as it tried to enqueue all the outgoing UDP messages. It now tries to deliver the outgoing UDP messages synchronously; if that fails, it drops the outgoing DNS message that would get queued up and then timeout on the client side. [GL #4930]

- Do not set `SO_INCOMING_CPU`.

  Remove the `SO_INCOMING_CPU` setting as kernel scheduling performs better without constraints. [GL #4936]

- Fix the `rndc dumpdb` command’s error reporting.

  The `rndc dumpdb` command was not reporting errors that occurred when `named` started up the database dump process. This has been fixed. [GL #4944]

- Fix long-running incoming transfers.

  Incoming transfers that took longer than 30 seconds would stop reading from the TCP stream and the incoming transfer would be indefinitely stuck, causing BIND 9 to hang during shutdown.

  This has been fixed, and the `max-transfer-time-in` and `max-transfer-idle-in` timeouts are now honored. [GL #4949]

- Fix an assertion failure when receiving DNS responses over TCP.

  When matching the received Query ID in the TCP connection, an invalid Query ID could cause an assertion failure. This has been fixed. [GL #4952]

### Known Issues

- There are no new known issues with this release. See above for a list of all known issues affecting this BIND 9 branch.

## Notes for BIND 9.20.2

### New Features

- Support for Offline KSK implemented.

  Add a new configuration option `offline-ksk` to enable Offline KSK key management. Signed Key Response (SKR) files created with `dnssec-ksr` (or other programs) can now be imported into `named` with the new `rndc skr -import` command. Rather than creating new DNSKEY, CDS, and CDNSKEY records and generating signatures covering these types, these records are loaded from the currently active bundle from the imported SKR.

  The implementation is loosely based on draft-icann-dnssec-keymgmt-01.txt. [GL #1128]

- Print the full path of the working directory in startup log messages.

  `named` now prints its initial working directory during startup, and the changed working directory when loading or reloading its configuration file, if it has a valid `directory` option defined. [GL #4731]

- Support a restricted key tag range when generating new keys.

  When multiple signers are being used to sign a zone, it is useful to be able to specify a restricted range of key tags to be used by an operator to sign the zone. The range can be specified with `tag-range` in `dnssec-policy`’s keys (for `named` and `dnssec-ksr`) and with the new options `dnssec-keyfromlabel -M` and `dnssec-keygen -M`. [GL #4830]

### Feature Changes

- Exempt prefetches from the `fetches-per-zone` and `fetches-per-server` quotas.

  Fetches generated automatically as a result of `prefetch` are now exempt from the `fetches-per-zone` and `fetches-per-server` quotas. This should help in maintaining the cache from which query responses can be given. [GL #4219]

- Improve performance for queries that require an NSEC3 wildcard proof.

  Rather than starting from the longest matching part of the requested name, lookup the shortest partial match. Most of the time this will be the actual closest encloser. [GL #4460]

- Follow the number of CPUs set by `taskset`/`cpuset`.

  Administrators may wish to constrain the set of cores that `named` runs on via the `taskset`, `cpuset`, or `numactl` programs (or equivalents on other OSes).

  If the admin has used `taskset`, `named` now automatically uses the given number of CPUs rather than the system-wide count. [GL #4884]

### Bug Fixes

- Delay the release of root privileges until after configuring controls.

  Delay relinquishing root privileges until the control channel has been configured, for the benefit of systems that require root to use privileged port numbers. This mostly affects systems without fine- grained privilege systems (i.e., other than Linux). [GL #4793]

- Fix a rare assertion failure when shutting down incoming transfer.

  A very rare assertion failure could be triggered when the incoming transfer was either forcefully shut down, or it finished during the printing of the details about the statistics channel. This has been fixed. [GL #4860]

- Fix algorithm rollover bug when there are two keys with the same keytag.

  If there was an algorithm rollover and two keys of different algorithms shared the same keytags, there was the possibility that the check of whether the key matched a specific state could be performed against the wrong key. This has been fixed by not only checking for the matching key tag but also the key algorithm. [GL #4878]

- Fix an assertion failure in `validate_dnskey_dsset_done()`.

  Under rare circumstances, `named` could terminate unexpectedly when validating a DNSKEY resource record if the validation had been canceled in the meantime. This has been fixed. [GL #4911]

### Known Issues

- Long-running tasks in offloaded threads (e.g. the loading of RPZ zones or processing zone transfers) may block the resolution of queries during these operations and cause the queries to time out.

  To work around the issue, the `UV_THREADPOOL_SIZE` environment variable can be set to a larger value before starting `named`. The recommended value is the number of RPZ zones (or number of transfers) plus the number of threads BIND should use, which is typically the number of CPUs. [GL #4898]

## Notes for BIND 9.20.1

### New Features

- Implement `rndc retransfer -force`.

  A new optional argument `-force` has been added to the command `rndc retransfer`. When it is specified, `named` aborts the ongoing zone transfer (if there is one) and starts a new transfer. [GL #2299] [GL !9219]

- `dig` now reports a missing QUESTION section for messages with opcode QUERY.

  Query responses should contain the QUESTION section, with some exceptions. `dig` was not reporting this. [GL #4808] [GL !9269]

### Feature Changes

- Tighten `max-recursion-queries` and add `max-query-restarts` configuration statement.

  There were cases when the `max-recursion-queries` quota was ineffective. It was possible to craft zones that would cause a resolver to waste resources by sending excessive queries while attempting to resolve a name. This has been addressed by correcting errors in the implementation of `max-recursion-queries` and by reducing the default value from 100 to 32.

  In addition, a new `max-query-restarts` configuration statement has been added, which limits the number of times a recursive server will follow CNAME or DNAME records before terminating resolution. This was previously a hard-coded limit of 16 but is now configurable with a default value of 11.

  ISC would like to thank Huayi Duan, Marco Bearzi, Jodok Vieli, and Cagin Tanir from NetSec group, ETH Zurich for discovering and notifying us about the issue. [GL #4741] [GL !9282]

- Allow shorter `resolver-query-timeout` configuration.

  The minimum allowed value of `resolver-query-timeout` was lowered from its previous value of 10 000 milliseconds (which is still the default) to 301 milliseconds. Note however that values of 1 to 300 inclusive are interpreted as seconds before applying the limit. A value of zero is interpreted as the default. [GL #4320] [GL !9220]

- Raise the log level of priming failures.

  When a priming query is complete, it was previously logged at level `DEBUG(1)`, regardless of success or failure. It is now logged to `NOTICE` in the case of failure. [GL #3516] [GL !9250]

### Bug Fixes

- Fix a crash caused by valid TSIG signatures with invalid time.

  An assertion failure was triggered when the TSIG had a valid cryptographic signature but the time was invalid. This could happen when the times between the primary and secondary servers were not synchronised. The crash has now been fixed. [GL #4811] [GL !9245]

- Return SERVFAIL for a too long CNAME chain.

  When following long CNAME chains, `named` was returning NOERROR (along with a partial answer) instead of SERVFAIL, if the chain exceeded the maximum length. This has been fixed. [GL #4449] [GL !9203]

- Reconfigure catz member zones during `named` reconfiguration.

  During a reconfiguration, `named` wasn’t reconfiguring catalog zones’ member zones. This has been fixed. [GL #4733]

- Update key lifetime and metadata after `dnssec-policy` reconfiguration.

  Adjust key state and timing metadata if `dnssec-policy` key lifetime configuration is updated, so that it also affects existing keys. [GL #4677] [GL !9191]

- Fix a crash during zone modification.

  Fix an assertion failure that could happen when an authoritative zone was modified while the server was generating an answer from that zone. [GL #4691] [GL !9126]

- Fix assertion failure when executing `named-checkconf -v` to print its version. [GL #4827] [GL !9246]

- Fix generation of 6to4-self name expansion from IPv4 address.

  The period between the most significant nibble of the encoded IPv4 address and the 2.0.0.2.IP6.ARPA suffix was missing, resulting in the wrong name being checked. This has been fixed. [GL #4766] [GL !9217]

- `dig +yaml` was producing unexpected and/or invalid YAML. output. [GL #4796] [GL !9213]

- SVBC ALPN text parsing failed to reject zero-length ALPN. [GL #4775] [GL !9209]

- Fix false QNAME minimisation error being reported.

  Remove the false positive `success resolving` log message when QNAME minimisation is in effect and the final result is an NXDOMAIN. [GL #4784] [GL !9215]

- Fix `--enable-tracing` build on systems without dtrace.

  A missing `util/dtrace.sh` file prevented builds on systems without the `dtrace` utility. This has been corrected. [GL #4835] [GL !9272]

### Known Issues

- There are no new known issues with this release. See above for a list of all known issues affecting this BIND 9 branch.

## Notes for BIND 9.20.0

Note

This section only lists changes since BIND 9.18.28, the most recent release on the previous stable branch of BIND at the time of the publication of BIND 9.20.0.

### New Features

- The `forwarders` statement now supports the `tls` argument, to be used to forward queries to DoT-enabled servers. [GL #3726]

- `named` now supports forwarding Dynamic DNS updates through DNS-over-TLS (DoT). [GL #3512]

- The `nsupdate` tool now supports DNS-over-TLS (DoT). [GL !6752]

- The `tls` block was extended with a new `cipher-suites` option that allows permitted cipher suites for TLSv1.3 to be set. Please consult the documentation for additional details. [GL #3504]

- Initial support for the PROXYv2 protocol was added. `named` can now accept PROXYv2 headers over all currently implemented DNS transports and `dig` can insert these headers into the queries it sends. Please consult the related documentation (`allow-proxy`, `allow-proxy-on`, `listen-on`, and `listen-on-v6` for `named`, `dig +proxy` and `dig +proxy-plain` for `dig`) for additional details. [GL #4388]

- The client-side support of the EDNS EXPIRE option has been expanded to include IXFR and AXFR query types. This enhancement enables `named` to perform AXFR and IXFR queries while incorporating the EDNS EXPIRE option. [GL #4170]

- A new configuration option `require-cookie` has been introduced. It specifies whether there should be a DNS COOKIE in the response for a given prefix; if not, `named` falls back to TCP. This is useful if it is known that a given server supports DNS COOKIE. It can also be used to force all non-DNS COOKIE responses to fall back to TCP. [GL #2295]

- The `check-svcb` option has been added to control the checking of additional constraints on SVCB records. This change affects `named`, `named-checkconf`, `named-checkzone`, `named-compilezone`, and `nsupdate`. [GL #3576]

- The new `resolver-use-dns64` option enables `named` to apply `dns64` rules to IPv4 server addresses when sending recursive queries, so that resolution can be performed over a NAT64 connection. [GL #608]

- A new option to `dnssec-policy` has been added, `cdnskey`, that allows users to enable or disable the publication of CDNSKEY records. [GL #4050]

- When using `dnssec-policy`, it is now possible to configure the digest type to use when CDS records need to be published with `cds-digest-types`. Also, publication of specific CDNSKEY/CDS records can now be set with `dnssec-signzone -G`. [GL #3837]

- Support for multi-signer model 2 (RFC 8901) when using `inline-signing` was added. [GL #2710]

- HSM support was added to `dnssec-policy`. Keys can now be configured with a `key-store` that allows users to set the directory where key files are stored and to set a PKCS#11 URI string. The latter requires OpenSSL 3 and a valid PKCS#11 provider to be configured for OpenSSL. [GL #1129]

- A new DNSSEC tool `dnssec-ksr` has been added to create Key Signing Request (KSR) and Signed Key Response (SKR) files. [GL #1128]

- `dnssec-verify` and `dnssec-signzone` now accept a `-J` option to specify a journal file to read when loading the zone to be verified or signed. [GL #2486]

- `dnssec-keygen` now allows the options `-k` and `-f` to be used together. This allows the creation of keys for a given `dnssec-policy` that match only the KSK (`-fK`) or ZSK (`-fZ`) roles. [GL #1128]

- The `response-policy` statement was extended with a new argument `ede`. It enables an RFC 8914 Extended DNS Error (EDE) code of choice to be set for responses which have been modified by a given RPZ. [GL #3410]

- A new way of configuring the preferred source address when talking to remote servers, such as `primaries` and `parental-agents`, has been added: setting the `source` and/or `source-v6` arguments for a given statement is now possible. This new approach is intended to eventually replace statements such as `parental-source`, `parental-source-v6`, `transfer-source`, etc. [GL #3762]

- The new command-line `delv +ns` option activates name server mode, to more accurately reproduce the behavior of `named` when resolving a query. In this mode, `delv` uses an internal recursive resolver rather than an external server. All messages sent and received during the resolution and validation process are logged. This can be used in place of `dig +trace`. [GL #3842]

- The read timeout in `rndc` can now be specified on the command line using the `-t` option, allowing commands that take a long time to complete sufficient time to do so. [GL #4046]

- The statistics channel now includes information about incoming zone transfers that are currently in progress. [GL #3883]

- Information on incoming zone transfers in the statistics channel now also shows the zones’ “first refresh” flag, which indicates that a zone is not fully ready and that its first ever refresh is pending or is in progress. The number of such zones is now also exposed by the `rndc status` command. [GL #4241]

- Added a new statistics variable `recursive high-water` that reports the maximum number of simultaneous recursive clients BIND has handled while running. [GL #4668]

- A new command, `rndc fetchlimit`, prints a list of name server addresses that are currently rate-limited due to `fetches-per-server` and domain names that are rate-limited due to `fetches-per-zone`. [GL #665]

- Queries and responses now emit distinct dnstap entries for DNS-over-TLS (DoT) and DNS-over-HTTPS (DoH), and `dnstap-read` understands these entries. [GL #4523]

- `dnstap-read` can now print long timestamps with millisecond precision. [GL #2360]

- Support for libsystemd’s `sd_notify()` function was added, enabling `named` to report its status to the init system. This allows systemd to wait until `named` is fully ready before starting other services that depend on name resolution. [GL #1176]

- Support for User Statically Defined Tracing (USDT) probes has been added. These probes enable fine-grained application tracing and introduce no overhead when they are not enabled. [GL #4041]

### Removed Features

- Support for Red Hat Enterprise Linux version 7 (and clones) has been dropped. A C11-compliant compiler is now required to compile BIND 9. [GL #3729]

- Compiling with jemalloc versions older than 4.0.0 is no longer supported; those versions do not provide the features required by current BIND 9 releases. [GL #4296]

- The `auto-dnssec` configuration statement has been removed. Please use `dnssec-policy` or manual signing instead. See article how to migrate from `auto-dnssec` to `dnssec-policy`.

  The following statements have become obsolete: `dnskey-sig-validity`, `dnssec-dnskey-kskonly`, `dnssec-update-mode`, `sig-validity-interval`, and `update-check-ksk`. [GL #3672]

- Dynamic updates that add and remove DNSKEY and NSEC3PARAM records no longer trigger key rollovers and denial-of-existence operations. This also means that the `dnssec-secure-to-insecure` option has been obsoleted. [GL #3686]

- The `glue-cache` option has been removed. The glue cache feature still works and is now permanently enabled. [GL #2147]

- Configuring the control channel to use a Unix domain socket has been a fatal error since BIND 9.18. The feature has now been completely removed and `named-checkconf` now reports it as a configuration error. [GL #4311]

- The statements setting alternate local addresses for inbound zone transfers (`alt-transfer-source`, `alt-transfer-source-v6`, and `use-alt-transfer-source`) have been removed. [GL #3714]

- The `resolver-nonbackoff-tries` and `resolver-retry-interval` statements have been removed. Using them is now a fatal error. [GL #4405]

- BIND 9 no longer supports non-zero `stale-answer-client-timeout` values, when the feature is turned on. When using a non-zero value, `named` now generates a warning log message, and treats the value as `0`. [GL #4447]

- The Differentiated Services Code Point (DSCP) feature has been removed: configuring DSCP values in `named.conf` is now a configuration error. [GL #3789]

- The `keep-response-order` option has been declared obsolete and the functionality has been removed. `named` expects DNS clients to be fully compliant with RFC 7766. [GL #3140]

- Zone type `delegation-only`, and the `delegation-only` and `root-delegation-only` statements, have been removed. Using them is a configuration error.

  These statements were created to address the SiteFinder controversy, in which certain top-level domains redirected misspelled queries to other sites instead of returning NXDOMAIN responses. Since top-level domains are now DNSSEC-signed, and DNSSEC validation is active by default, the statements are no longer needed. [GL #3953]

- The `coresize`, `datasize`, `files`, and `stacksize` options have been removed. The limits these options set should be enforced externally, either by manual configuration (e.g. using `ulimit`) or via the process supervisor (e.g. `systemd`). [GL #3676]

- Support for using AES as the DNS COOKIE algorithm (`cookie-algorithm aes;`) has been removed. The only supported DNS COOKIE algorithm is now the current default, SipHash-2-4. [GL #4421]

- The TKEY Mode 2 (Diffie-Hellman Exchanged Keying Mode) has been removed and using TKEY Mode 2 is now a fatal error. Users are advised to switch to TKEY Mode 3 (GSS-API). [GL #3905]

- Special-case code that was originally added to allow GSS-TSIG to work around bugs in the Windows 2000 version of Active Directory has now been removed, since Windows 2000 is long past end-of-life. The `-o` option and the `oldgsstsig` command to `nsupdate` have been deprecated, and are now treated as synonyms for `-g` and `gsstsig` respectively. [GL #4012]

- Support for the `lock-file` statement and the `named -X` command-line option has been removed. An external process supervisor should be used instead. [GL #4391]

  Alternatively, the `flock` utility (part of util-linux) can be used on Linux systems to achieve the same effect as `lock-file` or `named -X`:

      flock -n -x <directory>/named.lock <path>/named <arguments>

- The `named` command-line option `-U`, which specified the number of UDP dispatches, has been removed. Using it now returns a warning. [GL #1879]

- The `--with-tuning` option for `configure` has been removed. Each of the compile-time settings that required different values based on the “workload” (which were previously affected by the value of the `--with-tuning` option) has either been removed or changed to a sensible default. [GL #3664]

- The functions that were in the `libbind9` shared library have been moved to the `libisc` and `libisccfg` libraries. The now-empty `libbind9` has been removed and is no longer installed. [GL #3903]

- The `irs_resconf` module has been moved to the `libdns` shared library. The now-empty `libirs` library has been removed and is no longer installed. [GL #3904]

### Deprecated Features

Features listed in this section still work but are scheduled for eventual removal.

- The use of the `max-zone-ttl` option in `options` and `zone` blocks has been deprecated; it should now be configured as part of `dnssec-policy`. A warning is logged if this option is used in `options` or `zone` blocks. In a future release, it will become nonoperational. [GL #2918]

- The `sortlist` option has been deprecated and will be removed in a future BIND 9.21.x release. Users should not rely on a specific order of resource records in DNS messages. [GL #4593]

- The `fixed` value for the `rrset-order` option and the corresponding `configure` script option have been deprecated and will be removed in a future BIND 9.21.x release. Users should not rely on a specific order of resource records in DNS messages. [GL #4446]

### Feature Changes

- BIND now depends on liburcu, Userspace RCU, for lock-free data structures. [GL #3934]

- On Linux, libcap is now a required dependency to help `named` keep needed privileges. [GL #3583]

- Compiling BIND 9 now requires at least libuv version 1.34.0 or higher. libuv should be available on all supported platforms either as a native package or as a backport. [GL #3567]

- Outgoing zone transfers are no longer enabled by default. An explicit `allow-transfer` ACL must now be set at the `zone`, `view`, or `options` level to enable outgoing transfers. [GL #4728]

- DNS zones signed using `dnssec-policy` now automatically detect their parent servers, and BIND queries them to check the content of the DS RRset. This allows DNSSEC key rollovers to safely and automatically proceed when the parent zone is updated with new DNSSEC keys, i.e. using the CDS/CDNSKEY mechanism. This behavior is facilitated by the new `checkds` feature, which automatically populates `parental-agents` by resolving the parent NS records. These parent name servers are queried to check the DS RRset during a KSK rollover initiated by `dnssec-policy`. [GL #3901]

- The responsiveness of `named` was improved, when serving as an authoritative DNS server for a delegation-heavy zone(s) shortly after loading such zone(s). [GL #4045]

- To improve query-processing latency under load, the uninterrupted time spent on resolving long chains of cached domain names has been reduced. [GL #4185]

- QNAME minimization is now used when looking up the addresses of name servers during the recursive resolution process. [GL #4209]

- BIND now returns BADCOOKIE for out-of-date or otherwise bad but well-formed DNS server cookies. [GL #4194]

- The DNS name compression algorithm used in BIND 9 has been revised: it now compresses more thoroughly than before, so responses containing names with many labels might have a smaller encoding than before. [GL #3661]

- Processing large incremental transfers (IXFR) has been offloaded to a separate work thread so that it does not prevent networking threads from processing regular traffic in the meantime. [GL #4367]

- Querying the statistics channel no longer blocks DNS communication on the networking event loop level. [GL #4680]

- The `inline-signing` zone option is now ignored if there is no `dnssec-policy` configured for the zone. This means that unsigned zones no longer create redundant signed versions of the zone. [GL #4349]

- The `inline-signing` statement can now also be set inside `dnssec-policy`. The default is to use `inline-signing`. This also applies to the built-in policies `default` and ``insecure`. If `inline-signing` is set at the `zone` level, it overrides the value set in `dnssec-policy`. [GL #3677]

- Due to the change in default value from `no` to `yes`, DNSSEC-enabled dynamic zones that do not have `inline-signing` explicitly set must now add the option to their configuration with the value `no` if they do not want their zone also to be inline-signed.

- Following RFC 9276 recommendations, `dnssec-policy` now only allows an NSEC3 iteration count of 0 for the DNSSEC-signed zones using NSEC3 that the policy manages. [GL #4363]

- The maximum number of NSEC3 iterations allowed for validation purposes has been lowered from 150 to 50. DNSSEC responses containing NSEC3 records with iteration counts greater than 50 are now treated as insecure. [GL #4363]

- The `dnssec-validation yes` option now requires an explicitly configured `trust-anchors` statement. If using manual trust anchors is not operationally required, then please consider using `dnssec-validation auto` instead. [GL #4373]

- `named-compilezone` no longer performs zone integrity checks by default; this allows faster conversion of a zone file from one format to another. [GL #4364]

  Zone checks can be performed by running `named-checkzone` separately, or the previous default behavior can be restored by using:

      named-compilezone -i full -k fail -n fail -r warn -m warn -M warn -S warn -T warn -W warn -C check-svcb:fail

- The red-black tree data structure used in the RBTDB (the default database implementation for cache and zone databases), has been replaced with QP-tries. This is expected to improve performance and scalability, though in the current implementation large zones require roughly 15% more memory than the old red-black tree data structure.

  A side effect of this change is that zone files that are created with `masterfile-style` `relative` - for example, the output of `dnssec-signzone` - will no longer have multiple different $ORIGIN statements. There should be no other changes to server behavior.

  The old RBT-based database still exists for now, and can be used by specifying `database rbt` in a `zone` statement in `named.conf`, or by compiling with `configure --with-zonedb=rbt --with-cachedb=rbt`. [GL #4411] [GL #4614]

- Multiple RNDC messages are now processed when sent in a single TCP message.

  ISC would like to thank Dominik Thalhammer for reporting the issue and preparing the initial patch. [GL #4416]

- The DNSSEC signing data included in zone statistics identified keys only by the key ID; this caused confusion when two keys using different algorithms had the same ID. Zone statistics now identify keys using the algorithm number, followed by “+”, followed by the key ID: for example, `8+54274`. [GL #3525]

- The TTL of the NSEC3PARAM record for every NSEC3-signed zone was previously set to 0. It is now changed to match the SOA MINIMUM value for the given zone. [GL #3570]

- On startup, `named` now sets the limit on the number of open files to the maximum allowed by the operating system, instead of trying to set it to “unlimited”. [GL #3676]

- When an international domain name is not valid according to IDNA2008, `dig` now tries to convert it according to IDNA2003 rules, or pass it through unchanged, instead of stopping with an error message. The `idna2` utility can be used to check IDNA syntax. [GL #3527]

- The memory statistics have been reduced to a single counter, `InUse`; `Malloced` is an alias that holds the same value. The other counters were usable with the old BIND 9 internal memory allocator, but they are unnecessary now that the latter has been removed. [GL #3718]

- The log message `resolver priming query complete` has been moved from the INFO log level to the DEBUG(1) log level, to prevent `delv` from emitting that message when setting up its internal resolver. [GL #3842]

- Worker threads’ event loops are now managed by a new “loop manager” API, significantly changing the architecture of the task, timer, and networking subsystems for improved performance and code flow. [GL #3508]

- The code for DNS over TCP and DNS over TLS transports has been replaced with a new, unified transport implementation. [GL #3374]

### Bug Fixes

- When the same `notify-source` address and port number was configured for multiple destinations and zones, an unresponsive server could tie up the relevant network socket until it timed out; in the meantime, NOTIFY messages for other servers silently failed. `named` will now retry sending such NOTIFY messages over TCP. Furthermore, NOTIFY failures are now logged at the INFO level. [GL #4001] [GL #4002]

- DNS compression is no longer applied to the root name (`.`) if it is repeatedly used in the same RRset. [GL #3423]

- `named` could incorrectly return non-truncated, glueless referrals for responses whose size was close to the UDP packet size limit. This has been fixed. [GL #1967]

### Known Issues

- On some platforms, including FreeBSD, `named` must be run as root to use the `rndc` control channel on a privileged port (i.e., with a port number less than 1024; this includes the default `rndc` `port`, 953). Currently, using the `named -u` option to switch to an unprivileged user makes `rndc` unusable. This will be fixed in a future release; in the meantime, `mac_portacl` can be used as a workaround, as documented in https://kb.isc.org/docs/aa-00621. [GL #4793]

- See above for a list of all known issues affecting this BIND 9 branch.

## License

BIND 9 is open source software licensed under the terms of the Mozilla Public License, version 2.0 (see the `COPYING` file for the full text).

Those wishing to discuss license compliance may contact ISC at https://www.isc.org/contact/.

## End of Life

BIND 9.20 (Extended Support Version) will be supported until at least March, 2028. See https://kb.isc.org/docs/aa-00896 for details of ISC’s software support policy.

## Thank You

Thank you to everyone who assisted us in making this release possible.