Commit Graph
9728 Commits
Author SHA1 Message Date
Mark Andrews 7289d291bf Send and check grease queries
Grease queries exercise otherwise unexercised parts of the DNS
protocol.
2025-03-06 14:22:36 +11:00
Mark Andrews ca184670a2 Add grease controls to the view structure 2025-03-06 14:16:23 +11:00
Mark Andrews dbe6a64971 Add peer controls for grease extensions 2025-03-06 14:16:23 +11:00
Ondřej Surý 1e4695510a Revert "fix: dev: Delete dead nodes when committing a new version"
This reverts commit 67255da4b3, reversing
changes made to 74c9ff384e.
2025-03-05 17:46:54 +01:00
Aram Sargsyan 6cd9e4f67c Fix a bug in get_request_transport_type()
When dns_remote_done() is true, calling dns_remote_curraddr() asserts.
Add a dns_remote_curraddr() check before calling dns_remote_curraddr().
2025-03-05 12:18:11 +00:00
Ondřej Surý 552cf64a70 Replace isc_mem_destroy() with isc_mem_detach()
Remove legacy isc_mem_destroy() and just use isc_mem_detach() as
isc_mem_destroy() doesn't play well with call_rcu API.
2025-03-05 11:17:17 +01:00
Mark Andrews 006c5990ce Implement digest_sig and digest_rrsig for ZONEMD
ZONEMD needs to be able to digest SIG and RRSIG records.  The signer
field can be compressed in SIG so we need to call dns_name_digest().
While for RRSIG the records the signer field is not compressed the
canonical form has the signer field downcased (RFC 4034, 6.2).  This
also implies that compare_rrsig needs to downcase the signer field
during comparison.
2025-03-05 18:05:12 +11:00
Ondřej SurýandEvan Hunt 303c20caf8 Fix the foundname vs dcname madness in qpcache_findzonecut()
The qpcache_findzonecut() accepts two "foundnames": 'foundname' and
'dcname' could be NULL.  Originally, when 'dcname' would be NULL, the
'dcname' would be set to 'foundname'.  Then code like this was present:

    result = find_deepest_zonecut(&search, node, nodep, foundname,
                                  rdataset,
                                  sigrdataset DNS__DB_FLARG_PASS);
    dns_name_copy(foundname, dcname);

Which basically means that we are copying the .ndata over itself for no
apparent reason.  Cleanup the dcname vs foundname usage.

Co-authored-by: Evan Hunt <each@isc.org>
Co-authored-by: Ondřej Surý <ondrej@isc.org>
2025-03-05 07:49:46 +01:00
alessio 87776a51ae Cleanup dns_opcode_t
Make dns_opcode_t refer directly to the underlying enum, and use
attributes to ensure the underlying enum is the same size as uint16_t.
2025-03-04 18:35:14 +01:00
Ondřej Surý c5075a9a61 Remove convenience list macros from isc/util.h
The short convenience list macros were used very sparingly and
inconsistenly in the code base.  As the consistency is prefered over
the convenience, all shortened list macro were removed in favor of
their ISC_LIST API targets.
2025-03-01 07:33:40 +01:00
Ondřej Surý 2aa70fff76 Remove unused isc_mutexblock and isc_condition units
The isc_mutexblock and isc_condition units were no longer in use and
were removed.
2025-03-01 07:33:09 +01:00
Aram Sargsyan 7293cb0612 Fix a bug in dns_zone_getprimaryaddr()
When all the addresses were already iterated over, the
dns_remote_curraddr() function asserts. So before calling it,
dns_zone_getprimaryaddr() now checks the address list using the
dns_remote_done() function. This also means that instead of
returning 'isc_sockaddr_t' it now returns 'isc_result_t' and
writes the primary's address into the provided pointer only when
returning success.
2025-02-28 15:33:37 +00:00
Evan Hunt 9ebeb60174 fix the fetchresponse result for CNAME/DNAME
the fix in commit 1edbbc32b4 was incomplete; the wrong
event result could also be set in cache_name() and validated().
2025-02-27 19:00:27 +00:00
Aydın Mercan f4ab4f07e3 unify fips handling to isc_crypto and make the toggle one way
Since algorithm fetching is handled purely in libisc, FIPS mode toggling
can be purely done in within the library instead of provider fetching in
the binary for OpenSSL >=3.0.

Disabling FIPS mode isn't a realistic requirement and isn't done
anywhere in the codebase. Make the FIPS mode toggle enable-only to
reflect the situation.
2025-02-27 17:37:43 +03:00
Evan Hunt 1edbbc32b4 set eresult based on the type in ncache_adderesult()
when the caching of a negative record failed because of the
presence of a positive one, ncache_adderesult() could override
this to ISC_R_SUCCESS. this could cause CNAME and DNAME responses
to be handled incorrectly.  ncache_adderesult() now sets the result
code correctly in such cases.
2025-02-25 21:29:19 -08:00
Evan Hunt 6c2af2ae3b remove 'target' from dns_adb
the target name parameter to dns_adb_createfind() was always passed as
NULL, so we can safely remove it.

relatedly, the 'target' field in the dns_adbname structure was never
referenced after being set.  the 'expire_target' field was used, but
only as a way to check whether an ADB name represents a CNAME or DNAME,
and that information can be stored as a single flag.
2025-02-26 00:43:21 +00:00
Mark Andrews f98a8331aa Fix dual-stack-servers
Named was stopping nameserver address resolution attempts too soon
when dual stack servers are configured.  Dual stack servers are
used when there are *not* addresses for the server in a particular
address family so find->status == DNS_ADB_NOMOREADDRESSES is not a
sufficient stopping condition when dual stack servers are available.
Call fctx_try to see if the alternate servers can be used.
2025-02-25 23:47:46 +00:00
Mark Andrews b048190e23 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.
2025-02-25 22:59:46 +00:00
Evan Hunt 2f7e6eb019 allow NULL compression context in dns_name_towire()
passing NULL as the compression context to dns_name_towire()
copies the uncompressed name data directly into the target buffer.
2025-02-25 12:53:25 -08:00
Evan Hunt afb424c9b6 simplify dns_name_fromtext() interface
previously, dns_name_fromtext() took both a target name and an
optional target buffer parameter, which could override the name's
dedicated buffer. this interface is unnecessarily complex.

we now have two functions, dns_name_fromtext() to convert text
into a dns_name that has a dedicated buffer, and dns_name_wirefromtext()
to convert text into uncompressed DNS wire format and append it to a
target buffer.

in cases where it really is necessary to have both, we can use
dns_name_fromtext() to load the dns_name, then dns_name_towire()
to append the wire format to the target buffer.
2025-02-25 12:53:25 -08:00
Evan Hunt a6986f6837 remove 'target' parameter from dns_name_concatenate()
the target buffer passed to dns_name_concatenate() was never
used (except for one place in dig, where it wasn't actually
needed, and has already been removed in a prior commit).
we can safely remove the parameter.
2025-02-25 12:53:25 -08:00
Evan Hunt 2edefbad4a remove the 'name_coff' parameter in dns_name_towire()
this parameter was added as a (minor) optimization for
cases where dns_name_towire() is run repeatedly with the
same compression context, as when rendering all of the rdatas
in an rdataset. it is currently only used in one place.

we now simplify the interface by removing the extra parameter.
the compression offset value is now part of the compression
context, and can be activated when needed by calling
dns_compress_setmultiuse(). multiuse mode is automatically
deactivated by any subsequent call to dns_compress_permitted().
2025-02-25 12:53:25 -08:00
Evan Hunt 94a96a7a0e save time when creating a slab from another slab
the dns_rdataslab_fromrdataset() function creates a slab
from an rdataset. if the source rdataset already uses a slab,
then no processing is necessary; we can just copy the existing
slab to a new location.
2025-02-25 18:37:35 +00:00
Ondřej Surý 1e4fb53c61 Destroy the hashmap iterator inside the rwlock
Previously, the hashmap iterator for fetches-per-zone was destroy
outside the rwlock.  This could lead to an assertion failure due to a
timing race with the internal rehashing of the hashmap table as the
rehashing process requires no iterators to be running when rehashing the
hashmap table.  This has been fixed by moving the destruction of the
iterator inside the read locked section.
2025-02-25 13:36:37 +01:00
Ondřej Surý 67e1df1a07 Squash set_offsets() and dns_name_offsets() into single function
The third argument to set_offsets() was only used in
dns_name_fromregion() and not really needed.  We can remove the third
argument and then manually check whether the last label is root label.
2025-02-25 12:17:34 +01:00
Ondřej Surý 79c3871a7b Remove target buffer from dns_name_downcase()
There was just a single use of passing an extra buffer to
dns_name_downcase() which have been replaced by simple call to
isc_ascii_lowercase() and the 'target' argument from dns_name_downcase()
function has been removed.
2025-02-25 12:17:34 +01:00
Ondřej Surý 3bb47bc6cd Remove MAKE_EMPTY() macro from dns_name unit
The MAKE_EMPTY() macro was clearing up the output variable in case of
the failure.  However, this was breaking the usual design pattern that
the output variables are left in indeterminate state or we don't touch
them at all when a failure occurs.  Remove the macro and change the
dns_name_downcase() to not touch the name contents until success.
2025-02-25 12:17:34 +01:00
Ondřej Surý 259600c837 Cleanup the usage of dns_offsets_t vs unsigned char * pointers
There was a back-and-forth between static arrays and the pointers to the
offsets.  Since we are now only using the static arrays, we can cleanup
the usage of the pointers that would previously point either to the
static array or name->offsets if available.
2025-02-25 12:17:34 +01:00
Ondřej Surý 1c22ab2ef7 Simplify name initializers
We no longer need to pass labels to DNS_NAME_INITABSOLUTE
and DNS_NAME_INITNONABSOLUTE.
2025-02-25 12:17:34 +01:00
Ondřej Surý 04c2c2cbc8 Simplify dns_name_init()
Remove the now-unused offsets parameter from dns_name_init().
2025-02-25 12:17:34 +01:00
Ondřej Surý 08e966df82 Remove offsets from the dns_name and dns_fixedname structures
The offsets were meant to speed-up the repeated dns_name operations, but
it was experimentally proven that there's actually no real-world
benefit.  Remove the offsets and labels fields from the dns_name and the
static offsets fields to save 128 bytes from the fixedname in favor of
calculating labels and offsets only when needed.
2025-02-25 12:17:34 +01:00
alessio 887502e37d Drop malformed notify messages early instead of decompressing them
The DNS header shows if a message has multiple questions or invalid
NOTIFY sections. We can drop these messages early, right after parsing
the question. This matches RFC 9619 for multi-question messages and
Unbound's handling of NOTIFY.
To further add further robustness, we include an additional check for
unknown opcodes, and also drop those messages early.

Add early_sanity_check() function to check for these conditions:
- Messages with more than one question, as required by RFC 9619
- NOTIFY query messages containing answer sections (like Unbound)
- NOTIFY messages containing authority sections (like Unbound)
- Unknown opcodes.
2025-02-25 10:40:38 +01:00
Evan Hunt d0fd9cbe3b Fix a logic error in cache_name()
A change in 6aba56ae8 (checking whether a rejected RRset was identical
to the data it would have replaced, so that we could still cache a
signature) inadvertently introduced cases where processing of a
response would continue when previously it would have been skipped.
2025-02-24 15:04:14 -08:00
Ondřej Surý d1ef6a93c1 Acquire the database reference before possibly last node release
Acquire the database refernce in the detachnode() to prevent the last
reference to be release while the NODE_LOCK being locked.  The NODE_LOCK
is locked/unlocked inside the RCU critical section, thus it is most
probably this should not pose a problem as the database uses call_rcu
memory reclamation, but this it is still safer to acquire the reference
before releasing the node.
2025-02-24 20:05:56 +01:00
Ondřej Surý f5c204ac3e Move the library init and shutdown to executables
Instead of relying on unreliable order of execution of the library
constructors and destructors, move them to individual binaries.  The
advantage is that the execution time and order will remain constant and
will not depend on the dynamic load dependency solver.

This requires more work, but that was mitigated by a simple requirement,
any executable using libisc and libdns, must include <isc/lib.h> and
<dns/lib.h> respectively (in this particular order).  In turn, these two
headers must not be included from within any library as they contain
inlined functions marked with constructor/destructor attributes.
2025-02-22 16:19:00 +01:00
Ondřej Surý c6b0368b21 Dump the fetches from dns_resolver_dumpfetches()
Previously, the dns_resolver_dumpfetches() would go over the fetch
counters.  Alas, because of the earlier optimization, the fetch counters
would be increased only when fetches-per-zone was not 0, otherwise the
whole counting was skipped for performance reasons.

Instead of using the auxiliary fetch counters hash table, use the real
hash table that stores the fetch contexts to dump the ongoing fetches to
the recursing file.

Additionally print more information about the fetch context like start
and expiry times, number of fetch responses, number of queries and count
of allowed and dropped fetches.
2025-02-21 22:25:43 +01:00
Ondřej Surý cf078fadeb Fix the fetch context hash table lock ordering
The order of the fetch context hash table rwlock and the individual
fetch context was reversed when calling the release_fctx() function.
This was causing a problem when iterating the hash table, and thus the
ordering has been corrected in a way that the hash table rwlock is now
always locked on the outside and the fctx lock is the interior lock.
2025-02-21 22:05:43 +01:00
Ondřej Surý 77ec2a6c22 Cleanup the isc_counter unit
The isc_counter_create() doesn't need the return value (it was always
ISC_R_SUCCESS), use the macros to implement the reference counting,
little style cleanup, and expand the unit test.
2025-02-21 09:51:42 +00:00
Mark Andrews 83159d0a54 Remove check for missing RRSIG records from getsection
Checking whether the authority section is properly signed should
be left to the validator.  Checking in getsection (dns_message_parse)
was way too early and resulted in resolution failures of lookups
that should have otherwise succeeded.
2025-02-20 20:31:07 +00:00
Aram Sargsyan 716b936045 Implement sig0key-checks-limit and sig0message-checks-limit
Previously a hard-coded limitation of maximum two key or message
verification checks were introduced when checking the message's
SIG(0) signature. It was done in order to protect against possible
DoS attacks. The logic behind choosing the number two was that more
than one key should only be required only during key rotations, and
in that case two keys are enough. But later it became apparent that
there are other use cases too where even more keys are required, see
issue number #5050 in GitLab.

This change introduces two new configuration options for the views,
sig0key-checks-limit and sig0message-checks-limit, which define how
many keys are allowed to 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 latter protects against expensive cryptographic
operations when there are keys with colliding tags and algorithm
numbers, with default being 2, and the former protects against a bit
less expensive key parsing operations and defaults to 16.
2025-02-20 13:35:14 +00:00
Aram Sargsyan c701b590e4 Expose the incoming transfers' rates in the statistics channel
Expose the average transfer rate (in bytes-per-second) during the
last full 'min-transfer-rate-in <bytes> <minutes>' minutes interval.
If no such interval has passed yet, then the overall average rate is
reported instead.
2025-02-20 09:32:55 +00:00
Aram Sargsyan 91ea156203 Implement the min-transfer-rate-in configuration option
This new option sets a minimum amount of transfer rate for
an incoming zone transfer that will abort a transfer, which
for some network related reasons run very slowly.
2025-02-20 09:32:55 +00:00
Evan Hunt 6aba56ae89 Check whether a rejected rrset is different
Add a new dns_rdataset_equals() function to check whether two
rdatasets are equal in DNSSEC terms.

When an rdataset being cached is rejected because its trust
level is lower than the existing rdataset, we now check to see
whether the rejected data was identical to the existing data.
This allows us to cache a potentially useful RRSIG when handling
CD=1 queries, while still rejecting RRSIGs that would definitely
have resulted in a validation failure.
2025-02-19 17:25:20 -08:00
Ondřej SurýandEvan Hunt 2fc32c105d Remove the "raw" version of the dns_slabheader API
The "raw" version of the header was used for the noqname and the closest
proofs to save around 152 bytes of the dns_slabheader_t while bringing
an additional complexity.  Remove the raw version of the dns_slabheader
API at the slight expense of having unused dns_slabheader_t data sitting
in front of the proofs.
2025-02-19 15:00:15 -08:00
Evan Hunt c2e19771ac refactor dns_rdataslab_subtract() for efficiency
reduce the number of rdata comparisons needed by walking
through the original slab once to determine whether the rdata
in it is duplicated in the slab to be subtracted, and then
write out the rdatas that aren't. previously, this was
done twice: once when determining the size of the target buffer
and then again when copying data into it.
2025-02-19 15:00:15 -08:00
Evan Hunt 1d5fe36136 refactor dns_rdataslab_merge() for efficiency
when merging two rdata slabs, we now check once to see
whether an item in the new slab has a duplicate in the
old. previously this was done twice; once to determine the
size of the target buffer required, and then again when
copying the data into it.

we also minimize the number of rdata comparisons necessary,
by remembering which items in the old slab have already been
found to be duplicates.
2025-02-19 15:00:15 -08:00
Evan Hunt ed83455c81 dns_slabheader_fromrdataset() -> dns_rdataset_getheader()
The function name dns_slabheader_fromrdataset() was too similar
to dns_rdataslab_fromrdataset(). Instead, we now have an rdataset
method 'getheader' which is implemented for slab-type rdatasets.

A new NOHEADER rdataset attribute is set for rdatasets using
raw slabs (i.e., noqname and closest encloser proofs); when
called on rdatasets with that flag set, dns_rdataset_getheader()
returns NULL.
2025-02-19 14:58:32 -08:00
Evan Hunt 82edec67a5 initialize header in dns_rdataslab_fromrdataset()
when dns_rdataslab_fromrdataset() is run, in addition to
allocating space for a slab header, it also partially
initializes it, setting the type match rdataset->type and
rdataset->covers, the trust to rdataset->trust, and the TTL to
rdataset->ttl.
2025-02-19 14:58:32 -08:00
Evan Hunt b4bde9bef4 clarify dns_rdataslab_fromrdataset()
there are now two functions for creating an rdataslab from an
rdataset: dns_rdataslab_fromrdataset() creates a full slab (including
space for a slab header), and dns_rdataslab_raw_fromrdataset() creates
a raw slab.
2025-02-19 14:58:32 -08:00
Evan Hunt f1ab7f199b refactor dns_rdataslab_merge() and _subtract()
these two functions have been refactored for clarity
and readability, with a more logical flow, added comments,
and less code duplication.
2025-02-19 14:58:32 -08:00