If we're doing DNSSEC validation and fail because the upstream
reply to our query is SERVFAIL, log this as the reason in
validation result line.
This will make maintainers lives easier when they get reports
of "wrong" validation failure, which is sometimes an upstream problem.
This may be useful for embedded systems for example:
log-queries without only_failed places a heavy load on the
NAND flash memory. At the same time, logging requests
is necessary to troubleshoot network issues.
The presence of wrong RRSIG RRs in replies causes DNSSEC
validation to fail even when the RRs do not require validation
because the zone is unsigned.
This patch solves the problem and tidies up the logic.
Included is some fixes for hostname_issubdomain() which suffered
some confusions about argument order :) I've clarified that and
checked every to the function to make sure they are using the
correct argument order.
Note that, at the time of this commit, Google DNS appears to have
the same bug, so if you're using 8.8.8.8 or friends as upstream,
resolving the broken zones (eg rivcoed.org) will still fail.
Thanks to Petr Menšík for the bug report.
FreeBSD 15.0 has added Linux-compatible inotify support, so
enable it by looking if the version matches. Since FreeBSD inotify has
seen a few bug fixes in 2025H2, so only enable it if
__FreeBSD_version >= 1500068. The latter can be checked through
osreldate.h or sys/param.h; the latter defines more macros that clash
with dnsmasq's, such as MIN and MAX, so use the former.
If we have a wildcard record *.example.com and recieve a query for
a.example.com then that's OK, but we have to check that there isn't
an actual a.example.com record. The corner case is when we get a
query for *.example.com in that case the non-existence check
is not required, but was being done.
Thanks to Jan Breig for spotting this.
These can't be held forever by a client that opens a connection and
then sends nothing, but we can still be DoSsed by a server which
accepts a connection and never replies.
If the TCP process times out, it sends that information to the
parent so that the UDP query can be unblocked. As the TCP
timeout is 150s it's highly unlikely that any client will
still be waiting, but the point is to free resources.
A general rewrite and consolidation of the code that determines
if an incoming TCP connection is allowed, based on --address and --interface.
This was prompted by a bug found by Sławomir Zborowski where a TCP
connection for a valid IPv4 address on one interface which arrived
via a second interface which didn't have an IPv4 address would be
wrongly rejected.
Description: Fix some issues, some causing lintian warnings
Pointless quotation marks which get displayed in the rendered manual page.
groff-message troff:<standard input>:868: warning:
macro 'Om' not defined
[usr/share/man/sv/man8/dnsmasq.8.gz:1]
groff-message troff:<standard input>:2846: warning:
macro 'SH-FILER' not defined (possibly missing space after 'SH')
[usr/share/man/sv/man8/dnsmasq.8.gz:2]
Author: Sven Geuer <sge@debian.org>
Forwarded: no
Last-Update: 2025-12-04
Description: Fix typos in the english manual page
These typos were reported by Debian's lint tool.
Author: Sven Geuer <sge@debian.org>
Forwarded: no
Last-Update: 2025-12-04
A 'AddDhcpLease' DBus message which fails to allocate
a DHCP lease will cause dnsmasq to dereference a NULL pointer
and crash.
Allocation failure can happen if the particular
flavour (IPv4 pr IPv6) of DHCP is not configured in
this dnsmasq instance, or if the configured limit on
DHCP leases is reached or (unlikley) if dnsmasq cannot
allocate memory.
This patch provides error returns for all these situations.
This patch is inspired by a patch from
Stefan Hanreich <s.hanreich@proxmox.com> which was prompted by
a bug report from Lou Lécrivain.
This was supposed to disallow addresses which are in use by
the DHCP server, and the code works fine when only dhcp-range
is defined per broadcast domain. It's confused when there are
multiple dhcp-ranges which are valid for a particular request.
The options which cause dnsmasq to decorate a DNS query with the MAC
address on the originating client can fail when the query is sent
using TCP.
In TCP mode, dnsmasq spawns a new process to handle each TCP connection.
These child processes do not have an open netlink socket, which is
needed to read the kernel ARP table, so the process of adding the
client's MAC address as an EDNS0 option silently fails.
This is fixed by this patch by updating dnsmasq's ARP cache in the
main process just before forking the TCP-handler child process.
This ensures that the copy of the ARP cache inherited by the
TCP-handler contains the information required without the need to
read the kernel ARP table.
Thanks to Bruno Ravara for spotting and characterising this bug.
This change attempts to optimse TFTP perfomance.
It reads the next block immediately after sending a block,
in order to reduce latency between receiving an ACK and sending
the next block. Is also suppresses lseek() calls when reading
successive blocks.
This improves performance when doing transfers without windowing
and when only a single transfer is in progress at one time.
get_new_frec() garbage collects struct frec when they are
(by default) 40s old. This means that in an active dnsmasq
which is getting new queries, answers to old queries start to
be ignored soon after they hit 40s old. If there are no new
queries, get_new_frec() doesn't get called, and answers to old
queries will still be accepted for longer.
This patch stops lookup_frec() from returning old frecs which
are ready for GC. This helps avoid yet another variation
on the birthday attack, which is no particularly relevant,
given the need for an idle server.
get_new_frec() is not supposed to ever free an frec when
the force arg is set. Make this so. In theory, this fixes
a bug, but it's practically impossible to provoke and I have
no evidence that it has ever happened IRL.
TFTP fails with a timeout when the transfer exceeds 128K blocks.
The block field in an ACK packet is 16 bits, so large transfers
need to deal with this field wrapping. Testing failure meant
that it worked for the first wrap, but not for subsequent ones.
Having fixed the block number problem, file size calculations
accidentally being done in 32 bits not 64 bits then broke
transfers larger than 2G or maybe 4G.
The first problem was probably introduced in commit
ebef27f321 and has not appeared
in a stable release. The second appears to have been there forever.
Clearly, nobody is mad enough to transfer multi-gigabyte files
over TFTP.
Thanks to Jean-François JUBLIN for spotting this and supplying
useful packet dumps that made it easy to diagnose.
To provoke this bug, at least the following must be true.
A reply must be a CNAME.
The target of the CNAME must not exist for the queried RR (a No Data reply).
The No Data reply must include an SOA record in the NS section.
The query must take place over TCP.
The result is the caching of a CNAME whose target is the
name of the SOA record, instead of the No data record.
If there is a RR at this target, then a subsequent query for that
RRtype will get a qrong reply.
Thanks to the testers extraordinaire at Pi-Hole for spotting this
and providing enough information to chase it down.
Change the behaviour of the DHVPv6 server when a REBIND message
is received but no lease exists. Under these circumstances a new
lease is created _only_ when the --dhcp-authoritative option is
set. This matches the behavior of the DHCPv4 server.
Reading /etc/ethers assumes that dhcp-host cofig has already
been read, and that is the case for dhcp-host, but for unknown
reasons, the analogous congiguration is dhcp-hostfile was being
read after /etc/ethers.
Swap the order.
Thanks to Andreas Kuropka for spotting the problem.
servers for plain names (server=//1.2.3.4) as domain-specific.
This means that if we fail to get a DS record for such a query,
it gets given the benefit of the doubt.
Updates 57f0489f38
This fixes a problem introduced in 8a5fe8ce6b
On BSD, fdescfs is normally mounted at /dev/fd. However
if it is NOT mounted, devfs creates a directory at /dev/fd
which contains (only) the file descriptors 0,1 and 2.
Under these conditions, opendir() will succeed, and
if we proceed we will fail to close extant
file descriptors which should be closed.
Check that there is a filesystem mounted at /dev/fd
by checking that the device changes between /dev/fd
and /dev. If if doesn't, fall back to the dumb path.
Thanks to Roman Bogorodskiy for spotting the problem
and helping with diagnosis.