Commit Graph

153 Commits

Author SHA1 Message Date
Mark Andrews
799046929c Only check SVBC alias forms at higher levels
Allow SVBC (HTTPS) alias form with parameters to be accepted from
the wire and when transfered.  This is for possible future extensions.
2024-05-07 11:20:49 +10:00
Evan Hunt
a23ce2c53c add another test case for an incorrect QP iterator position
build a database tree with names containing control characters,
search for another control character, and verify the iterator is
positioned correctly.
2024-05-01 00:36:16 -07:00
Matthijs Mekking
ada46eb9f5 Add a unit test case for converting \000\009
Sanity checking that this domain converts to the key I am expecting.

Also fix some of the other names that had trailing 0x02 bits.
2024-04-30 16:00:13 -07:00
Evan Hunt
04d319afe4 include the nodenames when calculating memory to purge
when the cache is over memory, we purge from the LRU list until
we've freed the approximate amount of memory to be added. this
approximation could fail because the memory allocated for nodenames
wasn't being counted.

add a dns_name_size() function so we can look up the size of nodenames,
then add that to the purgesize calculation.
2024-04-30 12:50:01 -07:00
Evan Hunt
46d40b3dca fix structure names in qpcache.c and qpzone.c
- change dns_qpdata_t to qpcnode_t (QP cache node), and dns_qpdb_t to
  qpcache_t, as these types are only accessed locally.
- also change qpdata_t in qpzone.c to qpznode_t (QP zone node), for
  consistency.
- make the refcount declarations for qpcnode_t and qpznode_t static,
  using the new ISC_REFCOUNT_STATIC macros.
2024-04-30 12:42:07 -07:00
Aydın Mercan
4a3f7fe1ef Emit and read correct DoT and DoH dnstap entries
Other protocols still pretend to be TCP/UDP.
This only causes a difference when using dnstap-read on a file with DoQ
or DNSCrypt entries
2024-04-26 16:12:29 +03:00
Evan Hunt
b1b1ca8ca4 add another broken testcase 2024-04-25 10:29:07 -07:00
Evan Hunt
2dff926624 yet another fix_iterator() bug
under some circumstances it was possible for the iterator to
be set to the first leaf in a set of twigs, when it should have
been set to the last.

a unit test has been added to test this scenario. if there is a
a tree containing the following values: {".", "abb.", "abc."}, and
we query for "acb.", previously the iterator would be positioned at
"abb." instead of "abc.".

the tree structure is:
    branch (offset 1, ".")
      branch (offset 3, ".ab")
        leaf (".abb")
        leaf (".abc")

we find the branch with offset 3 (indicating that its twigs differ
from each other in the third position of the label, "abB" vs "abC").
but the search key differs from the found keys at position 2
("aC" vs "aB").  we look up the bit value in position 3 of the
search key ("B"), and incorrectly follow it onto the wrong twig
("abB").

to correct for this, we need to check for the case where the search
key is greater than the found key in a position earlier than the
branch offset. if it is, then we need to pop from the current leaf
to its parent, and get the greatest leaf from there.

a further change is needed to ensure that we don't do this twice;
when we've moved to a new leaf and the point of difference between
it and the search key even earlier than before, then we're definitely
at a predecessor node and there's no need to continue the loop.
2024-04-25 10:29:07 -07:00
Mark Andrews
e6984e5c07 Extract empty name in 'source' into 'name' 2024-04-24 01:38:14 +00:00
Mark Andrews
7a13fcd601 Extract non absolute name from source
The entire source region needs to be consumed for this usage.
2024-04-24 01:38:14 +00:00
Mark Andrews
7d7fc8cb2d Extract fully qualified named from source without buffer
'name.ndata' should point to the source.
2024-04-24 01:38:14 +00:00
Mark Andrews
254ba1b051 Test dns_name_fromregion
with a large source region and a large target buffer, both
larger than DNS_NAME_MAXWIRE.
2024-04-24 01:38:14 +00:00
Mark Andrews
36c11d9180 Check that name is properly reset by dns_qpkey_toname 2024-04-18 00:17:48 +00:00
Artem Boldariev
7f805659c3 dispatch_test: use the NM tests timeouts
This commit makes the dispatch_test use the same timeouts that network
manager tests. We do that because the old values appear to be too
small for our heavy loaded CI machines, leading to spurious failures
on them. The network manager tests are much more stable in this
situation and they use somewhat larger timeout values.

We use a smaller connection timeouts for the tests which are expected
to timeout to not wait for too long.
2024-04-15 16:33:24 +03:00
Evan Hunt
c47fa689d4 use a thread-local variable to get the current running loop
if we had a method to get the running loop, similar to how
isc_tid() gets the current thread ID, we can simplify loop
and loopmgr initialization.

remove most uses of isc_loop_current() in favor of isc_loop().
in some places where that was the only reason to pass loopmgr,
remove loopmgr from the function parameters.
2024-04-02 10:35:56 +02:00
Matthijs Mekking
2a724a808d Add a test case for fix_iterator hang
When fixing the iterator, when every leaf on this branch is greater
than the one we wanted we go back to the parent branch and iterate back
to the predecessor from that point.

But if there are no more previous leafs, it means the queried name
precedes the entire range of names in the database, so we would just
move the iterator one step back and continue from there.

This could end in a loop because the queried name precedes the entire
range of names and so none of those names are the predecessor of the
queried name.
2024-03-25 10:40:23 +01:00
Evan Hunt
5709f7bad9 rename qpdb to qpcache
move qpdb.c to qpcache.c and rename the "qp" database implementation
to "qpcache", in order to make it more clearly distinguishable from
"qpzone".
2024-03-08 15:36:56 -08:00
Evan Hunt
ab084d8c4f remove qp-zonedb.c and associated code
now that "qpzone" databases are available for use in zones, we no
longer need to retain the zone semantics in the "qp" database.

all zone-specific code has been removed from QPDB, and "configure
--with-zonedb" once again takes two values, rbt and qp.

some database API methods that are never used with a cache have
been removed from qpdb.c and qp-cachedb.c; these include newversion,
closeversion, subtractrdataset, and nodefullname.
2024-03-08 15:36:56 -08:00
Evan Hunt
ab13ba2438 add qpzone_test unit test
copy the non-cache-specific tests from the old rbtdb_test.c to
qpzone_test.c.
2024-03-08 15:36:56 -08:00
Evan Hunt
60b5422cda make the qpzone database dumpable
add database API method implementations needed to iterate and dump
a qpzone database to a file (createiterator, allrdatasets and
attachversion, plus dbiterator and rdatasetiter methods).

named-checkzone -D can now dump the contents of most zones,
but zone cuts are not correctly detected.
2024-03-08 15:36:56 -08:00
Evan Hunt
92b305be4b add a compile-time option to select default zone and cache DB
by default, QPDB is the database used by named and all tools and
unit tests. the old default of RBTDB can now be restored by using
"configure --with-zonedb=rbt --with-cachedb=rbt".

some tests have been fixed so they will work correctly with either
database.

CHANGES and release notes have been updated to reflect this change.
2024-03-06 10:49:02 +01:00
Matthijs Mekking
fe97aa59b9 Replace dns_rbtnode_t with dns_qpdata_t
This for now has almost the same structure contents except for
dns_qpdata_t has 'fn' and 'name' to store the domain name.
2024-03-06 09:57:25 +01:00
Evan Hunt
bb4464181a switch database defaults from "rbt" to "qp"
replace the string "rbt" throughout BIND with "qp" so that
qpdb databases will be used by default instead of rbtdb.
rbtdb databases can still be used by specifying "database rbt;"
in a zone statement.
2024-03-06 09:57:24 +01:00
Evan Hunt
845f832308 rename dns_rbtdb to dns_qpdb
this commit renames all variables and macros with the string "rbtdb"
or "RBDTB" to "qpdb" or "QPDB".
2024-03-06 09:57:24 +01:00
Mark Andrews
0651063658 Add RESINFO record type
This is a TXT clone using code point 261.
2024-02-26 12:02:40 +11:00
Evan Hunt
e40fd4ed06 fix several bugs in the RBTDB dbiterator implementation
- the DNS_DB_NSEC3ONLY and DNS_DB_NONSEC3 flags are mutually
  exclusive; it never made sense to set both at the same time.
  to enforce this, it is now a fatal error to do so.  the
  dbiterator implementation has been cleaned up to remove
  code that treated the two as independent: if nonsec3 is
  true, we can be certain nsec3only is false, and vice versa.
- previously, iterating a database backwards omitted
  NSEC3 records even if DNS_DB_NONSEC3 had not been set. this
  has been corrected.
- when an iterator reaches the origin node of the NSEC3 tree, we
  need to skip over it and go to the next node in the sequence.
  the NSEC3 origin node is there for housekeeping purposes and
  never contains data.
- the dbiterator_test unit test has been expanded, several
  incorrect expectations have been fixed. (for example, the
  expected number of iterations has been reduced by one; we were
  previously counting the NSEC3 origin node and we should not
  have been doing so.)
2024-02-15 10:15:50 -08:00
Evan Hunt
ac9bd03a0d clean up dns_rbt
- create_node() in rbt.c cannot fail
- the dns_rbt_*name() functions, which are wrappers around
  dns_rbt_[add|find|delete]node(), were never used except in tests.

this change isn't really necessary since RBT is likely to go away
eventually anyway. but keeping the API as simple as possible while it
persists is a good thing, and may reduce confusion while QPDB is being
developed from RBTDB code.
2024-02-14 01:36:44 -08:00
Evan Hunt
27c862d953 separate generic DB helpers into db_p.h
when the QPDB is implemented, we will need to have both qpdb_p.h and
rbtdb_p.h. in order to prevent name collisions or code duplication,
this commit adds a generic private header file, db_p.h, containing
structures and macros that will be used by both databases.

some functions and structs have been renamed to more specifically refer
to the RBT database, in order to avoid namespace collision with similar
things that will be needed by the QPDB later.
2024-02-14 09:00:27 +01:00
Matthijs Mekking
18b566ccea Refactor findzonekeys
Move dns_dnssec_findzonekeys from the dnssec.{c,h} source code to
zone.{c,h} (the header file already commented that this should be done
inside dns_zone_t).

Alter the function in such a way, that keys are searched for in the
key stores if a 'dnssec-policy' (kasp) is attached to the zone,
otherwise keep using the zone's key-directory.
2024-01-25 14:48:07 +01:00
Evan Hunt
ea9a8cb392 prevent an infinite loop in fix_iterator()
it was possible for fix_iterator() to get stuck in a loop while
trying to find the predecessor of a missing node. this has been
fixed and a regression test has been added.
2023-12-21 09:18:30 -08:00
Evan Hunt
84f79cd164 fix_iterator() could produce incoherent iterator stacks
the fix_iterator() function moves an iterator so that it points
to the predecessor of the searched-for name when that name doesn't
exist in the database. the tests only checked the correctness of
the top of the stack, however, and missed some cases where interior
branches in the stack could be missing or duplicated. in these
cases, the iterator would produce inconsistent results when walked.

the predecessors test case in qp_test has been updated to walk
each iterator to the end and ensure that the expected number of
nodes are found.
2023-12-21 09:18:30 -08:00
Matthijs Mekking
ab8a0c4b5a and fix yet another dns_qp_lookup() iterator bug
This one is similar to the bug when searching for a key, reaching a
dead-end branch that doesn't match, because the branch offset point
is after the point where the search key differs.

This fixes the case where we are multiple levels deep. In other
words, we had a more-than-one matches *after* the point where the
search key differs.

For example, consider the following qp-trie:

branch: "[e]", "[m]":
 - leaf: "a.b.c.d.e"
 - branch: "moo[g]", "moo[k]", "moo[n]":
   - leaf: "moog"
   - branch: "mook[e]", "mook[o]"
     - leaf: "mooker"
     - leaf: "mooko"
   - leaf: "moon"

If searching for a key "monky", we would reach the branch with
twigs "moo[k]" and "moo[n]". The key matches on the 'k' on offset=4,
and reaches the branch with twigs "mook[e]" and "mook[o]". This time
we cannot find a twig that matches our key at offset=5, there is no
twig for 'y'. The closest name we found was "mooker".

Note that on a branch it can't detect it is on a dead branch because the
key is not encapsulated in a branch node.

In the previous code we considered "mooker" to be the successor of
"monky" and so we needed to the predecessor of "mooker" to find the
predecessor for "monky". However, since the search key alread differed
before entering this branch, this is not enough. We would be left with
"moog" as the predecessor of "monky", while in this example "a.b.c.d.e"
is the actual predecessor.

Instead, we need to go up a level, find the predecessor and check
again if we are on the right branch, and repeat the process until we
are.

Unit tests to cover the scenario are now added.
2023-12-11 21:01:29 +00:00
Matthijs Mekking
276bdcf5cf and fix another dns_qp_lookup() iterator bug
There was yet another edge case in which an iterator could be
positioned at the wrong node after dns_qp_lookup(). When searching for
a key, it's possible to reach a leaf that matches at the given offset,
but because the offset point is *after* the point where the search key
differs from the leaf's contents, we are now at the wrong leaf.

In other words, the bug fixed the previous commit for dead-end branches
must also be applied on matched leaves.

For example, if searching for the key "monpop", we could reach a branch
containing "moop" and "moor". the branch offset point - i.e., the point
after which the branch's leaves differ from each other - is the
fourth character ("p" or "r"). The search key matches the fourth
character "p", and takes that twig to the next node (which can be
a branch for names starting with "moop", or could be a leaf node for
"moop").

The old code failed to detect this condition, and would have
incorrectly left the iterator pointing at some successor, and not
at the predecessor of the "moop".

To find the right predecessor in this case, we need to get to the
previous branch and get the previous from there.

This has been fixed and the unit test now includes several new
scenarios for testing search names that match and unmatch on the
offset but have a different character before the offset.
2023-12-11 21:01:29 +00:00
Evan Hunt
60a33ae6bb fix another dns_qp_lookup() iterator bug
there was another edge case in which an iterator could be positioned at
the wrong node after dns_qp_lookup().  when searching for a key, it's
possible to reach a dead-end branch that doesn't match, because the
branch offset point is *after* the point where the search key differs
from the branch's contents.

for example, if searching for the key "mop", we could reach a branch
containing "moon" and "moor". the branch offset point - i.e., the
point after which the branch's leaves differ from each other - is the
fourth character ("n" or "r"). however, both leaves differ from the
search key at position *three* ("o" or "p"). the old code failed to
detect this condition, and would have incorrectly left the iterator
pointing at some lower value and not at "moor".

this has been fixed and the unit test now includes this scenario.
2023-12-06 11:03:30 -08:00
Evan Hunt
8612902476 fix dns_qp_lookup() iterator bug
in some cases it was possible for the iterator to be positioned in the
wrong place by dns_qp_lookup(). previously, when a leaf node was found
which matched the search key at its parent branch's offset point, but
did not match after that point, the code incorrectly assumed the leaf
it had found was a successor to the searched-for name, and stepped the
iterator back to find a predecessor.  however, it was possible for the
non-matching leaf to be the predecessor, in which case stepping the
iterator back was wrong.

(for example: a branch contains "aba" and "abcd", and we are searching
for "abcde". we step down to the twig matching the letter "c" in
position 3. "abcd" is the predecessor of "abcde", so the iterator is
already correctly positioned, but because the twig was an exact match,
we would have moved it back one step to "aba".)

this previously went unnoticed due to a mistake in the qp_test unit
test, which had the wrong expected result for the test case that should
have detected the error. both the code and the test have been fixed.
2023-12-06 11:03:30 -08:00
Evan Hunt
947bc0a432 add an iterator argument to dns_qp_lookup()
the 'predecessor' argument to dns_qp_lookup() turns out not to
be sufficient for our needs: the predecessor node in a QP database
could have become "empty" (for the current version) because of an
update or because cache data expired, and in that case the caller
would have to iterate more than one step back to find the predecessor
node that it needs.

it may also be necessary for a caller to iterate forward, in
order to determine whether a node has any children.

for both of these reasons, we now replace the 'predecessor'
argument with an 'iter' argument. if set, this points to memory
with enough space for a dns_qpiter object.

when an exact match is found by the lookup, the iterator will be
pointing to the matching node. if not, it will be pointing to the
lexical predecessor of the nae that was searched for.

a dns_qpiter_current() method has been added for examining
the current value of the iterator without moving it in either
direction.
2023-12-06 11:03:30 -08:00
Artem Boldariev
eb52015db1 Stream DNS: add PROXY over TLS support
This commit extends Stream DNS with PROXY over TLS support.
2023-12-06 15:15:25 +02:00
Artem Boldariev
e97903ca14 Add PROXY support to Stream DNS
This commit makes it possible to use Stream DNS on top of PROXY Stream
either directly or indirectly (in the case when TLS is involved).
2023-12-06 15:15:24 +02:00
Matthijs Mekking
a759f7f33c Change max NSEC3 iterations in unit tests to 50
The nsec3 unit test needs to be adjusted to accept a lower maximum value
for NSEC3 iterations.
2023-12-05 14:58:58 +00:00
Ondřej Surý
14bdd21e0a Refactor the handling of isc_mem overmem condition
Previously, there were two methods of working with the overmem
condition:

1. hi/lo water callback - when the overmem condition was reached
   for the first time, the water callback was called with HIWATER
   mark and .is_overmem boolean was set internally.  Similarly,
   when the used memory went below the lo water mark, the water
   callback would be called with LOWATER mark and .is_overmem
   was reset.  This check would be called **every** time memory
   was allocated or freed.

2. isc_mem_isovermem() - a simple getter for the internal
   .is_overmem flag

This commit refactors removes the first method and move the hi/lo water
checks to the isc_mem_isovermem() function, thus we now have only a
single method of checking overmem condition and the check for hi/lo
water is removed from the hot path for memory contexts that doesn't use
overmem checks.
2023-11-29 14:16:20 +01:00
Ondřej Surý
aa393b9e57 Bump the timeouts in the dispatch_test
The client connection timeout was set to just one second, which might
not be enough on busy systems (and the CI machines are oh-boy-busy).
Bump the server timeouts to 10 seconds and client timeouts to 5 seconds,
this will make the unit test run a little bit longer, but it should be
more reliable.
2023-10-27 12:55:51 +02:00
Ondřej Surý
b7e793b84c Add tests/dns/badcache.out to .gitignore 2023-10-27 12:55:51 +02:00
Ondřej Surý
d246aa02a6 Add dispatch_getcp and dispatch_newtcp tests
Refactor the dispatch unit test to use more local variables (previously
dispatchmgr, dispatch and dispentry were all global), and add two new
tests:

* dispatch_getcp - test whether the TCP connection will get reused
* dispatch_newtcp - test that the TCP connection will not get reused
                    when DNS_DISPATCHOPT_UNSHARED is in effect
2023-10-24 13:07:03 +02:00
Ondřej Surý
f213f644ed Add option to mark TCP dispatch as unshared
The current dispatch code could reuse the TCP connection when
dns_dispatch_gettcp() would be used first.  This is problematic as the
dns_resolver doesn't use TCP connection sharing, but dns_request could
get the TCP stream that was created outside of the dns_request.

Add new DNS_DISPATCHOPT_UNSHARED option to dns_dispatch_createtcp() that
would prevent the TCP stream to be reused.  Use that option in the
dns_resolver call to dns_dispatch_createtcp() to prevent dns_request
from reusing the TCP connections created by dns_resolver.

Additionally, the dns_xfrin unit added TCP connection sharing for
incoming transfers.  While interleaving *xfr streams on a TCP connection
should work this should be a deliberate change and be property of the
server that can be controlled.  Additionally some level of parallel TCP
streams is desirable.  Revert to the old behaviour by removing the
dns_dispatch_gettcp() calls from dns_xfrin and use the new option to
prevent from sharing the transfer streams with dns_request.
2023-10-24 13:07:03 +02:00
Aram Sargsyan
b535843bb7 Fix an error in the qp_test.c unit test
In order to check whether there are enough inserted values the
code uses the 'tests' variable (loop counter), which is unreliable,
because the loop sometimes removes an item instead of inserting
one (when the randomly generated item already exists).

Instead of the loop counter, use the existing variable 'inserted',
which should indicate the correct number of the inserted items.
2023-10-19 08:46:58 +00:00
Ondřej Surý
b3a8f0048f Refactor dns_{acl,aclenv}_create to return void
The dns_{acl,aclenv}_create() can't fail, so change it to return void.
2023-10-13 14:44:40 +02:00
Evan Hunt
8f6a3f47db fix a QP chain bug
depending on how the QP trie is traversed during a lookup, it is
possible for a search to terminate on a leaf which is a partial
match, without that leaf being added to the chain. to ensure the
chain is correct in this case, when a partial match condition is
detected via qpkey_compare(), we will call add_link() again, just
in case.  (add_link() will check for a duplicated node, so it will
be harmless if it was already done.)
2023-10-09 13:29:02 -07:00
Evan Hunt
03016902dd rename dns_qp_findname_ancestor() to dns_qp_lookup()
I am weary of typing so long a name. (plus, the name has become slightly
misleading now that the DNS_QPFIND_NOEXACT option no longer exists.)
2023-09-28 00:32:44 -07:00
Evan Hunt
4e3e61806c get predecessor name in dns_qp_findname_ancestor()
dns_qp_findname_ancestor() now takes an optional 'predecessor'
parameter, which if non-NULL is updated to contain the DNSSEC
predecessor of the name searched for. this is done by constructing
an iterator stack while carrying out the search, so it can be used
to step backward if needed.
2023-09-28 00:32:37 -07:00
Evan Hunt
606232b8d5 remove DNS_QPFIND_NOEXACT
since dns_qp_findname_ancestor() can now return a chain object, it is no
longer necessary to provide a _NOEXACT search option. if we want to look
up the closest ancestor of a name, we can just do a normal search, and
if successful, retrieve the second-to-last node from the QP chain.

this makes ancestor lookups slightly more complicated for the caller,
but allows us to simplify the code in dns_qp_findname_ancestor(), making
it easier to ensure correctness.  this was a fairly rare use case:
outside of unit tests, DNS_QPFIND_NOEXACT was only used in the zone
table, which has now been updated to use the QP chain.  the equivalent
RBT feature is only used by the resolver for cache lookups of 'atparent'
types (i.e, DS records).
2023-09-28 00:30:57 -07:00