[Dnsmasq-discuss] Don't mix local (hosts/DHCP/config) records with cached upstream data
Dominik Derigs
dl6er at dl6er.de
Fri Jun 19 18:56:42 UTC 2026
Hi Simon, all,
we have run into a case where dnsmasq returns an authoritative local record
together with a cached upstream record for the same name, and additionally
forwards the query upstream even though it already has a local answer.
It happens when an upstream answer for a name is cached before a local
record
for that same name comes into existence, which is easy to hit with a
hostsdir:
adding or modifying a hosts file there triggers an inotify reload of
just that
file, without flushing the rest of the cache. The previously cached upstream
record stays around (and, with --use-stale-cache, lingers as a stale
entry once
its TTL passes). On the next query, answer_request() walks the whole
cache chain
for the name and adds both records to the reply; the expired upstream record
also sets *stale, which forwards the query to refresh it.
A restart clears the cache and the symptom disappears until the name is
resolved
upstream again, which is what makes it look intermittent.
Minimal reproducer (two loopback instances, no real network):
# upstream, authoritative for repro.test with a short TTL
dnsmasq --port=5392 --listen-address=127.0.0.1 --bind-interfaces \
--no-resolv --no-hosts --keep-in-foreground \
--address=/repro.test/192.0.2.50 --local-ttl=2 &
mkdir -p /tmp/hd
# under test
dnsmasq --port=5391 --listen-address=127.0.0.1 --bind-interfaces \
--no-resolv --no-hosts --keep-in-foreground \
--server=127.0.0.1#5392 --hostsdir=/tmp/hd \
--use-stale-cache=3600 --log-queries=extra &
dig +short @127.0.0.1 -p 5391 repro.test A # prime cache ->
192.0.2.50
echo "192.168.0.99 repro.test" > /tmp/hd/custom.list
sleep 4 # let the upstream
entry go stale
dig +noall +answer @127.0.0.1 -p 5391 repro.test A
Before the patch the final answer contains both 192.168.0.99 (local) and
192.0.2.50 (stale upstream), and the log shows the query being
forwarded. After
the patch only 192.168.0.99 is returned, with no forward.
The fix relies on cache_find_by_name() returning all local
(F_HOSTS/F_DHCP/F_CONFIG) records for a name ahead of any cached
records: once a
local record has answered, stop at the first non-local record so it is
neither
added to the reply nor allowed to set *stale. Multiple local records,
and the
normal case of multiple cached upstream records with no local record, are
unaffected.
Patch attached.
Warm regards,
Dominik
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Don-t-mix-local-hosts-DHCP-config-records-with-cache.patch
Type: text/x-patch
Size: 2756 bytes
Desc: not available
URL: <http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/attachments/20260619/080a5d16/attachment.bin>
More information about the Dnsmasq-discuss
mailing list