Compare commits

..

1411 Commits

Author SHA1 Message Date
Conrad Kostecki
d8f66f4fda Update German translations. 2025-12-07 13:44:40 +00:00
Simon Kelley
629107bd6d Merge OOB memory read fix. CVE-2025-54318 2025-12-06 14:04:23 +00:00
Sven Geuer
05464a173b Fix some issues with the swedish manual page, some causing lintian warnings
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
2025-12-05 15:13:54 +00:00
Sven Geuer
ae3d3d971e Fix typos in the english manual page
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
2025-12-05 15:13:45 +00:00
Sven Geuer
d1845782d6 Remove trailing white space from dnsmasq.conf.example
Description: Remove trailing white space
 For now only the file reported in bug #1022706 is handled by this patch while
 upstream has been informed about all existing cases.
Bug-Debian: https://bugs.debian.org/1022706
Forwarded: https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2024q4/017826.html
Author: Sven Geuer <sge@debian.org>
Last-Update: 2024-11-23
2025-12-05 15:12:28 +00:00
Matthias Andree
edb5f85fd1 CHANGELOG: Fix two typos 2025-12-05 15:10:31 +00:00
Simon Kelley
cef74423e2 Log error if we try and use netlink in a child process.
Child processes to handle TCP connections don't
have an open netlink socket. If they call
iface_enumerate() that's a bug.
2025-12-01 09:52:51 +00:00
Simon Kelley
959dead673 More fixes for DHCP ops in Dbus when DHCP not configured.
Following eb60168382
2025-11-30 22:59:27 +00:00
Simon Kelley
eb60168382 Fix SEGV in Dbus code.
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.
2025-11-28 16:10:37 +00:00
Simon Kelley
57a2f5778c Fix confusion in address checking code.
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.
2025-11-28 15:14:09 +00:00
Simon Kelley
7d5fbe7da3 Fix failure to add client MAC address to queries in TCP mode.
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.
2025-11-26 21:54:59 +00:00
Petr Menšík
ded935be37 Add captive-portal name support for DHCP options
Adds support into DHCP and DHCPv6 record. Useful for announcing URL for
captive portal API URI.

https://www.rfc-editor.org/rfc/rfc8910.html
2025-11-18 22:41:15 +00:00
Simon Kelley
aa9b71c681 Merge translated strings. 2025-11-18 22:20:42 +00:00
Daniel Nylander
e497f3f2c8 Add Swedish translation.
Thanks to Daniel Nylander.
2025-11-18 22:18:02 +00:00
Simon Kelley
ee09f0655c Optimise tftp.
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.
2025-09-01 22:35:02 +01:00
Simon Kelley
1e83316e06 Formatting. 2025-08-21 22:13:43 +01:00
Simon Kelley
9a566c0913 Tweak recently altered TFTP code. 2025-08-21 16:19:58 +01:00
Simon Kelley
06e2d479c9 Stop lookup_frec() returning old records.
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.
2025-08-21 14:17:01 +01:00
Simon Kelley
b52d1d2017 Tweak get_new_frec() behaviour in "force" mode.
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.
2025-08-21 13:21:27 +01:00
Simon Kelley
18195e7bb2 Useful error logging in dhcp-split-relay code. 2025-08-21 13:05:24 +01:00
Simon Kelley
d81b1d76a0 Fix TFTP problems with large files.
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.
2025-08-21 12:49:09 +01:00
Simon Kelley
1677c6e10b More development on dhcp-split-relay. 2025-08-20 12:36:03 +01:00
Simon Kelley
ff30fa4b91 Fix caching bug with negative records.
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.
2025-08-11 16:53:40 +01:00
Simon Kelley
c91c66ee63 Get destination address of received DHCPv4 packets right in dumpfile. 2025-07-27 16:23:59 +01:00
Simon Kelley
fc9f6985ab Add --dhcp-split-relay option.
This makes a DHCPv4 relay which is functional when
client and server networks aren't mutually route-able.
2025-07-27 15:27:40 +01:00
Simon Kelley
ea5b0e64e2 Make DHCP6ADVERTISE messages RFC 8415 compliant.
Include IA_* options even if no addresses are allocated, and
always return options specified in ORO.
2025-07-23 21:05:40 +01:00
Simon Kelley
e775264539 Fix wrong status in reply to DHCP6REQUEST.
If we jump to label request_no_address, address_assigned
has an undefined value, and maybe the wrong status is returned.
2025-07-23 21:04:06 +01:00
Simon Kelley
d976d94e3d Implement RFC 6221 para 4.
If the link address in a relayed DHCPv6 message is zero, don't
use it for addresss selection.
2025-07-22 22:09:49 +01:00
Simon Kelley
3034746748 Allow --dhcp-authoritative to control recreation of missing leases in DHCPv6.
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.
2025-07-22 21:51:47 +01:00
Simon Kelley
3ceea9e755 Fix packet validation in DHCPv6.
Some messages must be sent as multicast.
2025-07-22 20:43:52 +01:00
Geert Stappers
dfcef19fb4 Added a tail to .hmtl files
HTML-files `doc.html` and `setup.html` were missing closing tags.
Also some empty lines removed.

Signed-off-by: Geert Stappers <stappers@stappers.nl>
2025-07-20 15:29:43 +01:00
Simon Kelley
052aa0fcf3 Fix bounds checking in check_ia()
A malformed DHCP request can cause out-bounds memory reads, and probably SEGV.
2025-07-15 15:18:12 +01:00
Simon Kelley
f74b74e521 Refactor relay_reply6().
Traverse the nested data structures more efficiently,
more understandably, and with watertight checking of
buffer boundaries.
2025-07-15 15:17:46 +01:00
Simon Kelley
c9342cb556 Check for constructed name in --srv-host exceeding length limit.
Thanks to Mikhail Dmitrichenko for spotting this.
2025-07-15 15:15:32 +01:00
Simon Kelley
2b844b8c83 Fix BNF from --srv-host in manpage. 2025-07-14 15:15:26 +01:00
Simon Kelley
65e9a8957c Fix order of reads dhcp-hostsfile and /etc/ethers.
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.
2025-07-10 10:58:14 +01:00
Simon Kelley
da868a2fbe Restore bit-rotted warning about non-recursive upstreams. 2025-07-08 16:18:03 +01:00
Simon Kelley
bceb5287b9 Fix FTBFS on MacOS.
Fallout from 98189ff988

Thanks to Travis Rayan for the bug report.
2025-07-07 17:58:41 +01:00
Simon Kelley
84445dec26 Fix server selection for DS queries.
This was mainly done in 57e582492b
This commit extends the new behaviour to cases where DNSSEC
validation is not compiled-in or not enabled.
2025-07-07 17:16:32 +01:00
Rob Gill via Dnsmasq-discuss
c70b92b2a4 Add CG-NAT range to non-globally routed IP space per RFC7793
The Shared address space (100.64.0.0/10) used by CG-NAT, defined in RFC6598 should
not have reverse DNS queries sent to global DNS infrastructure.

Confirmed in RFC7793 and listed on
https://www.iana.org/assignments/locally-served-dns-zones/locally-served-dns-zones.xhtml

Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-06-26 13:10:48 +01:00
Simon Kelley
57e582492b Fix to 57f0489f38
When choosing a server to send a DS query to take
account of the need for DS records for a domain
to come from the parent of that domain.
2025-06-25 15:02:47 +01:00
Simon Kelley
ec8f3e65c1 Tweak domain-specific servers and DNSSEC code to treat
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
2025-06-23 21:48:29 +01:00
Simon Kelley
15841f187d Fix issue with fast file-descriptor close on *BSD.
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.
2025-06-22 23:04:36 +01:00
Simon Kelley
ade97495e6 Trvial formatting fix. 2025-06-20 17:12:32 +01:00
Simon Kelley
2b19285724 Fix breakage of ipset on *BSD.
Regression introduced in 98189ff988

Thanks to Harper Andrews for spotting this.
2025-06-20 15:48:47 +01:00
Simon Kelley
a444715bf0 Fix FTBFS on Jurassic gcc versions. 2025-06-20 15:27:43 +01:00
Simon Kelley
14e81b6976 Additional sanity check in filter_servers(). 2025-06-06 23:33:25 +01:00
Simon Kelley
6ce7f2d55a Fix regression in 9e67099ce7
Logging queries lost the RRtype.

Revert to e.g. query[A] example.com
2025-06-06 23:29:31 +01:00
Simon Kelley
287d6bc88d Fix 5846f749e5
Not sure how that bug got in there. Very (un)lucky choice
of test data, or last-minute "it'll be fine" modification I guess.

It was late, I can't remember.

Thanks to Dominik Derrigs for spotting the problem.
2025-06-03 22:16:50 +01:00
Simon Kelley
c378d2c1de Fix crash in filter_servers().
The bug occurs when we ask lookup_domain() for a server for a domain
which is not a general upstream server, by setting F_DOMAINSRV in the flags.

If there are no possible servers, because there are no upstream servers
defined (for instance, at startup) then the code steps off the end of an
array and SEGVs.

The bug has been latent for some time, but
3e659bd4ec added a new call to lookup_domain()
which can actually trigger the bug if DNSSEC is enabled and a certain
amount of bad luck ensues.

Thanks to the testers extraordinaire at PiHole for reporting this.
2025-06-02 22:37:08 +01:00
Simon Kelley
5846f749e5 Rewrite chunks of inotify.c to remove a memory leak.
The code is much easier to follow now, this shouldn't
happen again.
2025-05-29 22:44:15 +01:00
Matthias Andree
c9a4240ec4 Unbreak compilation on non-Linux systems (FreeBSD)
and put the void cast of netlink_warn under the same preprocessor
condition as its definition, #ifdef HAVE_LINUX_NETWORK.
2025-05-25 21:15:41 +01:00
Simon Kelley
e7b87dee85 Tftp code tweaks. 2025-05-24 21:15:02 +01:00
Simon Kelley
90b248582c Remove compiler warnings for obscure combinations of build options. 2025-05-24 15:09:53 +01:00
Simon Kelley
ebef27f321 Add TFTP options windowsize (RFC 7440) and timeout (RFC 2349). 2025-05-24 14:41:40 +01:00
Matthias Andree
1861a881eb Only define variable "a" if we HAVE_LINUX_NETWORK
Variable unsigned char a is defined unconditionally,
but it is only used if HAVE_LINUX_NETWORK is defined.
This triggers compiler warnings on, say, FreeBSD.

Fix by wrapping the definition in proper #ifdef.
2025-05-21 19:48:39 +01:00
Matthias Andree
96bdb42d40 Fix GCC's -Wunterminated-string-initialization warning in edns0.c.
GCC complains that writing the five-character "ODNS\0" string into
a four-element char magic[4] array truncates the NUL character.
The warning's rationale is that this is incompatible with C++, or
maybe non-intentional.

GCC 8 has added a nonstring variable attribute, clang 20.1 does
not yet support this, but clang's Git head does.

Add an ATTRIBUTE_NONSTRING macro, currently only defined on GCC >= 8
as __attribute__ ((nonstring)).  This successfully suppresses
the warning on Fedora Linux 42's default compiler.

The alternative would be to replace the "ODNS" literal by {0} and
instead memcpy(opt.magic, "ODNS", sizeof(opt.magic)); on the next line,
which is correct, C++ compatible, but also less concise.
2025-05-21 15:06:27 +01:00
Simon Kelley
c7a909ad65 Add RRtypes HHIT and BRID to the table. 2025-05-21 15:03:51 +01:00
Simon Kelley
baf3c57af5 Fix compiler warnings. 2025-05-18 18:22:48 +01:00
Simon Kelley
e48a2af4f5 Overhaul extract_addresses() function.
The proximate cause for doing this is to fix a bug that
causes replies to PTR queries with more than one answer to have the
second and subsequent answers ignored.

The fix turned into a small re-write which removed a very old hack.
When caching reponses which include CNAME records, the cache system
stores the CNAME with a link to the record representing the target of
the CNAME. This isn't possible for PTR records representing IP
addresses since the name stored is the target of the PTR, record and
its name is inferred from the address in the cache record. Such
cache records have the F_REVERSE flag set. To get
around this, long ago, the code which stores such records elided the
CNAME entirely, so
4.3.2.1.in-addr.arpa   CNAME 18/3.2.1.in-addr.arpa
18/3.2.1.in-addr.arpa   PTR   myhost.example.com

would be stored as
4.3.2.1.in-addr.arpa PTR   myhost.example.com

and returned from the cache to subsequent requestor in that form.

Since that hack was committed, dnsmasq has learned to cache arbitrary
RRs. So now we can store the PTR records for all the no-trivial cases.

The means the CNAME chains ending in PTR records don't get mangled,
and we can store PTR records whose name in not w.x.y.x.in-addr.arpa
or the IPv6 equivalent.
2025-05-18 17:24:41 +01:00
Simon Kelley
91b800cc62 CHANGELOG update. 2025-05-14 22:38:14 +01:00
Simon Kelley
075e4a56b7 --leasequery can now take a subnet argument. 2025-05-14 22:36:03 +01:00
Simon Kelley
48658ebc54 Add address filtering for leasequery. 2025-05-14 22:36:03 +01:00
Simon Kelley
692ed0dd32 Log source address of leasequeries. 2025-05-14 22:36:03 +01:00
Simon Kelley
43805c1859 Omit message type from leasequery.c option dump. 2025-05-14 22:36:03 +01:00
Simon Kelley
4fbe1add95 Implement RFC-4388 DHCPv4 leasequery. 2025-05-14 22:35:51 +01:00
Simon Kelley
57c7ae8fc0 CHANGELOG update. 2025-05-14 22:33:44 +01:00
Simon Kelley
d1008215dc Better error message when rejecting a TFTP transfer. 2025-05-14 21:15:17 +01:00
Simon Kelley
b0aa604fcc Tidy-up of TCP-child pipe handling code.
Functionality is unchanged, but the code is easier to read and understand.

Also fix memory leak of blocks when cache insert fails.
2025-05-11 15:30:30 +01:00
Simon Kelley
8ddabd11bc DNSSEC validation change for reverse lookups in RFC-1918 ranges and friends.
The large public DNS services seem not to return proof-of-nonexistence
for DS records at the start of RFC-1918 in-addr.arpa domains and the their
IPv6 equivalents. 10.in-addr.arpa, 168.192.in-addr.arpa etc.

Since dnsmasq already has an option which instructs it not bother
upstream servers with pointless queries about these address ranges,
namely --bogus-priv, we extend that to enable behaviour which allows
dnsmasq to assume that insecure NXDOMAIN replies for these domains
are expected and to assume that the domains are legitimately unsigned.

This behaviour only matters when some address range is directed to
another upstream server using --rev-server. In that case it allows
replies from that server to pass DNSSEC validation. Without such a
server configured, queries are never sent upstream so they are never
validated and the new behaviour is moot.
2025-05-09 21:46:50 +01:00
Simon Kelley
98189ff988 Fix problems with ipset or nftset and TCP DNS transport.
If DNS is happening over TCP, the query is handled by a forked
process. Of ipset ot nftset is configured, this might include
inserting addresses in the *sets. Before this update, that
was done by the forked process using handles inherited from the
parent "master" process.

This is inherently racy. If the master process or another
child process tries to do updates at the same time, the
updates can clash and fail.

To see this, you need a busy server doing lots of DNS
queries over TCP, and ipset or nftset configured.

Going forward, we use the already established pipe to send the
updates from the child back to the master process, which
serialises them.
2025-05-08 16:07:19 +01:00
Simon Kelley
e86d53c438 Fix some edge cases wth domains and --address and --server.
Consider what happens when the same domain appears in
--address and --server.

This commit fixes the order, I think correctly like this:
highest to lowest priority.

--address with a IPv4 or IPv6 address (as long as the query matches the type)
--address with # for all-zeros, as long as the query is A or AAAA)
--address with no address, which returns NXDOMAIN or NOERROR for all types.
--server with address set to # to use the unqualified servers.
--server with matching domain.
--server without domain or from /etc/resolv.conf.

Note that the above is only valid when same domain appears.
The domain being matched is determined first, and has a higher
priority, so you can send google.com to a server and force com
to return NXDOMAIN and for google.com the server config will
override the address config, because there's a longer match.
2025-04-29 16:33:22 +01:00
Simon Kelley
e127a972d1 Fix logging booboo. 2025-04-27 23:25:30 +01:00
Simon Kelley
a458c2bfb0 Tidy up pipe-to-parent code in DNS TCP path. 2025-04-23 12:14:00 +01:00
Simon Kelley
9e67099ce7 Tidy up replies to non-QUERY DNS opcodes in auth mode. 2025-04-22 18:07:24 +01:00
Rob Gill
cfa1313e1f Log format error from upstream as 'FORMERR'
Signed-off-by: Rob Gill <rrobgill@protonmail.com>

At the moment if a misformatted query is reported by the upstream server
it is not clear from the log.
Other error codes from RFC1035 (server failure, not implemented,
refused) are logged with text, but format error is logged merely as "1".

Such that an upstream reporting a format error is presently logged as eg:
Apr 20 12:01:55 dnsmasq[3023]: reply error is 1

After this patch they are logged informatively, eg:
Apr 20 12:48:40 dnsmasq[3023]: reply error is FORMERR

This is a two line fix, FORMERR is already defined in dns-protocol.h.
2025-04-20 22:38:43 +01:00
Simon Kelley
e3a2c8dadf Add --log-queries=auth option. 2025-04-20 22:20:52 +01:00
Simon Kelley
95b74a7acf Fix copy 'n paste error in DBUS server-statistics code. 2025-04-18 23:50:46 +01:00
Simon Kelley
ae57f84061 Do a better job of 942a35f517 2025-04-18 14:01:14 +01:00
Simon Kelley
0620309b73 Revise negative DNS caching to better comply with RFC2308. 2025-04-16 21:29:42 +01:00
Opty
942a35f517 Silence compiler warnings. 2025-04-16 16:00:47 +01:00
Simon Kelley
83658efbf4 Fix occasional crashes with DNSSEC and large nunbers of --address configs.
Commit 3e659bd4ec removed the concept of
an usptream DNS server which is capable of DNSSEC: they are all
(at least in theory) now usable. As a very unfortunate side-effect,
this removed the filter that ensured that dnssec_server() ONLY
returns servers, and not domains with literal addresses.

If we try and do DNSSEC queries for a domain, and there's
a --address line which matches the domain, then dnssec_server()
will return that. This would break DNSSEC validation, but that's
turns out not to matter, because under these circumstances
dnssec_server() will probably return an out-of-bounds index into
the servers[] array, and the process dies with SIGSEGV.

Many thanks to the hard workers at the Tomato project who
found this bug and provided enough information to diagnose it.
2025-04-04 22:01:51 +01:00
Paul Donald
b0b4d90b6a Multiple typo and spelling fixes. 2025-03-29 21:41:40 +00:00
Simon Kelley
bdce03f928 DNAME documentation update. 2025-03-15 17:02:02 +00:00
Simon Kelley
d390dc0338 Implement RFC6672 para 5.3.2. check for DNAME.
Also fix overflow checking of NSEC type maps.
2025-03-15 16:47:55 +00:00
Simon Kelley
105c25e561 Fix DNSSEC and DNAME.
Do the correct things to validate replies which
include a DNAME record.

Thanks to Graham Clinch for pointing this out.
2025-03-15 09:05:47 +00:00
Simon Kelley
67e07b7fe8 Make extract_name() easier to call operating on first name in message. 2025-03-14 15:12:46 +00:00
Simon Kelley
f5659b406b Move find_pseudoheader() before add_edns0_config() in TCP codepath.
There's no point in checking if the query has edns0 headers _after_
adding our own.

This has the affect that if --add-cpe-id or --add-subnet or their friends
are configured,  a query via TCP without EDNS0 will get an answer with EDNS0.

It's highly unlikely that this breaks anything, but it is incorrect.

Thanks to  Tijs Van Buggenhout  for spotting this.
2025-03-14 15:12:46 +00:00
Simon Kelley
484fea238a Silence compiler warning. 2025-03-14 15:12:46 +00:00
Simon Kelley
1e587bec57 Silence compiler warning. 2025-03-14 15:12:45 +00:00
Simon Kelley
581c201aa8 Avoid division by zero with unlucky choices of max-port and min-port. 2025-03-14 15:12:45 +00:00
Simon Kelley
5487f6979e Fix (benign) use of uninitialised data. 2025-03-14 15:12:45 +00:00
Simon Kelley
99f12e3541 Default --dump-mask to all-on, rather than all-off. 2025-03-14 15:12:45 +00:00
Simon Kelley
7c1212e3d1 Fix query-combining for queries with class other than IN.
Along the way, use of extract_request() and extract_name() got further
refined.
2025-03-14 15:12:45 +00:00
Simon Kelley
0ccbdf8087 Make extract_name() easier to call operating on first name in message. 2025-03-14 15:12:45 +00:00
Simon Kelley
57f0489f38 Redesign the interaction between DNSSEC vaildation and per-domain servers.
This should just work in all cases now. If the normal chain-of-trust exists into
the delegated domain then whether the domain is signed or not, DNSSEC
validation will function normally. In the case the delgated domain
is an "overlay" on top of the global DNS and no NS and/or DS records
exist connecting it to the global dns, then if the domain is
unsigned the situation will be handled by synthesising a
proof-of-non-existance-of-DS for the domain and queries will be
answered unvalidated; this action will be logged. A signed domain
without chain-of-trust can be validated if a suitable trust-anchor
is provided using --trust-anchor.

Thanks to Uwe Kleine-König for prompting this change, and contributing
valuable insights into what could be improved.
2025-03-14 15:12:45 +00:00
Simon Kelley
3e659bd4ec Remove the concept of "DNSSEC incapable servers".
We're going to replace this with configured or extrapolated DS records.
2025-03-14 15:12:45 +00:00
Tijs Van Buggenhout
9af15871e6 Fix crash when no upstream servers defined.
This is a regession introduced in 3b6df06fb8.

When dnsmasq is started without upstreams (yet), but a
DNS query comes in that needs forwarding dnsmasq now potentially crashes as
the value for "first" variable is undetermined.

A segmentation violation occurs when the index
is out of bounds of  serverarray.

Credits go to pedro0311 <pedro@freshtomato.org>
2025-03-14 15:09:35 +00:00
Simon Kelley
5897e79d05 Fix bogus compiler warnings. 2025-03-12 15:44:19 +00:00
Simon Kelley
fc9135ca9f Documentation for --do-0x20-encode. 2025-03-09 16:15:16 +00:00
Simon Kelley
e427d4b0e6 Default-off 0x20 encoding and provide --do-0x20-encode option.
For now, this causes too many problems to default on.

Hopefully this will change for future releases.
2025-03-04 12:59:17 +00:00
Simon Kelley
9df1bd0cc1 Revert 368ceff6e0 and fix correct problem.
The next() function is broken for any TFTP packet with padding
which doesn't end with a zero.

Rewrite to handle such packets.

Thanks to Helge Deller <deller@gmx.de> for persisting in finding the
actual problem and proposing a solution. This patch is modelled on his,
but rewritten for personal preference by Simon Kelley, who is
responsible for all bugs.
2025-03-01 22:43:23 +00:00
Simon Kelley
5990074ab0 Fix stupid error in allocating 0x20-flip bitmaps. 2025-02-21 14:41:34 +00:00
Simon Kelley
dbb69bd192 Merge branch 'master' of onyx:dnsmasq/dnsmasq 2025-02-21 13:08:26 +00:00
Simon Kelley
d17581c4c6 Use correct packet length when 0x20 flipping truncated packet.
This makes no difference in practice, since only the query is
operated on, but it is more correct.
2025-02-21 13:02:04 +00:00
Simon Kelley
2c9ed7f425 Fix possible problems with case-encode bigmap array allocation. 2025-02-20 22:59:04 +00:00
Simon Kelley
717ff6adc3 Update plen when getting retried query from stash.
They should be equal, but that depends on untrusted data.
2025-02-10 12:26:15 +00:00
Simon Kelley
f9f8d19bf5 Yet another 0x20 fix.
To complement the previous one, which fixed the retry path
when the query is retried from a different id/source address, this
fixes retries from the same id/source address.
2025-02-09 11:06:59 +00:00
Simon Kelley
535be2f5d3 Fix possible SIGSEGV in bpf.c 2025-02-08 22:58:42 +00:00
Simon Kelley
bceab45dbe Fix 0x20 problem.
A retry to upstream DNS servers triggered by the following conditions

1) A query asking for the same data as a previous query which has not yet been answered.
2) The second query arrives more than two seconds after the first.
3) Either the source of the second query or the id field differs from the first.

fails to set the case of the retry to the same pattern as the first attempt.

However dnsmasq expects the reply from upstream to have the case
pattern of the first attempt.

If the answer to the retry arrives before the answer to the first
query, dnsmasq will notice the case mismatch, log an error, and
ignore the answer.

The worst case scenario would be the first upstream query or reply is
lost and there would follow a short period where all queries for that
particular domain would fail.

This is a 2.91 development issue, it doesn't apply to previous stable releases.
2025-02-07 19:56:33 +00:00
Helge Deller
368ceff6e0 TFTP off-by-2 bugfix
Some of my PA-RISC UNIX machines boot remotely via tftp, but dnsmasq
randomly fails to deliver (the identical file) to some of the machines.

I traced the issue and basically dnsmasq fails with error "unsupported
request from IP.x.y.z" (line 366 in tftp.c).

Here is an example package which is sent (516 hex bytes):
76 6d 6c 69 6e 75 78 00 6f 63 74 65 74 00 12 74 10 3c 00 00 00 00 00 01
a9 24 00 00 00 00 00 00 1e 38 00 00 00 00 00 00 1c a0 00 00 00 00 00 00
1d 08 00 00 00 00 00 00 1d 28 00 00 00 00 00 00 08 00 00 00 00 00 00 00
03 d8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1d 30 00 00 00 02 ff e0
00 00 00 00 03 60 a8 49 55 93 00 00 00 01 f0 d4 21 e4 00 00 00 00 00 00
1d 78 00 00 00 f0 f0 d8 51 38 00 00 00 f0 f0 d4 21 c0 00 00 00 00 00 00
00 00 00 00 00 00 00 01 aa b8 00 00 00 f0 f0 e9 62 7c 00 00 00 00 00 00
03 01 ff ff ff ff ff ff 03 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00
00 03 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 04 ff ff ff ff ff ff
ff ff 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 00 00
00 05 00 00 00 00 00 00 1e 38 00 00 00 00 00 00 00 60 00 00 00 00 00 01
a6 68 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 ff 00 00 00 00 00 00
00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00
00 00 00 00 00 f0 f0 d8 4f 30 00 00 00 00 00 00 00 01 00 00 00 00 00 00
00 00 00 00 00 00 00 01 ae ec 00 00 00 00 00 00 1f 70 00 00 00 00 00 00
1e b8 00 00 03 60 a8 49 55 93 00 00 00 02 18 71 1a 00 00 00 00 00 00 00
00 03 00 00 00 00 00 00 00 03 00 00 00 00 00 00 1e 38 00 00 00 00 00 00
00 07 00 00 00 00 00 00 00 00 00 00 00 f0 f0 d2 f0 70 00 00 00 00 00 00
1f c0 00 00 00 f0 f0 d4 0b e8 00 00 00 00 00 00 00 01 00 00 00 00 00 00
00 60 ff ff ff fc 00 60 18 00 00 00 00 00 00 00 00 00 00 00 00 f0 f0 d8
8f d0 00 00 00 00 00 00 1f f8 00 00 00 00 00 00 00 00 00 00 00 f0 f0 d8
8d b8 00 00 00 00 00 00 1e e8 00 00

Please note the last 3 bytes: "e8 00 00".
If the 3rd last byte is "00", then dnsmasq works and it fails it it's "e8".

So, the bug is in line 366 of tftp.c:
   filename = next(&p, end)
Here filename gets the value NULL from next(), because the "end" variable is off-by-2.
The fix is to change line 363 to add an offset of 2:
  end = packet + 2 + len;

Signed-off-by: Helge Deller <deller@gmx.de>
Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2293793
2025-02-06 17:04:06 +00:00
Simon Kelley
77c4e95d4a Fix for case-sensitivity problems in DNS.
Fix a case sensitivity problem which has been lurking for a long while.
When we get example.com and Example.com and combine them, we send whichever
query arrives first upstream and then later answer it, and we also
answer the second with the same answer. That means that if example.com
arrives first, it will get the answer example.com - good - but Example.com
will _also_ get the answer example.com - not so good.

In theory, fixing this is simple without having to keep seperate
copies of all the queries: Just use the bit-vector representation
of case flipping that we have for 0x20-encoding to keep the
differences in case. The complication comes from the fact that
the existing bit-vector code only holds data on the first 32 alpha
letters, because we only flip that up to many for 0x20 encoding.

In practise, the delta between combined queries can almost always
be represented with that data, since almost all queries are
all lower case and we only purturb the first 32 letters with
0x20 encoding. It's therefore worth keeping the existing,
efficient data structure for the 99.9% of the time it works.
For the 0.1% it doesn't, however, one needs an arbitrary-length data
structure with the resource implications of that.

Thanks to Peter Tirsek for the well researched bug report which set me
on to these problems.
2025-02-06 17:02:50 +00:00
Simon Kelley
e44165c0f7 Fix bug in 0x20 encoding.
We must only compare case when mapping an answer from upstream
to a forwarding record, not when checking a query to see if it's a
duplicate. Since the saved query name is scrambled, that ensures
that almost all such checks will wrongly fail.

Thanks to Peter Tirsek for an exemplary bug report for this.
2025-02-06 10:36:21 +00:00
Simon Kelley
a1a214c393 Bump date on manpage. 2025-02-05 21:34:54 +00:00
Simon Kelley
94b7144a1b Fix c99ism added in 0b6144583b 2025-02-05 21:02:54 +00:00
Matthias Andree
e72910dec8 Spell check v2.91 CHANGELOG 2025-02-05 20:46:55 +00:00
Simon Kelley
0b6144583b Log failed TCP DNS connections upstream when --log-debug active. 2025-02-05 17:15:52 +00:00
Simon Kelley
f31667317d Manpage typo. 2025-02-05 15:20:31 +00:00
Simon Kelley
5226b712a3 Add --no-0x20-encode config option.
The "bit 0x20 encoding" implemented in 995a16ca0c
can interact badly with (hopefully) rare broken upstream servers. Provide
an option to turn it off and a log message to give a clue as to why DNS service
is non-functional.
2025-02-03 21:02:12 +00:00
Simon Kelley
1f84cde024 Tweak to logging.
When a cached answer is too big, log

cached reply is truncated

and not

config reply is truncated
2025-02-03 15:26:55 +00:00
Paul Donald
046bfa2af0 Clean up some of the man page formatting.
Some writing was improved for clarity, especially regarding the use of
tags which can be confusing and difficult to grasp.
2025-02-01 22:40:54 +00:00
Simon Kelley
0762732647 belt-and-braces extra call to check_log_writer() in tcp_request() 2025-02-01 15:24:24 +00:00
Brian Haley
efb8f10450 Fix potential memory leak
When a new IPv6 address is being added to a dhcp_config
struct, if there is anything invalid regarding the prefix
it looks like there is a potential memory leak.
ret_err_free() should be used to free it.

Also, the new addrlist struct is being linked into
the existing addr6 list in the dhcp_config before the
validity check, it is best to defer this insertion
until later so an invalid entry is not present, since
the CONFIG_ADDR6 flag might not have been set yet.

Signed-off-by: Brian Haley <haleyb.dev@gmail.com>
2025-01-24 23:01:08 +00:00
Simon Kelley
6dbdf16fd1 Move debian submodule to submodules/dnsmasq-debian. 2025-01-24 21:05:43 +00:00
Simon Kelley
6e6a45a7d9 Bump copyrights to 2025. 2025-01-23 17:08:39 +00:00
Simon Kelley
a4569c22cc Correct BNF for --trust-anchor in manpage. 2025-01-20 16:20:13 +00:00
Simon Kelley
199e65c4d9 Remove misleading comment. 2025-01-20 15:55:42 +00:00
Simon Kelley
bb8811d472 Convert DNS names in logs to all lower case.
0x20 encoding makes them look odd, otherwise.
2025-01-20 15:25:26 +00:00
Simon Kelley
995a16ca0c Implement "DNS-0x20 encoding".
This provides extra protection against reply-spoof attacks.

Since DNS queries are case-insensitive, it's possible to randomly flip
the case of letters in a query and still get the correct answer back.
This adds an extra dimension for a cache-poisoning attacker to guess
when sending replies in-the-blind since it's expected that the
legitimate answer will have the same pattern of upper and lower case
as the query, so any replies which don't can be ignored as
malicious.

The amount of extra entropy clearly depends on the number
of a-z and A-Z characters in the query, and this implementation puts a
hard limit of 32 bits to make rescource allocation easy. This about
doubles entropy over the standard random ID and random port
combination.
2025-01-19 21:54:58 +00:00
Simon Kelley
65f9c1aca1 Case-sensitive matching of questions and answers.
When checking that an answer is the answer to the question that
we asked, compare the name in a case-sensitive manner.

Clients can set the letters in a query to a random pattern of
uppercase and lowercase to add more randomness as protection against
cache-poisoning attacks, and we don't want to nullify that.

This actually restores the status quo before
commit ed6d29a784
since matching questions and answers using a checksum
can't help but be case sensitive.

This patch is a preparation for introducing DNS-0x20
in the dnsmasq query path.
2025-01-19 00:08:36 +00:00
Simon Kelley
b72ecb3a59 Fix log message fields in wrong order in some auth replies. 2025-01-18 23:56:23 +00:00
Simon Kelley
c221030f89 Rename cache_validated() to cache_not_validated().
Let's give the poor programmers a chance.
2025-01-18 23:26:06 +00:00
Simon Kelley
5bbea085d0 Fix subtle bug in arbitrary-RR caching.
If the client asks for DNSSEC RRs via the do bit, and
we have an answer cached, we can only return the cached
answer if the RR was not validated. This is because
we don't the extra info (RRSIGS, NSECs) for a complete
validated answer. In that case we have to forward again.

This bug was that the "is the cache entry validated" test was
in an outer loop rather than an inner one. A cache hit on
a different RRtype that wasn't validated would satify the
condition to use the cache, even if the cache entry for
the required RRtype didn't. The only time when there can be a mix
of validated and non validated cache entries for the same domain
is when most are not validated, but one is a negative cache for
a DS record.

This bug took a long time to find.
2025-01-18 23:15:53 +00:00
Simon Kelley
622cf03ab9 Fix fubar that could return unsigned NODATA response when do bit set. 2025-01-18 22:16:29 +00:00
Simon Kelley
8ce27433f8 Handle DS queries to auth zones.
When dnsmasq is configured to act as an authoritative server and has
an authoritative zone configured, and recieves a query for
that zone _as_forwarder_ it answers the query directly rather
than forwarding it. This doesn't affect the answer, but it
saves dnsmasq forwarding the query to the recusor upstream,
whch then bounces it back to dnsmasq in auth mode. The
exception should be when the query is for the root of zone, for a DS
RR. The answer to that has to come from the parent, via the
recursor, and will typically be a proof-of-nonexistence since
dnsmasq doesn't support signed zones. This patch suppresses
local answers and forces forwarding to the upstream recursor
for such queries. It stops breakage when a DNSSEC validating
client makes queries to dnsmasq acting as forwarder for a zone
for which it is authoritative.
2025-01-18 08:57:14 +00:00
Simon Kelley
5d894620b4 Extend build fingerprinting to include CFLAGS.
If the value of CFLAGS is changed between builds, the makefile
will rebuid, in the same way as for COPTS.
2025-01-17 16:48:08 +00:00
Simon Kelley
71766c0c35 Tweak handling of duplicate DNS answers via UDP.
If we get a duplicate answer for a query via UDP which we have
either already received and started DNSSEC validation, or was
truncated and we've passed to TCP, then just ignore it.

The code was already in place, but had evolved wonky and
only worked for error replies which would otherwise prompt
a retransmit.
2025-01-13 20:30:37 +00:00
Simon Kelley
da58455508 Tweak 7d915a0bb9
A downstream query may have gone to TCP, not just DNSSEC queries.
2025-01-13 11:03:30 +00:00
Simon Kelley
b915c9a661 Attempt to keep running if a child process dies.
If a child process dies unexpectedly, log the error and
try and tidy up so the main process continues to run and
doesn't block awaiting the dead child.
2025-01-13 10:56:19 +00:00
Simon Kelley
424aaa0f9d Fix another 509afcd1d2 SNAFU 2025-01-13 10:32:55 +00:00
Andrew Sayers
c72c895869 Improve "no upstream servers configured" when D-Bus is enabled
Print a specific INFO message instead of a generic WARNING message,
so users know what to do.

Starting dnsmasq without upstream servers indicates a problem by default,
but is perfectly normal with D-Bus enabled.  For example, NetworkManager
starts dnsmasq with no upstream servers, then immediately populates it
over D-Bus.
2025-01-12 22:32:32 +00:00
Simon Kelley
b7156116c2 Fix SNAFU in 509afcd1d2 2025-01-12 22:28:12 +00:00
Simon Kelley
7d915a0bb9 Don't do retries over UDP when we've sent the query by TCP. 2025-01-12 22:02:05 +00:00
Simon Kelley
509afcd1d2 Refactor poll() loop.
Handling events on file descriptors can result in new file
descriptors being created or old ones being deleted. As such
the results of the last call to poll() become invalid in subtle
ways.

After handling each file descriptor in  check_dns_listeners()
return, to go around the poll() loop again and get valid data
for the new situation.

Thanks to Dominik Derigs for his indefatigable sleuthing of this one.
2025-01-12 21:36:09 +00:00
Simon Kelley
51343bd9a2 Treat replies with CD flag set the same for UDP and TCP code paths. 2025-01-12 16:25:07 +00:00
Simon Kelley
b58276a73c Return EDE OTHER error when DNSSEC validation abandoned.
This distinguishes the case where we found a message was bogus
from cases where the process failed.
2025-01-12 16:00:09 +00:00
Matthias Andree
f162d344c0 cache: Fix potential NULL deref in arcane situations. 2025-01-08 23:34:12 +00:00
Simon Kelley
0003db15cb Fix crash introduced in 6656790f24 2025-01-07 23:08:35 +00:00
Simon Kelley
275f4a4475 Remove arbitrary workspace size limit.
I have no memory for why this was ever there. It breaks DNSSEC
validation of large RRsets.

I can't see any DoS potential that is exposed by removing it.
2025-01-07 21:41:30 +00:00
Andrew Sayers
12e4565fef Improve "chown of PID file failed" message for missing CAP_CHOWN
Print a specific INFO message instead of a generic WARNING message,
so users aren't inconvenienced and maintainers know what to do.

Debian currently runs this service as part of NetworkManager,
in a systemd service without CAP_CHOWN.  Other distributions may
have the same problem, or might add the issue in future.
This fix should communicate the issue clearly to them.
2025-01-07 21:03:25 +00:00
Andrew Sayers
7af26eed32 Fix manpage typo.
s/will we/will be/
2025-01-07 21:01:15 +00:00
Simon Kelley
63dc6eb316 Fix read_write() changes for TCP timeout.
I misread the man page for socket(7) and TCP timeouts.

A timeout generates a -1 return and EAGAIN errno, NOT a short read.

Short reads are legit, and aborting when they are seen creates
hard-to-reproduce errors.
2025-01-07 20:53:03 +00:00
Simon Kelley
6656790f24 Handle queries with EDNS client subnet fields better.
If dnsmasq is configured to add an EDNS client subnet to a query,
it is careful to suppress use of the cache, since a cached answer may
not be valid for a query with a different client subnet.
Extend this behaviour to queries which arrive a dnsmasq
already carrying an EDNS client subnet.

This change is rather more involved than may seem necessary at first sight,
since the existing code relies on all queries being decorated by dnsmasq
and therefore not cached, so there is no chance that an incoming query
might hit the cache and cache lookup don't need to be suppressed, just
cache insertion. When downstream queries may be a mix of client-subnet
bearing and plain vanilla, it can't be assumed that the answers are never
in the cache, and queries with subnets must not do lookups.
2025-01-07 20:46:33 +00:00
Simon Kelley
c8de423038 Fix finger-trouble in immediately previous commit. 2025-01-07 17:00:18 +00:00
Simon Kelley
c52653f97c Correctly handle failure of pipe() call in swap_to_tcp() 2025-01-06 23:16:40 +00:00
Simon Kelley
e24c341068 Fix wrong packet size when dumpong packets to file. 2025-01-01 17:03:50 +00:00
Simon Kelley
5ef6c8c24f Extend fcb40ee73d to cover "Make install-i18n" 2024-12-30 13:29:48 +00:00
Simon Kelley
7c348a0b73 Extend d578da0665 to Linux-only code. 2024-12-24 11:31:34 +00:00
Matthias Andree
d578da0665 Fix FTBFS when using -pedantic compiler flag.
I am attaching an incremental git-am ready patch to go on top your Git HEAD,
to fix all sorts of issues and make this conforming C99 with default
options set,
and fix another load of warnings you receive when setting the compiler
to pick the nits,
-pedantic-errors -std=c99 (or c11, c18, c2x).
It changes many void * to uint8_t * to make the "increment by bytes"
explicit.
You can't do:

void *foo;
// ...
foo += 2.
2024-12-24 11:18:42 +00:00
Conrad Kostecki
8949ef44b4 Update DE translation. 2024-12-24 09:47:41 +00:00
DL6ER
3ac11cdd98 Add newly assigned RRTYPE DSYNC
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 15:19:00 +00:00
DL6ER
5d49fa112d Add newly assigned RRTYPEs NXNAME, CLA, and IPN
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 15:18:56 +00:00
DL6ER
d29d19e654 Add newly assigned RRTYPE WALLET (262)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 15:18:47 +00:00
Simon Kelley
49ea7db74e Fix c9bc0156a8d36d56735831cb81e786d628ed73e
Eg.

dhcp-host=AA:BB:CC:DD:EE:FF,192.168.1.5,server,infinite

is broken.

Thanks to Dominik for the diagnosis.
2024-12-23 15:14:27 +00:00
Olaf Hering
fcb40ee73d Fix dependency in make install target
The make target 'install-common' expects results from the target 'all'.
A 'make -j install' may fail because both targets are brought
up-to-todate in parallel. As a result the final binary will not exist at
the time 'install-common' runs, because 'all' is not yet done.

Adjust the dependencies to update 'all' before processing 'install-common'.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
2024-12-23 15:02:34 +00:00
Simon Kelley
0f437b3b5e Banish compiler warnings. 2024-12-20 21:57:21 +00:00
Simon Kelley
8a5fe8ce6b Extend the code to effciently close unwanted file descriptors to *BSD. 2024-12-20 21:51:24 +00:00
Matthias Andree
2a664c03db bpf.c: Follow callback updates. 2024-12-20 21:07:09 +00:00
Simon Kelley
4902807879 Fix [-Wgnu-variable-sized-type-not-at-end] warning.
Thanks to Matthias Andree for pointing out this one.
2024-12-20 21:05:13 +00:00
Simon Kelley
742af6e4b9 Refactor receive_query() to removed duplicated code. 2024-12-20 20:02:01 +00:00
Simon Kelley
3eb008c36d Further refactoring of the TCP DNS codepath.
It's not t a thing of beauty, but it's less ugly than it was.
Any bugs, I blame on what I started from....
2024-12-19 16:38:47 +00:00
Simon Kelley
32248ebd5b Fix thinko in 3b74df4f55 2024-12-19 12:33:54 +00:00
Simon Kelley
5d32f35bdc Remove unused variable. 2024-12-19 00:36:42 +00:00
Loganaden Velvindron
d6379cd923 Add IANA Root TA 2024.
Signed-off-by: Loganaden Velvindron <logan at cyberstorm.mu>
Signed-off-by: Jaykishan Mutkawoa <jay at cyberstorm.mu>
2024-12-18 23:58:58 +00:00
Geert Stappers via Dnsmasq-discuss
9f7e9ba46f Minor typo fix, changed a "PCE" into "PXE". 2024-12-18 23:51:29 +00:00
Erik Karlsson
80498fab01 Update DNS records after pruning DHCP leases
Not doing so can result in a use after free since the name for DHCP
derived DNS records is represented as a pointer into the DHCP lease
table. Update will only happen when necessary since lease_update_dns
tests internally on dns_dirty and the force argument is zero.

Signed-off-by: Erik Karlsson <erik.karlsson@iopsys.eu>
2024-12-17 23:50:06 +00:00
Dominik Derigs
ea84abe3e9 Add missing count for PXE packets in metrics. 2024-12-17 23:34:13 +00:00
harry
0526792ebb Fix DHCPv6 relay on *BSD.
Analogous fix to 5a1f2c577d for DHCPv6 relay.
2024-12-17 23:17:27 +00:00
Simon Kelley
ab177cb153 Improve handling of non-QUERY DNS requests.
We can't answer and shouldn't forward non-QUERY DNS requests.

This patch fixes handling such requests from TCP connections; before
the connection would be closed without reply.

It also changes the RCODE in the answer from REFUSED to NOTIMP and
provides clearer logging.
2024-12-13 23:00:21 +00:00
Simon Kelley
3b74df4f55 Fix erroneous "DNSSEC validated" state with non-DNSSEC upstream servers.
When DNSEC validation is enabled, but a query is not validated
because it gets forwarded to a non-DNSEC-capable upstream
server, the rr_status array is not correctly cleared, with
the effect that the answer may be maked as DNSSEC validated
if the immediately preceding query was DNS signed and validated.
2024-12-10 15:01:59 +00:00
Simon Kelley
5483fead6a Support PXE proxy-DHCP and DHCP-relay at the same time.
When using PXE proxy-DHCP, dnsmasq supplies PXE information to
the client, which also talks to another "normal" DHCP server
for address allocation and similar. The normal DHCP server may
be on the local network, but it may also be remote, and accessed via
a DHCP relay. This change allows dnsmasq to act as both a
PXE proxy-DHCP server AND a DHCP relay for the same network.
2024-12-05 17:32:13 +00:00
Simon Kelley
7199531ff1 Add --dhcp-option-pxe config.
This acts almost exactly like --dhcp-option except that the defined option
is only sent when replying to PXE clients. More importantly, these
options are sent in reply PXE clients when dnsmasq in acting in PXE
proxy mode. In PXE proxy mode, the set of options sent is defined by
the PXE standard and the normal set of options is not sent. This config
allows arbitrary options in PXE-proxy replies. A typical use-case is
to send option 175 to iPXE. Thanks to Jason Berry for finding the
requirement for this.
2024-12-05 17:07:40 +00:00
Simon Kelley
5a1f2c577d Set sa_len field in DHCP relay code.
Ommision broke DHCP relay on *BSD.
2024-12-03 21:22:21 +00:00
Reynir Björnsson
6c9bc0156a Report multiple hostnames in --dhcp-host.
This is not supported, and doesn't behave as one might expect.
2024-12-01 23:50:18 +00:00
gen2dev
da2cc84854 Fix GCC-15, C23 compatibility and -Wincompatible-pointer-types errors
A bug in gentoo linux https://bugs.gentoo.org/945183 reported that dnsmasq 2.90 fails to compile with GCC 15.

The issue is that while previous versions of GCC defaulted to the C17 standard and C23 could be selected with
"-std=c23" or "-std=gnu23", GCC 15 defaults to C23. In C23 incompatible pointer types are an error instead of
a warning, so the "int (*callback)()" incomplete prototypes cause errors.

For example, compiling dnsmasq 2.90 with gcc 14.2.1 and "-std=gnu23" fails with errors such as:
    lease.c: In function `lease_find_interfaces':
    lease.c:467:34: warning: passing argument 3 of `iface_enumerate' from incompatible pointer type [-Wincompatible-pointer-types[https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wincompatible-pointer-types]]
      467 |   iface_enumerate(AF_INET, &now, find_interface_v4);
          |                                  ^~~~~~~~~~~~~~~~~
          |                                  |
          |                                  int (*)(struct in_addr,  int,  char *, struct in_addr,  struct in_addr,  void *)
    In file included from lease.c:17:
    dnsmasq.h:1662:50: note: expected `int (*)(void)' but argument is of type `int (*)(struct in_addr,  int,  char *, struct in_addr,  struct in_addr,  void *)'
     1662 | int iface_enumerate(int family, void *parm, int (callback)());
          |                                             ~~~~~^~~~~~~~~~~

This patch uses a typedef'ed union of pointer types to get type checking of the pointers. If that's too complicated,
another way might be to use (void *) casts to disable type checking.

Also, some of the IPv6 callbacks had "int preferred, int valid" and some had
"unsigned int preferred, unsigned int valid". This patch changes them all to "unsigned int"
so they're the same and to avoid casting "u32" to "int", eg:
    u32 preferred = 0xffffffff;
    callback(..., (int)preferred, ...)
Even if those cast values aren't used in the callback, casting u32 to "int" feels bad, especially if "int" is 32 bits.
2024-12-01 22:53:16 +00:00
Simon Kelley
a8088e331a Modify the behaviour of --synth-domain for IPv6.
When deriving a domain name from an IPv6 address, an address
such as 1234:: would become 1234--.example.com, which is
not legal in IDNA2008. Stop using the :: compression method,
so 1234:: becomes
1234-0000-0000-0000-0000-0000-0000-0000.example.com
2024-11-27 23:12:41 +00:00
Simon Kelley
41d2ae3203 Make the packet-dump code work with a FIFO.
mkfifo /tmp/dnsmasq.pipe
dnsmasq --dumpfile=/tmp/dnsmasq.pipe ....
wireshark -i /tmp/dnsmasq.pipe

gives real-time display of network traffic in Wireshark.
2024-11-27 16:03:13 +00:00
Simon Kelley
c6bc22adc7 Add missing dump_packet_udp() call. 2024-11-27 00:19:32 +00:00
Simon Kelley
9c057566d5 Update CHANGELOG. 2024-11-25 23:38:56 +00:00
Simon Kelley
32a8f3e009 Finesse TCP timeouts for upstream connections.
Timeouts for TCP connections to non-responive servers are very long.
This in not appropriate for DNS connections.

Set timeouts for connection setup, sending data and recieving data.
The timeouts for connection setup and sending data are set at 5 seconds.
For recieving the reply this is doubled, to take into account the
time for usptream to actually get the answer.

Thanks to Petr Menšík for pointing out this problem, and finding a better
and more portable solution than the one in place heretofore.
2024-11-25 23:18:07 +00:00
Simon Kelley
481ff0ed10 Logging tweaks. 2024-11-25 10:17:50 +00:00
Simon Kelley
f04cf8506a Simplify EDNS0 packet size handling.
In the post 2020 flag-day world, we limit UDP packets to 1232 bytes
which can go anywhere, so the dodgy code to try and determine the
functional maxmimum packet size on the path from upstream servers
is obsolete.
2024-11-24 23:06:22 +00:00
Simon Kelley
04d7693d86 Tweak logging for truncated replies. 2024-11-24 22:13:44 +00:00
Simon Kelley
4ea23f7ea1 Default --fast-dns-retries on when doing DNSSEC.
When doing DNSSEC validation, a single downstream query may
trigger many upstream queries. On an unreliable network, there
may not be enough downstream retries to ensure that all these
queries complete.
2024-11-24 21:52:39 +00:00
Simon Kelley
163c05c61d Make locally generated truncated answers consistent.
process_reply() is no longer doing this.
2024-11-24 08:42:33 +00:00
Simon Kelley
d2790914df More edns0 rationalisation. 2024-11-24 00:37:40 +00:00
Simon Kelley
334e144c36 Don't empty reply packets received from upstream marked as truncated.
It's concievable that upstream, has provided a useful minimal reply.

After a patch from Rahul Thakur.
2024-11-23 23:38:31 +00:00
Simon Kelley
8bd54efceb Typo fix. 2024-11-23 22:53:34 +00:00
Simon Kelley
e5e8c14d87 Large refactor of EDNS0 UDP packet size handling.
This was kinda strange before, with a lot of cargo-cult copied code,
and no clear strategy.

Now it works like this:

When talking upstream we always add a pseudoheader, and set the
UDP packet size to --edns-packet-max unless we've had problems
talking to a server, when it's reduced to 1280 if that fixes things.

Answering queries from downstream, we get the answer (either from
upstream or local data) If local data won't fit the advertised size
(or 512 if there's not pseudoheader) return truncated. If upstream
returns truncated, do likewise. If upstream is OK, but the answer is
too big for downstream, truncate the answer.
2024-11-23 22:38:41 +00:00
Simon Kelley
e778a28eee Remove obsolete comment. 2024-11-22 22:42:50 +00:00
Simon Kelley
4cf2f757ec Rationalise reties.
The saved query includes all the modifications, made on first
forwarding, which simplifies retries.
2024-11-22 22:23:36 +00:00
Simon Kelley
ae85ea3858 Fix buffer overflow when configured lease-change script name
is too long.

Thanks to Daniel Rhea for finding this one.
2024-11-21 15:42:49 +00:00
Simon Kelley
b087cf4a6c Fix out-of-bounds heap read in order_qsort().
We only need to order two server records on the ->serial field.
Literal address records are smaller and don't have
this field and don't need to be ordered on it.
To actually provoke this bug seems to need the same server-literal
to be repeated twice, eg --address=/a/1.1.1.1 --address-/a/1.1.1.1
which is clearly rare in the wild, but if it did exist it could
provoke a SIGSEV. Thanks to Daniel Rhea for fuzzing this one.
2024-11-21 15:28:31 +00:00
Simon Kelley
0adaf13438 Don't clear tcpfd for literal address server records.
They have smaller structs which don't include that field,
so this is a buffer overlow.

Error introduced in f5cdb007d8
2024-11-21 15:18:19 +00:00
Simon Kelley
b5ac983bf6 Fix wrong transaction ID when retrying DNSSEC queries. 2024-11-21 15:09:14 +00:00
Simon Kelley
498794ad85 Extralog tweaks to get log-id right in a couple of odd cases. 2024-11-03 23:40:43 +00:00
Simon Kelley
467fbd1086 Fix argument-order thinko on call to new lookup_frec() 2024-11-03 23:07:54 +00:00
Simon Kelley
7b7aef903e Handle error return from blockdata_alloc in all cases. 2024-11-02 22:37:51 +00:00
Simon Kelley
09a1839272 Don't send suspect answer as query to next server in DNS TCP codepath. 2024-11-02 22:18:56 +00:00
Simon Kelley
1b76e1c8ec Remove hash-questions.c - no longer required. 2024-11-02 21:29:47 +00:00
Simon Kelley
959d991d10 Replace query hashing in TCP code path. 2024-11-02 21:09:17 +00:00
Simon Kelley
ed6d29a784 Remove query hashing in UDP DNS code path.
Now we're always saving the query, this is no longer necessary,
and allows the removal of a lot of quite hairy code.

Much more code removal to come, once the TCP code path is also purged.
2024-11-02 15:33:37 +00:00
Simon Kelley
5d6399b71c DOn't churn a query though the blockdata store twice when forwarding it. 2024-11-01 16:50:15 +00:00
Simon Kelley
3b6df06fb8 Always save forwarded query locally.
We do this in many cases anyway (DNSSEC, fast-retry) and doing
it unconditionally allows much simplification of knarly code, to follow.
2024-11-01 16:06:58 +00:00
Simon Kelley
a9d46d42cb Tweak packet-reduction code going from TCP->UDP. 2024-10-13 23:09:48 +01:00
Simon Kelley
0338aa4586 Don't log bogus source address when doing fast retry. 2024-10-13 00:09:26 +01:00
Simon Kelley
d15d371051 Handle truncated response UDP-to-TCP to downstream queries when validating.
A relatively common situation is that the reply to a downstream query
will fit in a UDP packet when no DNSSEC RRs are present, but overflows
when the RRSIGS, NSEC ect are added. This extends the automatic
move from UDP to TCP to downstream queries which get truncated replies,
in the hope that once stripped of the DNSSEC RRs, the reply can be returned
via UDP, nwithout making the downstream retry with TCP.

If the downstream sets the DO bit, (ie it wants the DNSSEC RRs, then
this path is not taken, since the downstream will have to get a truncated
repsonse and retry to get a correct answer.
2024-10-12 22:32:21 +01:00
Simon Kelley
1c26ec2876 UDP-to-TCP bugfix: wrong calls to extract_name and
suppress rapid (UDP) retry once we've switched to TCP.
2024-10-04 17:20:33 +01:00
Simon Kelley
e9a7cd0a50 Fix DNSSEC work counting when swapping from UDP to TCP 2024-10-04 17:20:33 +01:00
Simon Kelley
f5cdb007d8 Improve handling of truncated replies to DNSSEC queries.
Heretofore, when a validating the result of an external query triggers
a DNSKEY or DS query and the result of that query is truncated, dnsmasq
has forced the whole validation process to move to TCP by returning a
truncated reply to the original requestor. This forces the original
requestor to retry the query in TCP mode, and the DNSSEC subqueries
also get made via TCP and everything works.

Note that in general the actual answer being validated is not large
enough to trigger truncation, and there's no reason not to return that
answer via UDP if we can validate it successfully. It follows that
a substandard client which can't do TCP queries will still work if the
answer could be returned via UDP, but fails if it gets an artifically
truncated answer and cannot move to TCP.

This patch teaches dnsmasq to move to TCP for DNSSEC queries when
validating UDP answers. That makes the substandard clients mentioned
above work, and saves a round trip even for clients that can do TCP.
2024-10-04 17:20:33 +01:00
Simon Kelley
46288c7e90 Tidy up parameters to sendmsg() syscall.
The msg_controllen field passed to sendmsg is computed using the
CMSG_SPACE(), which is correct, but CMSG_SPACE() can include
padding bytes at the end of the passed structure if they are required
to align subsequent structures in the buffer. Make sure these
bytes are zeroed to avoid passing uninitiased memory to the kernel,
even though it will never touch these bytes.

Also tidy up the mashalling code in send_from to use pointers to
the structure being filled out, rather than a temporary copy which
then gets memcpy()'d into place. The DHCP sendmsg code has always
worked like this.

Thanks to  Dominik Derigs for running Memcheck as submitting the
initial patch.
2024-10-04 17:20:24 +01:00
Simon Kelley
d7d682637d Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2024-10-04 17:03:55 +01:00
Simon Kelley
f006be7842 Fix crash when reloading DHCP config on SIGHUP.
Confusion in the code to free old DHCP configuration when it's
being reloaded causes invalid pointers to be followed and a crash.

https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2024q4/017764.html

has a more complete explanation of the problem.
2024-10-04 16:59:14 +01:00
Simon Kelley
550c368ade Treat cache insertion failure of DNSKEY and DS records as
another resource problem and fail validation with suitable logging.
2024-03-27 16:00:06 +00:00
Simon Kelley
b8ff4bb762 Remove debian directory and replace with a git submodule. 2024-02-22 22:45:37 +00:00
Simon Kelley
9adbf009a6 The DHCPv4 server doesn't need CAP_NET_ADMIN if always broadcasting.
CAP_NET_ADMIN is needed in the DHCPv4 code to place entries into
the ARP cache. If it's configured to unconditionally broadcast
to unconfigured clients, it never touches the ARP cache and
doesn't need CAP_NET_ADMIN.

Thanks to Martin Ivičič <max.enhanced@gmail.com> for prompting this.
2024-02-21 00:46:25 +00:00
renmingshuai
ccff85ad72 [PATCH] Fix error introduced in 51471cafa5
Signed-off-by: renmingshuai <renmingshuai@huawei.com>
2024-02-21 00:24:25 +00:00
Simon Kelley
4c590320ec Fix breakage in DBus FilterA and FilterAAAA methods.
In generalising the RR filter code, the Dbus methods
controlling filtering A and AAAA records
got severely broken. This, and the previous commit,
fixes things.
2024-02-20 23:38:26 +00:00
Simon Kelley
89aad01468 Fix infinite loop when invoking SetFilterA dbus method more than once.
Also applies to SetFilterAAAA.

Thanks to Clayton Craft for spotting the issue.
2024-02-19 23:21:58 +00:00
Simon Kelley
de6f914654 Add missing CHANGELOG entries for 2.90 2024-02-19 13:22:09 +00:00
Simon Kelley
1ed783b8d7 Fix spurious "resource limit exceeded" messages.
Replies from upstream with a REFUSED rcode can result in
log messages stating that a resource limit has been exceeded,
which is not the case.

Thanks to Dominik Derigs and the Pi-hole project for
spotting this.
2024-02-19 12:22:43 +00:00
Simon Kelley
3705ec5592 Relax limits imposed by d/t/functions.d/ip-addr.patterns in Debian autotest. 2024-02-15 09:55:57 +00:00
Simon Kelley
b6769234bc Bump Debian version. 2024-02-13 13:49:15 +00:00
Simon Kelley
214a046f47 Merge branch 'dnssec-limit'
This merges security fixes for CVE-2023-50387 and CVE-2023-50868

Keytrap - extreme CPU consumption in the DNSSEC validator.
2024-02-13 13:27:25 +00:00
Simon Kelley
b38da6b191 Reverse suppression of ANY query answer logging. 2024-02-13 13:26:24 +00:00
Simon Kelley
9621c16a78 Add CHANGELOG entry for DNSSEC security fixes. 2024-02-12 23:11:35 +00:00
Simon Kelley
3ae7f1ab0d Add --dnssec-limits option. 2024-02-12 23:11:35 +00:00
Simon Kelley
39de57499e Better allocation code for DS digest cache. 2024-02-12 23:11:35 +00:00
Simon Kelley
3c91bca943 Better stats and logging from DNSSEC resource limiting. 2024-02-12 23:11:35 +00:00
Simon Kelley
76bceb06c4 Overhaul data checking in NSEC code. 2024-02-12 23:11:35 +00:00
Simon Kelley
6f23a0a75e Rework validate-by-DS to avoid DoS vuln without arbitrary limits.
By calculating the hash of a DNSKEY once for each digest algo,
we reduce the hashing work from (no. DS) x (no. DNSKEY) to
(no. DNSKEY) x (no. distinct digests)

The number of distinct digests can never be more than 255 and
it's limited by which hashes we implement, so currently only 4.
2024-02-12 23:11:35 +00:00
Simon Kelley
06945c4b77 Update EDE code -> text conversion. 2024-02-12 23:11:35 +00:00
Simon Kelley
c5aa221e44 Parameterise work limits for DNSSEC validation. 2024-02-12 23:11:35 +00:00
Simon Kelley
bfefd6e38c Fix error introduced in 635bc51cac3d5d7dd49ce9e27149cf7e402b7e79 2024-02-12 23:11:35 +00:00
Simon Kelley
59d30390c9 Measure cryptographic work done by DNSSEC. 2024-02-12 23:11:34 +00:00
Simon Kelley
51471cafa5 Update NSEC3 iterations handling to conform with RFC 9276. 2024-02-12 23:11:34 +00:00
Simon Kelley
be73efc020 Update header with new EDE values. 2024-02-12 23:11:34 +00:00
Simon Kelley
40595f80d9 Protection against pathalogical DNSSEC domains.
An attacker can create DNSSEC signed domains which need a lot of
work to verfify. We limit the number of crypto operations to
avoid DoS attacks by CPU exhaustion.
2024-02-12 23:11:34 +00:00
Simon Kelley
8c8e5385fd Close debian bug. 2024-02-12 23:11:03 +00:00
Simon Kelley
3de7289bd6 Make --filter-rr=ANY filter the answer to ANY queries.
Thanks to Dominik Derigs for an earlier patch which inspired this.
2024-02-12 20:45:20 +00:00
Simon Kelley
febeea9d01 Tweak logging and special handling of T_ANY in rr-filter code. 2024-02-12 13:42:07 +00:00
Heikki Linnakangas
762a3f2430 Don't create a useless inotify file desrcriptor when --port=0
If there are no dynamic configuration directories configured with
dhcp-hostsdir, dhcp-optsdir and hostsdir then we need to use inotify
only to track changes to resolv-files, but we don't need to do
that when DNS is disabled (port=0) or no resolv-files are configured.

It turns out that inotify slots can be a scarce resource, so not
using one when it's not needed is a Goood Thing.

Patch by HL, description above from SRK.
2024-02-07 14:44:49 +00:00
Simon Kelley
6d35601da4 Refactor the accumulated crud of years in process_reply(). 2024-02-05 22:33:09 +00:00
Simon Kelley
a827127c77 Handle caching SOA for negative PTR queries.
Also deal with the fact that a root SOA is a thing.
2024-02-03 20:46:23 +00:00
Simon Kelley
d4a6f3a93e Fix logic error in signed RR handling.
In extract_addresses() the "secure" argument is only set if the
whole reply is validated (ie the AD bit can be set). Even without
that, some records may be validated, and should be marked
as such in the cache.

Related, the DNS doctor code has to update the flags for individual
RRs as it works, not the global "secure" flag.
2024-02-02 21:36:56 +00:00
Simon Kelley
86c15032ba Fix compiler warning. 2024-02-02 00:26:44 +00:00
Simon Kelley
12ddb2a4b9 Cache SOAs and return them with cached NXDOMAIN/NODATA replies.
Now we can cache arbirary RRs, give more correct answers when
replying negative answers from cache.

To implement this needed the DNS-doctor code to be untangled from
find_soa(), so it should be under suspicion for any regresssions
in that department.
2024-02-01 23:37:11 +00:00
Simon Kelley
db07664f2a Hardcode Lua library version in debian/rules, rather than the Makefile. 2024-01-26 23:03:34 +00:00
Simon Kelley
1205fc3541 Let pkg-config select the newest installed Lua version, don't hardcode it.
The version can be overridden with the LUA envvar

Make LUA=lua5.4

Thanks to Petr Menšík for the patch which inspired this one.
2024-01-26 22:44:06 +00:00
Simon Kelley
3a8ebcac77 Debian changelog tweaking: LUA -> Lua and use upstream test version
for experimental release.
2024-01-26 22:23:12 +00:00
Simon Kelley
729e54b386 debian/changelog cosmetic tweak. 2024-01-23 23:30:57 +00:00
Simon Kelley
a61dbc84bf Adjust .gitignore to reflect new Debian packaging. 2024-01-23 23:19:01 +00:00
Gioele Barabucci
3cbd4b0fc0 Use debhelper to simplify tmpfiles installation in debian package. 2024-01-23 23:09:11 +00:00
Simon Kelley
75965b19bd 2023->2024 in debian/copyright 2024-01-23 23:04:29 +00:00
Simon Kelley
830459d3a1 Tie up loose ends in debian/changelog for upload to experimental. 2024-01-23 23:02:49 +00:00
Justin
aa9e9651a1 Man page typo fix. 2024-01-21 22:24:43 +00:00
Simon Kelley
9142942483 Remove Debian patch to bump Lua version. It's upstream now. 2024-01-21 12:51:14 +00:00
Simon Kelley
68fe0d78bb Bump version in Debian changelog to 2.90 2024-01-19 22:35:28 +00:00
Simon Kelley
c9d7b983c4 Bump copright year in debian/copyright and add a copyright holder. 2024-01-19 14:47:03 +00:00
Simon Kelley
7c07dc3526 Bump LUA library to 5.4 2024-01-19 14:34:15 +00:00
Sven Geuer
cd93d15ab1 Largely replace the Debian packaging with a new and much more up-to-date
Debhelper based version.
2024-01-19 14:34:15 +00:00
Simon Kelley
34bbb7a1b8 Fix FTBFS introduced in 2748d4e901 2024-01-19 14:32:02 +00:00
Simon Kelley
b5820d1fd8 Bump copyright to 2024. 2024-01-13 22:20:04 +00:00
Petr Menšík
2748d4e901 Introduce new --local-service=host parameter
Similar to local-service, but more strict. Listen only on localhost
unless other interface is specified. Has no effect when interface is
provided explicitly. I had multiple bugs fillen on Fedora, because I have
changed default configuration to:

interface=lo
bind-interfaces

People just adding configuration parts to /etc/dnsmasq.d or appending to
existing configuration often fail to see some defaults are already there.
Give them auto-ignored configuration as smart default.

Signed-off-by: Petr Menšík <pemensik@redhat.com>

Do not add a new parameter on command line. Instead add just parameter
for behaviour modification of existing local-service option. Now it
accepts two optional values:
- net: exactly the same as before
- host: bind only to lo interface, do not listen on any other addresses
  than loopback.
2024-01-13 22:11:22 +00:00
Simon Kelley
63ba726e1f Fix --synth-domain NXDOMAIN responses.
By design, dnsmasq forwards queries for RR-types it has no data
on, even if it has data for the same domain and other RR-types.

This can lead to an inconsitent view of the DNS when an upstream
server returns NXDOMAIN for an RR-type and domain but the same domain
but a different RR-type gets an answer from dnsmasq. To avoid this,
dnsmasq converts NXDOMAIN answer from upstream to NODATA answers if
it would answer a query for the domain and a different RR-type.

An oversight missed out --synth-domain from the code to do this, so
--synth-domain=thekelleys.org.uk,192.168.0.0/24
would result in the correct answer to an A query for
192-168.0.1.thekelleys.org.uk and an AAAA query for the same domain
would be forwarded upstream and the resulting NXDOMAIN reply
returned.

After the fix, the reply gets converted to NODATA.

Thanks to Matt Wong for spotting the bug.
2023-12-03 17:48:56 +00:00
Simon Kelley
f1beb79429 Fix problem with domains associated with DHCP hosts at startup.
At startup, the leases file is read by lease_init(), and
in lease_init() undecorated hostnames are expanded into
FQDNs by adding the domain associated with the address
of the lease.

lease_init() happens relavtively early in the startup, party because
if it calls  the dhcp-lease helper script, we don't want that to inherit
a load of sensitive file descriptors. This has implications if domains
are defined using the --domain=example.com,eth0 format since it's long
before we call enumerate_interfaces(), so get_domain fails for such domains.

The patch just moves the hostname expansion function to a seperate
subroutine that gets called later, after enumerate_interfaces().
2023-12-03 16:09:08 +00:00
Simon Kelley
cd4db8246e Fix typo in dnsmasq.conf.example
Thanks to Brenton Bostick for the report.
2023-11-30 16:25:21 +00:00
Damian Sawicki
69877f565a Add information on process-forking for TCP connections to metrics.
Add the relevant information to the metrics and to the output of
dump_cache() (which is called when dnsmasq receives SIGUSR1).
Hence, users not collecting metrics will still be able to
troubleshoot with SIGUSR1. In addition to the current usage,
dump_cache() contains the information on the highest usage
since it was last called.
2023-11-30 15:55:51 +00:00
Simon Kelley
744231d995 Tighten up error checking in --bind-dynamic mode.
In bind-dynamic mode, its OK to fail to bind a socket to an address
given by --listen-address if no interface with that address exists
for the time being. Dnsmasq will attempt to create the socket again
when the host's network configuration changes.

The code used to ignore pretty much any error from bind(), which is
incorrect and can lead to confusing behaviour. This change make ONLY
a return of EADDRNOTAVAIL from bind() a non-error: anything else will be
fatal during startup phase, or logged after startup phase.

Thanks to Petr Menšík for the problem report and first-pass patch.
2023-11-27 23:08:31 +00:00
Simon Kelley
65c2d6afd6 Fix standalone SHA256 implementation.
Bug report here:
https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2023q4/017332.html

This error probably has no practical effect since even if the hash
is wrong, it's only compared internally to other hashes computed using
the same code.

Understanding the error:

hash-questions.c:168:21: runtime error: left shift of 128 by 24 places
cannot be represented in type 'int'

requires a certain amount of c-lawyerliness. I think the problem is that

m[i] = data[j] << 24

promotes the unsigned char data array value to int before doing the shift and
then promotes the result to unsigned char to match the type of m[i].
What needs to happen is to cast the unsigned char to unsigned int
BEFORE the shift.

This patch does that with explicit casts.
2023-11-22 22:02:05 +00:00
Simon Kelley
b27b94cfdc Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2023-11-22 15:29:10 +00:00
Simon Kelley
b8b5b734b4 Fix misuse of const pointer in src/nftset.c.
Thanks to  Kevin Darbyshire-Bryant for the initial patch, which was
modified by srk - any remaining bugs are his.
2023-11-22 15:20:53 +00:00
Simon Kelley
568fb02449 Fix use-after-free in cache_remove_uid().
Thanks to Kevin Darbyshire-Bryant for the bug report.
2023-11-13 22:08:08 +00:00
Simon Kelley
77ef9b2603 Fix crash when DNS disabled, introduced in 416390f996 2023-11-10 23:13:46 +00:00
Damian Sawicki
416390f996 Add --max-tcp-connections option to make this dynamically configurable. 2023-11-04 23:33:28 +00:00
Simon Kelley
24804b7431 Fix compile warning introduced by a889c554a7 2023-11-04 16:58:30 +00:00
Dominik Derigs
1fe9d2ba45 Add RESINFO RR-type to the table of RR-type names. 2023-11-04 16:52:09 +00:00
Simon Kelley
3868066085 Fix bad reply to DHCPCONFIRM messages (wrong message type).
Thanks to renmingshuai <renmingshuai@huawei.com> for
spotting the error, and making the initial patch.
2023-10-11 22:33:17 +01:00
Simon Kelley
a889c554a7 Work around possible Linux bug with VRF interfaces and DHCPv6.
The scope_id in the source address of recieved packets gets set
to the index of the VRF interface, not the slave. Fortunately,
the interface index returned by packetinfo is correct so we use
instead.

Thanks to Luci Stanescu <luci@safebits.tech> for characterising this.

Ref: https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2023q4/017276.html
2023-10-11 21:32:55 +01:00
Simon Kelley
ca8d04a8ff Cache zero-TTL DNS replies when stale-caching is enabled. 2023-10-09 21:15:13 +01:00
Simon Kelley
8b606543a3 Fix memory leak in arbitrary-RR caching.
If the cache insertion process fails for any reason, any
blockdata storage allocated needs to be freed.

Thanks to Damian Sawicki for spotting the problem and
supplying patches against earlier releases. This patch by SRK,
and any bugs are his.
2023-10-09 21:00:11 +01:00
renmingshuai
d16b995756 Fix memory leak when using --dhcp-optsfile with DHCPv6 options. 2023-09-30 23:31:08 +01:00
Simon Kelley
768b45a023 Remove two-decade old hack.
answer_request() builds answers in the same packet buffer
as the request.  This means that any EDNS0 header from the
original request is overwritten. If the answer is in cache, that's
fine: dnsmasq adds its own EDNS0 header, but if the cache lookup fails
partially and the request needs to be sent upstream, it's a problem.

This was fixed a long, long time ago by running the cache
lookup twice if the request included an EDNS0 header. The first time,
nothing would be written to the answer packet, nad if the cache
lookup failed, the untouched question packet was still available
to forward upstream. If cache lookup succeeded, the whole thing
was done again, this time writing the data into the reply packet.
In a world where EDNS0 was rare and so was memory, this was a
reasonable solution. Today EDNS0 is ubiquitous so basically
every query is being looked up twice in the cache. There's also
the problem that any code change which makes successive cache lookups
for a query possibly return different answers adds a subtle hidden
bug, because this hack depends on absence of that behaviour.

This commit removes the lookup-twice hack entirely. answer_request()
can now return zero and overwrite the question packet. The code which
was previously added to support stale caching by saving a copy of the
query in the block-storage system is extended to always be active.
This handles the case where answer_request() returns no answer OR
a stale answer and a copy of the original query is needed to forward
upstream.
2023-09-11 22:11:50 +01:00
Simon Kelley
3b5ddf37d9 Fix problem with arbitrary RR caching.
Caching an answer which has more that one RR, with at least
one answer being <=13 bytes and at least one being >13 bytes
can screw up the F_KEYTAG flag bit, resulting in the wrong
type of the address union being used and either a bad value
return or a crash in the block code.

Thanks to Dominik Derigs and the Pi-hole project for finding
and characterising this.
2023-09-02 21:34:54 +01:00
Simon Kelley
9bbf098a97 =/== typo in last commit. 2023-05-26 18:19:15 +01:00
Simon Kelley
6536187b62 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2023-05-26 18:01:58 +01:00
Simon Kelley
50adf82199 Behave better when attempting to contact unresponsive TCP servers.
By default TCP connect takes minutes to fail when trying to
connect a server which is not responding and for which the
network layer doesn't generate HOSTUNREACH errors.

This is doubled because having failed to connect in FASTOPEN
mode, the code then tries again with a call to connect().

We set TCP_SYNCNT to 2, which make the timeout about 10 seconds.
This in an unportable Linux feature, so it doesn't work on other
platforms.

No longer try connect() if sendmsg in fastopen mode fails with
ETIMEDOUT or EHOSTUNREACH since the story will just be the same.
2023-05-26 17:55:35 +01:00
Simon Kelley
1419de285f Log truncated DNS replies. 2023-05-17 23:19:30 +01:00
Simon Kelley
31c91b40bd Handle SERVFAIL responses to DS queries better.
On 15/5/2023 8.8.8.8 was returning SERVFAIL for a query on ec.europa.eu

ec.europa.eu is not a domain cut, that happens at jrc.ec.europa.eu. which
does return a signed proof of non-existance for a DS record.
Abandoning the search for a DS or proof of non existence at ec.europa.eu
renders everything within that domain BOGUS, since nothing is signed.

This code changes behaviour on a SERVFAIL to continue looking
deeper for a DS or proof of its nonexistence.
2023-05-17 12:20:50 +01:00
Simon Kelley
1d6fe0ea84 Code tidying. 2023-05-01 23:06:29 +01:00
Simon Kelley
d774add784 Fix issue with stale caching.
After replying with stale data, dnsmasq sends the query upstream to
refresh the cache asynchronously and sometimes sends the wrong packet:
packet length can be wrong, and if an EDE marking stale data is added
to the answer that can end up in the query also. This bug only seems
to cause problems when the usptream server is a DOH/DOT proxy. Thanks
to Justin He for the bug report.
2023-05-01 20:42:30 +01:00
Simon Kelley
7500157cff Improve RFC3315 para 15 packet validation.
Thanks to Shashikumar Shashil for spotting the ommision.
2023-04-24 17:43:02 +01:00
Simon Kelley
52e6ad2761 Log failure to determine MAC address in DHCPv6. 2023-04-17 21:25:30 +01:00
Petr Menšík
bcb46809dc Optimization of socket events handling of dbus.
Reduces calls to locate the file descriptor structure. Should lower CPU usage when monitoring
dbus watches.
2023-04-17 21:05:00 +01:00
Petr Menšík
33635d8564 Fix crash in dbus code.
If I configure dnsmasq to use dbus and then restart dbus.service with watchers present,
it crashes dnsmasq. The reason is simple, it uses loop to walk over watchers to call
dbus handling code. But from that code the same list can be modified and watchers removed.
But the list iteration continues anyway.

Restart the loop if list were modified.
2023-04-17 20:55:31 +01:00
Simon Kelley
bd188e306a Fix paren blunder in aaba66efbd
Thanks to Dominik Derigs for spotting this.
2023-04-17 16:23:06 +01:00
Simon Kelley
aaba66efbd Add --no-dhcpv4-interface and --no-dhcpv6-interface options. 2023-04-12 22:55:14 +01:00
Simon Kelley
597378cdf5 Turn "used" member of struct iname into flags in preparation for more. 2023-04-12 16:25:49 +01:00
Simon Kelley
15dcdc824a Missed copyright date. 2023-04-05 17:42:23 +01:00
Simon Kelley
86ee779e22 Make --server=/#/<addr> behave the same as --server=<addr>
For consistency with --address and older dnsmasq releases.
2023-04-05 17:29:04 +01:00
Simon Kelley
df242de5c6 Bump copyrights to 2023. 2023-04-05 12:34:34 +01:00
Simon Kelley
b14aa762ff Fix long-term bug in TCP caching code which would lose NXDOMAIN.
A NXDOMAIN answer recieved over TCP by a child process would
be correctly sent back to the master process which would then
fail to insert it into the cache.
2023-04-01 22:03:49 +01:00
Simon Kelley
a78487a4df Use a simpler arrangement for the all_addr union to avoid
the compiler padding it with an extra 8 bytes.

Use the F_KEYTAG flag in a a cache record to discriminate between
an arbitrary RR stored entirely in the addr union and one
which has a point to block storage.
2023-04-01 21:35:26 +01:00
Simon Kelley
3a601d06bd Fix copy-n-paste error in 138e1e2a2d 2023-04-01 00:50:29 +01:00
Simon Kelley
047256a6d8 --domain=# is valid. --synth-domain=# isn't. 2023-03-31 23:28:56 +01:00
Simon Kelley
c244d92d8a Allow --cache-rr=ANY with the obvious meaning. 2023-03-31 22:45:35 +01:00
Simon Kelley
138e1e2a2d Optimse memory use for arbitrary-RR caching.
RRs 13 bytes or less don't need to allocate block storage.
2023-03-31 17:44:02 +01:00
Simon Kelley
153eeb070b Optimise no-action case in rrfilter(). 2023-03-30 16:00:04 +01:00
Simon Kelley
a3c8b75972 Add filtering of arbitrary RR-types. 2023-03-29 22:43:21 +01:00
Simon Kelley
042c64273d Remove code for caching SRV.
Function replaced by the ability to cache any RR type.

For backwards compatibilty SRV records are always on the
list of cacheable RR-types.
2023-03-28 18:24:22 +01:00
Simon Kelley
638c7c4d20 Add --cache-rr to enable caching of arbitrary RR types. 2023-03-23 17:15:35 +00:00
Simon Kelley
88fc6c8023 Fold F_NOERR and F_DNSSEC to make space for new F_RR. 2023-03-20 23:11:38 +00:00
Simon Kelley
3fb10cd0d8 Merge branch 'master' into all-rr-type 2023-03-20 22:30:11 +00:00
Simon Kelley
ff28a485cf Close Debian bug. 2023-03-20 22:22:46 +00:00
Simon Kelley
1f0f86a0d0 Add EDE "filtered" extended error when --filter-A or --filter-AAAA act.
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.
2023-03-20 18:32:14 +00:00
Simon Kelley
2842972035 More --filter-AAAA caching improvements.
Cache answers before filtering and filter coming out of the cache.
2023-03-20 17:14:17 +00:00
Simon Kelley
5a9eae429a Improve cache use with --filter-A and --filter-AAAA
If --filter-AAAA is set and we have cached entry for
the domain in question fpr any RR type that allows us to
return a NODATA reply when --filter-AAAA is set without
going upstream. Similarly for --filter-A.
2023-03-20 15:16:29 +00:00
Simon Kelley
9461807011 Remove limitation on --dynamic-host.
Dynamic-host was implemented to ignore interface addresses with /32
(or /128 for IPv6) prefix lengths, since they are not useful for
synthesising addresses.

Due to a bug before 2.88, this didn't work for IPv4, and some have
used --dynamic-host=example.com,0.0.0.0,eth0 to do the equivalent of
--interface-name for such interfaces. When the bug was fixed in 2.88
these uses broke.

Since this behaviour seems to violate the principle of least surprise,
and since the 2.88 fix is breaking existing imstallations, this
commit removes the check on /32 and /128 prefix lengths to solve both
problems.
2023-03-16 15:16:17 +00:00
Simon Kelley
00be8b39e2 Fix DHCPv6 "use multicast" response which previously failed
to set the message type correctly.

Thanks to Petr Menšík for spotting the problem.
2023-03-15 21:12:55 +00:00
Clayton Craft
ef5aac95d4 Allow configuring filter-A/AAAA via dbus. 2023-03-08 15:35:05 +00:00
Simon Kelley
ef8e930e42 Generalise cached NXDOMAIN replies.
We can cache an NXDOMAIN reply to a query for any RRTYPE
and reply from a cached NXDOMAIN to any RRTYPE.
2023-03-08 12:47:45 +00:00
Simon Kelley
eb92fb32b7 Set the default maximum DNS UDP packet size to 1232.
http://www.dnsflagday.net/2020/ refers.

Thanks to Xiang Li for the prompt.
2023-03-07 22:21:21 +00:00
Simon Kelley
9a698434dd Bump version in Debian changelog. 2023-03-06 23:30:36 +00:00
Simon Kelley
f5ef0f064c Fix possible SEGV when no servers defined.
If there exists a --address=/<domain>/  or --server=/<domain>/#
configuration but no upstream server config unqualified by
domain then when a query which doesnt match the domain is
recieved it will use the qualfied server config and in the process
possibly make an out-of-bounds memory access.

Thanks to Daniel Danzberger for spotting the bug.
2023-03-06 23:00:58 +00:00
Dominik Derigs
997982f78b Fix --rev-server option. It was broken in 1db9943c68 when resolving upstream servers by name was extended to --rev-server without accounting for the fact that re-using one and the same upstream server for each of the x.y.z.in-addr.arpa is actually a wanted feature
Signed-off-by: DL6ER <dl6er@dl6er.de>
2023-03-06 17:32:18 +00:00
Simon Kelley
7d6b68c5d7 Document suppressing deafult options in --dhcp-option. 2023-03-06 13:06:03 +00:00
Taylor R Campbell
137ae2e9cf Avoid undefined behaviour with the ctype(3) functions.
As defined in the C standard:

	In all cases the argument is an int, the value of which shall
	be representable as an unsigned char or shall equal the value
	of the macro EOF.  If the argument has any other value, the
	behavior is undefined.

This is because they're designed to work with the int values returned
by getc or fgetc; they need extra work to handle a char value.

If EOF is -1 (as it almost always is), with 8-bit bytes, the allowed
inputs to the ctype(3) functions are:

	{-1, 0, 1, 2, 3, ..., 255}.

However, on platforms where char is signed, such as x86 with the
usual ABI, code like

	char *arg = ...;
	... isspace(*arg) ...

may pass in values in the range:

	{-128, -127, -126, ..., -2, -1, 0, 1, ..., 127}.

This has two problems:

1. Inputs in the set {-128, -127, -126, ..., -2} are forbidden.

2. The non-EOF byte 0xff is conflated with the value EOF = -1, so
   even though the input is not forbidden, it may give the wrong
   answer.

Casting char to int first before passing the result to ctype(3)
doesn't help: inputs like -128 are unchanged by this cast.  It is
necessary to cast char inputs to unsigned char first; you can then
cast to int if you like but there's no need because the functions
will always convert the argument to int by definition.  So the above
fragment needs to be:

	char *arg = ...;
	... isspace((unsigned char)*arg) ...

This patch inserts unsigned char casts where necessary, and changes
int casts to unsigned char casts where the input is char.

I left alone int casts where the input is unsigned char already --
they're not immediately harmful, although they would have the effect
of suppressing some compiler warnings if the input is ever changed to
be char instead of unsigned char, so it might be better to remove
those casts too.

I also left alone calls where the input is int to begin with because
it came from getc; casting to unsigned char here would be wrong, of
course.
2023-02-27 14:56:25 +00:00
Simon Kelley
5dc14b6e05 Replace dead link in dnsmasq.conf.example.
Thanks to Timo van Roermund for spotting this.
2023-02-02 20:24:24 +00:00
Simon Kelley
0427e37116 Replace dead link in dnsmasq.conf.example.
Thanks to Timo van Roermund for spotting this.
2023-02-02 20:20:13 +00:00
Dominik Derigs
e5e8cae1ca Add --no-ident option. 2023-01-23 22:48:01 +00:00
Simon Kelley
7f42ca8af8 Add acknowledgements to CHANGELOG for the 2.88 AWS efforts. 2023-01-14 11:12:17 +00:00
Simon Kelley
e4251eb13b Fix Changelog typos. 2023-01-14 11:01:10 +00:00
Simon Kelley
5083876910 Bump version in Debian changelog. 2023-01-13 22:03:33 +00:00
Simon Kelley
f172fdbb77 Fix bug which can break the invariants on the order of a hash chain.
If there are multiple cache records with the same name but different
F_REVERSE and/or F_IMMORTAL flags, the code added in fe9a134b could
concievable break the REVERSE-FORWARD-IMMORTAL order invariant.

Reproducing this is damn near impossible, but it is responsible
for rare and otherwise inexplicable reversion between 2.87 and 2.88
which manifests itself as a cache internal error. All observed
cases have depended on DNSSEC being enabled, but the bug could in
theory manifest itself without DNSSEC

Thanks to Timo van Roermund for reporting the bug and huge
efforts to isolate it.
2023-01-13 21:12:53 +00:00
Simon Kelley
3822825e54 Fix cosmetic big in dump_cache_entry() 2023-01-04 23:10:07 +00:00
Simon Kelley
1da54210fc Log all cache internal errors. 2023-01-02 22:17:57 +00:00
Simon Kelley
43a2a66531 If we hit a cache internal error, log the entry we failed to remove.
This is code which should never run, but if it does,
we now log information useful for debugging.
2022-12-22 23:19:05 +00:00
Simon Kelley
e6841ea2e0 Add posix-timezone and tzdb-timezone DHCPv6 options.
They are already in place for DHCPv4.
2022-12-04 22:00:54 +00:00
Simon Kelley
e939b45c9f Handle malformed DNS replies better.
If we detect that that reply from usptream is malformed,
transform it into a SERVFAIL reply before sending to the
original requestor.
2022-11-26 22:19:29 +00:00
Brad Smith
e3068ed111 Fix warning in cache.c 2022-11-26 21:48:17 +00:00
Dominik Derigs
efbf80be58 Make max staleness of stale cache entries configurable and default to one day. 2022-11-26 21:18:34 +00:00
Petr Menšík
022ad63f0c Fix use-after-free in mark_servers() 2022-11-26 18:49:21 +00:00
Petr Menšík
02f8754339 fixup! Handle DS records for unsupported crypto algorithms. 2022-11-22 22:51:11 +00:00
Simon Kelley
142456cfd0 Merge i18n strings. 2022-11-21 16:56:51 +00:00
Simon Kelley
207ce40db2 Add /etc/hosts gotcha to man page section for --dhcp-hosts. 2022-11-21 16:53:56 +00:00
Simon Kelley
881eaa4dbc Optimise readng large number --server options at start up.
When re-reading upstream servers from /etc/resolv.conf or other
sources that can change dnsmasq tries to avoid memory fragmentation by
re-using existing records that are being re-read unchanged. This
involves seaching all the server records for each new one installed.
During startup this search is pointless, and can cause long start
times with thousands of --server options because the work needed is
O(n^2). Handle this case more intelligently.  Thanks to Ye Zhou for
spotting the problem and an initial patch.
2022-11-21 16:40:53 +00:00
Matthias Andree
d6d7527c95 Fix CHANGELOG typos. 2022-11-18 09:10:32 +00:00
Conrad Kostecki
11b4be2036 Update german translation for release 2.88. 2022-11-17 20:00:42 +00:00
Simon Kelley
3e306c1202 Fix SEGV on --local= added by immediately previous commit. 2022-11-17 19:51:15 +00:00
Simon Kelley
7f227a83f2 Fix struct hostinfo free code and BSD compile.
The code added in6 c596f1cc1d92b2b90ef5ce043ace314eefa868b
fails to free the returned datastructures from gethostinfo()
because sdetails.hostinfo is used to loop through the addresses
and ends up NULL. In some libc implementations this results
in a SEGV when freeaddrinfo() is called.

Also fix FTBFS under BSD. Thanks to Johnny S. Lee for the bug report.
2022-11-17 13:16:55 +00:00
Simon Kelley
9ed3ee67ec Handle DS records for unsupported crypto algorithms correctly.
Such a DS, as long as it is validated, should allow answers
in the domain is attests to be returned as unvalidated, and not
as a validation error.
2022-11-16 16:49:30 +00:00
Simon Kelley
1f9215f5f9 Fix GOST signature algorithms for DNSSEC validation.
Use CryptoPro version of the hash function.
Handle the little-endian wire format of key data.
Get the wire order of S and R correct.

Note that Nettle version 3.6 or later is required for GOST support.
2022-11-16 15:57:31 +00:00
Simon Kelley
f52cfdd8c3 Handle known DNSSEC signature algorithms which are not supported.
This fixes a confusion if certain algorithms are not supported
because the version is the crypto library is too old.  The validation
should be treated the same as for a completely unknown algorithm,
(ie return unverified answer) and not as a validation failure
(ie return SERVFAIL).

The algorithems affected are GOST and ED448.
2022-11-13 15:55:09 +00:00
Simon Kelley
2fc904111d Fix --server=/domain/# 2022-11-07 23:24:31 +00:00
Simon Kelley
262dadf50e Fix --server with multiple domains. 2022-11-07 23:14:30 +00:00
Simon Kelley
6c596f1cc1 Make specifying nameservers by name work for DBus API. 2022-11-07 23:00:34 +00:00
Simon Kelley
dafa16c400 Call freeaddrinfo() in domain_rev[46]() 2022-11-07 22:01:28 +00:00
Simon Kelley
1db9943c68 Extend specifying DNS servers by domain-name to --rev-server
Also Dbus SetDomainServers method.

Revert getaddrinfo hints.ai_socktype to SOCK_DGRAM to eliminate
duplicating every address three times for DGRAM, STREAM and RAW
in the results.
2022-11-06 21:10:19 +00:00
Simon Kelley
5b868c213b Fix breakage of --local=/domain.name/1.2.3.4 in immediately previous commit. 2022-11-06 20:18:27 +00:00
Dominik Derigs
2d8905dafd Allow domain names as well is IP addresses in --server options. 2022-11-05 11:49:52 +00:00
Simon Kelley
9002108551 Bump Debian version and close bug. 2022-11-02 22:18:35 +00:00
Simon Kelley
d3c21c596e Reconcile "names" and "address" counts when reading hostfiles. 2022-10-30 15:40:20 +00:00
Simon Kelley
34fac952b6 Inotify: make "flushed" log message more understandable.
Saying we've "flushed x outdated entries" is confusing, since
the count is the total number of entries in the modified file,
most of which are going	to get added straight back when	the file
is re-read.

The log now looks like

dnsmasq: inotify: /tmp/dir/1 (new or modified)
dnsmasq: inotify: flushed 1 addresses read from /tmp/dir/1
dnsmasq: read /tmp/dir/1 - 2 addresses

which hopefully make it more obvious that /tmp/dir/1 contained one
address before, and now contains two.
2022-10-27 13:24:37 +01:00
Dominik Derigs
92c32e0bac Do not (try to) re-read deleted files inside a --hostsdir. 2022-10-27 12:36:38 +01:00
Simon Kelley
1bcad67806 Fix in dhcpv4 rapid-commit code.
1) Cosmetic: don't log the tags twice.

2) Functional. If a host has an old lease for a different address,
   the rapid-commit will appear to work, but the old lease will
   not be removed and the new lease will not be recorded, so
   the client and server will have conflicting state, leading to
   problems later.
2022-10-27 12:04:58 +01:00
Simon Kelley
fe9a134baf Add --no-round-robin option. 2022-10-18 16:06:48 +01:00
Simon Kelley
930428fb97 Fix loss of DNS servers on config reload.
A bug, introduced in 2.87, which could result in DNS
servers being removed from the configuration when reloading
server configuration from DBus, or re-reading /etc/resolv.conf
Only servers from the same source should be replaced, but some
servers from other sources (ie hard coded or another dynamic source)
could mysteriously disappear.
2022-10-17 21:15:43 +01:00
Dominik Derigs
936be022d9 Handle multiple addresses when removing duplicates in host files. 2022-10-16 22:30:08 +01:00
Dominik Derigs
0017dd74d5 Enhance --hostdir so that records are automatically removed when re-reading.
Initial patch from Dominik Derigs, re-written by Simon Kelley.
2022-10-16 22:10:48 +01:00
Dominik Derigs
0ba25a0512 Improve logging of DNS record source from --hostsdir files.
Patch author Dominik Derigs <dl6er@dl6er.de> with subsequent bugfixes
and tweaks from Simon Kelley.
2022-10-16 21:14:16 +01:00
Simon Kelley
a176cf1bc3 Move fast-dns-retry and use-stale-cache writeups in the CHANGELOG.
These are 2.88 changes, but the branch merge put them unde 2.87.
2022-10-14 11:46:13 +01:00
Simon Kelley
fdd9a96a8c Merge branch 'aws' 2022-10-13 15:37:52 +01:00
Simon Kelley
b87d7aa041 Fix bug in --dynamic-host when interface has /16 IPv4 address. 2022-10-13 15:02:54 +01:00
Temuri Doghonadze
f753e7eba6 Add Georgian translation. 2022-10-13 14:33:01 +01:00
Simon Kelley
78a5a21655 Fix Debian changelog date Fubar. 2022-09-25 23:55:09 +01:00
Simon Kelley
a5cbe6d112 Add ClearMetrics Dbus method. 2022-09-16 12:58:41 +01:00
Simon Kelley
9403664616 Optimise cache code when stale caching in use.
Exclude DNSSEC entries from stale caching.
2022-09-16 12:44:04 +01:00
Simon Kelley
f32498465d Don't exclude stale-cache answers from "local answered" metric. 2022-09-16 09:35:44 +01:00
Simon Kelley
fa45e06431 Initialise modified-moving-average latency calc better.
Use the first value, rather than initialising at zero,
which takes many queries to converge.
2022-09-16 00:16:18 +01:00
Simon Kelley
6722ec6c78 Split failed queries in retries in stat counting. 2022-09-16 00:07:36 +01:00
Simon Kelley
d882dfdae9 Tweak server-selection logic in the fast-retry case. 2022-09-15 23:54:53 +01:00
Simon Kelley
a2ee2426bf Keep a per-DNS-server moving average of query latency. 2022-09-15 23:22:02 +01:00
Simon Kelley
84bd46ddd7 Combine server stats from all records for the same server in DBUS method.
The DBUS per-server stats method should combine the stats from
different records (for different domains) in the same way at the
logging code.
2022-09-15 22:43:08 +01:00
Simon Kelley
271790685a Count NXDOMAIN replies from each server. 2022-09-15 22:29:44 +01:00
Simon Kelley
7a74037267 Add metric for queries which never see an answer. 2022-09-15 22:06:39 +01:00
Simon Kelley
9a9f6e147c Make fast-retry more configurable and do exponential backoff. 2022-09-15 19:29:49 +01:00
Simon Kelley
8f2d432799 Remove unused vars. 2022-09-13 09:36:08 +01:00
Simon Kelley
92eab03b12 Return EDE_STALE extended error when returning stale data from cache. 2022-09-12 15:28:46 +01:00
Simon Kelley
1ba4ae2830 Add stale cache replies to metrics. 2022-09-12 14:50:17 +01:00
Simon Kelley
0076481dfd Add GetServerMetrics method to DBus interface. 2022-09-12 14:35:40 +01:00
Simon Kelley
c0e731d545 Further optimisation of --port-limit.
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.
2022-09-09 23:15:50 +01:00
Simon Kelley
3f56bb8ba1 Second try at port-limit option.
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.
2022-09-09 17:09:32 +01:00
Simon Kelley
e518e87533 Fix namebuff overwrite leading to wrong log after socket bind warning. 2022-09-09 15:57:39 +01:00
Simon Kelley
c4b9bc63e0 Fix a problem in overload handling.
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.
2022-09-09 12:53:49 +01:00
Simon Kelley
1d53d958bb Remove fast-retry development logging. 2022-09-06 22:43:33 +01:00
Simon Kelley
d334e7c34f Add --use-stale-cache option. 2022-09-06 22:43:33 +01:00
Simon Kelley
d21438a7df Add --fast-dns-retry option.
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.
2022-09-06 22:43:33 +01:00
Simon Kelley
24c3b5b3d4 Add --port-limit option.
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.
2022-09-06 22:43:33 +01:00
Simon Kelley
4447d48bb9 Add DHCPv4 option 108 "ipv6-only" to the options table. 2022-09-06 22:40:06 +01:00
Simon Kelley
04cc2ae1a6 Fix logic when a SERVFAIL reply is received after good replt for DNSSEC.
If we get a SERVFAIL or REFUSED answer to a DNSSEC query for which
we already have a good answer, just ignore it.
2022-09-06 18:31:59 +01:00
Simon Kelley
32588c755a Add source address to RA packet dumps. 2022-09-06 18:08:39 +01:00
Simon Kelley
84a6d07cdd Fix DHCPv6 relay to use a more sensble source address.
Tweak things so that packets relayed towards a server
have source address on the server-facing network, not the
client-facing network. Thanks to Luis Thomas for spotting this
and initial patch.
2022-09-06 15:40:42 +01:00
Simon Kelley
d6c69f6bdb Free sockets awaiting upstream DNS replies ASAP.
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.
2022-09-06 15:35:54 +01:00
Simon Kelley
ce372917fe Tweak packet dump code to make port numbers more accurate.
Also add query-ids with log-queries=extra.
2022-09-05 18:04:35 +01:00
Simon Kelley
09d741f58a Simplify realloc use in poll.c 2022-08-11 17:04:54 +01:00
Petr Menšík
0666ae3d27 Introduce whine_realloc
Move few patters with whine_malloc, if (successful) copy+free, to a new
whine_realloc. It should do the same thing, but with a help from OS it
can avoid unnecessary copy and free if allocation of more data after
current data is possible.

Added few setting remanining space to 0, because realloc does not use
calloc like whine_malloc does. There is no advantage of zeroing what we
will immediately overwrite. Zero only remaining space.
2022-08-11 16:56:58 +01:00
Simon Kelley
ba4c7d906b CHANGELOG typo. 2022-08-08 15:36:47 +01:00
Simon Kelley
f4b2813818 Fix bad interaction between --address=/#/<ip> and --server=/some.domain/#
This would return <ip> for queries in some.domain, rather than
forwarding the query via the default server(s) read from /etc/resolv.conf.
2022-08-08 15:27:32 +01:00
Bertie, Taylor
5586934da0 Bound the value of UDP packet size in the EDNS0 header of
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.
2022-07-31 17:20:21 +01:00
Simon Kelley
6134b94c02 Update man page on DHCP data provided to scripts. Provide requested options for DHCPv6 also. 2022-07-31 12:15:38 +01:00
Simon Kelley
05e6728e98 Fix bit-rotted data handling code for LUA scripts. 2022-07-31 11:33:05 +01:00
Simon Kelley
6578acd668 Tidy last two commits. 2022-07-31 11:04:12 +01:00
Kevin Yeich
b5581ed173 Pass MUD URLs (RFC 8520) supplied via DHCPv4 to DHCP scripts
Extract Manufacturer Usage Description (MUD) URL from DHCP Option 161
and make it available to DHCP scripts as DNSMASQ_MUD_URL.

See https://datatracker.ietf.org/doc/html/rfc8520#section-17.3
and https://datatracker.ietf.org/doc/html/rfc8520#section-10

Co-authored-by: Jasper Wiegratz <wiegratz@uni-bremen.de>
2022-07-29 13:01:47 +01:00
Hugo Hakim Damer
508d6b4885 Pass MUD URLs (RFC 8520) supplied via DHCPv6 to DHCP scripts
Extract Manufacturer Usage Description (MUD) URL from DHCP Option 112
and make it available to DHCP scripts as DNSMASQ_MUD_URL.

This expands on the initial support for Manufacturer Usage Description
URLs that has been added in the previous commit for DHCPv4 by also
supporting MUD URLs supplied using DHCPv6.

See https://datatracker.ietf.org/doc/html/rfc8520#section-17.3
and https://datatracker.ietf.org/doc/html/rfc8520#section-10

Co-authored-by: Jasper Wiegratz <wiegratz@uni-bremen.de>
2022-07-29 12:57:27 +01:00
Simon Kelley
ef6efd69ed Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-07-19 23:40:50 +01:00
Simon Kelley
151d7dc5ea Fix comment typo. 2022-07-19 23:40:11 +01:00
Simon Kelley
20b4a4ea5b Fix comment typo. 2022-07-07 20:56:07 +01:00
Beniamino Galvani
770bce967c Fix parsing of IPv6 addresses with peer from netlink.
In the most common case, an IPv6 address doesn't have a peer and the
IFA_ADDRESS netlink attribute contains the address itself.

But if the address has a peer (typically for point to point links),
then IFA_ADDRESS contains the peer address and IFA_LOCAL contains the
address [1].

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv6/addrconf.c?h=v5.17#n5030

Fix the parsing of IPv6 addresses with peers, as currently dnsmasq
unsuccessfully tries to bind on the peer address.

A simple reproducer is:

  dnsmasq --conf-file=/dev/null -i dummy1 -d --bind-dynamic &
  sleep 2
  ip link add dummy1 type dummy
  ip link set dummy1 up
  ip addr add dev dummy1 fd01::1/64 peer fd01::2/64
  ip addr add dev dummy1 fd01::42/64
  sleep 2
  ss -lnp | grep dnsmasq | grep fd01

Before the patch:
  dnsmasq: failed to create listening socket for fd01::2: Cannot assign requested address
  dnsmasq: failed to create listening socket for fd01::2: Cannot assign requested address
  udp   UNCONN 0   [fd01::42]:53   [::]:*    users:(("dnsmasq",pid=23947,fd=14))
  tcp   LISTEN 0   [fd01::42]:53   [::]:*    users:(("dnsmasq",pid=23947,fd=15

After:
  udp   UNCONN 0   [fd01::42]:53   [::]:*    users:(("dnsmasq",pid=23973,fd=16))
  udp   UNCONN 0    [fd01::1]:53   [::]:*    users:(("dnsmasq",pid=23973,fd=14))
  tcp   LISTEN 0   [fd01::42]:53   [::]:*    users:(("dnsmasq",pid=23973,fd=17))
  tcp   LISTEN 0    [fd01::1]:53   [::]:*    users:(("dnsmasq",pid=23973,fd=15))
2022-05-27 21:16:18 +01:00
Simon Kelley
a267a9e489 Add the ability to specify destination port in DHCP-relay mode.
This change also removes a previous bug
where --dhcp-alternate-port would affect the port used
to relay _to_ as well as the port being listened on.
The new feature allows configuration to provide bug-for-bug
compatibility, if required. Thanks to Damian Kaczkowski
for the feature suggestion.
2022-05-26 16:40:44 +01:00
Simon Kelley
f65d210012 Fix outdated comment. 2022-05-26 14:49:10 +01:00
Petr Menšík
858bfcf261 Update GNU GPL file. 2022-05-13 21:22:11 +01:00
Dominik Derigs
9b801c4e72 Also log upstream port for dnssec-retry
Signed-off-by: DL6ER <dl6er@dl6er.de>
2022-04-18 15:28:27 +01:00
袁建鹏
1a98d1a94f Add inode compare while checking resolv file change
Fix a bug found on OpenWrt when IPv4/6 dual stack enabled:

The resolv file is located on tmpfs whose mtime resolution
is 1 second. If the resolv file is updated twice within one
second dnsmasq may can't notice the second update.

netifd updates the resolv file with method: write temp then move,
so adding an inode check fixes this bug.
2022-04-18 15:25:54 +01:00
Simon Kelley
03345ecefe Fix write-after-free error in DHCPv6 code. CVE-2022-0934 refers. 2022-03-31 21:35:20 +01:00
Simon Kelley
191924576c Add DNSMASQ_DATA_MISSING envvar to lease-change script. 2022-03-22 13:47:05 +00:00
Simon Kelley
756a1dcc19 Manpage update for --localise-queries.
Thanks to Leonardo Romor for the suggestion.
2022-03-05 18:13:15 +00:00
Simon Kelley
3ab6dd1c37 Enhance --domain to accept, interface names for the address range.
This allows hosts get a domain which relects the interface they
are attached to in a way which doesn't require hard-coding addresses.

Thanks to Sten Spans for the idea.
2022-03-05 18:07:07 +00:00
Simon Kelley
4458d87289 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-03-05 16:31:17 +00:00
Conrad Kostecki
b7f62475d0 Update German translation. 2022-03-02 19:28:26 +00:00
Simon Kelley
4732aa663b Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-24 23:21:55 +00:00
Simon Kelley
c27cfeaa7b Fix memory leak when DBUS connection fails. 2022-02-24 23:18:54 +00:00
Simon Kelley
bb6f6bae0b Fix longjump() compiler warnings. 2022-02-24 23:16:04 +00:00
Simon Kelley
f4c87b504b Fix missing reverse-records from --dynamic-host.
Thanks to Sten Spans for spotting the bug.
2022-02-18 20:53:56 +00:00
Simon Kelley
e426c2d3bc Add --conf-script 2022-02-08 12:10:27 +00:00
Simon Kelley
6279d9eaf3 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-04 22:28:53 +00:00
Simon Kelley
12949aa0c0 Ask netlink for new address events unconditionally.
The circumstances under which actions occur depending on
configuration is now controlled only by newaddress() in network.c
2022-02-04 22:24:00 +00:00
Simon Kelley
84f3357dd9 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-04 21:00:16 +00:00
Johnny S. Lee via Dnsmasq-discuss
4333d5d93a Fix FTBFS on BSD platforms.
Bug introduced in fc664d114d
2022-02-03 23:42:00 +00:00
Simon Kelley
fa580ad3eb Handle changing interface indexes when binding DHCP sockets. 2022-02-03 17:26:28 +00:00
Simon Kelley
292dfa653e Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-02 18:31:22 +00:00
Simon Kelley
7fbf1cce7b Improve the performance of DHCP relay.
On machines with many interfaces, enumerating them
via netlink on each packet reciept is slow,
and unneccesary. All we need is the local address->interface
mapping, which can be cached in the relay structures.
2022-02-02 18:28:27 +00:00
Simon Kelley
dbceeb4178 Dump.c Fix IPv6 checksum on big-endian. 2022-01-30 00:42:46 +00:00
Simon Kelley
ed200fa001 Handle options other than source link-layer address in router solicitations.
RFC 4861 para 4.1 is a MUST.
2022-01-29 23:22:52 +00:00
Simon Kelley
b5dafc0b7e Extend packet dump system to RA. 2022-01-29 22:52:21 +00:00
Simon Kelley
fc664d114d Extend packet-dump system to DHCP and TFTP. 2022-01-29 15:55:04 +00:00
Simon Kelley
c6d4c33d61 Bump copyright to 2022. 2022-01-24 15:19:00 +00:00
Simon Kelley
bf1fc6c6fd Tidy iface_check(). 2022-01-21 15:47:09 +00:00
Olaf Hering
b18e9c8c61 fix dnsmasq typo in man page
Fixes commit 27ce754b3d

Signed-off-by: Olaf Hering <olaf@aepfle.de>
2022-01-21 12:18:08 +00:00
Simon Kelley
a3293bb242 Fix indentation in Umbrella option code. 2022-01-21 12:07:42 +00:00
Simon Kelley
4e2a4b8788 Fix crash in PXE code with bad config. 2022-01-18 00:55:13 +00:00
Simon Kelley
2362784bc0 Debian bug management. 2022-01-18 00:32:15 +00:00
Simon Kelley
b2cec1b881 Debian: fold in 2.86-1.1 changelog and close bug introducded by same. 2022-01-18 00:02:32 +00:00
Simon Kelley
a946857133 Remove temporary debugging message and close related Debian bug. 2022-01-17 23:54:58 +00:00
Simon Kelley
10cd342f5c Document change of behaviour of --address in 2.86 onwards. 2022-01-17 16:01:02 +00:00
Simon Kelley
27ce754b3d Tidy previous commit and add manpage entries for new options. 2022-01-15 17:57:57 +00:00
Dominik Derigs
3ab0ad8748 Strip EDNS(0) Client Subnet / MAC information if --strip-subnet or --strip-mac is set. If both the add and strip options are set, incoming EDNS0 options are replaced. This ensures we do not unintentionally forward client information somewhere upstream when ECS is used in lower DNS layers in our local network.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2022-01-15 15:36:28 +00:00
Dominik Derigs
4308236262 Minimum safe size is recommended to be 1232. See https://dnsflagday.net/2020/
Signed-off-by: DL6ER <dl6er@dl6er.de>
2022-01-13 00:31:54 +00:00
Simon Kelley
ebd8350300 Fix DNSSEC failure to validate unsigned NoDATA replies.
A reply with an empty answer section would not always be checked
for either suitable NSEC records or proof of non-existence of
the relevant DS record.
2022-01-13 00:12:07 +00:00
Simon Kelley
8285d335f4 Fix error introduced in 11c52d032b 2022-01-12 23:05:25 +00:00
Simon Kelley
9db275ebea Small fix to ff43d35aee 2022-01-12 23:00:16 +00:00
Petr Menšík
1f8f78a49b Add root group writeable flag to log file
Some systems strips even root process capability of writing to different
users file. That include systemd under Fedora. When
log-facility=/var/log/dnsmasq.log is used, log file with mode 0640
is created. But restart then fails, because such log file can be used
only when created new. Existing file cannot be opened by root when
starting, causing fatal error. Avoid that by adding root group writeable flag.

Ensure group is always root when granting write access. If it is
anything else, administrator has to configure correct rights.
2022-01-11 23:43:09 +00:00
Simon Kelley
c2f129ba3d Fix FTBFS when HAVE_DNSSEC not defined. 2022-01-11 22:48:14 +00:00
Simon Kelley
07c47416a9 Log source of ignored query when local-service is used.
Thanks to Dominik Derigs for the initial patch.
2022-01-11 22:36:01 +00:00
Dominik Derigs
8f2a62b386 Extend cache dump: "!" as type for non-terminals, new flag "C" for config-provided and log source when applicable.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2022-01-11 22:17:14 +00:00
Dominik Derigs
a6c0edd4f4 Fix header of cache dump. The width of the host and address fields are 30 and 40 characters, respectively.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2022-01-11 22:16:48 +00:00
Simon Kelley
ff43d35aee Log port numbers in server addresses when non-standard ports in use. 2022-01-11 22:09:09 +00:00
Simon Kelley
70fca205be Overhaul code which sends DNSSEC queries.
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.
2022-01-11 00:29:36 +00:00
Simon Kelley
1033130b6c Handle malformed query packets sensibly.
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.
2022-01-09 23:21:55 +00:00
Andreas Metzler
8cfcd9ff63 Clarify man page for --filterwin2k 2022-01-06 23:12:53 +00:00
Daniel Collins
80a6c16dcc Implements a SetLocaliseQueriesOption D-Bus method.
For setting the state of the -y/--localise-queries option.
2022-01-06 00:23:53 +00:00
Simon Kelley
553c4c99cc Fix massive confusion on server reload.
The 2.86 upstream server rewrite severely broke re-reading
of server configuration. It would get everyting right the first
time, but on re-reading /etc/resolv.conf or --servers-file
or setting things with DBUS, the results were just wrong.

This should put things right again.
2022-01-03 23:32:30 +00:00
Simon Kelley
4165c1331b Fix fail to build when NO_SCRIPT set. 2022-01-03 23:31:15 +00:00
Fabrice Fontaine
b2690415bf src/option.c: fix build with gcc 4.8
Thanks for applying and fixing my patch. Here is another one on src/pattern.c

Best Regards,

Fabrice

Le dim. 2 janv. 2022 à 00:36, Simon Kelley <simon@thekelleys.org.uk> a écrit :
>
>
>
> Thanks,
>
>
> patch applied. Followed by a small fix, and then a larger fix when I was
> forced to look at the code in question ;)
>
>
>
> Cheers,
>
> Simon.
>
> On 31/12/2021 16:29, Fabrice Fontaine wrote:
> > Fix the following build failure with gcc 4.8 raised since version 2.86:
> >
> > option.c: In function 'one_opt':
> > option.c:2445:11: error: 'for' loop initial declarations are only allowed in C99 mode
> >            for (char *p = arg; *p; p++) {
> >            ^
> > option.c:2445:11: note: use option -std=c99 or -std=gnu99 to compile your code
> > option.c:2453:11: error: 'for' loop initial declarations are only allowed in C99 mode
> >            for (u8 i = 0; i < sizeof(daemon->umbrella_device); i++, arg+=2) {
> >            ^
> >
> > Fixes:
> >  - http://autobuild.buildroot.org/results/39b34a4e69fc10f4bd9d4ddb0ed8c0aae5741c84
> >
> > Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
> > ---
> >  src/option.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/option.c b/src/option.c
> > index ff54def..c57f6d8 100644
> > --- a/src/option.c
> > +++ b/src/option.c
> > @@ -2525,7 +2525,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
> >            arg += 9;
> >            if (strlen(arg) != 16)
> >                ret_err(gen_err);
> > -          for (char *p = arg; *p; p++) {
> > +          char *p;
> > +          for (*p = arg; *p; p++) {
> >              if (!isxdigit((int)*p))
> >                ret_err(gen_err);
> >            }
> > @@ -2533,7 +2534,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
> >
> >            u8 *u = daemon->umbrella_device;
> >            char word[3];
> > -          for (u8 i = 0; i < sizeof(daemon->umbrella_device); i++, arg+=2) {
> > +          u8 i;
> > +          for (i = 0; i < sizeof(daemon->umbrella_device); i++, arg+=2) {
> >              memcpy(word, &(arg[0]), 2);
> >              *u++ = strtoul(word, NULL, 16);
> >            }
> >
>

From 0c89dd2fa0fe50b00bca638dbbacfbd361526e0a Mon Sep 17 00:00:00 2001
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Date: Sun, 2 Jan 2022 21:57:52 +0100
Subject: [PATCH] src/pattern.c: fix build with gcc 4.8

Fix the following build failure:

pattern.c: In function 'is_valid_dns_name':
pattern.c:134:3: error: 'for' loop initial declarations are only allowed in C99 mode
   for (const char *c = value;; c++)
   ^
pattern.c:134:3: note: use option -std=c99 or -std=gnu99 to compile your code
pattern.c: In function 'is_valid_dns_name_pattern':
pattern.c:249:3: error: 'for' loop initial declarations are only allowed in C99 mode
   for (const char *c = value;; c++)
   ^

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2022-01-03 15:13:53 +00:00
Simon Kelley
011f8cf1d0 Tidy code for --umbrella option. 2022-01-01 23:33:39 +00:00
Simon Kelley
2748fb81e2 Fix 46312909d9 typo. 2022-01-01 23:03:26 +00:00
Fabrice Fontaine
46312909d9 src/option.c: fix build with gcc 4.8
Fix the following build failure with gcc 4.8 raised since version 2.86:

option.c: In function 'one_opt':
option.c:2445:11: error: 'for' loop initial declarations are only allowed in C99 mode
           for (char *p = arg; *p; p++) {
           ^
option.c:2445:11: note: use option -std=c99 or -std=gnu99 to compile your code
option.c:2453:11: error: 'for' loop initial declarations are only allowed in C99 mode
           for (u8 i = 0; i < sizeof(daemon->umbrella_device); i++, arg+=2) {
           ^

Fixes:
 - http://autobuild.buildroot.org/results/39b34a4e69fc10f4bd9d4ddb0ed8c0aae5741c84

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2022-01-01 23:00:25 +00:00
Simon Kelley
41adecad14 Include client address if TFTP file-not-found errors. 2022-01-01 22:15:16 +00:00
Simon Kelley
ea5d8c56a0 Finesse parsing of --dhcp-remoteid and --dhcp-subscrid.
To be treated as hex, the pattern must consist of only hex digits AND
contain at least one ':'. Thanks to Bengt-Erik Sandstrom who tripped
over a pattern consisting of a decimal number which was interpreted
surprisingly.
2021-12-30 23:22:43 +00:00
Simon Kelley
d242cbffa4 Add snooping of DHCPv6 prefix delegation to the DHCP-relay function. 2021-12-30 21:20:37 +00:00
Simon Kelley
1c8855ed10 Fix wrong client address for dhcp-script when DHCPv4 relay in use. 2021-12-26 16:35:54 +00:00
Simon Kelley
ea33a01303 Fix rare "Internal error in cache" messages.
Fix error created in 1ce1c6beae

Many thanks to Hartmut Birr for finding the bug and bisecting to
the guilty commit.

The breaking commit creates cache entries which have F_NXDOMAIN
set but none of F_IPV4, F_IPV6 or F_SRV. If cache_scan_free() is called
to delete such an entry it will fail to do so.

If the cache has no free slots and the least-recently-used slot is such
an entry, then a new insertion will attempt to make space by calling
cache_scan_free(), which will fail when it should be impossible and
trigger the internal error.
2021-12-24 18:58:35 +00:00
Simon Kelley
18b1d1424e Generalise --dhcp-relay.
Sending via broadcast/multicast is now supported for both
IPv4 and IPv6 and the configuration syntax made
easier (but backwards compatible).
2021-12-20 16:40:41 +00:00
Simon Kelley
1176cd58c9 Fix regression in --rebind-domain-ok in 2.86
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.
2021-12-08 23:51:38 +00:00
guns
44a4643b62 Correctly return a heap-allocated empty string instead of NULL
Commit 32e15c3f45 added the following
change:

  --- a/src/option.c
  +++ b/src/option.c
  @@ -654,7 +654,7 @@ static char *canonicalise_opt(char *s)
       return 0;

     if (strlen(s) == 0)
  -    return "";
  +    return opt_string_alloc("");

     unhide_metas(s);
     if (!(ret = canonicalise(s, &nomem)) && nomem)

Unfortunately, opt_string_alloc(const char *cp) returns NULL when
strlen(cp) == 0, which in turn causes --rebind-domain-ok='' to crash
with SIGSEGV.
2021-12-04 12:03:31 +00:00
Simon Kelley
ed96efd865 Fix confusion with log-IDs and DNS retries.
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.
2021-12-01 16:40:26 +00:00
Simon Kelley
e3093b532c Fix problems with upper-case in domain-match.
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.
2021-11-28 18:39:42 +00:00
Simon Kelley
9560658c5b Fix crash in PXE/netboot when DNS server disabled. 2021-10-19 15:33:41 +01:00
Simon Kelley
37a70d39e0 Add --filter and --filter-AAAA options. 2021-10-07 23:12:59 +01:00
Dominik Derigs
72fac0810c dnsmasq.h has to be included first as it sources config.h
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-10-07 09:28:34 +01:00
Simon Kelley
c166c07a93 Support IDN in --auth-zone. 2021-10-06 23:48:06 +01:00
Petr Menšík
39a625ff72 Disable transitional IDN rules, accept only sane names
Transitional encoding accepts every emoticon you can think about.
Because setlocale were not enabled before, IDN 2003 input was not
accepted by dnsmasq. It makes no sense therefore to maintain backward
compatibility. Accept only proper encoded unicode names and reject
random unicode characters.

Signed-off-by: Petr Menšík <pemensik@redhat.com>
2021-10-06 23:33:13 +01:00
Petr Menšík
ad32ca18a7 Enable locale support for IDN at startup
--address=/münchen.de/ is not accepted unless LOCALEDIR is defined on
build. It is not by default. If LIBIDN1 or 2 is defined, call setlocale
to initialize locale required to translate domains to ascii form.

Signed-off-by: Petr Menšík <pemensik@redhat.com>
2021-10-06 23:23:51 +01:00
Simon Kelley
efea282396 Fix logic in add_update_server() to make optimisation actually optimise. 2021-10-06 23:01:14 +01:00
Simon Kelley
33d6a01cd3 Use host byte-order variable for answer counting. 2021-10-06 22:54:35 +01:00
Simon Kelley
d290630d31 Fix crash after re-reading an empty resolv.conf file.
If dnsmasq re-reads a resolv file, and it's empty, it will
retry after a delay. In the meantime, the old servers from the
resolv file have been deleted, but the servers_array doesn't
get updated, leading to dangling pointers and crashes.

Thanks to Brad Jorsch for finding and analysing this bug.

This problem was introduced in 2.86.
2021-10-06 22:31:06 +01:00
Simon Kelley
d2ad5dc073 Fix truncation logic in make_local_answer()
add_resource_record() returns 1 if the record was added.
Only increment anscount of so.

Thanks to Petr Menšík for spotting the problem.
2021-10-05 23:38:20 +01:00
Simon Kelley
68ab5127af Man page tweak for --address and more than one address. 2021-10-05 22:50:58 +01:00
DL6ER
089a11f340 --local should behave as --server, not as --address according to the man page
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-10-05 22:47:10 +01:00
Olaf Hering
de1d04eb66 remove stale contrib/Suse
dnsmasq is included in SUSE Linux since 2004.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
2021-09-30 12:17:44 +01:00
Dominik Derigs
ed4e7defd7 Do not fail hard when rev-server has a non-zero final address part
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-09-30 11:52:24 +01:00
Simon Kelley
267ab619c4 Get compilation flags for libnftables from pkg-config.
Omission spotted by Olaf Hering. Thanks.
2021-09-29 23:24:52 +01:00
Matt Whitlock
0140454ba2 dnsmasq_time: avoid signed integer overflow when HAVE_BROKEN_RTC
The dnsmasq_time() function, in the case of HAVE_BROKEN_RTC, was calling
times() to read the number of ticks "elapsed since an arbitrary point in
the past" and then dividing that by sysconf(_SC_CLK_TCK) to compute the
number of seconds elapsed since that arbitrary instant. This works fine
until the number of ticks exceeds 2^31, beyond which time the function
would begin erroneously returning negative times. On my system this
happens after approximately 248 days of uptime. A symptom is that
dnsmasq no longer populates the resolver cache with DHCP-derived names
at startup, as the inserted cache entries immediately expire due to
having negative expiration times that cause is_expired() to return true
when called with now==0.

This commit replaces the archaic implementation of dnsmasq_time() with a
call to the POSIX-standardized clock_gettime(CLOCK_MONOTONIC), thereby
eliminating the need to convert manually from ticks to seconds. The new
implementation will yield correct results until the system uptime
exceeds approximately 68 years.

Signed-off-by: Matt Whitlock <dnsmasq@mattwhitlock.name>
2021-09-29 09:46:13 +01:00
Simon Kelley
2c60441239 Fix FTBFS when CONNTRACK and UBUS but not DNSSEC compile options selected. 2021-09-28 23:42:15 +01:00
Simon Kelley
cbbd56c965 Build Debian binaries with NFTset support. 2021-09-27 23:16:18 +01:00
Simon Kelley
2561f9fe0e Fix confusion in DNS retries and --strict-order.
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.
2021-09-27 22:37:02 +01:00
Simon Kelley
47aefca5e4 Add --nftset option, like --ipset but for the newer nftables.
Thanks to Chen Zhenge for the original patch, which I've
reworked. Any bugs down to SRK.
2021-09-27 21:49:28 +01:00
Simon Kelley
981fb03710 Make --rebind-domain-ok work with IDN. 2021-09-24 15:25:05 +01:00
Paul Fertser
ef2f8d70d2 manpage: clarify tags: semantics for --dhcp-host
Mention that several tags can be specified and instruct the user that
some other match must still be provided for the directive to have any
effect.
2021-09-24 14:46:25 +01:00
Dominik Derigs
d9995a1add Improve last patch by splitting the previously combined if
Signed-off-by: DL6ER <dl6er@dl6er.de>

(also cosmetic change to logging for improved translation from
Matthias Andree <matthias.andree@gmx.de>)
2021-09-23 22:54:17 +01:00
Dominik Derigs
ea7a05ad43 Correcly warn if dynamic directory is actually no directory
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-09-23 11:02:11 +01:00
Simon Kelley
26bbf5a314 Fix --address=/#/...... which was lost in 2.86
A victim of the domain-search rewrite. Apologies.
2021-09-23 10:54:46 +01:00
Dominik DL6ER
c147329823 Check if allocation of 66573 bytes succeeded before accessing the memory to avoid crash in busy times
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-09-20 21:20:41 +01:00
hev
eb88eed1fc Optimize inserting records into server list.
Signed-off-by: hev <r@hev.cc>
2021-09-20 20:12:50 +01:00
Simon Kelley
8312a3ba4f Thinko in immediately previous commit. 2021-09-20 19:44:56 +01:00
Simon Kelley
35f93081dc Add support for arbitrary prefix lengths in --rev-server and --domain=....,local
Previously, the prefix was limited to [8,16,24,32] for IPv4 and
to multiples of 4 for IPv6. This patch also makes the prefix-length optional
for --rev-server.

Inspired by a patch from DL6ER <dl6er@dl6er.de>, but completely
re-written by srk. All bugs are his.
2021-09-20 00:05:42 +01:00
Simon Kelley
de372d6914 Fix confusion is server=/domain/# combined with server|address=/domain/....
The 2.86 domain matching rewrite failed to take into account the possibilty that

server=/example.com/#

could be combined with, for example

address=/example.com/1.2.3.4

resulting in the struct server datastructure for the former getting passed
to forward_query(), rapidly followed by a SEGV.

This fix makes server=/example.com/# a fully fledged member of the
priority list, which is now  IPv6 addr, IPv4 addr, all zero return,
resolvconf servers, upstream servers, no-data return

Thanks to dl6er@dl6er.de for finding and characterising the bug.
2021-09-18 23:01:12 +01:00
Petr Menšík
4ac517e4ac Fix coverity issues in dnssec.c
Error: CHECKED_RETURN (CWE-252): [#def26]
dnsmasq-2.86rc3/src/dnssec.c:727: check_return: Calling "extract_name" without checking return value (as is done elsewhere 9 out of 10 times).
dnsmasq-2.86rc3/src/dnssec.c:459: example_checked: Example 1: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)".
dnsmasq-2.86rc3/src/dnssec.c:269: example_checked: Example 2: "extract_name(header, plen, &state->ip, state->buff, 1, 0)" has its value checked in "extract_name(header, plen, &state->ip, state->buff, 1, 0)".
dnsmasq-2.86rc3/src/dnssec.c:569: example_checked: Example 3: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)".
dnsmasq-2.86rc3/src/rfc1035.c:648: example_checked: Example 4: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)".
dnsmasq-2.86rc3/src/rfc1035.c:787: example_checked: Example 5: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)".
 #  725|         /* namebuff used for workspace above, restore to leave unchanged on exit */
 #  726|         p = (unsigned char*)(rrset[0]);
 #  727|->       extract_name(header, plen, &p, name, 1, 0);
 #  728|
 #  729|         if (key)

Error: CHECKED_RETURN (CWE-252): [#def27]
dnsmasq-2.86rc3/src/dnssec.c:1020: check_return: Calling "extract_name" without checking return value (as is done elsewhere 7 out of 8 times).
dnsmasq-2.86rc3/src/auth.c:140: example_checked: Example 1: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/dnssec.c:771: example_checked: Example 2: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/hash-questions.c:57: example_checked: Example 3: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/rfc1035.c:1028: example_checked: Example 4: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/rfc1035.c:1438: example_checked: Example 5: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)".
 # 1018|
 # 1019|     p = (unsigned char *)(header+1);
 # 1020|->   extract_name(header, plen, &p, name, 1, 4);
 # 1021|     p += 4; /* qtype, qclass */
 # 1022|
2021-09-11 22:08:25 +01:00
Petr Menšík
e3651367b3 Fix coverity detected issues in dnsmasq.c
Error: DEADCODE (CWE-561): [#def12]
dnsmasq-2.86rc3/src/dnsmasq.c:37: assignment: Assigning: "bind_fallback" = "0".
dnsmasq-2.86rc3/src/dnsmasq.c:927: const: At condition "bind_fallback", the value of "bind_fallback" must be equal to 0.
dnsmasq-2.86rc3/src/dnsmasq.c:927: dead_error_condition: The condition "bind_fallback" cannot be true.
dnsmasq-2.86rc3/src/dnsmasq.c:928: dead_error_line: Execution cannot reach this statement: "my_syslog(4, "setting --bin...".
dnsmasq-2.86rc3/src/dnsmasq.c:928: effectively_constant: Local variable "bind_fallback" is assigned only once, to a constant value, making it effectively constant throughout its scope. If this is not the intent, examine the logic to see if there is a missing assignment that would make "bind_fallback" not remain constant.
 #  926|
 #  927|     if (bind_fallback)
 #  928|->     my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
 #  929|
 #  930|     if (option_bool(OPT_NOWILD))

Error: REVERSE_NEGATIVE (CWE-191): [#def13]
dnsmasq-2.86rc3/src/dnsmasq.c:383: negative_sink_in_call: Passing "dnsmasq_daemon->pxefd" to a parameter that cannot be negative.
dnsmasq-2.86rc3/src/dnsmasq.c:1086: check_after_sink: You might be using variable "dnsmasq_daemon->pxefd" before verifying that it is >= 0.
 # 1084|   	{
 # 1085|   	  poll_listen(daemon->dhcpfd, POLLIN);
 # 1086|-> 	  if (daemon->pxefd != -1)
 # 1087|   	    poll_listen(daemon->pxefd, POLLIN);
 # 1088|   	}

Error: CHECKED_RETURN (CWE-252): [#def18]
dnsmasq-2.86rc3/src/dnsmasq.c:1582: check_return: Calling "fcntl(dnsmasq_daemon->helperfd, 4, i & 0xfffffffffffff7ff)" without checking return value. This library function may fail and return an error code.
 # 1580|   	    /* block in writes until all done */
 # 1581|   	    if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
 # 1582|-> 	      fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
 # 1583|   	    do {
 # 1584|   	      helper_write();

Error: CHECKED_RETURN (CWE-252): [#def22]
dnsmasq-2.86rc3/src/dnsmasq.c:1991: check_return: Calling "fcntl(confd, 4, flags & 0xfffffffffffff7ff)" without checking return value. This library function may fail and return an error code.
 # 1989|   		 Reset that here. */
 # 1990|   	      if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
 # 1991|-> 		fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
 # 1992|
 # 1993|   	      buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);

Error: CHECKED_RETURN (CWE-252): [#def26]
dnsmasq-2.86rc3/src/dnssec.c:727: check_return: Calling "extract_name" without checking return value (as is done elsewhere 9 out of 10 times).
dnsmasq-2.86rc3/src/dnssec.c:459: example_checked: Example 1: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)".
dnsmasq-2.86rc3/src/dnssec.c:269: example_checked: Example 2: "extract_name(header, plen, &state->ip, state->buff, 1, 0)" has its value checked in "extract_name(header, plen, &state->ip, state->buff, 1, 0)".
dnsmasq-2.86rc3/src/dnssec.c:569: example_checked: Example 3: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)".
dnsmasq-2.86rc3/src/rfc1035.c:648: example_checked: Example 4: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)".
dnsmasq-2.86rc3/src/rfc1035.c:787: example_checked: Example 5: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)".
 #  725|         /* namebuff used for workspace above, restore to leave unchanged on exit */
 #  726|         p = (unsigned char*)(rrset[0]);
 #  727|->       extract_name(header, plen, &p, name, 1, 0);
 #  728|
 #  729|         if (key)

Error: CHECKED_RETURN (CWE-252): [#def27]
dnsmasq-2.86rc3/src/dnssec.c:1020: check_return: Calling "extract_name" without checking return value (as is done elsewhere 7 out of 8 times).
dnsmasq-2.86rc3/src/auth.c:140: example_checked: Example 1: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/dnssec.c:771: example_checked: Example 2: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/hash-questions.c:57: example_checked: Example 3: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/rfc1035.c:1028: example_checked: Example 4: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)".
dnsmasq-2.86rc3/src/rfc1035.c:1438: example_checked: Example 5: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)".
 # 1018|
 # 1019|     p = (unsigned char *)(header+1);
 # 1020|->   extract_name(header, plen, &p, name, 1, 4);
 # 1021|     p += 4; /* qtype, qclass */
 # 1022|
2021-09-11 22:08:14 +01:00
Petr Menšík
02ea41ddd1 Fix coverity issues detected in domain-match.c
Error: CHECKED_RETURN (CWE-252): [#def28]
dnsmasq-2.86rc3/src/domain-match.c:414: check_return: Calling "add_resource_record" without checking return value (as is done elsewhere 44 out of 46 times).
dnsmasq-2.86rc3/src/auth.c:214: example_checked: Example 1: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)".
dnsmasq-2.86rc3/src/auth.c:239: example_checked: Example 2: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)".
dnsmasq-2.86rc3/src/rfc1035.c:1463: example_checked: Example 3: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)".
dnsmasq-2.86rc3/src/rfc1035.c:1500: example_checked: Example 4: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)".
dnsmasq-2.86rc3/src/rfc1035.c:2021: example_checked: Example 5: "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)" has its value checked in "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)".
 #  412|
 #  413|   	header->ancount = htons(ntohs(header->ancount) + 1);
 #  414|-> 	add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr);
 #  415|   	log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL);
 #  416|         }

Error: CHECKED_RETURN (CWE-252): [#def29]
dnsmasq-2.86rc3/src/domain-match.c:429: check_return: Calling "add_resource_record" without checking return value (as is done elsewhere 44 out of 46 times).
dnsmasq-2.86rc3/src/auth.c:214: example_checked: Example 1: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)".
dnsmasq-2.86rc3/src/auth.c:239: example_checked: Example 2: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)".
dnsmasq-2.86rc3/src/rfc1035.c:1463: example_checked: Example 3: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)".
dnsmasq-2.86rc3/src/rfc1035.c:1500: example_checked: Example 4: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)".
dnsmasq-2.86rc3/src/rfc1035.c:2021: example_checked: Example 5: "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)" has its value checked in "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)".
 #  427|
 #  428|   	header->ancount = htons(ntohs(header->ancount) + 1);
 #  429|-> 	add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr);
 #  430|   	log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL);
 #  431|         }

Error: NULL_RETURNS (CWE-476): [#def30]
dnsmasq-2.86rc3/src/domain-match.c:611: returned_null: "whine_malloc" returns "NULL" (checked 72 out of 76 times).
dnsmasq-2.86rc3/src/domain-match.c:611: var_assigned: Assigning: "alloc_domain" = "NULL" return value from "whine_malloc".
dnsmasq-2.86rc3/src/domain-match.c:620: dereference: Dereferencing a pointer that might be "NULL" "alloc_domain" when calling "hostname_isequal".
dnsmasq-2.86rc3/src/arp.c:88: example_checked: Example 1: "whine_malloc(48UL)" has its value checked in "arp = whine_malloc(48UL)".
dnsmasq-2.86rc3/src/blockdata.c:24: example_assign: Example 2: Assigning: "new" = return value from "whine_malloc(n * 48UL)".
dnsmasq-2.86rc3/src/blockdata.c:26: example_checked: Example 2 (cont.): "new" has its value checked in "new".
dnsmasq-2.86rc3/src/cache.c:1545: example_assign: Example 3: Assigning: "crecp" = return value from "whine_malloc(70UL)".
dnsmasq-2.86rc3/src/cache.c:1547: example_checked: Example 3 (cont.): "crecp" has its value checked in "crecp".
dnsmasq-2.86rc3/src/forward.c:1791: example_assign: Example 4: Assigning: "packet" = return value from "whine_malloc(66573UL)".
dnsmasq-2.86rc3/src/forward.c:1795: example_checked: Example 4 (cont.): "packet" has its value checked in "packet".
dnsmasq-2.86rc3/src/inotify.c:186: example_checked: Example 5: "whine_malloc(lendir + lenfile + 2UL)" has its value checked in "path = whine_malloc(lendir + lenfile + 2UL)".
 #  618|     if (flags & SERV_IS_LOCAL)
 #  619|       for (serv = daemon->servers; serv; serv = serv->next)
 #  620|->       if ((serv->flags & SERV_MARK) &&
 #  621|   	  hostname_isequal(alloc_domain, serv->domain))
 #  622|   	break;

Error: RESOURCE_LEAK (CWE-772): [#def31] [important]
dnsmasq-2.86rc3/src/domain-match.c:611: alloc_fn: Storage is returned from allocation function "whine_malloc".
dnsmasq-2.86rc3/src/domain-match.c:611: var_assign: Assigning: "alloc_domain" = storage returned from "whine_malloc(1UL)".
dnsmasq-2.86rc3/src/domain-match.c:620: noescape: Resource "alloc_domain" is not freed or pointed-to in "hostname_isequal".
dnsmasq-2.86rc3/src/domain-match.c:646: leaked_storage: Variable "alloc_domain" going out of scope leaks the storage it points to.
 #  644|
 #  645|         if (!(serv = whine_malloc(size)))
 #  646|-> 	return 0;
 #  647|
 #  648|         if (flags & SERV_IS_LOCAL)

Error: NULL_RETURNS (CWE-476): [#def32]
dnsmasq-2.86rc3/src/domain-match.c:611: returned_null: "whine_malloc" returns "NULL" (checked 72 out of 76 times).
dnsmasq-2.86rc3/src/domain-match.c:611: var_assigned: Assigning: "alloc_domain" = "NULL" return value from "whine_malloc".
dnsmasq-2.86rc3/src/domain-match.c:674: dereference: Dereferencing a pointer that might be "NULL" "alloc_domain" when calling "strlen".
dnsmasq-2.86rc3/src/arp.c:88: example_checked: Example 1: "whine_malloc(48UL)" has its value checked in "arp = whine_malloc(48UL)".
dnsmasq-2.86rc3/src/blockdata.c:24: example_assign: Example 2: Assigning: "new" = return value from "whine_malloc(n * 48UL)".
dnsmasq-2.86rc3/src/blockdata.c:26: example_checked: Example 2 (cont.): "new" has its value checked in "new".
dnsmasq-2.86rc3/src/cache.c:1545: example_assign: Example 3: Assigning: "crecp" = return value from "whine_malloc(70UL)".
dnsmasq-2.86rc3/src/cache.c:1547: example_checked: Example 3 (cont.): "crecp" has its value checked in "crecp".
dnsmasq-2.86rc3/src/forward.c:1791: example_assign: Example 4: Assigning: "packet" = return value from "whine_malloc(66573UL)".
dnsmasq-2.86rc3/src/forward.c:1795: example_checked: Example 4 (cont.): "packet" has its value checked in "packet".
dnsmasq-2.86rc3/src/inotify.c:186: example_checked: Example 5: "whine_malloc(lendir + lenfile + 2UL)" has its value checked in "path = whine_malloc(lendir + lenfile + 2UL)".
 #  672|     serv->flags = flags;
 #  673|     serv->domain = alloc_domain;
 #  674|->   serv->domain_len = strlen(alloc_domain);
 #  675|
 #  676|     if (flags & SERV_4ADDR)
2021-09-11 22:04:05 +01:00
Simon Kelley
51ffae4eab Fix coverity detected issues in cache.c
Error: UNINIT (CWE-457): [#def27]
dnsmasq-2.86test7/src/cache.c:1193: var_decl: Declaring variable "lrec" without initializer.
dnsmasq-2.86test7/src/cache.c:1315: uninit_use_in_call: Using uninitialized value "lrec.ttd" when calling "make_non_terminals".
 # 1313|       {
 # 1314|         lrec.name.namep = txt->name;
 # 1315|->       make_non_terminals(&lrec);
 # 1316|       }
 # 1317|

Error: CLANG_WARNING: [#def29]
dnsmasq-2.86test7/src/cache.c:1552:15: warning[core.uninitialized.Assign]: Assigned value is garbage or undefined
 # 1550|   	{
 # 1551|   	  crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_REVERSE);
 # 1552|-> 	  crecp->ttd = source->ttd;
 # 1553|   	  crecp->name.namep = name;
 # 1554|
2021-09-11 21:57:30 +01:00
Petr Menšík
afe84f37f8 Fix coverity detected issue in radv.c
Error: NULL_RETURNS (CWE-476): [#def114]
dnsmasq-2.86test7/src/radv.c:748: returned_null: "expand" returns "NULL" (checked 10 out of 11 times).
dnsmasq-2.86test7/src/radv.c:748: var_assigned: Assigning: "p" = "NULL" return value from "expand".
dnsmasq-2.86test7/src/radv.c:749: dereference: Dereferencing a pointer that might be "NULL" "p" when calling "memset". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/outpacket.c:83: example_checked: Example 1: "expand(len)" has its value checked in "p = expand(len)".
dnsmasq-2.86test7/src/outpacket.c:109: example_checked: Example 2: "expand(1UL)" has its value checked in "p = expand(1UL)".
dnsmasq-2.86test7/src/radv.c:269: example_checked: Example 3: "expand(16UL)" has its value checked in "ra = expand(16UL)".
dnsmasq-2.86test7/src/radv.c:363: example_checked: Example 4: "expand(32UL)" has its value checked in "opt = expand(32UL)".
dnsmasq-2.86test7/src/radv.c:708: example_checked: Example 5: "expand(32UL)" has its value checked in "opt = expand(32UL)".
 #  747|         int len = (maclen + 9) >> 3;
 #  748|         unsigned char *p = expand(len << 3);
 #  749|->       memset(p, 0, len << 3);
 #  750|         *p++ = ICMP6_OPT_SOURCE_MAC;
 #  751|         *p++ = len;

Error: NULL_RETURNS (CWE-476): [#def115]
dnsmasq-2.86test7/src/radv.c:748: returned_null: "expand" returns "NULL" (checked 10 out of 11 times).
dnsmasq-2.86test7/src/radv.c:748: var_assigned: Assigning: "p" = "NULL" return value from "expand".
dnsmasq-2.86test7/src/radv.c:750: dereference: Incrementing a pointer which might be null: "p".
dnsmasq-2.86test7/src/outpacket.c:83: example_checked: Example 1: "expand(len)" has its value checked in "p = expand(len)".
dnsmasq-2.86test7/src/outpacket.c:109: example_checked: Example 2: "expand(1UL)" has its value checked in "p = expand(1UL)".
dnsmasq-2.86test7/src/radv.c:269: example_checked: Example 3: "expand(16UL)" has its value checked in "ra = expand(16UL)".
dnsmasq-2.86test7/src/radv.c:363: example_checked: Example 4: "expand(32UL)" has its value checked in "opt = expand(32UL)".
dnsmasq-2.86test7/src/radv.c:708: example_checked: Example 5: "expand(32UL)" has its value checked in "opt = expand(32UL)".
 #  748|         unsigned char *p = expand(len << 3);
 #  749|         memset(p, 0, len << 3);
 #  750|->       *p++ = ICMP6_OPT_SOURCE_MAC;
 #  751|         *p++ = len;
 #  752|         memcpy(p, mac, maclen);
2021-09-11 21:51:10 +01:00
Petr Menšík
0afeef0e00 Fix coverity detected issues in option.c
Error: STRING_OVERFLOW (CWE-120): [#def99]
dnsmasq-2.86test7/src/option.c:801: fixed_size_dest: You might overrun the 100-character fixed-size string "buff" by copying "usage[i].arg" without checking the length.
#  799|         if (usage[i].arg)
#  800|   	{
#  801|-> 	  strcpy(buff, usage[i].arg);
#  802|   	  for (j = 0; tab[j].handle; j++)
#  803|   	    if (tab[j].handle == *(usage[i].arg))

Error: CLANG_WARNING: [#def100]
dnsmasq-2.86test7/src/option.c:962:3: warning[deadcode.DeadStores]: Value stored to 'domain' is never read
#  960|       }
#  961|
#  962|->   domain += sprintf(domain, "in-addr.arpa");
#  963|
#  964|     return 1;

Error: CLANG_WARNING: [#def101]
dnsmasq-2.86test7/src/option.c:981:3: warning[deadcode.DeadStores]: Value stored to 'domain' is never read
#  979|         domain += sprintf(domain, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
#  980|       }
#  981|->   domain += sprintf(domain, "ip6.arpa");
#  982|
#  983|     return 1;

Error: RESOURCE_LEAK (CWE-772): [#def102] [important]
dnsmasq-2.86test7/src/option.c:1809: alloc_fn: Storage is returned from allocation function "opt_malloc".
dnsmasq-2.86test7/src/option.c:1809: var_assign: Assigning: "path" = storage returned from "opt_malloc(strlen(directory) + len + 2UL)".
dnsmasq-2.86test7/src/option.c:1810: noescape: Resource "path" is not freed or pointed-to in "strcpy". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/option.c:1811: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/option.c:1812: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/option.c:1815: noescape: Resource "path" is not freed or pointed-to in "stat".
dnsmasq-2.86test7/src/option.c:1809: overwrite_var: Overwriting "path" in "path = opt_malloc(strlen(directory) + len + 2UL)" leaks the storage that "path" points to.
# 1807|   	      continue;
# 1808|
# 1809|-> 	    path = opt_malloc(strlen(directory) + len + 2);
# 1810|   	    strcpy(path, directory);
# 1811|   	    strcat(path, "/");

Error: RESOURCE_LEAK (CWE-772): [#def103] [important]
dnsmasq-2.86test7/src/option.c:1809: alloc_fn: Storage is returned from allocation function "opt_malloc".
dnsmasq-2.86test7/src/option.c:1809: var_assign: Assigning: "path" = storage returned from "opt_malloc(strlen(directory) + len + 2UL)".
dnsmasq-2.86test7/src/option.c:1810: noescape: Resource "path" is not freed or pointed-to in "strcpy". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/option.c:1811: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/option.c:1812: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.]
dnsmasq-2.86test7/src/option.c:1815: noescape: Resource "path" is not freed or pointed-to in "stat".
dnsmasq-2.86test7/src/option.c:1858: leaked_storage: Variable "path" going out of scope leaks the storage it points to.
# 1856|   	    free(files);
# 1857|   	  }
# 1858|-> 	break;
# 1859|         }
# 1860|

Error: RESOURCE_LEAK (CWE-772): [#def104] [important]
dnsmasq-2.86test7/src/option.c:1996: alloc_fn: Storage is returned from allocation function "canonicalise_opt".
dnsmasq-2.86test7/src/option.c:1996: var_assign: Assigning: "name" = storage returned from "canonicalise_opt(arg)".
dnsmasq-2.86test7/src/option.c:1998: leaked_storage: Variable "name" going out of scope leaks the storage it points to.
# 1996|   	if (!(name = canonicalise_opt(arg)) ||
# 1997|   	    (comma && !(target = canonicalise_opt(comma))))
# 1998|-> 	  ret_err(_("bad MX name"));
# 1999|
# 2000|   	new = opt_malloc(sizeof(struct mx_srv_record));

Error: RESOURCE_LEAK (CWE-772): [#def106] [important]
dnsmasq-2.86test7/src/option.c:3477: alloc_fn: Storage is returned from allocation function "opt_malloc".
dnsmasq-2.86test7/src/option.c:3477: var_assign: Assigning: "new" = storage returned from "opt_malloc(96UL)".
dnsmasq-2.86test7/src/option.c:3618: leaked_storage: Variable "new" going out of scope leaks the storage it points to.
# 3616|   		      sprintf(errstr, _("duplicate dhcp-host IP address %s"),
# 3617|   			      daemon->addrbuff);
# 3618|-> 		      return 0;
# 3619|   		    }
# 3620|   	      }

Error: RESOURCE_LEAK (CWE-772): [#def108] [important]
dnsmasq-2.86test7/src/option.c:3781: alloc_fn: Storage is returned from allocation function "opt_malloc".
dnsmasq-2.86test7/src/option.c:3781: var_assign: Assigning: "new" = storage returned from "opt_malloc(32UL)".
dnsmasq-2.86test7/src/option.c:3786: leaked_storage: Variable "new" going out of scope leaks the storage it points to.
# 3784|
# 3785|   	if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
# 3786|-> 	  ret_err(gen_err);
# 3787|
# 3788|   	new->wildcard = 0;

Error: RESOURCE_LEAK (CWE-772): [#def109] [important]
dnsmasq-2.86test7/src/option.c:3921: alloc_fn: Storage is returned from allocation function "opt_malloc".
dnsmasq-2.86test7/src/option.c:3921: var_assign: Assigning: "new" = storage returned from "opt_malloc(56UL)".
dnsmasq-2.86test7/src/option.c:3994: leaked_storage: Variable "new" going out of scope leaks the storage it points to.
# 3992|   	   }
# 3993|
# 3994|-> 	 ret_err(gen_err);
# 3995|          }
# 3996|

Error: CLANG_WARNING: [#def111]
dnsmasq-2.86test7/src/option.c:4693:25: warning[deadcode.DeadStores]: Value stored to 'tmp' during its initialization is never read
# 4691|   		if (!canon)
# 4692|                     {
# 4693|-> 		    struct name_list *tmp = new->names, *next;
# 4694|   		    for (tmp = new->names; tmp; tmp = next)
# 4695|
2021-09-11 21:50:33 +01:00
Petr Menšík
94a17fd97f Address coverity issues detected in util.c 2021-09-11 21:49:28 +01:00
Petr Menšík
5b5ec55445 Fix coverity warnings on dbus
Error: CLANG_WARNING: [#def30]
dnsmasq-2.86test7/src/dbus.c:117:3: warning[deadcode.DeadStores]: Value stored to 'w' is never read
 #  115|     daemon->watches = w;
 #  116|
 #  117|->   w = data; /* no warning */
 #  118|     return TRUE;
 #  119|   }

Error: CLANG_WARNING: [#def31]
dnsmasq-2.86test7/src/dbus.c:137:3: warning[deadcode.DeadStores]: Value stored to 'w' is never read
 #  135|       }
 #  136|
 #  137|->   w = data; /* no warning */
 #  138|   }
 #  139|

Error: CHECKED_RETURN (CWE-252): [#def32]
dnsmasq-2.86test7/src/dbus.c:146: check_return: Calling "dbus_message_iter_init" without checking return value (as is done elsewhere 4 out of 5 times).
dnsmasq-2.86test7/src/dbus.c:460: example_checked: Example 1: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)".
dnsmasq-2.86test7/src/dbus.c:573: example_checked: Example 2: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)".
dnsmasq-2.86test7/src/dbus.c:257: example_checked: Example 3: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)".
dnsmasq-2.86test7/src/dbus.c:427: example_checked: Example 4: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)".
 #  144|     char *domain;
 #  145|
 #  146|->   dbus_message_iter_init(message, &iter);
 #  147|
 #  148|     mark_servers(SERV_FROM_DBUS);

Error: NEGATIVE_RETURNS (CWE-394): [#def33]
dnsmasq-2.86test7/src/dbus.c:547: negative_return_fn: Function "parse_hex((char *)hwaddr, dhcp_chaddr, 16, NULL, &hw_type)" returns a negative number.
dnsmasq-2.86test7/src/dbus.c:547: assign: Assigning: "hw_len" = "parse_hex((char *)hwaddr, dhcp_chaddr, 16, NULL, &hw_type)".
dnsmasq-2.86test7/src/dbus.c:551: negative_returns: "hw_len" is passed to a parameter that cannot be negative.
 #  549|       hw_type = ARPHRD_ETHER;
 #  550|
 #  551|->   lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
 #  552|                      clid_len, now, 0);
 #  553|     lease_set_expires(lease, expires, now);

Error: CLANG_WARNING: [#def34]
dnsmasq-2.86test7/src/dbus.c:722:3: warning[deadcode.DeadStores]: Value stored to 'method' is never read
 #  720|       clear_cache_and_reload(dnsmasq_time());
 #  721|
 #  722|->   method = user_data; /* no warning */
 #  723|
 #  724|     /* If no reply or no error, return nothing */
2021-09-11 21:37:18 +01:00
Petr Menšík
1e6565c1a5 Retry dhcp6 ping on interrupts
Error: CHECKED_RETURN (CWE-252): [#def35]
dnsmasq-2.86test7/src/dhcp6.c:295: check_return: Calling "sendto(dnsmasq_daemon->icmp6fd, &neigh, 24UL, 0, __CONST_SOCKADDR_ARG({.__sockaddr__ = &addr.sa}), 28U)" without checking return value. This library function may fail and return an error code.
 #  293|   	break;
 #  294|
 #  295|->       sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
 #  296|
 #  297|         ts.tv_sec = 0;
2021-09-11 21:36:30 +01:00
Petr Menšík
fc522515b9 Fix coverity formats issues in blockdata
Error: PRINTF_ARGS (CWE-686): [#def16]
dnsmasq-2.86test7/src/blockdata.c:56: invalid_type: Argument "blockdata_count * 48UL" to format specifier "%u" was expected to have type "unsigned int" but has type "unsigned long".
 #   54|   {
 #   55|     my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
 #   56|-> 	    blockdata_count * sizeof(struct blockdata),
 #   57|   	    blockdata_hwm * sizeof(struct blockdata),
 #   58|   	    blockdata_alloced * sizeof(struct blockdata));

Error: PRINTF_ARGS (CWE-686): [#def17]
dnsmasq-2.86test7/src/blockdata.c:57: invalid_type: Argument "blockdata_hwm * 48UL" to format specifier "%u" was expected to have type "unsigned int" but has type "unsigned long".
 #   55|     my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
 #   56|   	    blockdata_count * sizeof(struct blockdata),
 #   57|-> 	    blockdata_hwm * sizeof(struct blockdata),
 #   58|   	    blockdata_alloced * sizeof(struct blockdata));
 #   59|   }

Error: PRINTF_ARGS (CWE-686): [#def18]
dnsmasq-2.86test7/src/blockdata.c:58: invalid_type: Argument "blockdata_alloced * 48UL" to format specifier "%u" was expected to have type "unsigned int" but has type "unsigned long".
 #   56|   	    blockdata_count * sizeof(struct blockdata),
 #   57|   	    blockdata_hwm * sizeof(struct blockdata),
 #   58|-> 	    blockdata_alloced * sizeof(struct blockdata));
 #   59|   }
 #   60|
2021-09-11 21:36:01 +01:00
Petr Menšík
9881b0736d Fix few coverity warnings in lease-tools
Error: UNINIT (CWE-457): [#def2]
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release.c:265: var_decl: Declaring variable "ifr" without initializer.
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release.c:285: uninit_use_in_call: Using uninitialized value "ifr". Field "ifr.ifr_ifru" is uninitialized when calling "setsockopt".
 #  283|     strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
 #  284|     ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
 #  285|->   if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
 #  286|       {
 #  287|         perror("cannot setup interface");

Error: CHECKED_RETURN (CWE-252): [#def3]
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:346: check_return: Calling "inet_pton" without checking return value (as is done elsewhere 61 out of 72 times).
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:188: example_assign: Example 1: Assigning: "s" = return value from "inet_pton(10, ip, &result.ip)".
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:189: example_checked: Example 1 (cont.): "s" has its value checked in "s <= 0".
dnsmasq-2.86test7/src/cache.c:1108: example_checked: Example 2: "inet_pton(10, token, &addr)" has its value checked in "inet_pton(10, token, &addr) > 0".
dnsmasq-2.86test7/src/dbus.c:525: example_checked: Example 3: "inet_pton(2, ipaddr, &addr.addr4)" has its value checked in "inet_pton(2, ipaddr, &addr.addr4)".
dnsmasq-2.86test7/src/domain.c:138: example_checked: Example 4: "inet_pton(prot, tail, addr)" has its value checked in "inet_pton(prot, tail, addr)".
dnsmasq-2.86test7/src/lease.c:81: example_checked: Example 5: "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)" has its value checked in "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)".
 #  344|       client_addr.sin6_flowinfo = 0;
 #  345|       client_addr.sin6_scope_id =0;
 #  346|->     inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
 #  347|       bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
 #  348|       inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);

Error: CHECKED_RETURN (CWE-252): [#def4]
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:347: check_return: Calling "bind(sock, (struct sockaddr *)&client_addr, 28U)" without checking return value. This library function may fail and return an error code.
 #  345|       client_addr.sin6_scope_id =0;
 #  346|       inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
 #  347|->     bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
 #  348|       inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
 #  349|       server_addr.sin6_port = htons(DHCP6_SERVER_PORT);

Error: CHECKED_RETURN (CWE-252): [#def5]
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:348: check_return: Calling "inet_pton" without checking return value (as is done elsewhere 61 out of 72 times).
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:188: example_assign: Example 1: Assigning: "s" = return value from "inet_pton(10, ip, &result.ip)".
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:189: example_checked: Example 1 (cont.): "s" has its value checked in "s <= 0".
dnsmasq-2.86test7/src/cache.c:1108: example_checked: Example 2: "inet_pton(10, token, &addr)" has its value checked in "inet_pton(10, token, &addr) > 0".
dnsmasq-2.86test7/src/dbus.c:525: example_checked: Example 3: "inet_pton(2, ipaddr, &addr.addr4)" has its value checked in "inet_pton(2, ipaddr, &addr.addr4)".
dnsmasq-2.86test7/src/domain.c:138: example_checked: Example 4: "inet_pton(prot, tail, addr)" has its value checked in "inet_pton(prot, tail, addr)".
dnsmasq-2.86test7/src/lease.c:81: example_checked: Example 5: "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)" has its value checked in "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)".
 #  346|       inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
 #  347|       bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
 #  348|->     inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
 #  349|       server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
 #  350|       int16_t recv_size = 0;

Error: NEGATIVE_RETURNS (CWE-394): [#def6]
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:360: var_tested_neg: Variable "recv_size" tests negative.
dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:373: negative_returns: "recv_size" is passed to a parameter that cannot be negative.
 #  371|   	  }
 #  372|
 #  373|->         int16_t result = parse_packet(response, recv_size);
 #  374|           if (result == NOT_REPLY_CODE)
 #  375|   	  {
2021-09-11 18:01:49 +01:00
Petr Menšík
e52b4b1466 Fix bunch of warnings in auth.c
Error: CLANG_WARNING: [#def7]
dnsmasq-2.86test7/src/auth.c:420:5: warning[deadcode.DeadStores]: Value stored to 'found' is never read
 #  418|          if (!found && is_name_synthetic(flag, name, &addr) )
 #  419|   	 {
 #  420|-> 	   found = 1;
 #  421|   	   nxdomain = 0;
 #  422|

Error: CLANG_WARNING: [#def8]
dnsmasq-2.86test7/src/auth.c:436:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read
 #  434|   	    {
 #  435|   	      auth = soa = 1; /* inhibits auth section */
 #  436|-> 	      found = 1;
 #  437|   	      log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
 #  438|   	    }

Error: CLANG_WARNING: [#def9]
dnsmasq-2.86test7/src/auth.c:472:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read
 #  470|   	      ns = 1; /* ensure we include NS records! */
 #  471|   	      axfr = 1;
 #  472|-> 	      found = 1;
 #  473|   	      axfroffset = nameoffset;
 #  474|   	      log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");

Error: CLANG_WARNING: [#def10]
dnsmasq-2.86test7/src/auth.c:480:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read
 #  478|   	      auth = 1;
 #  479|   	      ns = 1; /* inhibits auth section */
 #  480|-> 	      found = 1;
 #  481|   	      log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
 #  482|   	    }

Error: CLANG_WARNING: [#def11]
dnsmasq-2.86test7/src/auth.c:501:4: warning[deadcode.DeadStores]: Value stored to 'found' is never read
 #  499|   			log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid));
 #  500|   			*cut  = 0; /* remove domain part */
 #  501|-> 			found = 1;
 #  502|   			if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
 #  503|   						daemon->auth_ttl, NULL, qtype, C_IN,

Error: CLANG_WARNING: [#def12]
dnsmasq-2.86test7/src/auth.c:522:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read
 #  520|   		   {
 #  521|   		     log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid));
 #  522|-> 		     found = 1;
 #  523|   		     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
 #  524|   					     daemon->auth_ttl, NULL, qtype, C_IN,

Error: CLANG_WARNING: [#def13]
dnsmasq-2.86test7/src/auth.c:617:8: warning[deadcode.DeadStores]: Value stored to 'p' is never read
 #  615|   		p += sprintf(p, "%u.", a & 0xff);
 #  616|   	      a = a >> 8;
 #  617|-> 	      p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
 #  618|
 #  619|   	    }

Error: CPPCHECK_WARNING (CWE-758): [#def14]
dnsmasq-2.86test7/src/auth.c:627: warning[objectIndex]: The address of local variable 'addr6' might be accessed at non-zero index.
 #  625|   	      for (i = subnet->prefixlen-1; i >= 0; i -= 4)
 #  626|   		{
 #  627|-> 		  int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
 #  628|   		  p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
 #  629|   		}

Error: CLANG_WARNING: [#def15]
dnsmasq-2.86test7/src/auth.c:630:8: warning[deadcode.DeadStores]: Value stored to 'p' is never read
 #  628|   		  p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
 #  629|   		}
 #  630|-> 	      p += sprintf(p, "ip6.arpa");
 #  631|
 #  632|   	    }
2021-09-11 17:56:01 +01:00
Petr Menšík
2f45670951 Add safety checks to places pointed by Coverity
GCC Analyzer (experimental)

1. dnsmasq-2.85/src/forward.c:0: scope_hint: In function 'allocate_rfd.part.0'
2. dnsmasq-2.85/src/forward.c:2321:18: warning[-Wanalyzer-null-dereference]: dereference of NULL 'rfd'
 #  2319|     *fdlp = rfl;
 #  2320|
 #  2321|->   return rfl->rfd->fd;
 #  2322|   }
 #  2323|

1. dnsmasq-2.85/src/cache.c:0: scope_hint: In function 'log_query'
2. dnsmasq-2.85/src/cache.c:1969:20: warning[-Wanalyzer-null-dereference]: dereference of NULL 'name'
 #  1967|       source = "cached";
 #  1968|
 #  1969|->   if (strlen(name) == 0)
 #  1970|       name = ".";
 #  1971|

1. dnsmasq-2.85/src/cache.c:0: scope_hint: In function 'cache_scan_free'
2. dnsmasq-2.85/src/cache.c:436:20: warning[-Wanalyzer-null-argument]: use of NULL 'addr' where non-null expected
40. /usr/include/sys/un.h:37: included_from: Included from here.
41. dnsmasq-2.85/src/dnsmasq.h:101: included_from: Included from here.
42. dnsmasq-2.85/src/cache.c:17: included_from: Included from here.
43. /usr/include/string.h:64:12: note: argument 2 of 'memcmp' must be non-null
 #   434|   		   (flags & crecp->flags & F_REVERSE) &&
 #   435|   		   (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
 #   436|-> 		   memcmp(&crecp->addr, addr, addrlen) == 0)
 #   437|   	    {
 #   438|   	      *up = crecp->hash_next;
2021-09-11 14:48:17 +01:00
Petr Menšík
50d75ae514 Retry on interrupted error in tftp
Interrupt might arrive when sending error reply. Retry if possible.

Wrong Check of Return Value

10. dnsmasq-2.85/src/tftp.c:603: check_return: Calling "sendto(transfer->sockfd, dnsmasq_daemon->packet, len, 0, __CONST_SOCKADDR_ARG({.__sockaddr__ = &peer.sa}), sa_len(&peer))" without checking return value. This library function may fail and return an error code.
 #   601|   		  prettyprint_addr(&peer, daemon->addrbuff);
 #   602|   		  len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff);
 #   603|-> 		  sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer));
 #   604|   		}
 #   605|   	    }
2021-09-11 14:39:36 +01:00
Petr Menšík
dea69a12aa Small sanity check in wildcard tag matching code. 2021-09-11 14:26:03 +01:00
Dominik DL6ER
e0ce3c12f2 Add all current RR types to the table of type names used for query logging.
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.
2021-09-10 23:13:53 +01:00
Gustaf Ullberg
93cf516bf1 check_name() determines if IDN processing is needed.
Optimization that only runs IDN processing if it would alter the domain
name (non-ascii or uppercase characters).

This patch has conributions from Petr Menšík.
2021-09-10 00:13:39 +01:00
Simon Kelley
6f4de018af Revert "Skip ascii-only names IDN processing"
This reverts commit 9cb7f8a655.
2021-09-10 00:02:11 +01:00
Simon Kelley
6e91cf3172 Bump version in Debian changelog. 2021-09-08 23:19:08 +01:00
Petr Menšík
9cb7f8a655 Skip ascii-only names IDN processing
Calls to libidn on names without with only a-z A-Z - _ 0-9
have no effect, but are slow. This change elides those calls.

Patch inspire by analysis and an earlier patch from
Gustaf Ullberg <gustaf.ullberg@gmail.com>
2021-09-08 23:08:21 +01:00
Simon Kelley
5d8d1ad14b Merge branch 'nxdomain' 2021-09-08 23:05:35 +01:00
Simon Kelley
cac9ca38f6 Treat ANY queries the same as CNAME queries WRT to DNSSEC on CNAME targets. 2021-09-08 21:21:22 +01:00
Simon Kelley
c4523639d5 Treat ANY queries the same as CNAME queries WRT to DNSSEC on CNAME targets. 2021-09-08 21:19:15 +01:00
Simon Kelley
1ce1c6beae Caching cleanup. Use cached NXDOMAIN to answer queries of any type. 2021-09-05 18:47:45 +01:00
DL6ER
51d56df7a3 Add RFC 4833 DHCP options "posix-timezone" and "tzdb-timezone".
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-09-04 22:24:14 +01:00
Simon Kelley
860a9a57d6 Get logging of DNSSEC status right when Checking Disabled bit set. 2021-09-02 10:07:08 +01:00
Dominik DL6ER
c83e33d608 Final logging tweaks. 2021-09-01 21:19:47 +01:00
Simon Kelley
7b80c75d9d Rationalise query-reply logging.
Try and log exactly what was returned, rather than just what
got cached. Also give validation status of RRsets if extra logging specified.

This commit also fixes a long-standing bug in caching of CNAME chains
leading to a PTR record.

Based on and inspired by a patch from Dominik DL6ER <dl6er@dl6er.de>
2021-08-31 18:23:03 +01:00
Geoff Back
79337f99ae Support limited wildcards in the input tags for --tag-if. 2021-08-29 13:27:27 +01:00
Geert Stappers via Dnsmasq-discuss
a42ee397f3 Man page BNF error fix.
Move dhcp-range bracket indicating option.

There should already be an end-address or mode  when adding a netmask.

Also the date bumped.

Signed-off-by: Geert Stappers <stappers@stappers.nl>
2021-08-25 14:32:43 +01:00
Simon Kelley
e58f8bb8c1 Merge message changes into I18N files. 2021-08-25 14:11:42 +01:00
Dominik DL6ER
58cf958e41 Fix empty domain in server option parsing when more than one domain is given
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-08-25 14:09:40 +01:00
Etan Kissling
06d01f7ae4 Make comment style consistent.
Majority of code base does not use C90-style // end of line comments.
This formats the few existing exceptions using /* */ for consistency.
2021-08-12 17:02:45 +01:00
Etan Kissling
1a33eec0ba Adjust logging levels for connmark patterns.
This brings the log levels emitted by connmark pattern code in line with
the rest of the code base. LOG_DEBUG is used for diagnostics that may be
verbose depending on the request patterns. LOG_ERR is used for problems
with the implementation itself.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:02:24 +01:00
Etan Kissling
82de7a1e96 Re-order UBus teardown logic.
When destroying the UBus context, private fields of our ubus_object were
being reset to 0 while UBus was still owning those objects. While this
seems to work out fine, it seems cleaner to first release the object so
that UBus no longer owns it, before proceding to reset those fields.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:02:07 +01:00
Etan Kissling
8e9bde57c5 Eliminate redundant UBus notify variable.
There was a `notify` variable to keep track whether a subscriber is
observing our UBus object. However, it was not properly cleaned up in
`ubus_destroy`, potentially becoming stale over UBus reconnections.
The variable was removed and the current state is examined when sending
notifications, similarly as is done in other existing OpenWrt code.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:01:17 +01:00
Etan Kissling
1bb70e08be Handle UBus serialization errors.
The various blob / blobmsg commands can fail, e.g., when memory is low.
Previously, those errors were silently discarded. This patch adds checks
for the error conditions, logging them and exiting from the functions.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:00:18 +01:00
Simon Kelley
9afcb7ae61 Revert "There was a notify variable to keep track whether a subscriber is"
This reverts commit ea43234c86.
2021-08-12 17:00:10 +01:00
Simon Kelley
545c4955e6 Revert "Re-order UBus teardown logic."
This reverts commit d387f8f06c.
2021-08-12 16:58:30 +01:00
Simon Kelley
2f2d59b35c Define order of reading files when --addn-hosts given a directory.
Also applies to --dhcp-hostsfile and --dhcp-optsfile though it is
less useful there.
2021-08-12 16:48:54 +01:00
Simon Kelley
a1729deed3 Fiz sizeof() confusion in 527c3c7d0d 2021-08-11 09:10:39 +01:00
Simon Kelley
fc64b97cd5 dhcp_buff2 not availble in log_packet, use daemon->addrbuff 2021-08-10 23:54:13 +01:00
Simon Kelley
daddc8cb80 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2021-08-10 23:15:46 +01:00
Petr Menšík
527c3c7d0d Remove remaining uses of deprecated inet_ntoa() 2021-08-10 22:50:33 +01:00
Petr Menšík
fcb4dcaf7c Remove remaining uses of deprecated inet_addr() function. 2021-08-10 22:21:01 +01:00
Matthias Andree
3ca4995d34 CHANGELOG: spell-check 2021-08-10 21:40:06 +01:00
Etan Kissling
d387f8f06c Re-order UBus teardown logic.
When destroying the UBus context, private fields of our ubus_object were
being reset to 0 while UBus was still owning those objects. While this
seems to work out fine, it seems cleaner to first release the object so
that UBus no longer owns it, before proceding to reset those fields.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-10 21:16:03 +01:00
Etan Kissling
ea43234c86 There was a notify variable to keep track whether a subscriber is
observing our UBus object. However, it was not properly cleaned up in
`ubus_destroy`, potentially becoming stale over UBus reconnections.
The variable was removed and the current state is examined when sending
notifications, similarly as is done in other existing OpenWrt code.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-10 21:15:09 +01:00
Simon Kelley
867e56a45e Fix NOERR/NXDOMAIN in answers configured by --domain-needed. 2021-08-10 13:00:23 +01:00
Simon Kelley
a163c63787 CONNTRACK needs CAP_NET_ADMIN. 2021-08-05 23:40:04 +01:00
Simon Kelley
8389b943d3 Better fix than f2266d9678 2021-07-21 21:27:14 +01:00
Simon Kelley
f2266d9678 Add UINT32_MAX if not defined by system. 2021-07-21 00:23:28 +01:00
Simon Kelley
56bd806978 Typo in new EDE code. 2021-07-21 00:15:58 +01:00
Simon Kelley
ac7eeea44d Handle empty hostmaster in --auth-soa
Spotted by Max Julian Hofmann and the Advanced Research Team at CrowdStrike
2021-07-21 00:15:15 +01:00
Simon Kelley
b741059549 Detect malformed --dhcp-relay option.
Spotted by Max Julian Hofmann and the Advanced Research Team at CrowdStrike
2021-07-20 23:49:38 +01:00
Simon Kelley
cbd984287f Fix argument checking for --dhcp-match.
Spotted by Max Julian Hofmann and the Advanced Research Team at CrowdStrike
2021-07-20 23:45:36 +01:00
Simon Kelley
32e15c3f45 canonicalise_opt must always return heap memory.
Thanks to Max Julian Hofmann for spotting this.
2021-07-20 23:22:37 +01:00
Simon Kelley
f0dc324e35 Checks on prefix-length in --domain --synth-domain and --rev-server. 2021-07-20 23:15:28 +01:00
Simon Kelley
f83c6cf51a Return REFUSED in auth mode when we are not authoritative for the query. 2021-07-20 17:15:36 +01:00
Simon Kelley
c068b3ae2f --synth-domain now works in auth mode. 2021-07-19 09:38:48 +01:00
Simon Kelley
adf9dec1e6 Allow shorter IPv6 prefix lengths in (some) --synth-domain options. 2021-07-18 18:18:56 +01:00
Kevin Darbyshire-Bryant
767d9cbd96 Add --quiet-tftp. 2021-07-09 22:48:49 +01:00
Dominik DL6ER
e7ccd95c04 Add EDE return when no matching key found. 2021-07-09 22:12:42 +01:00
Simon Kelley
719f79a8fd Subtle change to priority of --server types.
Make --server=/example.com/1.2.3.4 take priority over
--server=/example.com/ (AKA --address=/example.com/ or --local=/example.com/)

This corrects a regression in the domain-match rewrite, and appears
to be the more useful order. It got swapped because I didn't consider
that both could usefully co-exist.
2021-07-06 21:02:35 +01:00
Kevin Darbyshire-Bryant
96f6444958 Fix thinko in a92c6d77dc 2021-07-05 21:00:47 +01:00
Simon Kelley
df25f204ba Fix logical error in d0ae3f5a4d
The code which checked for a possible local answer to a domain,
like --address=/example.com/1.2.3.4 could return false positives,
causing upstream NXDOMAIN replies to be rewritten as NOERROR.

Thanks to Dominik DL6ER for the bug report and analysis.
2021-07-05 20:56:11 +01:00
Simon Kelley
8acdc3ede7 Add calls to dump internally generated answers for dumpmask=0x0002 2021-07-04 23:12:14 +01:00
Simon Kelley
857b445522 Fix order of calls to resize-packet() and add_pseudoheader().
Avoids malformed replies with EDE in certain circumstances.
2021-07-04 22:38:26 +01:00
Simon Kelley
5bcca1219a Support IPv6 in --bogus-nxdomian and --ignore-address 2021-07-04 22:27:00 +01:00
Simon Kelley
4558c26fcd Make --rebind-localhost-ok apply to :: and 0.0.0.0
Also make the definition of local IPv6 addresses
the same for --bogus-priv and rebind protection.
2021-07-04 21:09:10 +01:00
Simon Kelley
a92c6d77dc Tidy domain parsing, make --server=/*/1.2.3.4 equivalent to --server=1.2.3.4 2021-07-03 12:56:50 +01:00
Petr Menšík
0c95a5ff53 Modify and propagate changed lease.
If hostname is reset on existing lease, propagate such change to leases
file and script.
2021-07-02 16:58:48 +01:00
Simon Kelley
cb6d06bb54 Rationalise SERV_MARK use. 2021-07-01 23:00:22 +01:00
Simon Kelley
3ef955c85a Fix oversight in build_server_array().
The index computation went awry when servers are disabled
by the loop-detection system.

Thanks to Xingcong Li for spotting this.
2021-07-01 22:40:31 +01:00
Simon Kelley
5e95c16c32 Allow wildcards in domain patterns.
Domain patterns in --address, --server and --local have, for many years,
matched complete labels only, so
--server=/google.com/1.2.3.4
will apply to google.com and www.google.com but NOT supergoogle.com

This commit introduces an optional '*' at the LHS of the domain string which
changes this behaviour so as to include substring matches _within_ labels. So,
--server=/*google.com/1.2.3.4
applies to google.com, www.google.com AND supergoogle.com.
2021-07-01 22:28:24 +01:00
Simon Kelley
4205e2ebcf Reuse workspace bit in struct server ->flags. 2021-07-01 13:22:10 +01:00
Etan Kissling
9d806c51c2 Fix ipset support.
This fixes a problem with ipset processing that got recently introduced
when `extract_request` filtering was tightened. During the recent change
an incorrect assumption was made that `extract_request` was only called
for requests but with ipset it is also called when processing responses.

The fix ensures that the new filters only apply to requests (QR=0 @ hdr)

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-06-30 12:31:51 +01:00
Simon Kelley
a38bb31727 Revert "Treat failure of ubus_add_object() in ubus_init() as retry-able."
This reverts commit 8a1ef367e2.
2021-06-30 12:30:15 +01:00
Simon Kelley
8a1ef367e2 Treat failure of ubus_add_object() in ubus_init() as retry-able.
3c93e8eb41 regularised ubus_init()
by avoiding logging calls (it can be called before logging is up)
but it instead returned any error from ubus_add_object() which
made such an error fatal. It turns out this is awkward, so this
patch returns NULL always, so that the event-loop will continue
attemping to connect to ubus forever.

This is not necessarily optimal either, and should be looked at
by a UBUS grown-up, but it does solve the immediate problem.
2021-06-27 21:32:10 +01:00
Simon Kelley
1291865c92 Fix trivial breakage of DBUS done by 85bc7534da 2021-06-27 21:16:30 +01:00
Simon Kelley
a9ebbee7b6 Compiler warnings. 2021-06-27 21:03:52 +01:00
Simon Kelley
06df5ad7d0 Tidy up interface to dbus and ubus modules.
Consistently treat a non-NULL return from [ud]bus-init() as a fatal error:
either die() if still starting, or log an error and disable
the relevant module if dnsmasq has already started.

Also rationalise calls to set and check listeners depending on
configuration.
2021-06-27 20:56:58 +01:00
Simon Kelley
66b863c989 Fix problem with re-allocation of serverarray. 2021-06-26 21:13:41 +01:00
Simon Kelley
c9efe8e5e1 Rationalise domain parsing for --rev-server and --domain. 2021-06-26 18:51:05 +01:00
Simon Kelley
d515223bb5 Don't re-use datastructures for --address and --local.
Doing so makes the loading process quadratic, which is a problem
when there are a large number.
2021-06-26 01:00:37 +01:00
Simon Kelley
b908f4334b Merge branch 'extended-error' 2021-06-26 00:38:55 +01:00
Simon Kelley
6261aba026 Initial implementation of RFC-8914 extended DNS errors. 2021-06-26 00:38:01 +01:00
Simon Kelley
85bc7534da Rationalise --server parsing and datastructure building.
Use add_update_server for everything.
2021-06-25 22:09:08 +01:00
Simon Kelley
1b30fd1732 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2021-06-25 10:46:53 +01:00
Simon Kelley
8c9196bff8 Correct domain search algorithm.
For reasons unknown, I (srk) assumed that the orginal
substring domain matching algorithm was still in use,
where example.com would match eg. sexample.com

In fact the far more sensible label-based match, where
example.com (or .example.com) matches example.com and
www.example.com, but not sexample.com, has been in use
since release 2.22. This commit implements the 2.22 to 2.85
behaviour in the new domain-search code.

Thanks to Kevin Darbyshire-Bryant for spotting my mistake.
2021-06-25 10:46:06 +01:00
Simon Kelley
b1daf44954 Correct domain search algorithm.
For reasons unknown, I (srk) assumed that the orginal
substring domain matching algorithm was still in use,
where example.comKevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk> would match eg. sexample.com

In fact the far more sensible label-based match, where
example.com (or .example.com) matches example.com and
www.example.com, but not sexample.com, has been in use
since release 2.22. This commit implements the 2.22 to 2.85
behaviour in the new domain-search code.

Thanks to Kevin Darbyshire-Bryant for spotting my mistake.
2021-06-24 23:28:47 +01:00
Simon Kelley
11c52d032b Initial changes for extended DNS error codes. 2021-06-21 17:37:46 +01:00
Simon Kelley
be291d979d Include EDNS0 in connmark REFUSED replies. 2021-06-21 16:59:42 +01:00
Simon Kelley
6d1edd8d32 Use correct packet-size limit in make_local_answer() 2021-06-21 15:59:07 +01:00
Simon Kelley
25ff956c7d Tidy up name buffer use in report_addresses().
Buffer may need to be twice MAXDNAME is escaping is
enabled in extract_name. The name may include weird characters.
2021-06-21 15:05:28 +01:00
Simon Kelley
38179500f8 CHANGELOG entry for new connmark code. 2021-06-21 14:35:36 +01:00
Simon Kelley
5f7be5f0d6 Fix compiler warning. 2021-06-21 14:31:54 +01:00
Etan Kissling
627056febb Connection track mark based DNS query filtering.
This extends query filtering support beyond what is currently possible
with the `--ipset` configuration option, by adding support for:
1) Specifying allowlists on a per-client basis, based on their
   associated Linux connection track mark.
2) Dynamic configuration of allowlists via Ubus.
3) Reporting when a DNS query resolves or is rejected via Ubus.
4) DNS name patterns containing wildcards.

Disallowed queries are not forwarded; they are rejected
with a REFUSED error code.

Signed-off-by: Etan Kissling <etan_kissling@apple.com>
(addressed reviewer feedback)
Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-06-21 14:14:55 +01:00
Simon Kelley
cbd76447fd Further work from a0a3b8ad3e
When query longer than longest domain, crop directly to length
of longest domain.
2021-06-21 00:01:51 +01:00
Simon Kelley
a60a233329 Fix bug introduced in 6860cf932b
Breakage 0f --no-rebind-domain due to incomplete edit.

Thanks to Kevin Darbyshire-Bryant for spotting this.
2021-06-20 23:02:54 +01:00
Simon Kelley
a0a3b8ad3e Fix bug in 6860cf932b
The optimisation based on the assumption that
"try now points to the last domain that sorts before the query"
fails in the specific edge case that the query sorts before
_any_ of the server domains. Handle this case.

Thanks to Xingcong Li for finding a test case for this bug.
2021-06-20 22:57:54 +01:00
Simon Kelley
d0ae3f5a4d Fix specific NOERR/NXDOMAIN confusion.
In the specific case of configuring an A record for a domain

address=/example.com/1.2.3.4

queries for *example.com for any other type will now return
NOERR, and not the previous erroneous NXDOMAIN. The same thing
applies for

address=/example.com/::1:2:3:4
address=/example.com/#
2021-06-17 23:11:17 +01:00
Simon Kelley
6860cf932b Optimise lokkup_domain() 2021-06-17 21:30:40 +01:00
Simon Kelley
0276e0805b merge development machines.
Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq
2021-06-16 14:05:49 +01:00
Simon Kelley
06ff3d8a26 Log the correct name when we retry a DNSSEC query.
If we retry a DNSSEC query because our client retries on us, and
we have an answer but are waiting on a DNSSEC query to validate it,
log the name of the DNSSEC query, not the client's query.
2021-06-16 13:59:57 +01:00
Simon Kelley
1a3b69aa56 Fix error in new domain-search code.
SERV_USE_RESOLV set implies struct serv_local,
so don't can't set ->arrayposn

Thanks to Xingcong Li for the cod review which led to this.
2021-06-16 09:57:41 +01:00
Simon Kelley
8237d06ab7 Typo in FAQ.
Reported by Alexander Traud.
2021-06-15 23:14:59 +01:00
Simon Kelley
1c9f136b57 Man page update, lease times can be given in days or weeks. 2021-06-15 22:07:59 +01:00
Simon Kelley
5ab7e4a475 Improve efficiency of DNSSEC.
The sharing point for DNSSEC RR data used to be when it entered the
cache, having been validated. After that queries requiring the KEY or
DS records would share the cached values. There is a common case in
dual-stack hosts that queries for A and AAAA records for the same
domain are made simultaneously.  If required keys were not in the
cache, this would result in two requests being sent upstream for the
same key data (and all the subsequent chain-of-trust queries.) Now we
combine these requests and elide the duplicates, resulting in fewer
queries upstream and better performance. To keep a better handle on
what's going on, the "extra" logging mode has been modified to
associate queries and answers for DNSSEC queries in the same way as
ordinary queries. The requesting address and port have been removed
from DNSSEC logging lines, since this is no longer strictly defined.
2021-06-15 15:27:29 +01:00
Simon Kelley
3236f358f8 Revise resource handling for number of concurrent DNS queries.
This used to have a global limit, but that has a problem when using
different servers for different upstream domains. Queries which are
routed by domain to an upstream server which is not responding will
build up and trigger the limit, which breaks DNS service for all other
domains which could be handled by other servers. The change is to make
the limit per server-group, where a server group is the set of servers
configured for a particular domain. In the common case, where only
default servers are declared, there is no effective change.
2021-06-13 21:29:22 +01:00
Simon Kelley
4a6550d69a Move make_local_answer() to domain-match.c 2021-06-10 21:40:52 +01:00
Simon Kelley
ff523d0c67 Fix TCP replies with --domain-needed. 2021-06-10 21:31:38 +01:00
Simon Kelley
3c93e8eb41 Re-order UBus initialisation to avoid logging before logs set up. 2021-06-08 23:13:48 +01:00
Simon Kelley
88a482fdb9 Rename hash_questions.c, for consistency. 2021-06-08 22:16:05 +01:00
Simon Kelley
12a9aa7c62 Major rewrite of the DNS server and domain handling code.
This should be largely transparent, but it drastically
improves performance and reduces memory foot-print when
configuring large numbers domains of the form
local=/adserver.com/
or
local=/adserver.com/#

Lookup times now grow as log-to-base-2 of the number of domains,
rather than greater than linearly, as before.
The change makes multiple addresses associated with a domain work
address=/example.com/1.2.3.4
address=/example.com/5.6.7.8
It also handles multiple upstream servers for a domain better; using
the same try/retry alogrithms as non domain-specific servers. This
also applies to DNSSEC-generated queries.

Finally, some of the oldest and gnarliest code in dnsmasq has had
a significant clean-up. It's far from perfect, but it _is_ better.
2021-06-08 22:10:55 +01:00
Simon Kelley
50ccf9c585 Fix manpage typo.
Thanks to Bart Wolther for the report.
2021-04-30 00:01:48 +01:00
Simon Kelley
d100eb05a3 <nettle/version.h> -> <nettle/bignum.h> for backward compatibility. 2021-04-14 21:15:34 +01:00
Petr Menšík
10d8b5f001 Reduce code duplication, reuse existing functions
dhcp_config_free and dhcp_opt_free already implement the same algorithm.
Reuse them. Adds forgotten hostname cleanup to config free.
2021-04-14 21:08:31 +01:00
Simon Kelley
ffd3ceb856 Remove old patch droppings in manpage. 2021-04-14 01:00:48 +01:00
Brian Hartvigsen
d942aa9321 Support Cisco Umbrella/OpenDNS Device ID & Remote IP
This is based on the information at
https://docs.umbrella.com/umbrella-api/docs/identifying-dns-traffic and
https://docs.umbrella.com/umbrella-api/docs/identifying-dns-traffic2 .
Using --umbrella by itself will enable Remote IP reporting. This can not
be used for any policy filtering in Cisco Umbrella/OpenDNS. Additional
information can be supplied using specific option specifications,
multiple can be separated by a comma:

--umbrella=orgid:1234,deviceid=0123456789abcdef

Specifies that you want to report organization 1234 using device
0123456789abcdef. For Cisco Umbrella Enterprise, see "Register (Create)
a device" (https://docs.umbrella.com/umbrella-api/docs/create-a-device)
for how to get a Device ID and "Organization ID endpoint"
(https://docs.umbrella.com/umbrella-api/docs/organization-endpoint) to
get organizations ID. For OpenDNS Home Users, there is no organization,
see Registration API endpoint
(https://docs.umbrella.com/umbrella-api/docs/registration-api-endpoint2)
for how to get a Device ID. Asset ID should be ignored unless
specifically instructed to use by support.

Signed-off-by: Brian Hartvigsen <brian.andrew@brianandjenny.com>
2021-04-14 00:16:14 +01:00
Simon Kelley
6469fefe89 Fix build failure with HAVE_CRYPTOHASH. 2021-04-13 23:33:46 +01:00
Simon Kelley
b082842ee7 Add NO_LOOP to config.h docs. 2021-04-12 17:43:59 +01:00
Geert Stappers
3573ca0eec Chomp file ends
Removed empty lines from end of src/*.[ch] files.
If the new last line became '#endif'
was the condition of the '#if' added.
2021-04-09 17:27:36 +01:00
Simon Kelley
ad90eb075d Fix bug in TCP process handling.
Fix bug which caused dnsmasq to lose track of processes forked
to handle TCP DNS connections under heavy load. The code
checked that at least one free process table slot was
available before listening on TCP sockets, but didn't take
into account that more than one TCP connection could
arrive, so that check was not sufficient to ensure that
there would be slots for all new processes. It compounded
this error by silently failing to store the process when
it did run out of slots. Even when this bug is triggered,
all the right things happen, and answers are still returned.
Only under very exceptional circumstances, does the bug
manifest itself: see
https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q2/014976.html

Thanks to Tijs Van Buggenhout for finding the conditions under
which the bug manifests itself, and then working out
exactly what was going on.
2021-04-09 16:08:05 +01:00
Simon Kelley
d55e2d086d Handle DHCPREBIND requests in the DHCPv6 server.
Patch by srk, based on submitted patch from liaichun@huawei.com
2021-04-09 15:19:28 +01:00
Simon Kelley
fe9c966a49 Fix debian/changelog format problem. 2021-04-08 22:41:46 +01:00
Simon Kelley
9f20afb1a8 Manpage typo. 2021-04-07 21:39:39 +01:00
Simon Kelley
f61afcfc70 Tidy error logging in 961daf8f92 2021-04-07 20:54:36 +01:00
Simon Kelley
961daf8f92 Handle resource exhaustion of struct frec_src same as struct frec.
Ie, by returning REFUSED response and (rate-limited) logging.
2021-04-06 23:52:09 +01:00
Simon Kelley
64a16cb376 Combine queries for the same DNS name if close in time.
If two queries arrive a second or so apart, they cannot be a try and
a retry from the same client (retries are at least three seconds apart.)

It's therefore safe not to forward the second query, but answer them
both when the reply arrives for the first.
2021-04-06 23:29:46 +01:00
Simon Kelley
ea6b0b2665 Subtly change behaviour on repeated DNS query.
This changes the behaviour introduced in
141a26f979

We re-introduce the distinction between a query
which is retried from the same source, and one which is
repeated from different sources.

In the later case, we still forward the query, to avoid
problems when the reply to the first query is lost
(see f8cf456920) but we suppress the behaviour
that's used on a retry, when the query is sent to
all available servers in parallel.

Retry -> all servers.
Repeat -> next server.

This avoids a significant increase in upstream traffic on
busy instances which see lots of queries for common names.

It does mean the clients which repeat queries from new source ports,
rather than retrying them from the same source port, will see
different behaviour, but it in fact restores the pre-2.83 behaviour,
so it's not expected to be a practical problem.
2021-04-05 21:01:09 +01:00
Matthias Andree
89df73ac05 CHANGELOG: fix typo recieved->received 2021-04-03 23:01:46 +01:00
Simon Kelley
7d3f3c9983 Fold NMU into Debian packaging. 2021-04-03 22:43:14 +01:00
Simon Kelley
1bdbea2461 Fold NMU into Debian packaging. 2021-03-30 22:42:29 +01:00
Simon Kelley
dfb1f7ccf1 TFTP tweak.
Check sender of all received packets, as specified in RFC 1350 para 4.

My understanding of the example in the RFC is that it in fact only
applies to server-to-client packets, and packet loss or duplication
cannot result in a client sending from more than one port to a server.
This check is not, therefore, strictly needed on the server side.
It's still useful, and adds a little security against packet
spoofing. (though if you're running TFTP on a public network with
bad actors, nothing can really save you.)
2021-03-30 21:32:07 +01:00
Matthias Andree
b5d1b20727 Fix spacing in translatable strings.
Signed-off-by: Matthias Andree <matthias.andree@gmx.de>
2021-03-28 00:58:54 +00:00
Matthias Andree
2a407a76be CHANGELOG: spell-check and correct first few entries
Signed-off-by: Matthias Andree <matthias.andree@gmx.de>
2021-03-28 00:56:13 +00:00
Matthias Andree
d1640a6338 po/de.po: Rework German translation...
for consistency, wording/language, typoes.

Signed-off-by: Matthias Andree <matthias.andree@gmx.de>
2021-03-28 00:55:44 +00:00
Simon Kelley
26b5c40d95 Replace ad-hoc libnettle version detecion with MIN_VERSION macro. 2021-03-27 23:29:36 +00:00
Petr Menšík
0b3ecf7432 Enable DNSSEC compilation on nettle 2.7.1
RHEL/CentOS 7 does not compile with DNSSEC enabled, because older
version is not supported. Add few defines to compile also on older
nettle versions.

Adds also major version 4 check, taking into account higher major
version.
2021-03-27 23:26:48 +00:00
Petr Menšík
8f9bd61505 Correct missing SERV_DO_DNSSEC flag, add new spot
One change to server_test_type forgot to set SERV_DO_DNSSEC. One new
place still can be reused.

Fixes commit e10a9239e1, thanks to
Xingcong Li for spotting it.
2021-03-27 23:16:09 +00:00
Simon Kelley
ea28d0ef8a Scale the DNS random scket pool on the value of dns-forward-max. 2021-03-26 22:02:04 +00:00
Simon Kelley
4a8c098840 Change the method of allocation of random source ports for DNS.
Previously, without min-port or max-port configured, dnsmasq would
default to the compiled in defaults for those, which are 1024 and
65535. Now, when neither are configured, it defaults instead to
the kernel's ephemeral port range, which is typically
32768 to 60999 on Linux systems. This change eliminates the
possibility that dnsmasq may be using a registered port > 1024
when a long-running daemon starts up and wishes to claim it.

This change does likely slighly reduce the number of random ports
and therefore the protection from reply spoofing. The older
behaviour can be restored using the min-port and max-port config
switches should that be a concern.
2021-03-26 21:19:39 +00:00
黎醒聪
ffa4628faa Fix thinko in 51f7bc924c 2021-03-22 22:00:26 +00:00
Petr Menšík
e10a9239e1 Move repeated test pattern to server_test_type
Use static function to test similar checks in multiple places.
2021-03-21 22:57:02 +00:00
Petr Menšík
51f7bc924c Create common function for forward dump, log and send
One part in dnssec retry path did not dump sent retry into dump file.
Make sure it is dumped all times it is sent by common function shared on
multiple places. Reduce a bit also server sending.
2021-03-21 22:56:05 +00:00
Petr Menšík
6c0bf79078 Reduce few repetitions in forward code 2021-03-21 22:54:12 +00:00
Matthias Andree
4b03170920 Update German translation for 2.85rc1.
Signed-off-by: Matthias Andree <matthias.andree@gmx.de>
2021-03-21 22:41:58 +00:00
Simon Kelley
1de6bbc108 Fix FTBS on FreeBSD due to Linux-specific optimisation of if_nametoindex() 2021-03-19 22:24:08 +00:00
Simon Kelley
023ace8e54 Merge branch 'random-port' 2021-03-17 20:42:21 +00:00
Simon Kelley
74d4fcd756 Use random source ports where possible if source addresses/interfaces in use.
CVE-2021-3448 applies.

It's possible to specify the source address or interface to be
used when contacting upstream nameservers: server=8.8.8.8@1.2.3.4
or server=8.8.8.8@1.2.3.4#66 or server=8.8.8.8@eth0, and all of
these have, until now, used a single socket, bound to a fixed
port. This was originally done to allow an error (non-existent
interface, or non-local address) to be detected at start-up. This
means that any upstream servers specified in such a way don't use
random source ports, and are more susceptible to cache-poisoning
attacks.

We now use random ports where possible, even when the
source is specified, so server=8.8.8.8@1.2.3.4 or
server=8.8.8.8@eth0 will use random source
ports. server=8.8.8.8@1.2.3.4#66 or any use of --query-port will
use the explicitly configured port, and should only be done with
understanding of the security implications.
Note that this change changes non-existing interface, or non-local
source address errors from fatal to run-time. The error will be
logged and communiction with the server not possible.
2021-03-17 20:39:33 +00:00
Simon Kelley
9eaa91bfc3 Teach --bogus-nxdomain and --ignore-address to take a subnet argument. 2021-03-17 20:31:06 +00:00
Petr Menšík
484bd75ce4 tftp warning fix.
At least on Fedora 32 with GCC 10.2.1, dnsmasq compilation emits warning:

tftp.c: In function ‘tftp_request’:
tftp.c:754:3: warning: ‘strcpy’ source argument is the same as
destination [-Wrestrict]
  754 |   strcpy(daemon->namebuff, file);

And indeed it is the same source always on line 477, sometimes also on
571 in tftp.c

Attached patch fixes the warning and possible undefined behaviour on
tftp error.
2021-03-17 14:40:04 +00:00
Simon Kelley
4c30e9602b Only log changes to DNS listeners when --log-debug is set. 2021-03-12 22:09:14 +00:00
Simon Kelley
b260d222af Add --log-debug option and MS_DEBUG flag to my_syslog(). 2021-03-12 21:57:57 +00:00
Simon Kelley
6528d62cd2 Merge i18n message files. 2021-03-11 23:46:45 +00:00
Simon Kelley
b7cf754f6f Add --dynamic-host option.
A and AAAA records which take their
network part from the network of a local interface. Useful
for routers with dynamically prefixes.
2021-03-11 23:39:33 +00:00
Simon Kelley
14e3f6ba19 Bump version in Debian changelog. 2021-03-02 21:41:04 +00:00
Petr Menšík
a8c1474562 Obtain MTU of interface only when it would be used
MTU were obtained early during iface_allowed check. But often it
returned from the function without ever using it. Because calls to
kernel might be costy, move fetching it only when it would be assigned.
2021-03-02 21:38:02 +00:00
Petr Menšík
8b8a4148ec Move flags to recvmsg function in netlink
netlink_multicast used 3 calls to fcntl in order to set O_NONBLOCK on
socket. It is possible to pass MSG_DONTWAIT flag just to recvmsg function,
without setting it permanently on socket. Save few kernel calls and use
recvmsg flags.

It is supported since kernel 2.2, should be fine for any device still
receiving updates.
2021-03-02 21:36:45 +00:00
Simon Kelley
9e147480ed Always use <poll.h>
Previously we were always using <sys/poll.h> since
HAVE_POLL_H is never set. This looks like an autoconfism
that has crept in, but we don't use autoconf.

poll.h is the correct header file, as far as I can tell.
2021-03-02 21:17:28 +00:00
Petr Menšík
4c0aecc685 Correct occasional --bind-dynamic synchronization break
Request only one re-read of addresses and/or routes

Previous implementation re-reads systemd addresses exactly the same
number of time equal number of notifications received.
This is not necessary, we need just notification of change, then re-read
the current state and adapt listeners. Repeated re-reading slows netlink
processing and highers CPU usage on mass interface changes.

Continue reading multicast events from netlink, even when ENOBUFS
arrive. Broadcasts are not trusted anyway and refresh would be done in
iface_enumerate. Save queued events sent again.

Remove sleeping on netlink ENOBUFS

With reduced number of written events netlink should receive ENOBUFS
rarely. It does not make sense to wait if it is received. It is just a
signal some packets got missing. Fast reading all pending packets is required,
seq checking ensures it already. Finishes changes by
commit 1d07667ac7.

Move restart from iface_enumerate to enumerate_interfaces

When ENOBUFS is received, restart of reading addresses is done. But
previously found addresses might not have been found this time. In order
to catch this, restart both IPv4 and IPv6 enumeration with clearing
found interfaces first. It should deliver up-to-date state also after
ENOBUFS.

Read all netlink messages before netlink restart

Before writing again into netlink socket, try fetching all pending
messages. They would be ignored, only might trigger new address
synchronization. Should ensure new try has better chance to succeed.

ENOBUFS error handling was improved. Netlink is correctly drained before
sending a new request again. It seems ENOBUFS supression is no longer
necessary or wanted. Let kernel tell us when it failed and handle it a
good way.
2021-03-02 18:21:32 +00:00
Simon Kelley
d556b8a5d5 Case error in x86-64_EFI pxe CSA 2021-02-28 21:36:03 +00:00
Simon Kelley
e7c0d7b348 dhcp-host selection fix for v4/v6.
Avoid treating a --dhcp-host which has an IPv6 address
as eligable for use with DHCPv4 on the grounds that it has
no address, and vice-versa.
2021-02-28 17:56:54 +00:00
Simon Kelley
17360439dc Clarification on dhcp-host and DNS. 2021-02-24 15:54:36 +00:00
Simon Kelley
9e169a9bea Belated CHANGELOG update. 2021-02-22 23:07:48 +00:00
Simon Kelley
305cb79c57 Simplify preceding fix.
Remove distinction between retry with same QID/SP and
retry for same query with different QID/SP. If the
QID/SP are the same as an existing one, simply retry,
if a new QID/SP is seen, add to the list to be replied to.
2021-02-18 21:50:33 +00:00
Simon Kelley
141a26f979 Fix problem with DNS retries in 2.83/2.84.
The new logic in 2.83/2.84 which merges distinct requests for the
same domain causes problems with clients which do retries as distinct
requests (differing IDs and/or source ports.) The retries just get
piggy-backed on the first, failed, request.

The logic is now changed so that distinct requests for repeated
queries still get merged into a single ID/source port, but they now
always trigger a re-try upstream.

Thanks to Nicholas Mu for his analysis.
2021-02-17 23:56:32 +00:00
Simon Kelley
cfcafdd27c Tweak f1204a875e
This gets, eg, v2.65test1 and v2.65test11 in the correct order.
2021-02-01 23:46:43 +00:00
Simon Kelley
f1204a875e Tweak sort order of tags in get-version.
We want to sort such that the most recent/relevant tag is first
and gets used to set the compiled-in version.

The solution is far from general, but works for the tag formats
used by dnsmasq. v2.84 sorts before v2.83, but v2.83 sorts
before v2.83rc1 and 2.83rc1 sorts before v2.83test1
2021-01-29 23:20:06 +00:00
Simon Kelley
20295012b8 Fix possible free-memory ref in e75069f79a 2021-01-24 22:25:13 +00:00
Simon Kelley
807e82343a Bump Debian changelog version. 2021-01-24 22:02:56 +00:00
Simon Kelley
c8e8f5c204 Bump copyright notices for 2021. Happy New Year! 2021-01-24 21:59:37 +00:00
Simon Kelley
a69b017902 Change HAVE_NETTLEHASH compile-time to HAVE_CRYPTOHASH.
HAVE_NETTLEHASH is retained for backwards compatibility, but deprecated.
2021-01-24 21:53:28 +00:00
Simon Kelley
e75069f79a Tidy initialisation in hash_questions.c 2021-01-22 22:50:25 +00:00
Simon Kelley
3f535da79e Fix for 12af2b171d 2021-01-22 22:26:25 +00:00
Simon Kelley
8ebdc364af Optimise sort_rrset for the case where the RR type no canonicalisation. 2021-01-22 18:50:43 +00:00
Simon Kelley
12af2b171d Fix to 75e2f0aec33e58ef5b8d4d107d821c215a52827c 2021-01-22 18:24:03 +00:00
Simon Kelley
04490bf622 Move fd into frec_src, fixes 15b60ddf93
If identical queries from IPv4 and IPv6 sources are combined by the
new code added in 15b60ddf93 then replies
can end up being sent via the wrong family of socket. The ->fd
should be per query, not per-question.

In bind-interfaces mode, this could also result in replies being sent
via the wrong socket even when IPv4/IPV6 issues are not in play.
2021-01-22 17:30:27 +00:00
Simon Kelley
327bbc92bc Changed priority to high in Debian changelog. 2021-01-17 23:35:24 +00:00
Simon Kelley
cc0b4489c7 Update to new struct frec fields in conntrack code. 2021-01-15 22:21:52 +00:00
Simon Kelley
9212ad284f Update Debian changelog. 2021-01-15 22:17:30 +00:00
Simon Kelley
503f68dbc4 Fix warning message logic. 2021-01-15 21:53:29 +00:00
Simon Kelley
e01e09c712 Add CVE numbers to security update descriptions in CHANGELOG 2021-01-08 22:50:03 +00:00
Simon Kelley
6a6e06fbb0 Small cleanups in frec_src datastucture handling. 2020-12-16 15:49:03 +00:00
Petr Menšík
2024f97297 Support hash function from nettle (only)
Unlike COPTS=-DHAVE_DNSSEC, allow usage of just sha256 function from
nettle, but keep DNSSEC disabled at build time. Skips use of internal
hash implementation without support for validation built-in.
2020-12-16 15:49:03 +00:00
Simon Kelley
25e63f1e56 Handle caching with EDNS options better.
If we add the EDNS client subnet option, or the client's
MAC address, then the reply we get back may very depending on
that. Since the cache is ignorant of such things, it's not safe to
cache such replies. This patch determines when a dangerous EDNS
option is being added and disables caching.

Note that for much the same reason, we can't combine multiple
queries for the same question when dangerous EDNS options are
being added, and the code now handles that in the same way. This
query combining is required for security against cache poisoning,
so disabling the cache has a security function as well as a
correctness one.
2020-12-16 15:49:03 +00:00
Simon Kelley
15b60ddf93 Handle multiple identical near simultaneous DNS queries better.
Previously, such queries would all be forwarded
independently. This is, in theory, inefficent but in practise
not a problem, _except_ that is means that an answer for any
of the forwarded queries will be accepted and cached.
An attacker can send a query multiple times, and for each repeat,
another {port, ID} becomes capable of accepting the answer he is
sending in the blind, to random IDs and ports. The chance of a
succesful attack is therefore multiplied by the number of repeats
of the query. The new behaviour detects repeated queries and
merely stores the clients sending repeats so that when the
first query completes, the answer can be sent to all the
clients who asked. Refer: CERT VU#434904.
2020-12-16 15:49:02 +00:00
Simon Kelley
824461192c Add missing check for NULL return from allocate_rfd(). 2020-12-16 15:49:02 +00:00
Simon Kelley
1eb6cedb03 Fix DNS reply when asking for DNSSEC and a validated CNAME is already cached. 2020-12-16 15:49:02 +00:00
Simon Kelley
059aded070 Optimse RR digest calculation in DNSSEC.
If an RR is of a type which doesn't need canonicalisation,
bypass the relatively slow canonicalisation code, and insert
it direct into the digest.
2020-12-16 15:49:02 +00:00
Simon Kelley
2d765867c5 Use SHA-256 to provide security against DNS cache poisoning.
Use the SHA-256 hash function to verify that DNS answers
received are for the questions originally asked. This replaces
the slightly insecure SHA-1 (when compiled with DNSSEC) or
the very insecure CRC32 (otherwise). Refer: CERT VU#434904.
2020-12-16 15:49:02 +00:00
Simon Kelley
257ac0c5f7 Check destination of DNS UDP query replies.
At any time, dnsmasq will have a set of sockets open, bound to
random ports, on which it sends queries to upstream nameservers.
This patch fixes the existing problem that a reply for ANY in-flight
query would be accepted via ANY open port, which increases the
chances of an attacker flooding answers "in the blind" in an
attempt to poison the DNS cache. CERT VU#434904 refers.
2020-12-16 15:48:36 +00:00
Simon Kelley
4e96a4be68 Fix remote buffer overflow CERT VU#434904
The problem is in the sort_rrset() function and allows a remote
attacker to overwrite memory. Any dnsmasq instance with DNSSEC
enabled is vulnerable.
2020-12-16 15:47:42 +00:00
Simon Kelley
a2a7e040b1 Use the values of --min-port and --max-port in TCP connections.
Rather that letting the kernel pick source ports, do it ourselves
so that the --min-port and --max-port parameters are be obeyed.
2020-12-12 23:26:45 +00:00
Wang Shanker
4ded96209e pxe: support pxe clients with custom vendor-class
From 606d638918edb0e0ec07fe27eb68d06fb5ebd981 Mon Sep 17 00:00:00 2001
From: Miao Wang <shankerwangmiao@gmail.com>
Date: Fri, 4 Dec 2020 09:59:37 +0800
Subject: [PATCH v2] pxe: support pxe clients with custom vendor-class

According to UEFI[1] and PXE[2] specs, PXE clients are required to have
`PXEClient` identfier in the vendor-class field of DHCP requests, and
PXE servers should also include that identifier in their responses.
However, the firmware of servers from a few vendors[3] are customized to
include a different identifier. This patch adds an option named
`dhcp-pxe-vendor` to provide a list of such identifiers. The identifier
used in responses sent from dnsmasq is identical to that in the coresponding
request.

[1]: https://uefi.org/sites/default/files/resources/UEFI%20Spec%202.8B%20May%202020.pdf
[2]: http://www.pix.net/software/pxeboot/archive/pxespec.pdf
[3]: For instance, TaiShan servers from Huawei, which are Arm64-based,
       send `HW-Client` in PXE requests up to now.

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
2020-12-06 22:48:11 +00:00
Matthias Andree
f60fea1fb0 CHANGELOG: Fix three typoes. 2020-07-19 21:54:44 +01:00
Simon Kelley
4d85e409cd Change default lease time for DHCPv6 to one day.
Also remove floor on valid and preffered times in RA when
no time is specified.
2020-07-12 22:45:46 +01:00
Simon Kelley
2bd02d2f59 Backdated CHANGELOG update. 2020-07-12 21:57:38 +01:00
Simon Kelley
7e194a0a7d Apply floor of 60s to TTL of DNSKEY and DS records in cache.
Short TTLs and specifically zero TTLs can mess up DNSSEC validation.
2020-07-12 17:43:25 +01:00
Simon Kelley
9beb4d9ea2 Fix BNF in man page description for --server. 2020-07-05 17:17:39 +01:00
Simon Kelley
ab5ebe9507 Bump Debian version to 2.82 2020-06-26 22:23:15 +01:00
Simon Kelley
837e8f4eb5 Remove runit support when building debs for Ubuntu. 2020-06-26 22:13:27 +01:00
Simon Kelley
e2cb655958 Thorough clean-up following 8270648da1. 2020-06-20 22:30:12 +01:00
Frank
8270648da1 Fix memory corruption on EAGAIN return from pipe during TCP requests.
This patch fixes a buffer overflow in TCP requests. Since the read is not
actually being retried, the byte written by the child can be left
in the pipe. When that happens, cache_recv_insert() reads the length of the
name, which is now multiplied by 256 due to the extra 0 byte (8 bit shift)
and results in daemon->namebuff being overflowed.

Namebuff is immediately before the daemon struct in memory so it
ends up corrupting the beginning of the daemon struct.
2020-06-20 15:17:56 +01:00
Simon Kelley
619000a3c5 Suppress logging of listen addresses during startup.
The initial call to enumerate_interfaces() happens before the
logging subsystem in initialised and the startup banner logged.
It's not intended that syslog be written at this point.
2020-04-29 00:09:58 +01:00
Petr Menšík
1c1b925052 Remove duplicate address family from listener
Since address already contain family, remove separate family from
listener. Use now family from address itself.
2020-04-29 00:06:57 +01:00
Petr Menšík
49bdf1ead9 Handle listening on duplicate addresses
Save listening address into listener. Use it to find existing listeners
before creating new one. If it exist, increase just used counter.
Release only listeners not already used.

Duplicates family in listener.
2020-04-29 00:06:31 +01:00
Petr Mensik
60a3ae19c5 Cleanup interfaces no longer available
Clean addresses and interfaces not found after enumerate. Free unused
records to speed up checking active interfaces and reduce used memory.
2020-04-29 00:06:01 +01:00
Petr Mensik
951a22165c Compare address and interface index for allowed interface
If interface is recreated with the same address but different index, it
would not change any other parameter.

Test also address family on incoming TCP queries.
2020-04-29 00:04:29 +01:00
Petr Mensik
51cdd1a227 Explicitly mark address port not used
On many places return value is ignored. Usually it means port is always
the same and not needed to be displayed. Unify warnings.
2020-04-29 00:04:04 +01:00
Petr Mensik
66adee85be Log listening on new interfaces
Log in debug mode listening on interfaces. They can be dynamically
found, include interface number, since it is checked on TCP connections.
Print also addresses found on them.
2020-04-29 00:03:21 +01:00
Simon Kelley
4890bcdea2 Workaround for reported recvmsg() ignoring MSG_PEEK. 2020-04-28 14:02:53 +01:00
Simon Kelley
8baf583a3f Allow IPv6 addresses ofthe form [::ffff:1.2.3.4] in --dhcp-option. 2020-04-23 23:14:45 +01:00
Simon Kelley
913fa15fb1 Convert failure of setsockopt(..., SOL_NETLINK, NETLINK_NO_ENOBUFS, ...) into warning.
We call this, which avoids POLLERR returns from netlink on a loaded system,
if the kernel is new enough to support it. Sadly, qemu-user doesn't support
the socket option, so if it fails despite the kernel being new enough to
support it, we just emit a warning, rather than failing hard.
2020-04-19 23:16:52 +01:00
Simon Kelley
00fe2f49e0 Debian package fix for kFreeBSD. 2020-04-19 21:59:13 +01:00
Simon Kelley
ec2067df75 Debian package fixes.
Add runit /etc files to conffiles.
Fix broken copyright file in dnsmasq binary package.
2020-04-12 16:12:50 +01:00
Simon Kelley
7ddb99d251 Debian changelog entry for CVE-2019-14834 2020-04-08 17:32:53 +01:00
Geert Stappers
ba26d3485b [PATCH] src/dnsmasq.c: Labeled a lonely #endif 2020-04-06 15:42:39 +01:00
Matthias Andree
081a1c4014 2.81rc5 CHANGELOG and man/dnsmasq.8 manual page improvements
Hi Simon,

>         Add --shared-network config. This enables allocation of addresses
>         the DHCP server in subnets where the server (or relay) doesn't
>         have an interface on the network in that subnet. Many thanks to
>         kamp.de for sponsoring this feature.
Does this paragraph lack a preposition "by" early on the 2nd line, or am
I mis-guessing the purpose?

...enables allocation of addresses *by* the DHCP server...

The manual page also seems to offer room for linguistic improvement
(apparently written by a German, so I see the typical patterns, and also
the misuse of which vs. that.

I am attaching a patch series vs. git to fix several issues in the
manpage and CHANGELOG.

From 35b88d98429e2fe016d9989d220f6faf2b933764 Mon Sep 17 00:00:00 2001
From: Matthias Andree <matthias.andree@gmx.de>
Date: Sun, 5 Apr 2020 11:18:05 +0200
Subject: [PATCH 1/5] man/dnsmasq.8: Properly capitalize DHCP acronym.
2020-04-06 15:29:24 +01:00
Simon Kelley
532246fc9e Tweak to DNSSEC logging. 2020-04-04 18:50:56 +01:00
Simon Kelley
8caf3d7c6c Fix rare problem allocating frec for DNSSEC.
A call to get_new_frec() for a DNSSEC query could manage to
free the original frec that we're doing the DNSSEC query to validate.
Bad things then happen.

This requires that the original frec is old, so it doesn't happen
in practice. I found it when running under gdb, and there have been
reports of SEGV associated with large system-clock warps which are
probably the same thing.
2020-04-04 17:00:32 +01:00
Oldřich Jedlička
d162bee356 Allow overriding of ubus service name.
Same as for the dbus, allow specifying ubus service name (namespace) on
the command line as an optional argument to --enable-ubus option.

Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
2020-03-28 18:16:53 +00:00
Simon Kelley
b43585c34b Fix nameserver list in auth mode.
If dnsmasq is not acting as an authoritative nameserver (no second
argument to --auth-server) then it should not appear in the NS RRset.

This leaves simply the list of servers specified in --auth-sec-servers.
2020-03-28 17:41:06 +00:00
Oldřich Jedlička
3f60ecd6f0 Fixed resource leak on ubus_init failure.
When ubus_add_object fails, the ubus_connect object is not freed, so the
connection leaks. Add ubus_destroy to free the connection object.

Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
2020-03-19 22:20:18 +00:00
Simon Kelley
0506a5ed4e Handle old kernels that don't do NETLINK_NO_ENOBUFS.
Deal with both old kernel header files that don't define it,
and old kernels that don't implement it.

Also generalise Linux kernel version handling.
2020-03-19 21:56:45 +00:00
Dominik DL6ER
e7ee1aa093 Extend stop-dns-rebind to reject IPv6 LL and ULA addresses.
We also reject the loopback address if rebind-localhost-ok is NOT set.

Signed-off-by: DL6ER <dl6er@dl6er.de>
2020-03-17 22:59:17 +00:00
Simon Kelley
63ed917ad9 Update to Debian runit mods. 2020-03-17 17:07:49 +00:00
Simon Kelley
63e21bdea3 Remove 19036 trust anchor, now expired. 2020-03-17 14:43:42 +00:00
Simon Kelley
1627d577af Set NETLINK_NO_ENOBUFS in netlink socket, to avoid POLLERR returns. 2020-03-10 23:55:18 +00:00
Conrad Kostecki
b837c4528d Update German translation. 2020-03-10 21:20:46 +00:00
Petr Menšík
46bdfe691a Fix error in IPv6 prefix calculation.
Error with prefixed address assignment. When it is calculating number of
addresses from prefixlen, it rotates only 32bit int instead of 64b uint.
Only result is assigned to 64b variable.

Two examples:

dhcp-host=[2000::1230:0:0/92],correct-prefix
dhcp-host=[2000::1234:5678:0/92],incorrect-prefix

If prefix length is lower than 96, the result is zero. It means
incorrect-prefix is not refused as it should. Fix is simple, attaching
patch with it. Just rotate 64b int.
2020-03-08 15:56:19 +00:00
Vladislav Grishenko
dded78b233 Add DHCPv6 ntp-server (56) option handling.
There was discussion in the past regarding DHCPv6 NTP server option
which needs special subclassing per RFC5908.

Patch adds support for unicast, multicast IPv6 address and for FQDN string,
preserving possibly used (as suggested earlier) hex value.

Unfortunately it's still not fully free from limitations - only address list or
only fqdn value list is possible, not mixed due current
state option parsing & flagging.
2020-03-08 15:34:34 +00:00
Kevin Darbyshire-Bryant
b594e8defa rfc3315: fix incorrect logical '&&' warning
rfc3315.c:1711:28: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
    if (!(addr_list->flags && ADDRLIST_DECLINED) ||
                           ^  ~~~~~~~~~~~~~~~~~

It's a flag bit so should be bitwise '&' operator

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2020-03-08 15:10:27 +00:00
Kevin Darbyshire-Bryant
70c50efd0d suppress non linux network unused var warnings
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2020-03-08 15:09:44 +00:00
Brad Smith
ea3c60ac07 Diverge error handling between *BSD and Linux. 2020-03-08 14:53:59 +00:00
Simon Kelley
fc19399a1f Fix compiler warning. 2020-03-05 22:13:45 +00:00
Simon Kelley
980b14f174 Compiler warning. 2020-03-05 18:01:48 +00:00
Simon Kelley
1df73fe831 Remove compiler warnings in IPv6 checksum code in dump.c 2020-03-05 17:51:17 +00:00
Simon Kelley
c125c1dfee Update decline address handling in DHCPv6 for new multi-address world.
When dhcp-host options can have many IPv6 addresses, we need
to deal with one of them being declined by a client. The other
addresses are still valid.

It seems that this logic never worked, even with only one address, since
the DECLINED flag was never tested.
2020-03-05 17:10:14 +00:00
Matthias Andree
e39c484ebd Fix parameters to setsockopt() for TCP_FASTOPEN. 2020-03-05 15:58:31 +00:00
Simon Kelley
977a5a2df1 Merge i18n messages. 2020-03-02 22:34:12 +00:00
Simon Kelley
02df0007c8 Trivial formatting fix. 2020-03-02 22:30:28 +00:00
Donald Sharp
b2ed691eb3 Ignore routes in non-main tables
Route lookup in Linux is bounded by `ip rules` as well
as the contents of specific routing tables.  With the
advent of vrf's(l3mdev's) non-default tables are regularly being
used for routing purposes.

dnsmasq listens to all route changes on the box and responds
to each one with an event.  This is *expensive* when a full
BGP routing table is placed into the linux kernel, moreso
when dnsmasq is responding to events in tables that it will
never actually need to respond to, since dnsmasq at this
point in time has no concept of vrf's and would need
to be programmed to understand them.  Help alleviate this load
by reducing the set of data that dnsmasq pays attention to
when we know there are events that are not useful at this
point in time.

Signed-off-by: Donald Sharp <donaldsharp72@gmail.com>
2020-03-02 18:11:22 +00:00
Kevin Darbyshire-Bryant
8d6d5730c9 option.c: fix NO_DHCP6 build error
Errors encountered if building with 'NO_DHCP6' introduced by
commit 137286e9ba

option.c: In function 'dhcp_config_free':
option.c:1040:24: error: 'struct dhcp_config' has no member named 'addr6'; did you mean 'addr'?
    for (addr = config->addr6; addr; addr = tmp)
                        ^~~~~
                        addr
option.c: In function 'one_opt':
option.c:3227:7: error: 'struct dhcp_config' has no member named 'addr6'; did you mean 'addr'?
  new->addr6 = NULL;
       ^~~~~
       addr

Wrap new code in ifdef HAVE_DHCP6

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2020-03-02 18:07:42 +00:00
Simon Kelley
48755ebf09 Optimise closing file descriptors.
Dnsmasq needs to close all the file descriptors it inherits, for security
reasons. This is traditionally done by calling close() on every possible
file descriptor (most of which won't be open.) On big servers where
"every possible file descriptor" is a rather large set, this gets
rather slow, so we use the /proc/<pid>/fd directory to get a list
of the fds which are acually open.

This only works on Linux. On other platforms, and on Linux systems
without a /proc filesystem, we fall back to the old way.
2020-03-02 17:42:51 +00:00
Simon Kelley
0541a1adf7 Factor out closing all file descriptors for later optimisation. 2020-03-02 17:10:25 +00:00
Simon Kelley
c992ed4bef Debian filemode tweak. 2020-03-02 14:16:48 +00:00
Simon Kelley
92025a4113 Debian package: support runscript init-system. 2020-02-29 22:56:38 +00:00
Simon Kelley
a7d19e917a Support ECC-GOST DNSSEC signature algorithm.
Requires forthcoming nettle 3.6 release.
2020-02-29 16:27:00 +00:00
Simon Kelley
ec1cc455d6 Add support for ED448 DNSSEC signature verification.
Note that the the current release of Nettle doesn't
yet have support. This code will become active on the
next Nettle release.
2020-02-29 16:24:49 +00:00
Simon Kelley
ee64582a1f Add --script-on-renewal option. 2020-02-27 16:54:12 +00:00
Simon Kelley
425e2405aa Remove DSA signature verification from DNSSEC, as specified in RFC 8624. 2020-02-26 18:28:32 +00:00
Simon Kelley
dea53e6658 Debian changelog update. 2020-02-12 22:36:16 +00:00
Simon Kelley
a9b022ab65 Allow empty server spec in --rev-server, to match --server. 2020-02-11 21:58:59 +00:00
Kevin Darbyshire-Bryant
c65b77c87f dnssec: add hostname info to insecure DS warning
Make the existing "insecure DS received" warning more informative by
reporting the domain name reporting the issue.

This may help identify a problem with a specific domain or server
configuration.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2020-02-11 21:32:56 +00:00
DDoSolitary
8e3a5cba8b Use <poll.h> instead of <sys/poll.h>
The former should be used according to POSIX, otherwise it causes
bunches of warnings when compiling for musl-based distros like Alpine
Linux.
2020-02-11 21:21:24 +00:00
Petr Menšík
29ae308398 Restore ability to answer non-recursive requests
Instead, check only local configured entries are answered without
rdbit set. All cached replies are still denied, but locally configured
names are available with both recursion and without it.

Fixes commit 4139298d28 unintended
behaviour.
2020-02-11 21:01:28 +00:00
Simon Kelley
306888afb3 Debian changelog update. 2020-02-10 22:49:18 +00:00
Simon Kelley
f064188032 Fix bug with prefixed wildcard addresses in 137286e9ba 2020-02-10 21:25:12 +00:00
Simon Kelley
77476580ed Fix problem with netlink socket and TCP DNS.
When dnsmasq forks a child to handle a TCP connection, that
child inherits the netlink socket that the main process has open.

The child never uses that socket, but there's a chance that when the
main process uses the netlink socket, the answer will go to a child
process which has a copy of the socket. This causes the main process
to block forever awaiting the answer which never comes.

The solution is for the child process to close the netlink socket it
inherits after the fork().  There's a nasty race because the error
decribed above could still occur in the window between the fork()
and the close() syscalls. That's fixed by blocking the parent awaiting
a single byte sent though the pipe the two processes share. This byte
is sent by the child after calling close() on the netlink socket.

Thanks to Alin Năstac for spotting this.
2020-02-09 23:19:41 +00:00
Simon Kelley
52ec783613 Add tag filtering of dhcp-host directives. 2020-02-07 21:05:54 +00:00
Simon Kelley
137286e9ba Extend 79aba0f10a for multiple IPv6 addresses. 2020-02-06 22:09:30 +00:00
Simon Kelley
79aba0f10a Support prefixed ranges of ipv6 addresses in dhcp-host.
When a request matching the clid or mac address is
recieved the server will iterate over all candidate
addresses until it find's one that is not already
leased to a different clid/iaid and advertise
this address.

Using multiple reservations for a single host makes it
possible to maintain a static leases only configuration
which support network booting systems with UEFI firmware
that request a new address (a new SOLICIT with a new IA_NA
option using a new IAID) for different boot modes, for
instance 'PXE over IPv6', and 'HTTP-Boot over IPv6'. Open
Virtual Machine Firmware (OVMF) and most UEFI firmware
build on the EDK2 code base exhibit this behaviour.
2020-02-03 23:58:45 +00:00
Simon Kelley
515ba97595 Fix infinite-loop router advert problems.
The previous code here, which started fast-RA whenever that local
address associated with a DHCP context changed, is very vulnerable
to flapping  due to dynamically created addresses in the same net.

Simplify so that if a context which has never found an interface now
finds one, that gets advertised, but not for other changes. That satisfies
the original intention that prefixes not in place when dnsmasq starts
should be recognised.

Also totally ignore all interfaces where we are configured not to do DHCP,
to preclude flapping of they have prefixes in common with interfaces
where we do DHCP.
2020-01-27 23:30:10 +00:00
Simon Kelley
cd672933c9 Fix RA problems with two interfaces on same IPv6 subnet. 2020-01-27 22:53:07 +00:00
Simon Kelley
d9603ef781 Fix the disease, not the symptom in e40d8bef3b 2020-01-26 18:13:35 +00:00
Dominik DL6ER
e40d8bef3b Do not try to measure length of NULL pointer. This avoids a crash for empty domains in server=//... configurations. 2020-01-20 21:20:59 +00:00
Simon Kelley
ab53883c94 Enhance --conf-dir to load files in a deterministic order. 2020-01-10 20:44:48 +00:00
Simon Kelley
6c1e9ac14b Remove experimental DHCPv6 prefix-class support.
The standard for this never made it beyond an internet-draft which expired
in 2012, so it can be considered dead, I think.
2020-01-07 22:04:07 +00:00
Simon Kelley
c7a44c4690 Revert tftp block number overflow check. Wrapping block nos is fine. 2020-01-07 20:30:16 +00:00
Simon Kelley
2ac4cf0146 Tweaks to TFTP.
Fail on overlarge files (block numbers are limited to 16 bits)
Honour tftp-max setting in single port mode.
Tweak timeouts, and fix logic which suppresses errors if the
last ACK is missing.
2020-01-06 23:39:33 +00:00
Sung Pae
a914d0aa6a Check for SERV_NO_REBIND on unqualified domains
Hello,

My home network has a DNS search domain of home.arpa and my machine's dnsmasq
instance is configured with:

        server=/home.arpa/192.168.0.1
        server=//192.168.0.1
        stop-dns-rebind
        rebind-domain-ok=home.arpa
        rebind-domain-ok=// # Match unqualified domains

Querying my router's FQDN works as expected:

        dnsmasq: query[A] gateway.home.arpa from 127.0.0.1
        dnsmasq: forwarded gateway.home.arpa to 192.168.0.1
        dnsmasq: reply gateway.home.arpa is 192.168.0.1

But using an unqualified domain name does not:

        dnsmasq: query[A] gateway from 127.0.0.1
        dnsmasq: forwarded gateway to 192.168.0.1
        dnsmasq: possible DNS-rebind attack detected: gateway

The attached patch addresses this issue by checking for SERV_NO_REBIND when
handling dotless domains.

>From 0460b07108b009cff06e29eac54910ec2e7fafce Mon Sep 17 00:00:00 2001
From: guns <self@sungpae.com>
Date: Mon, 30 Dec 2019 16:34:23 -0600
Subject: [PATCH] Check for SERV_NO_REBIND on unqualified domains
2020-01-05 22:07:01 +00:00
Simon Kelley
91102ad5eb Add warnings and caveats for --proxy-dnssec. 2020-01-05 21:58:00 +00:00
Simon Kelley
378fa56888 Don't send RAs on interfaces without a link-local address.
Since the source address of the RAs must be the link-local address.
2020-01-05 17:23:19 +00:00
Simon Kelley
2a8710ac2f Update copyrights to 2020. 2020-01-05 16:40:06 +00:00
Simon Kelley
66f62650c3 Add --tftp-single-port option. 2020-01-05 16:21:24 +00:00
Simon Kelley
18a6bdd541 Avoid RA code trampling on DHCPv6 messages.
Calling lease_update_file() _can_ result in a call to  periodic_ra()

Since both the DHCPv6 and RA subsystems use the same packet buffer
this can overwrite the DHCPv6 packet. To avoid this we ensure the
DHCPv6 packet has been sent before calling lease_update_file().
2019-12-20 18:19:20 +00:00
Simon Kelley
9e732445cf Fix crash in DHCP option parsing.
Thanks to Klaus Eisentraut <klaus.eisentraut@web.de> for finding this.
2019-12-12 20:56:08 +00:00
Simon Kelley
7d04e17444 Fix buffer overflow checking in parse_hex().
The inputs to parse_hex are never untrusted data, so not security problem.

Thanks to Klaus Eisentraut <klaus.eisentraut@web.de> for finding this.
2019-12-12 16:44:22 +00:00
Simon Kelley
34d41475e7 Fix dhcp-name-match to always match client-supplied name.
This modifies commit 6ebdc95754.
2019-12-05 23:54:28 +00:00
Ville Skyttä
0c211c4ec5 Support DHCP option 150 (TFTP server address, RFC 5859). 2019-12-05 17:11:09 +00:00
Ville Skyttä
bf23c8a394 Spelling and format fixes. 2019-12-05 16:50:57 +00:00
Simon Kelley
f73f7397d7 Fix bug which gave zero-length DHCPv6 packets if sendto() is interrupted. 2019-12-03 18:18:46 +00:00
Simon Kelley
5cee7c2702 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2019-12-03 16:07:21 +00:00
Simon Kelley
1aef66bb34 New CNAME code shouldn't spin on CNAME loops. 2019-11-30 21:07:15 +00:00
Simon Kelley
4a1c21d62c Fix spin-crash in new CNAME code (b59a5c2567)
Thanks to Tore Anderson for finding this.
2019-11-30 20:59:44 +00:00
nl6720
c117675ebd Fix systemd unit startup order
Order dnsmasq.service before network.target and after network-online.target & nss-lookup.target. Additionally pull in nss-lookup.target.
This matches the behaviour of systemd-resolved and Unbound.

Signed-off-by: nl6720 <nl6720@gmail.com>
2019-10-30 21:50:23 +00:00
Simon Kelley
6ebdc95754 Fix dhcp-name-match to function when name supplied in --dhcp-host. 2019-10-30 21:04:27 +00:00
Simon Kelley
55a22b88c2 Fix out-of-date comment. 2019-10-30 13:03:28 +00:00
Simon Kelley
1fd56c0e33 Tidy up CNAME representaion.
Use an explicit discriminator for the target union.
2019-10-30 12:58:28 +00:00
Simon Kelley
376cb97685 Extend non-terminal name handling to all locally configured RRs. 2019-10-29 22:58:55 +00:00
Simon Kelley
84449bf41c Generalise locally-configured CNAME handling.
It's now possible for the target of a CNAME to be any locally
configured RR or even point to a non-existent RR.
2019-10-29 22:24:19 +00:00
Dominik DL6ER
456a319775 DHCPv6 IAID should be of unsigned type. It is derived from strtoul() in lease.c:read_leases() and already now interpreted as unsigned in helper.c:276 and outpacket.c:put_opt6_long(). RFC3315 (section 22.4) shows that the IAID is 4 bytes long so we do not need to go up to unsigned long.
Signed-off-by: Dominik DL6ER <dl6er@dl6er.de>
2019-10-25 22:00:35 +01:00
Simon Kelley
157d8cfd6a Don't silently discard all-zeroes adddresses in --host-record. 2019-10-25 17:46:49 +01:00
Simon Kelley
1292e1a557 Don't waste time caching zero-TTL DNS records. 2019-10-25 17:31:53 +01:00
Simon Kelley
122997da54 Fix bugs in caching CNAMEs with target to SRV records. 2019-10-25 17:23:56 +01:00
Simon Kelley
b59a5c2567 Generalise CNAME handling.
Cope with cached and configured CNAMES for all record types we
support, including local-config but not cached types such as TXT.

Also, if we have a locally configured CNAME but no target for the
requested type, don't forward the query.
2019-10-25 16:13:38 +01:00
Geert Stappers
2a20cc6da8 Man page typo. 2019-10-22 18:20:56 +01:00
Simon Kelley
936bd82755 Fix too small control array in tftp code on BSD and SOLARIS
This causes tftp to fail on some BSD versions, for sure. It
works by chance on others.

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=241068
2019-10-12 23:29:59 +01:00
Florent Fourcot
13a58f9590 Add dhcp-ignore-clid configuration option
The idea of this option was already discussed years ago on the mailing
list:
https://dnsmasq-discuss.thekelleys.org.narkive.com/ZoFQNaGo/always-ignore-client-identifier#post4

In our production environnement, we discovered that some devices are
using 'client identifier' not unique at all, resulting on IP addresses
conflicts between several devices (we saw up to four devices using same
IP address).

The root cause is probably a buggy operating system/configuration of
decices, but this patch add a configuration workaround on server side
when fixing clients is impossible.

Signed-off-by: Charles Daymand <charles.daymand@wifirst.fr>
Signed-off-by: Florent Fourcot <florent.fourcot@wifirst.fr>
2019-10-12 22:16:40 +01:00
Simon Kelley
19b0e3bf21 Check for REFUSED and SERVFAIL replies to DNSKEY queries. 2019-10-12 21:54:37 +01:00
Simon Kelley
203ce0a081 Update to 04db1483d1 2019-10-12 21:41:20 +01:00
Simon Kelley
e3002bf1a6 Add missing dump_packet() for DNSSEC query retries. 2019-10-11 23:30:08 +01:00
Simon Kelley
04db1483d1 Fix crash on REFUSED answers to DNSSEC queries.
Some REFUSED answers to DNSSEC-originated queries would
bypass the DNSSEC code entirely, and be returned as answers
to the original query. In the process, they'd mess up datastructures
so that a retry of the original query would crash dnsmasq.
2019-10-11 23:22:17 +01:00
Petr Menšík
6fe436a448 Report error on dhcp_release
If no IPv4 address is present on given interface, the tool would not
send any request. It would not report any error at the same time. Report
error if request send failed.

Signed-off-by: Petr Mensik <pemensik@redhat.com>
2019-10-07 18:19:19 +01:00
Alin Nastac
e710c34469 Fix crash when negative SRV response over TCP gets stored in LRU cache entry.
Patch extended to receive side of pipe by SRK.
2019-09-30 15:30:26 +01:00
Simon Kelley
defd6b1d85 Fix 90d7c6b97d CAP_NET_RAW, not CAP_NET_ADMIN. 2019-09-16 23:02:12 +01:00
Simon Kelley
90d7c6b97d Keep suitable capabilities if we may bind server sockets to interface or port. 2019-09-14 21:13:03 +01:00
Simon Kelley
e24abf28a2 Fix botch in ae7a3b9d2e
Loop variable must count up from zero, now we're using it as
an array index.
2019-09-03 22:48:39 +01:00
Simon Kelley
69a0477b74 DNSSEC: unsigned RRs in the auth section are not bogus.
Even if they are in a signed zone.
2019-09-03 16:49:02 +01:00
Simon Kelley
ae7a3b9d2e DNSSEC: implement RFC-4036 para 5.3.3. rules on TTL values. 2019-09-03 14:40:47 +01:00
Brian Haley
d9f882bea2 Change dhcp_release to use default address when no IP subnet matches
Currently, dhcp_release will only send a 'fake' release
when the address given is in the same subnet as an IP
on the interface that was given.

This doesn't work in an environment where dnsmasq is
managing leases for remote subnets via a DHCP relay, as
running dhcp_release locally will just cause it to
silently exit without doing anything, leaving the lease
in the database.

Change it to use the default IP on the interface, as the
dnsmasq source code at src/dhcp.c does, if no matching subnet
IP is found, as a fall-back.  This fixes an issue we are
seeing in certain Openstack deployments where we are using
dnsmasq to provision baremetal systems in a datacenter.

While using Dbus might have seemed like an obvious solution,
because of our extensive use of network namespaces (which
Dbus doesn't support), this seemed like a better solution
than creating system.d policy files for each dnsmasq we
might spawn and using --enable-dbus=$id in order to isolate
messages to specific dnsmasq instances.

Signed-off-by: Brian Haley <haleyb.dev@gmail.com>
2019-08-30 21:21:57 +01:00
Simon Kelley
fef2f1c75e DNSSEC: Unsigned RRs in auth section proving that a DS doesn't exist are OK.
In a reply proving that a DS doesn't exist, it doesn't matter if RRs
in the auth section _other_ than NSEC/NSEC3 are not signed. We can't
set the AD flag when returning the query, but it still proves
that the DS doesn't exist for internal use.

As one of the RRs which may not be signed is the SOA record, use the
TTL of the NSEC record to cache the negative result, not one
derived from the SOA.

Thanks to Tore Anderson for spotting and diagnosing the bug.
2019-08-29 21:59:00 +01:00
Simon Kelley
5a91334985 Debian package: link against libidn2. 2019-08-23 22:31:30 +01:00
Simon Kelley
e198fe833a Compilation fix for MacOS.
Thanks to Pal Lockheart <ex@palx.org> for the original patch.
2019-08-22 23:23:29 +01:00
Simon Kelley
248efe8410 Truncate stupidly large cache sizes.
If the cache size is very large, the malloc() call will overflow
on 32 bit platforms and dnsmasq will crash. Limit to an order of
magnitude less.

Thanks to Lili Xu for spotting this.
2019-08-20 23:36:49 +01:00
Simon Kelley
dc6a57ffb8 Always force AD bit to zero in authoritative DNS answers. 2019-08-20 23:17:27 +01:00
Fabrice Fontaine
240da59f73 Makefile: fix i18n build with ubus
Commit caf4d571e6 forgot adding
ubus_libs to build_libs for all-i18n target

Fixes:
 - http://autobuild.buildroot.org/results/c0b27754b7ede024c095bdf0b3616e6f6be48c6d

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2019-08-16 16:31:41 +01:00
Simon Kelley
5a56233f53 CHANGELOG update for ab73a746a0 2019-08-14 21:53:59 +01:00
Simon Kelley
225accd235 Fix breakage of dhcp_lease_time utility. 2019-08-14 21:52:50 +01:00
Vladislav Grishenko
ab73a746a0 Fix build with libnettle 3.5 2019-08-14 21:36:52 +01:00
Simon Kelley
69bc94779c Fix memory leak in helper.c
Thanks to Xu Mingjie <xumingjie1995@outlook.com> for spotting this.
2019-08-14 20:44:50 +01:00
Jiri Slaby
3052ce208a Fix build after y2038 changes in glib.
SIOCGSTAMP is defined in linux/sockios.h, not asm/sockios.h now.
2019-07-24 17:34:48 +01:00
Simon Kelley
18e17665fd Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2019-07-24 17:20:26 +01:00
Simon Kelley
05299fdd5a Fix wrong return code from explore_rrset() with some errors. 2019-07-15 22:04:20 +01:00
Simon Kelley
7ef55691a2 Replace ash shell with dash in contrib/reverse-dns. 2019-04-08 17:17:07 +01:00
Simon Kelley
7509f94fc4 Debian startup fix. 2019-04-08 17:05:27 +01:00
Simon Kelley
343b7b4ad0 Support multiple daemon instances with systemd in Debian. 2019-04-08 16:50:13 +01:00
Jan Willem Janssen
a2b8220f4e Improved UBus supported
- aligned the handling of UBus connections with the DBus code as it
makes it a bit easier to comprehend;
- added logging to the various UBus calls to aid debugging from an
enduser point of view, but be careful to not flood the logs;
- show the (lack of) support for UBus in the configuration string.
2019-04-04 15:58:07 +01:00
Simon Kelley
5c464ef62e Allow more then one --conf-file on the command line. 2019-03-29 23:11:05 +00:00
Simon Kelley
5fc639cf9a Don't retry close() syscalls after an EINTR errors.
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2019q1/012953.html
2019-03-29 21:29:43 +00:00
Simon Kelley
7673013d23 Apply fix from c6cc455dd1 in DHCP code. 2019-03-28 22:04:10 +00:00
Jérémie Courrèges-Anglas
c6cc455dd1 Fix cmsg(3) API usage on OpenBSD
msg_controllen should be set using CMSG_SPACE() to account for padding.
RFC3542 provides more details:

  While sending an application may or may not include padding at the end
  of last ancillary data in msg_controllen and implementations must
  accept both as valid.

At least OpenBSD rejects control messages if msg_controllen doesn't
account for padding, so use CMSG_SPACE() for maximal portability.  This
is consistent with the example provided in the Linux cmsg(3) manpage.
2019-03-28 21:49:48 +00:00
Simon Kelley
1da81f7e23 CHANGELOG typo fix. 2019-03-28 13:51:11 +00:00
Simon Kelley
ae5b7e04a1 Add --shared-network DHCP configuration. 2019-03-27 22:33:28 +00:00
Simon Kelley
305ffb5ef0 Improve kernel-capability manipulation code under Linux.
Dnsmasq now fails early if a required capability is not available,
and tries not to request capabilities not required by its
configuration.
2019-03-16 18:17:17 +00:00
Simon Kelley
608aa9fcfc Support TCP fastopen on incoming and outgoing connections. 2019-03-10 22:52:54 +00:00
Dominik DL6ER
c61c7bb225 Remove redundant prototypes from dnsmasq.h
Dear Simon,

the attached patch removes three redundant prototypes from dnsmasq.h. There is no functional change.

Best regards,
Dominik

From c0b2ccfd20c4eec9d09468fdfe9b4ca8a8f8591e Mon Sep 17 00:00:00 2001
From: DL6ER <dl6er@dl6er.de>
Date: Sun, 10 Mar 2019 19:34:07 +0100
Subject: [PATCH] Remove redundant prototypes from dnsmasq.h

Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-03-10 20:31:57 +00:00
Simon Kelley
5ed82ae5f2 Remove unclear gcc-ism in conditional expression. 2019-03-05 16:38:34 +00:00
Simon Kelley
6799320edb Don't attempt to parse a sequence of hex digits without any colons as IPv6 address.
Another confusion in the heuristic dhcp-option parsing. Sigh.
2019-03-04 22:59:42 +00:00
Simon Kelley
c406fd60be Add Vcs-* fields to Debian control file. 2019-03-01 17:23:01 +00:00
Simon Kelley
5d514f22a9 Fix nodocs/nodoc confusion in Debian packaging. 2019-03-01 16:52:02 +00:00
Simon Kelley
a066aac332 Fix to credits in 162e5e0062 2019-03-01 16:18:07 +00:00
Simon Kelley
8bd28a87a2 Small error-message tweak, for clarity. 2019-03-01 15:00:12 +00:00
Simon Kelley
065e5bb0b1 More /etc/hosts linecount fixing. 2019-03-01 14:38:51 +00:00
Florent Fourcot
df6636bff6 lease: prune lease as soon as expired
We detected a performance issue on a dnsmasq running many dhcp sessions
(more than 10 000). At the end of the day, the server was only releasing
old DHCP leases but was consuming a lot of CPU.

It looks like curent dhcp pruning:
 1) it's pruning old sessions (iterate on all current leases). It's
 important to note that it's only pruning session expired since more
 than one second
 2) it's looking for next lease to expire (iterate on all current leases
 again)
 3) it launchs an alarm to catch next expiration found in step 2). This
 value can be zero for leases just expired (but not pruned).

So, for a second, dnsmasq could fall in a "prune loop" by doing:
 * Not pruning anything, since difftime() is not > 0
 * Run alarm again with zero as argument

On a server with very large number of leases and releasing often
sessions, that can waste a very big CPU time.

Signed-off-by: Florent Fourcot <florent.fourcot@wifirst.fr>
2019-02-27 21:28:32 +00:00
Sven Mueller
162e5e0062 Fix bug added in 2.80 non-terminal code which returns NODATA instead of NXDOMAIN.
Thanks to Sven Muleller and Maciej Żenczykowski for work on this.

https://bugzilla.redhat.com/show_bug.cgi?id=1674067 refers.
2019-02-27 21:17:37 +00:00
Simon Kelley
4219adeeef Fix line counting when reading /etc/hosts. 2019-02-27 20:30:21 +00:00
Brian Haley
28cfe36e1e Change read_leases() to skip invalid entries.
There's no reason to stop reading the existing lease file
when dnsmasq is started and an invalid entry is found, it
can just be ignored.  This was fallout from an Openstack
bug where the file was being written incorrectly with []
around IPv6 addresses.
2019-01-17 23:21:23 +00:00
Steven Siloti
d2d4990743 Fix missing braces in 8eac67c0a15b673c8d27002c248651b308093e4 2019-01-17 22:52:13 +00:00
Steven Siloti
18eac67c0a Fix entries in /etc/hosts disabling static leases.
It is possible for a config entry to have one address family specified by a
dhcp-host directive and the other added from /etc/hosts. This is especially
common on OpenWrt because it uses odhcpd for DHCPv6 and IPv6 leases are
imported into dnsmasq via a hosts file.

To handle this case there need to be separate *_HOSTS flags for IPv4 and IPv6.
Otherwise when the hosts file is reloaded it will clear the CONFIG_ADDR(6) flag
which was set by the dhcp-host directive.
2019-01-13 22:56:36 +00:00
Simon Kelley
f8c77edbdf Fix removal of DHCP_CLIENT_MAC options from DHCPv6 relay replies. 2019-01-10 21:58:18 +00:00
Simon Kelley
4bf62f616b Tidy cache_blockdata_free() 2019-01-10 21:54:22 +00:00
Simon Kelley
9c0d445ef4 Fix e7bfd556c0 to actually work. 2019-01-09 18:04:39 +00:00
Simon Kelley
2896e2485e Check for not(DS or DNSKEY) in is_outdated_cname_pointer()
Previous check was _for_ IPV4, IPv6 CNAME, and I missed adding SRV.
2019-01-09 15:12:34 +00:00
Simon Kelley
a90f09db4c Fix crash freeing negative SRV cache entries.
Thanks to Daniel for finding this one.
2019-01-09 15:08:16 +00:00
Simon Kelley
5b99eae59d Cache SRV records.
Inpsired by a patch from Jeremy Allison, but completely re-rolled
by srk. All bugs are mine.
2019-01-06 23:09:50 +00:00
Christian Weiske
2daca52b80 Fix typo in ra-param man page section. 2019-01-03 20:10:14 +00:00
Simon Kelley
2c594732eb File logic bug in cache-marshalling code. Introduced a couple of commits back. 2019-01-03 13:42:03 +00:00
Simon Kelley
cc921df9ce Remove nested struct/union in cache records and all_addr. 2019-01-02 22:48:59 +00:00
Simon Kelley
ab194ed7ca Futher address union tidying.
Pass DNSKEY and DS data into cache_insert via the address argument,
now these data types are included in struct all_addr.
2019-01-01 01:35:30 +00:00
Simon Kelley
65a01b71bb Tidy address-union handling: move class into explicit argument.
This moves the class argument to cache-insert into an argument,
rather then overloading a union in the address argument. Note that
tha class is NOT stored in the cache other than for DS/DNSKEY entries,
so must always be C_IN except for these. The data-extraction code
ensures this as it only attempts to cache C_IN class records.
2018-12-31 23:56:33 +00:00
Simon Kelley
bde46476ee Tidy all_addr union, merge log and rcode fields. 2018-12-31 23:28:24 +00:00
Simon Kelley
e7bfd556c0 Alter DHCP address selection after DECLINE in consec-addr mode.
Avoid offering the same address after a recieving a DECLINE message
to stop an infinite protocol loop. This has long been done in
default address allocation mode: this adds similar behaviour
when allocaing addresses consecutively.
2018-12-31 20:51:15 +00:00
Kevin Darbyshire-Bryant
b683cf37f9 build failure on master with NO_DHCPv6 and fix....
Hi Simon,

master has a build error when building without HAVE_DHCPv6

option.c: In function 'dhcp_context_free':
option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface'
       free(ctx->template_interface);

Sadly, need to put in a little conditional compilation ifdef'erey

Simplest patch in the world attached

Cheers,

Kevin D-B

012C ACB2 28C6 C53E 9775  9123 B3A2 389B 9DE2 334A

From 061eb8599636bb360e0b7fa5986935b86db39497 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Mon, 10 Dec 2018 10:07:33 +0000
Subject: [PATCH] option: fix non DHCPv6 build error

option.c: In function 'dhcp_context_free':
option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface'
       free(ctx->template_interface);
		^~

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-12-16 21:35:35 +00:00
Kevin Darbyshire-Bryant
3becf468ba fix ipv6 ipset bug in master
Hi Simon,

Another one fallen out of the openwrt tree shake :-)

ipv6 ipset addresses weren’t being set correctly.  patch attached

Cheers,

Kevin D-B

012C ACB2 28C6 C53E 9775  9123 B3A2 389B 9DE2 334A
From b50fc0491e374186f982b019f293379955afd203 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Wed, 12 Dec 2018 11:35:12 +0000
Subject: [PATCH] ipset fix ternary order swap

ee87504 Remove ability to compile without IPv6 support introduced a
ternary operator for ip address size.  Unfortunately the true/false
order was incorrect which meant ipv6 ipset addresses were added
incorrectly.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-12-16 21:32:05 +00:00
Petr Menšík
137e9f878f Fix option parsing errors introduced in 59e470381f
Thanks to Kevin Darbyshire-Bryant for spotting this.
2018-12-16 21:25:29 +00:00
Simon Kelley
07e25da5bf Treat DS and DNSKEY queries being forwarded the same as those locally originated.
The queries will not be forwarded to a server for a domain, unless
there's a trust anchor provided for that domain. This allows, especially,
suitable proof of non-existance for DS records to come from
the parent domain for domains which are not signed.
2018-12-16 18:21:58 +00:00
Simon Kelley
d46ee724fc Bump Debian version. 2018-11-02 23:10:00 +00:00
Petr Menšík
59e470381f Free config file values on parsing errors.
This time I have a little bit more controversal patches. But I think
still useful. They fixes memory leaks that might occur in some cases.
Most dnsmasq errors is fatal, so it does not matter. But some are not.
Some parts are reloaded on SIGHUP signal, so it might leak more than once.

Some example when it changes the failures. Use dhcp-options file with
this content:

tag:error,vendor:redhat
option:ntp-server,1.2.3.4.5
option6:ntp-server,[:::]

Is not fatal and dnsmasq will start. On each reload command, it would
leak some memory. I validated it using valgrind --leak-check=full
dnsmasq -d. This patch fixes it. It introduces something that might be
considered constructor and destructor of selected structures.
2018-11-02 22:39:39 +00:00
Simon Kelley
48d12f14c9 Remove the NO_FORK compile-time option, and support for uclinux.
In an era where everything has an MMU, this looks like
an anachronism, and it adds to (Ok, multiplies!) the
combinatorial explosion of compile-time options.
2018-11-02 21:55:04 +00:00
Simon Kelley
122392e0b3 Revert 68f6312d4b
The above is intended to increase robustness, but actually does the
opposite. The problem is that by ignoring SERVFAIL messages and hoping
for a better answer from another of the servers we've forwarded to,
we become vulnerable in the case that one or more of the configured
servers is down or not responding.

Consider the case that a domain is indeed BOGUS, and we've send the
query to n servers. With 68f6312d4b
we ignore the first n-1 SERVFAIL replies, and only return the
final n'th answer to the client. Now, if one of the servers we are
forwarding to is down, then we won't get all n replies, and the
client will never get an answer! This is a far more likely scenario
than a temporary SERVFAIL from only one of a set of notionally identical
servers, so, on the ground of robustness, we have to believe
any SERVFAIL answers we get, and return them to the client.

The client could be using the same recursive servers we are,
so it should, in theory, retry on SERVFAIL anyway.
2018-10-31 22:24:02 +00:00
Simon Kelley
3a5a84cdd1 Fix Makefile lines generating UBUS linker config.
If arg2 of pkg-wrapper is "--copy", then arg1 is NOT the name of
the package manager (--copy doesn't invoke it) it's a secondary
config string that inhibts the copy if found. This patch allows that
to be the empty string, for unconditional copy, and modifies the
ubus linker config to use it. It worked by coincidence before, because
there was no config string called "pkg-config".
2018-10-31 21:30:13 +00:00
Petr Menšík
24b87607c1 Do not rely on dead code elimination, use array instead.
Make options bits derived from size and count. Use size of option bits
and last supported bit in computation. No new change would be required
when new options are added. Just change OPT_LAST constant.
2018-10-24 22:30:18 +01:00
Simon Kelley
6f7812d97b Fix spurious AD flags in some DNS replies from local config. 2018-10-23 23:54:44 +01:00
Simon Kelley
cbb5b17ad8 Fix logging in cf5984367b 2018-10-23 23:45:57 +01:00
Vladislav Grishenko
cf5984367b Don't forward *.bind/*.server queries upstream
Chaos .bind and .server (RFC4892) zones are local, therefore
don't forward queries upstream to avoid mixing with supported
locally and false replies with NO_ID enabled.
2018-10-23 23:08:15 +01:00
Simon Kelley
ee8750451b Remove ability to compile without IPv6 support.
This was the source of a large number of #ifdefs, originally
included for use with old embedded libc versions. I'm
sure no-one wants or needs IPv6-free code these days, so this
is a move towards more maintainable code.
2018-10-23 22:10:17 +01:00
Simon Kelley
a220545c42 Ensure that AD bit is reset on answers from --address=/<domain>/<address>. 2018-10-22 18:21:48 +01:00
Simon Kelley
a799ca0c63 Impove cache behaviour for TCP connections.
For ease of implementaion, dnsmasq has always forked a new process to
handle each incoming TCP connection. A side-effect of this is that any
DNS queries answered from TCP connections are not cached: when TCP
connections were rare, this was not a problem.  With the coming of
DNSSEC, it's now the case that some DNSSEC queries have answers which
spill to TCP, and if, for instance, this applies to the keys for the
root then those never get cached, and performance is very bad.  This
fix passes cache entries back from the TCP child process to the main
server process, and fixes the problem.
2018-10-18 19:35:29 +01:00
Simon Kelley
91421cb757 Fix compiler warning. 2018-10-18 19:21:55 +01:00
Martin Schiller
53792c934c fix typo
it was introduced by commit 08933475ab

Signed-off-by: Martin Schiller <ms@dev.tdt.de>
2018-10-08 14:26:04 +01:00
Conrad Kostecki
df071825f2 Update German translation. 2018-10-06 23:55:12 +01:00
Simon Kelley
e1791f36ea Fix logging of DNSSEC queries in TCP mode. Destination server address was misleading. 2018-10-06 23:23:23 +01:00
Simon Kelley
0fdf3c1f61 Fix dhcp-match-name to match hostname, not complete FQDN.
Also do name matching for DHCPv6.
2018-10-05 23:35:54 +01:00
Simon Kelley
ee1df06aab Tweak strategy for confirming SLAAC addresses.
The code which conirms possible SLAAC addresses associated with
hosts known from DHCPv4 addresses keeps trying at longer and longer
intervals essentially forever, EXCEPT if sending an ICMP ping results
in a HOSTUNREACH error, which terminates the process immediately.

It turns out that this is too drastic. Routing changes associated
with addressing changes can cause temporary HOSTUNREACH problems,
even when an address has not gone forever. Therefore continue
trying in the face of HOSTUNREACH for the first part of the
process. HOSTUNREACH errors will still terminate the process
after it reaches the slow tail of retries.

Thanks to Andrey Vakhitov for help diagnosing this.
2018-10-05 22:22:41 +01:00
Simon Kelley
1e87eba424 Clarify manpage for --auth-sec-servers 2018-10-05 16:49:31 +01:00
Simon Kelley
08933475ab Make interface spec optional in --auth-server.
But make auth-server required when any auth-zones are defined.

The "glue record" field in auth-server is needed to synthesise
SOA and NS records in auth zones, so the --auth-server has to
be specified. If makes sense, however to define one or more
auth-zones that appear within the normal recursive DNS service
without actually acting as an authoritative DNS server on
any interface. Hence making the interface field optional.
2018-10-05 16:44:05 +01:00
Simon Kelley
7cbf497da4 Example config file fix for CERT Vulnerability VU#598349. 2018-09-26 18:04:38 +01:00
Simon Kelley
3a610a007f Finesse allocation of memory for "struct crec" cache entries.
These normally have enough space for a name of up to SMALLDNAME characters.
When used to hold /etc/hosts entries, they are allocated with just enough
bytes for the name held. When used to hold other configured stuff, (CNAMES
DS records. DHCP names etc), the name is replaced by a pointer to a string
held elsewhere, and F_NAMEP set. Hence only enough space to hold a char *
is needed, rather than SMALLDNAME bytes.
2018-09-26 16:50:35 +01:00
Simon Kelley
48b090cb5c Fix b6f926fbef to not SEGV on startup (rarely).
Many thanks to Kristian Evensen  for finding and diagnosing this.

We can't copy the whole of a crec structure in make_non_terminals, since
crec structures allocated to represent /etc/hosts entries are allocated with
just enough space for the actual name they contain, not the full
SMALLDNAME bytes declared in struct crec. Using structure copy therefore
copies beyond the end of the allocated source and, just occaisionally,
into unmapped memory, resulting in a SEGV.

Since the crecs we're making here always have F_NAMEP set, we're not
interested in copying the name field from the source anyway, we use the
namep part of the union and set it to point some way into the name
of the source crec to get the super-domain that we're representing.

The fix is therefore to copy the relevant fields of the crec, rather
than copying the whole and overwriting.
2018-09-26 12:53:59 +01:00
Simon Kelley
4139298d28 Change behavior when RD bit unset in queries.
Change anti cache-snooping behaviour with queries with the
recursion-desired bit unset. Instead to returning SERVFAIL, we
now always forward, and never answer from the cache. This
allows "dig +trace" command to work.
2018-09-19 22:27:11 +01:00
Simon Kelley
51cc10fa54 Add warning about 0.0.0.0 and :: addresses to man page. 2018-09-19 12:49:43 +01:00
Simon Kelley
ea6cc33804 Handle memory allocation failure in make_non_terminals()
Thanks to Kristian Evensen for spotting the problem.
2018-09-18 23:21:17 +01:00
Simon Kelley
ad03967ee4 Add debian/tmpfiles.conf 2018-09-17 23:54:13 +01:00
Simon Kelley
f4fd07d303 Debian bugfix. 2018-09-17 23:45:32 +01:00
Simon Kelley
e3c08a34a7 Debian packaging fix. (restorecon) 2018-09-17 23:20:00 +01:00
Simon Kelley
118011fe2b Debian packaging fix. (tmpfiles.d) 2018-09-17 23:15:37 +01:00
Simon Kelley
af3bd07355 Man page typo. 2018-09-08 15:08:22 +01:00
Simon Kelley
d68209978a Picky changes to 47b45b2967 2018-09-04 23:00:11 +01:00
Petr Menšík
47b45b2967 Fix lengths of interface names
Use helper function similar to copy correctly limited names into
buffers.
2018-09-04 22:47:58 +01:00
Petr Menšík
2b38e3823b Minor improvements in lease-tools
Limit max interface name to fit into buffer.
Make sure pointer have to be always positive.
Close socket after received reply.
2018-09-04 22:36:23 +01:00
Petr Menšík
282eab7952 Mark die function as never returning
Improves static analysis output and reduces false positives.
2018-09-04 22:32:51 +01:00
Simon Kelley
c346f61535 Handle ANY queries in context of da8b6517de 2018-09-04 21:14:18 +01:00
Simon Kelley
03212e533b Manpage typo. 2018-09-04 17:52:28 +01:00
Simon Kelley
da8b6517de Implement --address=/example.com/#
as (more efficient) syntactic sugar for --address=/example.com/0.0.0.0 and --address=/example.com/::
2018-09-03 23:18:36 +01:00
Simon Kelley
c5db8f93ec Tidy 7f876b64c22b2b18412e2e3d8506ee33e42db7c 2018-08-23 23:06:00 +01:00
Simon Kelley
974a6d087a Add --caa-record 2018-08-23 23:01:16 +01:00
Simon Kelley
b758b67c37 Improve logging of RRs from --dns-rr. 2018-08-23 21:41:23 +01:00
Simon Kelley
9bafdc62b7 Tidy up file parsing code. 2018-08-21 22:53:38 +01:00
Simon Kelley
97f876b64c Properly deal with unaligned addresses in DHCPv6 packets.
Thanks to Vladislav Grishenko for spotting this.
2018-08-21 22:06:36 +01:00
Simon Kelley
cbfbd173c4 Fix broken DNSSEC records in previous. 2018-08-21 18:25:18 +01:00
Simon Kelley
b6f926fbef Don't return NXDOMAIN to empty non-terminals.
When a record is defined locally, eg an A record for one.two.example then
we already know that if we forward, eg an AAAA query for one.two.example,
and get back NXDOMAIN, then we need to alter that to NODATA. This is handled
by  check_for_local_domain(). But, if we forward two.example, because
one.two.example exists, then the answer to two.example should also be
a NODATA.

For most local records this is easy, just to substring matching.
for A, AAAA and CNAME records that are in the cache, it's more difficult.
The cache has no efficient way to find such records. The fix is to
insert empty (none of F_IPV4, F_IPV6 F_CNAME set) records for each
non-terminal.

The same considerations apply in auth mode, and the same basic mechanism
is used there too.
2018-08-21 17:46:52 +01:00
Simon Kelley
c822620967 Add --dhcp-name-match 2018-08-08 23:46:03 +01:00
Simon Kelley
397c0502e2 Handle case of --auth-zone but no --auth-server. 2018-08-04 21:04:59 +01:00
Simon Kelley
1682d15a74 Add missing EDNS0 section.
EDNS0 section missing in replies to EDNS0-containing queries where
answer generated from --local=/<domain>/
2018-08-03 20:38:18 +01:00
Simon Kelley
dd33e98da0 Fix crash parsing a --synth-domain with no prefix.
Problem introduced in 2.79/6b2b564ac34cb3c862f168e6b1457f9f0b9ca69c
2018-07-30 14:55:39 +01:00
Simon Kelley
c16d966ad3 Add copyright to src/metrics.h 2018-07-29 22:31:02 +01:00
Simon Kelley
1dfed16071 Remove C99 only code. 2018-07-29 22:16:41 +01:00
Simon Kelley
6f835ed6c8 Format fixes - ubus.c 2018-07-29 22:15:36 +01:00
Kevin Darbyshire-Bryant
9d6fd1727e dnsmasq.c fix OPT_UBUS option usage
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-07-29 22:11:12 +01:00
Simon Kelley
8c1b6a5fd7 New metrics and ubus files. 2018-07-21 22:12:32 +01:00
Julian Kornberger
8dcdb33be9 Add --enable-ubus option. 2018-07-21 22:11:08 +01:00
Julian Kornberger
aba8bbb6e3 Add collection of metrics
Data can be retreived via D-Bus und U-Bus
2018-07-21 21:55:08 +01:00
Julian Kornberger
caf4d571e6 Add OpenWRT ubus patch
Originally written by John Crispin <john@phrozen.org>
2018-07-21 21:45:03 +01:00
Simon Kelley
3b6eb197a8 Log DNSSEC trust anchors at startup. 2018-07-20 21:23:56 +01:00
Simon Kelley
f3e57877ed Trivial comment change. 2018-07-20 21:10:48 +01:00
Simon Kelley
c851c695db Log failure to confirm an address in DHCPv6. 2018-07-20 17:35:24 +01:00
Simon Kelley
a3bd7e73d3 Fix missing fatal errors when parsing some command-line/config options. 2018-07-19 22:00:08 +01:00
Olivier Gayot
ab5ceaf74a Document the --help option in the french manual
The option was already described in the original manual page but was not
replicated in the french translation.

Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
2018-07-19 21:17:06 +01:00
Olivier Gayot
1f2f69d4f6 Fix recurrent minor spelling mistake in french manual
The use of "peut-être" should be spelled "peut être" (without the
hyphen) unless it can be replaced by "sans doute".

It is roughly the same difference between "maybe" and "may be".

As for "doit-être", it should always be spelled "doit être".

Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
2018-07-19 21:16:41 +01:00
Olivier Gayot
f361b39dea Fix some mistakes in french translation of the manual
Various typos were present along with spelling mistakes and grammar
errors. Some sentences were missing a few words to be easily
understandable.

Many of them probably remain though.

Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
2018-07-19 21:16:04 +01:00
Simon Kelley
eb1fe15ca8 When replacing cache entries, preserve CNAMES which target them.
When inserting new cache records, we first delete existing records
of the same name/type, to maintain consistency. This has the side effect
of deleting any CNAMES which have the records as target. So

cname1.example CNAME record.example
cname2.example CNAME record.example

looking up cname2.example will push it into the cache, and also
push record.example. Doing that deletes any cache of cname1.example.

This changeset avoids that problem by making sure that when
deleting record.example, and re-insterting it (with the same name -important),
it uses the same struct crec, with the same uid. This preserves the existing cnames.
2018-07-18 20:59:52 +01:00
Simon Kelley
45d8a2435e Introduce UID_NONE value, for cache records which are not the target of a CNAME. 2018-07-17 21:01:14 +01:00
Simon Kelley
706d84fd10 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2018-07-16 18:07:15 +01:00
Simon Kelley
a997ca0da0 Fix sometimes missing DNSSEC RRs when DNSSEC validation not enabled.
Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
of of having DNSSEC validation compiled in or enabled.

The thing to understand here is that the cache does not store all the
DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
to determine the set of DNSSEC RRs required in an answer. Therefore if
the client wants the DNSSEC RRs, the query can not be answered from
the cache. When DNSSEC validation is enabled, any query with the
do-bit set is never answered from the cache, unless the domain is
known not to be signed: the query is always forwarded. This ensures
that the DNSEC RRs are included.

The same thing should be true when DNSSEC validation is not enabled,
but there's a bug in the logic.

line 1666 of src/rfc1035.c looks like this

 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))

{ ...answer from cache ... }

So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
then the query is answered, and if the domain is known not to be
signed, the query is answered.

Unfortunately, if DNSSEC validation is not turned on then the
F_DNSSECOK bit is not valid, and it's always zero, so the question
always gets answered from the cache, even when the do-bit is set.

This code should look like that at line 1468, dealing with PTR queries

  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
      !do_bit ||
      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))

where the F_DNSSECOK bit is only used when validation is enabled.
2018-06-29 14:39:41 +01:00
Peter Pöschl
9268b5d677 Man page: uniform formatting style for options.
* Always use the long option form, except when options are introduced.
* Render options in bold, with '--' prefix.
2018-06-12 17:04:54 +01:00
Paul Maddock
51e4eeeb04 Fix address-dependent domains for IPv6.
Thanks to Paul Maddock for spotting this.
It seems to have been broken forever.
2018-06-12 16:37:40 +01:00
Simon Kelley
05ff659a3c Fix stupid infinite loop introduced by preceding commit. 2018-06-12 16:03:09 +01:00
Simon Kelley
db0f488ea8 Handle some corner cases in RA contructed interfaces with addresses changing interface.
Thanks to Vladislav Grishenko for work on this.
2018-06-07 21:37:02 +01:00
Geert Stappers
7dcca6c622 Warn about the impact of cache-size on performance. 2018-06-02 18:54:04 +01:00
Simon Kelley
090856c7e6 Allow zone transfer in authoritative mode whenever auth-peer is specified. 2018-06-02 18:37:07 +01:00
Simon Kelley
cc5cc8f1e0 Sane error message when pcap file header is wrong. 2018-06-02 14:45:17 +01:00
Simon Kelley
c488b68e75 Handle standard and contructed dhcp-ranges on the same interface. 2018-06-02 13:06:00 +01:00
Simon Kelley
1f1873aadd Log warning on very large cachesize config, instead of truncating it. 2018-05-11 23:38:23 +01:00
Maarten de Vries
0a496f059c Do unsolicited RAs for interfaces which appear after dnsmasq startup.
I noticed that dnsmasq often wasn't sending any unsolicited RAs for me.

This turned out to happen when the interface (a bridge interface) wasn't
created yet at the time dnsmasq started. When dnsmasq is started after
the interface is created, it sends RAs as expected. I assume this also
extends to other types of virtual interfaces that are created after
dnsmasq starts.

Digging into the source, it seems to be caused by a missing call to
ra_start_unsolicited for non-template contexts in construct_worker from
src/dhcp6.c. The attached patch adds that call, but only if the
interface index or address changed to prevent doing fast RAs for no reason.

I tested it on my own server and it appears to work as expected. When
the interface is created and configured, dnsmasq does fast RAs for a
while and then settles into slow RAs.
2018-05-11 23:20:58 +01:00
Simon Kelley
e27825b0ef Fix logging in previous. 2018-05-11 17:20:47 +01:00
Simon Kelley
1f60a18ea1 Retry SERVFAIL DNSSEC queries to a different server, if possible. 2018-05-11 16:44:16 +01:00
Simon Kelley
a0088e8364 Handle query retry on REFUSED or SERVFAIL for DNSSEC-generated queries. 2018-05-10 21:43:14 +01:00
Simon Kelley
34e26e14c5 Retry query to other servers on receipt of SERVFAIL rcode. 2018-05-10 20:54:57 +01:00
Simon Kelley
6b17335209 Add packet-dump debugging facility. 2018-05-08 18:32:14 +01:00
Simon Kelley
07ed585c38 Add logging for DNS error returns from upstream and local configuration. 2018-05-04 21:52:22 +01:00
Simon Kelley
0669ee7a69 Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip are set. 2018-05-04 16:46:24 +01:00
Simon Kelley
f84e674d8a Be persistent with broken-upstream-DNSSEC warnings. 2018-05-04 16:29:57 +01:00
Simon Kelley
7f0084316a Handle DNSSEC-unaware upstream servers better. 2018-04-15 20:01:49 +01:00
Simon Kelley
a6918530ce Change default for dnssec-check-unsigned. 2018-04-15 16:20:52 +01:00
Simon Kelley
4e72fec660 Fix DNSSEC without dnssec-check-unsigned.
An oversight meant that non-existance checking was being done
anyway.

(Should probably alter the default for this.)
2018-04-11 22:49:31 +01:00
Simon Kelley
4441cf762c Fix DNS server fd garbage collection.
If we're talking to upstream servers from a fixed port, specified by query-port
we create the fds to do this once, before dropping root, so that ports <1024 can be used.

But we call check_servers() before reading /etc/resolv.conf, so if the only servers
are in resolv.conf, at that point there will be no servers, and the fds get garbage
collected away, only to be recreated (but without root) after we read /etc/resolv.conf

Make pre-allocated server fds immortal, to avoid this problem.
2018-04-10 21:39:54 +01:00
Simon Kelley
e83915d10d Set V6ONLY on DNS upstream socket.
If query-port is set, we create sockets bound to the wildcard address and the query port for
IPv4 and IPv6, but the IPv6 one fails, because is covers IPv4 as well, and an IPv4 socket
already exists (it gets created first). Set V6ONLY to avoid this.
2018-04-10 21:27:26 +01:00
Kevin Darbyshire-Bryant
6d37924b86 Makefile: Stop creating '-d' directory
Install-common section was creating superfluous '-d' directory in build
location.

Split the directory creation into individual install commands to cope
with cross platform differences of interpreting subsequent '-d'
arguments.  e.g. GNU appears to be fine.  Apple creates the stray
directory.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-04-07 23:00:56 +01:00
Simon Kelley
f3d7974e86 Fixed bug number in changelog s/833596/883596/ 2018-03-26 13:23:59 +01:00
Simon Kelley
734d53176f Add RFC4039 rapid commit support. 2018-03-23 23:09:53 +00:00
Simon Kelley
9a7be47614 Add lintian override in Debian package. 2018-03-23 20:45:53 +00:00
Simon Kelley
26e27d0015 Symbolic link for /usr/share/doc/dnsmasq-base-lua in Debian package. 2018-03-18 17:29:12 +00:00
Simon Kelley
94b6878821 Tidy crypto.c of old library compat. Now need libnettle 3. 2018-03-17 18:39:23 +00:00
Simon Kelley
8b96552f0d Fix compiler warning. 2018-03-10 20:44:17 +00:00
Simon Kelley
ae290659de Fix debian/changelog syntax. 2018-03-10 20:28:32 +00:00
Simon Kelley
6b2b564ac3 Enhance --synth-domain to allow names with sequential integers. 2018-03-10 20:25:57 +00:00
Simon Kelley
4f7bb57e97 Fix deletion of dhcp-options from inotify dynamic files.
These were not deleted except in the case that a dhcp-optsfile
option was coincidentally provided.
2018-03-08 18:47:08 +00:00
Petr Menšík
56f0623930 Allow trailing dot in CNAME.
I got reported bug in Fedora [1], that cname is broken in new releases.
At first I though this was false report, but there is still new
regression in cname handling.

Before, it accepted alias with trailing dot. Not it would accept only
target, but not alias.

cname=alias.,target

is no longer valid. The issue is it will count size to skip after
canonicalize. If that ignores trailing dot, next name would be "". And
that is invalid and refused, dnsmasq refuses to start.

I also think that any whitespace like tab should be possible after
comma. So this fixes also 30858e3b9b.
2018-03-06 23:13:32 +00:00
Simon Kelley
f3223fbff6 Fix nettle_hash() function to avoid ABI incompatibilities.
The way of accessing the list of available hashes on nettle was
vulnerable to breaking if the version of libnettle in use was
different to the version dnsmasq was compiled against.
Change to a new system if libnettle >= 3.4 is in use.
Older versions if nettle are still OK, once 3.4 is reached,
the ABi problem is fixed. Thanks to Petr Menšík for clues on this.
2018-03-06 22:55:36 +00:00
Simon Kelley
4c4f4c2649 Debian dependency tweaking for new dnsmasq-base-lua package. 2018-02-16 22:43:29 +00:00
Ville Skyttä
773af304ea Man page typo fix. 2018-02-16 21:47:55 +00:00
Simon Kelley
4cc944b0d6 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2018-02-16 21:30:21 +00:00
Simon Kelley
87e00feb01 Compiler warning fixes. 2018-02-16 21:29:32 +00:00
Simon Kelley
e7a4af8903 Compiler warning fixes. 2018-02-16 21:27:35 +00:00
Simon Kelley
2d69d6146d Add liblua-dev to Debian build-depends. 2018-02-16 21:11:17 +00:00
Simon Kelley
30e4a9441e Debian package: add dnsmasq-base-lua binary package. 2018-02-16 19:56:56 +00:00
Simon Kelley
232a8f3569 Merge messages for release. 2018-02-14 23:02:34 +00:00
Simon Kelley
1721453d51 Remove special handling of A-for-A queries. 2018-02-14 22:56:09 +00:00
yiwenchen
499d8dde2b Fix boundary for test introduced in 3e3f1029c9ec6c63e430ff51063a6301d4b2262
This fixes breakage of  DHCPv6 relay.
2018-02-14 22:26:54 +00:00
Andy Hawkins
6f1cbfd000 Fix debian/readme typo. 2018-02-14 21:35:56 +00:00
Andy Hawkins
55ecde7f1b Inotify: Ignore backup files created by editors
Use strlen to determine the length of the filename returned by
inotify, as in->len refers to the length of the buffer containing
the name, not the length of the name itself.

http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2018q1/011950.html

Signed-off-by: Andy Hawkins <andy@gently.org.uk>

Patch further modified by simon@thekelleys.org to avoid
out-of-bounds array access with an empty string, call strlen once,
and reverse order of filename verifcation and resolv-file test.
2018-02-14 18:36:47 +00:00
Simon Kelley
6b54d69a85 Make failure to chown() pidfile a warning. 2018-02-08 21:32:16 +00:00
Simon Kelley
246a31cd73 Change ownership of pid file, to keep systemd happy. 2018-02-06 17:27:55 +00:00
Simon Kelley
83e4b73596 Remove confusion between --user and --script-user. 2018-02-06 16:57:15 +00:00
Simon Kelley
6340ca734f Tweak heuristic for initial DNSSEC memory allocation. 2018-01-30 21:39:01 +00:00
Simon Kelley
baf553db0c Default min-port to 1024 to avoid reserved ports. 2018-01-29 23:04:06 +00:00
Kurt H Maier
486bcd5a7b Simplify and correct bindtodevice(). 2018-01-26 15:10:59 +00:00
Simon Kelley
be9a74d2f8 Close Debian bug for CVE-2017-15107. 2018-01-26 14:36:32 +00:00
Leon M. George
ffcbc0f011 Example config typo fixes. 2018-01-26 13:17:41 +00:00
Simon Kelley
a969ba6e2a Special case NSEC processing for root DS record, to avoid spurious BOGUS. 2018-01-20 23:08:38 +00:00
Simon Kelley
f1781728af Add homepage to Debian control file. 2018-01-20 22:18:54 +00:00
Simon Kelley
cd7df612b1 Fix DNSSEC validation errors introduced in 4fe6744a22 2018-01-20 00:10:55 +00:00
Simon Kelley
c1a4e257a3 Try to be a little more clever at falling back to smaller DNS packet sizes. 2018-01-19 22:00:05 +00:00
Simon Kelley
4fe6744a22 DNSSEC fix for wildcard NSEC records. CVE-2017-15107 applies.
It's OK for NSEC records to be expanded from wildcards,
but in that case, the proof of non-existence is only valid
starting at the wildcard name, *.<domain> NOT the name expanded
from the wildcard. Without this check it's possible for an
attacker to craft an NSEC which wrongly proves non-existence
in a domain which includes a wildcard for NSEC.
2018-01-19 12:39:46 +00:00
Neil Jerram
3bd4c47f31 Remove limit on length of command-line options. 2018-01-18 22:49:38 +00:00
Artem Poloznikov
98196c4931 Typo fix. 2018-01-18 22:14:26 +00:00
Simon Kelley
22cd860124 Allow more than one --bridge-interface option to refer to an interface. 2018-01-14 22:57:14 +00:00
Simon Kelley
3c973ad92d Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC time validation. 2018-01-14 21:40:56 +00:00
Ville Skyttä
faaf306a63 Spelling fixes. 2018-01-14 17:32:52 +00:00
Geert Stappers
c7e6aea81b Change references to gPXE to iPXE.
Development of EtherBoot gPXE was always development
of iPXE core developer Michael Brown.

http://git.etherboot.org/?p=gpxe.git was last updated in 2011
https://git.ipxe.org/ipxe.git is well alive

This  s/gPXE/iPXE/ reflects that.

Signed-off-by: Geert Stappers <stappers@stappers.nl>
2018-01-13 17:56:37 +00:00
Simon Kelley
e541245987 Handle duplicate RRs in DNSSEC validation.
RFC 4034 says:
  [RFC2181] specifies that an RRset is not allowed to contain duplicate
  records (multiple RRs with the same owner name, class, type, and
  RDATA).  Therefore, if an implementation detects duplicate RRs when
  putting the RRset in canonical form, it MUST treat this as a protocol
  error.  If the implementation chooses to handle this protocol error
  in the spirit of the robustness principle (being liberal in what it
  accepts), it MUST remove all but one of the duplicate RR(s) for the
  purposes of calculating the canonical form of the RRset.

We chose to handle this robustly, having found at least one recursive
server in the wild which returns duplicate NSEC records in the AUTHORITY
section of an answer generated from a wildcard record. sort_rrset() is
therefore modified to delete duplicate RRs which are detected almost
for free during the bubble-sort process.

Thanks to Toralf Förster for helping to diagnose this problem.
2018-01-06 22:16:31 +00:00
Simon Kelley
84a01bee10 Bump year in Debian copyright notice. 2018-01-03 15:16:09 +00:00
Simon Kelley
d1ced3ae38 Update copyrights to 2018. 2018-01-01 22:18:03 +00:00
Simon Kelley
a6cee69af4 Fix exit code from dhcp_release6. 2017-12-14 22:40:48 +00:00
Simon Kelley
0039920ab6 Severely fix code formating of contrib/lease-tools/dhcp_release6.c 2017-12-14 22:29:31 +00:00
Simon Kelley
39d8550a80 Run Debian startup regex in "C" locale. 2017-12-14 21:23:34 +00:00
Simon Kelley
ef3d137a64 Fix infinite retries in strict-order mode.
If all configured dns servers return refused in
 response to a query; dnsmasq will end up in an infinite loop
 retransmitting the dns query resulting into high CPU load.
 Problem is caused by the dns refuse retransmission logic which does
 not check for the end of a dns server list iteration in strict mode.
 Having one configured dns server returning a refused reply easily
 triggers this problem in strict order mode. This was introduced in
 9396752c11

 Thanks to Hans Dedecker <dedeckeh@gmail.com> for spotting this
 and the initial patch.
2017-12-05 22:37:29 +00:00
Simon Kelley
8c707e1e37 Make 373e917389 compile without DNSSEC. 2017-12-05 22:28:10 +00:00
Simon Kelley
373e917389 Fix a6004d7f17 to cope with >256 RRs in answer section. 2017-12-01 22:40:56 +00:00
Josh Soref
74f0f9a042 Commment language tweaks. 2017-12-01 21:38:27 +00:00
李三0159
ed6bdb0967 Man page typos. 2017-11-30 16:47:01 +00:00
Simon Kelley
c88af046b7 Modify doc.html to mention git-over-http is now available. 2017-11-15 21:23:43 +00:00
Dr. Markus Waldeck
ae0187d454 Fix trust-anchor regexp in Debian init script. 2017-11-07 22:53:06 +00:00
Simon Kelley
0c50e3ddc8 Bump version in Debian package. 2017-11-07 22:49:20 +00:00
Petr Menšík
075366ad6e Open inotify socket only when used.
Some of our Openstack users run quite large number of dnsmasq instances
on single host. They started hitting default limit of inotify socket
number on single system after upgrade to more recent version. System
defaults of sysctl fs.inotify.max_user_instances is 128. They reached
limit of 116 dnsmasq instances, then more instances failed to start.

I was surprised they have any use case for such high number of
instances. They use one dnsmasq for one virtual network.

I found simple way to avoid hitting low system limit. They do not use
resolv.conf for name server configuration or any dhcp hosts or options
directory. Created inotify socket is never used in that case. Simple
patch attached.

I know we can raise inotify system limit. I think better is to not waste
resources that are left unused.
2017-11-05 16:05:39 +00:00
Simon Kelley
8e8b2d6f63 Release notes update. 2017-10-30 23:21:52 +00:00
Simon Kelley
087eb76140 Always return a SERVFAIL response to DNS queries with RD=0.
Unless we are acting in authoritative mode, obviously.

To do otherwise may allows cache snooping, see.
http://cs.unc.edu/~fabian/course_papers/cache_snooping.pdf
2017-10-30 23:16:54 +00:00
Simon Kelley
ebedcbaeb8 Typo in printf format string added in 22dee512f3 2017-10-29 20:54:17 +00:00
Simon Kelley
0954a977c9 Remove RSA/MD5 DNSSEC algorithm.
This is set to status DoNotImplement in RFC 6944.
2017-10-27 23:26:51 +01:00
Simon Kelley
b77efc1948 Tidy DNSSEC algorithm table use. 2017-10-27 23:23:53 +01:00
Simon Kelley
3b0cb34710 Fix manpage which said ZSK but meant KSK. 2017-10-27 22:54:35 +01:00
Simon Kelley
aa6f832d61 Add a few DNS RRs to the table. 2017-10-27 22:52:26 +01:00
Simon Kelley
ad9c6f06c5 Add support for Ed25519 DNSSEC signature algorithm. 2017-10-27 22:13:49 +01:00
Simon Kelley
a6004d7f17 Fix caching logic for validated answers.
The current logic is naive in the case that there is more than
one RRset in an answer (Typically, when a non-CNAME query is answered
by one or more CNAME RRs, and then then an answer RRset.)

If all the RRsets validate, then they are cached and marked as validated,
but if any RRset doesn't validate, then the AD flag is not set (good) and
ALL the RRsets are cached marked as not validated.

This breaks when, eg, the answer contains a validated CNAME, pointing
to a non-validated answer. A subsequent query for the CNAME without do
will get an answer with the AD flag wrongly reset, and worse, the same
query with do will get a cached answer without RRSIGS, rather than
being forwarded.

The code now records the validation of individual RRsets and that
is used to correctly set the "validated" bits in the cache entries.
2017-10-25 17:48:19 +01:00
Simon Kelley
c366717e66 Tidy up add_resource_record() buffer size checks.
Mainly code-size and readability fixes.

Also return NULL from do_rfc1035_name() when limit exceeded, so
that truncated bit gets set in answer.
2017-10-13 23:26:29 +01:00
Simon Kelley
22dee512f3 Log DNS server max packet size reduction. 2017-10-13 22:54:00 +01:00
Simon Kelley
6fd5d79e73 Fix logic on EDNS0 headers.
The logic to determine is an EDNS0 header was added was wrong. It compared
the packet length before and after the operations on the EDNS0 header,
but these can include adding options to an existing EDNS0 header. So
a query may have an existing EDNS0 header, which is extended, and logic
thinks that it had a header added de-novo.

Replace this with a simpler system. Check if the packet has an EDSN0 header,
do the updates/additions, and then check again. If it didn't have one
initially, but it has one laterly, that's the correct condition
to strip the header from a reply, and to assume that the client
cannot handle packets larger than 512 bytes.
2017-10-13 22:26:40 +01:00
Simon Kelley
9d6918d32c Use IP[V6]_UNICAST_IF socket option instead of SO_BINDTODEVICE for DNS.
dnsmasq allows to specify a interface for each name server passed with
the -S option or pushed through D-Bus; when an interface is set,
queries to the server will be forced via that interface.

Currently dnsmasq uses SO_BINDTODEVICE to enforce that traffic goes
through the given interface; SO_BINDTODEVICE also guarantees that any
response coming from other interfaces is ignored.

This can cause problems in some scenarios: consider the case where
eth0 and eth1 are in the same subnet and eth0 has a name server ns0
associated.  There is no guarantee that the response to a query sent
via eth0 to ns0 will be received on eth0 because the local router may
have in the ARP table the MAC address of eth1 for the IP of eth0. This
can happen because Linux sends ARP responses for all the IPs of the
machine through all interfaces. The response packet on the wrong
interface will be dropped because of SO_BINDTODEVICE and the
resolution will fail.

To avoid this situation, dnsmasq should only restrict queries, but not
responses, to the given interface. A way to do this on Linux is with
the IP_UNICAST_IF and IPV6_UNICAST_IF socket options which were added
in kernel 3.4 and, respectively, glibc versions 2.16 and 2.26.

Reported-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Beniamino Galvani <bgalvani@redhat.com>
2017-10-13 17:55:09 +01:00
Simon Kelley
a49c5c2265 Fix search_servers() segfault with DNSSEC.
--address=/example.com/<IP> would segfault if query on example.com
was generated as part of DNSSEC validation.
2017-10-10 22:04:59 +01:00
Simon Kelley
30858e3b9b Spaces in CNAME options break parsing.
cname = wibble,wobble

works, but

cname =	wibble, wobble

fails. Bug introduced in 2.77. commit a1d973f987
2017-10-09 22:36:11 +01:00
Simon Kelley
30df7efc96 Merge i18n messages. 2017-10-02 14:13:51 +01:00
Simon Kelley
3e8c42cba5 Debian changlelog update. 2017-09-29 17:39:26 +01:00
Simon Kelley
62cb936cb7 Security fix, CVE-2017-14491, DNS heap buffer overflow.
Further fix to 0549c73b7e
Handles case when RR name is not a pointer to the question,
only occurs for some auth-mode replies, therefore not
detected by fuzzing (?)
2017-09-26 22:00:11 +01:00
Simon Kelley
39921d03ba Update credits for Google security team. 2017-09-26 18:43:19 +01:00
Simon Kelley
6a0b00f0d6 Misc code cleanups arising from Google analysis.
No security impleications or CVEs.
2017-09-25 20:19:55 +01:00
Simon Kelley
51eadb692a Security fix, CVE-2017-14495, OOM in DNS response creation.
Fix out-of-memory Dos vulnerability. An attacker which can
send malicious DNS queries to dnsmasq can trigger memory
allocations in the add_pseudoheader function
The allocated memory is never freed which leads to a DoS
through memory exhaustion. dnsmasq is vulnerable only
if one of the following option is specified:
--add-mac, --add-cpe-id or --add-subnet.
2017-09-25 20:16:50 +01:00
Simon Kelley
897c113fda Security fix, CVE-2017-14496, Integer underflow in DNS response creation.
Fix DoS in DNS. Invalid boundary checks in the
add_pseudoheader function allows a memcpy call with negative
size An attacker which can send malicious DNS queries
to dnsmasq can trigger a DoS remotely.
dnsmasq is vulnerable only if one of the following option is
specified: --add-mac, --add-cpe-id or --add-subnet.
2017-09-25 20:11:58 +01:00
Simon Kelley
33e3f1029c Security fix, CVE-2017-14494, Infoleak handling DHCPv6 forwarded requests.
Fix information leak in DHCPv6. A crafted DHCPv6 packet can
cause dnsmasq to forward memory from outside the packet
buffer to a DHCPv6 server when acting as a relay.
2017-09-25 20:05:11 +01:00
Simon Kelley
3d4ff1ba84 Security fix, CVE-2017-14493, DHCPv6 - Stack buffer overflow.
Fix stack overflow in DHCPv6 code. An attacker who can send
a DHCPv6 request to dnsmasq can overflow the stack frame and
crash or control dnsmasq.
2017-09-25 19:59:54 +01:00
Simon Kelley
24036ea507 Security fix, CVE-2017-14492, DHCPv6 RA heap overflow.
Fix heap overflow in IPv6 router advertisement code.
This is a potentially serious security hole, as a
crafted RA request can overflow a buffer and crash or
control dnsmasq. Attacker must be on the local network.
2017-09-25 19:59:27 +01:00
Simon Kelley
0549c73b7e Security fix, CVE-2017-14491 DNS heap buffer overflow.
Fix heap overflow in DNS code. This is a potentially serious
security hole. It allows an attacker who can make DNS
requests to dnsmasq, and who controls the contents of
a domain, which is thereby queried, to overflow
(by 2 bytes) a heap buffer and either crash, or
even take control of, dnsmasq.
2017-09-25 18:17:11 +01:00
Christian Hesse
b697fbb7f1 Do not include stdio.h before dnsmasq.h
We define some constants in dnsmasq.h, which have an influence on
stdio.h. So do not include stdio.h before dnsmasq.h.
2017-09-25 17:36:24 +01:00
Rasmus Ahlberg
96e063c43d Update contrib/try-all-ns. 2017-09-25 17:30:59 +01:00
Chris Novakovic
4e841da1a6 Fix broken translations after commit 730c6745 2017-09-25 17:21:49 +01:00
Simon Kelley
09ce307bdb Disable libIDN2 underscore workaround with libIDN or fixed libIDN2. 2017-09-25 16:53:55 +01:00
Simon Kelley
a3303e196e Don't return arcount=1 if EDNS0 RR won't fit in the packet.
Omitting the EDNS0 RR but setting arcount gives a malformed packet.
Also, don't accept UDP packet size less than 512 in recieved EDNS0.
2017-09-07 20:45:00 +01:00
Simon Kelley
63437ffbb5 Fix CVE-2017-13704, which resulted in a crash on a large DNS query.
A DNS query recieved by UDP which exceeds 512 bytes (or the EDNS0 packet size,
if different.) is enough to cause SIGSEGV.
2017-09-06 22:34:21 +01:00
Simon Kelley
69a815aa8f Fix loss of undercores in domain names when using libidn2.
libidn2 strips underscores from international domain names
when encoding them. Indeed, it strips underscores even if
no encoding is necessary, which breaks SRV records.

Don't submit domain names to IDN encoding if they contain
one or more underscores to fix this.
2017-07-08 21:20:16 +01:00
Simon Kelley
1d224949cc Remove ping-check of configured DHCP address.
This was added in 5ce3e76fbf but
it trips over too many buggy clients that leave an interface configured
even in DHCPDISCOVER case.
2017-07-08 20:52:55 +01:00
Simon Kelley
391f708a09 Man page tweak. 2017-07-08 20:48:51 +01:00
Rosen Penev
cbd29e5da8 Printf related fixes. 2017-06-27 22:29:51 +01:00
Rosen Penev
50a2841d34 Fix function declarations. 2017-06-27 22:27:02 +01:00
Hans Dedecker
9396752c11 Try other servers if first returns REFUSED when --strict-order active.
If a DNS server replies REFUSED for a given DNS query in strict order mode
no failover to the next DNS server is triggered as the failover logic only
covers non strict mode.
As a result the client will be returned the REFUSED reply without first
falling back to the secondary DNS server(s).

Make failover support work as well for strict mode config in case REFUSED is
replied by deleting the strict order check and rely only on forwardall being
equal to 0 which is the case in non strict mode when a single server has been
contacted or when strict order mode has been configured.
2017-06-27 22:08:47 +01:00
Simon Kelley
712dadb287 Bump Debian version to 2.78-1 2017-06-25 21:35:47 +01:00
Simon Kelley
32be32eab8 Formatting fixes for CHANGELOG 2017-06-25 21:33:28 +01:00
Simon Kelley
1649f709e7 Fix DHCP relay, broken by ff325644c7
Thanks to John Fitzgibbon for initial patch.
2017-06-25 21:19:30 +01:00
Simon Kelley
50ca85504c Bump year in copyrights. 2017-06-24 22:43:18 +01:00
Simon Kelley
4bb68866a8 Tweak ICMP ping check logic for DHCPv4. 2017-06-15 23:23:25 +01:00
Chris Novakovic
2446514e71 Fix logic of appending ".<layer>" to PXE basename
Commit f77700aa, which fixes a compiler warning, also breaks the
behaviour of prepending ".<layer>" to basenames in --pxe-service: in
situations where the basename contains a ".", the ".<layer>" suffix is
erroneously added, and in situations where the basename doesn't contain
a ".", the ".<layer>" suffix is erroneously omitted.

A patch against the git HEAD is attached that inverts this logic and
restores the expected behaviour of --pxe-service.
2017-06-06 23:02:59 +01:00
Simon Kelley
109d0e74f1 Debian: improve regexp for parsing root.ds. 2017-06-05 20:50:54 +01:00
Simon Kelley
74ea91531a Fix typo and format in CHANGELOG 2017-05-22 22:58:46 +01:00
Matthias Andree
9828ab115e Fix compiler warning. 2017-05-21 22:41:16 +01:00
Matthias Andree
f77700aa27 Fix compiler warning. 2017-05-21 22:36:09 +01:00
Simon Kelley
0fbd980639 Fix compiler warning. 2017-05-21 22:24:43 +01:00
Simon Kelley
43cdf1c3d0 Remove automatic IDN support when building i18n.
Remove historic automatic inclusion of IDN support when
building internationalisation support. This doesn't
fit now there is a choice of IDN libraries. Be sure
to include either -DHAVE_IDN or _DHAVE_LIBIDN2 for
IDN support
2017-05-21 22:12:44 +01:00
Simon Kelley
ff19b1a97d Fix &/&& confusion. 2017-05-21 21:15:32 +01:00
Conrad Kostecki
1835343acd Update German translation. 2017-05-12 15:16:02 +01:00
Simon Kelley
2aaea18f43 Add .gitattributes to substitute VERSION on export. 2017-05-12 13:14:17 +01:00
Simon Kelley
7ab78b937f Fix c7be0164ce 2017-05-11 20:33:21 +01:00
Simon Kelley
c7be0164ce Suppress DHCP ping checks when allocating on the loopback interface. 2017-05-10 22:21:53 +01:00
Petr Menšík
d203af4a02 Add optional support for libidn2 and therefore IDNA2008. 2017-05-10 21:41:57 +01:00
Simon Kelley
05f76dab89 Don't die() on failing to parse lease-script output. 2017-05-09 22:57:04 +01:00
Simon Kelley
bf05f8ff20 Fix crash introduced by 09f3b2cd9c. 2017-05-09 22:37:46 +01:00
Simon Kelley
09f3b2cd9c Fix case of DS queries to domains marked as not doing DNSSEC.
This was causing confusion: DNSSEC queries would be sent to
servers for domains that don't do DNSSEC, but because of that status
the answers would be treated as answers to ordinary queries,
sometimes resulting in a crash.
2017-05-09 01:34:02 +01:00
Simon Kelley
22827870fa Fix botch introduced by 561441320f 2017-05-08 21:39:04 +01:00
Vladislav Grishenko
4583dd9e42 Replace obsolete utime() usage with utimes().
This fixes build time warnings with POSIX.1-2008-aware c libraries.
2017-05-03 23:16:51 +01:00
Simon Kelley
561441320f Fix a couple of crashes on malformed config files.
Thanks to Stephan Zeisberg and
american fuzzy lop http://lcamtuf.coredump.cx/afl/
2017-05-03 22:54:09 +01:00
Simon Kelley
b2a9c571eb Add "known-othernet" DHCP tag. 2017-04-30 18:21:31 +01:00
Simon Kelley
efff74c1ae Tweak logging introduced in 3a8b0f6fcc 2017-04-28 23:01:23 +01:00
Simon Kelley
a9df0e30b0 Revert "Implement RFC-6842 (Client-ids in DHCP replies.)"
This reverts commit 88a77a78ad.

A least one client has been found which breaks with this change. Since
the use-case is not clear, I'm reverting the change, at least for now.
2017-04-28 22:44:24 +01:00
Simon Kelley
5ce3e76fbf DHCPv4: do ICMP-ping check in all cases other that current lease. 2017-04-28 22:14:20 +01:00
Vladislav Grishenko
6ec5f5c427 Extend --ra-param mtu: field to allow an interface name. 2017-04-24 22:34:45 +01:00
Vladislav Grishenko
5a7212c70e Make --rev-server work in the presence of --bogus-priv. 2017-04-24 22:21:04 +01:00
Petr Menšík
3a8b0f6fcc Improve error handling with shcp-script "init" mode. 2017-04-23 14:12:37 +01:00
Simon Kelley
a24c31e023 Debian: enable PIE and BINDNOW hardening in build. 2017-04-16 22:45:53 +01:00
Simon Kelley
f5a3679f1d Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2017-04-16 22:27:51 +01:00
Simon Kelley
5ac813cb86 Bump Lua version to 5.2. 2017-04-16 20:47:11 +01:00
Simon Kelley
a93b02e321 Compile option string: show script-support independent of DHCP. 2017-04-16 20:38:22 +01:00
Petr Menšík
c77fb9d8f0 Capture and log STDOUT and STDERR output from dhcp-script. 2017-04-16 20:20:08 +01:00
Simon Kelley
facc18f2a8 Bump Debian standards version. 2017-04-11 18:52:36 +01:00
Simon Kelley
bc515b71ec Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2017-04-11 18:49:59 +01:00
Simon Kelley
7bfa26399b FreeBSD compilation tweak. 2017-04-11 18:49:27 +01:00
Simon Kelley
461b7b43b4 Debian: readme typos. 2017-04-11 18:06:13 +01:00
Simon Kelley
b1cefa57f1 Debian: strip dhcp_release6 binary. 2017-04-11 15:55:26 +01:00
Simon Kelley
ce9a9704c6 Debian: add lsb-base dep. 2017-04-11 15:34:25 +01:00
Simon Kelley
93a9a55055 Debian changelog format fixup. 2017-04-11 15:21:30 +01:00
Simon Kelley
44eb875a5a Handle change in format of Debian /usr/share/dns/root.ds. 2017-04-11 15:13:09 +01:00
Floris Bos
bc87e609c2 Debian initscript tweak.
Dnsmasq's startup script seems to assume users always want to use
dnsmasq as local DNS resolver, and tells resolvconf to put
"nameserver 127.0.0.1" in /etc/resolv.conf
The problem with this is that if users just want to use dnsmasq
as DHCP server, and put port=0 in /etc/dnsmasq.conf to disable
the DNS functionality, they end up with broken name resolving.

Put a basic check in the startup script that skips resolvconf
configuration if a line starting with port=0 is in /etc/dnsmasq.conf
This doesn't cover all cases (e.g. configuration could also be in
different file in /etc/dnsmasq.d), but is better than current
situation.
2017-04-11 14:19:57 +01:00
David Flamand
005c46d6f5 Add mtu facility to --ra-param. 2017-04-11 11:49:54 +01:00
Floris Bos
503c609149 --dhcp-reply-delay option to workaround PXE client bugs.
Adds option to delay replying to DHCP packets by one or more seconds.
This provides a workaround for a PXE boot firmware implementation
that has a bug causing it to fail if it receives a (proxy) DHCP
reply instantly.

On Linux it looks up the exact receive time of the UDP packet with
the SIOCGSTAMP ioctl to prevent multiple delays if multiple packets
come in around the same time.
2017-04-09 23:07:13 +01:00
Floris Bos
60704f5e2e Add support for unique TFTP root per MAC.
It is currently only possible to let the TFTP server serve a different
folder depending on the client's IP address.
However it isn't always possible to predict what the client's
IP address will be, especially in situations in which we are not
responsible for handing them out (e.g. proxy dhcp setups).

Extend the current --tftp-unique-root parameter to support having a
separate folder per MAC address instead.
2017-04-09 22:22:49 +01:00
Kristian Evensen
4e7694d710 Allow binding to both source address and interface in server specs.
The current --server syntax allows for binding to interface or
address. However, in some (admittedly special) cases it is useful to
be able to specify both. This commit introduces the following syntax
to support binding to both interface and address:

--server X.X.X.X@IP@interface#port

Based on my tests, the syntax is backwards compatible with the current
@IP/interface#port. The code will fail if two interface names are given.

v1->v2:
* Add man page description of the extended server syntax (thanks Simon Kelley)

Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
2017-03-22 21:32:50 +00:00
James Bottomley
e33b48700e When forwarding a query to a non-DNSSEC nameserver, don't verify the lack of DNSSEC.
The man page says that we don't do DNSSEC on forwarded domains, but if
you turn on dnssec_check_signatures this turns out to be untrue,
because we try to build up a DS chain to them.  Since forwarded domains
are usually used for split DNS to hidden domains, they're unlikely to
verify to the DNS root anyway, so the way to do DNSSEC for them (as the
manual says) is to provide a trust anchor for each forwarder.

The problem I've run into is a split DNS setup where I want DNSSEC to
work mostly, but one of the forwarding domains doesn't have an internal
DNSSEC capable resolver. Without this patch the entire domain goes
unresolvable because the DS record query to the internal resolver
returns a failure which is interpreted as the domain being BOGUS.

The fix is not to do the DS record chase for forwarded domains.
2017-03-17 21:44:10 +00:00
Petr Menšík
ad59f278c6 Fix man page re interface labels and add warning when used badly. 2017-03-17 17:22:19 +00:00
Bert Gijsbers
16f03e7139 Check for failure of "git describe" in get-version. 2017-03-06 23:07:32 +00:00
Olivier Gayot
dc99058d83 Improve error checking for --rev-server.
The rev-server directive only handles the following CIDR prefixes
properly: /8, /16, /24, /32.

Any other value was silently converted to /16 which could result in
unexpected behaviour.

This patch rejects any other value instead of making a silent
conversion.
2017-03-06 22:17:21 +00:00
Olivier Gayot
916959c188 Fix rev-server with /32 prefix.
[ excerpt from the man page ]
The rev-server directive provides a syntactic sugar to make specifying
address-to-name queries easier. For example
--rev-server=1.2.3.0/24,192.168.0.1 is exactly equivalent to
--server=/3.2.1.in-addr.arpa/192.168.0.1

It is not mentioned in the man page but the only prefixes that the
directive properly handles when dealing with IPv4 are /8, /16 and /24.
Specifying anything else as the same effect as specifying /16.

It is not a big deal for subnets on non-octet boundaries since they
cannot be represented using a single in-addr.arpa address. However, it
is unconvenient for /32 prefix while the analogous server directive
behaves as expected. E.g. the following server directive work
as expected:

    server=/42.10.168.192.in-addr.arpa/1.2.3.4

but the following does not:

    rev-server=192.168.10.42/32,1.2.3.4

and, in practice, the later behaves the same as:

    server=/168.192.in-addr.arpa/1.2.3.4

This strange behaviour is fixed by accepting /32 CIDR prefixes as a
valid value. Any other value will still be considered the same as /16.
2017-03-06 22:14:50 +00:00
Simon Kelley
864913c0f3 Man page typo. 2017-02-28 18:07:18 +00:00
Simon Kelley
13dee6f49e Compilation warning fixes. 2017-02-28 16:51:58 +00:00
Simon Kelley
62f9c0d470 Fix CNAME wildcard in auth-mode.
A domain can only have a CNAME if it has not other records.

Don't return a CNAME when there are records of other types on the name.
2017-02-19 23:07:01 +00:00
Simon Kelley
54bb3639d4 Update FAQ to fix a couple of dead links.
Thanks to Federico Bianchi for reporting this.
2017-02-19 22:13:36 +00:00
Simon Kelley
fca008d8d4 Make --bogus-priv apply to IPv6. 2017-02-19 18:50:41 +00:00
klemens
43517fcaf5 Spelling fixes. 2017-02-19 15:53:37 +00:00
Simon Kelley
88a77a78ad Implement RFC-6842 (Client-ids in DHCP replies.) 2017-02-11 17:02:02 +00:00
Hannu Nyman
3e2496fb16 Decrease the number of individual sites listed in log.
By default 30 first servers are listed individually to system log, and
then a count of the remaining items. With e.g. a NXDOMAIN based adblock
service, dnsmasq lists 30 unnecessary ad sites every time when dnsmasq
evaluates the list. But the actual nameservers in use are evaluated last
and are not displayed as they get included in the "remaining items" total.

Handle the "local addresses only" separately and list only a few of them.
Remove the "local addresses only" from the general count.
2017-02-11 13:44:08 +00:00
Simon Kelley
05da782f8f Add forthcoming 2017 root zone trust anchor to trust-anchors.conf. 2017-02-10 21:32:45 +00:00
Simon Kelley
361dfe5158 Improve connection handling when talking to TCP upsteam servers.
Specifically, be prepared to open a new connection when we
want to make multiple queries but the upstream server accepts
fewer queries per connection.
2017-02-10 21:12:30 +00:00
Baptiste Jonglez
68f6312d4b Stop treating SERVFAIL as a successful response from upstream servers.
This effectively reverts most of 51967f9807 ("SERVFAIL is an expected
error return, don't try all servers.") and 4ace25c5d6 ("Treat REFUSED (not
SERVFAIL) as an unsuccessful upstream response").

With the current behaviour, as soon as dnsmasq receives a SERVFAIL from an
upstream server, it stops trying to resolve the query and simply returns
SERVFAIL to the client.  With this commit, dnsmasq will instead try to
query other upstream servers upon receiving a SERVFAIL response.

According to RFC 1034 and 1035, the semantic of SERVFAIL is that of a
temporary error condition.  Recursive resolvers are expected to encounter
network or resources issues from time to time, and will respond with
SERVFAIL in this case.  Similarly, if a validating DNSSEC resolver [RFC
4033] encounters issues when checking signatures (unknown signing
algorithm, missing signatures, expired signatures because of a wrong
system clock, etc), it will respond with SERVFAIL.

Note that all those behaviours are entirely different from a negative
response, which would provide a definite indication that the requested
name does not exist.  In our case, if an upstream server responds with
SERVFAIL, another upstream server may well provide a positive answer for
the same query.

Thus, this commit will increase robustness whenever some upstream servers
encounter temporary issues or are misconfigured.

Quoting RFC 1034, Section 4.3.1. "Queries and responses":

    If recursive service is requested and available, the recursive response
    to a query will be one of the following:

       - The answer to the query, possibly preface by one or more CNAME
         RRs that specify aliases encountered on the way to an answer.

       - A name error indicating that the name does not exist.  This
         may include CNAME RRs that indicate that the original query
	  name was an alias for a name which does not exist.

       - A temporary error indication.

Here is Section 5.2.3. of RFC 1034, "Temporary failures":

    In a less than perfect world, all resolvers will occasionally be unable
    to resolve a particular request.  This condition can be caused by a
    resolver which becomes separated from the rest of the network due to a
    link failure or gateway problem, or less often by coincident failure or
    unavailability of all servers for a particular domain.

And finally, RFC 1035 specifies RRCODE 2 for this usage, which is now more
widely known as SERVFAIL (RFC 1035, Section 4.1.1. "Header section format"):

    RCODE           Response code - this 4 bit field is set as part of
                    responses.  The values have the following
                    interpretation:
                    (...)

                    2               Server failure - The name server was
                                    unable to process this query due to a
                                    problem with the name server.

For the DNSSEC-related usage of SERVFAIL, here is RFC 4033
Section 5. "Scope of the DNSSEC Document Set and Last Hop Issues":

    A validating resolver can determine the following 4 states:
    (...)

    Insecure: The validating resolver has a trust anchor, a chain of
       trust, and, at some delegation point, signed proof of the
       non-existence of a DS record.  This indicates that subsequent
       branches in the tree are provably insecure.  A validating resolver
       may have a local policy to mark parts of the domain space as
       insecure.

    Bogus: The validating resolver has a trust anchor and a secure
       delegation indicating that subsidiary data is signed, but the
       response fails to validate for some reason: missing signatures,
       expired signatures, signatures with unsupported algorithms, data
       missing that the relevant NSEC RR says should be present, and so
       forth.
    (...)

    This specification only defines how security-aware name servers can
    signal non-validating stub resolvers that data was found to be bogus
    (using RCODE=2, "Server Failure"; see [RFC4035]).

Notice the difference between a definite negative answer ("Insecure"
state), and an indefinite error condition ("Bogus" state).  The second
type of error may be specific to a recursive resolver, for instance
because its system clock has been incorrectly set, or because it does not
implement newer cryptographic primitives.  Another recursive resolver may
succeed for the same query.

There are other similar situations in which the specified behaviour is
similar to the one implemented by this commit.

For instance, RFC 2136 specifies the behaviour of a "requestor" that wants
to update a zone using the DNS UPDATE mechanism.  The requestor tries to
contact all authoritative name servers for the zone, with the following
behaviour specified in RFC 2136, Section 4:

    4.6. If a response is received whose RCODE is SERVFAIL or NOTIMP, or
    if no response is received within an implementation dependent timeout
    period, or if an ICMP error is received indicating that the server's
    port is unreachable, then the requestor will delete the unusable
    server from its internal name server list and try the next one,
    repeating until the name server list is empty.  If the requestor runs
    out of servers to try, an appropriate error will be returned to the
    requestor's caller.
2017-02-06 21:09:11 +00:00
Josh Soref
730c6745f0 Comprehensive spelling/typo fixes.
Thanks to Josh Soref for generating these fixes.
2017-02-06 16:14:04 +00:00
Simon Kelley
d42d4706bb Make --localise-queries apply to names from --interface-name. 2017-02-02 16:52:06 +00:00
Simon Kelley
0740e43e20 Fix rrfilter bug leading to malformed replies.
Bug tickled by Nominum upstream when DNSSEC enabled, due to
unusual order of RRs in reply from upstream server.
2017-01-26 18:02:54 +00:00
Simon Kelley
903df07bcb Detect and error loops in --cname configuration. 2017-01-19 17:22:00 +00:00
Simon Kelley
0ef1334d78 Tweak start-up logging 2017-01-15 16:42:39 +00:00
Reiter Wolfgang
5eb9dde09c Fix getsockname error return check. 2017-01-08 17:39:06 +00:00
Simon Kelley
ae3154aca9 Additional syntax check on MAC wildcards. 2017-01-01 22:59:46 +00:00
Simon Kelley
3ebe62d1b7 Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2017-01-01 22:42:31 +00:00
ZHAO Yu
f89cae3ecf Add DNSMASQ_REQUESTED_OPTIONS env-var to lease change script. 2016-12-22 22:32:31 +00:00
Simon Kelley
09b768efa4 Bump TCP connection backlog from 5 to 32. 2016-12-22 22:16:58 +00:00
Simon Kelley
a1d973f987 Allow multiple CNAMEs in a single --cname= option. 2016-12-22 22:09:50 +00:00
Simon Kelley
0682b7795c Debian packaging update. 2016-12-14 17:59:45 +00:00
Simon Kelley
b637d7815d Allow wildcard CNAME records in authoritative zones. 2016-12-13 16:44:11 +00:00
Kevin Darbyshire-Bryant
7ac9ae1125 Compile time option NO_ID
Some consider it good practice to obscure software version numbers to
clients.  Compiling with -DNO_ID removes the *.bind info structure.
This includes: version, author, copyright, cachesize, cache insertions,
evictions, misses & hits, auth & servers.
2016-09-09 20:52:08 +01:00
Simon Kelley
c6af3a32f2 Support cross-builds in Debian packaging. 2016-08-31 22:38:48 +01:00
Simon Kelley
16800ea072 Fix crash introduced in 2675f20615 2016-08-30 23:07:06 +01:00
Simon Kelley
b5e33ae53a Log ipset errors. 2016-08-28 21:26:42 +01:00
Peter Wu
3c0c1111fe Improve --address and --ipset docs, fix --help output
Manual page: clarify that the --address and --ipset options take one or
more domains rather than just two. Clarify that --ipset puts addresses
in all ipsets, it is not a 1:1 mapping from addresses.

Also increase the width for options output in --help, some options were
truncated leading to confusing output. Almost all options and
descriptions are now within the 120 colums limit.
2016-08-28 20:53:09 +01:00
Beniamino Galvani
2675f20615 Handle binding upstream servers to an interface
(--server=1.2.3.4@eth0) when the named interface
is destroyed and recreated in the kernel.
2016-08-28 20:44:05 +01:00
Simon Kelley
e94ad0fa01 Suppress useless warning about DHCP packets of interfaces without addresses.
This only makes sense for interfaces which we're configured to listen on.
Thanks to Andrew Shadura for bug report.
2016-08-28 18:09:17 +01:00
Simon Kelley
396750cef5 Refactor openBSD pftables code to remove blatant copyright violation. 2016-08-13 22:34:11 +01:00
Simon Kelley
6c45519e18 2.76-3 debian release. 2016-08-13 21:49:17 +01:00
Simon Kelley
6d95099c56 Handle v4-mapped IPv6 addresses sanely for --synth-domain. 2016-08-11 23:38:54 +01:00
Simon Kelley
c8328ecde8 Bump auth zone serial when reloading /etc/hosts and friends. 2016-08-05 16:54:58 +01:00
Mathias Kresin
094bfaeb4f auth-zone: allow to exclude ip addresses from answer. 2016-07-24 14:15:22 +01:00
Simon Kelley
bf4e62c19e Compile-time check on buffer sizes for leasefile parsing code. 2016-07-22 21:37:59 +01:00
Simon Kelley
6b1c464d6d Don't reset packet length on transmission, in case of retransmission. 2016-07-22 20:59:16 +01:00
Simon Kelley
fa78573778 Zero packet buffers before building output, to reduce risk of information leakage. 2016-07-22 20:56:01 +01:00
Simon Kelley
cd2ddb9904 Debian systemd bugfix. 2016-07-16 22:23:49 +01:00
Simon Kelley
9bb3998da4 Merge 2.76-1.2 Debian NMU. 2016-07-16 22:06:01 +01:00
Simon Kelley
d6dce53e08 malloc(); memset() -> calloc() for efficiency. 2016-07-11 21:34:31 +01:00
Kevin Darbyshire-Bryant
06093a9a84 Fix problem with --dnssec-timestamp
whereby receipt of SIGHUP would erroneously engage timestamp checking.
2016-07-11 21:03:27 +01:00
Ivan Kokshaysky
1d07667ac7 Fix logic error in Linux netlink code.
This could cause dnsmasq to enter a tight loop on systems
with a very large number of network interfaces.
2016-07-11 18:36:05 +01:00
Simon Kelley
591ed1e905 Fix bad behaviour with some DHCP option arrangements.
The check that there's enough space to store the DHCP agent-id
at the end of the packet could succeed when it should fail
if the END option is in either of the oprion-overload areas.
That could overwrite legit options in the request and cause
bad behaviour. It's highly unlikely that any sane DHCP client
would trigger this bug, and it's never been seen, but this
fixes the problem.

Also fix off-by-one in bounds checking of option processing.
Worst case scenario on that is a read one byte beyond the
end off a buffer with a crafted packet, and maybe therefore
a SIGV crash if the memory after the buffer is not mapped.

Thanks to Timothy Becker for spotting these.
2016-07-11 18:18:42 +01:00
Kristjan Onu
907efeb2dc Manpage typo. 2016-07-10 22:37:57 +01:00
Simon Kelley
beea62cb66 Update .gitignore for change contrib/wrt -> contrib/lease-tools. 2016-07-10 22:13:57 +01:00
Simon Kelley
5874f3e922 Fix editing error on man page.
Thanks to Eric Westbrook for spotting this.
2016-07-10 22:12:08 +01:00
zeha@debian.org
04cb536f16 Merge 2.67-1.1 Debian NMU. 2016-07-06 22:30:10 +01:00
Simon Kelley
8ee8524016 Bump Debian version. 2016-07-06 22:23:22 +01:00
Simon Kelley
ce7845bf54 Check return of expand() always. 2016-07-06 21:42:27 +01:00
Simon Kelley
d55f81f5fd Zero newly malloc'ed memory. 2016-07-06 21:33:56 +01:00
Simon Kelley
294d36df47 Calculate length of TFTP error reply correctly. 2016-07-06 21:30:25 +01:00
Simon Kelley
f186bdcbc7 Fix debian changelog. 2016-05-18 15:51:54 +01:00
Jan Psota
ed1bd54b5c Update Polish translation.
Thanks to Jan Psota.
2016-05-18 15:16:29 +01:00
Simon Kelley
da2cad4b14 Doc about --pxe-service basename change into CHANGELOG. 2016-05-18 15:14:08 +01:00
Simon Kelley
0a4a04969d Final PXE tweak, and release-note to reflect changes. 2016-05-15 20:13:45 +01:00
Sergey Nechaev
45cb8dd9be Stricter command line args validation to dhcp_release6. 2016-05-14 21:36:15 +01:00
Simon Kelley
88b09aaddc Merge messages into translation files. 2016-05-14 20:56:02 +01:00
Simon Kelley
fe71bba356 Tweak UEFI workaround code. 2016-05-14 20:50:45 +01:00
Simon Kelley
cbc100fc81 Tweak CSAs affected by UEFI PXE workaround code. 2016-05-11 22:17:18 +01:00
Simon Kelley
68bea10bbf Fix error in PXE arch names and add ARM32 and ARM64. 2016-05-11 22:15:06 +01:00
Simon Kelley
8628cd603f Workaround for UEFI PXE boot problems. 2016-05-10 17:31:48 +01:00
Neil Jerram
ff325644c7 Fix for DHCP in transmission interface when --bridge-interface in use.
From f3d832b41f44c856003517c583fbd7af4dca722c Mon Sep 17 00:00:00 2001
From: Neil Jerram <Neil.Jerram@metaswitch.com>
Date: Fri, 8 Apr 2016 19:23:47 +0100
Subject: [PATCH] Fix DHCPv4 reply via --bridge-interface alias interface

Sending a DHCPv4 reply through a --bridge-interface alias interface
was inadvertently broken by

  commit 65c7212000
  Author: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
  Date:   Thu Mar 19 23:22:21 2015 +0000

      dhcp: set outbound interface via cmsg in unicast reply

        If multiple routes to the same network exist, Linux blindly picks
        the first interface (route) based on destination address, which might not be
        the one we're actually offering leases. Rather than relying on this,
        always set the interface for outgoing unicast DHCP packets.

because in the aliasing case, iface_index is changed from the index of
the interface on which the packet was received, to be the interface
index of the 'bridge' interface (where the DHCP context is expected to
be defined, and so needs to be looked up).

For the cmsg code that the cited commit added, we need the original
iface_index; so this commit saves that off before the aliasing code
can change it, as rcvd_iface_index, and then uses rcvd_iface_index
instead of iface_index for the cmsg code.
2016-05-03 22:49:46 +01:00
Simon Kelley
b97026035e Limit number of upstream nameservers when logging configuration. 2016-05-03 22:34:06 +01:00
Simon Kelley
69cbf78bb6 Add contrib/lease-tools/dhcp_release6 2016-05-03 21:33:38 +01:00
Simon Kelley
c6cdf6bbee Move dhcp_release and dhcp_lease_time to contrib/lease_tools. 2016-05-03 21:14:14 +01:00
Simon Kelley
09217a1a87 Add --help to manpage . 2016-05-03 17:04:35 +01:00
Simon Kelley
332c41e2ff Debian init.d script fix. 2016-05-01 22:36:46 +01:00
Simon Kelley
2c0c36f54b Fix problem with IPv6 in new ARP-search code. 2016-05-01 20:57:08 +01:00
Simon Kelley
d6b749af91 Fix typo in SDBM hash function.
Thanks to Luis Carvalho for spotting the error.
2016-04-25 17:05:15 +01:00
Simon Kelley
14ffa0770b Fix init of per server EDNS UDP packet size. 2016-04-25 16:36:44 +01:00
Simon Kelley
87985855ad Remove pre-existing EDNS0_OPTION_NOMDEVICEID if MAC address unknown. 2016-04-25 15:33:30 +01:00
Simon Kelley
a2bc254bed Check return-code of inet_pton when parsing DHCPv4 options. 2016-04-21 22:41:31 +01:00
Simon Kelley
a7b27e84fa NULL pointer check. 2016-03-16 19:11:52 +00:00
Simon Kelley
529b030228 Tidy code. 2016-03-16 19:00:45 +00:00
Simon Kelley
4caa86dd7d Tidy. 2016-03-16 18:44:16 +00:00
Simon Kelley
e1abeeeec2 Fix memory leak in inotify code. 2016-03-16 18:12:35 +00:00
Simon Kelley
40205a053e Bound hash-iterations in DNSSEC NSEC3 checking. 2016-03-14 21:24:00 +00:00
Simon Kelley
b8ac466209 Tidy code. 2016-03-10 18:40:53 +00:00
Simon Kelley
d1377fa3c4 Account for TFTP packet headers in IPv6 correctly. 2016-03-04 21:32:21 +00:00
Simon Kelley
fa79466c2a Tighten syntax checking for dhcp-range and clarify man page. 2016-03-03 20:33:54 +00:00
Simon Kelley
a93bd4b016 Fix broken DNSMASQ_USER<x> envvars in script with more than one class. 2016-03-01 18:58:01 +00:00
Simon Kelley
407a1f3e95 Tidy parsing code. 2016-03-01 17:06:07 +00:00
Simon Kelley
4b6af5d53f Fix pointer declaration botch. 2016-03-01 17:00:26 +00:00
Simon Kelley
7aa3f9af66 format fix. 2016-03-01 16:32:30 +00:00
Simon Kelley
f7cf749943 Check return code from open() 2016-03-01 16:19:23 +00:00
Simon Kelley
aa300f7167 Fix typo in last commit. 2016-03-01 15:19:13 +00:00
Simon Kelley
c7f3bd2ac8 Replace incoming EDNS0_OPTION_NOMDEVICEID and EDNS0_OPTION_NOMCPEID options. 2016-02-28 21:48:34 +00:00
Simon Kelley
22fe2fd038 Fix --add-subnet when returning empty or default subnet. 2016-02-28 17:07:10 +00:00
Simon Kelley
7480aeffc8 Apply ceiling of lease length to TTL when --dhcp-ttl in use. 2016-02-26 21:58:20 +00:00
Simon Kelley
bec366b404 Add --tftp-mtu option. 2016-02-24 22:03:26 +00:00
Simon Kelley
e06e6e34bf Update CHANGELOG. 2016-02-24 21:26:16 +00:00
Simon Kelley
832e47beab Add --dhcp-ttl option. 2016-02-24 21:24:45 +00:00
Simon Kelley
df3d54f776 Add TTL parameter to --host-record and --cname. 2016-02-24 21:03:38 +00:00
Simon Kelley
22c0f4fe87 Fix previous commit. 2016-02-17 22:12:31 +00:00
Simon Kelley
9e4cf47ee8 Add --add-mac=text option. 2016-02-17 20:26:32 +00:00
Simon Kelley
fdc97e1383 Avoid divide-by-zero when dhcp-range is a whole /64 2016-02-13 17:47:17 +00:00
S L
a18bf3149a Avoid losing timer when deleting a RA context. 2016-02-12 17:36:20 +00:00
Simon Kelley
1566bacb2c Fix breakage in ARP code when IPV6 support not compiled in. 2016-02-05 14:48:25 +00:00
Simon Kelley
e6e751b066 Make names of ARP script actions consistent. 2016-02-01 17:59:07 +00:00
Andy Stormont
8de875f0fb Fix FTBFS on illumos 2016-02-01 12:07:57 +00:00
Chris Novakovic
4ace25c5d6 Treat REFUSED (not SERVFAIL) as an unsuccessful upstream response
Commit 51967f9807 began treating SERVFAIL
as a successful response from an upstream server (thus ignoring future
responses to the query from other upstream servers), but a typo in that
commit means that REFUSED responses are accidentally being treated as
successful instead of SERVFAIL responses.

This commit corrects this typo and provides the behaviour intended by
commit 51967f9: SERVFAIL responses are considered successful (and will
be sent back to the requester), while REFUSED responses are considered
unsuccessful (and dnsmasq will wait for responses from other upstream
servers that haven't responded yet).
2016-01-25 21:54:35 +00:00
Simon Kelley
1e5051228d Final form of configuration for EDNS0 MAC-address code. 2016-01-25 21:29:23 +00:00
Hans Dedecker
926332a764 Add --max-port config option. 2016-01-23 10:48:12 +00:00
Simon Kelley
d05dd58de1 Fix wrong reply to simple name when --domain-needed set and no servers configured.
Also return REFUSED and not SERVFAIL when out of memory.

Thanks to Allain Legacy for problem report.
2016-01-19 21:23:30 +00:00
Simon Kelley
f7443d76f7 Fix problems in last commit when DNSSEC not enabled. 2016-01-19 20:29:57 +00:00
Simon Kelley
f344dbc622 Complete DNSSEC server-selection code and set conntrack on DNSSEC queries. 2016-01-18 18:11:54 +00:00
Simon Kelley
f4d0c660ca Fix sporadic crash in find_mac() - hwlen must be zero for empty entries. 2016-01-18 12:51:08 +00:00
Simon Kelley
1801a29226 Fix botch in forward.c flags code.
Thanks to Matthias Anfree for spotting this.
2016-01-17 21:53:57 +00:00
Simon Kelley
92be34a407 Complete work to allow DNSSEC validation with private DNS servers. 2016-01-16 18:39:54 +00:00
Simon Kelley
bb58f63ce5 arp.c tidy up. 2016-01-14 19:23:10 +00:00
Simon Kelley
367341f745 Disable DNSSEC for server=/domain/.. servers unless trust-anchor provided. 2016-01-12 15:58:23 +00:00
André Glüpker
eddf365284 Fix bad cache-size calculation when hosts-file read fails. 2016-01-12 12:54:17 +00:00
Simon Kelley
a63b8b89e6 DNSSEC: Handle non-root trust anchors, and check we have a root trust anchor. 2016-01-12 11:28:58 +00:00
Simon Kelley
5757371d43 Inhibit DNSSEC validation when forwarding to private servers for a domain.
server=/example.com/<ip-of-server>

The rationale is that the chain-of-trust will not be complete to
private servers. If it was, it would not be necessary to access the
server direct.
2016-01-11 22:50:00 +00:00
Simon Kelley
b633de9413 Fix FTBFS when scripts excluded at compilation time. 2016-01-06 22:51:17 +00:00
Simon Kelley
c49778df4a Update copyright notices. Happy new year! 2016-01-06 18:52:33 +00:00
Simon Kelley
53a9173fc0 Handle building with script support enabled and DHCP disabled. 2016-01-06 17:59:13 +00:00
Simon Kelley
d917275e48 Fix botch in new arp-cache linked-list code resulting in 100% CPU spin. 2016-01-04 17:17:41 +00:00
Simon Kelley
cc7cb0b893 Fix datatype-sixe botch which broke DNSSEC sig timestamps when far in the future. 2016-01-04 16:04:51 +00:00
Simon Kelley
ec0628c4b2 Trivial code tweak. 2015-12-31 20:55:39 +00:00
Simon Kelley
97b1d25764 Correct logic for when to start helper. 2015-12-31 18:52:38 +00:00
Simon Kelley
33702ab1f8 First complete version of DNS-client-id EDNS0 and ARP tracking code. 2015-12-28 23:17:15 +00:00
Simon Kelley
11867dc28c Cache access to the kernel's ARP table. 2015-12-23 16:15:58 +00:00
Simon Kelley
d3a8b39c7d More EDNS0 packet-size tweaks. 2015-12-23 12:27:37 +00:00
Simon Kelley
15379ea1f2 Log signature algo with DNSKEY and DS, also digest with DS. 2015-12-21 18:31:55 +00:00
Simon Kelley
efef497b89 Fix build failure when DNSSEC code omitted. 2015-12-21 17:30:44 +00:00
Simon Kelley
5aa5f0ff2f Truncate DNS replies >512 bytes that the client isn't expecting. 2015-12-21 17:20:35 +00:00
Simon Kelley
5bb88f0963 Handle extending EDNS0 OPT RR. 2015-12-21 16:23:47 +00:00
Simon Kelley
1d03016bbc Split EDNS0 stuff into its own source file. 2015-12-21 14:17:06 +00:00
Simon Kelley
ce5732e84f NSEC3 check: RFC5155 para 8.2 2015-12-20 21:39:19 +00:00
Simon Kelley
a86fdf437e Minor tweak to previous commit. 2015-12-20 21:19:20 +00:00
Simon Kelley
3e86d316c4 Nasty, rare and obscure off-by-one in DNSSEC hostname_cmp(). 2015-12-20 20:50:05 +00:00
Simon Kelley
d67ecac59d More tweaks in handling unknown DNSSEC algorithms. 2015-12-20 20:44:23 +00:00
Simon Kelley
fa14bec83b Major tidy up of EDNS0 handling and computation/use of udp packet size. 2015-12-20 17:12:16 +00:00
Simon Kelley
14a4ae883d Do a better job of determining which DNSSEC sig algos are supported. 2015-12-17 17:29:57 +00:00
Simon Kelley
3b799c826d Fix brace botch in dnssec_validate_ds()
Thanks to Michał Kępień for spotting this.
2015-12-17 16:58:04 +00:00
Simon Kelley
b40f26c019 Tidy up DNSSEC non-existence code. Check zone status is NSEC proof bad. 2015-12-17 11:57:26 +00:00
Simon Kelley
dd4ad9ac7e Tweaks to EDNS0 handling in DNS replies. 2015-12-17 10:44:58 +00:00
Simon Kelley
2dbba34b2c DNSSEC validation tweak.
A zone which has at least one key with an algorithm we don't
support should be considered as insecure.
2015-12-16 13:41:58 +00:00
Simon Kelley
c2bcd1e183 Generalise RR-filtering code, for use with EDNS0. 2015-12-15 17:25:21 +00:00
Simon Kelley
d64c81fff7 Move code which caches DS records to a more logical place. 2015-12-15 16:11:06 +00:00
Simon Kelley
93be5b1e02 Abandon caching RRSIGs and returning them from cache.
The list of exceptions to being able to locally answer
cached data for validated records when DNSSEC data is requested
was getting too long, so don't ever do that. This means
that the cache no longer has to hold RRSIGS and allows
us to lose lots of code. Note that cached validated
answers are still returned as long as do=0
2015-12-15 12:04:40 +00:00
Simon Kelley
9a31b68b59 Major rationalisation of DNSSEC validation.
Much gnarly special-case code removed and replaced with correct
general implementaion. Checking of zone-status moved to DNSSEC code,
where it should be, vastly simplifying query-forwarding code.
2015-12-15 10:20:39 +00:00
Simon Kelley
0007ee9064 Fix crash at start up with conf-dir=/path,*
Thanks to Brian Carpenter and American Fuzzy Lop for finding the bug.
2015-11-21 21:47:41 +00:00
Simon Kelley
67ab3285b5 Handle unknown DS hash algos correctly.
When we can validate a DS RRset, but don't speak the hash algo it
contains, treat that the same as an NSEC/3 proving that the DS
doesn't exist. 4025 5.2
2015-11-20 23:20:47 +00:00
Edwin Török
41a8d9e99b Fix crash when empty address from DNS overlays A record from hosts. 2015-11-14 17:55:41 +00:00
Simon Kelley
90477fb794 Update list of subnet for --bogus-priv
RFC6303 specifies & recommends following zones not be forwarded
to globally facing servers.
+------------------------------+-----------------------+
| Zone                         | Description           |
+------------------------------+-----------------------+
| 0.IN-ADDR.ARPA               | IPv4 "THIS" NETWORK   |
| 127.IN-ADDR.ARPA             | IPv4 Loopback NETWORK |
| 254.169.IN-ADDR.ARPA         | IPv4 LINK LOCAL       |
| 2.0.192.IN-ADDR.ARPA         | IPv4 TEST-NET-1       |
| 100.51.198.IN-ADDR.ARPA      | IPv4 TEST-NET-2       |
| 113.0.203.IN-ADDR.ARPA       | IPv4 TEST-NET-3       |
| 255.255.255.255.IN-ADDR.ARPA | IPv4 BROADCAST        |
+------------------------------+-----------------------+

Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
2015-10-20 21:21:32 +01:00
Simon Kelley
98079ea898 Catch errors from sendmsg in DHCP code.
Logs, eg,  iptables DROPS of dest 255.255.255.255
2015-10-13 20:32:21 +01:00
Simon Kelley
4790115455 Use /run/dnsmasq instead of /var/run/dnsmasq in Debian package. 2015-09-29 22:54:41 +01:00
Simon Kelley
27b78d990b Rationalise 5e3e464ac4 2015-09-26 21:40:45 +01:00
Simon Kelley
77607cbea0 Respect the --no-resolv flag in inotify code. 2015-09-10 23:08:43 +01:00
Simon Kelley
102208df69 DHCPv6 option 56 does not hold an address list. (RFC 5908). 2015-09-10 21:50:00 +01:00
Simon Kelley
6de81f1250 Handle signed dangling CNAME replies to DS queries. 2015-09-09 22:51:13 +01:00
Simon Kelley
20fd11e11a Clarify man page on RDNSS set in router advertisement. 2015-08-26 22:48:13 +01:00
Simon Kelley
9cdcfe9f19 Suggest solution to ENOMEM error with IPv6 multicast. 2015-08-26 22:38:08 +01:00
Simon Kelley
5e3e464ac4 Fix behaviour of empty dhcp-option=option6:dns-server, which should inhibit sending option. 2015-08-25 23:08:39 +01:00
Simon Kelley
3a3965ac21 Don't answer non-auth queries for auth zones locally when --localise-queries set. 2015-08-09 17:45:06 +01:00
Ed Bardsley
a7369bef8a Enhance --add-subnet to allow arbitary subnet addresses. 2015-08-05 21:17:18 +01:00
Simon Kelley
d2aa7dfbb6 Include 0.0.0.0/8 in DNS rebind checks. 2015-08-03 21:52:12 +01:00
Simon Kelley
63ec5d1264 Fix new poll() code for helper pipe. Removed CPU-spin. 2015-07-30 20:59:07 +01:00
Simon Kelley
f6381cf482 Declare utime(). 2015-07-27 19:48:43 +01:00
Kevin Darbyshire-Bryant
34b5d19488 Update DNSSEC timestamp file on process TERM. 2015-07-27 19:34:23 +01:00
Conrad Kostecki
d6cb7e4815 Update german translation 2015-07-27 19:22:49 +01:00
Simon Kelley
d389e0191b DNSSEC fix: correct logic for signed records in unsigned DNS space. 2015-07-27 18:56:43 +01:00
Simon Kelley
d3699bb6bc Small tweak to DNSSEC fix. 2015-07-16 22:37:37 +01:00
Simon Kelley
13480e8c2a DNSSEC fix, signed wildcard CNAME to unsigned domain. 2015-07-16 22:23:13 +01:00
Jan Psota
5b3b93f80a Update Polish translation. 2015-07-15 19:57:47 +01:00
Simon Kelley
b69e845b1c Close Lauchpad bug in Debian changelog. 2015-07-15 19:54:50 +01:00
Simon Kelley
90c3822bfa Grow pollfds array exponentially. 2015-07-13 12:47:52 +01:00
Simon Kelley
c895a0626d Merge messages for translations. 2015-07-12 21:27:40 +01:00
Simon Kelley
b842bc97bb Use poll() instead of select() to remove limits on open file descriptors. 2015-07-12 21:09:11 +01:00
Simon Kelley
0f38fa05a6 Log message typo. 2015-07-08 22:42:14 +01:00
Simon Kelley
45c5cb1f8f Fix compilation warning. 2015-07-08 22:40:57 +01:00
Simon Kelley
f6d6956261 Test for overflowing platform FD_SET size. 2015-07-08 22:38:13 +01:00
Simon Kelley
60176c7bf4 Bump version in Debian changelog. 2015-07-07 21:54:55 +01:00
Simon Kelley
362c9303da Fix inotify code to handle dangling symlinks better. 2015-07-06 21:48:49 +01:00
Simon Kelley
5e95a552ee Avoid hanngs in DHCP ping code when system time goes backwards. 2015-07-05 22:31:30 +01:00
Simon Kelley
90cb222551 --conf-file should read no file, not try and read the default file. 2015-07-05 21:59:10 +01:00
Ján Sáreník
850163288d Manpage typo fix. 2015-07-05 21:23:27 +01:00
Simon Kelley
e3ec6f0bd7 Handle CNAMEs to DS records when confirming absence of DS for DNSSEC. 2015-06-12 21:39:11 +01:00
Simon Kelley
f7bfbdc872 Merge messages and fix makefile process to do this. 2015-06-10 22:31:02 +01:00
Neil Jerram
4918bd5505 Documenation updates for --bridge-interface and "off-link". 2015-06-10 22:23:20 +01:00
Neil Jerram
9bad339af8 Apply --bridge-interfaces to unsolicited router advertisements. 2015-06-10 22:16:35 +01:00
Neil Jerram
ba4fc0f996 Upply --bridge-interface aliasing to solicited router advertisements. 2015-06-10 22:14:49 +01:00
Neil Jerram
2fd5bc952d Allow router advertisements to have the "off-link" bit set. 2015-06-10 22:13:06 +01:00
Neil Jerram
0ddb8769bb Extend --bridge-interface aliasing to DHCPv6. 2015-06-10 22:11:06 +01:00
Neil Jerram
654f59e762 Fix logging of unknown interface in --bridge-interface, DHPCv4. 2015-06-10 22:06:33 +01:00
Simon Kelley
d91b1fd402 Add a couple of missed logging strings to the catalogue. 2015-06-09 20:45:07 +01:00
Nicolas Cavallari
c6d82c9ba6 Add Dbus methods to create and delete DHCP leases. 2015-06-09 20:42:20 +01:00
Simon Kelley
4d25cf89d5 Handle corner cases in NSEC coverage checks. 2015-06-06 23:13:57 +01:00
Simon Kelley
24e9207e13 More reproducibility fixes for Debian package. 2015-06-04 22:32:43 +01:00
Simon Kelley
89130d91d6 DHCPv6: DHCPCONFIRM should be OK for any address on link, not just dynamic addresses. 2015-06-03 22:34:14 +01:00
Simon Kelley
d644b2a17d Close Debian bug for bug fixed upstream. 2015-06-01 21:00:16 +01:00
swigger
bd7bfa21c4 Correctly sanitise DNS header bits in answer when recreating query for retry. 2015-06-01 20:54:59 +01:00
Simon Kelley
403de05925 Merge branch 'master' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq 2015-05-26 22:12:01 +01:00
John Hanks
46c89f2bd0 Add infiniband to example config file. 2015-05-26 22:07:57 +01:00
Christian Demsar
23facf0d77 Man page typo. 2015-05-20 20:26:23 +01:00
Simon Kelley
549b1a478c Tweak immediately previous patch. 2015-05-20 20:20:24 +01:00
Simon Kelley
7f8565b94c Select correct DHCP context when in PXE bootserver mode. 2015-05-19 23:01:27 +01:00
Simon Kelley
06568c6636 Remove support for DNS Extended Label Types.
The support was only partial, and the whole concept is
now deprecated in the standards.
2015-05-15 20:43:48 +01:00
Simon Kelley
5d07d77e75 Fix buffer overflow introduced in 2.73rc6.
Fix off-by-one in code which checks for over-long domain names
in received DNS packets. This enables buffer overflow attacks
which can certainly crash dnsmasq and may allow for arbitrary
code execution. The problem was introduced in commit b8f16556d,
release 2.73rc6, so has not escaped into any stable release.
Note that the off-by-one was in the label length determination,
so the buffer can be overflowed by as many bytes as there are
labels in the name - ie, many.

Thanks to Ron Bowes, who used lcmatuf's afl-fuzz tool to find
the problem.
2015-05-15 18:13:06 +01:00
Simon Kelley
62018e1f72 Use correct DHCP context for PXE-proxy server-id. 2015-05-14 21:30:00 +01:00
Simon Kelley
7c0f2543a7 Tweak last commit. 2015-05-14 21:16:18 +01:00
Simon Kelley
ca85a28241 Allow T1 and T2 DHCPv4 options to be set. 2015-05-13 22:33:04 +01:00
Simon Kelley
585840b033 Pointer to mail-archive mailing list mirror in doc.html. 2015-05-13 12:35:57 +01:00
Simon Kelley
dec180ac00 Tweak Debian systemd unit file. 2015-05-13 12:16:13 +01:00
Simon Kelley
86fa104692 Tweak EDNS timeout code. 2015-05-10 14:04:06 +01:00
Simon Kelley
b059c96dc6 Check IPv4-mapped IPv6 addresses with --stop-rebind. 2015-05-08 20:25:51 +01:00
Simon Kelley
a77cec8d58 Handle UDP packet loss when fragmentation of large packets is broken. 2015-05-08 16:25:38 +01:00
Nicolas Cavallari
64bcff1c7c Constify some DHCP lease management functions. 2015-04-28 21:55:18 +01:00
Simon Kelley
2ed162ac20 Don't remove RRSIG RR from answers to ANY queries when the do bit is not set. 2015-04-28 21:26:35 +01:00
Simon Kelley
e66b4dff3c Fix argument-order botch which broke DNSSEC for TCP queries. 2015-04-28 20:45:57 +01:00
Johnny S. Lee
8efd731cc4 Make get-version work when repo is a git submodule. 2015-04-26 22:23:57 +01:00
Simon Kelley
a5ae1f8587 Logs in DHCPv6 not suppressed by dhcp6-quiet. 2015-04-25 21:46:10 +01:00
Simon Kelley
b8f16556d3 Tweaks to previous, DNS label charset commit. 2015-04-22 21:14:31 +01:00
Simon Kelley
cbe379ad6b Handle domain names with '.' or /000 within labels.
Only in DNSSEC mode, where we might need to validate or store
such names. In none-DNSSEC mode, simply don't cache these, as before.
2015-04-21 22:57:06 +01:00
Simon Kelley
338b340be9 Revert 61b838dd57 and just quieten log instead. 2015-04-20 21:34:05 +01:00
Moshe Levi
a006eb7e14 Check IP address command line arg in dhcp_release.c 2015-04-19 22:10:40 +01:00
Simon Kelley
554b580e97 Log domain when reporting DNSSEC validation failure. 2015-04-17 22:50:20 +01:00
Simon Kelley
0df29f5e23 Note CVE-2015-3294 2015-04-16 15:24:52 +01:00
Stefan Tomanek
b4c0f092d8 Fix (srk induced) crash in new tftp_no_fail code. 2015-04-16 15:20:59 +01:00
Simon Kelley
78c6184752 Auth: correct replies to NS and SOA in .arpa zones. 2015-04-16 15:05:30 +01:00
Simon Kelley
38440b204d Fix crash in auth code with odd configuration. 2015-04-12 21:52:47 +01:00
Simon Kelley
ad4a8ff7d9 Fix crash on receipt of certain malformed DNS requests. 2015-04-09 21:48:00 +01:00
Simon Kelley
04b0ac0537 Fix crash caused by looking up servers.bind when many servers defined. 2015-04-06 17:19:13 +01:00
Simon Kelley
982faf4024 Fix compiler warning when not including DNSSEC. 2015-04-03 21:42:30 +01:00
Simon Kelley
fe3992f9fa Return INSECURE, rather than BOGUS when DS proved not to exist.
Return INSECURE when validating DNS replies which have RRSIGs, but
when a needed DS record in the trust chain is proved not to exist.
It's allowed for a zone to set up DNSKEY and RRSIG records first, then
add a DS later, completing the chain of trust.

Also, since we don't have the infrastructure to track that these
non-validated replies have RRSIGS, don't cache them, so we don't
provide answers with missing RRSIGS from the cache.
2015-04-03 21:25:05 +01:00
Stefan Tomanek
7aa970e2c7 Whitespace fixes. 2015-04-01 17:55:07 +01:00
Stefan Tomanek
30d0879ed5 add --tftp-no-fail to ignore missing tftp root 2015-03-31 22:32:11 +01:00
Simon Kelley
fd6ad9e481 Merge message translations. 2015-03-30 07:52:21 +01:00
Simon Kelley
794fccca7f Fix crash in last commit. 2015-03-29 22:35:44 +01:00
Simon Kelley
394ff492da Allow control characters in names in the cache, handle when logging. 2015-03-29 22:17:14 +01:00
Simon Kelley
1e153945de DNSSEC fix for non-ascii characters in labels. 2015-03-28 21:34:07 +00:00
Simon Kelley
0b8a5a30a7 Protect against broken DNSSEC upstreams. 2015-03-27 11:44:55 +00:00
Simon Kelley
150162bc37 Return SERVFAIL when validation abandoned. 2015-03-27 09:58:26 +00:00
Simon Kelley
8805283088 Don't fail DNSSEC when a signed CNAME dangles into an unsigned zone. 2015-03-26 21:15:43 +00:00
Lung-Pin Chang
65c7212000 dhcp: set outbound interface via cmsg in unicast reply
If multiple routes to the same network exist, Linux blindly picks
  the first interface (route) based on destination address, which might not be
  the one we're actually offering leases. Rather than relying on this,
  always set the interface for outgoing unicast DHCP packets.
2015-03-19 23:22:21 +00:00
Simon Kelley
979fe86bc8 Make --address=/example.com/ equivalent to --server=/example.com/ 2015-03-19 22:50:22 +00:00
Simon Kelley
ff841ebf5a Fix boilerplate code for re-running system calls on EINTR and EAGAIN etc.
The nasty code with static variable in retry_send() which
avoids looping forever needs to be called on success of the syscall,
to reset the static variable.
2015-03-11 21:36:30 +00:00
Simon Kelley
360f2513ab Tweak DNSSEC timestamp code to create file later, removing need to chown it. 2015-03-07 18:28:06 +00:00
Simon Kelley
4c960fa90a New version of contrib/reverse-dns 2015-03-04 20:32:26 +00:00
Simon Kelley
9003b50b13 Fix last commit to not crash if uid changing not configured. 2015-03-02 22:47:23 +00:00
Simon Kelley
f6e62e2af9 Add --dnssec-timestamp option and facility. 2015-03-01 18:17:54 +00:00
Joachim Zobel
47b9ac59c7 Log parsing utils in contrib/reverse-dns 2015-02-23 21:38:11 +00:00
Tomas Hozza
0705a7e2d5 Fix uninitialized value used in get_client_mac() 2015-02-23 21:26:26 +00:00
Chen Wei
28b879ac47 Fix trivial memory leaks to quieten valgrind. 2015-02-17 22:07:35 +00:00
Simon Kelley
caeea190f1 Make dynamic hosts files work when --no-hosts set. 2015-02-14 20:08:56 +00:00
Simon Kelley
8ff70de618 Typos. 2015-02-14 20:02:37 +00:00
Simon Kelley
ee4d1cea92 Debian systemd fixes. 2015-02-12 18:30:32 +00:00
Shantanu Gadgil
f4f400776b Fix get-version script which returned wrong tag in some situations. 2015-02-11 20:16:59 +00:00
Chris Lamb
b467a454b4 Make Debian build reproducible. 2015-02-09 11:52:30 +00:00
Simon Kelley
efb8b5566a man page typo. 2015-02-07 22:36:34 +00:00
Simon Kelley
f9c863708c Extra logging for inotify code. 2015-02-03 21:52:48 +00:00
Simon Kelley
2941d3ac89 Fixup dhcp-configs after reading extra hostfiles with inotify. 2015-02-02 22:36:42 +00:00
Thiébaud Weksteen
d36b732c4c Manpage typo fix. 2015-02-02 21:38:27 +00:00
Simon Kelley
d2c5458e31 Debian changelog bugfix. 2015-02-02 21:27:39 +00:00
Simon Kelley
8d8a54ec79 Fix build failure on openBSD. 2015-02-01 21:48:46 +00:00
Simon Kelley
1062667618 BSD make support 2015-02-01 00:15:16 +00:00
Simon Kelley
6ef15b34ca Fix broken ECDSA DNSSEC signatures. 2015-01-31 22:44:26 +00:00
Simon Kelley
3d04f46334 inotify documentation updates. 2015-01-31 21:59:13 +00:00
Simon Kelley
aff3396280 Update copyrights for dawn of 2015. 2015-01-31 20:13:40 +00:00
Simon Kelley
70d1873dd9 Expand inotify code to dhcp-hostsdir, dhcp-optsdir and hostsdir. 2015-01-31 19:59:29 +00:00
Simon Kelley
0491805d2f Allow inotify to be disabled at compile time on Linux. 2015-01-26 11:23:43 +00:00
Win King Wan
61b838dd57 Don't reply to DHCPv6 SOLICIT messages when not configured for statefull DHCPv6. 2015-01-21 20:41:48 +00:00
Conrad Kostecki
fbf01f7046 Update German translation. 2015-01-20 21:07:56 +00:00
Simon Kelley
5f4dc5c6ca Add --dhcp-hostsdir config option. 2015-01-20 20:51:02 +00:00
Simon Kelley
2ae195f5a7 Don't treat SERVFAIL as a recoverable error..... 2015-01-18 22:20:48 +00:00
Simon Kelley
393415597c Cope with multiple interfaces with the same LL address. 2015-01-18 22:11:10 +00:00
Simon Kelley
ae4624bf46 Logs for DS records consistent. 2015-01-12 23:22:08 +00:00
Simon Kelley
5e321739db Don't answer from cache RRsets from wildcards, as we don't have NSECs. 2015-01-12 23:16:56 +00:00
Simon Kelley
9f79ee4ae3 Log port of requestor when doing extra logging. 2015-01-12 20:18:18 +00:00
RinSatsuki
28de38768e Add --min-cache-ttl option. 2015-01-10 15:22:21 +00:00
Simon Kelley
25cf5e373e Add --log-queries=extra option for more complete logging. 2015-01-09 15:53:03 +00:00
132 changed files with 55847 additions and 23858 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
VERSION export-subst

12
.gitignore vendored
View File

@@ -4,11 +4,7 @@ src/dnsmasq.pot
src/dnsmasq
src/dnsmasq_baseline
src/.copts_*
contrib/wrt/dhcp_lease_time
contrib/wrt/dhcp_release
debian/base/
debian/daemon/
debian/files
debian/substvars
debian/utils-substvars
debian/utils/
contrib/lease-tools/dhcp_lease_time
contrib/lease-tools/dhcp_release
contrib/lease-tools/dhcp_release6

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "debian"]
path = debian
url = git://thekelleys.org.uk/dnsmasq-debian.git
[submodule "submodules/dnsmasq-debian"]
path = submodules/dnsmasq-debian
url = https://thekelleys.org.uk/git/dnsmasq-debian

4239
CHANGELOG

File diff suppressed because it is too large Load Diff

View File

@@ -56,7 +56,7 @@ release 0.95 Major rewrite: remove calls to gethostbyname() and talk
any more memory after start-up. The NAT-like forwarding was
inspired by a suggestion from Eli Chen <eli@routefree.com>
release 0.96 Fixed embarrasing thinko in cache linked-list code.
release 0.96 Fixed embarrassing thinko in cache linked-list code.
release 0.98 Some enhancements and bug-fixes.
Thanks to "Denis Carre" <denis.carre@laposte.net> and Martin
@@ -78,7 +78,7 @@ release 0.98 Some enhancements and bug-fixes.
ids, to thwart DNS spoofers.
(7) Dnsmasq no longer forwards queries when the
"recursion desired" bit is not set in the header.
(8) Fixed getopt code to work on compliers with unsigned char.
(8) Fixed getopt code to work on compilers with unsigned char.
release 0.991 Added -b flag: when set causes dnsmasq to always answer
reverse queries on the RFC 1918 private IP space itself and
@@ -88,7 +88,7 @@ release 0.991 Added -b flag: when set causes dnsmasq to always answer
Fixed a bug which stopped dnsmasq working on a box with
two or more interfaces with the same IP address.
Fixed cacheing of CNAMEs. Previously, a CNAME which pointed
Fixed caching of CNAMEs. Previously, a CNAME which pointed
to a name with many A records would not have all the addresses
returned when being answered from the cache.
@@ -191,7 +191,7 @@ release 1.1 Added --user argument to allow user to change to
release 1.2 Added IPv6 DNS record support. AAAA records are cached
and read from /etc/hosts. Reverse-lookups in the
ip6.int and ip6.arpa domains are suppored. Dnsmasq can
ip6.int and ip6.arpa domains are supported. Dnsmasq can
talk to upstream servers via IPv6 if it finds IP6 addresses
in /etc/resolv.conf and it offers DNS service automatically
if IPv6 support is present in the kernel.
@@ -214,7 +214,7 @@ release 1.3 Some versions of the Linux kernel return EINVAL rather
starting, rather than after the first query - principle
of least surprise applies here.
release 1.4 Fix a bug with DHPC lease parsing which broke in
release 1.4 Fix a bug with DHCP lease parsing which broke in
non-UTC timezones. Thanks to Mark Wormgoor for
spotting and diagnosing this. Fixed versions in
the .spec files this time. Fixed bug in Suse startup
@@ -258,7 +258,7 @@ release 1.7 Fix a problem with cache not clearing properly
on receipt of SIGHUP. Bug spotted by Sat Deshpande.
In group-id changing code:
1) Drop supplimentary groups.
1) Drop supplementary groups.
2) Change gid before dropping root (patch from Soewono Effendi.)
3) Change group to "dip" if it exists, to allow access
to /etc/ppp/resolv.conf (suggestion from Jorg Sommer.)
@@ -297,7 +297,7 @@ release 1.9 Fixes to rpm .spec files.
required. The difference is not really visible with
bloated libcs like glibc, but should dramatically reduce
memory requirements when linked against ulibc for use on
embeded routers, and that's the point really. Thanks to
embedded routers, and that's the point really. Thanks to
Matthew Natalier for prompting this.
Changed debug mode (-d) so that all logging appears on
@@ -319,12 +319,12 @@ release 1.9 Fixes to rpm .spec files.
uClinux. Thanks to Matthew Natalier for uClinux stuff.
release 1.10 Log warnings if resolv.conf or dhcp.leases are not
accessable for any reason, as suggested by Hinrich Eilts.
accessible for any reason, as suggested by Hinrich Eilts.
Fixed wrong address printing in error message about
no interface with address.
Updated docs and split installation instuctions into setup.html.
Updated docs and split installation instructions into setup.html.
Fix bug in CNAME chasing code: One CNAME pointing
to many A records would lose A records after the
@@ -346,7 +346,7 @@ release 1.10 Log warnings if resolv.conf or dhcp.leases are not
Added -S option to directly specify upstream servers and
added ability to direct queries for specific domains to
specfic servers. Suggested by Jens Vonderheide.
specific servers. Suggested by Jens Vonderheide.
Upgraded random ID generation - patch from Rob Funk.
@@ -386,13 +386,13 @@ release 1.11 Actually implement the -R flag promised in the 1.10 man page.
names in /etc/hosts -suggestion from Phil Harman.
Always return a zero time-to-live for names derived from
DHCP which stops anthing else caching these
DHCP which stops anything else caching these
names. Previously the TTL was derived from the lease
time but that is incorrect since a lease can be given
up early: dnsmasq would know this but anything with the
name cached with long TTL would not be updated.
Extended HAVE_IPV6 config flag to allow compliation on
Extended HAVE_IPV6 config flag to allow compilation on
old systems which don't have modern library routines
like inet_ntop(). Thanks to Phil Harman for the patch.
@@ -471,7 +471,7 @@ release 1.14 Fixed man page description of -b option which confused
/etc/resolv.conf.
(Thanks to Klaas Teschauer)
Check that recieved queries have only rfc1035-legal characters
Check that received queries have only rfc1035-legal characters
in them. This check is mainly to avoid bad strings being
sent to syslog.
@@ -549,7 +549,7 @@ release 1.16 Allow "/" characters in domain names - this fixes
release 1.17 Fixed crash with DHCP hostnames > 40 characters.
Fixed name-comparision routines to not depend on Locale,
Fixed name-comparison routines to not depend on Locale,
in theory this versions since 1.15 could lock up or give
wrong results when run with locale != 'C'.
@@ -574,7 +574,7 @@ release 1.18 Added round-robin DNS for names which have more than one
forwarded because -D is in effect, return NXDOMAIN not
an empty reply.
Add code to return the software version in repsonse to the
Add code to return the software version in response to the
correct magic query in the same way as BIND. Use
"dig version.bind chaos txt" to make the query.
@@ -635,7 +635,7 @@ release 2.0
dynamic allocation.
Allow dhcp-host options for the same host with different
IP adresses where the correct one will be selected for
IP addresses where the correct one will be selected for
the network the host appears on.
Fix parsing of --dhcp-option to allow more than one
@@ -674,7 +674,7 @@ release 2.1
Fix unaligned access warnings on BSD/Alpha.
Allow empty DHCP options, like so: dhpc-option=44
Allow empty DHCP options, like so: dhcp-option=44
Allow single-byte DHCP options like so: dhcp-option=20,1
@@ -745,7 +745,7 @@ release 2.3
around a bug in the DHCP client in HP Jetdirect printers.
Thanks to Marko Stolle for finding this problem.
Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
Return DHCP T1 and T2 times, with "fuzz" to desynchronise lease
renewals, as specified in the RFC.
Ensure that the END option is always present in DHCP
@@ -838,7 +838,7 @@ release 2.4
by Chad Skeeters.
Fixed bug in /etc/ethers parsing code triggered by tab
characters. Qudos to Dag Wieers for hepling to nail that
characters. Kudos to Dag Wieers for helping to nail that
one.
Added "bind-interfaces" option correctly.
@@ -975,7 +975,7 @@ release 2.8
configuration. Specifically: (1) options are matched on
the netids from dhcp-range, dhcp-host, vendor class and
user class(es). Multiple net-ids are allowed and options
are searched on them all. (2) matches agains vendor class
are searched on them all. (2) matches against vendor class
and user class are now on a substring, if the given
string is a substring of the vendor/user class, then a
match occurs. Thanks again to Richard Musil for prompting
@@ -997,7 +997,7 @@ release 2.8
Add checks against DHCP clients which return zero-length
hostnames. This avoids the potential lease-loss problems
reffered to above. Also, if a client sends a hostname when
referred to above. Also, if a client sends a hostname when
it creates a lease but subsequently sends no or a
zero-length hostname whilst renewing, continue to use the
existing hostname, don't wipe it out.
@@ -1010,7 +1010,7 @@ release 2.9
but to the address of another interface were ignored
unless the loopback interface was explicitly configured.
2) on OpenBSD failure to configure one interface now
causes a fatal error on startup rather than an huge
causes a fatal error on startup rather than a huge
stream of log messages. Thanks to Erik Jan Tromp for
finding that bug.
@@ -1019,7 +1019,7 @@ release 2.9
broken. The new algorithm is to pick as before for the
first try, but if a query is retried, to send to all
available servers in parallel. The first one to reply
then becomes prefered for the next query. This should
then becomes preferred for the next query. This should
improve reliability without generating significant extra
upstream load.
@@ -1027,7 +1027,7 @@ release 2.9
unqualified domains introduced in version 2.8
Allow fallback to "bind-interfaces" at runtime: Some
verions of *BSD seem to have enough stuff in the header
versions of *BSD seem to have enough stuff in the header
files to build but no kernel support. Also now log if
"bind-interfaces" is forced on.
@@ -1049,7 +1049,7 @@ release 2.9
first name found is now returned for reverse lookups,
rather than all of them.
Add back fatal errors when nonexistant
Add back fatal errors when nonexistent
interfaces or interface addresses are given but only in
"bind-interfaces" mode. Principle of least surprise applies.
@@ -1193,7 +1193,7 @@ version 2.14
version 2.15
Fixed NXDOMAIN/NODATA confusion for locally known
names. We now return a NODATA reponse for names which are
names. We now return a NODATA response for names which are
locally known. Now a query for (eg AAAA or MX) for a name
with an IPv4 address in /etc/hosts which fails upstream
will generate a NODATA response. Note that the query
@@ -1229,7 +1229,7 @@ version 2.16
Set NONBLOCK on all listening sockets to workaround non-POSIX
compliance in Linux 2.4 and 2.6. This fixes rare hangs which
occured when corrupted packets were received. Thanks to
occurred when corrupted packets were received. Thanks to
Joris van Rantwijk for chasing that down.
Updated config.h for NetBSD. Thanks to Martin Lambers.
@@ -1297,7 +1297,7 @@ version 2.18
interfaces with more than one IPv6 address. Thanks to
Martin Pels for help with that.
Fix problems which occured when more than one dhcp-range
Fix problems which occurred when more than one dhcp-range
was specified in the same subnet: sometimes parameters
(lease time, network-id tag) from the wrong one would be
used. Thanks to Rory Campbell-Lange for the bug report.
@@ -1314,7 +1314,7 @@ version 2.19
Thanks to Richard Atterer for the bug report.
Check for under-length option fields in DHCP packets, a
zero length client-id, in particluar, could seriously
zero length client-id, in particular, could seriously
confuse dnsmasq 'till now. Thanks to Will Murname for help
with that.
@@ -1389,7 +1389,7 @@ version 2.21
recursive queries.
Fix DHCP address allocation problem when netid tags are in
use. Thanks to Will Murnane for the bug report and
use. Thanks to Will Murname for the bug report and
subsequent testing.
Add an additional data section to the reply for MX and SRV
@@ -1505,7 +1505,7 @@ version 2.23
from dnsmasq --version. Thanks to Dirk Schenkewitz for
the suggestion.
Fix pathalogical behaviour when a broken client keeps sending
Fix pathological behaviour when a broken client keeps sending
DHCPDISCOVER messages repeatedly and fast. Because dealing with
each of these takes a few seconds, (because of the ping) then a
queue of DHCP packets could build up. Now, the results of a ping
@@ -1593,7 +1593,7 @@ version 2.24
than one dhcp-range is available. Thanks to Sorin Panca
for help chasing this down.
Added more explict error mesages to the hosts file and
Added more explicit error messages to the hosts file and
ethers file reading code. Markus Kaiserswerth suffered to
make this happen.
@@ -1617,7 +1617,7 @@ version 2.25
Fixed Suse spec file - thanks to Steven Springl.
Fixed DHCP bug when two distict subnets are on the same
Fixed DHCP bug when two distinct subnets are on the same
physical interface. Thanks to Pawel Zawora for finding
this and suggesting the fix.
@@ -1740,7 +1740,7 @@ version 2.28
Fixed regression in netlink code under 2.2.x kernels which
occurred in 2.27. Erik Jan Tromp is the vintage kernel fan
who found this. P.S. It looks like this "netlink bind:
permission denied" problem occured in kernels at least as
permission denied" problem occurred in kernels at least as
late a 2.4.18. Good information from Alain Richoux.
Added a warning when it's impossible to give a host its
@@ -1761,7 +1761,7 @@ version 2.28
Eric House and Eric Spakman for help in chasing this down.
Tolerate configuration screwups which lead to the DHCP
server attemping to allocate its own address to a
server attempting to allocate its own address to a
client; eg setting the whole subnet range as a DHCP
range. Addresses in use by the server are now excluded
from use by clients.
@@ -2067,7 +2067,7 @@ version 2.36
kernel. Thanks to Philip Wall for the bug report.
Added --dhcp-bridge option, but only to the FreeBSD
build. This fixes an oddity with a a particular bridged
build. This fixes an oddity with a particular bridged
network configuration on FreeBSD. Thanks to Luigi Rizzo
for the patch.
@@ -2273,7 +2273,7 @@ version 2.40
this.
Use client-id as hash-seed for DHCP address allocation
with Firewire and Infiniband, as these don't supply an MAC
with Firewire and InfiniBand, as these don't supply a MAC
address.
Tweaked TFTP file-open code to make it behave sensibly
@@ -2307,7 +2307,7 @@ version 2.40
Continue to use unqualified hostnames provided by DHCP
clients, even if the domain part is illegal. (The domain
is ignored, and an error logged.) Previously in this
situation, the whole name whould have been
situation, the whole name would have been
rejected. Thanks to Jima for the patch.
Handle EINTR returns from wait() correctly and reap
@@ -2319,7 +2319,7 @@ version 2.40
leases file and passed to the lease-change
script. Suggestion from Ben Voigt.
Re-run the lease chamge script with an "old" event for
Re-run the lease change script with an "old" event for
each lease when dnsmasq receives a SIGHUP.
Added more useful exit codes, including passing on a
@@ -2417,7 +2417,7 @@ version 2.41
Changed behavior of DHCP server to always return total length of
a new lease in DHCPOFFER, even if an existing lease
exists. (It used to return the time remaining on the lease
whne one existed.) This fixes problems with the Sony Ericsson
when one existed.) This fixes problems with the Sony Ericsson
K610i phone. Thanks to Hakon Stordahl for finding and
fixing this.
@@ -2433,7 +2433,7 @@ version 2.41
Add --dhcp-match flag, to check for arbitrary options in
DHCP messages from clients. This enables use of dnsmasq
with gPXE. Thanks to Rance Hall for the suggestion.
with iPXE. Thanks to Rance Hall for the suggestion.
Added --dhcp-broadcast, to force broadcast replies to DHCP
clients which need them but are too dumb or too old to
@@ -2476,7 +2476,7 @@ version 2.42
Fix OS detection logic to cope with GNU/FreeBSD.
Fix unitialised variable in DBus code - thanks to Roy
Fix uninitialised variable in DBus code - thanks to Roy
Marples.
Fix network enumeration code to work on later NetBSD -

43
COPYING
View File

@@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

94
FAQ
View File

@@ -9,7 +9,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
from port 53 the replies would be _to_ port 53 and get blocked.
This is not a security hole since dnsmasq will only accept replies to that
port: queries are dropped. The replies must be to oustanding queries
port: queries are dropped. The replies must be to outstanding queries
which dnsmasq has forwarded, otherwise they are dropped too.
Addendum: dnsmasq now has the option "query-port" (-Q), which allows
@@ -59,7 +59,7 @@ A: Yes, there is explicit support for *BSD and MacOS X and Solaris.
Q: My company's nameserver knows about some names which aren't in the
public DNS. Even though I put it first in /etc/resolv.conf, it
dosen't work: dnsmasq seems not to use the nameservers in the order
doesn't work: dnsmasq seems not to use the nameservers in the order
given. What am I doing wrong?
A: By default, dnsmasq treats all the nameservers it knows about as
@@ -144,19 +144,19 @@ Q: Who are Verisign, what do they have to do with the bogus-nxdomain
option in dnsmasq and why should I wory about it?
A: [note: this was written in September 2003, things may well change.]
Versign run the .com and .net top-level-domains. They have just
Verisign run the .com and .net top-level-domains. They have just
changed the configuration of their servers so that unknown .com and
.net domains, instead of returning an error code NXDOMAIN, (no such
domain) return the address of a host at Versign which runs a web
domain) return the address of a host at Verisign which runs a web
server showing a search page. Most right-thinking people regard
this new behaviour as broken :-). You can test to see if you are
suffering Versign brokeness by run a command like
suffering Verisign brokenness by run a command like
host jlsdajkdalld.com
If you get "jlsdajkdalld.com" does not exist, then all is fine, if
host returns an IP address, then the DNS is broken. (Try a few
different unlikely domains, just in case you picked a wierd one
different unlikely domains, just in case you picked a weird one
which really _is_ registered.)
Assuming that your DNS is broken, and you want to fix it, simply
@@ -180,7 +180,7 @@ A: There are a couple of configuration gotchas which have been
whilst the ISC one works.
The first thing to check is the broadcast address set for the
ethernet interface. This is normally the adddress on the connected
ethernet interface. This is normally the address on the connected
network with all ones in the host part. For instance if the
address of the ethernet interface is 192.168.55.7 and the netmask
is 255.255.255.0 then the broadcast address should be
@@ -205,7 +205,7 @@ A: By default, none of the DHCP clients send the host-name when asking
send with the "hostname" keyword in /etc/network/interfaces. (See
"man interfaces" for details.) That doesn't work for dhclient, were
you have to add something like "send host-name daisy" to
/etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send
/etc/dhclient.conf [Update: the latest dhcpcd packages _do_ send
the hostname by default.
Q: I'm network booting my machines, and trying to give them static
@@ -236,11 +236,11 @@ Q: What network types are supported by the DHCP server?
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
Linux all network types (including FireWire) are supported.
Q: What are these strange "bind-interface" and "bind-dynamic" options?
Q: What are these strange "bind-interfaces" and "bind-dynamic" options?
A: Dnsmasq from v2.63 can operate in one of three different "networking
modes". This is unfortunate as it requires users configuring dnsmasq
to take into account some rather bizzare contraints and select the
to take into account some rather bizarre constraints and select the
mode which best fits the requirements of a particular installation.
The origin of these are deficiencies in the Unix networking
model and APIs and each mode has different advantages and
@@ -252,10 +252,10 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
::). This allows it to recieve all the packets sent to the server on
::). This allows it to receive all the packets sent to the server on
the relevant port. Access control (--interface, --except-interface,
--listen-address, etc) is implemented by dnsmasq: it queries the
kernel to determine the interface on which a packet was recieved and
kernel to determine the interface on which a packet was received and
the address to which it was sent, and applies the configured
rules. Wildcard mode is the default if neither of the other modes are
specified.
@@ -276,7 +276,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
The mode chosen has four different effects: co-existence with other
servers, semantics of --interface access control, effect of new
interfaces, and legality of --interface specifications for
non-existent inferfaces. We will deal with these in order.
non-existent interfaces. We will deal with these in order.
A dnsmasq instance running in wildcard mode precludes a machine from
running a second instance of dnsmasq or any other DNS, TFTP or DHCP
@@ -297,7 +297,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
mode, such interfaces are handled normally.
A --interface specification for a non-existent interface is a fatal
An --interface specification for a non-existent interface is a fatal
error at start-up when in --bind-interfaces mode, by just generates a
warning in wildcard or bind-dynamic mode.
@@ -313,15 +313,25 @@ Q: Can I get email notification when a new version of dnsmasq is
released?
A: Yes, new releases of dnsmasq are always announced through
freshmeat.net, and they allow you to subcribe to email alerts when
freshmeat.net, and they allow you to subscribe to email alerts when
new versions of particular projects are released. New releases are
also announced in the dnsmasq-discuss mailing list, subscribe at
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
Q: What does the dhcp-authoritative option do?
A: See http://www.isc.org/files/auth.html - that's
for the ISC daemon, but the same applies to dnsmasq.
A: The DHCP spec says that when a DHCP server receives a renewal request
from a client it has no knowledge of, it should just ignore it.
This is because it's supported to have more than one DHCP server
on a network, and another DHCP server may be dealing with the client.
This has the unfortunate effect that when _no_ DHCP replies to
the client, it takes some time for the client to time-out and start
to get a new lease. Setting this option makes dnsmasq violate the
standard to the extent that it will send a NAK reply to the client,
causing it to immediately start to get a new lease. This improves
behaviour when machines move networks, and in the case that the DHCP
lease database is lost. As long as there are not more tha one DHCP
server on the network, it's safe to enable the option.
Q: Why does my Gentoo box pause for a minute before getting a new
lease?
@@ -349,18 +359,64 @@ A: By default, the identity of a machine is determined by using the
method for setting the client-id varies with DHCP client software,
dhcpcd uses the "-I" flag. Windows uses a registry setting,
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
Addendum:
From version 2.46, dnsmasq has a solution to this which doesn't
involve setting client-IDs. It's possible to put more than one MAC
address in a --dhcp-host configuration. This tells dnsmasq that it
should use the specified IP for any of the specified MAC addresses,
and furthermore it gives dnsmasq permission to sumarily abandon a
and furthermore it gives dnsmasq permission to summarily abandon a
lease to one of the MAC addresses if another one comes along. Note
that this will work fine only as longer as only one interface is
up at any time. There is no way for dnsmasq to enforce this
constraint: if you configure multiple MAC addresses and violate
this rule, bad things will happen.
Addendum-II: The link above is dead, the former contents of the link are:
------------------------------------------------------------------------------
How can I keep the same DHCP client reservation, if the MAC address changes?
When you reserve an IP address for a DHCP client, you provide the
MAC address of the client's NIC.
It is possible to use a custom identifier, which is sent as
option 61 in the client's DHCP Discover and Request packet.
The DhcpClientIdentifier is a REG_DWORD value that is located at:
Windows NT 4.0 SP2+
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Adapter Name>'X'\Parameters\Tcpip
where <Adapter Name> is the NIC driver name and 'X' is the number of the NIC.
Windows 2000
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TcpIp\Parameters\Interfaces\<NIC GUID>
where <NIC GUID> is the GUID of the NIC.
The valid range of data is 0x0 - 0xFFFFFFFF. The custom identifier is send as 4 bytes,
8 hexadecimal character, in groups of 2 hexadecimal characters, with the groups being
sent in reverse order. If the custom identifier is less than 8 hexadeciaml characters,
it is zero padded at the end. Examples:
Custom Client Client Reservation
Identifier on DHCP Server
12345678 78563412
123456 56341200
1234 34120000
1234567 67452301
12345 45230100
123 23010000
A18F42 428FA100
CF432 32F40C00
C32D1BE BED1320C
-------------------------------------------------------------------------------------------------------
Q: Can dnsmasq do DHCP on IP-alias interfaces?
A: Yes, from version-2.21. The support is only available running under
@@ -488,7 +544,7 @@ Q: DHCP doesn't work with windows 7 but everything else is fine.
A: There seems to be a problem if Windows 7 doesn't get a value for
DHCP option 252 in DHCP packets it gets from the server. The
symtoms have beeen variously reported as continual DHCPINFORM
symptoms have been variously reported as continual DHCPINFORM
requests in an attempt to get an option-252, or even ignoring DHCP
offers completely (and failing to get an IP address) if there is no
option-252 supplied. DHCP option 252 is for WPAD, WWW Proxy

View File

@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2014 Simon Kelley
# dnsmasq is Copyright (c) 2000-2025 Simon Kelley
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@ LDFLAGS =
COPTS =
RPM_OPT_FLAGS =
LIBS =
LUA = lua
#################################################################
@@ -53,34 +54,43 @@ top?=$(CURDIR)
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS "" --copy '-lubox -lubus'`
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
idn2_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --libs libidn2`
ct_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
ct_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.1`
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1`
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags $(LUA)`
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs $(LUA)`
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags 'nettle hogweed'`
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs 'nettle hogweed'`
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
copts_conf = .copts_$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | \
( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
nft_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_NFTSET $(PKG_CONFIG) --cflags libnftables`
nft_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_NFTSET $(PKG_CONFIG) --libs libnftables`
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
sum?=$(shell echo $(CC) -DDNSMASQ_COMPILE_FLAGS="$(CFLAGS)" -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
sum!=echo $(CC) -DDNSMASQ_COMPILE_FLAGS="$(CFLAGS)" -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' '
copts_conf = .copts_$(sum)
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o pattern.o \
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o \
metrics.o domain-match.o nftset.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
all : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
top="$(top)" \
build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \
-f $(top)/Makefile dnsmasq
mostly_clean :
@@ -92,10 +102,9 @@ clean : mostly_clean
rm -f core */core
rm -f *~ contrib/*/*~ */*~
install : all install-common
install-common :
$(INSTALL) -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
install : all
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)
@@ -103,24 +112,28 @@ all-i18n : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
top="$(top)" \
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
build_cflags="$(version) $(dbus_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) `$(PKG_CONFIG) --cflags libidn`" \
build_libs="$(dbus_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) `$(PKG_CONFIG) --libs libidn`" \
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \
-f $(top)/Makefile dnsmasq
for f in `cd $(PO); echo *.po`; do \
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
done
install-i18n : all-i18n install-common
install-i18n : all-i18n
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)
cd $(BUILDDIR); $(top)/bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
merge :
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
@cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile dnsmasq.pot
for f in `cd $(PO); echo *.po`; do \
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
done
# Cannonicalise .po file.
# Canonicalise .po file.
%.po :
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
mv $(PO)/$*.po $(PO)/$*.po.orig && $(MSGMERGE) --no-wrap $(PO)/$*.po.orig $(BUILDDIR)/dnsmasq.pot >$(PO)/$*.po;
@@ -139,7 +152,7 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all
$(top)/bld/bloat-o-meter dnsmasq_baseline dnsmasq; \
size dnsmasq_baseline dnsmasq
# rules below are targets in recusive makes with cwd=$(BUILDDIR)
# rules below are targets in recursive makes with cwd=$(BUILDDIR)
$(copts_conf): $(hdrs)
@rm -f *.o .copts_*

View File

@@ -10,13 +10,15 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
radv.c slaac.c auth.c ipset.c domain.c \
dnssec.c dnssec-openssl.c blockdata.c tables.c \
loop.c inotify.c
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
crypto.c dump.c ubus.c metrics.c \
domain-match.c nftset.c
LOCAL_MODULE := dnsmasq
LOCAL_C_INCLUDES := external/dnsmasq/src
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_TFTP -DNO_SCRIPT
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

View File

@@ -9,18 +9,29 @@
# If we can find one which matches $v[0-9].* then we assume it's
# a version-number tag, else we just use the whole string.
# If there is more than one v[0-9].* tag, sort them and use the
# first. This favours, eg v2.63 over 2.63rc6.
# first. The insane arguments to the sort command are to ensure
# that, eg v2.64 comes before v2.63, but v2.63 comes before v2.63rc1
# and v2.63rc1 comes before v2.63test1
if which git >/dev/null 2>&1 && [ -d $1/.git ]; then
cd $1; git describe | sed 's/^v//'
# Change directory to the toplevel source directory.
if test -z "$1" || ! test -d "$1" || ! cd "$1"; then
echo "$0: First argument $1 must be toplevel dir." >&2
exit 1
fi
if which git >/dev/null 2>&1 && \
([ -d .git ] || grep '^gitdir:' .git >/dev/null 2>&1) && \
git describe >/dev/null 2>&1; then
git describe | sed 's/^v//'
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
# unsubstituted VERSION, but no git available.
# unsubstituted VERSION, but no git available.
echo UNKNOWN
else
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
if [ $? -eq 0 ]; then
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
echo "${vers}" | sort -k1.2,1.5Vr -k1.6,1.6 -k1.8,1.9Vr -k1.10,1.11Vr | head -n 1 | sed 's/^v//'
else
cat $1/VERSION
fi

View File

@@ -1,33 +1,37 @@
#!/bin/sh
search=$1
shift
pkg=$1
shift
op=$1
shift
in=`cat`
if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
echo $in | grep $search >/dev/null 2>&1; then
# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP
search()
{
grep "^\#[[:space:]]*define[[:space:]]*$1" config.h >/dev/null 2>&1 || \
echo $in | grep $1 >/dev/null 2>&1
}
while [ "$#" -gt 0 ]; do
search=$1
pkg=$2
op=$3
lib=$4
shift 4
if search "$search"; then
# Nasty, nasty, in --copy, arg 2 (if non-empty) is another config to search for, used with NO_GMP
if [ $op = "--copy" ]; then
if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
echo $in | grep $pkg >/dev/null 2>&1; then
if [ -z "$pkg" ]; then
pkg="$lib"
elif search "$pkg"; then
pkg=""
else
pkg="$*"
pkg="$lib"
fi
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
pkg=`$pkg --static $op $*`
elif search "${search}_STATIC"; then
pkg=`$pkg --static $op $lib`
else
pkg=`$pkg $op $*`
pkg=`$pkg $op $lib`
fi
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
if search "${search}_STATIC"; then
if [ $op = "--libs" ] || [ $op = "--copy" ]; then
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
else
@@ -38,3 +42,4 @@ if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
fi
fi
done

View File

@@ -22,7 +22,7 @@ sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
Optionally, edit your dnsmasq configuration file to your liking.
To start the launchd job, which starts dnsmaq, reboot or use the command:
To start the launchd job, which starts dnsmasq, reboot or use the command:
sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
To stop the launchd job, which stops dnsmasq, use the command:

View File

@@ -1,6 +0,0 @@
This packaging is now unmaintained in the dnsmasq source: dnsmasq is
included in Suse proper, and up-to-date packages are now available
from
ftp://ftp.suse.com/pub/people/ug/

View File

@@ -1,27 +0,0 @@
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
It fixes the depancy from the dns daemon name 'named'
After appending the patch, the SuSEfirewall is again able to autodetect
the dnsmasq named service.
This is a very old bug in the SuSEfirewall script.
The SuSE people think the name of the dns server will allways 'named'
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
+++ /sbin/SuSEfirewall2 2004-01-23 13:31:56.000000000 +0100
@@ -764,7 +764,7 @@
echo 'FW_ALLOW_INCOMING_HIGHPORTS_UDP should be set to yes, if you are running a DNS server!'
test "$FW_SERVICE_AUTODETECT" = yes -o "$FW_SERVICE_AUTODETECT" = dmz -o "$FW_SERVICE_AUTODETECT" = ext && {
- test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv named && {
+ test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv dnsmasq && {
echo -e 'Warning: detected activated named, enabling FW_SERVICE_DNS!
You still have to allow tcp/udp port 53 on internal, dmz and/or external.'
FW_SERVICE_DNS=$FW_SERVICE_AUTODETECT
@@ -878,7 +878,7 @@
test -e /etc/resolv.conf || echo "Warning: /etc/resolv.conf not found"
# Get ports/IP bindings of NAMED/SQUID
test "$FW_SERVICE_DNS" = yes -o "$FW_SERVICE_DNS" = dmz -o "$FW_SERVICE_DNS" = ext -o "$START_NAMED" = yes && DNS_PORT=`$LSOF -i -n -P | \
- $AWK -F: '/^named .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
+ $AWK -F: '/^dnsmasq .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
test "$FW_SERVICE_SQUID" = yes -o "$FW_SERVICE_SQUID" = dmz -o "$FW_SERVICE_SQUID" = ext -o "$START_SQUID" = yes && SQUID_PORT=`$LSOF -i -n -P | \
$AWK -F: '/^squid .* UDP/ {print $2}'| $SORT -un`

View File

@@ -1,23 +0,0 @@
--- man/dnsmasq.8 2004-08-08 20:57:56.000000000 +0200
+++ man/dnsmasq.8 2004-08-12 00:40:01.000000000 +0200
@@ -69,7 +69,7 @@
.TP
.B \-g, --group=<groupname>
Specify the group which dnsmasq will run
-as. The defaults to "dip", if available, to facilitate access to
+as. The defaults to "dialout", if available, to facilitate access to
/etc/ppp/resolv.conf which is not normally world readable.
.TP
.B \-v, --version
--- src/config.h 2004-08-11 11:39:18.000000000 +0200
+++ src/config.h 2004-08-12 00:40:01.000000000 +0200
@@ -44,7 +44,7 @@
#endif
#define DEFLEASE 3600 /* default lease time, 1 hour */
#define CHUSER "nobody"
-#define CHGRP "dip"
+#define CHGRP "dialout"
#define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68

View File

@@ -1,111 +0,0 @@
###############################################################################
#
# General
#
###############################################################################
Name: dnsmasq
Version: 2.33
Release: 1
Copyright: GPL
Group: Productivity/Networking/DNS/Servers
Vendor: Simon Kelley
Packager: Simon Kelley
URL: http://www.thekelleys.org.uk/dnsmasq
Provides: dns_daemon
Conflicts: bind bind8 bind9
PreReq: %fillup_prereq %insserv_prereq
Autoreqprov: on
Source0: %{name}-%{version}.tar.bz2
BuildRoot: /var/tmp/%{name}-%{version}
Summary: A lightweight caching nameserver
%description
Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It
is designed to provide DNS and, optionally, DHCP, to a small network. It can
serve the names of local machines which are not in the global DNS. The DHCP
server integrates with the DNS server and allows machines with DHCP-allocated
addresses to appear in the DNS with names configured either in each host or
in a central configuration file. Dnsmasq supports static and dynamic DHCP
leases and BOOTP for network booting of diskless machines.
###############################################################################
#
# Build
#
###############################################################################
%prep
%setup -q
patch -p0 <rpm/%{name}-SuSE.patch
%build
%{?suse_update_config:%{suse_update_config -f}}
make all-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
###############################################################################
#
# Install
#
###############################################################################
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p ${RPM_BUILD_ROOT}/etc/init.d
make install-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
install -o root -g root -m 755 rpm/rc.dnsmasq-suse $RPM_BUILD_ROOT/etc/init.d/dnsmasq
install -o root -g root -m 644 dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
strip $RPM_BUILD_ROOT/usr/sbin/dnsmasq
ln -sf ../../etc/init.d/dnsmasq $RPM_BUILD_ROOT/usr/sbin/rcdnsmasq
###############################################################################
#
# Clean up
#
###############################################################################
%clean
rm -rf $RPM_BUILD_ROOT
###############################################################################
#
# Post-install scriptlet
#
###############################################################################
%post
%{fillup_and_insserv dnsmasq}
###############################################################################
#
# Post-uninstall scriptlet
#
# The %postun script executes after the package has been removed. It is the
# last chance for a package to clean up after itself.
#
###############################################################################
%postun
%{insserv_cleanup}
###############################################################################
#
# File list
#
###############################################################################
%files
%defattr(-,root,root)
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
%doc contrib
%config /etc/init.d/dnsmasq
%config /etc/dnsmasq.conf
/usr/sbin/rcdnsmasq
/usr/sbin/dnsmasq
/usr/share/locale/*/LC_MESSAGES/*
%doc %{_mandir}/man8/dnsmasq.8.gz
%doc %{_mandir}/*/man8/dnsmasq.8.gz

View File

@@ -1,79 +0,0 @@
#! /bin/sh
#
# init.d/dnsmasq
#
### BEGIN INIT INFO
# Provides: dnsmasq
# Required-Start: $network $remote_fs $syslog
# Required-Stop:
# Default-Start: 3 5
# Default-Stop:
# Description: Starts internet name service masq caching server (DNS)
### END INIT INFO
NAMED_BIN=/usr/sbin/dnsmasq
NAMED_PID=/var/run/dnsmasq.pid
NAMED_CONF=/etc/dnsmasq.conf
if [ ! -x $NAMED_BIN ] ; then
echo -n "dnsmasq not installed ! "
exit 5
fi
. /etc/rc.status
rc_reset
case "$1" in
start)
echo -n "Starting name service masq caching server "
checkproc -p $NAMED_PID $NAMED_BIN
if [ $? -eq 0 ] ; then
echo -n "- Warning: dnsmasq already running ! "
else
[ -e $NAMED_PID ] && echo -n "- Warning: $NAMED_PID exists ! "
fi
startproc -p $NAMED_PID $NAMED_BIN -u nobody
rc_status -v
;;
stop)
echo -n "Shutting name service masq caching server "
checkproc -p $NAMED_PID $NAMED_BIN
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
killproc -p $NAMED_PID -TERM $NAMED_BIN
rc_status -v
;;
try-restart)
$0 stop && $0 start
rc_status
;;
restart)
$0 stop
$0 start
rc_status
;;
force-reload)
$0 reload
rc_status
;;
reload)
echo -n "Reloading name service masq caching server "
checkproc -p $NAMED_PID $NAMED_BIN
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
killproc -p $NAMED_PID -HUP $NAMED_BIN
rc_status -v
;;
status)
echo -n "Checking for name service masq caching server "
checkproc -p $NAMED_PID $NAMED_BIN
rc_status -v
;;
probe)
test $NAMED_CONF -nt $NAMED_PID && echo reload
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
exit 1
;;
esac
rc_exit

View File

@@ -13,10 +13,10 @@ connection comes out of the other side. However, sometimes, we want to
maintain that relationship through the proxy and continue the connection
mark on packets upstream of our proxy
DNSMasq includes such a feature enabled by the --conntrack
Dnsmasq includes such a feature enabled by the --conntrack
option. This allows, for example, using iptables to mark traffic from
a particular IP, and that mark to be persisted to requests made *by*
DNSMasq. Such a feature could be useful for bandwidth accounting,
Dnsmasq. Such a feature could be useful for bandwidth accounting,
captive portals and the like. Note a similar feature has been
implemented in Squid 2.2
@@ -40,7 +40,7 @@ on IP address. 3) Saves the firewall mark back to the connection mark
(which will persist it across related packets)
4) is applied to the OUTPUT table, which is where we first see packets
generated locally. DNSMasq will have already copied the firewall mark
generated locally. Dnsmasq will have already copied the firewall mark
from the request, across to the new packet, and so all that remains is
for iptables to copy it to the connection mark so it's persisted across
packets.

View File

@@ -55,7 +55,7 @@ Index: src/dnsmasq.c
}
@@ -434,7 +433,7 @@
/* lose the setuid and setgid capbilities */
/* lose the setuid and setgid capabilities */
if (capset(hdr, data) == -1)
{
- send_event(err_pipe[1], EVENT_CAP_ERR, errno);

View File

@@ -0,0 +1,6 @@
CFLAGS?= -O2 -Wall -W
all: dhcp_release dhcp_release6 dhcp_lease_time
clean:
rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time

View File

@@ -83,7 +83,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
if (p >= end - 2)
return NULL; /* malformed packet */
opt_len = option_len(p);
if (p >= end - (2 + opt_len))
if (end - p < (2 + opt_len))
return NULL; /* malformed packet */
if (*p == opt && opt_len >= minsize)
return p;
@@ -153,7 +153,11 @@ int main(int argc, char **argv)
exit(1);
}
lease.s_addr = inet_addr(argv[1]);
if (inet_pton(AF_INET, argv[1], &lease) < 1)
{
fprintf(stderr, "invalid address: %s\n", argv[1]);
exit(1);
}
memset(&packet, 0, sizeof(packet));
@@ -168,7 +172,7 @@ int main(int argc, char **argv)
*(p++) = 1;
*(p++) = DHCPINFORM;
/* Explicity request the lease time, it won't be sent otherwise:
/* Explicitly request the lease time, it won't be sent otherwise:
this is a dnsmasq extension, not standard. */
*(p++) = OPTION_REQUESTED_OPTIONS;
*(p++) = 1;
@@ -176,8 +180,8 @@ int main(int argc, char **argv)
*(p++) = OPTION_END;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_family = AF_INET;
(void)inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr);
dest.sin_port = ntohs(DHCP_SERVER_PORT);
if (sendto(fd, &packet, sizeof(packet), 0,
@@ -206,13 +210,13 @@ int main(int argc, char **argv)
{
unsigned int x;
if ((x = t/86400))
printf("%dd", x);
printf("%ud", x);
if ((x = (t/3600)%24))
printf("%dh", x);
printf("%uh", x);
if ((x = (t/60)%60))
printf("%dm", x);
printf("%um", x);
if ((x = t%60))
printf("%ds", x);
printf("%us", x);
}
return 0;
}

View File

@@ -117,7 +117,7 @@ static ssize_t netlink_recv(int fd)
msg.msg_flags = 0;
while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
/* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
/* 2.2.x doesn't support MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
big buffer and pray in that case. */
if (rc == -1 && errno == EOPNOTSUPP)
{
@@ -178,7 +178,7 @@ static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
}
static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index)
static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index, int ifrfd, struct ifreq *ifr)
{
struct sockaddr_nl addr;
struct nlmsghdr *h;
@@ -218,7 +218,17 @@ static struct in_addr find_interface(struct in_addr client, int fd, unsigned int
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
if (h->nlmsg_type == NLMSG_DONE)
exit(0);
{
/* No match found, return first address as src/dhcp.c code does */
ifr->ifr_addr.sa_family = AF_INET;
if (ioctl(ifrfd, SIOCGIFADDR, ifr) != -1)
return ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
else
{
fprintf(stderr, "error: local IPv4 address not found\n");
exit(1);
}
}
else if (h->nlmsg_type == RTM_NEWADDR)
{
struct ifaddrmsg *ifa = NLMSG_DATA(h);
@@ -270,16 +280,22 @@ int main(int argc, char **argv)
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
a DHCP server */
strcpy(ifr.ifr_name, argv[1]);
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
{
perror("cannot setup interface");
exit(1);
}
if (inet_pton(AF_INET, argv[2], &lease.s_addr) < 1)
{
perror("invalid ip address");
exit(1);
}
lease.s_addr = inet_addr(argv[2]);
server = find_interface(lease, nl, if_nametoindex(argv[1]));
server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr);
memset(&packet, 0, sizeof(packet));

View File

@@ -0,0 +1,38 @@
.TH DHCP_RELEASE 1
.SH NAME
dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server.
.SH SYNOPSIS
.B dhcp_release6 --iface <interface> --client-id <client-id> --server-id
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
.SH "DESCRIPTION"
A utility which forces the DHCP server running on this machine to release a
DHCPv6 lease.
.SS OPTIONS
.IP "-a, --ip"
IPv6 address to release.
.IP "-c, --client-id"
Colon-separated hex string representing DHCPv6 client id. Normally
it can be found in leases file both on client and server.
.IP "-d, --dry-run"
Print hexadecimal representation of generated DHCPv6 release packet to standard
output and exit.
.IP "-h, --help"
print usage information to standard output and exit.
.IP "-i, --iaid"
Decimal representation of DHCPv6 IAID. Normally it can be found in leases file
both on client and server.
.IP "-n, --iface"
Network interface to send a DHCPv6 release packet from.
.IP "-s, --server-id"
Colon-separated hex string representing DHCPv6 server id. Normally
it can be found in leases file both on client and server.
.SH NOTES
MUST be run as root - will fail otherwise.
.SH LIMITATIONS
Only usable on IPv6 DHCP leases.
.SH SEE ALSO
.BR dnsmasq (8)
.SH AUTHOR
This manual page was written by Simon Kelley <simon@thekelleys.org.uk>.

View File

@@ -0,0 +1,508 @@
/*
dhcp_release6 --iface <interface> --client-id <client-id> --server-id
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
MUST be run as root - will fail otherwise
*/
/* Send a DHCPRELEASE message to IPv6 multicast address via the specified interface
to tell the local DHCP server to delete a particular lease.
The interface argument is the interface in which a DHCP
request _would_ be received if it was coming from the client,
rather than being faked up here.
The client-id argument is colon-separated hex string and mandatory. Normally
it can be found in leases file both on client and server
The server-id argument is colon-separated hex string and mandatory. Normally
it can be found in leases file both on client and server.
The iaid argument is numeric string and mandatory. Normally
it can be found in leases file both on client and server.
IP is an IPv6 address to release
If --dry-run is specified, dhcp_release6 just prints hexadecimal representation of
packet to send to stdout and exits.
If --help is specified, dhcp_release6 print usage information to stdout and exits
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <errno.h>
#include <unistd.h>
#define NOT_REPLY_CODE 115
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
enum DHCP6_TYPES
{
SOLICIT = 1,
ADVERTISE = 2,
REQUEST = 3,
CONFIRM = 4,
RENEW = 5,
REBIND = 6,
REPLY = 7,
RELEASE = 8,
DECLINE = 9,
RECONFIGURE = 10,
INFORMATION_REQUEST = 11,
RELAY_FORW = 12,
RELAY_REPL = 13
};
enum DHCP6_OPTIONS
{
CLIENTID = 1,
SERVERID = 2,
IA_NA = 3,
IA_TA = 4,
IAADDR = 5,
ORO = 6,
PREFERENCE = 7,
ELAPSED_TIME = 8,
RELAY_MSG = 9,
AUTH = 11,
UNICAST = 12,
STATUS_CODE = 13,
RAPID_COMMIT = 14,
USER_CLASS = 15,
VENDOR_CLASS = 16,
VENDOR_OPTS = 17,
INTERFACE_ID = 18,
RECONF_MSG = 19,
RECONF_ACCEPT = 20,
};
enum DHCP6_STATUSES
{
SUCCESS = 0,
UNSPEC_FAIL = 1,
NOADDR_AVAIL=2,
NO_BINDING = 3,
NOT_ON_LINK = 4,
USE_MULTICAST =5
};
static struct option longopts[] = {
{"ip", required_argument, 0, 'a' },
{"server-id", required_argument, 0, 's' },
{"client-id", required_argument, 0, 'c' },
{"iface", required_argument, 0, 'n' },
{"iaid", required_argument, 0, 'i' },
{"dry-run", no_argument, 0, 'd' },
{"help", no_argument, 0, 'h' },
{0, 0, 0, 0 }
};
const short DHCP6_CLIENT_PORT = 546;
const short DHCP6_SERVER_PORT = 547;
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
struct dhcp6_option {
uint16_t type;
uint16_t len;
char value[1024];
};
struct dhcp6_iaaddr_option {
uint16_t type;
uint16_t len;
struct in6_addr ip;
uint32_t preferred_lifetime;
uint32_t valid_lifetime;
};
struct dhcp6_iana_option {
uint16_t type;
uint16_t len;
uint32_t iaid;
uint32_t t1;
uint32_t t2;
char options[1024];
};
struct dhcp6_packet {
size_t len;
char buf[2048];
};
size_t pack_duid(const char* str, char* dst)
{
char* tmp = strdup(str);
char* tmp_to_free = tmp;
char *ptr;
uint8_t write_pos = 0;
while ((ptr = strtok (tmp, ":")))
{
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
write_pos += 1;
tmp = NULL;
}
free(tmp_to_free);
return write_pos;
}
struct dhcp6_option create_client_id_option(const char* duid)
{
struct dhcp6_option option;
option.type = htons(CLIENTID);
bzero(option.value, sizeof(option.value));
option.len = htons(pack_duid(duid, option.value));
return option;
}
struct dhcp6_option create_server_id_option(const char* duid)
{
struct dhcp6_option option;
option.type = htons(SERVERID);
bzero(option.value, sizeof(option.value));
option.len = htons(pack_duid(duid, option.value));
return option;
}
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip)
{
struct dhcp6_iaaddr_option result;
result.type =htons(IAADDR);
/* no suboptions needed here, so length is 24 */
result.len = htons(24);
result.preferred_lifetime = 0;
result.valid_lifetime = 0;
int s = inet_pton(AF_INET6, ip, &(result.ip));
if (s <= 0) {
if (s == 0)
fprintf(stderr, "Not in presentation format");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
return result;
}
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr)
{
struct dhcp6_iana_option result;
result.type = htons(IA_NA);
result.iaid = htonl(atoi(iaid));
result.t1 = 0;
result.t2 = 0;
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
return result;
}
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id)
{
struct dhcp6_packet result;
bzero(result.buf, sizeof(result.buf));
/* message_type */
result.buf[0] = RELEASE;
/* tx_id */
bzero(result.buf+1, 3);
struct dhcp6_option client_option = create_client_id_option(client_id);
struct dhcp6_option server_option = create_server_id_option(server_id);
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
int offset = 4;
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
result.len = offset;
return result;
}
uint16_t parse_iana_suboption(char* buf, size_t len)
{
size_t current_pos = 0;
char option_value[1024];
while (current_pos < len)
{
uint16_t option_type, option_len;
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
option_type = ntohs(option_type);
option_len = ntohs(option_len);
current_pos += 2 * sizeof(uint16_t);
if (option_type == STATUS_CODE)
{
uint16_t status;
memcpy(&status, buf + current_pos, sizeof(uint16_t));
status = ntohs(status);
if (status != SUCCESS)
{
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
option_value[option_len-sizeof(uint16_t)] ='\0';
fprintf(stderr, "Error: %s\n", option_value);
}
return status;
}
}
return -2;
}
int16_t parse_packet(char* buf, size_t len)
{
int16_t ret = -1;
uint8_t type = buf[0];
/*skipping tx id. you need it, uncomment following line
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
*/
size_t current_pos = 4;
if (type != REPLY )
return NOT_REPLY_CODE;
char option_value[1024];
while (current_pos < len)
{
uint16_t option_type, option_len;
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
option_type = ntohs(option_type);
option_len = ntohs(option_len);
current_pos += 2 * sizeof(uint16_t);
if (option_type == STATUS_CODE)
{
uint16_t status;
memcpy(&status, buf + current_pos, sizeof(uint16_t));
status = ntohs(status);
if (status != SUCCESS)
{
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
fprintf(stderr, "Error: %d %s\n", status, option_value);
return status;
}
/* Got success status, return that if there's no specific error in an IA_NA. */
ret = SUCCESS;
}
if (option_type == IA_NA )
{
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
if (result)
return result;
}
current_pos += option_len;
}
return ret;
}
void usage(const char* arg, FILE* stream)
{
const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
}
static void fail_fatal(const char *errstr, int exitcode)
{
perror(errstr);
exit(exitcode);
}
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
{
struct sockaddr_in6 server_addr, client_addr;
char response[1400];
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
int i = 0;
if (sock < 0)
{
perror("creating socket");
return -1;
}
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1)
{
perror("SO_BINDTODEVICE");
close(sock);
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
client_addr.sin6_family = AF_INET6;
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
client_addr.sin6_flowinfo = 0;
client_addr.sin6_scope_id =0;
if (inet_pton(AF_INET6, "::", &client_addr.sin6_addr) <= 0)
fail_fatal("inet_pton", 5);
if (bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)) != 0)
perror("bind"); /* continue on bind error */
if (inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr) <= 0)
fail_fatal("inet_pton", 5);
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
ssize_t recv_size = 0;
int result;
for (i = 0; i < 5; i++)
{
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
fail_fatal("sendto failed", 4);
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
if (recv_size == -1)
{
if (errno == EAGAIN)
{
sleep(1);
continue;
}
else
{
perror("recvfrom");
result = UNSPEC_FAIL;
}
}
else
{
result = parse_packet(response, recv_size);
if (result == NOT_REPLY_CODE)
{
sleep(1);
continue;
}
}
close(sock);
return result;
}
close(sock);
fprintf(stderr, "Response timed out\n");
return -1;
}
int main(int argc, char * const argv[])
{
const char* UNINITIALIZED = "";
const char* iface = UNINITIALIZED;
const char* ip = UNINITIALIZED;
const char* client_id = UNINITIALIZED;
const char* server_id = UNINITIALIZED;
const char* iaid = UNINITIALIZED;
int dry_run = 0;
while (1)
{
int option_index = 0;
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
if (c == -1)
break;
switch(c)
{
case 0:
if (longopts[option_index].flag !=0)
break;
printf ("option %s", longopts[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'i':
iaid = optarg;
break;
case 'n':
iface = optarg;
break;
case 'a':
ip = optarg;
break;
case 'c':
client_id = optarg;
break;
case 'd':
dry_run = 1;
break;
case 's':
server_id = optarg;
break;
case 'h':
usage(argv[0], stdout);
return 0;
case '?':
usage(argv[0], stderr);
return -1;
default:
abort();
}
}
if (iaid == UNINITIALIZED)
{
fprintf(stderr, "Missing required iaid parameter\n");
usage(argv[0], stderr);
return -1;
}
if (server_id == UNINITIALIZED)
{
fprintf(stderr, "Missing required server-id parameter\n");
usage(argv[0], stderr);
return -1;
}
if (client_id == UNINITIALIZED)
{
fprintf(stderr, "Missing required client-id parameter\n");
usage(argv[0], stderr);
return -1;
}
if (ip == UNINITIALIZED)
{
fprintf(stderr, "Missing required ip parameter\n");
usage(argv[0], stderr);
return -1;
}
if (iface == UNINITIALIZED)
{
fprintf(stderr, "Missing required iface parameter\n");
usage(argv[0], stderr);
return -1;
}
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
if (dry_run)
{
uint16_t i;
for(i=0; i<packet.len; i++)
printf("%hhx", packet.buf[i]);
printf("\n");
return 0;
}
return send_release_packet(iface, &packet);
}

View File

@@ -0,0 +1,695 @@
/* leasequery is Copyright (c) 2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Author's email: simon@thekelleys.org.uk */
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <limits.h>
#include <net/if.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <netdb.h>
#include <linux/types.h>
#include <linux/capability.h>
#include <arpa/inet.h>
#include <ctype.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#define INADDRSZ 4
#define ADDRSTRLEN 46
#define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
#define DHCP_CHADDR_MAX 16
#define DHCP_SERVER_PORT 67
#define DHCP_CLIENT_PORT 68
#define BOOTREQUEST 1
#define BOOTREPLY 2
#define DHCP_COOKIE 0x63825363
#define DHCPLEASEQUERY 10
#define DHCPLEASEUNASSIGNED 11
#define DHCPLEASEUNKNOWN 12
#define DHCPLEASEACTIVE 13
#define OPTION_END 255
#define OPTION_ROUTER 3
#define OPTION_VENDOR_CLASS_OPT 43
#define OPTION_LEASE_TIME 51
#define OPTION_MESSAGE_TYPE 53
#define OPTION_SERVER_IDENTIFIER 54
#define OPTION_REQUESTED_OPTIONS 55
#define OPTION_VENDOR_ID 60
#define OPTION_CLIENT_ID 61
/* flags in top of length field for DHCP-option tables */
#define OT_ADDR_LIST 0x8000
#define OT_RFC1035_NAME 0x4000
#define OT_INTERNAL 0x2000
#define OT_NAME 0x1000
#define OT_CSTRING 0x0800
#define OT_DEC 0x0400
#define OT_TIME 0x0200
#define GETSHORT(s, cp) do { \
unsigned char *t_cp = (unsigned char *)(cp); \
(s) = ((u16)t_cp[0] << 8) \
| ((u16)t_cp[1]) \
; \
(cp) += 2; \
} while(0)
#define GETLONG(l, cp) do { \
unsigned char *t_cp = (unsigned char *)(cp); \
(l) = ((u32)t_cp[0] << 24) \
| ((u32)t_cp[1] << 16) \
| ((u32)t_cp[2] << 8) \
| ((u32)t_cp[3]) \
; \
(cp) += 4; \
} while (0)
#define PUTSHORT(s, cp) do { \
u16 t_s = (u16)(s); \
unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += 2; \
} while(0)
#define PUTLONG(l, cp) do { \
u32 t_l = (u32)(l); \
unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += 4; \
} while (0)
union all_addr {
struct in_addr addr4;
struct in6_addr addr6;
};
struct dhcp_packet_with_opts{
struct dhcp_packet {
unsigned char op, htype, hlen, hops;
unsigned int xid;
unsigned short secs, flags;
struct in_addr ciaddr, yiaddr, siaddr, giaddr;
unsigned char chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
} header;
unsigned char options[312];
};
static const struct opttab_t {
char *name;
u16 val, size;
} opttab[] = {
{ "netmask", 1, OT_ADDR_LIST },
{ "time-offset", 2, 4 },
{ "router", 3, OT_ADDR_LIST },
{ "dns-server", 6, OT_ADDR_LIST },
{ "log-server", 7, OT_ADDR_LIST },
{ "lpr-server", 9, OT_ADDR_LIST },
{ "hostname", 12, OT_INTERNAL | OT_NAME },
{ "boot-file-size", 13, 2 | OT_DEC },
{ "domain-name", 15, OT_NAME },
{ "swap-server", 16, OT_ADDR_LIST },
{ "root-path", 17, OT_NAME },
{ "extension-path", 18, OT_NAME },
{ "ip-forward-enable", 19, 1 },
{ "non-local-source-routing", 20, 1 },
{ "policy-filter", 21, OT_ADDR_LIST },
{ "max-datagram-reassembly", 22, 2 | OT_DEC },
{ "default-ttl", 23, 1 | OT_DEC },
{ "mtu", 26, 2 | OT_DEC },
{ "all-subnets-local", 27, 1 },
{ "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
{ "router-discovery", 31, 1 },
{ "router-solicitation", 32, OT_ADDR_LIST },
{ "static-route", 33, OT_ADDR_LIST },
{ "trailer-encapsulation", 34, 1 },
{ "arp-timeout", 35, 4 | OT_DEC },
{ "ethernet-encap", 36, 1 },
{ "tcp-ttl", 37, 1 },
{ "tcp-keepalive", 38, 4 | OT_DEC },
{ "nis-domain", 40, OT_NAME },
{ "nis-server", 41, OT_ADDR_LIST },
{ "ntp-server", 42, OT_ADDR_LIST },
{ "vendor-encap", 43, OT_INTERNAL },
{ "netbios-ns", 44, OT_ADDR_LIST },
{ "netbios-dd", 45, OT_ADDR_LIST },
{ "netbios-nodetype", 46, 1 },
{ "netbios-scope", 47, 0 },
{ "x-windows-fs", 48, OT_ADDR_LIST },
{ "x-windows-dm", 49, OT_ADDR_LIST },
{ "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
{ "lease-time", 51, OT_INTERNAL | OT_TIME },
{ "option-overload", 52, OT_INTERNAL },
{ "message-type", 53, OT_INTERNAL | OT_DEC },
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
{ "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL },
{ "T1", 58, OT_TIME},
{ "T2", 59, OT_TIME},
{ "vendor-class", 60, OT_NAME },
{ "client-id", 61, OT_INTERNAL },
{ "nis+-domain", 64, OT_NAME },
{ "nis+-server", 65, OT_ADDR_LIST },
{ "tftp-server", 66, OT_NAME },
{ "bootfile-name", 67, OT_NAME },
{ "mobile-ip-home", 68, OT_ADDR_LIST },
{ "smtp-server", 69, OT_ADDR_LIST },
{ "pop3-server", 70, OT_ADDR_LIST },
{ "nntp-server", 71, OT_ADDR_LIST },
{ "irc-server", 74, OT_ADDR_LIST },
{ "user-class", 77, 0 },
{ "rapid-commit", 80, 0 },
{ "FQDN", 81, OT_INTERNAL },
{ "agent-info", 82, OT_INTERNAL },
{ "last-transaction", 91, 4 | OT_TIME },
{ "associated-ip", 92, OT_ADDR_LIST },
{ "client-arch", 93, 2 | OT_DEC },
{ "client-interface-id", 94, 0 },
{ "client-machine-id", 97, 0 },
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
{ "ipv6-only", 108, 4 | OT_DEC }, /* RFC 8925 */
{ "subnet-select", 118, OT_INTERNAL },
{ "domain-search", 119, OT_RFC1035_NAME },
{ "sip-server", 120, 0 },
{ "classless-static-route", 121, 0 },
{ "vendor-id-encap", 125, 0 },
{ "tftp-server-address", 150, OT_ADDR_LIST },
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
{ NULL, 0, 0 }
};
static void prettyprint_time(char *buf, unsigned int t);
static char *print_mac(char *buff, unsigned char *mac, int len);
int lookup_dhcp_opt(char *name)
{
const struct opttab_t *t = opttab;
int i;
for (i = 0; t[i].name; i++)
if (strcasecmp(t[i].name, name) == 0)
return t[i].val;
return -1;
}
char *option_string(unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len)
{
int o, i, j, nodecode = 0;
const struct opttab_t *ot = opttab;
char addrbuff[ADDRSTRLEN];
for (o = 0; ot[o].name; o++)
if (ot[o].val == opt)
{
if (buf)
{
memset(buf, 0, buf_len);
if (ot[o].size & OT_ADDR_LIST)
{
union all_addr addr;
int addr_len = INADDRSZ;
for (buf[0]= 0, i = 0; i <= opt_len - addr_len; i += addr_len)
{
if (i != 0)
strncat(buf, ", ", buf_len - strlen(buf));
/* align */
memcpy(&addr, &val[i], addr_len);
inet_ntop(AF_INET, &val[i], addrbuff, ADDRSTRLEN);
strncat(buf, addrbuff, buf_len - strlen(buf));
}
}
else if (ot[o].size & OT_NAME)
for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
{
char c = val[i];
if (isprint((unsigned char)c))
buf[j++] = c;
}
else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
{
unsigned int dec = 0;
for (i = 0; i < opt_len; i++)
dec = (dec << 8) | val[i];
if (ot[o].size & OT_TIME)
prettyprint_time(buf, dec);
else
sprintf(buf, "%u", dec);
}
else
nodecode = 1;
}
break;
}
if (opt_len != 0 && buf && (!ot[o].name || nodecode))
{
int trunc = 0;
if (opt_len > 14)
{
trunc = 1;
opt_len = 14;
}
print_mac(buf, val, opt_len);
if (trunc)
strncat(buf, "...", buf_len - strlen(buf));
}
return ot[o].name ? ot[o].name : "";
}
static void prettyprint_time(char *buf, unsigned int t)
{
if (t == 0xffffffff)
sprintf(buf, "infinite");
else
{
unsigned int x, p = 0;
if ((x = t/86400))
p += sprintf(&buf[p], "%ud", x);
if ((x = (t/3600)%24))
p += sprintf(&buf[p], "%uh", x);
if ((x = (t/60)%60))
p += sprintf(&buf[p], "%um", x);
if ((x = t%60))
sprintf(&buf[p], "%us", x);
}
}
static char *print_mac(char *buff, unsigned char *mac, int len)
{
char *p = buff;
int i;
if (len == 0)
sprintf(p, "<null>");
else
for (i = 0; i < len; i++)
p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
return buff;
}
static unsigned char *dhcp_skip_opts(struct dhcp_packet_with_opts *pktp)
{
unsigned char *start = (unsigned char *)(((unsigned int *)&pktp->options[0]) + 1);
while (*start != 0)
start += start[1] + 2;
return start;
}
static unsigned char *dhcp_find_opt(struct dhcp_packet_with_opts *pktp, int optno)
{
unsigned char *start = (unsigned char *)(((unsigned int *)&pktp->options[0]) + 1);
while (*start != OPTION_END)
{
if (*start == optno)
return start;
start += start[1] + 2;
}
return NULL;
}
static void option_put(struct dhcp_packet_with_opts *pktp, int opt, int len, unsigned int val)
{
int i;
unsigned char *p = dhcp_skip_opts(pktp);
if (p)
{
*p++ = opt;
*p++ = len;
for (i = 0; i < len; i++)
*(p++) = val >> (8 * (len - (i + 1)));
}
}
static void option_put_string(struct dhcp_packet_with_opts *pktp, int opt,
const char *string, int null_term)
{
unsigned char *p;
size_t len = strlen(string);
if (null_term && len != 255)
len++;
if ((p = dhcp_skip_opts(pktp)))
{
*p++ = opt;
*p++ = len;
memcpy(p, string, len);
}
}
/* in may equal out, when maxlen may be -1 (No max len).
Return -1 for extraneous no-hex chars found. */
int parse_hex(char *in, unsigned char *out, int maxlen,
unsigned int *wildcard_mask, int *mac_type)
{
int done = 0, mask = 0, i = 0;
char *r;
if (mac_type)
*mac_type = 0;
while (!done && (maxlen == -1 || i < maxlen))
{
for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
if (*r != '*' && !isxdigit((unsigned char)*r))
return -1;
if (*r == 0)
done = 1;
if (r != in )
{
if (*r == '-' && i == 0 && mac_type)
{
*r = 0;
*mac_type = strtol(in, NULL, 16);
mac_type = NULL;
}
else
{
*r = 0;
if (strcmp(in, "*") == 0)
{
mask = (mask << 1) | 1;
i++;
}
else
{
int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++)
{
char sav;
if (j < bytes - 1)
{
sav = in[(j+1)*2];
in[(j+1)*2] = 0;
}
/* checks above allow mix of hexdigit and *, which
is illegal. */
if (strchr(&in[j*2], '*'))
return -1;
out[i] = strtol(&in[j*2], NULL, 16);
mask = mask << 1;
if (++i == maxlen)
break;
if (j < bytes - 1)
in[(j+1)*2] = sav;
}
}
}
}
in = r+1;
}
if (wildcard_mask)
*wildcard_mask = mask;
return i;
}
static char *split_chr(char *s, char c)
{
char *comma, *p;
if (!s || !(comma = strchr(s, c)))
return NULL;
p = comma;
*comma = ' ';
for (; *comma == ' '; comma++);
for (; (p >= s) && *p == ' '; p--)
*p = 0;
return comma;
}
static char *split(char *s)
{
return split_chr(s, ',');
}
int main(int argc, char **argv)
{
int fd;
struct ifreq ifr;
struct in_addr iface_addr, server_addr, lease_addr;
struct dhcp_packet_with_opts pkt;
struct sockaddr_in saddr;
unsigned char *p;
ssize_t sz;
unsigned char mac[DHCP_CHADDR_MAX], clid[256], req_options[256];
char buff[500];
int clid_len = 0, mac_len = 0, mac_type = 0, opts_len = 0;
unsigned short port = DHCP_SERVER_PORT;
unsigned int xid;
struct timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
xid = rand();
server_addr.s_addr = lease_addr.s_addr = iface_addr.s_addr = 0;
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("leasequery: cannot create socket");
exit(1);
}
while (1)
{
int option = getopt(argc, argv, "i:s:l:m:c:p:r:");
if (option == -1)
break;
switch (option)
{
default:
fprintf(stderr,
"-p <port> port on DHCP server.\n"
"-i <interface> exit interface to DHCP server.\n"
"-s <inet-addr> DHCP server address.\n"
"-l <inet-addr> Query lease by IP address.\n"
"-m <MAC-addr> Query lease by MAC address.\n"
"-c <hex> Query lease by client-id.\n"
"-r <name>|<int>[,...] List of options to return.\n");
exit(1);
case 'p':
port = atoi(optarg);
break;
case 'i':
strncpy(ifr.ifr_name, optarg, IF_NAMESIZE);
ifr.ifr_addr.sa_family = AF_INET;
if (ioctl(fd, SIOCGIFADDR, &ifr) == -1)
{
perror("leasequery: cannot get interface address");
exit(1);
}
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
break;
case 's':
if (inet_pton(AF_INET, optarg, &server_addr) <= 0)
{
fprintf(stderr, "leasequery: bad server address\n");
exit(1);
}
break;
case 'l':
if (inet_pton(AF_INET, optarg, &lease_addr) <= 0)
{
fprintf(stderr, "leasequery: bad lease address\n");
exit(1);
}
break;
case 'm':
mac_type = 1; /* default ethernet */
mac_len = parse_hex(optarg, mac, DHCP_CHADDR_MAX, NULL, &mac_type);
if (!mac_type)
mac_type = 1; /* default ethernet */
break;
case 'c':
clid_len = parse_hex(optarg, clid, 256, NULL, NULL);
break;
case 'r':
{
char *comma;
int opt;
while (optarg)
{
comma = split(optarg);
if ((opt = lookup_dhcp_opt(optarg)) != -1 || (opt = atoi(optarg)) != 0)
req_options[opts_len++] = opt;
optarg = comma;
}
break;
}
}
}
if (!server_addr.s_addr)
{
fprintf(stderr, "leasequery: no server address\n");
exit(1);
}
memset(&pkt, 0, sizeof pkt);
pkt.header.op = BOOTREQUEST;
pkt.header.xid = xid;
pkt.header.ciaddr = lease_addr;
pkt.header.hlen = mac_len;
pkt.header.htype = mac_type;
memcpy(pkt.header.chaddr, mac, mac_len);
*((unsigned int *)&pkt.options[0]) = htonl(DHCP_COOKIE);
/* Dnsmasq extension. */
pkt.header.giaddr.s_addr = iface_addr.s_addr ? iface_addr.s_addr : INADDR_BROADCAST;
option_put(&pkt, OPTION_MESSAGE_TYPE, 1, DHCPLEASEQUERY);
if (clid_len != 0)
{
p = dhcp_skip_opts(&pkt);
*p++ = OPTION_CLIENT_ID;
*p++ = clid_len;
memcpy(p, clid, clid_len);
}
if (opts_len != 0)
{
p = dhcp_skip_opts(&pkt);
*p++ = OPTION_REQUESTED_OPTIONS;
*p++ = opts_len;
memcpy(p, req_options, opts_len);
}
if (iface_addr.s_addr)
{
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = iface_addr.s_addr;
if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
{
perror("leasequery: cannot bind DHCP server socket");
exit(1);
}
}
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
saddr.sin_addr = server_addr;
while((sz = sendto(fd, &pkt, dhcp_skip_opts(&pkt) - ((unsigned char *)&pkt), 0, (struct sockaddr *)&saddr, sizeof(saddr))) == -1 &&
errno == EINTR);
if (sz == -1)
{
perror("leasequery: sendto()");
exit(1);
}
sz = recv(fd, &pkt, sizeof(pkt), 0);
if (sz == -1)
{
perror("leasequery: recv()");
exit(1);
}
if (sz >= sizeof(pkt.header) &&
pkt.header.op == BOOTREPLY &&
(p = dhcp_find_opt(&pkt, OPTION_MESSAGE_TYPE)) &&
pkt.header.xid == xid)
{
if (p[2] == DHCPLEASEUNASSIGNED)
printf("UNASSIGNED\n");
else if (p[2] == DHCPLEASEUNKNOWN)
printf("UNKNOWN\n");
else if (p[2] == DHCPLEASEACTIVE)
{
print_mac(buff, pkt.header.chaddr, pkt.header.hlen);
printf("ACTIVE %s %s\n", inet_ntoa(pkt.header.ciaddr), buff);
p = (unsigned char *)(((unsigned int *)&pkt.options[0]) + 1);
while (*p != OPTION_END)
{
if (*p != OPTION_MESSAGE_TYPE)
{
char *optname = option_string(p[0], option_ptr(p, 0), option_len(p), buff, 500);
printf("size:%3d option:%3d %s %s\n", option_len(p), p[0], optname, buff);
}
p += p[1] + 2;
}
}
}
}

View File

@@ -3,7 +3,7 @@
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
# Script for dnsmasq lease-change hook.
# Maintains the above file with a IP address/MAC address pairs,
# Maintains the above file with an IP address/MAC address pairs,
# one lease per line. Works with IPv4 and IPv6 leases, file is
# atomically updated, so no races for users of the data.

View File

@@ -3,7 +3,7 @@
# first column of this file, then a DNAT port-forward will be set up
# to the address which has just been allocated by DHCP . The second field
# is port number(s). If there is only one, then the port-forward goes to
# the same port on the DHCP-client, if there are two seperated with a
# the same port on the DHCP-client, if there are two separated with a
# colon, then the second number is the port to which the connection
# is forwarded on the DHCP-client. By default, forwarding is set up
# for TCP, but it can done for UDP instead by prefixing the port to "u".

View File

@@ -0,0 +1,18 @@
The script reads stdin and replaces all IP addresses with names before
outputting it again. IPs from private networks are reverse looked up
via dns. Other IP addresses are searched for in the dnsmasq query log.
This gives names (CNAMEs if I understand DNS correctly) that are closer
to the name the client originally asked for then the names obtained by
reverse lookup. Just run
netstat -n -4 | ./reverse_replace.sh
to see what it does. It needs
log-queries
log-facility=/var/log/dnsmasq.log
in the dnsmasq configuration.
The script runs on debian (with dash installed) and on busybox.

View File

@@ -0,0 +1,125 @@
#!/bin/dash
# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
#
# Usage e.g.: netstat -n -4 | reverse_replace.sh
# Parses stdin for IP4 addresses and replaces them
# with names retrieved by parsing the dnsmasq log.
# This currently only gives CNAMEs. But these
# usually tell you more than the ones from reverse
# lookups.
#
# This has been tested on debian and asuswrt. Please
# report successful tests on other platforms.
#
# Author: Joachim Zobel <jz-2014@heute-morgen.de>
# License: Consider this MIT style licensed. You can
# do as you ike, but you must not remove my name.
#
LOG=/var/log/dnsmasq.log
MAX_LINES=15000
# sed regex do match IPs
IP_regex='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
# private IP ranges
IP_private='\(^127\.\)\|\(^192\.168\.\)\|\(^10\.\)\|\(^172\.1[6-9]\.\)\|\(^172\.2[0-9]\.\)\|\(^172\.3[0-1]\.\)'
#######################################################################
# Find Commands
HOST=nslookup
if type host > /dev/null 2>&1; then
# echo "No need for nslookup, host is there"
HOST=host
fi
#######################################################################
# Functions
# Use shell variables for an (IP) lookup table
create_lookup_table()
{
# Parse log into lookup table
local CMDS="$( tail -"$MAX_LINES" "$LOG" | \
grep " is $IP_regex" | \
sed "s#.* \([^ ]*\) is \($IP_regex\).*#set_val \2 \1;#" )"
local IFS='
'
for CMD in $CMDS
do
eval $CMD
done
}
set_val()
{
local _IP=$(echo $1 | tr . _)
local KEY="__IP__$_IP"
eval "$KEY"=$2
}
get_val()
{
local _IP=$(echo $1 | tr . _)
local KEY="__IP__$_IP"
eval echo -n '${'"$KEY"'}'
}
dns_lookup()
{
local IP=$1
local RTN="$($HOST $IP | \
sed 's#\s\+#\n#g' | \
grep -v '^$' | \
tail -1 | tr -d '\n' | \
sed 's#\.$##')"
if echo $RTN | grep -q NXDOMAIN; then
echo -n $IP
else
echo -n "$RTN"
fi
}
reverse_dns()
{
local IP=$1
# Skip if it is not an IP
if ! echo $IP | grep -q "^$IP_regex$"; then
echo -n $IP
return
fi
# Do a dns lookup, if it is a local IP
if echo $IP | grep -q $IP_private; then
dns_lookup $IP
return
fi
local NAME="$(get_val $IP)"
if [ -z "$NAME" ]; then
echo -n $IP
else
echo -n $NAME
fi
}
#######################################################################
# Main
create_lookup_table
while read LINE; do
for IP in $(echo "$LINE" | \
sed "s#\b\($IP_regex\)\b#\n\1\n#g" | \
grep $IP_regex)
do
NAME=`reverse_dns $IP `
# echo "$NAME $IP"
LINE=`echo "$LINE" | sed "s#$IP#$NAME#" `
done
echo $LINE
done

View File

@@ -1,5 +1,8 @@
[Unit]
Description=dnsmasq - A lightweight DHCP and caching DNS server
After=network.target
Before=network-online.target nss-lookup.target
Wants=nss-lookup.target
[Service]
Type=dbus

View File

@@ -2,7 +2,7 @@ A remake of patch Bob Carroll had posted to dnsmasq,
now compatible with version 2.47. Hopefully he doesn't
mind (sending a copy of this mail to him too).
Maybe the patch in question is not acceptible
Maybe the patch in question is not acceptable
as it doesn't add new switch, rather it binds itself to "strict-order".
What it does is: if you have strict-order in the

View File

@@ -0,0 +1,10 @@
Hi,
I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
Find the patch attached.
Regards,
Rasmus Ahlberg
Software Developer, R&D
Electrolux Small Appliances

View File

@@ -0,0 +1,20 @@
diff --git a/src/forward.c b/src/forward.c
index e3fa94b..ecf3b98 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now)
/* Note: if we send extra options in the EDNS0 header, we can't recreate
the query from the reply. */
- if (RCODE(header) == REFUSED &&
- forward->forwardall == 0 &&
- !(forward->flags & FREC_HAS_EXTRADATA))
+ if ((RCODE(header) == REFUSED &&
+ forward->forwardall == 0 &&
+ !(forward->flags & FREC_HAS_EXTRADATA)) ||
+ /* If strict-order is set, try next server on NXDOMAIN reply */
+ (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) &&
+ server->next != NULL))
/* for broken servers, attempt to send to another one. */
{
unsigned char *pheader;

View File

@@ -1,5 +1,5 @@
This is the README for the DNSmasq webmin module.
This is the README for the Dnsmasq webmin module.
Problems:
@@ -48,7 +48,7 @@ wade through the config file and man pages again.
If you modify it, or add a language file, and you have a spare moment,
please e-mail me - I won't be upset at all if you fix my poor coding!
(rather the opposite - I'd be pleased someone found it usefull)
(rather the opposite - I'd be pleased someone found it useful)
Cheers,
Neil Fisher <neil@magnecor.com.au>

View File

@@ -1,6 +0,0 @@
CFLAGS?= -O2 -Wall -W
all: dhcp_release dhcp_lease_time
clean:
rm -f *~ *.o core dhcp_release dhcp_lease_time

View File

@@ -4,7 +4,7 @@ reboot, then it will eventually be restored as hosts renew their
leases. Until a host renews (which may take hours/days) it will
not exist in the DNS if dnsmasq's DDNS function is in use.
*WRT systems remount all non-volatile fileystems read-only after boot,
*WRT systems remount all non-volatile filesystems read-only after boot,
so the normal leasefile will not work. They do, however have NV
storage, accessed with the nvram command:
@@ -62,7 +62,7 @@ about 100 bytes, so restricting the number of leases to 50 will limit
use to half that. (The default limit in the distributed source is 150)
Any UI script which reads the dnsmasq leasefile will have to be
ammended, probably by changing it to read the output of
amended, probably by changing it to read the output of
`lease_update init` instead.

View File

@@ -44,10 +44,22 @@ SetFilterWin2KOption
--------------------
Takes boolean, sets or resets the --filterwin2k option.
SetFilterA
------------------------
Takes boolean, sets or resets the --filter-A option.
SetFilterAAAA
------------------------
Takes boolean, sets or resets the --filter-AAAA option.
SetBogusPrivOption
------------------
Takes boolean, sets or resets the --bogus-priv option.
SetLocaliseQueriesOption
------------------------
Takes boolean, sets or resets the --localise-queries option.
SetServers
----------
Returns nothing. Takes a set of arguments representing the new
@@ -169,7 +181,94 @@ Return an array of strings, each string is the IP address of an upstream
server which has been found to loop queries back to this dnsmasq instance, and
it therefore not being used.
AddDhcpLease
------------
Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
database, as if a client requested and obtained a lease.
If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
D-Bus signal and will run the configured DHCP lease script accordingly.
This function takes many arguments which are the lease parameters:
- A string with the textual representation of the IPv4 or IPv6 address of the
client.
Examples:
"192.168.1.115"
"1003:1234:abcd::1%eth0"
"2001:db8:abcd::1"
- A string representing the hardware address of the client, using the same
format as the one used in the lease database.
Examples:
"00:23:45:67:89:ab"
"06-00:20:e0:3b:13:af" (token ring)
- The hostname of the client, as an array of bytes (so there is no problem
with non-ASCII character encoding). May be empty.
Example (for "hostname.or.fqdn"):
[104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
empty.
Examples:
DHCPv6 DUID:
[0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
DHCPv4 client identifier:
[255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
- The duration of the lease, in seconds. If the lease is updated, then
the duration replaces the previous duration.
Example:
7200
- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
Example (for IPv6):
203569230
- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
(IA_NA). For DHCPv4 leases, this must be set to false.
RemoveDhcpLease
---------------
Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
database, as if a client sent a release message to abandon a lease.
This function takes only one parameter: the text representation of the
IPv4 or IPv6 address of the lease to remove.
Note that this function will trigger the DhcpLeaseRemoved signal and the
configured DHCP lease script will be run with the "del" action.
GetMetrics
----------
Returns an array with various metrics for DNS and DHCP.
GetServerMetrics
----------------
Returns per-DNS-server metrics.
ClearMetrics
------------
Clear call metric counters, global and per-server.
2. SIGNALS
----------

1
debian Symbolic link
View File

@@ -0,0 +1 @@
submodules/dnsmasq-debian/debian

1197
debian/changelog vendored

File diff suppressed because it is too large Load Diff

5
debian/conffiles vendored
View File

@@ -1,5 +0,0 @@
/etc/init.d/dnsmasq
/etc/default/dnsmasq
/etc/dnsmasq.conf
/etc/resolvconf/update.d/dnsmasq
/etc/insserv.conf.d/dnsmasq

46
debian/control vendored
View File

@@ -1,46 +0,0 @@
Source: dnsmasq
Section: net
Priority: optional
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
nettle-dev (>=2.4-3), libbsd-dev [!linux-any]
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
Standards-Version: 3.9.5
Package: dnsmasq
Architecture: all
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
init-system-helpers (>= 1.18~)
Suggests: resolvconf
Conflicts: resolvconf (<<1.15)
Description: Small caching DNS proxy and DHCP/TFTP server
Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP
server. It is designed to provide DNS and optionally, DHCP, to a
small network. It can serve the names of local machines which are
not in the global DNS. The DHCP server integrates with the DNS
server and allows machines with DHCP-allocated addresses
to appear in the DNS with names configured either in each host or
in a central configuration file. Dnsmasq supports static and dynamic
DHCP leases and BOOTP/TFTP for network booting of diskless machines.
Package: dnsmasq-base
Architecture: any
Depends: adduser, ${shlibs:Depends}
Breaks: dnsmasq (<< 2.63-1~)
Replaces: dnsmasq (<< 2.63-1~)
Recommends: dns-root-data
Description: Small caching DNS proxy and DHCP/TFTP server
This package contains the dnsmasq executable and documentation, but
not the infrastructure required to run it as a system daemon. For
that, install the dnsmasq package.
Package: dnsmasq-utils
Architecture: linux-any
Depends: ${shlibs:Depends}
Conflicts: dnsmasq (<<2.40)
Description: Utilities for manipulating DHCP leases
Small utilities to query a DHCP server's lease database and
remove leases from it. These programs are distributed with dnsmasq
and may not work correctly with other DHCP servers.

21
debian/copyright vendored
View File

@@ -1,21 +0,0 @@
dnsmasq is Copyright (c) 2000-2013 Simon Kelley
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
On Debian GNU/Linux systems, the text of the GNU general public license is
available in the file /usr/share/common-licenses/GPL-2 or
/usr/share/common-licenses/GPL-3
The Debian package of dnsmasq was created by Simon Kelley with assistance
from Lars Bahner.

18
debian/dbus.conf vendored
View File

@@ -1,18 +0,0 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="uk.org.thekelleys.dnsmasq"/>
<allow send_destination="uk.org.thekelleys.dnsmasq"/>
</policy>
<policy user="dnsmasq">
<allow own="uk.org.thekelleys.dnsmasq"/>
<allow send_destination="uk.org.thekelleys.dnsmasq"/>
</policy>
<policy context="default">
<deny own="uk.org.thekelleys.dnsmasq"/>
<deny send_destination="uk.org.thekelleys.dnsmasq"/>
</policy>
</busconfig>

33
debian/default vendored
View File

@@ -1,33 +0,0 @@
# This file has five functions:
# 1) to completely disable starting dnsmasq,
# 2) to set DOMAIN_SUFFIX by running `dnsdomainname`
# 3) to select an alternative config file
# by setting DNSMASQ_OPTS to --conf-file=<file>
# 4) to tell dnsmasq to read the files in /etc/dnsmasq.d for
# more configuration variables.
# 5) to stop the resolvconf package from controlling dnsmasq's
# idea of which upstream nameservers to use.
# For upgraders from very old versions, all the shell variables set
# here in previous versions are still honored by the init script
# so if you just keep your old version of this file nothing will break.
#DOMAIN_SUFFIX=`dnsdomainname`
#DNSMASQ_OPTS="--conf-file=/etc/dnsmasq.alt"
# Whether or not to run the dnsmasq daemon; set to 0 to disable.
ENABLED=1
# By default search this drop directory for configuration options.
# Libvirt leaves a file here to make the system dnsmasq play nice.
# Comment out this line if you don't want this. The dpkg-* are file
# endings which cause dnsmasq to skip that file. This avoids pulling
# in backups made by dpkg.
CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
# If the resolvconf package is installed, dnsmasq will use its output
# rather than the contents of /etc/resolv.conf to find upstream
# nameservers. Uncommenting this line inhibits this behaviour.
# Note that including a "resolv-file=<filename>" line in
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
# installed: the line below must be uncommented.
#IGNORE_RESOLVCONF=yes

View File

@@ -1 +0,0 @@
/etc/dbus-1/system.d/dnsmasq.conf

View File

@@ -1,24 +0,0 @@
#!/bin/sh
set -e
# Create the dnsmasq user in dnsmasq-base, so that Dbus doesn't complain.
# create a user to run as (code stolen from dovecot-common)
if [ "$1" = "configure" ]; then
if [ -z "`id -u dnsmasq 2> /dev/null`" ]; then
adduser --system --home /var/lib/misc --gecos "dnsmasq" \
--no-create-home --disabled-password \
--quiet dnsmasq || true
fi
# Make the directory where we keep the pid file - this
# has to be owned by "dnsmasq" so that the file can be unlinked.
# This is only actually used by the dnsmasq binary package, not
# dnsmasq-base, but it's much easier to create it here so that
# we don't have synchronisation issues with the creation of the
# dnsmasq user.
if [ ! -d /var/run/dnsmasq ]; then
mkdir /var/run/dnsmasq
chown dnsmasq:nogroup /var/run/dnsmasq
fi
fi

View File

@@ -1,11 +0,0 @@
#!/bin/sh
set -e
if [ purge = "$1" ]; then
if [ -x "$(command -v deluser)" ]; then
deluser --quiet --system dnsmasq > /dev/null || true
else
echo >&2 "not removing dnsmasq system account because deluser command was not found"
fi
rm -rf /var/run/dnsmasq
fi

317
debian/init vendored
View File

@@ -1,317 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: dnsmasq
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $network $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: DHCP and DNS server
### END INIT INFO
set +e # Don't exit on error status
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/dnsmasq
NAME=dnsmasq
DESC="DNS forwarder and DHCP server"
# Most configuration options in /etc/default/dnsmasq are deprecated
# but still honoured.
ENABLED=1
if [ -r /etc/default/$NAME ]; then
. /etc/default/$NAME
fi
# Get the system locale, so that messages are in the correct language, and the
# charset for IDN is correct
if [ -r /etc/default/locale ]; then
. /etc/default/locale
export LANG
fi
# /etc/dnsmasq.d/README is a non-conffile installed by the dnsmasq package.
# Should the dnsmasq package be removed, the following test ensures that
# the daemon is no longer started, even if the dnsmasq-base package is
# still in place.
test -e /etc/dnsmasq.d/README || exit 0
test -x $DAEMON || exit 0
# Provide skeleton LSB log functions for backports which don't have LSB functions.
if [ -f /lib/lsb/init-functions ]; then
. /lib/lsb/init-functions
else
log_warning_msg () {
echo "${@}."
}
log_success_msg () {
echo "${@}."
}
log_daemon_msg () {
echo -n "${1}: $2"
}
log_end_msg () {
if [ $1 -eq 0 ]; then
echo "."
elif [ $1 -eq 255 ]; then
/bin/echo -e " (warning)."
else
/bin/echo -e " failed!"
fi
}
fi
# RESOLV_CONF:
# If the resolvconf package is installed then use the resolv conf file
# that it provides as the default. Otherwise use /etc/resolv.conf as
# the default.
#
# If IGNORE_RESOLVCONF is set in /etc/default/dnsmasq or an explicit
# filename is set there then this inhibits the use of the resolvconf-provided
# information.
#
# Note that if the resolvconf package is installed it is not possible to
# override it just by configuration in /etc/dnsmasq.conf, it is necessary
# to set IGNORE_RESOLVCONF=yes in /etc/default/dnsmasq.
if [ ! "$RESOLV_CONF" ] &&
[ "$IGNORE_RESOLVCONF" != "yes" ] &&
[ -x /sbin/resolvconf ]
then
RESOLV_CONF=/var/run/dnsmasq/resolv.conf
fi
for INTERFACE in $DNSMASQ_INTERFACE; do
DNSMASQ_INTERFACES="$DNSMASQ_INTERFACES -i $INTERFACE"
done
for INTERFACE in $DNSMASQ_EXCEPT; do
DNSMASQ_INTERFACES="$DNSMASQ_INTERFACES -I $INTERFACE"
done
if [ ! "$DNSMASQ_USER" ]; then
DNSMASQ_USER="dnsmasq"
fi
# This tells dnsmasq to ignore DNS requests that don't come from a local network.
# It's automatically ignored if --interface --except-interface, --listen-address
# or --auth-server exist in the configuration, so for most installations, it will
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
# from being vulnerable to DNS-reflection attacks.
DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
# If the dns-root-data package is installed, then the trust anchors will be
# available in $ROOT_DS, in BIND zone-file format. Reformat as dnsmasq
# --trust-anchor options.
ROOT_DS="/usr/share/dns/root.ds"
if [ -f $ROOT_DS ]; then
DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -e s/". IN DS "/--trust-anchor=.,/ -e s/" "/,/g $ROOT_DS | tr '\n' ' '`"
fi
start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
# /var/run may be volatile, so we need to ensure that
# /var/run/dnsmasq exists here as well as in postinst
if [ ! -d /var/run/dnsmasq ]; then
mkdir /var/run/dnsmasq || return 2
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
fi
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON -- \
-x /var/run/dnsmasq/$NAME.pid \
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
${MAILTARGET:+ -t $MAILTARGET} \
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
${DHCP_LEASE:+ -l $DHCP_LEASE} \
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
${RESOLV_CONF:+ -r $RESOLV_CONF} \
${CACHESIZE:+ -c $CACHESIZE} \
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} \
|| return 2
}
start_resolvconf()
{
# If interface "lo" is explicitly disabled in /etc/default/dnsmasq
# Then dnsmasq won't be providing local DNS, so don't add it to
# the resolvconf server set.
for interface in $DNSMASQ_EXCEPT
do
[ $interface = lo ] && return
done
if [ -x /sbin/resolvconf ] ; then
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.$NAME
fi
return 0
}
stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /var/run/dnsmasq/$NAME.pid --name $NAME
}
stop_resolvconf()
{
if [ -x /sbin/resolvconf ] ; then
/sbin/resolvconf -d lo.$NAME
fi
return 0
}
status()
{
# Return
# 0 if daemon is running
# 1 if daemon is dead and pid file exists
# 3 if daemon is not running
# 4 if daemon status is unknown
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
case "$?" in
0) [ -e "/var/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
1) return 0 ;;
*) return 4 ;;
esac
}
case "$1" in
start)
test "$ENABLED" != "0" || exit 0
log_daemon_msg "Starting $DESC" "$NAME"
start
case "$?" in
0)
log_end_msg 0
start_resolvconf
exit 0
;;
1)
log_success_msg "(already running)"
exit 0
;;
*)
log_end_msg 1
exit 1
;;
esac
;;
stop)
stop_resolvconf
if [ "$ENABLED" != "0" ]; then
log_daemon_msg "Stopping $DESC" "$NAME"
fi
stop
RETVAL="$?"
if [ "$ENABLED" = "0" ]; then
case "$RETVAL" in
0) log_daemon_msg "Stopping $DESC" "$NAME"; log_end_msg 0 ;;
esac
exit 0
fi
case "$RETVAL" in
0) log_end_msg 0 ; exit 0 ;;
1) log_warning_msg "(not running)" ; exit 0 ;;
*) log_end_msg 1; exit 1 ;;
esac
;;
restart|force-reload)
test "$ENABLED" != "0" || exit 1
$DAEMON --test ${CONFIG_DIR:+ -7 $CONFIG_DIR} ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} >/dev/null 2>&1
if [ $? -ne 0 ]; then
NAME="configuration syntax check"
RETVAL="2"
else
stop_resolvconf
stop
RETVAL="$?"
fi
log_daemon_msg "Restarting $DESC" "$NAME"
case "$RETVAL" in
0|1)
sleep 2
start
case "$?" in
0)
log_end_msg 0
start_resolvconf
exit 0
;;
*)
log_end_msg 1
exit 1
;;
esac
;;
*)
log_end_msg 1
exit 1
;;
esac
;;
status)
log_daemon_msg "Checking $DESC" "$NAME"
status
case "$?" in
0) log_success_msg "(running)" ; exit 0 ;;
1) log_success_msg "(dead, pid file exists)" ; exit 1 ;;
3) log_success_msg "(not running)" ; exit 3 ;;
*) log_success_msg "(unknown)" ; exit 4 ;;
esac
;;
dump-stats)
kill -s USR1 `cat /var/run/dnsmasq/$NAME.pid`
;;
systemd-start-resolvconf)
start_resolvconf
;;
systemd-stop-resolvconf)
stop_resolvconf
;;
systemd-exec)
# /var/run may be volatile, so we need to ensure that
# /var/run/dnsmasq exists here as well as in postinst
if [ ! -d /var/run/dnsmasq ]; then
mkdir /var/run/dnsmasq || return 2
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
fi
# Enable DBus by default because we use DBus activation with systemd.
exec $DAEMON --keep-in-foreground --enable-dbus \
-x /var/run/dnsmasq/$NAME.pid \
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
${MAILTARGET:+ -t $MAILTARGET} \
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
${DHCP_LEASE:+ -l $DHCP_LEASE} \
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
${RESOLV_CONF:+ -r $RESOLV_CONF} \
${CACHESIZE:+ -c $CACHESIZE} \
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
;;
*)
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|dump-stats|status}" >&2
exit 3
;;
esac
exit 0

1
debian/insserv vendored
View File

@@ -1 +0,0 @@
$named dnsmasq

38
debian/postinst vendored
View File

@@ -1,38 +0,0 @@
#!/bin/sh
set -e
# Code copied from dh_systemd_enable ----------------------
# This will only remove masks created by d-s-h on package removal.
deb-systemd-helper unmask dnsmasq.service >/dev/null || true
# was-enabled defaults to true, so new installations run enable.
if deb-systemd-helper --quiet was-enabled dnsmasq.service; then
# Enables the unit on first installation, creates new
# symlinks on upgrades if the unit file has changed.
deb-systemd-helper enable dnsmasq.service >/dev/null || true
else
# Update the statefile to add new symlinks (if any), which need to be
# cleaned up on purge. Also remove old symlinks.
deb-systemd-helper update-state dnsmasq.service >/dev/null || true
fi
# End code copied from dh_systemd_enable ------------------
if [ -x /etc/init.d/dnsmasq ]; then
update-rc.d dnsmasq defaults 15 85 >/dev/null
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
if [ -e /var/run/dnsmasq/dnsmasq.pid ]; then
ACTION=restart
else
ACTION=start
fi
if [ -x /usr/sbin/invoke-rc.d ] ; then
invoke-rc.d dnsmasq $ACTION || true
else
/etc/init.d/dnsmasq $ACTION || true
fi
fi
fi

22
debian/postrm vendored
View File

@@ -1,22 +0,0 @@
#!/bin/sh
set -e
if [ purge = "$1" ]; then
update-rc.d dnsmasq remove >/dev/null
fi
# Code copied from dh_systemd_enable ----------------------
if [ "$1" = "remove" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper mask dnsmasq.service >/dev/null
fi
fi
if [ "$1" = "purge" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper purge dnsmasq.service >/dev/null
deb-systemd-helper unmask dnsmasq.service >/dev/null
fi
fi
# End code copied from dh_systemd_enable ------------------

14
debian/prerm vendored
View File

@@ -1,14 +0,0 @@
#!/bin/sh
set -e
if [ "$1" = "remove" ]; then
if [ -x /usr/sbin/invoke-rc.d ] ; then
invoke-rc.d dnsmasq stop || true
else
/etc/init.d/dnsmasq stop || true
fi
fi
exit 0

79
debian/readme vendored
View File

@@ -1,79 +0,0 @@
Notes on configuring dnsmasq as packaged for Debian.
(1) To configure dnsmasq edit /etc/dnsmasq.conf. The file is well
commented; see also the dnsmasq.8 man page for explanation of
the options. The file /etc/default/dnsmasq also exists but it
shouldn't need to be touched in most cases. To set up DHCP
options you might need to refer to a copy of RFC 2132. This is
available on Debian systems in the package doc-rfc-std as the file
/usr/share/doc/RFC/draft-standard/rfc2132.txt.gz .
(2) Installing the dnsmasq package also creates the directory
/etc/dnsmasq.d which is searched by dnsmasq for configuration file
fragments. This behaviour can be disabled by editing
/etc/default/dnsmasq.
(3) If the Debian resolvconf package is installed then, regardless
of what interface configuration daemons are employed, the list of
nameservers to which dnsmasq should forward queries can be found
in /var/run/dnsmasq/resolv.conf; also, 127.0.0.1 is listed as the
first nameserver address in /etc/resolv.conf. This works using the
default configurations of resolvconf and dnsmasq.
(4) In the absence of resolvconf, if you are using dhcpcd then
dnsmasq should read the list of nameservers from the automatically
generated file /etc/dhcpc/resolv.conf. You should list 127.0.0.1
as the first nameserver address in /etc/resolv.conf.
(5) In the absence of resolvconf, if you are using pppd then
dnsmasq should read the list of nameservers from the automatically
generated file /etc/ppp/resolv.conf. You should list 127.0.0.1
as the first nameserver address in /etc/resolv.conf.
(6) In the absence of resolvconf, dns-nameservers lines in
/etc/network/interfaces are ignored. If you do do not use
resolvconf, list 127.0.0.1 as the first nameserver address
in /etc/resolv.conf and configure your nameservers using
"server=<IP-address>" lines in /etc/dnsmasq.conf.
(7) If you run multiple DNS servers on a single machine, each
listening on a different interface, then it is necessary to use
the bind-interfaces option by uncommenting "bind-interfaces" in
/etc/dnsmasq.conf. This option stops dnsmasq from binding the
wildcard address and allows servers listening on port 53 on
interfaces not in use by dnsmasq to work. The Debian
libvirt package will add a configuration file in /etc/dnsmasq.d
which does this so that the "system" dnsmasq and "private" dnsmasq
instances started by libvirt do not clash.
(8) The following options are supported in DEB_BUILD_OPTIONS
noopt : compile without optimisation.
nostrip : don't remove symbols from binary.
nodocs : omit documentation.
notftp : omit TFTP support.
nodhcp : omit DHCP support.
nodhcp6 : omit DHCPv6 support.
noscript : omit lease-change script support.
use_lua : provide support for lease-change scripts written
in Lua.
noipv6 : omit IPv6 support.
nodbus : omit DBus support.
noconntrack : omit connection tracking support.
noipset : omit IPset support.
nortc : compile alternate mode suitable for systems without an RTC.
noi18n : omit translations and internationalisation support.
noidn : omit international domain name support, must be
combined with noi18n to be effective.
gitversion : set the version of the produced packages from the
git-derived versioning information on the source,
rather the the debian changelog.
(9) Dnsmasq comes as three packages - dnsmasq-utils, dnsmasq-base and
dnsmasq. Dnsmasq-base provides the dnsmasq executable and
documentation (including this file). Dnsmasq, which depends on
dnsmasq-base, provides the init script and configuration
infrastructure. This file assumes that both are installed. It is
possible to install only dnsmasq-base and use dnsmasq as a
non-"system" daemon. Libvirt, for instance, does this.
Dnsmasq-utils provides the utilities dhcp_release and
dhcp_lease_time.

View File

@@ -1,7 +0,0 @@
# All files in this directory will be read by dnsmasq as
# configuration files, except if their names end in
# ".dpkg-dist",".dpkg-old" or ".dpkg-new"
#
# This can be changed by editing /etc/default/dnsmasq

84
debian/resolvconf vendored
View File

@@ -1,84 +0,0 @@
#!/bin/sh
#
# Script to update the resolver list for dnsmasq
#
# N.B. Resolvconf may run us even if dnsmasq is not (yet) running.
# If dnsmasq is installed then we go ahead and update the resolver list
# in case dnsmasq is started later.
#
# Assumption: On entry, PWD contains the resolv.conf-type files.
#
# This file is part of the dnsmasq package.
#
set -e
RUN_DIR="/var/run/dnsmasq"
RSLVRLIST_FILE="${RUN_DIR}/resolv.conf"
TMP_FILE="${RSLVRLIST_FILE}_new.$$"
MY_NAME_FOR_RESOLVCONF="dnsmasq"
[ -x /usr/sbin/dnsmasq ] || exit 0
[ -x /lib/resolvconf/list-records ] || exit 1
PATH=/bin:/sbin
report_err() { echo "$0: Error: $*" >&2 ; }
# Stores arguments (minus duplicates) in RSLT, separated by spaces
# Doesn't work properly if an argument itself contains whitespace
uniquify()
{
RSLT=""
while [ "$1" ] ; do
for E in $RSLT ; do
[ "$1" = "$E" ] && { shift ; continue 2 ; }
done
RSLT="${RSLT:+$RSLT }$1"
shift
done
}
if [ ! -d "$RUN_DIR" ] && ! mkdir --parents --mode=0755 "$RUN_DIR" ; then
report_err "Failed trying to create directory $RUN_DIR"
exit 1
fi
RSLVCNFFILES=""
for F in $(/lib/resolvconf/list-records --after "lo.$MY_NAME_FOR_RESOLVCONF") ; do
case "$F" in
"lo.$MY_NAME_FOR_RESOLVCONF")
# Omit own record
;;
lo.*)
# Include no more records after one for a local nameserver
RSLVCNFFILES="${RSLVCNFFILES:+$RSLVCNFFILES }$F"
break
;;
*)
RSLVCNFFILES="${RSLVCNFFILES:+$RSLVCNFFILES }$F"
;;
esac
done
NMSRVRS=""
if [ "$RSLVCNFFILES" ] ; then
uniquify $(sed -n -e 's/^[[:space:]]*nameserver[[:space:]]\+//p' $RSLVCNFFILES)
NMSRVRS="$RSLT"
fi
# Dnsmasq uses the mtime of $RSLVRLIST_FILE, with a resolution of one second,
# to detect changes in the file. This means that if a resolvconf update occurs
# within one second of the previous one then dnsmasq may fail to notice the
# more recent change. To work around this problem we sleep one second here
# if necessary in order to ensure that the new mtime is different.
if [ -f "$RSLVRLIST_FILE" ] && [ "$(ls -go --time-style='+%s' "$RSLVRLIST_FILE" | { read p h s t n ; echo "$t" ; })" = "$(date +%s)" ] ; then
sleep 1
fi
clean_up() { rm -f "$TMP_FILE" ; }
trap clean_up EXIT
: >| "$TMP_FILE"
for N in $NMSRVRS ; do echo "nameserver $N" >> "$TMP_FILE" ; done
mv -f "$TMP_FILE" "$RSLVRLIST_FILE"

View File

@@ -1,13 +0,0 @@
#!/bin/sh
# Resolvconf packaging event hook script for the dnsmasq package
restart_dnsmasq() {
if which invoke-rc.d >/dev/null 2>&1 ; then
invoke-rc.d dnsmasq restart
elif [ -x /etc/init.d/dnsmasq ] ; then
/etc/init.d/dnsmasq restart
fi
}
case "$1" in
install) restart_dnsmasq ;;
esac

224
debian/rules vendored
View File

@@ -1,224 +0,0 @@
#!/usr/bin/make -f
# debian/rules file - for dnsmasq.
# Copyright 2001-2011 by Simon Kelley
# Based on the sample in the debian hello package which carries the following:
# Copyright 1994,1995 by Ian Jackson.
# I hereby give you perpetual unlimited permission to copy,
# modify and relicense this file, provided that you do not remove
# my name from the file itself. (I assert my moral right of
# paternity under the Copyright, Designs and Patents Act 1988.)
# This file may have to be extensively modified
package=dnsmasq-base
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all" dpkg-buildflags
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
CFLAGS += -Wall -W
LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
DEB_COPTS = $(COPTS)
TARGET = install-i18n
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
# Force package version based on git tags.
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
PACKAGE_VERSION = $(shell bld/get-version `pwd` | sed 's/test/~&/; s/[a-z]/~&/; s/-/./g; s/$$/-1/; s/^/-v/';)
endif
ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_DBUS
endif
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
ifeq ($(DEB_HOST_ARCH_OS),linux)
DEB_COPTS += -DHAVE_CONNTRACK
endif
endif
ifneq (,$(filter noipset,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DNO_IPSET
endif
ifneq (,$(filter nodhcp6,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DNO_DHCP6
endif
ifneq (,$(filter noipv6,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DNO_IPV6
endif
ifneq (,$(filter notftp,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DNO_TFTP
endif
ifneq (,$(filter nodhcp,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DNO_DHCP
endif
ifneq (,$(filter noscript,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DNO_SCRIPT
endif
ifneq (,$(filter nortc,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_BROKEN_RTC
endif
ifneq (,$(filter noi18n,$(DEB_BUILD_OPTIONS)))
TARGET = install
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_IDN
endif
endif
ifneq (,$(filter uselua,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_LUASCRIPT
endif
ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_DNSSEC
endif
ifneq ($(DEB_HOST_ARCH_OS),linux)
# For strlcpy in FreeBSD
LDFLAGS += -lbsd
endif
clean:
$(checkdir)
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
make clean
make -C contrib/wrt clean
binary-indep: checkroot
$(checkdir)
rm -rf debian/daemon
install -m 755 \
-d debian/daemon/DEBIAN \
-d debian/daemon/usr/share/doc \
-d debian/daemon/etc/init.d \
-d debian/daemon/etc/dnsmasq.d \
-d debian/daemon/etc/resolvconf/update.d \
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
-d debian/daemon/etc/default \
-d debian/daemon/lib/systemd/system \
-d debian/daemon/etc/insserv.conf.d
install -m 644 debian/conffiles debian/daemon/DEBIAN
install -m 755 debian/postinst debian/postrm debian/prerm debian/daemon/DEBIAN
install -m 755 debian/init debian/daemon/etc/init.d/dnsmasq
install -m 755 debian/resolvconf debian/daemon/etc/resolvconf/update.d/dnsmasq
install -m 755 debian/resolvconf-package debian/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
install -m 644 debian/default debian/daemon/etc/default/dnsmasq
install -m 644 dnsmasq.conf.example debian/daemon/etc/dnsmasq.conf
install -m 644 debian/readme.dnsmasq.d debian/daemon/etc/dnsmasq.d/README
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-gencontrol $(PACKAGE_VERSION) -T -pdnsmasq -Pdebian/daemon
chown -R root.root debian/daemon
chmod -R g-ws debian/daemon
dpkg --build debian/daemon ..
binary-arch: checkroot
$(checkdir)
rm -rf debian/base
install -m 755 \
-d debian/base/DEBIAN \
-d debian/base/etc/dbus-1/system.d \
-d debian/base/usr/share/doc/$(package) \
-d debian/base/usr/share/doc/$(package)/examples \
-d debian/base/var/run \
-d debian/base/usr/share/$(package) \
-d debian/base/var/lib/misc
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
# Need to remove paypal links in Debian Package for policy reasons.
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >debian/base/usr/share/doc/$(package)/doc.html
echo "</BODY>" >>debian/base/usr/share/doc/$(package)/doc.html
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
install -m 644 dnsmasq.conf.example debian/base/usr/share/doc/$(package)/examples/.
install -m 644 trust-anchors.conf debian/base/usr/share/$(package)/.
install -m 644 FAQ debian/base/usr/share/doc/$(package)/.
gzip -9 debian/base/usr/share/doc/$(package)/FAQ
install -m 644 CHANGELOG debian/base/usr/share/doc/$(package)/changelog
gzip -9 debian/base/usr/share/doc/$(package)/changelog
install -m 644 CHANGELOG.archive debian/base/usr/share/doc/$(package)/changelog.archive
gzip -9 debian/base/usr/share/doc/$(package)/changelog.archive
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
gzip -9 debian/base/usr/share/doc/$(package)/DBus-interface
endif
install -m 644 debian/dnsmasq-base.conffiles debian/base/DEBIAN/conffiles
install -m 755 debian/dnsmasq-base.postinst debian/base/DEBIAN/postinst
install -m 755 debian/dnsmasq-base.postrm debian/base/DEBIAN/postrm
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
gzip -9 debian/base/usr/share/doc/$(package)/changelog.Debian
install -m 644 debian/readme debian/base/usr/share/doc/$(package)/README.Debian
install -m 644 debian/copyright debian/base/usr/share/doc/$(package)/copyright
install -m 644 debian/dbus.conf debian/base/etc/dbus-1/system.d/dnsmasq.conf
gzip -9 debian/base/usr/share/man/man8/dnsmasq.8
for f in debian/base/usr/share/man/*; do \
if [ -f $$f/man8/dnsmasq.8 ]; then \
gzip -9 $$f/man8/dnsmasq.8 ; \
fi \
done
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
endif
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
chown -R root.root debian/base
chmod -R g-ws debian/base
dpkg --build debian/base ..
ifeq ($(DEB_HOST_ARCH_OS),linux)
rm -rf debian/utils
install -m 755 -d debian/utils/DEBIAN \
-d debian/utils/usr/share/man/man1 \
-d debian/utils/usr/bin \
-d debian/utils/usr/share/doc/dnsmasq-utils
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
gzip -9 debian/utils/usr/share/man/man1/dhcp_release.1
install -m 755 contrib/wrt/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
install -m 644 contrib/wrt/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
gzip -9 debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
gzip -9 debian/utils/usr/share/man/man1/dhcp_lease_time.1
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
endif
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-shlibdeps -Tdebian/utils-substvars debian/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
chown -R root.root debian/utils
chmod -R g-ws debian/utils
dpkg --build debian/utils ..
endif
define checkdir
test -f Makefile -a -f debian/rules
endef
# Below here is fairly generic really
binary: binary-arch binary-indep
build:
build-arch:
build-indep:
checkroot:
test root = "`whoami`"
.PHONY: binary binary-arch binary-indep clean checkroot

View File

@@ -1 +0,0 @@
1.0

View File

@@ -1,32 +0,0 @@
[Unit]
Description=dnsmasq - A lightweight DHCP and caching DNS server
[Service]
Type=dbus
BusName=uk.org.thekelleys.dnsmasq
# Test the config file and refuse starting if it is not valid.
ExecStartPre=/usr/sbin/dnsmasq --test
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
# wrapper picking up extra configuration files and then execs dnsmasq
# itself, when called with the "systemd-exec" function.
#
# It also adds the command-line flags
# --keep-in-foreground --enable-dbus
# to enable DBus by default because we use DBus activation.
#
ExecStart=/etc/init.d/dnsmasq systemd-exec
# The systemd-*-resolvconf functions configure (and deconfigure)
# resolvconf to work with the dnsmasq DNS server. They're called liek
# this to get correct error handling (ie don't start-resolvconf if the
# dnsmasq daemon fails to start.
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target

View File

@@ -27,8 +27,8 @@
# Replies which are not DNSSEC signed may be legitimate, because the domain
# is unsigned, or may be forgeries. Setting this option tells dnsmasq to
# check that an unsigned reply is OK, by finding a secure proof that a DS
# record somewhere between the root and the domain does not exist.
# check that an unsigned reply is OK, by finding a secure proof that a DS
# record somewhere between the root and the domain does not exist.
# The cost of setting this is that even queries in unsigned domains will need
# one or more extra DNS queries to verify.
#dnssec-check-unsigned
@@ -85,12 +85,22 @@
# subdomains to the vpn and search ipsets:
#ipset=/yahoo.com/google.com/vpn,search
# Add the IPs of all queries to yahoo.com, google.com, and their
# subdomains to netfilters sets, which is equivalent to
# 'nft add element ip test vpn { ... }; nft add element ip test search { ... }'
#nftset=/yahoo.com/google.com/ip#test#vpn,ip#test#search
# Use netfilters sets for both IPv4 and IPv6:
# This adds all addresses in *.yahoo.com to vpn4 and vpn6 for IPv4 and IPv6 addresses.
#nftset=/yahoo.com/4#ip#test#vpn4
#nftset=/yahoo.com/6#ip#test#vpn6
# You can control how dnsmasq talks to a server: this forces
# queries to 10.1.2.3 to be routed via eth1
# server=10.1.2.3@eth1
# and this sets the source (ie local) address used to talk to
# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
# 10.1.2.3 to 192.168.1.1 port 55 (there must be an interface with that
# IP on the machine, obviously).
# server=10.1.2.3@192.168.1.1#55
@@ -183,13 +193,13 @@
#dhcp-range=1234::2, 1234::500, 64, 12h
# Do Router Advertisements, BUT NOT DHCP for this subnet.
#dhcp-range=1234::, ra-only
#dhcp-range=1234::, ra-only
# Do Router Advertisements, BUT NOT DHCP for this subnet, also try and
# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack
# hosts. Use the DHCPv4 lease to derive the name, network segment and
# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack
# hosts. Use the DHCPv4 lease to derive the name, network segment and
# MAC address and assume that the host will also have an
# IPv6 address calculated using the SLAAC alogrithm.
# IPv6 address calculated using the SLAAC algorithm.
#dhcp-range=1234::, ra-names
# Do Router Advertisements, BUT NOT DHCP for this subnet.
@@ -210,9 +220,9 @@
#dhcp-range=1234::, ra-stateless, ra-names
# Do router advertisements for all subnets where we're doing DHCPv6
# Unless overriden by ra-stateless, ra-names, et al, the router
# Unless overridden by ra-stateless, ra-names, et al, the router
# advertisements will have the M and O bits set, so that the clients
# get addresses and configuration from DHCPv6, and the A bit reset, so the
# get addresses and configuration from DHCPv6, and the A bit reset, so the
# clients don't use SLAAC addresses.
#enable-ra
@@ -251,6 +261,13 @@
# the IP address 192.168.0.60
#dhcp-host=id:01:02:02:04,192.168.0.60
# Always give the InfiniBand interface with hardware address
# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
# ip address 192.168.0.61. The client id is derived from the prefix
# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
# hex digits of the hardware address.
#dhcp-host=id:ff:00:00:00:00:00:02:00:00:02:c9:00:f4:52:14:03:00:28:05:81,192.168.0.61
# Always give the host with client identifier "marjorie"
# the IP address 192.168.0.60
#dhcp-host=id:marjorie,192.168.0.60
@@ -278,11 +295,11 @@
# any machine with Ethernet address starting 11:22:33:
#dhcp-host=11:22:33:*:*:*,set:red
# Give a fixed IPv6 address and name to client with
# Give a fixed IPv6 address and name to client with
# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
# Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
# Note also the they [] around the IPv6 address are obilgatory.
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
# Note also that the [] around the IPv6 address are obligatory.
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
# Ignore any clients which are not specified in dhcp-host lines
# or /etc/ethers. Equivalent to ISC "deny unknown-clients".
@@ -338,13 +355,21 @@
# Send DHCPv6 option. Note [] around IPv6 addresses.
#dhcp-option=option6:dns-server,[1234::77],[1234::88]
# Send DHCPv6 option for namservers as the machine running
# Send DHCPv6 option for namservers as the machine running
# dnsmasq and another.
#dhcp-option=option6:dns-server,[::],[1234::88]
# Ask client to poll for option changes every six hours. (RFC4242)
#dhcp-option=option6:information-refresh-time,6h
# Set option 58 client renewal time (T1). Defaults to half of the
# lease time if not specified. (RFC2132)
#dhcp-option=option:T1,1m
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
# lease time if not specified. (RFC2132)
#dhcp-option=option:T2,2m
# Set the NTP time server address to be the same machine as
# is running dnsmasq
#dhcp-option=42,0.0.0.0
@@ -369,7 +394,7 @@
# The following DHCP options set up dnsmasq in the same way as is specified
# for the ISC dhcpcd in
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
# https://web.archive.org/web/20040313070105/http://us1.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
# adapted for a typical dnsmasq installation where the host running
# dnsmasq is also the host running samba.
# you may want to uncomment some or all of them if you use
@@ -421,22 +446,22 @@
#dhcp-option-force=211,30i
# Set the boot filename for netboot/PXE. You will only need
# this is you want to boot machines over the network and you will need
# a TFTP server; either dnsmasq's built in TFTP server or an
# this if you want to boot machines over the network and you will need
# a TFTP server; either dnsmasq's built-in TFTP server or an
# external one. (See below for how to enable the TFTP server.)
#dhcp-boot=pxelinux.0
# The same as above, but use custom tftp-server instead machine running dnsmasq
#dhcp-boot=pxelinux,server.name,192.168.1.100
# Boot for Etherboot gPXE. The idea is to send two different
# filenames, the first loads gPXE, and the second tells gPXE what to
# load. The dhcp-match sets the gpxe tag for requests from gPXE.
#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
#dhcp-boot=tag:!gpxe,undionly.kpxe
#dhcp-boot=mybootimage
# Boot for iPXE. The idea is to send two different
# filenames, the first loads iPXE, and the second tells iPXE what to
# load. The dhcp-match sets the ipxe tag for requests from iPXE.
#dhcp-boot=undionly.kpxe
#dhcp-match=set:ipxe,175 # iPXE sends a 175 option.
#dhcp-boot=tag:ipxe,http://boot.ipxe.org/demo/boot.php
# Encapsulated options for Etherboot gPXE. All the options are
# Encapsulated options for iPXE. All the options are
# encapsulated within option 175
#dhcp-option=encap:175, 1, 5b # priority code
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
@@ -486,6 +511,9 @@
# Set the root directory for files available via FTP.
#tftp-root=/var/ftpd
# Do not abort if the tftp-root is unavailable
#tftp-no-fail
# Make the TFTP server more secure: with this set, only files owned by
# the user dnsmasq is running as will be send over the net.
#tftp-secure
@@ -507,7 +535,7 @@
# (using /etc/hosts) then that name can be specified as the
# tftp_servername (the third option to dhcp-boot) and in that
# case dnsmasq resolves this name and returns the resultant IP
# addresses in round robin fasion. This facility can be used to
# addresses in round robin fashion. This facility can be used to
# load balance the tftp load among a set of servers.
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
@@ -529,6 +557,14 @@
# http://www.isc.org/files/auth.html
#dhcp-authoritative
# Set the DHCP server to enable DHCPv4 Rapid Commit Option per RFC 4039.
# In this mode it will respond to a DHCPDISCOVER message including a Rapid Commit
# option with a DHCPACK including a Rapid Commit option and fully committed address
# and configuration information. This must only be enabled if either the server is
# the only server for the subnet, or multiple servers are present and they each
# commit a binding for all clients.
#dhcp-rapid-commit
# Run an executable when a DHCP lease is created or destroyed.
# The arguments sent to the script are "add" or "del",
# then the MAC address, the IP address and finally the hostname
@@ -628,7 +664,7 @@
# Provide an alias for a "local" DNS name. Note that this _only_ works
# for targets which are names from DHCP or /etc/hosts. Give host
# "bert" another name, bertrand
#cname=bertand,bert
#cname=bertrand,bert
# For debugging purposes, log each DNS query as it passes through
# dnsmasq.
@@ -646,3 +682,8 @@
# Include all files in a directory which end in .conf
#conf-dir=/etc/dnsmasq.d/,*.conf
# If a DHCP client claims that its name is "wpad", ignore that.
# This fixes a security hole. see CERT Vulnerability VU#598349
#dhcp-name-match=set:wpad-ignore,wpad
#dhcp-ignore-names=tag:wpad-ignore

View File

@@ -18,7 +18,7 @@ Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmas
<P>
The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
cacheing of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
caching of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
<DIR>
<LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
<LI>Upstream servers can be configured in a variety of convenient ways, including dynamic configuration as these change on moving upstream network.
@@ -66,6 +66,10 @@ the repo, or get a copy using git protocol with the command
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
or
<PRE><TT>git clone http://thekelleys.org.uk/git/dnsmasq.git </TT></PRE>
<H2>License.</H2>
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
for details.
@@ -74,7 +78,9 @@ for details.
There is a dnsmasq mailing list at <A
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
first location for queries, bugreports, suggestions etc.
first location for queries, bugreports, suggestions etc. The list is mirrored, with a
search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
You can contact me at <A
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
@@ -89,7 +95,5 @@ a contribution towards my expenses, please use the donation button below.
<input type="image" src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal The safer, easier way to pay online.">
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1">
</form>
</BODY>
</HTML>

File diff suppressed because it is too large Load Diff

View File

@@ -478,7 +478,8 @@ la traza reversa direcci
.TP
.B \-c, --cache-size=<tamaño de caché>
Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
Fijar el tamaño a cero deshabilita el caché.
Fijar el tamaño a cero deshabilita el caché. Nota: el gran tamaño de
caché afecta el rendimiento.
.TP
.B \-N, --no-negcache
Deshabilitar caché negativo. El caché negativo le permite a dnsmasq
@@ -1062,10 +1063,14 @@ esta opci
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
.TP
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
como si hubieran llegado a la interface <nombre de interface>. Esta opción
es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
los paquetes llegan a interfaces tap que no tienen una dirección IP.
Tratar paquetes de pedidos DHCP (v4 y v6) y de IPv6 Router Solicit que
llegan a cualquiera de las interfaces <alias> como si hubieran llegado
a la interface <nombre de interface>. Esta opción permite que dnsmasq
puede proporcionar los servicios DHCP y RA a través de interfaces
ethernet sin dirección y sin puente; por ejemplo en un nodo de cálculo
de OpenStack, donde cada una de esas interfaces es una interfaz TAP
para una máquina virtual, o al usar bridging estilo viejo en
plataformas BSD.
.TP
.B \-s, --domain=<dominio>[,<rango de IPs>]
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser

View File

@@ -10,7 +10,7 @@ est un serveur à faible empreinte mémoire faisant DNS, TFTP, PXE, annonces de
routeurs et DHCP. Il offre à la fois les services DNS et DHCP pour un réseau
local (LAN).
.PP
Dnsmasq accepte les requêtes DNS et y réponds soit en utilisant un petit cache
Dnsmasq accepte les requêtes DNS et y répond soit en utilisant un petit cache
local, soit en effectuant une requête à un serveur DNS récursif externe (par
exemple celui de votre fournisseur d'accès internet). Il charge le contenu du
fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
@@ -19,25 +19,25 @@ pour les hôtes présents dans le service DHCP. Il peut aussi agir en temps que
serveur DNS faisant autorité pour un ou plusieurs domaines, permettant à des
noms locaux d'apparaitre dans le DNS global.
.PP
Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les
Le serveur DHCP de Dnsmasq supporte les définitions d'adresses statiques et les
réseaux multiples. Il fournit par défaut un jeu raisonnable de paramètres DHCP,
et peut être configuré pour fournir n'importe quelle option DHCP.
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. Le
support PXE est complet, et comprend un mode proxy permettant de fournir des
informations PXE aux clients alors que l'allocation DHCP est effectuée par un
autre serveur.
informations PXE aux clients alors que l'allocation d'adresse via DHCP est
effectuée par un autre serveur.
.PP
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionalités
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionnalités
que le serveur DHCPv4, mais aussi le support des annonces de routeurs ainsi
qu'une fonctionalité permettant l'addition de ressources AAAA pour des
qu'une fonctionnalité permettant l'addition de ressources AAAA pour des
clients utilisant DHCPv4 et la configuration IPv6 sans état (stateless
autoconfiguration).
Il inclut le support d'allocations d'adresses (à la fois en DHCPv6 et en
annonces de routeurs - RA) pour des sous-réseaux dynamiquement délégués via
une délégation de préfixe DHCPv6.
.PP
Dnsmasq est developpé pour de petits systèmes embarqués. It tends à avoir
Dnsmasq est développé pour de petits systèmes embarqués. Il tend à avoir
l'empreinte mémoire la plus faible possible pour les fonctions supportées,
et permet d'exclure les fonctions inutiles du binaire compilé.
.SH OPTIONS
@@ -46,16 +46,23 @@ Dans ce cas, la fonction correspondante sera désactivée. Par exemple
.B --pid-file=
(sans paramètre après le =) désactive l'écriture du fichier PID.
Sur BSD, à moins que le logiciel ne soit compilé avec la bibliothèque GNU
getopt, la forme longue des options ne fonctionne pas en ligne de commande; Elle
getopt, la forme longue des options ne fonctionne pas en ligne de commande; elle
est toujours supportée dans le fichier de configuration.
.TP
.B --test
Vérifie la syntaxe du ou des fichiers de configurations. Se termine avec le
Vérifie la syntaxe du ou des fichiers de configuration. Se termine avec le
code de retour 0 si tout est OK, ou un code différent de 0 dans le cas
contraire. Ne démarre pas Dnsmasq.
.TP
.B \-w, --help
Affiche toutes les options de ligne de commande.
.B --help dhcp
affiche les options de configuration connues pour DHCPv4, et
.B --help dhcp6
affiche les options de configuration connues pour DHCPv6.
.TP
.B \-h, --no-hosts
Ne pas charger les noms du fichier /etc/hosts.
Ne pas charger les noms d'hôtes du fichier /etc/hosts.
.TP
.B \-H, --addn-hosts=<fichier>
Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts.
@@ -68,7 +75,7 @@ fichiers contenus dans ce répertoire.
.B \-E, --expand-hosts
Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service
DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les
DHCP. Notez que cela ne s'applique pas aux noms de domaine dans les CNAME, les
enregistrements PTR, TXT, etc...
.TP
.B \-T, --local-ttl=<durée>
@@ -86,7 +93,7 @@ Les réponses négatives provenant des serveurs amonts contiennent normalement
une information de durée de vie (time-to-live) dans les enregistrements SOA,
information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse
du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette
option permet de doner une valeur de durée de vie par défaut (en secondes) que
option permet de donner une valeur de durée de vie par défaut (en secondes) que
dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
l'absence d'enregistrement SOA.
.TP
@@ -194,7 +201,7 @@ au dessus de la valeur spécifiée. Utile pour des systèmes derrière des dispo
garde-barrières ("firewalls").
.TP
.B \-i, --interface=<nom d'interface>
N'écouter que sur l'interface réseau spécifiée. Dnsmasq aujoute automatiquement
N'écouter que sur l'interface réseau spécifiée. Dnsmasq ajoute automatiquement
l'interface locale ("loopback") à la liste des interfaces lorsque l'option
.B --interface
est utilisée.
@@ -205,13 +212,13 @@ ou
n'est donnée, Dnsmasq écoutera sur toutes les interfaces disponibles sauf
celle(s) spécifiée(s) par l'option
.B --except-interface.
Les alias d'interfaces IP (e-g "eth1:0") ne peuvent être utilisés ni avec
Les alias d'interfaces IP (par exemple "eth1:0") ne peuvent être utilisés ni avec
.B --interface
ni
.B \--except-interface.
Utiliser l'option
.B --listen-address
à la place. Un simple joker, consistant d'un '*' final, peut-être utilisé dans
à la place. Un simple joker, consistant en un '*' final, peut être utilisé dans
les options
.B \--interface
et
@@ -229,10 +236,10 @@ sont fournies n'importe pas, et que l'option
.B --except-interface
l'emporte toujours sur les autres.
.TP
.B --auth-server=<domaine>,<interface>|<addresse IP>
.B --auth-server=<domaine>,<interface>|<adresse IP>
Active le mode DNS faisant autorité pour les requêtes arrivant sur cette
interface ou sur cette adresse. Noter que l'interface ou l'adresse n'ont
pas besoin d'être mentionées ni dans
pas besoin d'être mentionnées ni dans
.B --interface
ni dans
.B --listen-address
@@ -253,7 +260,7 @@ Ecouter sur la ou les adresse(s) IP spécifiée(s). Les options
.B \--interface
et
.B \--listen-address
peuvent-être spécifiées simultanément, auquel cas un jeu d'interfaces et
peuvent être spécifiées simultanément, auquel cas un jeu d'interfaces et
d'adresses seront utilisées. Notez que si
aucune option
.B \--interface
@@ -265,7 +272,7 @@ nécessaire de fournir explicitement son adresse IP, 127.0.0.1 via l'option
.B \--listen-address.
.TP
.B \-z, --bind-interfaces
Sur les systèmes qui le supporte, Dnsmasq s'associe avec l'interface joker
Sur les systèmes qui le supportent, Dnsmasq s'associe avec l'interface joker
("wildcard"), même lorsqu'il ne doit écouter que sur certaines interfaces. Par
la suite, il rejette les requêtes auxquelles il ne doit pas répondre. Cette
situation présente l'avantage de fonctionner même lorsque les interfaces vont
@@ -302,7 +309,7 @@ le réseau auquel ils sont attachés). Cette possibilité est actuellement limit
.TP
.B \-b, --bogus-priv
Fausse résolution inverse pour les réseaux privés. Toutes les requêtes DNS
inverses pour des adresses IP privées (ie 192.168.x.x, etc...) qui ne sont pas
inverses pour des adresses IP privées (192.168.x.x, etc...) qui ne sont pas
trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées
une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises
aux serveurs de nom amont ("upstream server").
@@ -317,7 +324,7 @@ modifiera 1.2.3.56 en 6.7.8.56 et 1.2.3.67 en 6.7.8.67.
Cette fonctionnalité correspond à ce que les routeurs Cisco PIX appellent
"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme
d'une gamme d'adresses, alors seules les adresses dans cette gamme seront
ecrites, et non le sous-réseau dans son ensemble. Ainsi,
écrites, et non le sous-réseau dans son ensemble. Ainsi,
.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
fait correspondre 192.168.0.10->192.168.0.40 à 10.0.0.10->10.0.0.40
.TP
@@ -380,7 +387,7 @@ effectuer ses requêtes à tous les serveurs disponibles. Le résultat renvoyé
au client sera celui fournit par le premier serveur ayant répondu.
.TP
.B --stop-dns-rebind
Rejete (et enregistre dans le journal d'activité) les adresses dans la gamme
Rejette (et enregistre dans le journal d'activité) les adresses dans la gamme
d'adresses IP privée (au sens RFC1918) qui pourraient être renvoyées par les
serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherchant
à détourner de leur usage les logiciels de navigation web ('browser') en s'en
@@ -389,13 +396,13 @@ servant pour découvrir les machines situées sur le réseau local.
.B --rebind-localhost-ok
Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses
est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la
lutte contre le spam), la bloquer peut entraîner des disfonctionnements de ces
lutte contre le spam), la bloquer peut entraîner des dysfonctionnements de ces
services.
.TP
.B --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/]
Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines.
Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs
noms de domains entourés par des '/', selon une syntaxe similaire à l'option
noms de domaine entourés par des '/', selon une syntaxe similaire à l'option
--server, c-à-d :
.B --rebind-domain-ok=/domaine1/domaine2/domaine3/
.TP
@@ -474,7 +481,7 @@ serveur de nom. Il doit s'agir d'une des adresses IP appartenant à la machine s
laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera
consignée dans le journal des événements, ou alors d'un nom d'interface. Si un nom
d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées
depuis cette interface; si une adresse ip est donnée, alors l'adresse source de
depuis cette interface; si une adresse IP est donnée, alors l'adresse source de
la requête sera l'adresse en question. L'option query-port est ignorée pour tous
les serveurs ayant une adresse source spécifiée, mais il est possible de la donner
directement dans la spécification de l'adresse source. Forcer les requêtes à être
@@ -510,7 +517,7 @@ d'IP netfilter (ipset) indiqués. Domaines et sous-domaines sont résolus de la
même façon que pour --address. Ces groupes d'IP doivent déjà exister. Voir
ipset(8) pour plus de détails.
.TP
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préference>]
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préférence>]
Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom
donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans
l'option
@@ -612,7 +619,7 @@ l'enregistrement est donnée dans les données hexadécimales, qui peuvent
être de la forme 01:23:45, 01 23 45,+012345 ou n'importe quelle combinaison.
.TP
.B --interface-name=<nom>,<interface>
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
Définit un enregistrement DNS associant le nom avec l'adresse primaire sur
l'interface donnée en argument. Cette option spécifie un enregistrement de type
A pour le nom donné en argument de la même façon que s'il était défini par une
ligne de /etc/hosts, sauf que l'adresse n'est pas constante mais dépendante de
@@ -638,7 +645,7 @@ IPv6 pouvant commencer par '::', mais les noms DNS ne pouvant pas commencer
par '-', si aucun préfixe n'est donné, un zéro est ajouté en début de nom.
Ainsi, ::1 devient 0--1.
La plage d'adresses peut-être de la forme
La plage d'adresses peut être de la forme
<adresse IP>,<adresse IP> ou <adresse IP>/<masque réseau>
.TP
.B --add-mac
@@ -647,7 +654,7 @@ amonts. Cela peut être utilisé dans un but de filtrage DNS par les serveurs
amonts. L'adresse MAC peut uniquement être ajoutée si le requêteur est sur le
même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme
utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée,
aussi cette fonctionalité doit être considérée comme expérimentale. Notez
aussi cette fonctionnalité doit être considérée comme expérimentale. Notez
également qu'exposer les adresses MAC de la sorte peut avoir des implications
en termes de sécurité et de vie privée. L'avertissement donné pour --add-subnet
s'applique également ici.
@@ -659,19 +666,20 @@ longueur du préfixe : 32 (ou 128 dans le cas d'IPv6) transmet la totalité
de l'adresse, 0 n'en transmet aucun mais marque néanmoins la requête ce qui
fait qu'aucun serveur amont ne rajoutera d'adresse client. La valeur par
défaut est zéro et pour IPv4 et pour IPv6. A noter que les serveurs amonts
peuvent-être configurés pour retourner des valeurs différentes en fonction
peuvent être configurés pour retourner des valeurs différentes en fonction
de cette information mais que le cache de dnsmasq n'en tient pas compte.
Si une instance de dnsmasq est configurée de telle maniêre que des valeurs
différentes pourraient-être rencontrés, alors le cache devrait être désactivé.
Si une instance de dnsmasq est configurée de telle manière que des valeurs
différentes pourraient être rencontrées, alors le cache devrait être désactivé.
.TP
.B \-c, --cache-size=<taille>
Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
Définir une valeur de zéro désactive le cache.
Définir une valeur de zéro désactive le cache. Remarque: la taille importante
du cache a un impact sur les performances.
.TP
.B \-N, --no-negcache
Désactive le "cache négatif". Le "cache négatif" permet à Dnsmasq de se souvenir
des réponses de type "no such domain" fournies par les serveurs DNS en amont et
de fournir les réponses sans avoir à re-transmettre les requêtes aux serveurs
de fournir les réponses sans avoir à retransmettre les requêtes aux serveurs
amont.
.TP
.B \-0, --dns-forward-max=<nombre de requêtes>
@@ -683,17 +691,17 @@ son journal des requêtes, ce qui peut générer un nombre important de requête
simultanées.
.TP
.B --proxy-dnssec
Un resolveur sur une machine cliente peut effectuer la validation DNSSEC de
Un résolveur sur une machine cliente peut effectuer la validation DNSSEC de
deux façons : il peut effectuer lui-même les opérations de chiffrements sur
la réponse reçue, ou il peut laisser le serveur récursif amont faire la
validation et positionner un drapeau dans la réponse au cas où celle-ci est
correcte. Dnsmasq n'est pas un validateur DNSSEC, aussi il ne peut effectuer
la validation comme un serveur de nom récursif, cependant il peut retransmettre
les résultats de validation de ses serveurs amonts. Cette option permet
l'activation de cette fonctionalité. Vous ne devriez utiliser cela que si vous
l'activation de cette fonctionnalité. Vous ne devriez utiliser cela que si vous
faites confiance aux serveurs amonts
.I ainsi que le réseau entre vous et eux.
Si vous utilisez le premier mode DNSSEC, la validation par le resolveur des
Si vous utilisez le premier mode DNSSEC, la validation par le résolveur des
clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les
données nécessaires par un client pour effectuer la validation lui-même.
.TP
@@ -703,12 +711,12 @@ Définie une zone DNS pour laquelle dnsmasq agit en temps que serveur faisant
autorité. Les enregistrements DNS définis localement et correspondant à ce
domaine seront fournis. Les enregistrements A et AAAA doivent se situer dans
l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage DHCP
(ce comportement peut-être désactivé par
(ce comportement peut être désactivé par
.B constructor-noauth:
). Le ou les sous-réseaux sont également utilisé(s) pour définir les domaines
in-addr.arpa et ip6.arpa servant à l'interrogation DNS inverse. Si la longueur
de préfixe n'est pas spécifiée, elle sera par défaut de 24 pour IPv4 et 64 pour
IPv6. Dans le cas d'IPv4, la longueur du masque de réseau devrait-être de 8, 16
IPv6. Dans le cas d'IPv4, la longueur du masque de réseau devrait être de 8, 16
ou 24, sauf si en cas de mise en place d'une délégation de la zone in-addr.arpa
conforme au RFC 2317.
.TP
@@ -719,7 +727,7 @@ optionnel, les valeurs par défaut devant convenir à la majorité des cas.
.TP
.B --auth-sec-servers=<domaine>[,<domaine>[,<domaine>...]]
Spécifie un ou plusieurs serveur de nom secondaires pour une zone pour
laquelle dnsmasq fait autorité. Ces serveurs doivent-être configurés pour
laquelle dnsmasq fait autorité. Ces serveurs doivent être configurés pour
récupérer auprès de dnsmasq les informations liées à la zone au travers d'un
transfert de zone, et répondre aux requêtes pour toutes les zones pour
lesquelles dnsmasq fait autorité.
@@ -733,7 +741,7 @@ seront acceptées pour tous les serveurs secondaires.
.B --conntrack
Lis le marquage de suivi de connexion Linux associé aux requêtes DNS entrantes
et positionne la même marque au trafic amont utilisé pour répondre à ces
requétes. Cela permet au trafic généré par Dnsmasq d'étre associé aux requêtes
requêtes. Cela permet au trafic généré par Dnsmasq d'être associé aux requêtes
l'ayant déclenché, ce qui est pratique pour la gestion de la bande passante
(accounting) et le filtrage (firewall). Dnsmasq doit pour cela être compilé
avec le support conntrack, le noyau doit également inclure conntrack et être
@@ -742,7 +750,7 @@ configuré pour cela. Cette option ne peut pas être combinée avec
.TP
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
.TP
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
<adresse de début> et <adresse de fin> et à partir des adresses définies
@@ -755,7 +763,7 @@ durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par d
de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
minutes.
Pour les plages IPv6, la durée de bail peut-être égale au mot-clef "deprecated"
Pour les plages IPv6, la durée de bail peut être égale au mot-clef "deprecated"
(obsolète); Cela positionne la durée de vie préférée envoyée dans les baux DHCP
ou les annonces routeurs à zéro, ce qui incite les clients à utiliser d'autres
adresses autant que possible, pour toute nouvelle connexion, en préalable à
@@ -795,7 +803,7 @@ adresses assignées à l'interface. Par exemple
provoque la recherche d'adresses de la forme <réseau>::1 sur eth0 et crée une
plage allant de <réseau>::1 à <réseau>:400. Si une interface est assignée à
plus d'un réseau, les plages correspondantes seront automatiquement créées,
rendues obsolètes puis supprimées lorsque l'adress est rendue obsolète puis
rendues obsolètes puis supprimées lorsque l'adresse est rendue obsolète puis
supprimée. Le nom de l'interface peut être spécifié avec un caractère joker '*'
final.
@@ -809,7 +817,7 @@ obsolètes ne conviennent pas.
Si une plage dhcp-range est uniquement utilisée pour du DHCP sans-état
("stateless") ou de l'autoconfiguration sans état ("SLAAC"), alors l'adresse
peut-être indiquée sous la forme '::'
peut être indiquée sous la forme '::'
.B --dhcp-range=::,constructor:eth0
@@ -851,8 +859,8 @@ et
.B pxe-service
pour plus de détails).
Pour IPv6, le mode peut-être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless.
Pour IPv6, le mode peut être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless, off-link.
.B ra-only
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
@@ -883,11 +891,14 @@ connectés (et non ceux pour lesquels DHCP se fait via relai), et ne
fonctionnera pas si un hôte utilise les "extensions de vie privée"
("privacy extensions").
.B ra-names
peut-être combiné avec
peut être combiné avec
.B ra-stateless
et
.B slaac.
.B off-link
indique à dnsmasq d'annoncer le préfixe sans le bit L (sur lien).
.TP
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
@@ -911,7 +922,7 @@ sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pa
besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
déclaration de plage d'adresses dhcp-range.
Il est possible d'utiliser des identifiants clients (appellé "DUID client" dans
Il est possible d'utiliser des identifiants clients (appelés "DUID client" dans
le monde IPv6) plutôt que des adresses matérielles pour identifier les hôtes,
en préfixant ceux-ci par 'id:'. Ainsi,
.B --dhcp-host=id:01:02:03:04,.....
@@ -923,7 +934,7 @@ ceci :
Un seul
.B dhcp-host
peut contenir une adresse IPv4, une adresse IPv6, ou les deux en même temps.
Les adresses IPv6 doivent-être mises entre crochets comme suit :
Les adresses IPv6 doivent être mises entre crochets comme suit :
.B --dhcp-host=laptop,[1234::56]
Les adresses IPv6 peuvent ne contenir que la partie identifiant de client :
.B --dhcp-host=laptop,[::56]
@@ -942,7 +953,7 @@ identifiant client mais pas les autres.
Si un nom apparaît dans /etc/hosts, l'adresse associée peut être allouée à un
bail DHCP mais seulement si une option
.B --dhcp-host
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut-être donné dans
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut être donné dans
une option
.B dhcp-host
, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir
@@ -970,7 +981,7 @@ Les adresses ethernet (mais pas les identifiants clients) peuvent être définie
avec des octets joker, ainsi par exemple
.B --dhcp-host=00:20:e0:3b:13:*,ignore
demande à Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est à noter
que "*" doit-être précédé d'un caractère d'échappement ou mis entre guillemets
que "*" doit être précédé d'un caractère d'échappement ou mis entre guillemets
lorsque spécifié en option de ligne de commande, mais pas dans le fichier de
configuration.
@@ -1056,14 +1067,14 @@ qu'aux réseaux dont tous les labels coïncident avec ceux de la requête.
Un traitement spécial est effectué sur les chaînes de caractères fournies pour
l'option 119, conformément à la RFC 3397. Les chaînes de caractères ou les
adresses IP sous forme de 4 chiffres séparés par des points donnés en arguments
de l'option 120 sont traités conforméments à la RFC 3361. Les adresses IP sous
de l'option 120 sont traités conformément à la RFC 3361. Les adresses IP sous
forme de 4 chiffres séparés par des points suivies par une barre montante "/",
puis une taille de masque sont encodés conforméments à la RFC 3442.
puis une taille de masque sont encodés conformément à la RFC 3442.
Les options IPv6 sont fournies en utilisant le mot-clef
.B option6:
suivi par le numéro d'option ou le nom d'option. L'espace de nommage des options
IPv6 est disjint de l'espace de nommage des options IPv4. Les adresses IPv6
IPv6 est disjoint de l'espace de nommage des options IPv4. Les adresses IPv6
en option doivent être entourées de crochets, comme par exemple :
.B --dhcp-option=option6:ntp-server,[1234::56]
@@ -1072,7 +1083,7 @@ adéquat sont envoyées pour un numéro d'option donné, il est tout à fait pos
de persuader Dnsmasq de générer des paquets DHCP illégaux par une utilisation
incorrecte de cette option. Lorsque la valeur est un nombre décimal, Dnsmasq
doit déterminer la taille des données. Cela est fait en examinant le numéro de
l'option et/ou la valeur, mais peut-être évité en rajoutant un suffixe d'une
l'option et/ou la valeur, mais peut être évité en rajoutant un suffixe d'une
lettre comme suit :
b = un octet, s = 2 octets, i = 4 octets. Cela sert essentiellement pour des
options encapsulées de classes de vendeurs (voir plus bas), pour lesquelles
@@ -1085,7 +1096,7 @@ d'une chaîne de caractères comme nom de serveur TFTP, il est nécessaire de fa
comme suit :
.B --dhcp-option=66,"1.2.3.4"
Les options encapsulées de classes de vendeurs peuvent-être aussi spécifiées
Les options encapsulées de classes de vendeurs peuvent être aussi spécifiées
(pour IPv4 seulement) en utilisant
.B --dhcp-option
: par exemple
@@ -1102,7 +1113,7 @@ par le client. Il est possible d'omettre complètement une classe de vendeur :
.B --dhcp-option=vendor:,1,0.0.0.0
Dans ce cas l'option encapsulée est toujours envoyée.
En IPv4, les options peuvent-être encapsulées au sein d'autres options :
En IPv4, les options peuvent être encapsulées au sein d'autres options :
par exemple
.B --dhcp-option=encap:175, 190, "iscsi-client0"
enverra l'option 175, au sein de laquelle se trouve l'option 190.
@@ -1125,7 +1136,7 @@ une option encapsulée.
Cela fonctionne exactement de la même façon que
.B --dhcp-option
sauf que cette option sera toujours envoyée, même si le client ne la demande pas
dans la liste de paramêtres requis. Cela est parfois nécessaire, par exemple lors
dans la liste de paramètres requis. Cela est parfois nécessaire, par exemple lors
de la fourniture d'options à PXELinux.
.TP
.B --dhcp-no-override
@@ -1146,10 +1157,10 @@ Toutes les requêtes DHCP arrivant sur cette interface seront relayées au
serveur DHCP distant correspondant à l'adresse de serveur indiquée. Il est
possible de relayer depuis une unique adresse locale vers différents serveurs
distant en spécifiant plusieurs fois l'option dhcp-relay avec la même adresse
locale et différentes adresses de serveur. L'adresse de serveur doit-être
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut-être
locale et différentes adresses de serveur. L'adresse de serveur doit être
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut être
l'adresse de multicast ff05::1:3 correspondant à tous les serveurs DHCP. Dans
ce cas, l'interface doittre spécifiée et ne peut comporter de caractère
ce cas, l'interface doit être spécifiée et ne peut comporter de caractère
joker. Elle sera utilisée pour indiquer l'interface à partir de laquelle le
multicast pourra atteindre le serveur DHCP.
@@ -1178,14 +1189,14 @@ vice-versa.
Associe une chaîne de classe de vendeur à un label. La plupart
des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
représente, d'une certaine façon, le type d'hôte. Cette option associe des
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent-être
fournie de manière sélective aux différentes classes d'hôtes. Par exemple,
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent être
fournies de manière sélective aux différentes classes d'hôtes. Par exemple,
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
ou
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
.B --dhcp-option=tag:printers,3,192.168.4.4
La chaîne de caractères de la classe de vendeur founie en argument est cherchée
La chaîne de caractères de la classe de vendeur fournie en argument est cherchée
en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie
par le client, de façon à permettre la recherche d'un sous-ensemble de la chaîne
de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé
@@ -1215,7 +1226,7 @@ matérielle coïncide avec les critères définis.
.TP
.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant>
Associe des options de relais DHCP issus de la RFC3046 à des labels.
Cette information peut-être fournie par des relais DHCP. L'identifiant
Cette information peut être fournie par des relais DHCP. L'identifiant
de circuit ou l'identifiant distant est normalement fourni sous la forme d'une
chaîne de valeurs hexadécimales séparées par des ":", mais il est également
possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si
@@ -1228,7 +1239,7 @@ est supporté en IPv6 (mais non dhcp-circuitid).
(IPv4 et IPv6) Associe des options de relais DHCP issues de la RFC3993 à des
labels.
.TP
.B --dhcp-proxy[=<adresse ip>]......
.B --dhcp-proxy[=<adresse IP>]......
(IPv4 seulement) Un agent relai DHCP normal est uniquement utilisé pour faire
suivre les éléments initiaux de l'interaction avec le serveur DHCP. Une fois
que le client est configuré, il communique directement avec le serveur. Cela
@@ -1249,7 +1260,7 @@ interactions avec les relais dont l'adresse est dans la liste seront affectées.
Si aucune valeur n'est spécifiée, associe le label si le client
envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
fournie, positionne le label seulement dans le cas où l'option est fournie et
correspond à la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel
correspond à la valeur. La valeur peut être de la forme "01:ff:*:02", auquel
cas le début de l'option doit correspondre (en respectant les jokers). La
valeur peut aussi être de la même forme que dans
.B dhcp-option
@@ -1259,14 +1270,14 @@ valeur peut aussi être de la même forme que dans
--dhcp-match=set:efi-ia32,option:client-arch,6
spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
d'architectures envoyé par le client au sein de l'option 93. (se réferer
d'architectures envoyé par le client au sein de l'option 93. (se référer
au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères,
celle-ci est recherchée (correspondance en temps que sous-chaîne).
Pour la forme particulière vi-encap:<numéro d'entreprise>, la comparaison se
fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying
vendor classes") pour l'entreprise dont le numéro est fourni en option.
Veuillez vous réferer à la RFC 3925 pour plus de détail.
Veuillez vous référer à la RFC 3925 pour plus de détails.
.TP
.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]]
Effectue une opération booléenne sur les labels. Si tous les labels
@@ -1277,7 +1288,7 @@ Si aucun tag:<label> n'est spécifié, alors tous les labels fournis par
set:<label> sont positionnés.
N'importe quel nombre de set: ou tag: peuvent être fournis, et l'ordre est sans
importance.
Les lignes tag-if sont executées dans l'ordre, ce qui fait que si un label dans
Les lignes tag-if sont exécutées dans l'ordre, ce qui fait que si un label dans
tag:<label> est un label positionné par une rêgle
.B tag-if,
la ligne qui positionne le label doit précéder celle qui le teste.
@@ -1317,17 +1328,17 @@ le cas de certains vieux clients BOOTP.
(IPv4 seulement) Spécifie les options BOOTP devant être retournées par le
serveur DHCP. Le nom de serveur ainsi que l'adresse sont optionnels : s'ils
ne sont pas fournis, le nom est laissé vide et l'adresse fournie est celle de
la machine sur laquelle s'exécute Dnsmasq. Si Dnsmasq founit un service TFTP (voir
la machine sur laquelle s'exécute Dnsmasq. Si Dnsmasq fournit un service TFTP (voir
.B --enable-tftp
), alors seul un nom de fichier est requis ici pour permettre un démarrage par
le réseau.
Si d'éventuels labels sont fournis, ils doivent coïncider avec
ceux du client pour que cet élement de configuration lui soit envoyé.
ceux du client pour que cet élément de configuration lui soit envoyé.
Une adresse de serveur TFTP peut être spécifiée à la place de l'adresse IP,
sous la forme d'un nom de domaine qui sera cherché dans le fichier /etc/hosts.
Ce nom peut être associé dans /etc/hosts avec plusieurs adresses IP, auquel cas
celles-ci seront utilisées tour à tour (algorithme round-robin).
Cela peut-être utiliser pour équilibrer la charge tftp sur plusieurs serveurs.
Cela peut être utilisé pour équilibrer la charge tftp sur plusieurs serveurs.
.TP
.B --dhcp-sequential-ip
Dnsmasq est conçu pour choisir l'adresse IP des clients DHCP en utilisant
@@ -1343,6 +1354,13 @@ Veuillez noter que dans ce mode séquentiel, les clients qui laissent expirer
leur bail ont beaucoup plus de chance de voir leur adresse IP changer, aussi
cette option ne devrait pas être utilisée dans un cas général.
.TP
.B --dhcp-ignore-clid
Dnsmasq lit l'option 'client identifier' (RFC 2131) envoyée par les clients
(si disponible) afin d'identifier les clients. Cela permet de distribuer la
même adresse IP à un client utilisant plusieurs interfaces. Activer cette option
désactive la lecture du 'client identifier', afin de toujours identifier un client
en utilisant l'adresse MAC.
.TP
.B --pxe-service=[tag:<label>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>|<nom de serveur>]
La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple
obtention d'une adresse IP, le téléchargement du fichier spécifié dans
@@ -1354,7 +1372,7 @@ Ceci spécifie l'option de démarrage qui apparaitra dans un menu de démarrage
PXE. <CSA> est le type du système client. Seuls des types de services valides
apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha,
Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI;
D'autres types peuvent-être spécifiés sous la forme d'une valeur entière. Le
D'autres types peuvent être spécifiés sous la forme d'une valeur entière. Le
paramètre après le texte correspondant à l'entrée dans le menu peut être un nom
de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au
client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur
@@ -1373,7 +1391,7 @@ démarrage n'est fournie (ou qu'une valeur de 0 est donnée pour le type de
service), alors l'entrée de menu provoque l'interruption du démarrage par
le réseau et la poursuite du démarrage sur un média local. L'adresse de serveur
peut être donnée sous la forme de nom de domaine qui est recherché dans
/etc/hosts. Ce nom peut-être associé à plusieurs adresses IP, qui dans ce cas
/etc/hosts. Ce nom peut être associé à plusieurs adresses IP, qui dans ce cas
sont utilisées à tour de rôle (en "round-robin").
.TP
.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>]
@@ -1432,7 +1450,7 @@ Utiliser cette option avec précaution, une adresse allouée à un client BOOTP
étant perpétuelle, et de fait n'est plus disponibles pour d'autres hôtes. Si
aucun argument n'est donné, alors cette option permet une allocation dynamique
dans tous les cas. Si des arguments sont spécifiés, alors l'allocation ne se
fait que lorsque tous les identifiants coïncident. Il est possible de répeter
fait que lorsque tous les identifiants coïncident. Il est possible de répéter
cette option avec plusieurs jeux d'arguments.
.TP
.B \-5, --no-ping
@@ -1557,7 +1575,7 @@ Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
sont ouverts sur /dev/null (sauf en mode déverminage).
Le script n'est pas lancé de manière concurrente : au plus une instance du
script est executée à la fois (dnsmasq attends qu'une instance de script se
script est exécutée à la fois (dnsmasq attend qu'une instance de script se
termine avant de lancer la suivante). Les changements dans la base des baux
nécessitant le lancement du script sont placé en attente dans une queue jusqu'à
terminaison d'une instance du script en cours. Si cette mise en queue fait que
@@ -1572,7 +1590,7 @@ le script sera invoqué avec une action "old" pour tous les baux existants.
Il existe deux autres actions pouvant apparaître comme argument au script :
"init" et "tftp". D'autres sont susceptibles d'être rajoutées dans le futur,
aussi les scripts devraient-être écrits de sorte à ignorer les actions
aussi les scripts devraient être écrits de sorte à ignorer les actions
inconnues. "init" est décrite ci-dessous dans
.B --leasefile-ro.
L'action "tftp" est invoquée lorsqu'un transfert de fichier TFTP s'est
@@ -1585,7 +1603,7 @@ Spécifie un script écrit en Lua, devant être exécuté lorsque des baux sont
créés, détruits ou modifiés. Pour utiliser cette option, dnsmasq doit être
compilé avec avec le support de Lua. L'interpréteur Lua est initialisé une
seule fois, lorsque dnsmasq démarre, ce qui fait que les variables globales
persistent entre les évênements liés aux baux. Le code Lua doit définir une
persistent entre les événements liés aux baux. Le code Lua doit définir une
fonction
.B lease
et peut fournir des fonctions
@@ -1634,7 +1652,7 @@ et
.B --dhcp-scriptuser
Spécifie l'utilisateur sous lequel le script shell lease-change ou le script
doivent être exécutés. La valeur par défaut correspond à l'utilisateur root
mais peut-être changée par le biais de cette option.
mais peut être changée par le biais de cette option.
.TP
.B \-9, --leasefile-ro
Supprimer complètement l'usage du fichier servant de base de donnée pour les
@@ -1646,8 +1664,8 @@ biais de l'option
être complètement gérée par le script sur un stockage externe. En addition aux
actions décrites dans
.B --dhcp-script,
le script de changement d'état de bail est appellé une fois, au lancement de
Dnsmasq, avec pour seul argument "init". Lorsqu'appellé de la sorte, le script
le script de changement d'état de bail est appelé une fois, au lancement de
Dnsmasq, avec pour seul argument "init". Lorsqu'appelé de la sorte, le script
doit fournir l'état de la base de baux, dans le format de fichier de baux de
Dnsmasq, sur sa sortie standard (stdout) et retourner un code de retour de 0.
Positionner cette option provoque également une invocation du script de
@@ -1655,11 +1673,14 @@ changement d'état de bail à chaque changement de l'identifiant de client, de
longueur de bail ou de date d'expiration.
.TP
.B --bridge-interface=<interface>,<alias>[,<alias>]
Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
comme si elles arrivaient de l'interface <interface>. Cette option est
nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
pas d'adresse IP. Chaque <alias> peut finir avec un simple '*' joker.
Traiter les requêtes DHCP (v4 et v6) et IPv6 Router Solicit arrivant
sur n'importe laquelle des interfaces <alias> comme si elles
arrivaient de l'interface <interface>. Cette option permet à dnsmasq
de fournir les service DHCP et RA sur les interfaces ethernet non
adressés et non pontés; par exemple sur un hôte de calcul d'OpenStack
où chaque telle interface est une interface TAP à une machine
virtuelle, ou lors de l'utilisation de pont ethernet "ancien mode" sur
plate-forme BSD. Chaque <alias> peut finir avec un simple '*' joker.
.TP
.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
@@ -1686,20 +1707,20 @@ positionné à la première valeur de la directive "search" du fichier
/etc/resolv.conf (ou équivalent).
La gamme d'adresses peut être de la forme
<adresse ip>,<adresse ip> ou <adresse ip>/<masque de réseau> voire une simple
<adresse ip>. Voir
<adresse IP>,<adresse IP> ou <adresse IP>/<masque de réseau> voire une simple
<adresse IP>. Voir
.B --dhcp-fqdn
qui peut changer le comportement de dnsmasq relatif aux domaines.
Si la gamme d'adresse est fournie sous la forme
<adresse ip>/<taille de réseau>, alors le drapeau "local" peut-être rajouté
qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et
<adresse IP>/<taille de réseau>, alors le drapeau "local" peut être rajouté
qui a pour effet d'ajouter --local-declarations aux requêtes DNS directes et
inverses. C-à-d
.B --domain=thekelleys.org.uk,192.168.0.0/24,local
est identique à
.B --domain=thekelleys.org.uk,192.168.0.0/24
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
La taille de réseau doit-être de 8, 16 ou 24 pour être valide.
La taille de réseau doit être de 8, 16 ou 24 pour être valide.
.TP
.B --dhcp-fqdn
Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients
@@ -1711,8 +1732,8 @@ ce nom est transféré au nouveau client. Si
est spécifié, ce comportement change : les noms non qualifiés ne sont plus
rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP
avec le même nom peuvent tous les deux garder le nom, pour peu que la partie
relative au domaine soit différente (c-à-d que les noms pleinements qualifiés
diffèrent). Pour d'assurer que tous les noms ont une partie domaine, il doit-y
relative au domaine soit différente (c-à-d que les noms pleinement qualifiés
diffèrent). Pour s'assurer que tous les noms ont une partie domaine, il doit y
avoir au moins un
.B --domain
sans gamme d'adresses de spécifié lorsque l'option
@@ -1729,7 +1750,7 @@ Windows de la mise à jour de serveurs Active Directory. Voir la RFC 4702 pour
plus de détails.
.TP
.B --enable-ra
Active la fonctionalité d'annonces routeurs IPv6 ("IPv6 Router Advertisement").
Active la fonctionnalité d'annonces routeurs IPv6 ("IPv6 Router Advertisement").
DHCPv6 ne gère pas la configuration complète du réseau de la même façon que
DHCPv4. La découverte de routeurs et la découverte (éventuelle) de préfixes pour
la création autonome d'adresse sont gérées par un protocole différent.
@@ -1741,7 +1762,7 @@ dhcp-range et, par défaut, fournir comme valeur de routeur et de DNS récursif
la valeur d'adresse link-local appropriée parmi celles de la machine sur
laquelle tourne dnsmasq.
Par défaut, les bits "managed address" sont positionnés, et le bit "use SLAAC"
("utiliser SLAAC") est réinitialisé. Cela peut-être changé pour des
("utiliser SLAAC") est réinitialisé. Cela peut être changé pour des
sous-réseaux donnés par le biais du mot clef de mode décris dans
.B --dhcp-range.
Les paramètres DNS du RFC6106 sont inclus dans les annonces. Par défaut,
@@ -1750,27 +1771,27 @@ dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
DNSSL.
.TP
.B --ra-param=<interface>,[high|low],[[<intervalle d'annonce routeur>],<durée de vie route>]
.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
Configure pour une interface donnée des valeurs pour les annonces routeurs
différentes des valeurs par défaut. La valeur par défaut du champ priorité
pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
pour le routeur peut être changée de "medium" (moyen) à "high" (haute) ou
"low" (basse). Par exemple :
.B --ra-param=eth0,high.
Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
.B --ra-param=eth0,high,0.
Un intervalle (en secondes) entre les annonces routeur peut être fourni par :
.B --ra-param=eth0,60.
La durée de vie de la route peut-être changée ou mise à zéro, auquel cas
La durée de vie de la route peut être changée ou mise à zéro, auquel cas
le routeur peut annoncer les préfixes mais pas de route :
.B --ra-parm=eth0,0,0
.B --ra-param=eth0,0,0
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
Ces trois paramètres peuvent-être configurés en une fois :
.B --ra-param=low,60,1200
Ces quatre paramètres peuvent être configurés en une fois :
.B --ra-param=eth0,mtu:1280,low,60,1200
La valeur pour l'interface peut inclure un caractère joker.
.TP
.B --enable-tftp[=<interface>[,<interface>]]
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
un accès en lecture est possible; les extensions tsize et blksize sont supportées
(tsize est seulement supporté en mode octet). Sans argument optionel, le service
(tsize est seulement supportée en mode octet). Sans argument optionnel, le service
TFTP est fourni sur les mêmes interfaces que le service DHCP. Si une liste
d'interfaces est fournie, cela définit les interfaces sur lesquelles le
service TFTP sera activé.
@@ -1841,9 +1862,9 @@ Un serveur TFTP écoute sur le port prédéfini 69 ("well-known port") pour
l'initiation de la connexion, mais utilise également un port dynamiquement
alloué pour chaque connexion. Normalement, ces ports sont alloués par
le système d'exploitation, mais cette option permet de spécifier une gamme
de ports à utiliser pour les transferts TFTP. Cela peut-être utile si
de ports à utiliser pour les transferts TFTP. Cela peut être utile si
TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur
de début pour la plage de port ne peut-être inférieure à 1025 sauf si
de début pour la plage de port ne peut être inférieure à 1025 sauf si
dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de
connexions TFTP concurrentes est limitée par la taille de la gamme de
ports ainsi spécifiée.
@@ -1853,8 +1874,8 @@ Un serveur TFTP écoute sur un numéro de port bien connu (69) pour l'initiation
de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces
numéros de ports sont en principe alloués par le système d'exploitation, mais
cette option permet de spécifier une gamme de ports à utiliser pour les
transferts TFTP. Cela peut-être utile lorsque ceux-ci doivent traverser un
dispositif garde-barrière ("firewall"). Le début de la plage ne peut-être
transferts TFTP. Cela peut être utile lorsque ceux-ci doivent traverser un
dispositif garde-barrière ("firewall"). Le début de la plage ne peut être
inférieur à 1024 à moins que Dnsmasq ne fonctionne en temps que
super-utilisateur ("root"). Le nombre maximal de connexions TFTP concurrentes
est limitée par la taille de la plage de ports ainsi définie.
@@ -1889,7 +1910,7 @@ par "--". Les lignes commençant par # sont des commentaires et sont ignorées.
Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du
fichier de configuration prends le pas sur celle fournie en ligne de commande.
Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et
"#" ne soit interprêtés, et il est possible d'utiliser les séquences
"#" ne soient interprétés, et il est possible d'utiliser les séquences
d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent
respectivement à la barre oblique descendante ("anti-slash"), guillemets doubles,
tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et
@@ -1934,8 +1955,8 @@ traces dans un fichier (voir
.B --log-facility
), alors
.B Dnsmasq
ferme et re-rouvre le fichier de traces. Il faut noter que pendant cette
opération Dnsmasq ne s'exécute pas en temps que "root". Lorsqu'il créé un
ferme et rouvre le fichier de traces. Il faut noter que pendant cette
opération Dnsmasq ne s'exécute pas en tant que "root". Lorsqu'il créé un
fichier de traces pour la première fois, Dnsmasq change le propriétaire du
fichier afin de le faire appartenir à l'utilisateur non "root" sous lequel
Dnsmasq s'exécute. Le logiciel de rotation de fichiers de trace logrotate doit
@@ -1977,7 +1998,7 @@ qu'une connexion PPP ne soit établie. Dans ce cas, Dnsmasq vérifie régulière
pour voir si un fichier
.I /etc/resolv.conf
est créé. Dnsmasq peut être configuré pour lire plus d'un fichier resolv.conf.
Cela est utile sur un ordinateur portable où PPP et DHCP peuvent-être utilisés :
Cela est utile sur un ordinateur portable où PPP et DHCP peuvent être utilisés :
Dnsmasq peut alors être configuré pour lire à la fois
.I /etc/ppp/resolv.conf
et
@@ -2001,7 +2022,7 @@ ou alors en mettant leurs adresses dans un autre fichier, par exemple
.I /etc/resolv.dnsmasq
et en lançant Dnsmasq avec l'option
.B \-r /etc/resolv.dnsmasq.
Cette deuxième technique permet la mise-à-jour dynamique des addresses de
Cette deuxième technique permet la mise-à-jour dynamique des adresses de
serveurs DNS amont par le biais de PPP ou DHCP.
.PP
Les adresses dans /etc/hosts prennent le dessus sur celles fournies par le
@@ -2061,10 +2082,10 @@ et pour affecter l'option envoyée, sur la base de la plage sélectionnée.
Ce système a évolué d'un système plus ancien et aux possibilités plus limitées,
et pour des raisons de compatibilité "net:" peut être utilisé à la place de
"tag:" et "set:" peut-être omis (à l'exception de
"tag:" et "set:" peut être omis (à l'exception de
.B dhcp-host,
où "net:" peut-être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
peut-être utilisé à la place de '!' pour indiquer la négation.
où "net:" peut être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
peut être utilisé à la place de '!' pour indiquer la négation.
.PP
Le serveur DHCP intégré dans Dnsmasq fonctionne également en temps que serveur
BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies,
@@ -2091,7 +2112,7 @@ scénarios de complexité croissante. Le pré-requis pour chacun de ces scénari
est l'existence d'une adresse IP globalement disponible, d'un enregistrement de
type A ou AAAA pointant vers cette adresse, ainsi que d'un serveur DNS externe
capable d'effectuer la délégation de la zone en question. Pour la première
partie de ces explications, nous allons appeller serveur.exemple.com
partie de ces explications, nous allons appeler serveur.exemple.com
l'enregistrement A (ou AAAA) de l'adresse globalement accessible, et
notre.zone.com la zone pour laquelle dnsmasq fait autorité.
@@ -2132,11 +2153,11 @@ notre.zone.com NS our.zone.com
.fi
L'enregistrement A pour notre.zone.com est dorénavant un enregistrement "colle"
qui résoud le problème de poule et d'oeuf consistant à trouver l'adresse IP
qui résout le problème de poule et d'oeuf consistant à trouver l'adresse IP
du serveur de nom pour notre.zone.com lorsque l'enregistrement se trouve dans
la zone en question. Il s'agit du seul rôle de cet enregistrement : comme dnsmasq
fait désormais autorité pour notre.zone.com, il doit également fournir cet
enregistrement. Si l'adresse externe est statique, cela peut-être réalisé par
enregistrement. Si l'adresse externe est statique, cela peut être réalisé par
le biais d'une entrée dans
.B /etc/hosts
ou via un
@@ -2188,7 +2209,7 @@ spécifiques, vous pouvez le faire via :
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
et ip6.arpa associés aux sous-réseaux définis dans la déclaration de zone
auth-zone, ce qui fait que les requêtes DNS inversées (de l'adresse vers
le nom) peuvent-simplement être configurées avec un enregistrement NS
le nom) peuvent simplement être configurées avec un enregistrement NS
adéquat. Par exemple, comme nous définissons plus haut les adresses
1.2.3.0/24 :
.nf
@@ -2237,7 +2258,7 @@ celui fourni par
.B --domain.
Si l'option
.B --dhcp-fqdn
est fournie, alors les noms pleinemenet qualifiés associés aux baux DHCP
est fournie, alors les noms pleinement qualifiés associés aux baux DHCP
sont utilisés, dès lors qu'ils correspondent au nom de domaine associé
à la zone.
@@ -2276,7 +2297,7 @@ Dnsmasq est capable de gérer le DNS et DHCP pour au moins un millier de clients
Pour cela, la durée des bail ne doit pas être très courte (moins d'une heure).
La valeur de
.B --dns-forward-max
peut-être augmentée : commencer par la rendre égale au nombre de clients et
peut être augmentée : commencer par la rendre égale au nombre de clients et
l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends
également de la performance des serveurs amonts. La taille du cache DNS peut-
être augmentée : la limite en dur est de 10000 entrées et la valeur par défaut
@@ -2300,7 +2321,7 @@ Il est possible d'utiliser Dnsmasq pour bloquer la publicité sur la toile
en associant des serveurs de publicité bien connus à l'adresse 127.0.0.1 ou
0.0.0.0 par le biais du fichier
.B /etc/hosts
ou d'un fichier d'hôte additionnel. Cette liste peut-être très longue, Dnsmasq
ou d'un fichier d'hôte additionnel. Cette liste peut être très longue, Dnsmasq
ayant été testé avec succès avec un million de noms. Cette taille de fichier
nécessite un processeur à 1 Ghz et environ 60 Mo de RAM.

2870
man/sv/dnsmasq.8 Normal file

File diff suppressed because it is too large Load Diff

2401
po/de.po

File diff suppressed because it is too large Load Diff

3055
po/es.po

File diff suppressed because it is too large Load Diff

2958
po/fi.po

File diff suppressed because it is too large Load Diff

2097
po/fr.po

File diff suppressed because it is too large Load Diff

2146
po/id.po

File diff suppressed because it is too large Load Diff

2958
po/it.po

File diff suppressed because it is too large Load Diff

2952
po/ka.po Normal file

File diff suppressed because it is too large Load Diff

3031
po/no.po

File diff suppressed because it is too large Load Diff

3074
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2053
po/ro.po

File diff suppressed because it is too large Load Diff

2979
po/sv.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -78,7 +78,7 @@ by modifying MODIFY_RESOLV_CONF_DYNAMICALLY="no" in <TT>/etc/sysconfig/network/c
<h3>Automatic DNS server configuration with DHCP.</h3>
You need to get your DHCP client to write the addresse(s) of the DNS
You need to get your DHCP client to write the address(es) of the DNS
servers to a file other than <TT>/etc/resolv.conf</TT>. For dhcpcd, the
<TT>dhcpcd.exe</TT> script gets run with the addresses of the nameserver(s) in
the shell variable <TT>$DNS</TT>. The following bit of shell script
@@ -86,8 +86,8 @@ uses that to write a file suitable for dnsmasq.
<PRE>
echo -n >|/etc/dhcpc/resolv.conf
dnsservs=${DNS//,/ }
for serv in $dnsservs; do
dnsservers=${DNS//,/ }
for serv in $dnsservers; do
echo "nameserver $serv" >>/etc/dhcpc/resolv.conf
done
@@ -125,7 +125,7 @@ address of its ethernet card. For the former to work, a machine needs to know it
requests a DHCP lease. For dhcpcd, the -h option specifies this. The
names may be anything as far as DHCP is concerned, but dnsmasq adds
some limitations. By default the names must no have a domain part, ie
they must just be a alphanumeric name, without any dots. This is a
they must just be alphanumeric names, without any dots. This is a
security feature to stop a machine on your network telling DHCP that
its name is "www.microsoft.com" and thereby grabbing traffic which
shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
@@ -186,7 +186,7 @@ more than one nameserver just include as many
<H2>Local domains.</H2>
Sometimes people have local domains which they do not want forwarded
to upstream servers. This is accomodated by using server options
to upstream servers. This is accommodated by using server options
without the server IP address. To make things clearer <TT>local</TT>
is a synonym for <TT>server</TT>. For example the option
<TT>local=/localnet/</TT> ensures that any domain name query which ends in
@@ -229,3 +229,5 @@ contents of the cache to the syslog.
<P>For a complete listing of options please take a look at the manpage
dnsmasq(8).
</BODY>
</HTML>

240
src/arp.c Normal file
View File

@@ -0,0 +1,240 @@
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
/* Time between forced re-loads from kernel. */
#define INTERVAL 90
#define ARP_MARK 0
#define ARP_FOUND 1 /* Confirmed */
#define ARP_NEW 2 /* Newly created */
#define ARP_EMPTY 3 /* No MAC addr */
struct arp_record {
unsigned short hwlen, status;
int family;
unsigned char hwaddr[DHCP_CHADDR_MAX];
union all_addr addr;
struct arp_record *next;
};
static struct arp_record *arps = NULL, *old = NULL, *freelist = NULL;
static time_t last = 0;
static int filter_mac(int family, void *addrp, char *mac, size_t maclen, void *parmv)
{
struct arp_record *arp;
(void)parmv;
if (maclen > DHCP_CHADDR_MAX)
return 1;
/* Look for existing entry */
for (arp = arps; arp; arp = arp->next)
{
if (family != arp->family || arp->status == ARP_NEW)
continue;
if (family == AF_INET)
{
if (arp->addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
continue;
}
else
{
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr6, (struct in6_addr *)addrp))
continue;
}
if (arp->status == ARP_EMPTY)
{
/* existing address, was negative. */
arp->status = ARP_NEW;
arp->hwlen = maclen;
memcpy(arp->hwaddr, mac, maclen);
}
else if (arp->hwlen == maclen && memcmp(arp->hwaddr, mac, maclen) == 0)
/* Existing entry matches - confirm. */
arp->status = ARP_FOUND;
else
continue;
break;
}
if (!arp)
{
/* New entry */
if (freelist)
{
arp = freelist;
freelist = freelist->next;
}
else if (!(arp = whine_malloc(sizeof(struct arp_record))))
return 1;
arp->next = arps;
arps = arp;
arp->status = ARP_NEW;
arp->hwlen = maclen;
arp->family = family;
memcpy(arp->hwaddr, mac, maclen);
if (family == AF_INET)
arp->addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
else
memcpy(&arp->addr.addr6, addrp, IN6ADDRSZ);
}
return 1;
}
/* If in lazy mode, we cache absence of ARP entries. */
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
{
struct arp_record *arp, *tmp, **up;
int updated = 0;
again:
/* If the database is less then INTERVAL old, look in there.
If we're a child process, we always rely on the existing cache we
inherited from the parent, since we don't have a netlink socket.
*/
if (difftime(now, last) < INTERVAL || daemon->pipe_to_parent != -1)
{
/* addr == NULL -> just make cache up-to-date */
if (!addr)
return 0;
for (arp = arps; arp; arp = arp->next)
{
if (addr->sa.sa_family != arp->family)
continue;
if (arp->family == AF_INET &&
arp->addr.addr4.s_addr != addr->in.sin_addr.s_addr)
continue;
if (arp->family == AF_INET6 &&
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr6, &addr->in6.sin6_addr))
continue;
/* Only accept positive entries unless in lazy mode. */
if (arp->status != ARP_EMPTY || lazy || updated)
{
if (mac && arp->hwlen != 0)
memcpy(mac, arp->hwaddr, arp->hwlen);
return arp->hwlen;
}
}
}
/* Not in cache in child, no go. */
if (daemon->pipe_to_parent != -1)
return 0;
/* Not found, try the kernel */
if (!updated)
{
updated = 1;
last = now;
/* Mark all non-negative entries */
for (arp = arps; arp; arp = arp->next)
if (arp->status != ARP_EMPTY)
arp->status = ARP_MARK;
iface_enumerate(AF_UNSPEC, NULL, (callback_t){.af_unspec=filter_mac});
/* Remove all unconfirmed entries to old list. */
for (arp = arps, up = &arps; arp; arp = tmp)
{
tmp = arp->next;
if (arp->status == ARP_MARK)
{
*up = arp->next;
arp->next = old;
old = arp;
}
else
up = &arp->next;
}
goto again;
}
/* record failure, so we don't consult the kernel each time
we're asked for this address */
if (freelist)
{
arp = freelist;
freelist = freelist->next;
}
else
arp = whine_malloc(sizeof(struct arp_record));
if (arp)
{
arp->next = arps;
arps = arp;
arp->status = ARP_EMPTY;
arp->family = addr->sa.sa_family;
arp->hwlen = 0;
if (addr->sa.sa_family == AF_INET)
arp->addr.addr4.s_addr = addr->in.sin_addr.s_addr;
else
memcpy(&arp->addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
}
return 0;
}
int do_arp_script_run(void)
{
struct arp_record *arp;
/* Notify any which went, then move to free list */
if (old)
{
#ifdef HAVE_SCRIPT
if (option_bool(OPT_SCRIPT_ARP))
queue_arp(ACTION_ARP_DEL, old->hwaddr, old->hwlen, old->family, &old->addr);
#endif
arp = old;
old = arp->next;
arp->next = freelist;
freelist = arp;
return 1;
}
for (arp = arps; arp; arp = arp->next)
if (arp->status == ARP_NEW)
{
#ifdef HAVE_SCRIPT
if (option_bool(OPT_SCRIPT_ARP))
queue_arp(ACTION_ARP, arp->hwaddr, arp->hwlen, arp->family, &arp->addr);
#endif
arp->status = ARP_FOUND;
return 1;
}
return 0;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,36 +18,51 @@
#ifdef HAVE_AUTH
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
static struct addrlist *find_addrlist(struct addrlist *list, int flag, union all_addr *addr_u)
{
struct addrlist *subnet;
for (subnet = zone->subnet; subnet; subnet = subnet->next)
{
if (!(subnet->flags & ADDRLIST_IPV6))
{
struct in_addr netmask, addr = addr_u->addr.addr4;
if (!(flag & F_IPV4))
continue;
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen));
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
return subnet;
}
#ifdef HAVE_IPV6
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
return subnet;
#endif
}
do {
if (!(list->flags & ADDRLIST_IPV6))
{
struct in_addr netmask, addr = addr_u->addr4;
if (!(flag & F_IPV4))
continue;
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
if (is_same_net(addr, list->addr.addr4, netmask))
return list;
}
else if (is_same_net6(&(addr_u->addr6), &list->addr.addr6, list->prefixlen))
return list;
} while ((list = list->next));
return NULL;
}
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, union all_addr *addr_u)
{
/* No zones specified, no filter */
if (!zone->subnet)
return NULL;
return find_addrlist(zone->subnet, flag, addr_u);
}
static struct addrlist *find_exclude(struct auth_zone *zone, int flag, union all_addr *addr_u)
{
if (!zone->exclude)
return NULL;
return find_addrlist(zone->exclude, flag, addr_u);
}
static int filter_zone(struct auth_zone *zone, int flag, union all_addr *addr_u)
{
if (find_exclude(zone, flag, addr_u))
return 0;
/* No subnets specified, no filter */
if (!zone->subnet)
return 1;
@@ -81,15 +96,16 @@ int in_zone(struct auth_zone *zone, char *name, char **cut)
}
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query)
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now,
union mysockaddr *peer_addr, int local_query)
{
char *name = daemon->namebuff;
unsigned char *p, *ansp;
int qtype, qclass;
int qtype, qclass, rc;
int nameoffset, axfroffset = 0;
int q, anscount = 0, authcount = 0;
int anscount = 0, authcount = 0;
struct crec *crecp;
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0, out_of_zone = 0, notimp = 0;
struct auth_zone *zone = NULL;
struct addrlist *subnet = NULL;
char *cut;
@@ -97,29 +113,33 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
struct txt_record *txt;
struct interface_name *intr;
struct naptr *na;
struct all_addr addr;
struct cname *a;
union all_addr addr;
struct cname *a, *candidate;
unsigned int wclen;
unsigned int log_flags = local_query ? 0 : F_NOERR;
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
if (ntohs(header->qdcount) != 1)
return 0;
/* determine end of question section (we put answers there) */
if (!(ansp = skip_questions(header, qlen)))
return 0; /* bad packet */
/* now process each question, answers go in RRs after the question */
p = (unsigned char *)(header+1);
for (q = ntohs(header->qdcount); q != 0; q--)
if (OPCODE(header) != QUERY)
notimp = 1;
else
{
unsigned short flag = 0;
unsigned int flag = 0;
int found = 0;
int cname_wildcard = 0;
/* save pointer to name for copying into answers */
nameoffset = p - (unsigned char *)header;
/* now extract name as .-concatenated string into name */
if (!extract_name(header, qlen, &p, name, 1, 4))
if (!extract_name(header, qlen, &p, name, EXTR_NAME_EXTRACT, 4))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -128,27 +148,32 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (qclass != C_IN)
{
auth = 0;
continue;
out_of_zone = 1;
goto done;
}
if (qtype == T_PTR)
if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
(flag = in_arpa_name_2_addr(name, &addr)) &&
!local_query)
{
if (!(flag = in_arpa_name_2_addr(name, &addr)))
continue;
if (!local_query)
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = find_subnet(zone, flag, &addr)))
break;
if (!zone)
{
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = find_subnet(zone, flag, &addr)))
break;
if (!zone)
{
auth = 0;
continue;
}
out_of_zone = 1;
auth = 0;
goto done;
}
else if (qtype == T_SOA)
soa = 1, found = 1;
else if (qtype == T_NS)
ns = 1, found = 1;
}
if (qtype == T_PTR && flag)
{
intr = NULL;
if (flag == F_IPV4)
@@ -157,7 +182,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
struct addrlist *addrlist;
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr4.s_addr == addrlist->addr.addr4.s_addr)
break;
if (addrlist)
@@ -166,14 +191,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
#ifdef HAVE_IPV6
else if (flag == F_IPV6)
for (intr = daemon->int_names; intr; intr = intr->next)
{
struct addrlist *addrlist;
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr6, &addrlist->addr.addr6))
break;
if (addrlist)
@@ -182,14 +206,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
intr = intr->next;
}
#endif
if (intr)
{
if (in_zone(zone, intr->name, NULL))
if (local_query || in_zone(zone, intr->name, NULL))
{
found = 1;
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
log_query(log_flags | flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", intr->name))
@@ -208,18 +231,21 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
*p = 0; /* must be bare name */
/* add external domain */
strcat(name, ".");
strcat(name, zone->domain);
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
if (zone)
{
strcat(name, ".");
strcat(name, zone->domain);
}
log_query(log_flags | flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid), 0);
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", name))
anscount++;
}
else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
{
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
log_query(log_flags | (crecp->flags & ~F_FORWARD), name, &addr, record_source(crecp->uid), 0);
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
@@ -231,34 +257,52 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
if (!found && is_rev_synth(flag, &addr, name) && (local_query || in_zone(zone, name, NULL)))
{
log_query(log_flags | F_CONFIG | F_REVERSE | flag, name, &addr, NULL, 0);
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", name))
anscount++;
}
if (found)
nxdomain = 0;
else
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
log_query(log_flags | flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL, 0);
continue;
goto done;
}
cname_restart:
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (in_zone(zone, name, &cut))
break;
if (!zone)
if (found)
/* NS and SOA .arpa requests have set found above. */
cut = NULL;
else
{
auth = 0;
continue;
for (zone = daemon->auth_zones; zone; zone = zone->next)
if (in_zone(zone, name, &cut))
break;
if (!zone)
{
out_of_zone = 1;
auth = 0;
goto done;
}
}
for (rec = daemon->mxnames; rec; rec = rec->next)
if (!rec->issrv && hostname_isequal(name, rec->name))
if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
{
nxdomain = 0;
if (qtype == T_MX)
if (rc == 2 && qtype == T_MX)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
log_query(log_flags | F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
anscount++;
@@ -266,14 +310,14 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
if (rec->issrv && hostname_isequal(name, rec->name))
if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
{
nxdomain = 0;
if (qtype == T_SRV)
if (rc == 2 && qtype == T_SRV)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
log_query(log_flags | F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, T_SRV, C_IN, "sssd",
rec->priority, rec->weight, rec->srvport, rec->target))
@@ -301,13 +345,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (txt = daemon->rr; txt; txt = txt->next)
if (hostname_isequal(name, txt->name))
if ((rc = hostname_issubdomain(name, txt->name)))
{
nxdomain = 0;
if (txt->class == qtype)
if (rc == 2 && txt->class == qtype)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
log_query(log_flags | F_CONFIG | F_RRNAME, name, NULL, NULL, txt->class);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
anscount++;
@@ -315,13 +359,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (txt = daemon->txt; txt; txt = txt->next)
if (txt->class == C_IN && hostname_isequal(name, txt->name))
if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
{
nxdomain = 0;
if (qtype == T_TXT)
if (rc == 2 && qtype == T_TXT)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
log_query(log_flags | F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
anscount++;
@@ -329,13 +373,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (na = daemon->naptr; na; na = na->next)
if (hostname_isequal(name, na->name))
if ((rc = hostname_issubdomain(name, na->name)))
{
nxdomain = 0;
if (qtype == T_NAPTR)
if (rc == 2 && qtype == T_NAPTR)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
log_query(log_flags | F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, T_NAPTR, C_IN, "sszzzd",
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
@@ -346,55 +390,43 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (qtype == T_A)
flag = F_IPV4;
#ifdef HAVE_IPV6
if (qtype == T_AAAA)
flag = F_IPV6;
#endif
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
if ((rc = hostname_issubdomain(name, intr->name)))
{
struct addrlist *addrlist;
nxdomain = 0;
if (flag)
if (rc == 2 && flag)
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
(local_query || filter_zone(zone, flag, &addrlist->addr)))
{
#ifdef HAVE_IPV6
if (addrlist->flags & ADDRLIST_REVONLY)
continue;
#endif
found = 1;
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
log_query(log_flags | F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &addrlist->addr))
anscount++;
}
}
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(name, a->alias) )
{
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
strcpy(name, a->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
goto cname_restart;
}
if (!found && is_name_synthetic(flag, name, &addr) )
{
nxdomain = 0;
log_query(log_flags | F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
anscount++;
}
if (!cut)
{
nxdomain = 0;
@@ -402,8 +434,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (qtype == T_SOA)
{
auth = soa = 1; /* inhibits auth section */
found = 1;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
log_query(log_flags | F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>", 0);
}
else if (qtype == T_AXFR)
{
@@ -411,24 +442,24 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (peer_addr->sa.sa_family == AF_INET)
peer_addr->in.sin_port = 0;
#ifdef HAVE_IPV6
else
peer_addr->in6.sin6_port = 0;
#endif
{
peer_addr->in6.sin6_port = 0;
peer_addr->in6.sin6_scope_id = 0;
}
for (peers = daemon->auth_peers; peers; peers = peers->next)
if (sockaddr_isequal(peer_addr, &peers->addr))
break;
/* Refuse all AXFR unless --auth-sec-servers is set */
if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
/* Refuse all AXFR unless --auth-sec-servers or auth-peers is set */
if ((!daemon->secondary_forward_server && !daemon->auth_peers) ||
(daemon->auth_peers && !peers))
{
if (peer_addr->sa.sa_family == AF_INET)
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
#ifdef HAVE_IPV6
else
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
#endif
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
return 0;
@@ -438,16 +469,14 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
soa = 1; /* inhibits auth section */
ns = 1; /* ensure we include NS records! */
axfr = 1;
found = 1;
axfroffset = nameoffset;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
log_query(log_flags | F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>", 0);
}
else if (qtype == T_NS)
{
auth = 1;
ns = 1; /* inhibits auth section */
found = 1;
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
log_query(log_flags | F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>", 0);
}
}
@@ -462,12 +491,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
nxdomain = 0;
if ((crecp->flags & flag) &&
(local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
(local_query || filter_zone(zone, flag, &(crecp->addr))))
{
*cut = '.'; /* restore domain part */
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
log_query(log_flags | crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
*cut = 0; /* remove domain part */
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &crecp->addr))
@@ -485,10 +513,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
do
{
nxdomain = 0;
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
{
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
found = 1;
log_query(log_flags | (crecp->flags & ~F_REVERSE), name, &crecp->addr, record_source(crecp->uid), 0);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
qtype == T_A ? "4" : "6", &crecp->addr))
@@ -497,10 +524,68 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
}
if (!found)
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
/* Only supply CNAME if no record for any type is known. */
if (nxdomain)
{
/* Check for possible wildcard match against *.domain
return length of match, to get longest.
Note that if return length of wildcard section, so
we match b.simon to _both_ *.simon and b.simon
but return a longer (better) match to b.simon.
*/
for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
if (a->alias[0] == '*')
{
char *test = name;
while ((test = strchr(test+1, '.')))
{
if (hostname_isequal(test, &(a->alias[1])))
{
if (strlen(test) > wclen && !cname_wildcard)
{
wclen = strlen(test);
candidate = a;
cname_wildcard = 1;
}
break;
}
}
}
else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
{
/* Simple case, no wildcard */
wclen = strlen(a->alias);
candidate = a;
}
if (candidate)
{
log_query(log_flags | F_CONFIG | F_CNAME, name, NULL, NULL, 0);
strcpy(name, candidate->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
goto cname_restart;
}
else if (cache_find_non_terminal(name, now))
nxdomain = 0;
log_query(log_flags | flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL, 0);
}
}
done:
/* Add auth section */
if (auth && zone)
@@ -518,19 +603,18 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (!(subnet->flags & ADDRLIST_IPV6))
{
in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;
in_addr_t a = ntohl(subnet->addr.addr4.s_addr) >> 8;
char *p = name;
if (subnet->prefixlen >= 24)
p += sprintf(p, "%d.", a & 0xff);
p += sprintf(p, "%u.", a & 0xff);
a = a >> 8;
if (subnet->prefixlen >= 16 )
p += sprintf(p, "%d.", a & 0xff);
p += sprintf(p, "%u.", a & 0xff);
a = a >> 8;
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
sprintf(p, "%u.in-addr.arpa", a & 0xff);
}
#ifdef HAVE_IPV6
else
{
char *p = name;
@@ -538,13 +622,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
{
int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];
int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
}
p += sprintf(p, "ip6.arpa");
sprintf(p, "ip6.arpa");
}
#endif
}
/* handle NS and SOA in auth section or for explicit queries */
@@ -568,16 +651,20 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
struct name_list *secondary;
newoffset = ansp - (unsigned char *)header;
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
/* Only include the machine running dnsmasq if it's acting as an auth server */
if (daemon->authinterface)
{
if (offset == 0)
offset = newoffset;
if (ns)
anscount++;
else
authcount++;
newoffset = ansp - (unsigned char *)header;
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
{
if (offset == 0)
offset = newoffset;
if (ns)
anscount++;
else
authcount++;
}
}
if (!subnet)
@@ -681,14 +768,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
anscount++;
#ifdef HAVE_IPV6
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if ((addrlist->flags & ADDRLIST_IPV6) &&
(local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
anscount++;
#endif
/* restore config data */
if (cut)
@@ -725,38 +810,26 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
char *cache_name = cache_get_name(crecp);
if (!strchr(cache_name, '.') &&
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
{
qtype = T_A;
#ifdef HAVE_IPV6
if (crecp->flags & F_IPV6)
qtype = T_AAAA;
#endif
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
(crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
anscount++;
}
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr))) &&
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN,
(crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
anscount++;
}
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
{
strcpy(name, cache_get_name(crecp));
if (in_zone(zone, name, &cut) &&
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr))))
{
qtype = T_A;
#ifdef HAVE_IPV6
if (crecp->flags & F_IPV6)
qtype = T_AAAA;
#endif
if (cut)
*cut = 0;
if (cut)
*cut = 0;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN,
(crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
anscount++;
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN,
(crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
anscount++;
}
}
}
@@ -790,25 +863,53 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
header->hb4 &= ~HB4_RA;
}
/* authoritive */
/* data is never DNSSEC signed. */
header->hb4 &= ~HB4_AD;
/* authoritative */
if (auth)
header->hb3 |= HB3_AA;
/* truncation */
if (trunc)
header->hb3 |= HB3_TC;
{
header->hb3 |= HB3_TC;
if (!(ansp = skip_questions(header, qlen)))
return 0; /* bad packet */
anscount = authcount = 0;
log_query(log_flags | F_AUTH, "reply", NULL, "truncated", 0);
}
if ((auth || local_query) && nxdomain)
SET_RCODE(header, NXDOMAIN);
else
SET_RCODE(header, NOERROR); /* no error */
header->ancount = htons(anscount);
header->nscount = htons(authcount);
header->arcount = htons(0);
if ((!local_query && out_of_zone) || notimp)
{
if (out_of_zone)
{
addr.log.rcode = REFUSED;
addr.log.ede = EDE_NOT_AUTH;
}
else
{
addr.log.rcode = NOTIMP;
addr.log.ede = EDE_UNSET;
}
SET_RCODE(header, addr.log.rcode);
header->ancount = htons(0);
header->nscount = htons(0);
log_query(log_flags | F_UPSTREAM | F_RCODE, "error", &addr, NULL, 0);
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
}
return ansp - (unsigned char *)header;
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,16 +16,14 @@
#include "dnsmasq.h"
#ifdef HAVE_DNSSEC
static struct blockdata *keyblock_free;
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
static void blockdata_expand(int n)
static void add_blocks(int n)
{
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
if (n > 0 && new)
if (new)
{
int i;
@@ -49,57 +47,133 @@ void blockdata_init(void)
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
if (option_bool(OPT_DNSSEC_VALID))
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
add_blocks(daemon->cachesize);
}
void blockdata_report(void)
{
if (option_bool(OPT_DNSSEC_VALID))
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
blockdata_count * sizeof(struct blockdata),
blockdata_hwm * sizeof(struct blockdata),
blockdata_alloced * sizeof(struct blockdata));
my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"),
blockdata_count * sizeof(struct blockdata),
blockdata_hwm * sizeof(struct blockdata),
blockdata_alloced * sizeof(struct blockdata));
}
struct blockdata *blockdata_alloc(char *data, size_t len)
static struct blockdata *new_block(void)
{
struct blockdata *block;
if (!keyblock_free)
add_blocks(50);
if (keyblock_free)
{
block = keyblock_free;
keyblock_free = block->next;
blockdata_count++;
if (blockdata_hwm < blockdata_count)
blockdata_hwm = blockdata_count;
block->next = NULL;
return block;
}
return NULL;
}
static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
{
struct blockdata *block, *ret = NULL;
struct blockdata **prev = &ret;
size_t blen;
while (len > 0)
do
{
if (!keyblock_free)
blockdata_expand(50);
if (keyblock_free)
{
block = keyblock_free;
keyblock_free = block->next;
blockdata_count++;
}
else
if (!(block = new_block()))
{
/* failed to alloc, free partial chain */
blockdata_free(ret);
return NULL;
}
if (blockdata_hwm < blockdata_count)
blockdata_hwm = blockdata_count;
if ((blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len) > 0)
{
if (data)
{
memcpy(block->key, data, blen);
data += blen;
}
else if (!read_write(fd, block->key, blen, RW_READ))
{
/* failed read free partial chain */
blockdata_free(ret);
return NULL;
}
}
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
memcpy(block->key, data, blen);
data += blen;
len -= blen;
*prev = block;
prev = &block->next;
block->next = NULL;
}
} while (len != 0);
return ret;
}
struct blockdata *blockdata_alloc(char *data, size_t len)
{
return blockdata_alloc_real(0, data, len);
}
/* Add data to the end of the block.
newlen is length of new data, NOT total new length.
Use blockdata_alloc(NULL, 0) to make empty block to add to. */
int blockdata_expand(struct blockdata *block, size_t oldlen, char *data, size_t newlen)
{
struct blockdata *b;
/* find size of current final block */
for (b = block; oldlen > KEYBLOCK_LEN && b; b = b->next, oldlen -= KEYBLOCK_LEN);
/* chain to short for length, something is broken */
if (oldlen > KEYBLOCK_LEN)
{
blockdata_free(block);
return 0;
}
while (1)
{
struct blockdata *new;
size_t blocksize = KEYBLOCK_LEN - oldlen;
size_t size = (newlen <= blocksize) ? newlen : blocksize;
if (size != 0)
{
memcpy(&b->key[oldlen], data, size);
data += size;
newlen -= size;
}
/* full blocks from now on. */
oldlen = 0;
if (newlen == 0)
break;
if ((new = new_block()))
{
b->next = new;
b = new;
}
else
{
/* failed to alloc, free partial chain */
blockdata_free(block);
return 0;
}
}
return 1;
}
void blockdata_free(struct blockdata *blocks)
{
struct blockdata *tmp;
@@ -119,7 +193,7 @@ void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
{
size_t blen;
struct blockdata *b;
void *new, *d;
uint8_t *new, *d;
static unsigned int buff_len = 0;
static unsigned char *buff = NULL;
@@ -147,5 +221,19 @@ void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
return data;
}
#endif
void blockdata_write(struct blockdata *block, size_t len, int fd)
{
for (; len > 0 && block; block = block->next)
{
size_t blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
read_write(fd, block->key, blen, RW_WRITE);
len -= blen;
}
}
struct blockdata *blockdata_read(int fd, size_t len)
{
return blockdata_alloc_real(fd, NULL, len);
}

214
src/bpf.c
View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +20,9 @@
#include <ifaddrs.h>
#include <sys/param.h>
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
#include <sys/sysctl.h>
#endif
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
@@ -29,9 +31,7 @@
# include <net/if_var.h>
#endif
#include <netinet/in_var.h>
#ifdef HAVE_IPV6
# include <netinet6/in6_var.h>
#endif
#include <netinet6/in6_var.h>
#ifndef SA_SIZE
#define SA_SIZE(sa) \
@@ -42,12 +42,12 @@
#ifdef HAVE_BSD_NETWORK
static int del_family = 0;
static struct all_addr del_addr;
static union all_addr del_addr;
#endif
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
int arp_enumerate(void *parm, int (*callback)())
int arp_enumerate(void *parm, callback_t callback)
{
int mib[6];
size_t needed;
@@ -91,7 +91,7 @@ int arp_enumerate(void *parm, int (*callback)())
rtm = (struct rt_msghdr *)next;
sin2 = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
if (!(*callback)(AF_INET, &sin2->sin_addr, LLADDR(sdl), sdl->sdl_alen, parm))
if (!callback.af_unspec(AF_INET, &sin2->sin_addr, LLADDR(sdl), sdl->sdl_alen, parm))
return 0;
}
@@ -100,10 +100,10 @@ int arp_enumerate(void *parm, int (*callback)())
#endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
int iface_enumerate(int family, void *parm, int (*callback)())
int iface_enumerate(int family, void *parm, callback_t callback)
{
struct ifaddrs *head, *addrs;
int errsav, fd = -1, ret = 0;
int errsave, fd = -1, ret = 0;
if (family == AF_UNSPEC)
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
@@ -119,127 +119,123 @@ int iface_enumerate(int family, void *parm, int (*callback)())
if (getifaddrs(&head) == -1)
return 0;
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6)
#if defined(HAVE_BSD_NETWORK)
if (family == AF_INET6)
fd = socket(PF_INET6, SOCK_DGRAM, 0);
#endif
for (addrs = head; addrs; addrs = addrs->ifa_next)
{
if (addrs->ifa_addr->sa_family == family)
int iface_index = if_nametoindex(addrs->ifa_name);
if (iface_index == 0 || !addrs->ifa_addr ||
addrs->ifa_addr->sa_family != family ||
(!addrs->ifa_netmask && family != AF_LINK))
continue;
if (family == AF_INET)
{
int iface_index = if_nametoindex(addrs->ifa_name);
if (iface_index == 0 || !addrs->ifa_addr ||
(!addrs->ifa_netmask && family != AF_LINK))
struct in_addr addr, netmask, broadcast;
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr)
continue;
if (family == AF_INET)
{
struct in_addr addr, netmask, broadcast;
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET && del_addr.addr.addr4.s_addr == addr.s_addr)
continue;
#endif
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
if (addrs->ifa_broadaddr)
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
else
broadcast.s_addr = 0;
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
goto err;
}
#ifdef HAVE_IPV6
else if (family == AF_INET6)
{
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
int i, j, prefix = 0;
u32 valid = 0xffffffff, preferred = 0xffffffff;
int flags = 0;
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
if (addrs->ifa_broadaddr)
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
else
broadcast.s_addr = 0;
if (!callback.af_inet(addr, iface_index, NULL, netmask, broadcast, parm))
goto err;
}
else if (family == AF_INET6)
{
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
int i, j, prefix = 0;
u32 valid = 0xffffffff, preferred = 0xffffffff;
int flags = 0;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr.addr6, addr))
continue;
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr))
continue;
#endif
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
struct in6_ifreq ifr6;
memset(&ifr6, 0, sizeof(ifr6));
strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
struct in6_ifreq ifr6;
memset(&ifr6, 0, sizeof(ifr6));
safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
{
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
flags |= IFACE_TENTATIVE;
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
flags |= IFACE_DEPRECATED;
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
{
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
flags |= IFACE_TENTATIVE;
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
flags |= IFACE_DEPRECATED;
#ifdef IN6_IFF_TEMPORARY
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
flags |= IFACE_PERMANENT;
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
flags |= IFACE_PERMANENT;
#endif
#ifdef IN6_IFF_PRIVACY
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
flags |= IFACE_PERMANENT;
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
flags |= IFACE_PERMANENT;
#endif
}
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
{
valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
}
}
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
{
valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
}
#endif
for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
if (netmask[i] != 0xff)
break;
if (i != IN6ADDRSZ && netmask[i])
for (j = 7; j > 0; j--, prefix++)
if ((netmask[i] & (1 << j)) == 0)
break;
/* voodoo to clear interface field in address */
if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
{
addr->s6_addr[2] = 0;
addr->s6_addr[3] = 0;
}
if (!((*callback)(addr, prefix, scope_id, iface_index, flags,
(int) preferred, (int)valid, parm)))
goto err;
}
#endif /* HAVE_IPV6 */
#ifdef HAVE_DHCP6
else if (family == AF_LINK)
{
/* Assume ethernet again here */
struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
if (sdl->sdl_alen != 0 &&
!((*callback)(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm)))
goto err;
}
#endif
for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
if (netmask[i] != 0xff)
break;
if (i != IN6ADDRSZ && netmask[i])
for (j = 7; j > 0; j--, prefix++)
if ((netmask[i] & (1 << j)) == 0)
break;
/* voodoo to clear interface field in address */
if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
{
addr->s6_addr[2] = 0;
addr->s6_addr[3] = 0;
}
if (!callback.af_inet6(addr, prefix, scope_id, iface_index, flags,
(unsigned int) preferred, (unsigned int)valid, parm))
goto err;
}
#ifdef HAVE_DHCP6
else if (family == AF_LINK)
{
/* Assume ethernet again here */
struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
if (sdl->sdl_alen != 0 &&
!callback.af_local(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm))
goto err;
}
#endif
}
ret = 1;
err:
errsav = errno;
errsave = errno;
freeifaddrs(head);
if (fd != -1)
close(fd);
errno = errsav;
errno = errsave;
return ret;
}
@@ -359,7 +355,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
iov[3].iov_base = mess;
iov[3].iov_len = len;
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
}
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
@@ -424,11 +420,9 @@ void route_sock(void)
{
del_family = sa->sa_family;
if (del_family == AF_INET)
del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
#ifdef HAVE_IPV6
del_addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
else if (del_family == AF_INET6)
del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
#endif
del_addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
else
del_family = 0;
}
@@ -444,5 +438,3 @@ void route_sock(void)
}
#endif /* HAVE_BSD_NETWORK */

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,17 +15,28 @@
*/
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
#define MAX_PROCS 20 /* default max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
#define TCP_TIMEOUT 5 /* timeout waiting to connect to an upstream server - double this for answer */
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
#define EDNS_PKTSZ 1232 /* default max EDNS.0 UDP packet from from /dnsflagday.net/2020 */
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
#define DNSSEC_LIMIT_WORK 40 /* Max number of queries to validate one question */
#define DNSSEC_LIMIT_SIG_FAIL 20 /* Number of signature that can fail to validate in one answer */
#define DNSSEC_LIMIT_CRYPTO 200 /* max no. of crypto operations to validate one query. */
#define DNSSEC_LIMIT_NSEC3_ITERS 150 /* Max. number if iterations allowed in NSEC3 record. */
#define DNSSEC_ASSUMED_DS_TTL 3600 /* TTL for negative DS records implied by server=/domain/ */
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define SMALL_PORT_RANGE 30 /* If DNS port range is smaller than this, use different allocation. */
#define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 20 /* or 20 seconds */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
#define MAXLEASES 1000 /* maximum number of DHCP leases */
#define PING_WAIT 3 /* wait for ping address-in-use test */
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
@@ -33,22 +44,29 @@
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
#define SMALLDNAME 50 /* most domain names are smaller than this */
#define CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */
#define DNSSEC_MIN_TTL 60 /* DNSKEY and DS records in cache last at least this long */
#define HOSTSFILE "/etc/hosts"
#define ETHERSFILE "/etc/ethers"
#define DEFLEASE 3600 /* default lease time, 1 hour */
#define DEFLEASE 3600 /* default DHCPv4 lease time, one hour */
#define DEFLEASE6 (3600*24) /* default lease time for DHCPv6. One day. */
#define CHUSER "nobody"
#define CHGRP "dip"
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
#define TFTP_MAX_WINDOW 32 /* max window size to negotiate */
#define TFTP_TRANSFER_TIME 120 /* Abandon TFTP transfers after this long. Two mins. */
#define LOG_MAX 5 /* log-queue length */
#define RANDFILE "/dev/urandom"
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
#define DNSMASQ_UBUS_NAME "dnsmasq" /* Default - may be overridden by config */
#define AUTH_TTL 600 /* default TTL for auth DNS */
#define SOA_REFRESH 1200 /* SOA refresh default */
#define SOA_RETRY 180 /* SOA retry default */
#define SOA_EXPIRY 1209600 /* SOA expiry default */
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
#define LOOP_TEST_TYPE T_TXT
#define DEFAULT_FAST_RETRY 1000 /* ms, default delay before fast retry */
#define STALE_CACHE_EXPIRY 86400 /* 1 day in secs, default maximum expiry time for stale cache data */
/* compile-time options: uncomment below to enable or do eg.
make COPTS=-DHAVE_BROKEN_RTC
@@ -87,14 +105,17 @@ HAVE_DBUS
support some methods to allow (re)configuration of the upstream DNS
servers via DBus.
HAVE_UBUS
define this if you want to link against libubus
HAVE_IDN
define this if you want international domain name support.
NOTE: for backwards compatibility, IDN support is automatically
included when internationalisation support is built, using the
*-i18n makefile targets, even if HAVE_IDN is not explicitly set.
define this if you want international domain name 2003 support.
HAVE_LIBIDN2
define this if you want international domain name 2008 support.
HAVE_CONNTRACK
define this to include code which propogates conntrack marks from
define this to include code which propagates conntrack marks from
incoming DNS queries to the corresponding upstream queries. This adds
a build-dependency on libnetfilter_conntrack, but the resulting binary will
still run happily on a kernel without conntrack support.
@@ -103,6 +124,10 @@ HAVE_IPSET
define this to include the ability to selectively add resolved ip addresses
to given ipsets.
HAVE_NFTSET
define this to include the ability to selectively add resolved ip addresses
to given nftables sets.
HAVE_AUTH
define this to include the facility to act as an authoritative DNS
server for one or more zones.
@@ -110,24 +135,31 @@ HAVE_AUTH
HAVE_DNSSEC
include DNSSEC validator.
HAVE_DUMPFILE
include code to dump packets to a libpcap-format file for debugging.
HAVE_LOOP
include functionality to probe for and remove DNS forwarding loops.
HAVE_INOTIFY
use the Linux inotify facility to efficiently re-read configuration files.
NO_IPV6
NO_ID
Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
NO_TFTP
NO_DHCP
NO_DHCP6
NO_SCRIPT
NO_LARGEFILE
NO_AUTH
these are avilable to explictly disable compile time options which would
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
which are enabled by default in the distributed source tree. Building dnsmasq
NO_DUMPFILE
NO_LOOP
NO_INOTIFY
NO_IPSET
these are available to explicitly disable compile time options which would
otherwise be enabled automatically or which are enabled by default
in the distributed source tree. Building dnsmasq
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
NO_NETTLE_ECC
Don't include the ECDSA cypher in DNSSEC validation. Needed for older Nettle versions.
NO_GMP
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
@@ -155,6 +187,7 @@ RESOLVFILE
#define HAVE_AUTH
#define HAVE_IPSET
#define HAVE_LOOP
#define HAVE_DUMPFILE
/* Build options which require external libraries.
@@ -166,9 +199,10 @@ RESOLVFILE
/* #define HAVE_LUASCRIPT */
/* #define HAVE_DBUS */
/* #define HAVE_IDN */
/* #define HAVE_LIBIDN2 */
/* #define HAVE_CONNTRACK */
/* #define HAVE_DNSSEC */
/* #define HAVE_NFTSET */
/* Default locations for important system files. */
@@ -222,27 +256,13 @@ HAVE_SOCKADDR_SA_LEN
defined if struct sockaddr has sa_len field (*BSD)
*/
/* Must preceed __linux__ since uClinux defines __linux__ too. */
#if defined(__uClinux__)
#define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_SOCKADDR_SA_LEN
/* Never use fork() on uClinux. Note that this is subtly different from the
--keep-in-foreground option, since it also suppresses forking new
processes for TCP connections and disables the call-a-script on leasechange
system. It's intended for use on MMU-less kernels. */
#define NO_FORK
#elif defined(__UCLIBC__)
#if defined(__UCLIBC__)
#define HAVE_LINUX_NETWORK
#if defined(__UCLIBC_HAS_GNU_GETOPT__) || \
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
# define HAVE_GETOPT_LONG
#endif
#undef HAVE_SOCKADDR_SA_LEN
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
# define NO_FORK
#endif
#if defined(__UCLIBC_HAS_IPV6__)
# ifndef IPV6_V6ONLY
# define IPV6_V6ONLY 26
@@ -260,7 +280,7 @@ HAVE_SOCKADDR_SA_LEN
defined(__DragonFly__) || \
defined(__FreeBSD_kernel__)
#define HAVE_BSD_NETWORK
/* Later verions of FreeBSD have getopt_long() */
/* Later versions of FreeBSD have getopt_long() */
#if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG
#endif
@@ -270,12 +290,16 @@ HAVE_SOCKADDR_SA_LEN
#define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG
#define HAVE_SOCKADDR_SA_LEN
#define NO_IPSET
/* Define before sys/socket.h is included so we get socklen_t */
#define _BSD_SOCKLEN_T_
/* Select the RFC_3542 version of the IPv6 socket API.
Define before netinet6/in6.h is included. */
#define __APPLE_USE_RFC_3542
#define NO_IPSET
#define __APPLE_USE_RFC_3542
/* Required for Mojave. */
#ifndef SOL_TCP
# define SOL_TCP IPPROTO_TCP
#endif
#elif defined(__NetBSD__)
#define HAVE_BSD_NETWORK
@@ -290,29 +314,9 @@ HAVE_SOCKADDR_SA_LEN
#endif
/* Decide if we're going to support IPv6 */
/* We assume that systems which don't have IPv6
headers don't have ntop and pton either */
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY)
# define HAVE_IPV6
# define ADDRSTRLEN INET6_ADDRSTRLEN
#else
# if !defined(INET_ADDRSTRLEN)
# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
# endif
# undef HAVE_IPV6
# define ADDRSTRLEN INET_ADDRSTRLEN
#endif
/* rules to implement compile-time option dependencies and
the NO_XXX flags */
#ifdef NO_IPV6
#undef HAVE_IPV6
#endif
#ifdef NO_TFTP
#undef HAVE_TFTP
#endif
@@ -322,7 +326,7 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_DHCP6
#endif
#if defined(NO_DHCP6) || !defined(HAVE_IPV6)
#if defined(NO_DHCP6)
#undef HAVE_DHCP6
#endif
@@ -331,7 +335,7 @@ HAVE_SOCKADDR_SA_LEN
#define HAVE_DHCP
#endif
#if defined(NO_SCRIPT) || !defined(HAVE_DHCP) || defined(NO_FORK)
#if defined(NO_SCRIPT)
#undef HAVE_SCRIPT
#undef HAVE_LUASCRIPT
#endif
@@ -345,23 +349,47 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_AUTH
#endif
#if !defined(HAVE_LINUX_NETWORK)
#undef HAVE_NFTSET
#endif
#if defined(NO_IPSET)
#undef HAVE_IPSET
#endif
#if defined(HAVE_IPSET)
# if defined(HAVE_LINUX_NETWORK)
# define HAVE_LINUX_IPSET
# elif defined(HAVE_BSD_NETWORK)
# define HAVE_BSD_IPSET
# else
# undef HAVE_IPSET
# endif
#endif
#ifdef NO_LOOP
#undef HAVE_LOOP
#endif
#ifdef NO_DUMPFILE
#undef HAVE_DUMPFILE
#endif
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
#define HAVE_INOTIFY
#endif
/* This never compiles code, it's only used by the makefile to fingerprint builds. */
#ifdef DNSMASQ_COMPILE_FLAGS
static char *compile_flags = DNSMASQ_COMPILE_FLAGS;
#endif
/* Define a string indicating which options are in use.
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
DNSMASQ_COMPILE_OPTS is only defined in dnsmasq.c */
#ifdef DNSMASQ_COMPILE_OPTS
static char *compile_opts =
#ifndef HAVE_IPV6
"no-"
#endif
"IPv6 "
#ifndef HAVE_GETOPT_LONG
"no-"
@@ -370,21 +398,26 @@ static char *compile_opts =
#ifdef HAVE_BROKEN_RTC
"no-RTC "
#endif
#ifdef NO_FORK
"no-MMU "
#endif
#ifndef HAVE_DBUS
"no-"
#endif
"DBus "
#ifndef HAVE_UBUS
"no-"
#endif
"UBus "
#ifndef LOCALEDIR
"no-"
#endif
"i18n "
#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
#if defined(HAVE_LIBIDN2)
"IDN2 "
#else
#if !defined(HAVE_IDN)
"no-"
#endif
"IDN "
#endif
"IDN "
#endif
#ifndef HAVE_DHCP
"no-"
#endif
@@ -394,14 +427,14 @@ static char *compile_opts =
"no-"
# endif
"DHCPv6 "
# if !defined(HAVE_SCRIPT)
#endif
#if !defined(HAVE_SCRIPT)
"no-scripts "
# else
# if !defined(HAVE_LUASCRIPT)
"no-"
# endif
"Lua "
#else
# if !defined(HAVE_LUASCRIPT)
"no-"
# endif
"Lua "
#endif
#ifndef HAVE_TFTP
"no-"
@@ -415,6 +448,10 @@ static char *compile_opts =
"no-"
#endif
"ipset "
#ifndef HAVE_NFTSET
"no-"
#endif
"nftset "
#ifndef HAVE_AUTH
"no-"
#endif
@@ -423,13 +460,20 @@ static char *compile_opts =
"no-"
#endif
"DNSSEC "
#ifdef NO_ID
"no-ID "
#endif
#ifndef HAVE_LOOP
"no-"
#endif
"loop-detect";
"loop-detect "
#ifndef HAVE_INOTIFY
"no-"
#endif
"inotify "
#ifndef HAVE_DUMPFILE
"no-"
#endif
"dumpfile";
#endif /* defined(DNSMASQ_COMPILE_OPTS) */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@ static int gotit = 0; /* yuck */
static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data);
int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr, int istcp, unsigned int *markp)
int get_incoming_mark(union mysockaddr *peer_addr, union all_addr *local_addr, int istcp, unsigned int *markp)
{
struct nf_conntrack *ct;
struct nfct_handle *h;
@@ -36,21 +36,19 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP);
nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port));
#ifdef HAVE_IPV6
if (peer_addr->sa.sa_family == AF_INET6)
{
nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6);
nfct_set_attr(ct, ATTR_IPV6_SRC, peer_addr->in6.sin6_addr.s6_addr);
nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in6.sin6_port);
nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr.addr6.s6_addr);
nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr6.s6_addr);
}
else
#endif
{
nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr);
nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in.sin_port);
nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr.addr4.s_addr);
nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr4.s_addr);
}
@@ -84,7 +82,4 @@ static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, vo
return NFCT_CB_CONTINUE;
}
#endif
#endif /* HAVE_CONNTRACK */

506
src/crypto.c Normal file
View File

@@ -0,0 +1,506 @@
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#if defined(HAVE_DNSSEC)
/* Minimal version of nettle */
/* bignum.h includes version.h and works on
earlier releases of nettle which don't have version.h */
#include <nettle/bignum.h>
#if !defined(NETTLE_VERSION_MAJOR)
# define NETTLE_VERSION_MAJOR 2
# define NETTLE_VERSION_MINOR 0
#endif
#define MIN_VERSION(major, minor) ((NETTLE_VERSION_MAJOR == (major) && NETTLE_VERSION_MINOR >= (minor)) || \
(NETTLE_VERSION_MAJOR > (major)))
#include <nettle/rsa.h>
#include <nettle/ecdsa.h>
#include <nettle/ecc-curve.h>
#if MIN_VERSION(3, 1)
#include <nettle/eddsa.h>
#endif
#if MIN_VERSION(3, 6)
# include <nettle/gostdsa.h>
#endif
#if MIN_VERSION(3, 1)
/* Implement a "hash-function" to the nettle API, which simply returns
the input data, concatenated into a single, statically maintained, buffer.
Used for the EdDSA sigs, which operate on the whole message, rather
than a digest. */
struct null_hash_digest
{
uint8_t *buff;
size_t len;
};
struct null_hash_ctx
{
size_t len;
};
static size_t null_hash_buff_sz = 0;
static uint8_t *null_hash_buff = NULL;
#define BUFF_INCR 128
static void null_hash_init(void *ctx)
{
((struct null_hash_ctx *)ctx)->len = 0;
}
static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
{
struct null_hash_ctx *ctx = ctxv;
size_t new_len = ctx->len + length;
if (new_len > null_hash_buff_sz)
{
uint8_t *new;
if (!(new = whine_malloc(new_len + BUFF_INCR)))
return;
if (null_hash_buff)
{
if (ctx->len != 0)
memcpy(new, null_hash_buff, ctx->len);
free(null_hash_buff);
}
null_hash_buff_sz = new_len + BUFF_INCR;
null_hash_buff = new;
}
memcpy(null_hash_buff + ctx->len, src, length);
ctx->len += length;
}
static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
{
(void)length;
((struct null_hash_digest *)dst)->buff = null_hash_buff;
((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
}
static struct nettle_hash null_hash = {
"null_hash",
sizeof(struct null_hash_ctx),
sizeof(struct null_hash_digest),
0,
(nettle_hash_init_func *) null_hash_init,
(nettle_hash_update_func *) null_hash_update,
(nettle_hash_digest_func *) null_hash_digest
};
#endif /* MIN_VERSION(3, 1) */
/* expand ctx and digest memory allocations if necessary and init hash function */
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
{
static void *ctx = NULL;
static unsigned char *digest = NULL;
static unsigned int ctx_sz = 0;
static unsigned int digest_sz = 0;
void *new;
if (ctx_sz < hash->context_size)
{
if (!(new = whine_malloc(hash->context_size)))
return 0;
if (ctx)
free(ctx);
ctx = new;
ctx_sz = hash->context_size;
}
if (digest_sz < hash->digest_size)
{
if (!(new = whine_malloc(hash->digest_size)))
return 0;
if (digest)
free(digest);
digest = new;
digest_sz = hash->digest_size;
}
*ctxp = ctx;
*digestp = digest;
hash->init(ctx);
return 1;
}
static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
unsigned char *p;
size_t exp_len;
static struct rsa_public_key *key = NULL;
static mpz_t sig_mpz;
(void)digest_len;
if (key == NULL)
{
if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
return 0;
nettle_rsa_public_key_init(key);
mpz_init(sig_mpz);
}
if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
return 0;
key_len--;
if ((exp_len = *p++) == 0)
{
GETSHORT(exp_len, p);
key_len -= 2;
}
if (exp_len >= key_len)
return 0;
key->size = key_len - exp_len;
mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
switch (algo)
{
case 5: case 7:
return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
case 8:
return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
case 10:
return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
}
return 0;
}
static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
unsigned char *p;
unsigned int t;
struct ecc_point *key;
static struct ecc_point *key_256 = NULL, *key_384 = NULL;
static mpz_t x, y;
static struct dsa_signature *sig_struct;
#if !MIN_VERSION(3, 4)
#define nettle_get_secp_256r1() (&nettle_secp_256r1)
#define nettle_get_secp_384r1() (&nettle_secp_384r1)
#endif
if (!sig_struct)
{
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
return 0;
nettle_dsa_signature_init(sig_struct);
mpz_init(x);
mpz_init(y);
}
switch (algo)
{
case 13:
if (!key_256)
{
if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
return 0;
nettle_ecc_point_init(key_256, nettle_get_secp_256r1());
}
key = key_256;
t = 32;
break;
case 14:
if (!key_384)
{
if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
return 0;
nettle_ecc_point_init(key_384, nettle_get_secp_384r1());
}
key = key_384;
t = 48;
break;
default:
return 0;
}
if (sig_len != 2*t || key_len != 2*t ||
!(p = blockdata_retrieve(key_data, key_len, NULL)))
return 0;
mpz_import(x, t , 1, 1, 0, 0, p);
mpz_import(y, t , 1, 1, 0, 0, p + t);
if (!ecc_point_set(key, x, y))
return 0;
mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
}
#if MIN_VERSION(3, 6)
static int dnsmasq_gostdsa_verify(struct blockdata *key_data, unsigned int key_len,
unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
unsigned char *p;
static struct ecc_point *gost_key = NULL;
static mpz_t x, y;
static struct dsa_signature *sig_struct;
if (algo != 12 ||
sig_len != 64 || key_len != 64 ||
!(p = blockdata_retrieve(key_data, key_len, NULL)))
return 0;
if (!sig_struct)
{
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
!(gost_key = whine_malloc(sizeof(struct ecc_point))))
return 0;
nettle_dsa_signature_init(sig_struct);
nettle_ecc_point_init(gost_key, nettle_get_gost_gc256b());
mpz_init(x);
mpz_init(y);
}
mpz_import(x, 32, -1, 1, 0, 0, p);
mpz_import(y, 32, -1, 1, 0, 0, p + 32);
if (!ecc_point_set(gost_key, x, y))
return 0;
mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig);
mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig + 32);
return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
}
#endif
#if MIN_VERSION(3, 1)
static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
unsigned char *p;
if (digest_len != sizeof(struct null_hash_digest) ||
!(p = blockdata_retrieve(key_data, key_len, NULL)))
return 0;
/* The "digest" returned by the null_hash function is simply a struct null_hash_digest
which has a pointer to the actual data and a length, because the buffer
may need to be extended during "hashing". */
switch (algo)
{
case 15:
if (key_len != ED25519_KEY_SIZE ||
sig_len != ED25519_SIGNATURE_SIZE)
return 0;
return ed25519_sha512_verify(p,
((struct null_hash_digest *)digest)->len,
((struct null_hash_digest *)digest)->buff,
sig);
#if MIN_VERSION(3, 6)
case 16:
if (key_len != ED448_KEY_SIZE ||
sig_len != ED448_SIGNATURE_SIZE)
return 0;
return ed448_shake256_verify(p,
((struct null_hash_digest *)digest)->len,
((struct null_hash_digest *)digest)->buff,
sig);
#endif
}
return 0;
}
#endif
static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
/* Ensure at runtime that we have support for this digest */
if (!hash_find(algo_digest_name(algo)))
return NULL;
/* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
switch (algo)
{
case 5: case 7: case 8: case 10:
return dnsmasq_rsa_verify;
#if MIN_VERSION(3, 6)
case 12:
return dnsmasq_gostdsa_verify;
#endif
case 13: case 14:
return dnsmasq_ecdsa_verify;
#if MIN_VERSION(3, 1)
case 15:
return dnsmasq_eddsa_verify;
#endif
#if MIN_VERSION(3, 6)
case 16:
return dnsmasq_eddsa_verify;
#endif
}
return NULL;
}
int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo);
func = verify_func(algo);
if (!func)
return 0;
return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
}
/* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
define which algo numbers we support. If algo_digest_name() returns
non-NULL for an algorithm number, we assume that algorithm is
supported by verify(). */
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
char *ds_digest_name(int digest)
{
switch (digest)
{
case 1: return "sha1";
case 2: return "sha256";
#if MIN_VERSION(3, 6)
case 3: return "gosthash94cp";
#endif
case 4: return "sha384";
default: return NULL;
}
}
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
char *algo_digest_name(int algo)
{
switch (algo)
{
case 1: return NULL; /* RSA/MD5 - Must Not Implement. RFC 6944 para 2.3. */
case 2: return NULL; /* Diffie-Hellman */
case 3: return NULL; ; /* DSA/SHA1 - Must Not Implement. RFC 8624 section 3.1 */
case 5: return "sha1"; /* RSA/SHA1 */
case 6: return NULL; /* DSA-NSEC3-SHA1 - Must Not Implement. RFC 8624 section 3.1 */
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
case 8: return "sha256"; /* RSA/SHA-256 */
case 10: return "sha512"; /* RSA/SHA-512 */
#if MIN_VERSION(3, 6)
case 12: return "gosthash94cp"; /* ECC-GOST */
#endif
case 13: return "sha256"; /* ECDSAP256SHA256 */
case 14: return "sha384"; /* ECDSAP384SHA384 */
#if MIN_VERSION(3, 1)
case 15: return "null_hash"; /* ED25519 */
# if MIN_VERSION(3, 6)
case 16: return "null_hash"; /* ED448 */
# endif
#endif
default: return NULL;
}
}
/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
char *nsec3_digest_name(int digest)
{
switch (digest)
{
case 1: return "sha1";
default: return NULL;
}
}
/* Find pointer to correct hash function in nettle library */
const struct nettle_hash *hash_find(char *name)
{
if (!name)
return NULL;
#if MIN_VERSION(3,1) && defined(HAVE_DNSSEC)
/* We provide a "null" hash which returns the input data as digest. */
if (strcmp(null_hash.name, name) == 0)
return &null_hash;
#endif
/* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
incompatibilities if sizeof(nettle_hashes) changes between library
versions. */
#if MIN_VERSION(3, 4)
return nettle_lookup_hash(name);
#else
{
int i;
for (i = 0; nettle_hashes[i]; i++)
if (strcmp(nettle_hashes[i]->name, name) == 0)
return nettle_hashes[i];
}
return NULL;
#endif
}
#endif /* defined(HAVE_DNSSEC) */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,6 +52,15 @@ const char* introspection_xml_template =
" <method name=\"SetFilterWin2KOption\">\n"
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"SetFilterA\">\n"
" <arg name=\"filter-a\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"SetFilterAAAA\">\n"
" <arg name=\"filter-aaaa\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"SetLocaliseQueriesOption\">\n"
" <arg name=\"localise-queries\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"SetBogusPrivOption\">\n"
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
" </method>\n"
@@ -70,10 +79,34 @@ const char* introspection_xml_template =
" <arg name=\"hwaddr\" type=\"s\"/>\n"
" <arg name=\"hostname\" type=\"s\"/>\n"
" </signal>\n"
#ifdef HAVE_DHCP
" <method name=\"AddDhcpLease\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"hwaddr\" type=\"s\"/>\n"
" <arg name=\"hostname\" type=\"ay\"/>\n"
" <arg name=\"clid\" type=\"ay\"/>\n"
" <arg name=\"lease_duration\" type=\"u\"/>\n"
" <arg name=\"ia_id\" type=\"u\"/>\n"
" <arg name=\"is_temporary\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"DeleteDhcpLease\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
" </method>\n"
#endif
" <method name=\"GetMetrics\">\n"
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
" </method>\n"
" <method name=\"GetServerMetrics\">\n"
" <arg name=\"metrics\" direction=\"out\" type=\"a{ss}\"/>\n"
" </method>\n"
" <method name=\"ClearMetrics\">\n"
" </method>\n"
" </interface>\n"
"</node>\n";
static char *introspection_xml = NULL;
static int watches_modified = 0;
struct watch {
DBusWatch *watch;
@@ -95,14 +128,15 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
w->watch = watch;
w->next = daemon->watches;
daemon->watches = w;
watches_modified++;
w = data; /* no warning */
(void)data; /* no warning */
return TRUE;
}
static void remove_watch(DBusWatch *watch, void *data)
{
struct watch **up, *w, *tmp;
struct watch **up, *w, *tmp;
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
{
@@ -111,21 +145,26 @@ static void remove_watch(DBusWatch *watch, void *data)
{
*up = tmp;
free(w);
watches_modified++;
}
else
up = &(w->next);
}
w = data; /* no warning */
(void)data; /* no warning */
}
static void dbus_read_servers(DBusMessage *message)
static DBusMessage* dbus_read_servers(DBusMessage *message)
{
DBusMessageIter iter;
union mysockaddr addr, source_addr;
char *domain;
dbus_message_iter_init(message, &iter);
if (!dbus_message_iter_init(message, &iter))
{
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
}
mark_servers(SERV_FROM_DBUS);
@@ -167,9 +206,6 @@ static void dbus_read_servers(DBusMessage *message)
}
}
#ifndef HAVE_IPV6
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
#else
if (i == sizeof(struct in6_addr))
{
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
@@ -184,7 +220,6 @@ static void dbus_read_servers(DBusMessage *message)
source_addr.in6.sin6_port = htons(daemon->query_port);
skip = 0;
}
#endif
}
else
/* At the end */
@@ -201,13 +236,14 @@ static void dbus_read_servers(DBusMessage *message)
domain = NULL;
if (!skip)
add_update_server(SERV_FROM_DBUS, &addr, &source_addr, NULL, domain);
add_update_server(SERV_FROM_DBUS, &addr, &source_addr, NULL, domain, NULL);
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
}
/* unlink and free anything still marked. */
cleanup_servers();
return NULL;
}
#ifdef HAVE_LOOP
@@ -223,7 +259,7 @@ static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
for (serv = daemon->servers; serv; serv = serv->next)
if (serv->flags & SERV_LOOP)
{
prettyprint_addr(&serv->addr, daemon->addrbuff);
(void)prettyprint_addr(&serv->addr, daemon->addrbuff);
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
}
@@ -262,9 +298,14 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
{
const char *str = NULL;
union mysockaddr addr, source_addr;
int flags = 0;
u16 flags = 0;
char interface[IF_NAMESIZE];
char *str_addr, *str_domain = NULL;
struct server_details sdetails = { 0 };
sdetails.addr = &addr;
sdetails.source_addr = &source_addr;
sdetails.interface = interface;
sdetails.flags = &flags;
if (strings)
{
@@ -347,24 +388,6 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
strcpy(str_addr, str);
}
memset(&addr, 0, sizeof(addr));
memset(&source_addr, 0, sizeof(source_addr));
memset(&interface, 0, sizeof(interface));
/* parse the IP address */
if ((addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, &flags)))
{
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s': %s",
str, addr_err);
break;
}
/* 0.0.0.0 for server address == NULL, for Dbus */
if (addr.in.sin_family == AF_INET &&
addr.in.sin_addr.s_addr == 0)
flags |= SERV_NO_ADDR;
if (strings)
{
char *p;
@@ -378,7 +401,31 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
else
p = NULL;
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain);
if (strings && strlen(str_addr) == 0)
add_update_server(SERV_LITERAL_ADDRESS | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
else
{
if ((addr_err = parse_server(str_addr, &sdetails)))
{
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s': %s",
str, addr_err);
break;
}
while (parse_server_next(&sdetails))
{
if ((addr_err = parse_server_addr(&sdetails)))
{
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s': %s",
str, addr_err);
break;
}
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
}
}
} while ((str_domain = p));
}
else
@@ -392,47 +439,362 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
dbus_message_iter_get_basic(&string_iter, &str);
dbus_message_iter_next (&string_iter);
if ((addr_err = parse_server(str_addr, &sdetails)))
{
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s': %s",
str, addr_err);
break;
}
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str);
while (parse_server_next(&sdetails))
{
if ((addr_err = parse_server_addr(&sdetails)))
{
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s': %s",
str, addr_err);
break;
}
/* 0.0.0.0 for server address == NULL, for Dbus */
if (addr.in.sin_family == AF_INET &&
addr.in.sin_addr.s_addr == 0)
flags |= SERV_LITERAL_ADDRESS;
else
flags &= ~SERV_LITERAL_ADDRESS;
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
}
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
}
if (sdetails.orig_hostinfo)
freeaddrinfo(sdetails.orig_hostinfo);
/* jump to next element in outer array */
dbus_message_iter_next(&array_iter);
}
cleanup_servers();
if (dup)
free(dup);
return error;
}
static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
static DBusMessage *dbus_get_bool(DBusMessage *message, dbus_bool_t *enabled, char *name)
{
DBusMessageIter iter;
dbus_bool_t enabled;
if (!dbus_message_iter_init(message, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected boolean argument");
dbus_message_iter_get_basic(&iter, &enabled);
if (enabled)
{
my_syslog(LOG_INFO, "Enabling --%s option from D-Bus", name);
set_option_bool(flag);
}
dbus_message_iter_get_basic(&iter, enabled);
if (*enabled)
my_syslog(LOG_INFO, _("Enabling --%s option from D-Bus"), name);
else
my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
return NULL;
}
static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
{
dbus_bool_t val;
DBusMessage *reply = dbus_get_bool(message, &val, name);
if (!reply)
{
my_syslog(LOG_INFO, "Disabling --%s option from D-Bus", name);
reset_option_bool(flag);
if (val)
set_option_bool(flag);
else
reset_option_bool(flag);
}
return reply;
}
#ifdef HAVE_DHCP
static DBusMessage *dbus_add_lease(DBusMessage* message)
{
struct dhcp_lease *lease;
const char *ipaddr, *hwaddr, *hostname, *tmp;
const unsigned char* clid;
int clid_len, hostname_len, hw_len, hw_type;
dbus_uint32_t expires, ia_id;
dbus_bool_t is_temporary;
union all_addr addr;
time_t now = dnsmasq_time();
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
DBusMessageIter iter, array_iter;
if (!dbus_message_iter_init(message, &iter))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as first argument");
dbus_message_iter_get_basic(&iter, &ipaddr);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as second argument");
dbus_message_iter_get_basic(&iter, &hwaddr);
dbus_message_iter_next(&iter);
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected byte array as third argument");
dbus_message_iter_recurse(&iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
tmp = memchr(hostname, '\0', hostname_len);
if (tmp)
{
if (tmp == &hostname[hostname_len - 1])
hostname_len--;
else
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Hostname contains an embedded NUL character");
}
dbus_message_iter_next(&iter);
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected byte array as fourth argument");
dbus_message_iter_recurse(&iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as fifth argument");
dbus_message_iter_get_basic(&iter, &expires);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as sixth argument");
dbus_message_iter_get_basic(&iter, &ia_id);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as sixth argument");
dbus_message_iter_get_basic(&iter, &is_temporary);
if (inet_pton(AF_INET, ipaddr, &addr.addr4))
{
if (!daemon->dhcp)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"DHCPv4 not configured");
if (ia_id != 0 || is_temporary)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"ia_id and is_temporary must be zero for IPv4 lease");
if (!(lease = lease_find_by_addr(addr.addr4)))
lease = lease4_allocate(addr.addr4);
}
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, ipaddr, &addr.addr6))
{
if (!daemon->doing_dhcp6)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"DHCPv6 not configured");
if (!(lease = lease6_find_by_addr(&addr.addr6, 128, 0)))
lease = lease6_allocate(&addr.addr6,
is_temporary ? LEASE_TA : LEASE_NA);
if (lease)
lease_set_iaid(lease, ia_id);
}
#endif
else
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s'", ipaddr);
if (!lease)
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"unable to allocate lease for IP address '%s'", ipaddr);
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
if (hw_len < 0)
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid HW address '%s'", hwaddr);
if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER;
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
clid_len, now, 0);
lease_set_expires(lease, expires, now);
if (hostname_len != 0)
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
lease_update_file(now);
lease_update_dns(0);
return NULL;
}
static DBusMessage *dbus_del_lease(DBusMessage* message)
{
struct dhcp_lease *lease = NULL;
DBusMessageIter iter;
const char *ipaddr;
DBusMessage *reply;
union all_addr addr;
dbus_bool_t ret = 1;
time_t now = dnsmasq_time();
if (!dbus_message_iter_init(message, &iter))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as first argument");
dbus_message_iter_get_basic(&iter, &ipaddr);
if (inet_pton(AF_INET, ipaddr, &addr.addr4) && daemon->dhcp)
lease = lease_find_by_addr(addr.addr4);
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, ipaddr, &addr.addr6) && daemon->doing_dhcp6)
lease = lease6_find_by_addr(&addr.addr6, 128, 0);
#endif
else
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s'", ipaddr);
if (lease)
{
lease_prune(lease, now);
lease_update_file(now);
lease_update_dns(0);
}
else
ret = 0;
if ((reply = dbus_message_new_method_return(message)))
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
DBUS_TYPE_INVALID);
return reply;
}
#endif
static DBusMessage *dbus_get_metrics(DBusMessage* message)
{
DBusMessage *reply = dbus_message_new_method_return(message);
DBusMessageIter array, dict, iter;
int i;
dbus_message_iter_init_append(reply, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
for (i = 0; i < __METRIC_MAX; i++) {
const char *key = get_metric_name(i);
dbus_uint32_t value = daemon->metrics[i];
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
dbus_message_iter_close_container(&array, &dict);
}
dbus_message_iter_close_container(&iter, &array);
return reply;
}
static void add_dict_entry(DBusMessageIter *container, const char *key, const char *val)
{
DBusMessageIter dict;
dbus_message_iter_open_container(container, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &val);
dbus_message_iter_close_container(container, &dict);
}
static void add_dict_int(DBusMessageIter *container, const char *key, const unsigned int val)
{
snprintf(daemon->namebuff, MAXDNAME, "%u", val);
add_dict_entry(container, key, daemon->namebuff);
}
static DBusMessage *dbus_get_server_metrics(DBusMessage* message)
{
DBusMessage *reply = dbus_message_new_method_return(message);
DBusMessageIter server_array, dict_array, server_iter;
struct server *serv;
dbus_message_iter_init_append(reply, &server_iter);
dbus_message_iter_open_container(&server_iter, DBUS_TYPE_ARRAY, "a{ss}", &server_array);
/* sum counts from different records for same server */
for (serv = daemon->servers; serv; serv = serv->next)
serv->flags &= ~SERV_MARK;
for (serv = daemon->servers; serv; serv = serv->next)
if (!(serv->flags & SERV_MARK))
{
unsigned int port;
unsigned int queries = 0, failed_queries = 0, nxdomain_replies = 0, retrys = 0;
unsigned int sigma_latency = 0, count_latency = 0;
struct server *serv1;
for (serv1 = serv; serv1; serv1 = serv1->next)
if (!(serv1->flags & SERV_MARK) && sockaddr_isequal(&serv->addr, &serv1->addr))
{
serv1->flags |= SERV_MARK;
queries += serv1->queries;
failed_queries += serv1->failed_queries;
nxdomain_replies += serv1->nxdomain_replies;
retrys += serv1->retrys;
sigma_latency += serv1->query_latency;
count_latency++;
}
dbus_message_iter_open_container(&server_array, DBUS_TYPE_ARRAY, "{ss}", &dict_array);
port = prettyprint_addr(&serv->addr, daemon->namebuff);
add_dict_entry(&dict_array, "address", daemon->namebuff);
add_dict_int(&dict_array, "port", port);
add_dict_int(&dict_array, "queries", queries);
add_dict_int(&dict_array, "failed_queries", failed_queries);
add_dict_int(&dict_array, "nxdomain", nxdomain_replies);
add_dict_int(&dict_array, "retries", retrys);
add_dict_int(&dict_array, "latency", sigma_latency/count_latency);
dbus_message_iter_close_container(&server_array, &dict_array);
}
dbus_message_iter_close_container(&server_iter, &server_array);
return reply;
}
DBusHandlerResult message_handler(DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -469,7 +831,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
#endif
else if (strcmp(method, "SetServers") == 0)
{
dbus_read_servers(message);
reply = dbus_read_servers(message);
new_servers = 1;
}
else if (strcmp(method, "SetServersEx") == 0)
@@ -486,10 +848,72 @@ DBusHandlerResult message_handler(DBusConnection *connection,
{
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
}
else if (strcmp(method, "SetFilterA") == 0)
{
static int done = 0;
static struct rrlist list = { 0, NULL };
dbus_bool_t enabled;
if (!(reply = dbus_get_bool(message, &enabled, "filter-A")))
{
if (!done)
{
done = 1;
list.next = daemon->filter_rr;
daemon->filter_rr = &list;
}
list.rr = enabled ? T_A : 0;
}
}
else if (strcmp(method, "SetFilterAAAA") == 0)
{
static int done = 0;
static struct rrlist list = { 0, NULL };
dbus_bool_t enabled;
if (!(reply = dbus_get_bool(message, &enabled, "filter-AAAA")))
{
if (!done)
{
done = 1;
list.next = daemon->filter_rr;
daemon->filter_rr = &list;
}
list.rr = enabled ? T_AAAA : 0;
}
}
else if (strcmp(method, "SetLocaliseQueriesOption") == 0)
{
reply = dbus_set_bool(message, OPT_LOCALISE, "localise-queries");
}
else if (strcmp(method, "SetBogusPrivOption") == 0)
{
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
}
#ifdef HAVE_DHCP
else if (strcmp(method, "AddDhcpLease") == 0)
{
reply = dbus_add_lease(message);
}
else if (strcmp(method, "DeleteDhcpLease") == 0)
{
reply = dbus_del_lease(message);
}
#endif
else if (strcmp(method, "GetMetrics") == 0)
{
reply = dbus_get_metrics(message);
}
else if (strcmp(method, "GetServerMetrics") == 0)
{
reply = dbus_get_server_metrics(message);
}
else if (strcmp(method, "ClearMetrics") == 0)
{
clear_metrics();
}
else if (strcmp(method, "ClearCache") == 0)
clear_cache = 1;
else
@@ -498,7 +922,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
if (new_servers)
{
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
check_servers();
check_servers(0);
if (option_bool(OPT_RELOAD))
clear_cache = 1;
}
@@ -506,7 +930,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
if (clear_cache)
clear_cache_and_reload(dnsmasq_time());
method = user_data; /* no warning */
(void)user_data; /* no warning */
/* If no reply or no error, return nothing */
if (!reply)
@@ -532,8 +956,11 @@ char *dbus_init(void)
dbus_error_init (&dbus_error);
if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
return NULL;
{
dbus_error_free(&dbus_error);
return NULL;
}
dbus_connection_set_exit_on_disconnect(connection, FALSE);
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
NULL, NULL, NULL);
@@ -558,8 +985,7 @@ char *dbus_init(void)
}
void set_dbus_listeners(int *maxfdp,
fd_set *rset, fd_set *wset, fd_set *eset)
void set_dbus_listeners(void)
{
struct watch *w;
@@ -568,43 +994,53 @@ void set_dbus_listeners(int *maxfdp,
{
unsigned int flags = dbus_watch_get_flags(w->watch);
int fd = dbus_watch_get_unix_fd(w->watch);
bump_maxfd(fd, maxfdp);
int poll_flags = POLLERR;
if (flags & DBUS_WATCH_READABLE)
FD_SET(fd, rset);
poll_flags |= POLLIN;
if (flags & DBUS_WATCH_WRITABLE)
FD_SET(fd, wset);
poll_flags |= POLLOUT;
FD_SET(fd, eset);
poll_listen(fd, poll_flags);
}
}
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
static int check_dbus_watches()
{
DBusConnection *connection = (DBusConnection *)daemon->dbus;
struct watch *w;
watches_modified = 0;
for (w = daemon->watches; w; w = w->next)
if (dbus_watch_get_enabled(w->watch))
{
unsigned int flags = 0;
int fd = dbus_watch_get_unix_fd(w->watch);
if (FD_ISSET(fd, rset))
int poll_flags = poll_check(fd, POLLIN|POLLOUT|POLLERR);
if ((poll_flags & POLLIN) != 0)
flags |= DBUS_WATCH_READABLE;
if (FD_ISSET(fd, wset))
if ((poll_flags & POLLOUT) != 0)
flags |= DBUS_WATCH_WRITABLE;
if (FD_ISSET(fd, eset))
if ((poll_flags & POLLERR) != 0)
flags |= DBUS_WATCH_ERROR;
if (flags != 0)
dbus_watch_handle(w->watch, flags);
{
dbus_watch_handle(w->watch, flags);
if (watches_modified)
return 0;
}
}
return 1;
}
void check_dbus_listeners()
{
DBusConnection *connection = (DBusConnection *)daemon->dbus;
while (!check_dbus_watches()) ;
if (connection)
{
dbus_connection_ref (connection);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,11 +20,11 @@
void dhcp_common_init(void)
{
/* These each hold a DHCP option max size 255
and get a terminating zero added */
daemon->dhcp_buff = safe_malloc(256);
daemon->dhcp_buff2 = safe_malloc(256);
daemon->dhcp_buff3 = safe_malloc(256);
/* These each hold a DHCP option max size 255
and get a terminating zero added */
daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ);
daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
/* dhcp_packet is used by v4 and v6, outpacket only by v6
sizeof(struct dhcp_packet) is as good an initial size as any,
@@ -38,7 +38,7 @@ void dhcp_common_init(void)
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
{
ssize_t sz;
ssize_t sz, new_sz;
while (1)
{
@@ -65,9 +65,48 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
}
}
while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
while ((new_sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
/* Some kernels seem to ignore MSG_PEEK, and dequeue the packet anyway.
If that happens we get EAGAIN here because the socket is non-blocking.
Use the result of the original testing recvmsg as long as the buffer
was big enough. There's a small race here that may lose the odd packet,
but it's UDP anyway. */
return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
if (new_sz == -1 && (errno == EWOULDBLOCK || errno == EAGAIN))
new_sz = sz;
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
}
/* like match_netid() except that the check can have a trailing * for wildcard */
/* started as a direct copy of match_netid() */
int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool)
{
struct dhcp_netid *tmp1;
for (; check; check = check->next)
{
const int check_len = strlen(check->net);
const int is_wc = (check_len > 0 && check->net[check_len - 1] == '*');
/* '#' for not is for backwards compat. */
if (check->net[0] != '!' && check->net[0] != '#')
{
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
if (is_wc ? (strncmp(check->net, tmp1->net, check_len-1) == 0) :
(strcmp(check->net, tmp1->net) == 0))
break;
if (!tmp1)
return 0;
}
else
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
if (is_wc ? (strncmp((check->net)+1, tmp1->net, check_len-2) == 0) :
(strcmp((check->net)+1, tmp1->net) == 0))
return 0;
}
return 1;
}
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
@@ -75,8 +114,11 @@ struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
struct tag_if *exprs;
struct dhcp_netid_list *list;
/* this now uses match_netid_wild() above so that tag_if can
* be used to set a 'group of interfaces' tag.
*/
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
if (match_netid(exprs->tag, tags, 1))
if (match_netid_wild(exprs->tag, tags))
for (list = exprs->set; list; list = list->next)
{
list->list->next = tags;
@@ -86,22 +128,41 @@ struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
return tags;
}
/* pxemode == 0 -> don't include dhcp-option-pxe options.
pxemode == 1 -> do include dhcp-option-pxe options.
pxemode == 2 -> include ONLY dhcp-option-pxe options. */
int pxe_ok(struct dhcp_opt *opt, int pxemode)
{
if (opt->flags & DHOPT_PXE_OPT)
{
if (pxemode != 0)
return 1;
}
else
{
if (pxemode != 2)
return 1;
}
return 0;
}
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags, struct dhcp_opt *opts)
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags, struct dhcp_opt *opts, int pxemode)
{
struct dhcp_netid *tagif = run_tag_if(tags);
struct dhcp_opt *opt;
struct dhcp_opt *tmp;
/* flag options which are valid with the current tag set (sans context tags) */
for (opt = opts; opt; opt = opt->next)
{
opt->flags &= ~DHOPT_TAGOK;
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
match_netid(opt->netid, tagif, 0))
match_netid(opt->netid, tagif, 0) &&
pxe_ok(opt, pxemode))
opt->flags |= DHOPT_TAGOK;
}
/* now flag options which are valid, including the context tags,
otherwise valid options are inhibited if we found a higher priority one above */
if (context_tags)
@@ -121,7 +182,8 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
match_netid(opt->netid, tagif, 0))
match_netid(opt->netid, tagif, 0) &&
pxe_ok(opt, pxemode))
{
struct dhcp_opt *tmp;
for (tmp = opts; tmp; tmp = tmp->next)
@@ -134,7 +196,9 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
/* now flag untagged options which are not overridden by tagged ones */
for (opt = opts; opt; opt = opt->next)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) && !opt->netid)
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
!opt->netid &&
pxe_ok(opt, pxemode))
{
for (tmp = opts; tmp; tmp = tmp->next)
if (tmp->opt == opt->opt && (tmp->flags & DHOPT_TAGOK))
@@ -144,7 +208,7 @@ struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *con
else if (!tmp->netid)
my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring duplicate dhcp-option %d"), tmp->opt);
}
/* Finally, eliminate duplicate options later in the chain, and therefore earlier in the config file. */
for (opt = opts; opt; opt = opt->next)
if (opt->flags & DHOPT_TAGOK)
@@ -276,30 +340,38 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
return 1;
#ifdef HAVE_DHCP6
if ((context->flags & CONTEXT_V6) && (config->flags & CONFIG_WILDCARD))
return 1;
#endif
if (context->flags & CONTEXT_V6)
{
struct addrlist *addr_list;
for (; context; context = context->current)
#ifdef HAVE_DHCP6
if (context->flags & CONTEXT_V6)
{
if ((config->flags & CONFIG_ADDR6) && is_same_net6(&config->addr6, &context->start6, context->prefix))
return 1;
}
else
if (config->flags & CONFIG_ADDR6)
for (; context; context = context->current)
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
{
if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64)
return 1;
if (is_same_net6(&addr_list->addr.addr6, &context->start6, context->prefix))
return 1;
}
}
else
#endif
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
return 1;
{
for (; context; context = context->current)
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
return 1;
}
return 0;
}
struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *clid, int clid_len,
unsigned char *hwaddr, int hw_len,
int hw_type, char *hostname)
static struct dhcp_config *find_config_match(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *clid, int clid_len,
unsigned char *hwaddr, int hw_len,
int hw_type, char *hostname,
struct dhcp_netid *tags, int tag_not_needed)
{
int count, new;
struct dhcp_config *config, *candidate;
@@ -311,7 +383,9 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
{
if (config->clid_len == clid_len &&
memcmp(config->clid, clid, clid_len) == 0 &&
is_config_in_context(context, config))
is_config_in_context(context, config) &&
match_netid(config->filter, tags, tag_not_needed))
return config;
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
@@ -319,7 +393,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
see lease_update_from_configs() */
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 &&
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
is_config_in_context(context, config))
is_config_in_context(context, config) &&
match_netid(config->filter, tags, tag_not_needed))
return config;
}
@@ -327,14 +402,16 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
if (hwaddr)
for (config = configs; config; config = config->next)
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
is_config_in_context(context, config))
is_config_in_context(context, config) &&
match_netid(config->filter, tags, tag_not_needed))
return config;
if (hostname && context)
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_NAME) &&
hostname_isequal(config->hostname, hostname) &&
is_config_in_context(context, config))
is_config_in_context(context, config) &&
match_netid(config->filter, tags, tag_not_needed))
return config;
@@ -343,7 +420,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
/* use match with fewest wildcard octets */
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
if (is_config_in_context(context, config))
if (is_config_in_context(context, config) &&
match_netid(config->filter, tags, tag_not_needed))
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
if (conf_addr->wildcard_mask != 0 &&
conf_addr->hwaddr_len == hw_len &&
@@ -357,6 +435,21 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
return candidate;
}
/* Find tagged configs first. */
struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *clid, int clid_len,
unsigned char *hwaddr, int hw_len,
int hw_type, char *hostname, struct dhcp_netid *tags)
{
struct dhcp_config *ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 0);
if (!ret)
ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 1);
return ret;
}
void dhcp_update_configs(struct dhcp_config *configs)
{
/* Some people like to keep all static IP addresses in /etc/hosts.
@@ -371,8 +464,14 @@ void dhcp_update_configs(struct dhcp_config *configs)
int prot = AF_INET;
for (config = configs; config; config = config->next)
{
if (config->flags & CONFIG_ADDR_HOSTS)
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR6 | CONFIG_ADDR_HOSTS);
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
#ifdef HAVE_DHCP6
if (config->flags & CONFIG_ADDR6_HOSTS)
config->flags &= ~(CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS);
#endif
}
#ifdef HAVE_DHCP6
again:
@@ -403,30 +502,41 @@ void dhcp_update_configs(struct dhcp_config *configs)
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
if (!crec)
continue; /* should be never */
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
inet_ntop(prot, &crec->addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
config->hostname, daemon->addrbuff);
}
if (prot == AF_INET &&
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr4)) || conf_tmp == config))
{
config->addr = crec->addr.addr.addr.addr4;
config->addr = crec->addr.addr4;
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
continue;
}
#ifdef HAVE_DHCP6
if (prot == AF_INET6 &&
(!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
(!(conf_tmp = config_find_by_address6(configs, NULL, 0, &crec->addr.addr6)) || conf_tmp == config))
{
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
/* host must have exactly one address if comming from /etc/hosts. */
if (!config->addr6 && (config->addr6 = whine_malloc(sizeof(struct addrlist))))
{
config->addr6->next = NULL;
config->addr6->flags = 0;
}
if (config->addr6 && !config->addr6->next && !(config->addr6->flags & (ADDRLIST_WILDCARD|ADDRLIST_PREFIX)))
{
memcpy(&config->addr6->addr.addr6, &crec->addr.addr6, IN6ADDRSZ);
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS;
}
continue;
}
#endif
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
inet_ntop(prot, &crec->addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
daemon->addrbuff, config->hostname);
@@ -465,11 +575,11 @@ char *whichdevice(void)
return NULL;
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*')))
if (if_tmp->name && (!(if_tmp->flags & INAME_USED) || strchr(if_tmp->name, '*')))
return NULL;
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
if (iface->dhcp_ok)
if (iface->dhcp4_ok || iface->dhcp6_ok)
{
if (!found)
found = iface;
@@ -478,20 +588,50 @@ char *whichdevice(void)
}
if (found)
return found->name;
{
char *ret = safe_malloc(strlen(found->name)+1);
strcpy(ret, found->name);
return ret;
}
return NULL;
}
void bindtodevice(char *device, int fd)
static int bindtodevice(char *device, int fd)
{
struct ifreq ifr;
strcpy(ifr.ifr_name, device);
size_t len = strlen(device)+1;
if (len > IFNAMSIZ)
len = IFNAMSIZ;
/* only allowed by root. */
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
errno != EPERM)
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
return 2;
return 1;
}
int bind_dhcp_devices(char *bound_device)
{
int ret = 0;
if (bound_device)
{
if (daemon->dhcp)
{
if (!daemon->relay4)
ret |= bindtodevice(bound_device, daemon->dhcpfd);
if (daemon->enable_pxe && daemon->pxefd != -1)
ret |= bindtodevice(bound_device, daemon->pxefd);
}
#if defined(HAVE_DHCP6)
if (daemon->doing_dhcp6 && !daemon->relay6)
ret |= bindtodevice(bound_device, daemon->dhcp6fd);
#endif
}
return ret;
}
#endif
@@ -545,8 +685,8 @@ static const struct opttab_t {
{ "parameter-request", 55, OT_INTERNAL },
{ "message", 56, OT_INTERNAL },
{ "max-message-size", 57, OT_INTERNAL },
{ "T1", 58, OT_INTERNAL | OT_TIME},
{ "T2", 59, OT_INTERNAL | OT_TIME},
{ "T1", 58, OT_TIME},
{ "T2", 59, OT_TIME},
{ "vendor-class", 60, 0 },
{ "client-id", 61, OT_INTERNAL },
{ "nis+-domain", 64, OT_NAME },
@@ -559,16 +699,24 @@ static const struct opttab_t {
{ "nntp-server", 71, OT_ADDR_LIST },
{ "irc-server", 74, OT_ADDR_LIST },
{ "user-class", 77, 0 },
{ "rapid-commit", 80, 0 },
{ "FQDN", 81, OT_INTERNAL },
{ "agent-id", 82, OT_INTERNAL },
{ "agent-info", 82, OT_INTERNAL },
{ "last-transaction", 91, 4 | OT_TIME },
{ "associated-ip", 92, OT_ADDR_LIST },
{ "client-arch", 93, 2 | OT_DEC },
{ "client-interface-id", 94, 0 },
{ "client-machine-id", 97, 0 },
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
{ "ipv6-only", 108, 4 | OT_DEC }, /* RFC 8925 */
{ "captive-portal", 114, OT_NAME }, /* RFC 8910 */
{ "subnet-select", 118, OT_INTERNAL },
{ "domain-search", 119, OT_RFC1035_NAME },
{ "sip-server", 120, 0 },
{ "classless-static-route", 121, 0 },
{ "vendor-id-encap", 125, 0 },
{ "tftp-server-address", 150, OT_ADDR_LIST },
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
{ NULL, 0, 0 }
};
@@ -599,9 +747,12 @@ static const struct opttab_t opttab6[] = {
{ "sntp-server", 31, OT_ADDR_LIST },
{ "information-refresh-time", 32, OT_TIME },
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
{ "ntp-server", 56, OT_ADDR_LIST },
{ "posix-timezone", 41, OT_NAME }, /* RFC 4833, Sec. 3 */
{ "tzdb-timezone", 42, OT_NAME }, /* RFC 4833, Sec. 3 */
{ "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ },
{ "bootfile-url", 59, OT_NAME },
{ "bootfile-param", 60, OT_CSTRING },
{ "captive-portal", 103, OT_NAME }, /* RFC 8910 */
{ NULL, 0, 0 }
};
#endif
@@ -692,7 +843,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
if (ot[o].size & OT_ADDR_LIST)
{
struct all_addr addr;
union all_addr addr;
int addr_len = INADDRSZ;
#ifdef HAVE_DHCP6
@@ -713,7 +864,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
{
char c = val[i];
if (isprint((int)c))
if (isprint((unsigned char)c))
buf[j++] = c;
}
#ifdef HAVE_DHCP6
@@ -727,7 +878,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
{
char c = val[k];
if (isprint((int)c))
if (isprint((unsigned char)c))
buf[j++] = c;
}
i = l;
@@ -748,7 +899,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
for (k = 0; k < len && j < buf_len; k++)
{
char c = *p++;
if (isprint((int)c))
if (isprint((unsigned char)c))
buf[j++] = c;
}
i += len +2;
@@ -855,14 +1006,14 @@ void log_context(int family, struct dhcp_context *context)
if (context->flags & CONTEXT_RA_STATELESS)
{
if (context->flags & CONTEXT_TEMPLATE)
strncpy(daemon->dhcp_buff, context->template_interface, 256);
strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
else
strcpy(daemon->dhcp_buff, daemon->addrbuff);
}
else
#endif
inet_ntop(family, start, daemon->dhcp_buff, 256);
inet_ntop(family, end, daemon->dhcp_buff3, 256);
inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
my_syslog(MS_DHCP | LOG_INFO,
(context->flags & CONTEXT_RA_STATELESS) ?
_("%s stateless on %s%.0s%.0s%s") :
@@ -893,12 +1044,37 @@ void log_context(int family, struct dhcp_context *context)
void log_relay(int family, struct dhcp_relay *relay)
{
int broadcast = relay->server.addr4.s_addr == 0;
inet_ntop(family, &relay->local, daemon->addrbuff, ADDRSTRLEN);
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
if (family == AF_INET && relay->port != DHCP_SERVER_PORT)
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
#ifdef HAVE_DHCP6
struct in6_addr multicast;
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
if (family == AF_INET6)
{
broadcast = IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast);
if (relay->port != DHCPV6_SERVER_PORT)
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
}
#endif
if (relay->interface)
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
else
{
if (broadcast)
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s via %s"), daemon->addrbuff, relay->interface);
else if (relay->split_mode)
my_syslog(MS_DHCP | LOG_INFO, _("DHCP split-relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
else
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
}
else
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff);
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +19,10 @@
#define DHCP_CLIENT_ALTPORT 1068
#define PXE_PORT 4011
/* These each hold a DHCP option max size 255
and get a terminating zero added */
#define DHCP_BUFF_SZ 256
#define BOOTREQUEST 1
#define BOOTREPLY 2
#define DHCP_COOKIE 0x63825363
@@ -50,8 +54,11 @@
#define OPTION_SNAME 66
#define OPTION_FILENAME 67
#define OPTION_USER_CLASS 77
#define OPTION_RAPID_COMMIT 80
#define OPTION_CLIENT_FQDN 81
#define OPTION_AGENT_ID 82
#define OPTION_LAST_TRANSACTION 91
#define OPTION_ASSOCIATED_IP 92
#define OPTION_ARCH 93
#define OPTION_PXE_UUID 97
#define OPTION_SUBNET_SELECT 118
@@ -59,12 +66,14 @@
#define OPTION_SIP_SERVER 120
#define OPTION_VENDOR_IDENT 124
#define OPTION_VENDOR_IDENT_OPT 125
#define OPTION_MUD_URL_V4 161
#define OPTION_END 255
#define SUBOPT_CIRCUIT_ID 1
#define SUBOPT_REMOTE_ID 2
#define SUBOPT_SUBNET_SELECT 5 /* RFC 3527 */
#define SUBOPT_SUBSCR_ID 6 /* RFC 3393 */
#define SUBOPT_FLAGS 10 /* RFC 5010 */
#define SUBOPT_SERVER_OR 11 /* RFC 5107 */
#define SUBOPT_PXE_BOOT_ITEM 71 /* PXE standard */
@@ -81,6 +90,11 @@
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8
#define DHCPFORCERENEW 9
#define DHCPLEASEQUERY 10
#define DHCPLEASEUNASSIGNED 11
#define DHCPLEASEUNKNOWN 12
#define DHCPLEASEACTIVE 13
#define BRDBAND_FORUM_IANA 3561 /* Broadband forum IANA enterprise */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,8 +20,6 @@
struct iface_param {
struct dhcp_context *current;
struct dhcp_relay *relay;
struct in_addr relay_local;
int ind;
};
@@ -34,8 +32,6 @@ static int complete_context(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam);
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam);
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index);
static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface);
static int make_fd(int port)
{
@@ -67,9 +63,9 @@ static int make_fd(int port)
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
/* When bind-interfaces is set, there might be more than one dnmsasq
/* When bind-interfaces is set, there might be more than one dnsmasq
instance binding port 67. That's OK if they serve different networks.
Need to set REUSEADDR|REUSEPORT to make this posible.
Need to set REUSEADDR|REUSEPORT to make this possible.
Handle the case that REUSEPORT is defined, but the kernel doesn't
support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -137,7 +133,7 @@ void dhcp_packet(time_t now, int pxe_fd)
struct dhcp_packet *mess;
struct dhcp_context *context;
struct dhcp_relay *relay;
int is_relay_reply = 0;
int is_relay_reply = 0, is_relay_use_source = 0;
struct iname *tmp;
struct ifreq ifr;
struct msghdr msg;
@@ -145,11 +141,15 @@ void dhcp_packet(time_t now, int pxe_fd)
struct cmsghdr *cmptr;
struct iovec iov;
ssize_t sz;
int iface_index = 0, unicast_dest = 0, is_inform = 0;
int iface_index = 0, unicast_dest = 0, is_inform = 0, loopback = 0;
int rcvd_iface_index, relay_index;
struct in_addr iface_addr;
struct iface_param parm;
time_t recvtime = now;
#ifdef HAVE_LINUX_NETWORK
struct arpreq arp_req;
struct timeval tv;
struct in_addr dst_addr;
#endif
union {
@@ -174,8 +174,13 @@ void dhcp_packet(time_t now, int pxe_fd)
if ((sz = recv_dhcp_packet(fd, &msg)) == -1 ||
(sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))))
return;
#if defined (HAVE_LINUX_NETWORK)
#if defined (HAVE_LINUX_NETWORK)
if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
recvtime = tv.tv_sec;
dst_addr.s_addr = 0;
if (msg.msg_controllen >= sizeof(struct cmsghdr))
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
@@ -186,7 +191,8 @@ void dhcp_packet(time_t now, int pxe_fd)
} p;
p.c = CMSG_DATA(cmptr);
iface_index = p.p->ipi_ifindex;
if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
dst_addr = p.p->ipi_addr;
if (dst_addr.s_addr != INADDR_BROADCAST)
unicast_dest = 1;
}
@@ -216,19 +222,57 @@ void dhcp_packet(time_t now, int pxe_fd)
iface_index = *(p.i);
}
#endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
return;
#ifdef HAVE_DUMPFILE
union mysockaddr *sockp = NULL;
# ifdef HAVE_LINUX_NETWORK
union mysockaddr tosock;
sockp = &tosock;
tosock.in.sin_port = htons(daemon->dhcp_server_port);
tosock.in.sin_addr = dst_addr;
tosock.sa.sa_family = AF_INET;
# ifdef HAVE_SOCKADDR_SA_LEN
tosock.in.sin_len = sizeof(struct sockaddr_in);
# endif
# endif
dump_packet_udp(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, sockp, -1);
#endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name) ||
ioctl(daemon->dhcpfd, SIOCGIFFLAGS, &ifr) != 0)
return;
mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
/* Non-standard extension:
If giaddr == 255.255.255.255 we reply to the source
address in the request packet header. This makes
stand-alone leasequery clients easier, as they
can leave source address determination to the kernel.
In this case, set a flag and clear giaddr here,
to avoid massive relay confusion. */
if (mess->giaddr.s_addr == INADDR_BROADCAST)
{
mess->giaddr.s_addr = 0;
is_relay_use_source = 1;
}
loopback = !mess->giaddr.s_addr && (ifr.ifr_flags & IFF_LOOPBACK);
#ifdef HAVE_LINUX_NETWORK
/* ARP fiddling uses original interface even if we pretend to use a different one. */
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
#endif
/* One form of bridging on BSD has the property that packets
can be recieved on bridge interfaces which do not have an IP address.
We allow these to be treated as aliases of another interface which does have
an IP address with --dhcp-bridge=interface,alias,alias */
/* If the interface on which the DHCP request was received is an
alias of some other interface (as specified by the
--bridge-interface option), change ifr.ifr_name so that we look
for DHCP contexts associated with the aliased interface instead
of with the aliasing one. */
rcvd_iface_index = iface_index;
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
@@ -236,12 +280,14 @@ void dhcp_packet(time_t now, int pxe_fd)
{
if (!(iface_index = if_nametoindex(bridge->iface)))
{
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);
my_syslog(MS_DHCP | LOG_WARNING,
_("unknown interface %s in bridge-interface"),
bridge->iface);
return;
}
else
{
strncpy(ifr.ifr_name, bridge->iface, IF_NAMESIZE);
safe_strncpy(ifr.ifr_name, bridge->iface, sizeof(ifr.ifr_name));
break;
}
}
@@ -256,16 +302,16 @@ void dhcp_packet(time_t now, int pxe_fd)
unicast_dest = 1;
#endif
if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
if ((relay_index = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, ifr.ifr_name)))
{
/* Reply from server, using us as relay. */
iface_index = relay->iface_index;
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
rcvd_iface_index = relay_index;
if (!indextoname(daemon->dhcpfd, rcvd_iface_index, ifr.ifr_name))
return;
is_relay_reply = 1;
iov.iov_len = sz;
#ifdef HAVE_LINUX_NETWORK
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
#endif
}
else
@@ -275,27 +321,26 @@ void dhcp_packet(time_t now, int pxe_fd)
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
else
{
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
if (iface_check(AF_INET, NULL, ifr.ifr_name, NULL))
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
return;
}
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
if (tmp->name && (tmp->flags & INAME_4) && wildcard_match(tmp->name, ifr.ifr_name))
return;
/* unlinked contexts/relays are marked by context->current == context */
/* unlinked contexts are marked by context->current == context */
for (context = daemon->dhcp; context; context = context->next)
context->current = context;
for (relay = daemon->relay4; relay; relay = relay->next)
relay->current = relay;
relay->matchcount = 0;
parm.current = NULL;
parm.relay = NULL;
parm.relay_local.s_addr = 0;
parm.ind = iface_index;
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL))
{
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
for a secondary */
@@ -305,7 +350,7 @@ void dhcp_packet(time_t now, int pxe_fd)
match.ind = iface_index;
if (!daemon->if_addrs ||
!iface_enumerate(AF_INET, &match, check_listen_addrs) ||
!iface_enumerate(AF_INET, &match, (callback_t){.af_inet=check_listen_addrs}) ||
!match.matched)
return;
@@ -314,29 +359,27 @@ void dhcp_packet(time_t now, int pxe_fd)
there is more than one address on the interface in the same subnet */
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
}
if (!iface_enumerate(AF_INET, &parm, complete_context))
return;
/* We're relaying this request */
if (parm.relay_local.s_addr != 0 &&
relay_upstream4(parm.relay, (struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, iface_index))
if (!iface_enumerate(AF_INET, &parm, (callback_t){.af_inet=complete_context}))
return;
relay_upstream4(iface_addr, iface_index, mess, (size_t)sz, unicast_dest);
/* May have configured relay, but not DHCP server */
if (!daemon->dhcp)
return;
lease_prune(NULL, now); /* lose any expired leases */
iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
now, unicast_dest, &is_inform, pxe_fd, iface_addr);
iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, now, unicast_dest,
loopback, &is_inform, pxe_fd, iface_addr, recvtime,
is_relay_use_source ? dest.sin_addr : mess->giaddr);
lease_update_file(now);
lease_update_dns(0);
if (iov.iov_len == 0)
return;
}
msg.msg_name = &dest;
msg.msg_namelen = sizeof(dest);
msg.msg_control = NULL;
@@ -356,11 +399,17 @@ void dhcp_packet(time_t now, int pxe_fd)
if (mess->ciaddr.s_addr != 0)
dest.sin_addr = mess->ciaddr;
}
else if (mess->giaddr.s_addr && !is_relay_reply)
if ((is_relay_use_source || mess->giaddr.s_addr) && !is_relay_reply)
{
/* Send to BOOTP relay */
dest.sin_port = htons(daemon->dhcp_server_port);
dest.sin_addr = mess->giaddr;
/* Send to BOOTP relay. */
if (is_relay_use_source)
/* restore as-received value */
mess->giaddr.s_addr = INADDR_BROADCAST;
else
{
dest.sin_addr = mess->giaddr;
dest.sin_port = htons(daemon->dhcp_server_port);
}
}
else if (mess->ciaddr.s_addr)
{
@@ -376,36 +425,46 @@ void dhcp_packet(time_t now, int pxe_fd)
}
}
#if defined(HAVE_LINUX_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
else
{
/* broadcast to 255.255.255.255 (or mac address invalid) */
/* fill cmsg for outbound interface (both broadcast & unicast) */
struct in_pktinfo *pkt;
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof(control_u);
/* alignment padding passed to the kernel should not be uninitialised. */
memset(&control_u, 0, sizeof(control_u));
cmptr = CMSG_FIRSTHDR(&msg);
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi_ifindex = iface_index;
pkt->ipi_ifindex = rcvd_iface_index;
pkt->ipi_spec_dst.s_addr = 0;
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_PKTINFO;
dest.sin_addr.s_addr = INADDR_BROADCAST;
dest.sin_port = htons(daemon->dhcp_client_port);
}
else
{
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
arp_req.arp_ha.sa_family = mess->htype;
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
/* interface name already copied in */
arp_req.arp_flags = ATF_COM;
if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
cmptr->cmsg_type = IP_PKTINFO;
if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
{
/* broadcast to 255.255.255.255 (or mac address invalid) */
dest.sin_addr.s_addr = INADDR_BROADCAST;
dest.sin_port = htons(daemon->dhcp_client_port);
}
else
{
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
arp_req.arp_ha.sa_family = mess->htype;
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
/* interface name already copied in */
arp_req.arp_flags = ATF_COM;
if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
}
}
#elif defined(HAVE_SOLARIS_NETWORK)
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
@@ -434,6 +493,17 @@ void dhcp_packet(time_t now, int pxe_fd)
#elif defined(HAVE_BSD_NETWORK)
else
{
#ifdef HAVE_DUMPFILE
if (ntohs(mess->flags) & 0x8000)
dest.sin_addr.s_addr = INADDR_BROADCAST;
else
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
(union mysockaddr *)&dest, fd);
#endif
send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
return;
}
@@ -442,10 +512,23 @@ void dhcp_packet(time_t now, int pxe_fd)
#ifdef HAVE_SOLARIS_NETWORK
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
#endif
#ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
(union mysockaddr *)&dest, fd);
#endif
while(sendmsg(fd, &msg, 0) == -1 && retry_send());
while(retry_send(sendmsg(fd, &msg, 0)));
/* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
if (errno != 0)
{
inet_ntop(AF_INET, &dest.sin_addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
daemon->addrbuff, strerror(errno));
}
}
/* check against secondary interface addresses */
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
@@ -480,7 +563,30 @@ static int check_listen_addrs(struct in_addr local, int if_index, char *label,
3) Fills in local (this host) and router (this host or relay) addresses.
4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
static void guess_range_netmask(struct in_addr addr, struct in_addr netmask)
{
struct dhcp_context *context;
for (context = daemon->dhcp; context; context = context->next)
if (!(context->flags & CONTEXT_NETMASK) &&
(is_same_net(addr, context->start, netmask) ||
is_same_net(addr, context->end, netmask)))
{
if (context->netmask.s_addr != netmask.s_addr &&
!(is_same_net(addr, context->start, netmask) &&
is_same_net(addr, context->end, netmask)))
{
inet_ntop(AF_INET, &context->start, daemon->dhcp_buff, DHCP_BUFF_SZ);
inet_ntop(AF_INET, &context->end, daemon->dhcp_buff2, DHCP_BUFF_SZ);
inet_ntop(AF_INET, &netmask, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, daemon->addrbuff);
}
context->netmask = netmask;
}
}
static int complete_context(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
@@ -488,27 +594,55 @@ static int complete_context(struct in_addr local, int if_index, char *label,
struct dhcp_context *context;
struct dhcp_relay *relay;
struct iface_param *param = vparam;
struct shared_network *share;
(void)label;
for (share = daemon->shared_networks; share; share = share->next)
{
#ifdef HAVE_DHCP6
if (share->shared_addr.s_addr == 0)
continue;
#endif
if (share->if_index != 0)
{
if (share->if_index != if_index)
continue;
}
else
{
if (share->match_addr.s_addr != local.s_addr)
continue;
}
for (context = daemon->dhcp; context; context = context->next)
{
if (context->netmask.s_addr != 0 &&
is_same_net(share->shared_addr, context->start, context->netmask) &&
is_same_net(share->shared_addr, context->end, context->netmask))
{
/* link it onto the current chain if we've not seen it before */
if (context->current == context)
{
/* For a shared network, we have no way to guess what the default route should be. */
context->router.s_addr = 0;
context->local = local; /* Use configured address for Server Identifier */
context->current = param->current;
param->current = context;
}
if (!(context->flags & CONTEXT_BRDCAST))
context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
}
}
}
guess_range_netmask(local, netmask);
for (context = daemon->dhcp; context; context = context->next)
{
if (!(context->flags & CONTEXT_NETMASK) &&
(is_same_net(local, context->start, netmask) ||
is_same_net(local, context->end, netmask)))
{
if (context->netmask.s_addr != netmask.s_addr &&
!(is_same_net(local, context->start, netmask) &&
is_same_net(local, context->end, netmask)))
{
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
}
context->netmask = netmask;
}
if (context->netmask.s_addr != 0 &&
is_same_net(local, context->start, context->netmask) &&
is_same_net(local, context->end, context->netmask))
@@ -533,14 +667,20 @@ static int complete_context(struct in_addr local, int if_index, char *label,
}
for (relay = daemon->relay4; relay; relay = relay->next)
if (if_index == param->ind && relay->local.addr.addr4.s_addr == local.s_addr && relay->current == relay &&
(param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr))
if (!relay->split_mode && relay->local.addr4.s_addr == local.s_addr)
{
relay->current = param->relay;
param->relay = relay;
param->relay_local = local;
if (if_index == param->ind)
relay->iface_index = if_index;
/* More than one interface with the relay address breaks things. */
if (relay->matchcount++ == 1 && !relay->warned)
{
relay->warned = 1;
inet_ntop(AF_INET, &local, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP relay address %s appears on more than one interface"), daemon->addrbuff);
}
}
return 1;
}
@@ -556,7 +696,7 @@ struct dhcp_context *address_available(struct dhcp_context *context,
struct dhcp_context *tmp;
for (tmp = context; tmp; tmp = tmp->current)
if (taddr.s_addr == context->router.s_addr)
if (taddr.s_addr == tmp->router.s_addr)
return NULL;
for (tmp = context; tmp; tmp = tmp->current)
@@ -580,7 +720,7 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
{
/* We start of with a set of possible contexts, all on the current physical interface.
These are chained on ->current.
Here we have an address, and return the actual context correponding to that
Here we have an address, and return the actual context corresponding to that
address. Note that none may fit, if the address came a dhcp-host and is outside
any dhcp-range. In that case we return a static range if possible, or failing that,
any context on the correct subnet. (If there's more than one, this is a dodgy
@@ -622,9 +762,69 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
return NULL;
}
/* Check if and address is in use by sending ICMP ping.
This wrapper handles a cache and load-limiting.
Return is NULL is address in use, or a pointer to a cache entry
recording that it isn't. */
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash, int loopback)
{
static struct ping_result dummy;
struct ping_result *r, *victim = NULL;
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
((float)PING_WAIT)));
/* check if we failed to ping addr sometime in the last
PING_CACHE_TIME seconds. If so, assume the same situation still exists.
This avoids problems when a stupid client bangs
on us repeatedly. As a final check, if we did more
than 60% of the possible ping checks in the last
PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
for (count = 0, r = daemon->ping_results; r; r = r->next)
if (difftime(now, r->time) > (float)PING_CACHE_TIME)
victim = r; /* old record */
else
{
count++;
if (r->addr.s_addr == addr.s_addr)
return r;
}
/* didn't find cached entry */
if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
{
/* overloaded, or configured not to check, loopback interface, return "not in use" */
dummy.hash = hash;
return &dummy;
}
else if (icmp_ping(addr))
return NULL; /* address in use. */
else
{
/* at this point victim may hold an expired record */
if (!victim)
{
if ((victim = whine_malloc(sizeof(struct ping_result))))
{
victim->next = daemon->ping_results;
daemon->ping_results = victim;
}
}
/* record that this address is OK for 30s
without more ping checks */
if (victim)
{
victim->addr = addr;
victim->time = now;
victim->hash = hash;
}
return victim;
}
}
int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now)
struct dhcp_netid *netids, time_t now, int loopback)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -638,7 +838,11 @@ int address_allocate(struct dhcp_context *context,
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
dispersal even with similarly-valued "strings". */
for (j = 0, i = 0; i < hw_len; i++)
j += hwaddr[i] + (j << 6) + (j << 16) - j;
j = hwaddr[i] + (j << 6) + (j << 16) - j;
/* j == 0 is marker */
if (j == 0)
j = 1;
for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current)
@@ -676,69 +880,36 @@ int address_allocate(struct dhcp_context *context,
(!IN_CLASSC(ntohl(addr.s_addr)) ||
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
{
struct ping_result *r, *victim = NULL;
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
((float)PING_WAIT)));
*addrp = addr;
/* check if we failed to ping addr sometime in the last
PING_CACHE_TIME seconds. If so, assume the same situation still exists.
This avoids problems when a stupid client bangs
on us repeatedly. As a final check, if we did more
than 60% of the possible ping checks in the last
PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
for (count = 0, r = daemon->ping_results; r; r = r->next)
if (difftime(now, r->time) > (float)PING_CACHE_TIME)
victim = r; /* old record */
else
{
count++;
if (r->addr.s_addr == addr.s_addr)
{
/* consec-ip mode: we offered this address for another client
(different hash) recently, don't offer it to this one. */
if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
break;
return 1;
}
}
if (!r)
/* in consec-ip mode, skip addresses equal to
the number of addresses rejected by clients. This
should avoid the same client being offered the same
address after it has rjected it. */
if (option_bool(OPT_CONSEC_ADDR) && c->addr_epoch)
c->addr_epoch--;
else
{
if ((count < max) && !option_bool(OPT_NO_PING) && icmp_ping(addr))
struct ping_result *r;
if ((r = do_icmp_ping(now, addr, j, loopback)))
{
/* consec-ip mode: we offered this address for another client
(different hash) recently, don't offer it to this one. */
if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
{
*addrp = addr;
return 1;
}
}
else
{
/* address in use: perturb address selection so that we are
less likely to try this address again. */
if (!option_bool(OPT_CONSEC_ADDR))
c->addr_epoch++;
}
else
{
/* at this point victim may hold an expired record */
if (!victim)
{
if ((victim = whine_malloc(sizeof(struct ping_result))))
{
victim->next = daemon->ping_results;
daemon->ping_results = victim;
}
}
/* record that this address is OK for 30s
without more ping checks */
if (victim)
{
victim->addr = addr;
victim->time = now;
victim->hash = j;
}
return 1;
}
}
}
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
@@ -793,14 +964,14 @@ void dhcp_read_ethers(void)
lineno++;
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
while (strlen(buff) > 0 && isspace((unsigned char)buff[strlen(buff)-1]))
buff[strlen(buff)-1] = 0;
if ((*buff == '#') || (*buff == '+') || (*buff == 0))
continue;
for (ip = buff; *ip && !isspace((int)*ip); ip++);
for(; *ip && isspace((int)*ip); ip++)
for (ip = buff; *ip && !isspace((unsigned char)*ip); ip++);
for(; *ip && isspace((unsigned char)*ip); ip++)
*ip = 0;
if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
{
@@ -815,7 +986,7 @@ void dhcp_read_ethers(void)
if (!*cp)
{
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
if (inet_pton(AF_INET, ip, &addr.s_addr) < 1)
{
my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
continue;
@@ -924,7 +1095,7 @@ char *host_from_dns(struct in_addr addr)
if (daemon->port == 0)
return NULL; /* DNS disabled. */
lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
lookup = cache_find_by_addr(NULL, (union all_addr *)&addr, 0, F_IPV4);
if (lookup && (lookup->flags & F_HOSTS))
{
@@ -941,8 +1112,7 @@ char *host_from_dns(struct in_addr addr)
if (!legal_hostname(hostname))
return NULL;
strncpy(daemon->dhcp_buff, hostname, 256);
daemon->dhcp_buff[255] = 0;
safe_strncpy(daemon->dhcp_buff, hostname, 256);
strip_hostname(daemon->dhcp_buff);
return daemon->dhcp_buff;
@@ -951,74 +1121,4 @@ char *host_from_dns(struct in_addr addr)
return NULL;
}
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index)
{
/* ->local is same value for all relays on ->current chain */
struct all_addr from;
if (mess->op != BOOTREQUEST)
return 0;
/* source address == relay address */
from.addr.addr4 = relay->local.addr.addr4;
/* already gatewayed ? */
if (mess->giaddr.s_addr)
{
/* if so check if by us, to stomp on loops. */
if (mess->giaddr.s_addr == relay->local.addr.addr4.s_addr)
return 1;
}
else
{
/* plug in our address */
mess->giaddr.s_addr = relay->local.addr.addr4.s_addr;
}
if ((mess->hops++) > 20)
return 1;
for (; relay; relay = relay->current)
{
union mysockaddr to;
to.sa.sa_family = AF_INET;
to.in.sin_addr = relay->server.addr.addr4;
to.in.sin_port = htons(daemon->dhcp_server_port);
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
if (option_bool(OPT_LOG_OPTS))
{
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, inet_ntoa(relay->server.addr.addr4));
}
/* Save this for replies */
relay->iface_index = iface_index;
}
return 1;
}
static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface)
{
struct dhcp_relay *relay;
if (mess->giaddr.s_addr == 0 || mess->op != BOOTREPLY)
return NULL;
for (relay = daemon->relay4; relay; relay = relay->next)
{
if (mess->giaddr.s_addr == relay->local.addr.addr4.s_addr)
{
if (!relay->interface || wildcard_match(relay->interface, arrival_interface))
return relay->iface_index != 0 ? relay : NULL;
}
}
return NULL;
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -55,16 +55,19 @@
#define OPTION6_RECONF_ACCEPT 20
#define OPTION6_DNS_SERVER 23
#define OPTION6_DOMAIN_SEARCH 24
#define OPTION6_IA_PD 25
#define OPTION6_IAPREFIX 26
#define OPTION6_REFRESH_TIME 32
#define OPTION6_REMOTE_ID 37
#define OPTION6_SUBSCRIBER_ID 38
#define OPTION6_FQDN 39
#define OPTION6_NTP_SERVER 56
#define OPTION6_CLIENT_MAC 79
#define OPTION6_MUD_URL 112
/* replace this with the real number when allocated.
defining this also enables the relevant code. */
/* #define OPTION6_PREFIX_CLASS 99 */
#define NTP_SUBOPTION_SRV_ADDR 1
#define NTP_SUBOPTION_MC_ADDR 2
#define NTP_SUBOPTION_SRV_FQDN 3
#define DHCP6SUCCESS 0
#define DHCP6UNSPEC 1
@@ -72,4 +75,3 @@
#define DHCP6NOBINDING 3
#define DHCP6NOTONLINK 4
#define DHCP6USEMULTI 5

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,22 +22,14 @@
struct iface_param {
struct dhcp_context *current;
struct dhcp_relay *relay;
struct in6_addr fallback, relay_local, ll_addr, ula_addr;
struct in6_addr fallback, ll_addr, ula_addr;
int ind, addr_match;
};
struct mac_param {
struct in6_addr *target;
unsigned char *mac;
unsigned int maclen;
};
static int complete_context6(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
unsigned int preferred, unsigned int valid, void *vparam);
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv);
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
void dhcp6_init(void)
@@ -58,9 +50,9 @@ void dhcp6_init(void)
!set_ipv6pktinfo(fd))
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
/* When bind-interfaces is set, there might be more than one dnmsasq
/* When bind-interfaces is set, there might be more than one dnsmasq
instance binding port 547. That's OK if they serve different networks.
Need to set REUSEADDR|REUSEPORT to make this posible.
Need to set REUSEADDR|REUSEPORT to make this possible.
Handle the case that REUSEPORT is defined, but the kernel doesn't
support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
@@ -101,7 +93,7 @@ void dhcp6_packet(time_t now)
struct iface_param parm;
struct cmsghdr *cmptr;
struct msghdr msg;
int if_index = 0;
uint32_t if_index = 0;
union {
struct cmsghdr align; /* this ensures alignment */
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
@@ -112,7 +104,8 @@ void dhcp6_packet(time_t now)
struct iname *tmp;
unsigned short port;
struct in6_addr dst_addr;
struct in6_addr all_servers;
memset(&dst_addr, 0, sizeof(dst_addr));
msg.msg_control = control_u.control6;
@@ -141,26 +134,91 @@ void dhcp6_packet(time_t now)
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
return;
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
#ifdef HAVE_LINUX_NETWORK
/* This works around a possible Linux kernel bug when using interfaces
enslaved to a VRF. The scope_id in the source address gets set
to the index of the VRF interface, not the slave. Fortunately,
the interface index returned by packetinfo is correct so we use
that instead. Log this once, so if it triggers in other circumstances
we've not anticipated and breaks things, we get some clues. */
if (from.sin6_scope_id != if_index)
{
static int logged = 0;
if (!logged)
{
my_syslog(MS_DHCP | LOG_WARNING,
_("Working around kernel bug: faulty source address scope for VRF slave %s"),
ifr.ifr_name);
logged = 1;
}
from.sin6_scope_id = if_index;
}
#endif
#ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
#endif
if (relay_reply6(&from, sz, ifr.ifr_name))
{
#ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
(union mysockaddr *)&from, daemon->dhcp6fd);
#endif
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
save_counter(-1), 0, (struct sockaddr *)&from,
sizeof(from))));
}
else
{
struct dhcp_bridge *bridge, *alias;
int multicast_dest = 0;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
if (tmp->name && (tmp->flags & INAME_6) &&
wildcard_match(tmp->name, ifr.ifr_name))
return;
parm.current = NULL;
parm.relay = NULL;
memset(&parm.relay_local, 0, IN6ADDRSZ);
parm.ind = if_index;
parm.addr_match = 0;
memset(&parm.fallback, 0, IN6ADDRSZ);
memset(&parm.ll_addr, 0, IN6ADDRSZ);
memset(&parm.ula_addr, 0, IN6ADDRSZ);
/* If the interface on which the DHCPv6 request was received is
an alias of some other interface (as specified by the
--bridge-interface option), change parm.ind so that we look
for DHCPv6 contexts associated with the aliased interface
instead of with the aliasing one. */
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
{
parm.ind = if_nametoindex(bridge->iface);
if (!parm.ind)
{
my_syslog(MS_DHCP | LOG_WARNING,
_("unknown interface %s in bridge-interface"),
bridge->iface);
return;
}
break;
}
if (alias)
break;
}
for (context = daemon->dhcp6; context; context = context->next)
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
{
@@ -176,11 +234,33 @@ void dhcp6_packet(time_t now)
}
for (relay = daemon->relay6; relay; relay = relay->next)
relay->current = relay;
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
return;
relay->matchcount = 0;
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &all_servers);
if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
multicast_dest = 1;
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
if (IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
multicast_dest = 1;
else
{
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
we're listening there for DHCPv6 server reasons. */
if (relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
return;
}
if (!iface_enumerate(AF_INET6, &parm, (callback_t){.af_inet6=complete_context6}))
return;
/* Check for a relay again after iface_enumerate/complete_context has had
chance to fill in relay->iface_index fields. This handles first time through
and any changes in interface config. */
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
return;
if (daemon->if_names || daemon->if_addrs)
{
@@ -192,217 +272,225 @@ void dhcp6_packet(time_t now)
return;
}
if (parm.relay)
{
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
we're listening there for DHCPv6 server reasons. */
struct in6_addr all_servers;
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id);
return;
}
/* May have configured relay, but not DHCP server */
if (!daemon->doing_dhcp6)
return;
lease_prune(NULL, now); /* lose any expired leases */
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
port = dhcp6_reply(parm.current, multicast_dest, if_index, ifr.ifr_name, &parm.fallback,
&parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
/* The port in the source address of the original request should
be correct, but at least once client sends from the server port,
so we explicitly send to the client port to a client, and the
server port to a relay. */
if (port != 0)
{
from.sin6_port = htons(port);
#ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
NULL, (union mysockaddr *)&from, daemon->dhcp6fd);
#endif
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from))));
}
/* These need to be called _after_ we send DHCPv6 packet, since lease_update_file()
may trigger sending an RA packet, which overwrites our buffer. */
lease_update_file(now);
lease_update_dns(0);
}
/* The port in the source address of the original request should
be correct, but at least once client sends from the server port,
so we explicitly send to the client port to a client, and the
server port to a relay. */
if (port != 0)
{
from.sin6_port = htons(port);
while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0),
0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
retry_send());
}
}
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep)
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
{
/* Recieving a packet from a host does not populate the neighbour
/* Receiving a packet from a host does not populate the neighbour
cache, so we send a neighbour discovery request if we can't
find the sender. Repeat a few times in case of packet loss. */
struct neigh_packet neigh;
struct sockaddr_in6 addr;
struct mac_param mac_param;
int i;
union mysockaddr addr;
int i, maclen;
neigh.type = ND_NEIGHBOR_SOLICIT;
neigh.code = 0;
neigh.reserved = 0;
neigh.target = *client;
/* RFC4443 section-2.3: checksum has to be zero to be calculated */
neigh.checksum = 0;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.sin6_len = sizeof(struct sockaddr_in6);
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = *client;
addr.sin6_scope_id = iface;
mac_param.target = client;
mac_param.maclen = 0;
mac_param.mac = mac;
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_port = htons(IPPROTO_ICMPV6);
addr.in6.sin6_addr = *client;
addr.in6.sin6_scope_id = iface;
for (i = 0; i < 5; i++)
{
struct timespec ts;
iface_enumerate(AF_UNSPEC, &mac_param, find_mac);
if (mac_param.maclen != 0)
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
break;
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, (struct sockaddr *)&addr, sizeof(addr));
while(retry_send(sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr))));
ts.tv_sec = 0;
ts.tv_nsec = 100000000; /* 100ms */
nanosleep(&ts, NULL);
}
*maclenp = mac_param.maclen;
*maclenp = maclen;
*mactypep = ARPHRD_ETHER;
}
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
{
struct mac_param *parm = parmv;
if (family == AF_INET6 && IN6_ARE_ADDR_EQUAL(parm->target, (struct in6_addr *)addrp))
{
if (maclen <= DHCP_CHADDR_MAX)
{
parm->maclen = maclen;
memcpy(parm->mac, mac, maclen);
}
return 0; /* found, abort */
}
return 1;
}
static int complete_context6(struct in6_addr *local, int prefix,
int scope, int if_index, int flags, unsigned int preferred,
unsigned int valid, void *vparam)
{
struct dhcp_context *context;
struct shared_network *share;
struct dhcp_relay *relay;
struct iface_param *param = vparam;
struct iname *tmp;
int match = !daemon->if_addrs;
(void)scope; /* warning */
if (if_index == param->ind)
{
if (IN6_IS_ADDR_LINKLOCAL(local))
param->ll_addr = *local;
else if (IN6_IS_ADDR_ULA(local))
param->ula_addr = *local;
if (!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_LINKLOCAL(local) &&
!IN6_IS_ADDR_MULTICAST(local))
if (if_index != param->ind)
return 1;
if (IN6_IS_ADDR_LINKLOCAL(local))
param->ll_addr = *local;
else if (IN6_IS_ADDR_ULA(local))
param->ula_addr = *local;
if (IN6_IS_ADDR_LOOPBACK(local) ||
IN6_IS_ADDR_LINKLOCAL(local) ||
IN6_IS_ADDR_MULTICAST(local))
return 1;
/* if we have --listen-address config, see if the
arrival interface has a matching address. */
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (tmp->addr.sa.sa_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
match = param->addr_match = 1;
/* Determine a globally address on the arrival interface, even
if we have no matching dhcp-context, because we're only
allocating on remote subnets via relays. This
is used as a default for the DNS server option. */
param->fallback = *local;
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_DHCP) &&
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix <= context->prefix &&
context->current == context)
{
if (is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
struct dhcp_context *tmp, **up;
/* use interface values only for constructed contexts */
if (!(context->flags & CONTEXT_CONSTRUCTED))
preferred = valid = 0xffffffff;
else if (flags & IFACE_DEPRECATED)
preferred = 0;
if (context->flags & CONTEXT_DEPRECATE)
preferred = 0;
/* order chain, longest preferred time first */
for (up = &param->current, tmp = param->current; tmp; tmp = tmp->current)
if (tmp->preferred <= preferred)
break;
else
up = &tmp->current;
context->current = *up;
*up = context;
context->local6 = *local;
context->preferred = preferred;
context->valid = valid;
}
else
{
for (share = daemon->shared_networks; share; share = share->next)
{
/* IPv4 shared_address - ignore */
if (share->shared_addr.s_addr != 0)
continue;
if (share->if_index != 0)
{
if (share->if_index != if_index)
continue;
}
else
{
if (!IN6_ARE_ADDR_EQUAL(&share->match_addr6, local))
continue;
}
if (is_same_net6(&share->shared_addr6, &context->start6, context->prefix) &&
is_same_net6(&share->shared_addr6, &context->end6, context->prefix))
{
context->current = param->current;
param->current = context;
context->local6 = *local;
context->preferred = context->flags & CONTEXT_DEPRECATE ? 0 :0xffffffff;
context->valid = 0xffffffff;
}
}
}
}
if (match)
for (relay = daemon->relay6; relay; relay = relay->next)
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6))
{
/* if we have --listen-address config, see if the
arrival interface has a matching address. */
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (tmp->addr.sa.sa_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
param->addr_match = 1;
/* Determine a globally address on the arrival interface, even
if we have no matching dhcp-context, because we're only
allocating on remote subnets via relays. This
is used as a default for the DNS server option. */
param->fallback = *local;
for (context = daemon->dhcp6; context; context = context->next)
relay->iface_index = if_index;
/* More than one interface with the relay address breaks things. */
if (relay->matchcount++ == 1 && !relay->warned)
{
if ((context->flags & CONTEXT_DHCP) &&
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
/* link it onto the current chain if we've not seen it before */
if (context->current == context)
{
struct dhcp_context *tmp, **up;
/* use interface values only for contructed contexts */
if (!(context->flags & CONTEXT_CONSTRUCTED))
preferred = valid = 0xffffffff;
else if (flags & IFACE_DEPRECATED)
preferred = 0;
if (context->flags & CONTEXT_DEPRECATE)
preferred = 0;
/* order chain, longest preferred time first */
for (up = &param->current, tmp = param->current; tmp; tmp = tmp->current)
if (tmp->preferred <= preferred)
break;
else
up = &tmp->current;
context->current = *up;
*up = context;
context->local6 = *local;
context->preferred = preferred;
context->valid = valid;
}
}
relay->warned = 1;
inet_ntop(AF_INET6, &local, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP relay address %s appears on more than one interface"), daemon->addrbuff);
}
}
for (relay = daemon->relay6; relay; relay = relay->next)
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr.addr6) && relay->current == relay &&
(IN6_IS_ADDR_UNSPECIFIED(&param->relay_local) || IN6_ARE_ADDR_EQUAL(local, &param->relay_local)))
{
relay->current = param->relay;
param->relay = relay;
param->relay_local = *local;
}
}
return 1;
return 1;
}
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, u64 addr)
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, struct in6_addr *addr)
{
struct dhcp_config *config;
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_ADDR6) &&
is_same_net6(&config->addr6, net, prefix) &&
(prefix == 128 || addr6part(&config->addr6) == addr))
return config;
if (config->flags & CONFIG_ADDR6)
{
struct addrlist *addr_list;
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
if ((!net || is_same_net6(&addr_list->addr.addr6, net, prefix) || ((addr_list->flags & ADDRLIST_WILDCARD) && prefix == 64)) &&
is_same_net6(&addr_list->addr.addr6, addr, (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128))
return config;
}
return NULL;
}
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
unsigned int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -424,7 +512,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
j = rand64();
else
for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j;
j = clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
for (c = context; c; c = c->current)
@@ -435,10 +523,26 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
else
{
if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
/* seed is largest extant lease addr in this context */
start = lease_find_max_addr6(c) + serial;
{
/* seed is largest extant lease addr in this context,
skip addresses equal to the number of addresses rejected
by clients. This should avoid the same client being offered the same
address after it has rjected it. */
start = lease_find_max_addr6(c) + 1 + serial + c->addr_epoch;
if (c->addr_epoch)
c->addr_epoch--;
}
else
start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
{
u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
u64 offset = j + c->addr_epoch;
/* don't divide by zero if range is whole 2^64 */
if (range != 0)
offset = offset % range;
start = addr6part(&c->start6) + offset;
}
/* iterate until we find a free address. */
addr = start;
@@ -448,16 +552,15 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
for (d = context; d; d = d->current)
if (addr == addr6part(&d->local6))
break;
*ans = c->start6;
setaddr6part (ans, addr);
if (!d &&
!lease6_find_by_addr(&c->start6, c->prefix, addr) &&
!config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, addr))
{
*ans = c->start6;
setaddr6part (ans, addr);
return c;
}
!config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, ans))
return c;
addr++;
if (addr == addr6part(&c->end6) + 1)
@@ -511,27 +614,6 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
return NULL;
}
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
{
if (!config || !(config->flags & CONFIG_ADDR6))
return 0;
if ((config->flags & CONFIG_WILDCARD) && context->prefix == 64)
{
*addr = context->start6;
setaddr6part(addr, addr6part(&config->addr6));
return 1;
}
if (is_same_net6(&context->start6, &config->addr6, context->prefix))
{
*addr = config->addr6;
return 1;
}
return 0;
}
void make_duid(time_t now)
{
(void)now;
@@ -557,7 +639,7 @@ void make_duid(time_t now)
newnow = now - 946684800;
#endif
iface_enumerate(AF_LOCAL, &newnow, make_duid1);
iface_enumerate(AF_LOCAL, &newnow, (callback_t){.af_local=make_duid1});
if(!daemon->duid)
die("Cannot create DHCPv6 server DUID: %s", NULL, EC_MISC);
@@ -607,12 +689,13 @@ struct cparam {
static int construct_worker(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
int preferred, int valid, void *vparam)
unsigned int preferred, unsigned int valid, void *vparam)
{
char ifrn_name[IFNAMSIZ];
struct in6_addr start6, end6;
struct dhcp_context *template, *context;
struct iname *tmp;
(void)scope;
(void)flags;
(void)valid;
@@ -631,17 +714,30 @@ static int construct_worker(struct in6_addr *local, int prefix,
if (flags & IFACE_DEPRECATED)
return 1;
if (!indextoname(daemon->icmp6fd, if_index, ifrn_name))
return 0;
/* Ignore interfaces where we're not doing RA/DHCP6 */
if (!indextoname(daemon->icmp6fd, if_index, ifrn_name) ||
!iface_check(AF_LOCAL, NULL, ifrn_name, NULL))
return 1;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifrn_name))
return 1;
for (template = daemon->dhcp6; template; template = template->next)
if (!(template->flags & CONTEXT_TEMPLATE))
if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
{
/* non-template entries, just fill in interface and local addresses */
if (prefix <= template->prefix &&
is_same_net6(local, &template->start6, template->prefix) &&
is_same_net6(local, &template->end6, template->prefix))
{
/* First time found, do fast RA. */
if (template->if_index == 0)
{
ra_start_unsolicited(param->now, template);
param->newone = 1;
}
template->if_index = if_index;
template->local6 = *local;
}
@@ -656,24 +752,33 @@ static int construct_worker(struct in6_addr *local, int prefix,
setaddr6part(&end6, addr6part(&template->end6));
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_CONSTRUCTED) &&
if (!(context->flags & CONTEXT_TEMPLATE) &&
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
{
int flags = context->flags;
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
if (flags & CONTEXT_OLD)
/* If there's an absolute address context covering this address
then don't construct one as well. */
if (!(context->flags & CONTEXT_CONSTRUCTED))
break;
if (context->if_index == if_index)
{
/* address went, now it's back */
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicted(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;
int cflags = context->flags;
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
if (cflags & CONTEXT_OLD)
{
/* address went, now it's back, and on the same interface */
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicited(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;
}
break;
}
break;
}
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
@@ -690,7 +795,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
context->next = daemon->dhcp6;
daemon->dhcp6 = context;
ra_start_unsolicted(param->now, context);
ra_start_unsolicited(param->now, context);
/* we created a new one, need to call
lease_update_file to get periodic functions called */
param->newone = 1;
@@ -718,7 +823,7 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_CONSTRUCTED)
context->flags |= CONTEXT_GC;
iface_enumerate(AF_INET6, &param, construct_worker);
iface_enumerate(AF_INET6, &param, (callback_t){.af_inet6=construct_worker});
for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
{
@@ -729,7 +834,7 @@ void dhcp_construct_contexts(time_t now)
{
if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
{
/* previously constructed context has gone. advertise it's demise */
/* previously constructed context has gone; advertise its demise */
context->flags |= CONTEXT_OLD;
context->address_lost_time = now;
/* Apply same ceiling of configured lease time as in radv.c */
@@ -738,7 +843,7 @@ void dhcp_construct_contexts(time_t now)
/* maximum time is 2 hours, from RFC */
if (context->saved_valid > 7200) /* 2 hours */
context->saved_valid = 7200;
ra_start_unsolicted(now, context);
ra_start_unsolicited(now, context);
param.newone = 1; /* include deletion */
if (context->flags & CONTEXT_RA_NAME)
@@ -773,6 +878,4 @@ void dhcp_construct_contexts(time_t now)
}
}
#endif
#endif /* HAVE_DHCP6 */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,6 +16,8 @@
#define NAMESERVER_PORT 53
#define TFTP_PORT 69
#define MIN_PORT 1024 /* first non-reserved port */
#define MAX_PORT 65535u
#define IN6ADDRSZ 16
#define INADDRSZ 4
@@ -74,9 +76,48 @@
#define T_AXFR 252
#define T_MAILB 253
#define T_ANY 255
#define T_CAA 257
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
#define EDNS0_OPTION_EDE 15 /* IANA - RFC 8914 */
#define EDNS0_OPTION_NOMDEVICEID 65073 /* Nominum temporary assignment */
#define EDNS0_OPTION_NOMCPEID 65074 /* Nominum temporary assignment */
#define EDNS0_OPTION_UMBRELLA 20292 /* Cisco Umbrella temporary assignment */
/* RFC-8914 extended errors, negative values are our definitions */
#define EDE_UNSET -1 /* No extended DNS error available */
#define EDE_OTHER 0 /* Other */
#define EDE_USUPDNSKEY 1 /* Unsupported DNSKEY algo */
#define EDE_USUPDS 2 /* Unsupported DS Digest */
#define EDE_STALE 3 /* Stale answer */
#define EDE_FORGED 4 /* Forged answer */
#define EDE_DNSSEC_IND 5 /* DNSSEC Indeterminate */
#define EDE_DNSSEC_BOGUS 6 /* DNSSEC Bogus */
#define EDE_SIG_EXP 7 /* Signature Expired */
#define EDE_SIG_NYV 8 /* Signature Not Yet Valid */
#define EDE_NO_DNSKEY 9 /* DNSKEY missing */
#define EDE_NO_RRSIG 10 /* RRSIGs missing */
#define EDE_NO_ZONEKEY 11 /* No Zone Key Bit Set */
#define EDE_NO_NSEC 12 /* NSEC Missing */
#define EDE_CACHED_ERR 13 /* Cached Error */
#define EDE_NOT_READY 14 /* Not Ready */
#define EDE_BLOCKED 15 /* Blocked */
#define EDE_CENSORED 16 /* Censored */
#define EDE_FILTERED 17 /* Filtered */
#define EDE_PROHIBITED 18 /* Prohibited */
#define EDE_STALE_NXD 19 /* Stale NXDOMAIN */
#define EDE_NOT_AUTH 20 /* Not Authoritative */
#define EDE_NOT_SUP 21 /* Not Supported */
#define EDE_NO_AUTH 22 /* No Reachable Authority */
#define EDE_NETERR 23 /* Network error */
#define EDE_INVALID_DATA 24 /* Invalid Data */
#define EDE_SIG_E_B_V 25 /* Signature Expired before Valid */
#define EDE_TOO_EARLY 26 /* To Early */
#define EDE_UNS_NS3_ITER 27 /* Unsupported NSEC3 Iterations Value */
#define EDE_UNABLE_POLICY 28 /* Unable to conform to policy */
#define EDE_SYNTHESIZED 29 /* Synthesized */
struct dns_header {
u16 id;
@@ -84,15 +125,15 @@ struct dns_header {
u16 qdcount,ancount,nscount,arcount;
};
#define HB3_QR 0x80
#define HB3_QR 0x80 /* Query */
#define HB3_OPCODE 0x78
#define HB3_AA 0x04
#define HB3_TC 0x02
#define HB3_RD 0x01
#define HB3_AA 0x04 /* Authoritative Answer */
#define HB3_TC 0x02 /* TrunCated */
#define HB3_RD 0x01 /* Recursion Desired */
#define HB4_RA 0x80
#define HB4_AD 0x20
#define HB4_CD 0x10
#define HB4_RA 0x80 /* Recursion Available */
#define HB4_AD 0x20 /* Authenticated Data */
#define HB4_CD 0x10 /* Checking Disabled */
#define HB4_RCODE 0x0f
#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3)
@@ -101,15 +142,15 @@ struct dns_header {
#define RCODE(x) ((x)->hb4 & HB4_RCODE)
#define SET_RCODE(x, code) (x)->hb4 = ((x)->hb4 & ~HB4_RCODE) | code
#define GETSHORT(s, cp) { \
#define GETSHORT(s, cp) do { \
unsigned char *t_cp = (unsigned char *)(cp); \
(s) = ((u16)t_cp[0] << 8) \
| ((u16)t_cp[1]) \
; \
(cp) += 2; \
}
} while(0)
#define GETLONG(l, cp) { \
#define GETLONG(l, cp) do { \
unsigned char *t_cp = (unsigned char *)(cp); \
(l) = ((u32)t_cp[0] << 24) \
| ((u32)t_cp[1] << 16) \
@@ -117,17 +158,17 @@ struct dns_header {
| ((u32)t_cp[3]) \
; \
(cp) += 4; \
}
} while (0)
#define PUTSHORT(s, cp) { \
#define PUTSHORT(s, cp) do { \
u16 t_s = (u16)(s); \
unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += 2; \
}
} while(0)
#define PUTLONG(l, cp) { \
#define PUTLONG(l, cp) do { \
u32 t_l = (u32)(l); \
unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_l >> 24; \
@@ -135,10 +176,18 @@ struct dns_header {
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += 4; \
}
} while (0)
#define CHECK_LEN(header, pp, plen, len) \
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
#define ADD_RDLEN(header, pp, plen, len) \
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
/* Escape character in our presentation format for names.
Cannot be '.' or /000 and must be !isprint().
Note that escaped chars are stored as
<NAME_ESCAPE> <orig-char+1>
to ensure that the escaped form of /000 doesn't include /000
*/
#define NAME_ESCAPE 1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

778
src/domain-match.c Normal file
View File

@@ -0,0 +1,778 @@
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
static int order(char *qdomain, size_t qlen, struct server *serv);
static int order_qsort(const void *a, const void *b);
static int order_servers(struct server *s, struct server *s2);
/* If the server is USE_RESOLV or LITERAL_ADDRESS, it lives on the local_domains chain. */
#define SERV_IS_LOCAL (SERV_USE_RESOLV | SERV_LITERAL_ADDRESS)
void build_server_array(void)
{
struct server *serv;
int count = 0;
for (serv = daemon->servers; serv; serv = serv->next)
#ifdef HAVE_LOOP
if (!(serv->flags & SERV_LOOP))
#endif
{
count++;
if (serv->flags & SERV_WILDCARD)
daemon->server_has_wildcard = 1;
}
for (serv = daemon->local_domains; serv; serv = serv->next)
{
count++;
if (serv->flags & SERV_WILDCARD)
daemon->server_has_wildcard = 1;
}
daemon->serverarraysz = count;
if (count > daemon->serverarrayhwm)
{
struct server **new;
count += 10; /* A few extra without re-allocating. */
if ((new = whine_malloc(count * sizeof(struct server *))))
{
if (daemon->serverarray)
free(daemon->serverarray);
daemon->serverarray = new;
daemon->serverarrayhwm = count;
}
}
count = 0;
for (serv = daemon->servers; serv; serv = serv->next)
#ifdef HAVE_LOOP
if (!(serv->flags & SERV_LOOP))
#endif
{
daemon->serverarray[count] = serv;
serv->serial = count;
serv->last_server = -1;
count++;
}
for (serv = daemon->local_domains; serv; serv = serv->next, count++)
daemon->serverarray[count] = serv;
qsort(daemon->serverarray, daemon->serverarraysz, sizeof(struct server *), order_qsort);
/* servers need the location in the array to find all the whole
set of equivalent servers from a pointer to a single one. */
for (count = 0; count < daemon->serverarraysz; count++)
if (!(daemon->serverarray[count]->flags & SERV_IS_LOCAL))
daemon->serverarray[count]->arrayposn = count;
}
/* we're looking for the server whose domain is the longest exact match
to the RH end of qdomain, or a local address if the flags match.
Add '.' to the LHS of the query string so
server=/.example.com/ works.
A flag of F_SERVER returns an upstream server only.
A flag of F_DNSSECOK disables NODOTS servers from consideration.
A flag of F_DS returns parent domain server.
A flag of F_DOMAINSRV returns a domain-specific server only.
A flag of F_CONFIG returns anything that generates a local
reply of IPv4 or IPV6.
return 0 if nothing found, 1 otherwise.
*/
int lookup_domain(char *domain, int flags, int *lowout, int *highout)
{
int rc, crop_query, nodots;
ssize_t qlen;
int try, high, low = 0;
int nlow = 0, nhigh = 0;
char *cp, *qdomain;
/* may be no configured servers. */
if (daemon->serverarraysz == 0)
return 0;
/* DS records should come from the parent domain. */
if (flags & F_DS)
{
if ((cp = strchr(domain, '.')))
domain = cp+1;
else
domain = "";
}
qdomain = domain;
/* find query length and presence of '.' */
for (cp = qdomain, nodots = 1, qlen = 0; *cp; qlen++, cp++)
if (*cp == '.')
nodots = 0;
/* Handle empty name, and searches for DNSSEC queries without
diverting to NODOTS servers. */
if (qlen == 0 || flags & F_DNSSECOK)
nodots = 0;
/* Search shorter and shorter RHS substrings for a match */
while (qlen >= 0)
{
/* Note that when we chop off a label, all the possible matches
MUST be at a larger index than the nearest failing match with one more
character, since the array is sorted longest to smallest. Hence
we don't reset low to zero here, we can go further below and crop the
search string to the size of the largest remaining server
when this match fails. */
high = daemon->serverarraysz;
crop_query = 1;
/* binary search */
while (1)
{
try = (low + high)/2;
if ((rc = order(qdomain, qlen, daemon->serverarray[try])) == 0)
break;
if (rc < 0)
{
if (high == try)
{
/* qdomain is longer or same length as longest domain, and try == 0
crop the query to the longest domain. */
crop_query = qlen - daemon->serverarray[try]->domain_len;
break;
}
high = try;
}
else
{
if (low == try)
{
/* try now points to the last domain that sorts before the query, so
we know that a substring of the query shorter than it is required to match, so
find the largest domain that's shorter than try. Note that just going to
try+1 is not optimal, consider searching bbb in (aaa,ccc,bb). try will point
to aaa, since ccc sorts after bbb, but the first domain that has a chance to
match is bb. So find the length of the first domain later than try which is
is shorter than it.
There's a nasty edge case when qdomain sorts before _any_ of the
server domains, where try _doesn't point_ to the last domain that sorts
before the query, since no such domain exists. In that case, the loop
exits via the rc < 0 && high == try path above and this code is
not executed. */
ssize_t len, old = daemon->serverarray[try]->domain_len;
while (++try != daemon->serverarraysz)
{
if (old != (len = daemon->serverarray[try]->domain_len))
{
crop_query = qlen - len;
break;
}
}
break;
}
low = try;
}
};
if (rc == 0)
{
int found = 1;
if (daemon->server_has_wildcard)
{
/* if we have example.com and *example.com we need to check against *example.com,
but the binary search may have found either. Use the fact that example.com is sorted before *example.com
We favour example.com in the case that both match (ie www.example.com) */
while (try != 0 && order(qdomain, qlen, daemon->serverarray[try-1]) == 0)
try--;
if (!(qdomain == domain || *qdomain == 0 || *(qdomain-1) == '.'))
{
while (try < daemon->serverarraysz-1 && order(qdomain, qlen, daemon->serverarray[try+1]) == 0)
try++;
if (!(daemon->serverarray[try]->flags & SERV_WILDCARD))
found = 0;
}
}
if (found && filter_servers(try, flags, &nlow, &nhigh))
/* We have a match, but it may only be (say) an IPv6 address, and
if the query wasn't for an AAAA record, it's no good, and we need
to continue generalising */
{
/* We've matched a setting which says to use servers without a domain.
Continue the search with empty query. We set the F_SERVER flag
so that --address=/#/... doesn't match. */
if (daemon->serverarray[nlow]->flags & SERV_USE_RESOLV)
{
crop_query = qlen;
flags |= F_SERVER;
}
else
break;
}
}
/* crop_query must be at least one always. */
if (crop_query == 0)
crop_query = 1;
/* strip chars off the query based on the largest possible remaining match,
then continue to the start of the next label unless we have a wildcard
domain somewhere, in which case we have to go one at a time. */
qlen -= crop_query;
qdomain += crop_query;
if (!daemon->server_has_wildcard)
while (qlen > 0 && (*(qdomain-1) != '.'))
qlen--, qdomain++;
}
/* domain has no dots, and we have at least one server configured to handle such,
These servers always sort to the very end of the array.
A configured server eg server=/lan/ will take precdence. */
if (nodots &&
(daemon->serverarray[daemon->serverarraysz-1]->flags & SERV_FOR_NODOTS) &&
(nlow == nhigh || daemon->serverarray[nlow]->domain_len == 0))
{
filter_servers(daemon->serverarraysz-1, flags, &nlow, &nhigh);
qlen = 0;
}
if (lowout)
*lowout = nlow;
if (highout)
*highout = nhigh;
/* qlen == -1 when we failed to match even an empty query, if there are no default servers. */
if (nlow == nhigh || qlen == -1)
return 0;
return 1;
}
int server_samegroup(struct server *a, struct server *b)
{
return order_servers(a, b) == 0;
}
int filter_servers(int seed, int flags, int *lowout, int *highout)
{
int nlow = seed, nhigh = seed;
int i;
/* expand nlow and nhigh to cover all the records with the same domain
nlow is the first, nhigh - 1 is the last. nlow=nhigh means no servers,
which can happen below. */
while (nlow > 0 && order_servers(daemon->serverarray[nlow-1], daemon->serverarray[nlow]) == 0)
nlow--;
while (nhigh < daemon->serverarraysz-1 && order_servers(daemon->serverarray[nhigh], daemon->serverarray[nhigh+1]) == 0)
nhigh++;
nhigh++;
#define SERV_LOCAL_ADDRESS (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)
if (flags & F_CONFIG)
{
/* We're just lookin for any matches that return an RR. */
for (i = nlow; i < nhigh; i++)
if (daemon->serverarray[i]->flags & SERV_LOCAL_ADDRESS)
break;
/* failed, return failure. */
if (i == nhigh)
nhigh = nlow;
}
else
{
/* Now the matching server records are all between low and high.
order_qsort() ensures that they are in the order
IPv6 addr, IPv4 addr, return zero for both, no-data return,
"use resolvconf" servers, domain-specific upstream servers.
See which of those match our query in that priority order and narrow (low, high) */
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++);
if (!(flags & F_SERVER) && i != nlow && (flags & F_IPV6))
nhigh = i;
else
{
nlow = i;
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_4ADDR); i++);
if (!(flags & F_SERVER) && i != nlow && (flags & F_IPV4))
nhigh = i;
else
{
nlow = i;
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_ALL_ZEROS); i++);
if (!(flags & F_SERVER) && i != nlow && (flags & (F_IPV4 | F_IPV6)))
nhigh = i;
else
{
nlow = i;
/* now look for a NXDOMAIN answer --local=/domain/ */
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
if (!(flags & (F_DOMAINSRV | F_SERVER)) && i != nlow)
nhigh = i;
else
{
nlow = i;
/* return "use resolv.conf servers" if they exist */
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_USE_RESOLV); i++);
if (i != nlow)
nhigh = i;
else
{
/* If we want a server for a particular domain, and this one isn't, return nothing. */
if (nlow < daemon->serverarraysz && nlow != nhigh && (flags & F_DOMAINSRV) &&
daemon->serverarray[nlow]->domain_len == 0 && !(daemon->serverarray[nlow]->flags & SERV_FOR_NODOTS))
nlow = nhigh;
}
}
}
}
}
}
*lowout = nlow;
*highout = nhigh;
return (nlow != nhigh);
}
int is_local_answer(time_t now, int first, char *name)
{
int flags = 0;
int rc = 0;
if ((flags = daemon->serverarray[first]->flags) & SERV_LITERAL_ADDRESS)
{
if (flags & SERV_4ADDR)
rc = F_IPV4;
else if (flags & SERV_6ADDR)
rc = F_IPV6;
else if (flags & SERV_ALL_ZEROS)
rc = F_IPV4 | F_IPV6;
else
{
/* argument first is the first struct server which matches the query type;
now roll back to the server which is just the same domain, to check if that
provides an answer of a different type. */
for (;first > 0 && order_servers(daemon->serverarray[first-1], daemon->serverarray[first]) == 0; first--);
if ((daemon->serverarray[first]->flags & SERV_LOCAL_ADDRESS) ||
check_for_local_domain(name, now))
rc = F_NOERR;
else
rc = F_NXDOMAIN;
}
}
return rc;
}
size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header *header, char *name, char *limit, int first, int last, int ede)
{
int trunc = 0, anscount = 0;
unsigned char *p;
int start;
union all_addr addr;
setup_reply(header, flags, ede);
gotname &= ~(F_QUERY | F_DS);
if (flags & (F_NXDOMAIN | F_NOERR))
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL, 0);
if (flags & F_RCODE)
{
union all_addr a;
a.log.rcode = RCODE(header);
a.log.ede = ede;
log_query(F_UPSTREAM | F_RCODE, "opcode", &a, NULL, 0);
}
if (!(p = skip_questions(header, size)))
return 0;
if (flags & gotname & F_IPV4)
for (start = first; start != last; start++)
{
struct serv_addr4 *srv = (struct serv_addr4 *)daemon->serverarray[start];
if (srv->flags & SERV_ALL_ZEROS)
memset(&addr, 0, sizeof(addr));
else
addr.addr4 = srv->addr;
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr))
anscount++;
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL, 0);
}
if (flags & gotname & F_IPV6)
for (start = first; start != last; start++)
{
struct serv_addr6 *srv = (struct serv_addr6 *)daemon->serverarray[start];
if (srv->flags & SERV_ALL_ZEROS)
memset(&addr, 0, sizeof(addr));
else
addr.addr6 = srv->addr;
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr))
anscount++;
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL, 0);
}
if (trunc)
{
header->hb3 |= HB3_TC;
if (!(p = skip_questions(header, size)))
return 0; /* bad packet */
anscount = 0;
}
header->ancount = htons(anscount);
return p - (unsigned char *)header;
}
#ifdef HAVE_DNSSEC
int dnssec_server(struct server *server, char *keyname, int is_ds, int *firstp, int *lastp)
{
int first, last, index;
/* Find server to send DNSSEC query to. This will normally be the
same as for the original query, but may be another if
servers for domains are involved. */
if (!lookup_domain(keyname, F_SERVER | F_DNSSECOK | (is_ds ? F_DS : 0), &first, &last))
return -1;
for (index = first; index != last; index++)
if (daemon->serverarray[index] == server)
break;
/* No match to server used for original query.
Use newly looked up set. */
if (index == last)
index = daemon->serverarray[first]->last_server == -1 ?
first : daemon->serverarray[first]->last_server;
if (firstp)
*firstp = first;
if (lastp)
*lastp = last;
return index;
}
#endif
/* order by size, then by dictionary order */
static int order(char *qdomain, size_t qlen, struct server *serv)
{
size_t dlen = 0;
/* servers for dotless names always sort last
searched for name is never dotless. */
if (serv->flags & SERV_FOR_NODOTS)
return -1;
dlen = serv->domain_len;
if (qlen < dlen)
return 1;
if (qlen > dlen)
return -1;
return hostname_order(qdomain, serv->domain);
}
static int order_servers(struct server *s1, struct server *s2)
{
int rc;
/* need full comparison of dotless servers in
order_qsort() and filter_servers() */
if (s1->flags & SERV_FOR_NODOTS)
return (s2->flags & SERV_FOR_NODOTS) ? 0 : 1;
if ((rc = order(s1->domain, s1->domain_len, s2)) != 0)
return rc;
/* For identical domains, sort wildcard ones first */
if (s1->flags & SERV_WILDCARD)
return (s2->flags & SERV_WILDCARD) ? 0 : 1;
return (s2->flags & SERV_WILDCARD) ? -1 : 0;
}
static int order_qsort(const void *a, const void *b)
{
int rc;
struct server *s1 = *((struct server **)a);
struct server *s2 = *((struct server **)b);
rc = order_servers(s1, s2);
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
in a very specific order IPv6 literal, IPv4 literal, all-zero literal,
NXDOMAIN literal. We also include SERV_USE_RESOLV in this, so that
use-standard servers sort before ordinary servers. (SERV_USR_RESOLV set
implies that none of SERV_LITERAL_ADDRESS,SERV_4ADDR,SERV_6ADDR,SERV_ALL_ZEROS
are set) */
if (rc == 0)
rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS | SERV_USE_RESOLV))) -
((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS | SERV_USE_RESOLV)));
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
if (rc == 0)
if (!(s1->flags & SERV_IS_LOCAL) && !(s2->flags & SERV_IS_LOCAL))
rc = s1->serial - s2->serial;
return rc;
}
/* When loading large numbers of server=.... lines during startup,
there's no possibility that there will be server records that can be reused, but
searching a long list for each server added grows as O(n^2) and slows things down.
This flag is set only if is known there may be free server records that can be reused.
There's a call to mark_servers(0) in read_opts() to reset the flag before
main config read. */
static int maybe_free_servers = 0;
/* Must be called before add_update_server() to set daemon->servers_tail */
void mark_servers(int flag)
{
struct server *serv, *next, **up;
maybe_free_servers = !!flag;
daemon->servers_tail = NULL;
/* mark everything with argument flag */
for (serv = daemon->servers; serv; serv = serv->next)
{
if (serv->flags & flag)
serv->flags |= SERV_MARK;
else
serv->flags &= ~SERV_MARK;
daemon->servers_tail = serv;
}
/* --address etc is different: since they are expected to be
1) numerous and 2) not reloaded often. We just delete
and recreate. */
if (flag)
for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = next)
{
next = serv->next;
if (serv->flags & flag)
{
*up = next;
free(serv->domain);
free(serv);
}
else
up = &serv->next;
}
}
void cleanup_servers(void)
{
struct server *serv, *tmp, **up;
/* unlink and free anything still marked. */
for (serv = daemon->servers, up = &daemon->servers, daemon->servers_tail = NULL; serv; serv = tmp)
{
tmp = serv->next;
if (serv->flags & SERV_MARK)
{
server_gone(serv);
*up = serv->next;
free(serv->domain);
free(serv);
}
else
{
up = &serv->next;
daemon->servers_tail = serv;
}
}
}
int add_update_server(int flags,
union mysockaddr *addr,
union mysockaddr *source_addr,
const char *interface,
const char *domain,
union all_addr *local_addr)
{
struct server *serv = NULL;
char *alloc_domain;
if (!domain)
domain = "";
/* .domain == domain, for historical reasons. */
if (*domain == '.')
while (*domain == '.') domain++;
else if (*domain == '*')
{
domain++;
if (*domain != 0)
flags |= SERV_WILDCARD;
}
if (*domain == 0)
alloc_domain = whine_malloc(1);
else
alloc_domain = canonicalise((char *)domain, NULL);
if (!alloc_domain)
return 0;
if (flags & SERV_IS_LOCAL)
{
size_t size;
if (flags & SERV_6ADDR)
size = sizeof(struct serv_addr6);
else if (flags & SERV_4ADDR)
size = sizeof(struct serv_addr4);
else
size = sizeof(struct serv_local);
if (!(serv = whine_malloc(size)))
{
free(alloc_domain);
return 0;
}
serv->next = daemon->local_domains;
daemon->local_domains = serv;
if (flags & SERV_4ADDR)
((struct serv_addr4*)serv)->addr = local_addr->addr4;
if (flags & SERV_6ADDR)
((struct serv_addr6*)serv)->addr = local_addr->addr6;
}
else
{
/* Upstream servers. See if there is a suitable candidate, if so unmark
and move to the end of the list, for order. The entry found may already
be at the end. */
struct server **up, *tmp;
serv = NULL;
if (maybe_free_servers)
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
{
tmp = serv->next;
if ((serv->flags & SERV_MARK) &&
hostname_isequal(alloc_domain, serv->domain))
{
/* Need to move down? */
if (serv->next)
{
*up = serv->next;
daemon->servers_tail->next = serv;
daemon->servers_tail = serv;
serv->next = NULL;
}
break;
}
else
up = &serv->next;
}
if (serv)
{
free(alloc_domain);
alloc_domain = serv->domain;
}
else
{
if (!(serv = whine_malloc(sizeof(struct server))))
{
free(alloc_domain);
return 0;
}
memset(serv, 0, sizeof(struct server));
/* Add to the end of the chain, for order */
if (daemon->servers_tail)
daemon->servers_tail->next = serv;
else
daemon->servers = serv;
daemon->servers_tail = serv;
}
#ifdef HAVE_LOOP
serv->uid = rand32();
#endif
if (interface)
safe_strncpy(serv->interface, interface, sizeof(serv->interface));
if (addr)
serv->addr = *addr;
if (source_addr)
serv->source_addr = *source_addr;
serv->tcpfd = -1;
}
serv->flags = flags;
serv->domain = alloc_domain;
serv->domain_len = strlen(alloc_domain);
return 1;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,22 +18,17 @@
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
#ifdef HAVE_IPV6
static int match_domain(struct in_addr addr, struct cond_domain *c);
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
#endif
static int match_domain6(struct in6_addr *addr, struct cond_domain *c);
int is_name_synthetic(int flags, char *name, struct all_addr *addr)
int is_name_synthetic(int flags, char *name, union all_addr *addrp)
{
char *p;
struct cond_domain *c = NULL;
int prot = AF_INET;
#ifdef HAVE_IPV6
if (flags & F_IPV6)
prot = AF_INET6;
#endif
int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET;
union all_addr addr;
for (c = daemon->synth_domains; c; c = c->next)
{
int found = 0;
@@ -55,61 +50,83 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
if (pref && *pref != 0)
continue; /* prefix match fail */
/* NB, must not alter name if we return zero */
for (p = tail; *p; p++)
if (c->indexed)
{
char c = *p;
if ((c >='0' && c <= '9') || c == '-')
continue;
#ifdef HAVE_IPV6
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
continue;
#endif
break;
}
if (*p != '.')
continue;
*p = 0;
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
#ifdef HAVE_IPV6
else
*p = ':';
#endif
}
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
{
if (prot == AF_INET)
for (p = tail; *p; p++)
{
if (!c->is6 &&
ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
found = 1;
}
#ifdef HAVE_IPV6
else
{
u64 addrpart = addr6part(&addr->addr.addr6);
char c = *p;
if (c->is6 &&
is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
found = 1;
if (c < '0' || c > '9')
break;
}
#endif
if (*p != '.')
continue;
*p = 0;
if (hostname_isequal(c->domain, p+1))
{
if (prot == AF_INET)
{
unsigned int index = atoi(tail);
if (!c->is6 &&
index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
{
addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
found = 1;
}
}
else
{
u64 index = atoll(tail);
if (c->is6 &&
index <= addr6part(&c->end6) - addr6part(&c->start6))
{
u64 start = addr6part(&c->start6);
addr.addr6 = c->start6;
setaddr6part(&addr.addr6, start + index);
found = 1;
}
}
}
}
else
{
/* NB, must not alter name if we return zero */
for (p = tail; *p; p++)
{
char c = *p;
if ((c >='0' && c <= '9') || c == '-')
continue;
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
continue;
break;
}
if (*p != '.')
continue;
*p = 0;
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
else
*p = ':';
}
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, &addr))
found = (prot == AF_INET) ? match_domain(addr.addr4, c) : match_domain6(&addr.addr6, c);
}
/* restore name */
@@ -118,80 +135,110 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
*p = '-';
*p = '.';
if (found)
return 1;
{
if (addrp)
*addrp = addr;
return 1;
}
}
return 0;
}
int is_rev_synth(int flag, struct all_addr *addr, char *name)
int is_rev_synth(int flag, union all_addr *addr, char *name)
{
struct cond_domain *c;
if (flag & F_IPV4 && (c = search_domain(addr->addr.addr4, daemon->synth_domains)))
if (flag & F_IPV4 && (c = search_domain(addr->addr4, daemon->synth_domains)))
{
char *p;
*name = 0;
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
if (c->indexed)
{
unsigned int index = ntohl(addr->addr4.s_addr) - ntohl(c->start.s_addr);
snprintf(name, MAXDNAME, "%s%u", c->prefix ? c->prefix : "", index);
}
else
{
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
inet_ntop(AF_INET, &addr->addr4, name + strlen(name), ADDRSTRLEN);
for (p = name; *p; p++)
if (*p == '.')
*p = '-';
}
inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
for (p = name; *p; p++)
if (*p == '.')
*p = '-';
strncat(name, ".", MAXDNAME);
strncat(name, c->domain, MAXDNAME);
return 1;
}
#ifdef HAVE_IPV6
if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains)))
if ((flag & F_IPV6) && (c = search_domain6(&addr->addr6, daemon->synth_domains)))
{
char *p;
*name = 0;
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
/* IPv6 presentation address can start with ":", but valid domain names
cannot start with "-" so prepend a zero in that case. */
if (!c->prefix && *name == ':')
if (c->indexed)
{
*name = '0';
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
u64 index = addr6part(&addr->addr6) - addr6part(&c->start6);
snprintf(name, MAXDNAME, "%s%llu", c->prefix ? c->prefix : "", index);
}
else
{
int i;
char frag[6];
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME);
for (i = 0; i < 16; i += 2)
{
sprintf(frag, "%s%02x%02x", i == 0 ? "" : "-", addr->addr6.s6_addr[i], addr->addr6.s6_addr[i+1]);
strncat(name, frag, MAXDNAME);
}
}
for (p = name; *p; p++)
if (*p == ':')
*p = '-';
strncat(name, ".", MAXDNAME);
strncat(name, c->domain, MAXDNAME);
return 1;
}
#endif
return 0;
}
static int match_domain(struct in_addr addr, struct cond_domain *c)
{
if (c->interface)
{
struct addrlist *al;
for (al = c->al; al; al = al->next)
if (!(al->flags & ADDRLIST_IPV6) &&
is_same_net_prefix(addr, al->addr.addr4, al->prefixlen))
return 1;
}
else if (!c->is6 &&
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return 1;
return 0;
}
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
{
for (; c; c = c->next)
if (!c->is6 &&
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
if (match_domain(addr, c))
return c;
return NULL;
}
@@ -205,16 +252,39 @@ char *get_domain(struct in_addr addr)
return daemon->domain_suffix;
}
#ifdef HAVE_IPV6
static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
{
/* subnet from interface address. */
if (c->interface)
{
struct addrlist *al;
for (al = c->al; al; al = al->next)
if (al->flags & ADDRLIST_IPV6 &&
is_same_net6(addr, &al->addr.addr6, al->prefixlen))
return 1;
}
else if (c->is6)
{
if (c->prefixlen >= 64)
{
u64 addrpart = addr6part(addr);
if (is_same_net6(addr, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
return 1;
}
else if (is_same_net6(addr, &c->start6, c->prefixlen))
return 1;
}
return 0;
}
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
{
u64 addrpart = addr6part(addr);
for (; c; c = c->next)
if (c->is6 &&
is_same_net6(addr, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
if (match_domain6(addr, c))
return c;
return NULL;
@@ -229,4 +299,3 @@ char *get_domain6(struct in6_addr *addr)
return daemon->domain_suffix;
}
#endif

Some files were not shown because too many files have changed in this diff Show More