Commit graph

3149 commits

Author SHA1 Message Date
Andoni Duarte
6cae1d10ca Merge tag 'v9.21.22'
Some checks are pending
CodeQL / Analyze (push) Waiting to run
SonarCloud / Build and analyze (push) Waiting to run
2026-05-20 10:26:28 +00:00
Ondřej Surý
5c8dcd4419
Fix use-after-free in concurrent dns_tsigkey_delete()
Two TSIG-authenticated TKEY DELETE queries for the same dynamic key,
arriving on different worker loops, could each enter
dns_tsigkey_delete() and cause over-decrementing the key refcount.

This has been fixed by making dns_tsigkey_delete() idempotent.
2026-05-17 17:14:08 +02:00
Ondřej Surý
28483b3b73
Drop in-domain NS without glue from the delegation set
Pull the dns_message_findname() lookups into cache_delegglue() and
cache_delegglue6() so each helper now owns its glue lookup and returns
the number of addresses cached.  cache_delegns() splits referrals into
two cases: in-domain (the NS name is below the delegation point) and
sibling/in-bailiwick.

An in-domain NS without glue is unresolvable by definition - the
resolver would have to ask the very server it's trying to find.  Log
"missing mandatory glue" at notice level and skip the deleg entirely
rather than leaving an unusable entry in the set.  A new
dns_delegset_freedeleg() undoes a fresh dns_delegset_allocdeleg() so
the rest of the delegation set is preserved.
2026-05-15 07:26:38 +02:00
Ondřej Surý
11bca1051f
Switch UDP fetches to TCP on the first response with a wrong query id
Until now, the dispatcher silently dropped UDP responses from the
expected peer that carried the wrong DNS message id and kept listening
for the correct id to arrive within the read timeout.  An off-path
attacker who knows the destination address and source port of an
outgoing fetch could exploit that quiet retry window to flood the
resolver with guessed responses; with a gigabit link the per-query
success probability grows linearly with the number of guesses that
arrive before the legitimate answer or the timeout.

Treat any such mismatch as a possible spoofing attempt and let the
resolver immediately retry the same query over TCP, the same control
path the truncation handler already uses.

Add a resolver statistics counter - exposed as 'queries retried over TCP
after a response with mismatched query id' in rndc stats and
'MismatchTCP' in the statistics channel

Assisted-by: Claude:claude-opus-4-7
2026-05-14 15:56:18 +02:00
Alessio Podda
52edb98e3c Delay binding glue to rdataset
The dns_glue struct currently contains four dns_rdataset structs to hold
the glue. These structs are over 100 bytes each because they need to be
able to hold data for multiple types of databases.

Since the dns_glue_t type is only used by qpzone, we can instead hold
pointers to the vecheaders directly, and only bind the vecheaders to
the rdatasets when adding the glue to the message.
2026-05-11 10:28:20 +02:00
Alessio Podda
d7a5a2e86b Make dns_glue_t private to qpzone
The dns_glue_t, dns_gluelist_t and dns_glue_additionaldata_ctx types are
only used in qpzone.c. This commits moves them to the private header
qpzone_p.h.

This is done in preparation of a followup commit that will refactor them
to use types that are private to qpzone.
2026-05-11 10:22:25 +02:00
Ondřej Surý
51dde6ef43
Fix GSS-API context leak in TKEY negotiation
Reject multi-round GSS-API negotiation (GSS_S_CONTINUE_NEEDED) in
dst_gssapi_acceptctx().  Each call to gss_accept_sec_context()
allocates a context inside the GSS library; without this fix, the
context handle was passed back to process_gsstkey() which did not
store it persistently, leaking it on every incomplete negotiation.

An unauthenticated attacker could exhaust server memory by sending
repeated TKEY queries with GSSAPI tokens, each leaking one GSS
context.  The leaked memory is allocated by the GSS library via
malloc(), bypassing BIND's memory accounting.

In practice, Kerberos/SPNEGO (the only mechanism used with BIND)
completes in a single round, so rejecting continuation does not
affect real-world deployments.  See RFC 3645 Section 4.1.3.
2026-05-07 13:32:15 +02:00
Colin Vidal
e986b19d0d
Limit the number of addresses returned per ADB find
The number of `dns_adbaddrfind_t` (NS address with metadata like SRTT)
returned from an ADB NS name lookup is now limited by the caller. The
default value (outside the resolver) uses `max-delegation-servers`, and
the resolver, for a given fetch, start with `max-delegation-servers` and
decrement it at each ADB fetch. This ensures that, for a given
delegation, no more than 13 nameservers will be contacted.

This is the same mechanism used when looking up `dns_adbaddrfind_t` from
a list of glues (addresses).
2026-05-07 13:32:15 +02:00
Mark Andrews
cd96894bcd
Remove remaining RFC 3445 KEY flags
RFC 3445 also eliminated the DNS_KEYTYPE_NOAUTH, DNS_KEYTYPE_NOCONF,
and DNS_KEYOWNER_ENTITY flags. With NOAUTH and NOCONF gone, the
concept of NOKEY can no longer be expressed in KEY records.

DNS_KEYOWNER_ENTITY was already unused as of 22d688f656 but still
defined; that is now also removed.
2026-05-05 10:17:31 +02:00
Evan Hunt
9c06f0a41d
Remove DNS_KEYFLAG_EXTENDED
The DNS_KEYFLAG_EXTENDED flag was only legitimate for type KEY
and was eliminated by RFC 3445. Dropping the extended-flags
handling in pub_compare() also fixes a possible crash when
signing a zone whose journal contains a crafted DNSKEY: a
6-byte record with the EXTENDED bit set produced a memmove()
length that underflowed and ran off a stack buffer.
2026-05-05 10:16:02 +02:00
Ondřej Surý
746fb28369
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
2026-04-29 15:08:20 +02:00
Ondřej Surý
0c007d8659
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.
2026-04-16 13:39:18 +02:00
Colin Vidal
1d10e4513f 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.
2026-04-16 11:28:13 +02:00
Ondřej Surý
876a896f0f 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.
2026-04-16 11:28:13 +02:00
Mark Andrews
20f8e9eb56 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().
2026-04-14 21:49:59 -07:00
Ondřej Surý
d5ee86b799
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.
2026-04-14 17:48:13 +02:00
Mark Andrews
e43e4bd20a Use the correct maximal compressed bit map buffer size
There are up to 256 windows in a NSEC/NSEC3 compressed bit
map of 32 + 2 octets each.
2026-04-10 15:45:01 +10:00
Matthijs Mekking
9c420582be Move dns_zone_next/dns_zone_first to zonemgr
Walking the list of managed zones is a function that operates
on the zone manager object.
2026-04-08 14:27:06 +02:00
Matthijs Mekking
a320801042 Move three more functions to zoneproperties.c
Move the following functions to the zoneproperties source files, as
they are simple get functions:
- dns_zone_getgluecachestats
- dns_zone_getkeystores
- dns_zone_getrequesttransporttype
2026-04-08 14:24:17 +02:00
Matthijs Mekking
080e849eaa Move zonemgr to own source file
In order to make zone.c more readable, we are splitting it up in
separate source files. This moves the zonemgr to its own file
("zonemgr.c").

Since this code accesses the zone structure directly, move the
'struct dns_zonemgr' and its prerequisites to "zone_p.h".

The helper functions 'forward_cancel()', 'zone_xfrdone()',
'zmgr_start_xfrin_ifquota()', and 'zmgr_resume_xfrs() need to be
internally accessible to both source files.

Note: This commit does not compile.
2026-04-08 14:24:17 +02:00
Ondřej Surý
14cebe4d61 Change NSEC3 and NSEC3PARAM struct fields to use isc_region_t
Replace the separate pointer+length field pairs in dns_rdata_nsec3_t
(salt/salt_length, next/next_length, typebits/len) and
dns_rdata_nsec3param_t (salt/salt_length) with isc_region_t.  This
makes the structs self-describing and eliminates a class of
length-mismatch bugs.

The dns_zone_setnsec3param() signature is updated to take
isc_region_t *salt instead of separate saltlen and salt arguments.

Function signatures for dns_nsec3_addnsec3, dns_db_getnsec3parameters,
and related internal functions still use separate pointer+length pairs
and should be updated in a follow-up.
2026-04-02 16:53:18 +02:00
Matthijs Mekking
93376b8f67 Return void in functions that cannot fail
dns_zone_getloadtime(), dns_zone_getexpiretime(),
dns_zone_getrefreshtime(), and dns_zone_getrefreshkeytime()
cannot fail, so return void instead of ISC_R_SUCCESS.
2026-04-02 15:50:09 +02:00
Matthijs Mekking
f015170ec7 Fix some documentation issues
dns_zone_setorigin() does not return ISC_R_SUCCESS, but void.

dns_zone_setalsonotify() referred to non-existing
dns_zone_alsonotifywithkeys().
2026-04-02 15:50:09 +02:00
Matthijs Mekking
f04590d006 Remove unneccesary functions
Remove dns_zone_getmem() (duplicate of dns_zone_getmctx()).
Remove dns_zone_getrdclass() (duplicate of dns_zone_getclass()).
Remove obsoleted dns_zone_getstatscounters().
Remove obsoleted dns_zone_setstatistics().
2026-04-02 15:50:09 +02:00
Matthijs Mekking
2893e128a7 Move zone set/get properties to own source file
In order to make zone.c more readable, we are splitting it up in
separate source files. This moves the set and get functions to its
own file ("zoneproperties.c").

Since this code accesses the zone structure directly, move the
'struct dns_zone' and its prerequisites to "zone_p.h".

The helper functions 'inline_raw()', 'inline_secure()',
'dns_zone_setview_helper()', 'zone_settimer(), 'set_resigntime()', and
'zone_freedbargs()' need to be internally accessible to both source
files.

A few set/get functions remain in zone.c for now:
- dns_zone_getserial
- dns_zone_getversion
- dns_zone_setviewcommit
- dns_zone_setviewrevert
- dns_zone_get_rpz_num
- dns_zone_set_parentcatz
- dns_zone_get_parentcatz
- dns_zone_setrawdata
- dns_zone_setskr
- dns_zone_getskrbundle
- dns_zone_setnsec3param
- dns_zone_setoption
- dns_zone_getoptions
- dns_zone_getrequesttransporttype
- dns_zone_getredirecttype
- dns__zone_getnotifyctx
- dns_zone_getgluecachestats
- dns_zone_setplugins
- dns_zone_setserial
- dns_zone_getxfr
- dns_zone_getkeystores
2026-04-02 15:50:07 +02:00
Matthijs Mekking
e1bd1a4003 Introduce zone functions dns_zone_(get|set)modded
Introduce new functions to set and get whether the zone configuration
has been modified with 'rndc modzone'.
2026-04-02 12:35:54 +00:00
Alessio Podda
6202492509 Remove node and db pointer from dns_rdataset_t.vec
Now that we track the references at the vecheader level, binding an
rdataset is no longer guaranteed to keep its node alive. Therefore
remove the node pointer from the rdataset, and instead decide whether
glue is required by explicitely passing the owner name to addglue.
2026-03-31 16:22:56 +02:00
Alessio Podda
3521900ecd Add hashmap to qpz_heap
This commit adds a level of indirection to the signing operations.
Instead of being intrusive, the qpz_heap will keep track of which
headers must be resigned through a hashmap.
The intent is to make dns_vecheader_t entirely self-contained. In
particular, the ownership structure between the heap and the headers is
flipped. Before, the headers would "own" the heap, now the heap owns
the header.
2026-03-31 16:22:56 +02:00
Alessio Podda
1aa0768151 Refactor setsigningtime
Change setsigningtime to take the node of the header being changed.
Done to facilitate further refactoring that will remove the header
pointer from vecheader.
2026-03-31 16:22:56 +02:00
Ondřej Surý
9e40f6508c Remove the dead dns_expire_ttl code path and deletettl stats counter
Now that TTL-based cleaning has been removed, the dns_expire_ttl enum
value, its switch case in expireheader(), and the deletettl stats counter
(text, XML, JSON) are all dead code.  Remove them so the stats channel
no longer reports a permanently-zero counter.
2026-03-30 21:46:44 +02:00
Ondřej Surý
dc9564f14d Raise the minimum cache size to 8 MB, warn below 256 MB
Lower the hard floor for max-cache-size from 2 MB to 8 MB to support
resource-constrained environments (e.g. CPE devices) while remaining
safe for LRU-only eviction.
2026-03-30 21:46:44 +02:00
Ondřej Surý
6fa415f71f Refactor the 'max-cache-size' configuration handling
Extract the inline max-cache-size logic from configure_view() into
reusable helpers: configure_max_cache_size(), default_max_cache_size(),
max_cache_size_as_percent(), and sanitized_max_cache_size().

Move DNS_CACHE_MINSIZE and DNS_ADB_MINADBSIZE to public headers and
remove the SIZE_AS_PERCENT sentinel.
2026-03-30 21:46:44 +02:00
Ondřej Surý
d7c99c14fc Remove 'unlimited' setting for the max-cache-size
Since TTL-based cache cleaning has been removed, an unlimited
max-cache-size would eventually exhaust system memory.

Both 'max-cache-size unlimited;' and 'max-cache-size 0;' now fall
back to the default value (90% of physical memory for recursive
views).
2026-03-30 21:46:44 +02:00
Ondřej Surý
602f5b73e6 Remove TTL-based cleaning from the QPcache
The experiments show that the SIEVE-LRU based mechanism is good enough
as the only mechanism for cleaning up the expired entries from the
cache.

This simplifies the internal logic and memory usage of the cache.

The disadvantage is that the cache use will organically grow until it
hits the overmem cleaning mechanism.

The advantage is that the measurements show that BIND 9 is well behaved
even with 512 MB cache under heavy load.
2026-03-30 21:46:44 +02:00
Ondřej Surý
08a33a9cc9 Remove useless .expire initialization from rdataslab
dns_rdataslab_fromrdataset() set .expire to rdataset->ttl, but the
only consumer (qpcache_addrdataset) immediately overwrote it with
now + rdataset->ttl.  Remove the redundant initialization and set the
expire time only once.
2026-03-30 21:46:44 +02:00
Evan Hunt
dc6202479f remove find_deepest_zonecut() from qpcache
because the cache no longer stores delegation (parent-side) NS rrsets,
and authoritative (child-side) NS rrsets don't affect recursion,
it no longer makes sense for qpcache_find() to look for NS rrsets
and return DNS_R_DELEGATION. that code has been removed.

the cache still does search for covering DNAME records. the
check_zonecut() function has been renamed to check_dname() for clarity.

related changes:
- one test case has been removed from the mirror system test, because it
  tested the behavior of a cached delegation.
- query_checkrrl() and rpz_rrset_find() have been updated so they no
  longer expect cache responses to have DNS_R_DELEGATION response codes.
2026-03-30 20:41:13 +02:00
Colin Vidal
6ed7a8a723 Resolver is parent-centric
The resolver now uses glue addresses from `dns_deleg_t` objects stored
in the delegation database.  The main cache is still used for ADB A/AAAA
lookups when no glue is available for a nameserver name.

The resolver's `fctx_getaddresses()` is refactored to, for each
delegation of the delegation set, try to get the address-based finds,
then nameserver name lookups. (Later, the logic to handle DELEG
`include-delegparm=` will be hooked there too.)
2026-03-30 20:41:13 +02:00
Colin Vidal
cfac5f3974 Add dns_adb_createaddrinfosfind() for address-based lookups
Add a new ADB API function that creates a find from a list of addresses
rather than by looking up nameserver names.  This enables the resolver
to handle address-based delegations (NS-based with glues or DELEG with
addresses) and name-based delegations uniformly (i.e. the list of finds
from ADB is handled the same way no matter the type of the delegation).
2026-03-30 20:41:13 +02:00
Evan Hunt
a9883483ef Remove dns_db_findzonecut()
This function is no longer used and has been removed, along with its
implementation in qpcache.
2026-03-30 20:41:13 +02:00
Colin Vidal
de8bc44dc8 Use delegation DB for bestzonecut lookups
Function `dns_view_bestzonecut()` now uses the delegation DB instead of
the main cache when looking up at the cache.

As a result, replace `dns_rdataset_t` (representing an NS RRset) with
`dns_delegset_t` in `dns_view_bestzonecut()` and
`dns_resolver_createfetch()` APIs. The resolver and query processing now
use the delegation DB instead of the cache for zonecut lookups.

In the case of the delegation lives in the local database, the locally
found `rdataset` is internally converted into a `dns_delegset_t` object.
From caller POV, it doesn't change anything: a delegation set is a
read-only object which can be used as long as needed and must be
detached one it's done with it.
2026-03-30 20:41:13 +02:00
Colin Vidal
c7b75f448f Populate the delegation DB from referrals answers
The resolver now caches NS records and their A/AAAA glues from referral
answers into the delegation database.

A new `cache_delegns()` function extracts NS names and associated glue
addresses from the authority/additional sections of a referral answer
and use those informations to build a delegation set, which is then
inserted into the delegation database.

The created delegation set contains a delegation per NS RR. If the NS RR
has matching A/AAAA RR, the delegation only store the addresses and not
the name. (Note this is technically possible to group all NS RR which
doesn't have glues into a single delegation, and the implementation can
be changed in that way in the future).

Each view has its own instance of the delegation database (they are
never shared between views), but a server restart/reload preserve the
delegation database state.
2026-03-30 20:41:13 +02:00
Colin Vidal
1b5f757084 Introduce a delegation database
Add `dns_delegdb_t`, a qpmulti-based database enabling to lookup a
delegation set (`dns_delegset_t`) from a zonecut name (`dns_name_t`). A
delegation set object essentially contains an expiration time and a list
of delegation (`dns_deleg_t`). Finally, a delegation can be either:

- A list of IP addresses (`isc_netaddrlist_t`), for NS-based delegation
  providing glues or DELEG-based delegation using `server-ipv4=` or
  `server-ipv6=`;
- Or a list of nameserver names, for NS-based delegation without glues,
  or DELEG-based delegation using `server-name=`;
- Or a list of nameserver names, for DELEG-based delegation using
  `include-delegparam=`.

The delegation database API provides lookup by closest zonecut,
delegation and delegation set builders as well as insertion of those
newly built delegation set, dumping to a `FILE *`, conversion from an NS
rdataset to a delegation set, deletion of a specific zonecut or all the
sub-tree of a given zonecut.

A memory context is internally used inside the delegation database and
can be constraint to a maximum size. Once it gets close to its maximum
size and a new delegation set is inserted into the database, a
reclamation flow is run internally removing the least recently used
entries.

The delegation set and delegation objects are, once they been inserted
into the database, read-only object. Thus, the caller can use them
without concurrency or locking concerns, and must detached them once its
done with it.
2026-03-30 20:41:13 +02:00
Alessio Podda
ed0ecb62e4 Add low contention stats counter
In the current statistics counter implementation, the statistics are
backed by an array of counters, which are updated via atomic operations.
This leads to contention, especially on high core count
machines.

This commit introduces a new isc_statsmulti_t counter that keeps a
separate array per thread. These counters are then aggregated only when
statistics are queried, shifting work off the critical path.

These changes lead to a ~2% improvement in perflab.
2026-03-26 10:19:25 +01:00
Mark Andrews
ed15b6cb26 Add switch to disable cookie checking in delv
This adds the switch +[no]cookie to delv to control the sending of
DNS COOKIE options when sending requests.  The default is to send
DNS COOKIE options.
2026-03-26 11:18:26 +11:00
Michał Kępień
b0fc0e31c5 Merge tag 'v9.21.20' 2026-03-25 14:23:41 +00:00
Aram Sargsyan
4ac3a6520e Convert dns_dtenv_t reference counting to standard macors
Use standard reference counting macros for dns_dtenv_t instead of
custom attach/detach functions.
2026-03-18 16:10:07 +00:00
Ondřej Surý
7f8b972a3d
Remove NZF support, make LMDB required for new zone storage
Drop the NZF (New Zone File) fallback for persisting runtime zone
configurations, making LMDB (NZD) the only storage backend. This
removes all #ifdef HAVE_LMDB conditionals, the meson 'lmdb' option,
and the NZF-related functions. LMDB is now a mandatory build
dependency.

The named-nzd2nzf tool is now always built.
2026-03-18 11:02:33 +01:00
Matthijs Mekking
0ec08c2120
Don't verify already trusted rdatasets
If we already marked an rdataset as secure (or it has even stronger
trust), there is no need to cryptographically verify it again.
2026-03-13 13:03:33 +01:00
Ondřej Surý
c1ba80169c
Introduce max-delegation-servers configuration option
Make the maximum number of processed delegation nameservers configurable
via the new 'max-delegation-servers' option (default: 13), replacing the
hardcoded NS_PROCESSING_LIMIT (20).

The default is reduced to 13 to precisely match the maximum number of
root servers that can fit into a classic 512-byte UDP payload.  This
provides a natural, historically sound cap that mitigates resource
exhaustion and amplification attacks from artificially inflated or
misconfigured delegations.

The configuration option is strictly bounded between 1 and 100 to ensure
resolver stability.
2026-03-04 16:13:49 +01:00
Michal Nowak
239464f276
Use clang-format-22 to update formatting 2026-03-04 10:56:41 +01:00