If a NODATA answer is returned instead of actual data for A or AAAA
queries because of the existence of --filter-A or --filter-AAAA
config options, then mark the replies with an EDE "filtered" tag.
Basic patch by Petr Menšík, tweaked by Simon Kelley to apply onto
the preceding caching patches.
No longer try and fail to open every port when the port range
is in complete use; go straight to re-using an existing socket.
Die at startup if port range is smaller than --port-limit, since
the code behaves badly in this case.
1) It's expected to fail to bind a new source port when they
are scarce, suppress warning in log in this case.
2) Optimse bind_local when max_port - min_port is small. There's no
randomness in this case, so we try all possible source ports
rather than poking at random ones for an arbitrary number of tries.
3) In allocate_rfd() handle the case that all available source ports
are already open. In this case we need to pick an existing
socket/port to use, such that it has a different port from any we
already hold. This gives the required property that the set of ports
utilised by any given query is set by --port-limit and we don't
re-use any until we have port-limit different ones.
Sending the same query repeatedly to a dnsmasq instance which
doesn't get replies from upstream will eventually hit the
hard limit on frec_src structures and start gettin REFUSED
replies. This is OK, except that since the queries are no longer
being forwarded, an upstream server coming back doesn't reset the
situation. If there is any other traffic, frec allocation will
eventually delete the timed-out frec and get things moving again,
but that's not guaranteed.
To fix this we explicitly delete the frec once timed out in this case.
Thanks to Filip Jenicek for noticing and characterising this problem.
This gives dnsmasq the ability to originate retries for upstream DNS
queries itself, rather than relying on the downstream client. This is
most useful when doing DNSSEC over unreliable upstream network. It
comes with some cost in memory usage and network bandwidth.
By default, when sending a query via random ports to multiple upstream servers or
retrying a query dnsmasq will use a single random port for all the tries/retries.
This option allows a larger number of ports to be used, which can increase robustness
in certain network configurations. Note that increasing this to more than
two or three can have security and resource implications and should only
be done with understanding of those.
Once we have a good answer, close the socket so that the fd can
be reused during DNSSEC validation and we don't have to read and
discard more replies from other servers.
forwarded queries to the configured or default value of
edns-packet-max. There's no point letting a client set a larger
value if we're unable to return the answer.
There are two functional changes in this commit.
1) When searching for an in-flight DNSSEC query to use
(rather than starting a new one), compare the already
sent query (stored in the frec "stash" field, rather than
using the hash of the query. This is probably faster (no hash
calculation) and eliminates having to worry about the
consequences of a hash collision.
2) Check for dependency loops in DNSSEC validation,
say validating A requires DS B and validating DS B
requires DNSKEY C and validating DNSKEY C requires DS B.
This should never happen in correctly signed records, but it's
likely the case that sufficiently broken ones can cause
our validation code requests to exhibit cycles.
The result is that the ->blocking_query list
can form a cycle, and under certain circumstances that can lock us in
an infinite loop.
Instead we transform the situation into an ABANDONED state.
Previously, hash_questions() would return a random hash
if the packet was malformed, and probably the hash of a previous
query. Now handle this as an error.
The 2.86 domain-match rewrite changed matching from
whole-labels to substring matching, so example.com
would match example.com and www.example.com, as before,
but also goodexample.com, which is a regression. This
restores the original behaviour.
Also restore the behaviour of --rebind-domain-ok=//
to match domains with onlt a single label and no dots.
Thanks to Sung Pae for reporting these bugs and supplying
an initial patch.
The IDs logged when --log-queries=extra is in effect
can be wrong in three cases.
1) When query is retried in response to a a SERVFAIL or REFUSED
answer from upstream. In this case the ID of an unrelated query will
appear in the answer log lines.
2) When the same query arrives from two clients. The query is
sent upstream once, as designed, and the result returned to both clients,
as designed, but the reply to the first client gets the log-ID of the
second query in error.
3) When a query arrives, is sent upstream, and the reply comes back,
but the transaction is blocked awaiting a DNSSEC query needed to validate
the reply. If the client retries the query in this state, the blocking
DNSSEC query will be resent, as designed, but that send will be logged with
the ID of the original, currently blocked, query.
Thanks to Dominik Derigs for his analysis of this problem.
The domain-match rewrite didn't take into account
that domain names are case-insensitive, so things like
--address=/Example.com/.....
didn't work correctly.
Behaviour to stop infinite loops when all servers return REFUSED
was wrongly activated on client retries, resulting in
incorrect REFUSED replies to client retries.
Thanks to Johannes Stezenbach for finding the problem.
This patch also changes the method of calling querystr() such that
it is only called when logging is enabled, to eliminate any
possible performance problems from searching the larger table.