2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

8548 Commits

Author SHA1 Message Date
Mark Andrews
26f817f574 Return ISC_R_NOTIMPLEMENTED rather than ISC_R_UNEXPECTEDEND
If the keydata rdata is shorter that 16 octets it is not out private
keydata type and we have not implemented a tostruct method for it.
2022-02-25 21:06:16 -08:00
Mark Andrews
48039fa25e Do not return ISC_R_UNEXPECTEDEND
All rdata passed to dns_rdata_tostruct is supposed to be well formed,
assert if it isn't.
2022-02-25 20:57:08 -08:00
Evan Hunt
bbaade23eb mem_maybedup() can no longer fail
mem_maybedup() calls isc_mem_allocate() if an mctx is supplied,
but that can no longer fail, so now the only way mem_maybedup()
could return NULL is if it was given a NULL source address by the
caller. this commit adds a REQUIRE to prevent that scenario, and
cleans up all the calling code that previously checked for NULL
return values.

this function is mostly used in rdata tostruct() implementations, so
the documentation for dns_rdata_tostruct() has been updated to
remove 'ISC_R_NOMEMORY' as a possible return value.
2022-02-25 20:57:08 -08:00
Michał Kępień
b645e28167 Add "UNUSED(fctx);" to FCTXTRACE*() macro stubs
Commit b6d40b3c4e4452cee6f7f06d889e4e8d113e9588 removed most uses of the
'fctx' variable from the rctx_dispfail() function: it is now only needed
by the FCTXTRACE3() macro.  However, when --enable-querytrace is not in
effect, that macro evaluates to a list of UNUSED() macros that does not
include "UNUSED(fctx);".  This triggers the following compilation
warning when building without --enable-querytrace:

    resolver.c: In function 'rctx_dispfail':
    resolver.c:7888:21: warning: unused variable 'fctx' [-Wunused-variable]
     7888 |         fetchctx_t *fctx = rctx->fctx;
          |                     ^~~~

Fix by adding "UNUSED(fctx);" lines to all FCTXTRACE*() macros.  This is
safe to do because all of those macros use the 'fctx' local variable, so
there is no danger of introducing new errors caused by use of undeclared
identifiers.
2022-02-21 10:50:38 +01:00
Evan Hunt
b6d40b3c4e correct TCP error handling in dispatch and resolver
- certain TCP result codes, including ISC_R_EOF and
  ISC_R_CONNECTIONRESET, were being mapped to ISC_R_SHUTTINGDOWN
  before calling the response handler in tcp_recv_cancelall().
  the result codes should be passed through to the response handler
  without being changed.

- the response handlers, resquery_response() and req_response(), had
  code to return immediately if encountering ISC_R_EOF, but this is
  not the correct behavior; that should only happen in the case of
  ISC_R_CANCELED when it was the caller that canceled the operation

- ISC_R_CONNECTIONRESET was not being caught in rctx_dispfail().

- removed code in rctx_dispfail() to retry queries without EDNS
  when receiving ISC_R_EOF; this is now treated the same as any
  other connection failure.
2022-02-17 09:59:12 +01:00
Evan Hunt
4444b168db negative 'blackhole' ACL match could be treated as positive
There was a bug in the checking of the "blackhole" ACL in
dns_request_create*(), causing an address to be treated as included
in the ACL if it was explicitly *excluded*. Thus, leaving "blackhole"
unset had no effect, but setting it to "none" would cause any
destination addresses to be rejected for dns_request purposes. This
would cause zone transfer requests and SOA queries to fail, among
other things.

The bug has been fixed, and "blackhole { none; };" was added to the
xfer system test as a regression test.
2022-02-16 19:05:06 -08:00
Michał Kępień
f286c845b0 Log the result of each resolver priming attempt
When a resolver priming attempt completes, the following message is
currently logged:

    resolver priming query complete

This message is identical for both successful and failed priming
attempts.  Consider the following log excerpts:

  - successful priming attempt:

        10-Feb-2022 11:33:11.272 all zones loaded
        10-Feb-2022 11:33:11.272 running
        10-Feb-2022 11:33:19.722 resolver priming query complete

  - failed priming attempt:

        10-Feb-2022 11:33:29.978 all zones loaded
        10-Feb-2022 11:33:29.978 running
        10-Feb-2022 11:33:38.432 timed out resolving '_.org/A/IN': 2001:500:9f::42#53
        10-Feb-2022 11:33:38.522 timed out resolving './NS/IN': 2001:500:9f::42#53
        10-Feb-2022 11:33:42.132 timed out resolving '_.org/A/IN': 2001:500:12::d0d#53
        10-Feb-2022 11:33:42.285 timed out resolving './NS/IN': 2001:500:12::d0d#53
        10-Feb-2022 11:33:44.685 resolver priming query complete

Include the result of each priming attempt in the relevant log message
to give the administrator better insight into named's resolver priming
process.
2022-02-16 13:26:12 +01:00
Ondřej Surý
cdce681cf7 Remove unused dns_timer API
The dns_timer API was unused, and this commit just removes it.
2022-02-16 10:49:48 +01:00
Evan Hunt
e8ac7cf6ec remove error handling code around dns_dnsseckey_create()
this function can no longer fail, so error checking is not necessary.
2022-01-31 10:39:04 -08:00
Evan Hunt
d3fed6f400 update dlz_minimal.h
the addition of support for ECS client information in DLZ
modules omitted some necessary changes to build modules
in contrib.
2022-01-27 15:48:50 -08:00
Evan Hunt
737e658602 allow dns_clientinfo to store client ECS data
this brings DNS_CLIENTINFO_VERSION into line with the subscription
branch so that fixes applied to clientinfo processing can also be
applied to the main branch without diverging.
2022-01-27 13:53:59 -08:00
Aram Sargsyan
4a6c66288f Fix a memory leak in dns_dlzcreate()
dns_dlzcreate() fails to free the memory allocated for dlzname
when an error occurs.

Free dlzname's memory (acquired earlier with isc_mem_strdup())
by calling isc_mem_free() before returning an error code.
2022-01-25 08:21:50 +00:00
Aram Sargsyan
2fd967136a Improve the zones' view reverting logic when a zone is a catalog zone
When a zone is being configured with a new view, the catalog zones
structure will also be linked to that view. Later on, in case of some
error, should the zone be reverted to the previous view, the link
between the catalog zones structure and the view won't be reverted.

Change the dns_zone_setviewrevert() function so it calls
dns_zone_catz_enable() during a zone revert, which will reset the
link between `catzs` and view.
2022-01-25 08:20:52 +00:00
Aram Sargsyan
6b937ed5f6 Separate the locked parts of dns_zone_catz_enable/disable functions
Separate the locked parts of dns_zone_catz_enable() and
dns_zone_catz_disable() functions into static functions.  This will
let us perform those tasks from the other parts of the module while
the zone is locked, avoiding one pair of additional unlocking and
locking operations.
2022-01-25 08:20:52 +00:00
Ondřej Surý
c960236adb Don't schedule next zone events when shutting down
When the named is shutting down, the zone event callbacks could
re-schedule the stub and refresh events leading to assertion failure.

Handle the ISC_R_SHUTTINGDOWN event state gracefully by bailing out.
2022-01-13 17:58:33 +01:00
Ondřej Surý
efca93942c Refactor zone stub, refresh and notify event callbacks
This commit cleanups the way how we handle the revent->result in the
stub_callback(), refresh_callback() and notify_done() zone callbacks.
2022-01-13 17:58:33 +01:00
Ondřej Surý
8a0c4355d2 Remove the workaround for broken handling of NOTIFY with SOA
In 2000, old BIND instances (BIND 8?) would return FORMERR if the SOA is
included in the NOTIFY.

Remove the workaround that detected the state and resent the NOTIFY
without SOA record.
2022-01-13 17:09:43 +01:00
Ondřej Surý
58bd26b6cf Update the copyright information in all files in the repository
This commit converts the license handling to adhere to the REUSE
specification.  It specifically:

1. Adds used licnses to LICENSES/ directory

2. Add "isc" template for adding the copyright boilerplate

3. Changes all source files to include copyright and SPDX license
   header, this includes all the C sources, documentation, zone files,
   configuration files.  There are notes in the doc/dev/copyrights file
   on how to add correct headers to the new files.

4. Handle the rest that can't be modified via .reuse/dep5 file.  The
   binary (or otherwise unmodifiable) files could have license places
   next to them in <foo>.license file, but this would lead to cluttered
   repository and most of the files handled in the .reuse/dep5 file are
   system test files.
2022-01-11 09:05:02 +01:00
Matthijs Mekking
beeefe35c4 Fix bug introduced by #763 related to offline keys
In some cases we want to keep expired signatures. For example, if the
KSK is offline, we don't want to fall back to signing with the ZSK.
We could remove the signatures, but in any case we end up with a broken
zone.

The change made for GL #763 prevented the behavior to sign the DNSKEY
RRset with the ZSK if the KSK was offline (and signatures were expired).

The change causes the definition of "having both keys": if one key is
offline, we still consider having both keys, so we don't fallback
signing with the ZSK if KSK is offline.

That change also works the other way, if the ZSK is offline, we don't
fallback signing with the KSK.

This commit fixes that, so we only fallback signing zone RRsets with
the KSK, not signing key RRsets with the ZSK.
2022-01-06 09:32:32 +01:00
Matthijs Mekking
2d2858841a Only warn if we could not delete signature
BIND can log this warning:

    zone example.ch/IN (signed): Key example.ch/ECDSAP256SHA256/56340
      missing or inactive and has no replacement: retaining signatures.

This log can happen when BIND tries to remove signatures because the
are about to expire or to be resigned. These RRsets may be signed with
the KSK if the ZSK files has been removed from disk. When we have
created a new ZSK we can replace the signatures creeated by the KSK
with signatures from the new ZSK.

It complains about the KSK being missing or inactive, but actually it
takes the key id from the RRSIG.

The warning is logged if BIND detects the private ZSK file is missing.

The warning is logged even if we were able to delete the signature.

With the change from this commit it only logs this warning if it is not
okay to delete the signature.
2022-01-06 09:32:32 +01:00
Michał Kępień
ef625f5f06 Do not detach raw zone until dumping is complete
When the signed version of an inline-signed zone is dumped to disk, the
serial number of the unsigned version of the zone is stored in the
raw-format header so that the contents of the signed zone can be
resynchronized after named restart if the unsigned zone file is modified
while named is not running.

In order for the serial number of the unsigned zone to be determined
during the dump, zone->raw must be set to a non-NULL value.  This should
always be the case as long as the signed version of the zone is used for
anything by named.

However, a scenario exists in which the signed version of the zone has
zone->raw set to NULL while it is being dumped:

 1. Zone dump is requested; zone_dump() is invoked.

 2. Another zone dump is already in progress, so the dump gets deferred
    until I/O is available (see zonemgr_getio()).

 3. The last external reference to the zone is released.
    zone_shutdown() gets queued to the zone's task.

 4. I/O becomes available for zone dumping.  zone_gotwritehandle() gets
    queued to the zone's task.

 5. The zone's task runs zone_shutdown().  zone->raw gets set to NULL.

 6. The zone's task runs zone_gotwritehandle().  zone->raw is determined
    to be NULL, causing the serial number of the unsigned version of the
    zone to be omitted from the raw-format dump of the signed zone file.

Note that the naïve solution - deferring the dns_zone_detach() call for
zone->raw until zone_free() gets called for the secure version of the
zone - does not work because it leads to a chicken-and-egg problem when
the inline-signed zone is about to get freed: the raw zone holds a weak
reference to the secure zone and that reference does not get released
until the reference count for the raw zone reaches zero, which in turn
would not happen until all weak references to the secure zone were
released.

Defer detaching from zone->raw in zone_shutdown() if the zone is in the
process of being dumped to disk.  Ensure zone->raw gets detached from
after the dump is finished if detaching gets deferred.  Prevent zone
dumping from being requeued upon failure if the zone is in the process
of being cleaned up as it opens up possibilities for the zone->raw
reference to leak, triggering a shutdown hang.
2022-01-05 17:53:49 +01:00
Ondřej Surý
1064b2fc47 Revert "Ensure the correct ordering zone_shutdown() vs zone_gotwritehandle()"
This reverts commit cc1d4e1aa63fdc7e82a00fd7b06d50fb4dbc8e96.
2022-01-05 17:53:49 +01:00
Ondřej Surý
ab5b2ef43c Add isc_refcount_destroy() for dns_zt reference counters
The zt_destroy() function was missing isc_refcount_destroy() on the two
reference counters.  The isc_refcount_destroy() adds proper memory
ordering on destroy and also ensures that the reference counters have
been zeroed before destroying the object.
2022-01-05 16:56:16 +01:00
Ondřej Surý
f326d45135 Lock view while accessing its zone table
Commit 308bc46a59302c88ecff11d4831475ecfa8b8fb0 introduced a change to
the view_flushanddetach() function which makes the latter access
view->zonetable without holding view->lock.  As confirmed by TSAN, this
enables races between threads for view->zonetable accesses.

Swap the view->zonetable pointer under view lock and then detach the
local swapped dns_zt_t later when the view lock is already unlocked.

This commit also changes the dns_zt interfaces, so the setting the
zonetable "flush" flag is separate operation to dns_zt_detach,
e.g. instead of doing:

    if (view->flush) {
        dns_zt_flushanddetach(&zt);
    } else {
        dns_zt_detach(&zt);
    }

the code is now:

    if (view->flush) {
        dns_zt_flush(zt);
    }
    dns_zt_detach(&zt);

making the code more consistent with how we handle flushing and
detaching dns_zone_t pointers from the view.
2022-01-05 16:56:16 +01:00
Michał Kępień
cc1d4e1aa6 Ensure the correct ordering zone_shutdown() vs zone_gotwritehandle()
When the signed version of an inline-signed zone is dumped to disk, the
serial number of the unsigned version of the zone is written in the
raw-format header so that the contents of the signed zone can be
resynchronized after named restart if the unsigned zone file is
modified while named is not running (see RT #26676).

In order for the serial number of the unsigned zone to be determined
during the dump, zone->raw must be set to a non-NULL value.  This
should always be the case as long as the signed version of the zone is
used for anything by named.

However, under certain circumstances the zone->raw could be set to NULL
while the zone is being dumped.

Defer detaching from zone->raw in zone_shutdown() if the zone is in the
process of being dumped to disk.
2022-01-05 10:27:55 +01:00
Artem Boldariev
64f7c55662 Use the TLS context cache for client-side contexts (XoT)
This commit enables client-side TLS contexts re-use for zone transfers
over TLS. That, in turn, makes it possible to use the internal session
cache associated with the contexts, allowing the TLS connections to be
established faster and requiring fewer resources by not going through
the full TLS handshake procedure.

Previously that would recreate the context on every connection, making
TLS session resumption impossible.

Also, this change lays down a foundation for Strict TLS (when the
client validates a server certificate), as the TLS context cache can
be extended to store additional data required for validation (like
intermediates CA chain).
2021-12-29 10:25:15 +02:00
Mark Andrews
dc8595936c remove broken-nsec and reject-000-label options 2021-12-23 15:13:46 +11:00
Mark Andrews
a23507c4fa Pass the digest buffer length to EVP_DigestSignFinal
OpenSSL 3.0.1 does not accept 0 as a digest buffer length when
calling EVP_DigestSignFinal as it now checks that the digest buffer
length is large enough for the digest.  Pass the digest buffer
length instead.
2021-12-17 20:28:01 +11:00
Ondřej Surý
72cc25465f Reduce freemax values for dns_message mempools
It was discovered that NAME_FREEMAX and RDATASET_FREEMAX was based on
the NAME_FILLCOUNT and RDATASET_FILLCOUNT respectively multiplied by 8
and then when used in isc_mempool_setfreemax, the value would be again
multiplied by 32.

Keep the 8 multiplier in the #define and remove the 32 multiplier as it
was kept in error.  The default fillcount can fit 99.99% of the requests
under normal circumstances, so we don't need to keep that many free
items on the mempool.
2021-12-15 21:25:00 +01:00
Ondřej Surý
ce75d4a96b Set the clientmgr isc_mem_t context name
The memory context created in the clientmgr context was missing a name,
so it was nameless in the memory context statistics.

Set the clientmgr memory context name to "clientmgr".
2021-12-14 19:15:58 +00:00
Michal Nowak
9c013f37d0
Drop cppcheck workarounds
As cppcheck was removed from the CI, associated workarounds and
suppressions are not required anymore.
2021-12-14 15:03:56 +01:00
Evan Hunt
157d7bd0e9 incidental cleanups
the 'dipsatchmgr->state' was never set, so the MGR_IS_SHUTTINGDOWN
macro was always false. both of these have been removed.

renamed the 'dispatch->state' field to 'tcpstate' to make its purpose
less ambiguous.

changed an FCTXTRACE log message from "response did not match question"
to the more correctly descriptive "invalid question section".
2021-12-08 10:22:03 -08:00
Evan Hunt
5f82fc11a9 prevent a shutdown hang on non-matching TCP responses
When a non-matching DNS response is received by the resolver,
it calls dns_dispatch_getnext() to resume reading. This is necessary
for UDP but not for TCP, because TCP connections automatically
resume reading after any valid DNS response.

This commit adds a 'tcpreading' flag to TCP dispatches, so that
`dispatch_getnext()` can be called multiple times without subsequent
calls having any effect.
2021-12-08 10:22:03 -08:00
Evan Hunt
4d4cea243a restore the fetch lifetime timer
the lifetime expiry timer for the fetch context was removed
when we switched to using in-band netmgr timeouts. however,
it turns out some dependency loops can occur between a fetch
and the ADB the validator; these deadlocks were formerly broken
when the timer fired, and now there's no timer. we can fix these
errors individually, but in the meantime we don't want the server
to get hung at shutdown because of dangling fetches.

this commit puts back a single timer, which fires two seconds
after the fetch should have completed, and shuts it down. it also
logs a message at level INFO so we know about the problems when
they occur.
2021-12-03 09:49:24 +01:00
Mark Andrews
0aaaa8768f
Reject NSEC records with next field with \000 label
A number of DNS implementation produce NSEC records with bad type
maps that don't contain types that exist at the name leading to
NODATA responses being synthesize instead of the records in the
zone.  NSEC records with these bad type maps often have the NSEC
NSEC field set to '\000.QNAME'.  We look for the first label of
this pattern.

e.g.
	example.com NSEC \000.example.com SOA NS NSEC RRSIG
	example.com RRRSIG NSEC ...
	example.com SOA ...
	example.com RRRSIG SOA ...
	example.com NS ...
	example.com RRRSIG NS ...
	example.com A ...
	example.com RRRSIG A ...

	A is missing from the type map.

This introduces a temporary option 'reject-000-label' to control
this behaviour.
2021-12-02 14:27:18 +01:00
Mark Andrews
733f58a7a5
Allow servers that emit broken NSEC records to be identified
'server <prefix> { broken-nsec yes; };' can now be used to stop
NSEC records from negative responses from servers in the given
prefix being cached and hence available to synth-from-dnssec.
2021-12-02 14:27:14 +01:00
Mark Andrews
454c29046f
Check that SOA and DNSKEY are consistent in NSEC typemaps
If there is a SOA record present then there should also be a
DNSKEY record present as the DNSKEY is supposed to live at the
zone apex like the SOA.
2021-12-02 14:24:37 +01:00
Mark Andrews
5252985a21
Look for covering NSEC under two more conditions
1) when after processing a node there where no headers that
   contained active records.

   When

       if (check_stale_header(node, header, &locktype, lock, &search,
			      &header_prev);

   succeeds or

       if (EXISTS(header) && !ANCIENT(header))

   fails for all entries in the list leading to 'empty_node' remaining
   true.

   If there is are no active records we know nothing about the
   current state of the name so we treat is as ISC_R_NOTFOUND.

2) when there was a covering NOQNAME proof found or all the
   active headers where negative.

   When

	if (header->noqname != NULL &&
	    header->trust == dns_trust_secure)

   succeeds or

	if (!NEGATIVE(header))

   never succeeds.  Under these conditions there could (should be for
   found_noqname) be a covering NSEC earlier in the tree.
2021-12-02 14:24:37 +01:00
Mark Andrews
4bdd5a9953
Ignore NSEC records without RRSIG and NSEC present
dns_nsec_noexistnodata now checks that RRSIG and NSEC are
present in the type map.  Both types should be present in
a correctly constructed NSEC record.  This check is in
addition to similar checks in resolver.c and validator.c.
2021-12-02 14:18:42 +01:00
Mark Andrews
8ff2c133b5
Add dns_nsec_requiredtypespresent
checks an NSEC rdataset to ensure that both NSEC and RRSIG are
present in the type map.  These types are required for the NSEC
to be valid
2021-12-02 14:18:42 +01:00
Mark Andrews
43316a40a0
Record how often DNS_R_COVERINGNSEC is returned from the cache
reported as "covering nsec returned" when dumping cache stats
and as "CoveringNSEC" in json and xml cache statistics.
2021-12-02 14:18:41 +01:00
Mark Andrews
62dd9ec9c1
Report Cache NSEC auxilary database size 2021-12-02 14:18:41 +01:00
Mark Andrews
85bfcaeb2e
Extend dns_db_nodecount to access auxilary rbt node counts
dns_db_nodecount can now be used to get counts from the auxilary
rbt databases.  The existing node count is returned by
tree=dns_dbtree_main.  The nsec and nsec3 node counts by dns_dbtree_nsec
and dns_dbtree_nsec3 respectively.
2021-12-02 14:18:41 +01:00
Mark Andrews
c8a7f92b9e
Allow "black lies" to be cached
"black lies" differ from "white lies" in that the owner name of the
NSEC record matches the QNAME and the intent is to return NODATA
instead of NXDOMAIN for all types.  Caching this NSEC does not lead
to unexpected behaviour on synthesis when the QNAME matches the
NSEC owner which it does for the the general "white lie" response.

"black lie" QNAME NSEC \000.QNAME NSEC RRSIG

"white lie" QNAME- NSEC QNAME+ NSEC RRSIG

where QNAME- is a name that is close to QNAME but sorts before QNAME
and QNAME+ is a that is close to QNAME but sorts after QNAME.

Black lies are safe to cache as they don't bring into existence
names that are not intended to exist.  "Black lies" intentional change
NXDOMAIN to NODATA. "White lies" bring QNAME- into existence and named
would synthesis NODATA for QNAME+ if it is queried for that name
instead of discovering the, presumable, NXDOMAIN response.

Note rejection NSEC RRsets with NEXT names starting with the label
'\000' renders this change ineffective (see reject-000-label).
2021-12-02 14:18:41 +01:00
Mark Andrews
6fae151c9d
Do not cache minimal NSEC records (NSEC + RRSIG only)
these are not useful for dnssec synthesis as they can result in
false NODATA responses and just consume cache memory
2021-12-02 14:18:41 +01:00
Mark Andrews
27acf56ba3
Remove unnecessary dns_rbt_fullnamefromnode call
the results from dns_rbt_fullnamefromnode are not used.
2021-12-02 14:18:40 +01:00
Mark Andrews
89542b8a15
Count DNS_R_COVERINGNSEC as a cache {query}hit
Note when synthesising answer involving wildcards we look in the
cache multiple times, once for the QNAME and once for the wildcard
name which is constucted by looking at the names from the covering
NSEC return by the QNAME miss.
2021-12-02 14:18:40 +01:00
Mark Andrews
3a5652ccb1
Rework rbtdb.c:find_coveringnsec() to use the auxilary nsec rbt
this improves the performance of looking for NSEC and RRSIG(NSEC)
records in the cache by skipping lots of nodes in the main trees
in the cache without these records present.  This is a simplified
version of previous_closest_nsec() which uses the same underlying
mechanism to look for NSEC and RRSIG(NSEC) records in authorative
zones.

The auxilary NSEC tree was already being maintained as a side effect
of looking for the covering NSEC in large zones where there can be
lots of glue records that needed to be skipped.  Nodes are added
to the tree whenever a NSEC record is added to the primary tree.
They are removed when the corresponding node is removed from the
primary tree.

Having nodes in the NSEC tree w/o NSEC records in the primary tree
should not impact on synth-from-dnssec efficiency as that node would
have held the NSEC we would have been needed to synthesise the
response.  Removing the node when the NSEC RRset expires would only
cause rbtdb to return a NSEC which would be rejected at a higher
level.
2021-12-02 14:18:40 +01:00
Evan Hunt
fa8f409af2 On non-matching answer, check for missed timeout
A TCP connection may be held open past its proper timeout if it's
receiving a stream of DNS responses that don't match any queries.
In this case, we now check whether the oldest query should have timed
out.
2021-12-01 11:45:55 -08:00
Ondřej Surý
ba1cadf14a Tear down the TCP connection on too many unexpected DNS messages
When the outgoing TCP dispatch times-out active response, we might still
receive the answer during the lifetime of the connection.  Previously,
we would just ignore any non-matching DNS answers, which would allow the
server to feed us with otherwise valid DNS answer and keep the
connection open.

Add a counter for timed-out DNS queries over TCP and tear down the whole
TCP connection if we receive unexpected number of DNS answers.
2021-12-01 11:45:55 -08:00